Compare commits
966 Commits
practical-
...
multi-tena
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c315a1548 | ||
|
|
4dfe872c27 | ||
|
|
d2e6e52fd0 | ||
|
|
df7dacdc39 | ||
|
|
0b54c730d7 | ||
|
|
70ddcb56ba | ||
|
|
719a08d993 | ||
|
|
81f287e9ff | ||
|
|
cf724e8693 | ||
|
|
869e2b23fb | ||
|
|
5d33611ef1 | ||
|
|
95c3001f35 | ||
|
|
6597b20ff9 | ||
|
|
25538b2cc4 | ||
|
|
14590545f5 | ||
|
|
f7a9258473 | ||
|
|
49b78d9933 | ||
|
|
b7fa412733 | ||
|
|
14864cbf9b | ||
|
|
c40942694e | ||
|
|
c1df7e2700 | ||
|
|
f6c3d730af | ||
|
|
22cab89749 | ||
|
|
c85b588719 | ||
|
|
2ac730dfe2 | ||
|
|
669bdf5b7d | ||
|
|
744867243f | ||
|
|
79830b752a | ||
|
|
4bb5a99b37 | ||
|
|
dfa8539b9b | ||
|
|
226a104417 | ||
|
|
539ecbc039 | ||
|
|
61adb5c8ae | ||
|
|
be2595f49d | ||
|
|
63d02ab19d | ||
|
|
12d2c50248 | ||
|
|
2bdad2db47 | ||
|
|
33055d74ba | ||
|
|
702eeb9caa | ||
|
|
8d01eb48e6 | ||
|
|
b98f2394b8 | ||
|
|
80f72549a2 | ||
|
|
bd729b7437 | ||
|
|
3aaa90746b | ||
|
|
b55b4ad49d | ||
|
|
ae171a2a82 | ||
|
|
2828deaece | ||
|
|
f8376c803f | ||
|
|
fe13f56aa1 | ||
|
|
1e27a414db | ||
|
|
6edd445e3d | ||
|
|
4a5008f1b5 | ||
|
|
749e880aa7 | ||
|
|
f0789acf42 | ||
|
|
5acbec4c45 | ||
|
|
4f6ad8edc4 | ||
|
|
4048d2b736 | ||
|
|
f919d31232 | ||
|
|
5e2184945c | ||
|
|
c3e046d9d9 | ||
|
|
33dc7cb7dc | ||
|
|
5cbe885d7e | ||
|
|
6b45194c65 | ||
|
|
1d3ab0f6af | ||
|
|
2d29bd4226 | ||
|
|
6bbd5d723e | ||
|
|
2a45acad33 | ||
|
|
c7dd92d3b3 | ||
|
|
905d8c3bb2 | ||
|
|
bb6cae1433 | ||
|
|
d85889b376 | ||
|
|
d1a20296d9 | ||
|
|
2f8c80572b | ||
|
|
7ef9d23e94 | ||
|
|
0a130781d1 | ||
|
|
6ce5a24614 | ||
|
|
627f847d5e | ||
|
|
89c2a61737 | ||
|
|
4403b06416 | ||
|
|
55f3e1c673 | ||
|
|
007b640209 | ||
|
|
59af80fe7f | ||
|
|
ed3b5bb5e8 | ||
|
|
58f78432f0 | ||
|
|
a2a5e52576 | ||
|
|
b50c962201 | ||
|
|
2209a7206f | ||
|
|
828c640307 | ||
|
|
4293c611be | ||
|
|
f155a0dc8e | ||
|
|
dbf6dfbe26 | ||
|
|
826e63a861 | ||
|
|
357292d445 | ||
|
|
87e5261942 | ||
|
|
5d60156456 | ||
|
|
ccd5edb76f | ||
|
|
99f7ddb760 | ||
|
|
40137f182c | ||
|
|
4666a0e9b3 | ||
|
|
17650d134a | ||
|
|
f40107a50f | ||
|
|
656dad2f3e | ||
|
|
c2dac86db0 | ||
|
|
858e3e6559 | ||
|
|
86cb6e0ffe | ||
|
|
3c485dea48 | ||
|
|
9b79fe8271 | ||
|
|
4f854f77b7 | ||
|
|
2191db06d4 | ||
|
|
274353d016 | ||
|
|
f0e63da1a2 | ||
|
|
4b34db817e | ||
|
|
a4aeb06d13 | ||
|
|
3389fbad53 | ||
|
|
3aa6822a72 | ||
|
|
bdfad20dd5 | ||
|
|
d8c9bbc775 | ||
|
|
5e014309cc | ||
|
|
390b9cf73e | ||
|
|
760beb0087 | ||
|
|
5b2f883934 | ||
|
|
98521a3a89 | ||
|
|
51c9f7fca3 | ||
|
|
d593abf718 | ||
|
|
fdd390c389 | ||
|
|
cfba4ecdb2 | ||
|
|
e45c17c4c5 | ||
|
|
f58a0151fe | ||
|
|
ff9aca14b8 | ||
|
|
de74af4fec | ||
|
|
393a90a0d0 | ||
|
|
3f06ab62b1 | ||
|
|
a148dc82a9 | ||
|
|
a039fd7a3a | ||
|
|
00485a5c7f | ||
|
|
50cf5e70fb | ||
|
|
7e5864b97b | ||
|
|
194ad023bd | ||
|
|
f16b07a2d6 | ||
|
|
7bf8bad9e4 | ||
|
|
ab1725e673 | ||
|
|
77631de0ff | ||
|
|
f6bdecd877 | ||
|
|
e05084afdc | ||
|
|
4c49640763 | ||
|
|
4433990878 | ||
|
|
6d092cb3e7 | ||
|
|
66957520f7 | ||
|
|
3596d7815b | ||
|
|
b72724649e | ||
|
|
aed81672a2 | ||
|
|
a1c530640c | ||
|
|
bcd7599676 | ||
|
|
5edb5932b5 | ||
|
|
7bd524976a | ||
|
|
7b7907616f | ||
|
|
e763418e38 | ||
|
|
36e4f2d5f1 | ||
|
|
38f0b9b560 | ||
|
|
246bb9a7e0 | ||
|
|
678bfce993 | ||
|
|
f8bc9fc622 | ||
|
|
d37fd4deae | ||
|
|
394cef66c2 | ||
|
|
7432f1e237 | ||
|
|
8eea52c4e5 | ||
|
|
4c777245fc | ||
|
|
42464bc5bd | ||
|
|
a436efab67 | ||
|
|
5ae056cb03 | ||
|
|
e37a7fb42b | ||
|
|
e3306bab3a | ||
|
|
2cdbcd6de8 | ||
|
|
fae66a2b79 | ||
|
|
f45ad79015 | ||
|
|
f9dd0964d2 | ||
|
|
30ca7ae14d | ||
|
|
82cb796a50 | ||
|
|
a98aeda96f | ||
|
|
1a10a5a9d1 | ||
|
|
edd3865094 | ||
|
|
8990fa8dee | ||
|
|
2b624b3c04 | ||
|
|
93b600affb | ||
|
|
bea6f032ac | ||
|
|
20b8531dc8 | ||
|
|
05c1638984 | ||
|
|
218dfef16b | ||
|
|
bcdb64777a | ||
|
|
dd9df3a08c | ||
|
|
fa12a5d3a8 | ||
|
|
0196b322f0 | ||
|
|
87cfc2ed79 | ||
|
|
b9bcd4c265 | ||
|
|
a54de8a9bb | ||
|
|
c5d7026fc5 | ||
|
|
93841a02ea | ||
|
|
42bd112649 | ||
|
|
d0add206ba | ||
|
|
b9659837c2 | ||
|
|
04f81af6c3 | ||
|
|
8bd1ea4faa | ||
|
|
fa00b6bfa8 | ||
|
|
6a8e08a81a | ||
|
|
25a33678f2 | ||
|
|
1e8081e83e | ||
|
|
88aea40885 | ||
|
|
a341800efc | ||
|
|
d75a2a1651 | ||
|
|
38c0e3d08d | ||
|
|
951d48f470 | ||
|
|
5f81d73c95 | ||
|
|
9ee5fef458 | ||
|
|
1723d314c5 | ||
|
|
f14316256c | ||
|
|
a945e4dc5f | ||
|
|
8575d5d711 | ||
|
|
a9cb35ba4f | ||
|
|
7e21e25cf3 | ||
|
|
ce9b8815df | ||
|
|
f2018eca30 | ||
|
|
af513ba157 | ||
|
|
1aa1b471a5 | ||
|
|
f42b921a50 | ||
|
|
db26e9a054 | ||
|
|
1dd2ae6a4c | ||
|
|
2d672250fd | ||
|
|
59f959fcc2 | ||
|
|
d35179c8ae | ||
|
|
9e0f6d3946 | ||
|
|
b627b6aa83 | ||
|
|
e98c6cda51 | ||
|
|
481b099655 | ||
|
|
d9534b635e | ||
|
|
d7173ff737 | ||
|
|
571bc840ad | ||
|
|
8664e72189 | ||
|
|
f1aec581c7 | ||
|
|
2492c7562a | ||
|
|
83690f95d7 | ||
|
|
02b071f4a0 | ||
|
|
beca94906c | ||
|
|
d6c10050b4 | ||
|
|
5fc9aa7c2f | ||
|
|
9214474325 | ||
|
|
55008a112c | ||
|
|
600ee94ed9 | ||
|
|
55f5734d7b | ||
|
|
a4fa53556b | ||
|
|
ca8f16fb0c | ||
|
|
6d7cde6058 | ||
|
|
2b8e222f23 | ||
|
|
00e97feac7 | ||
|
|
10dd1270fc | ||
|
|
94181fa0da | ||
|
|
9203113c09 | ||
|
|
e326bd1ef8 | ||
|
|
69bae32c80 | ||
|
|
00c20df133 | ||
|
|
bcb94ae9e7 | ||
|
|
64072af7ad | ||
|
|
b9f540f1ee | ||
|
|
cb7e3038fa | ||
|
|
460a4e1b3b | ||
|
|
14495fce2b | ||
|
|
e06b7d4fd3 | ||
|
|
72bd9004cc | ||
|
|
84b0ab50f4 | ||
|
|
aaaf5679ae | ||
|
|
b1bfb7a915 | ||
|
|
58919ad4d4 | ||
|
|
49f0037145 | ||
|
|
d0b5ee7e75 | ||
|
|
c37552661c | ||
|
|
d6a7d8348e | ||
|
|
586003c9b9 | ||
|
|
163ce9b64c | ||
|
|
1d5268d348 | ||
|
|
ef098b5d02 | ||
|
|
1eabb4445e | ||
|
|
b10aed3d14 | ||
|
|
6590a0c811 | ||
|
|
8eed156143 | ||
|
|
0ab9a98ba9 | ||
|
|
72dadaf3f2 | ||
|
|
f0079d67fd | ||
|
|
bc4560b8d9 | ||
|
|
466e56b90f | ||
|
|
aa0397ad1a | ||
|
|
c91f3e7927 | ||
|
|
69cf72af22 | ||
|
|
f3491a1a31 | ||
|
|
71ef748af8 | ||
|
|
5caa285ede | ||
|
|
e14c1ce771 | ||
|
|
8d22ab850a | ||
|
|
82af22b997 | ||
|
|
37a1f748e7 | ||
|
|
a24122ecd7 | ||
|
|
ccbea1fc51 | ||
|
|
ac7079b91a | ||
|
|
91c9829d77 | ||
|
|
5304b298f6 | ||
|
|
e09369aa5a | ||
|
|
3363e36669 | ||
|
|
ea2ce56e52 | ||
|
|
dee60e0699 | ||
|
|
8af7031c92 | ||
|
|
e62fc0c039 | ||
|
|
ad31a52663 | ||
|
|
de16b96971 | ||
|
|
ed9bff5d61 | ||
|
|
f0e34726ec | ||
|
|
3ca8154279 | ||
|
|
2cbd2e0aa7 | ||
|
|
73d7d64225 | ||
|
|
16913aa721 | ||
|
|
ba426d7737 | ||
|
|
3d4d785f33 | ||
|
|
8df5e278c8 | ||
|
|
ea8fb7cad2 | ||
|
|
b7b8b11860 | ||
|
|
1d02b17c20 | ||
|
|
bae61108be | ||
|
|
f60e530636 | ||
|
|
b3e9761305 | ||
|
|
5f75197a42 | ||
|
|
fbd2867ad2 | ||
|
|
2ca23ad99a | ||
|
|
4b032d74be | ||
|
|
8bfa73a67a | ||
|
|
f188e193f3 | ||
|
|
b362855a60 | ||
|
|
4c28d6b98c | ||
|
|
2276f2281a | ||
|
|
7ccb580e91 | ||
|
|
0346dfd584 | ||
|
|
5a64afe209 | ||
|
|
fd82d710b6 | ||
|
|
2056d7c51b | ||
|
|
91866293bc | ||
|
|
2714537140 | ||
|
|
fbc1535015 | ||
|
|
36de89570f | ||
|
|
22e595131c | ||
|
|
c037660b01 | ||
|
|
208d14d65a | ||
|
|
80b9cd83fb | ||
|
|
721ec4a5da | ||
|
|
fb9db32da7 | ||
|
|
874720b68d | ||
|
|
34f558199a | ||
|
|
597883fa08 | ||
|
|
07eab9378a | ||
|
|
806cbbd9ed | ||
|
|
8adf2a3dd0 | ||
|
|
2164ffc9b2 | ||
|
|
73a1a4c51b | ||
|
|
7091f1ffa6 | ||
|
|
fa44f6abe0 | ||
|
|
8586d7f1ce | ||
|
|
b2d818fc30 | ||
|
|
a20d5ee99f | ||
|
|
74b55423d5 | ||
|
|
7962c7e7a8 | ||
|
|
96acbc0919 | ||
|
|
6f5759b5ba | ||
|
|
322b5f18ed | ||
|
|
a7df09d56f | ||
|
|
e36dac9b81 | ||
|
|
8214175890 | ||
|
|
bc8207d29d | ||
|
|
9e55768312 | ||
|
|
6bfd0f4792 | ||
|
|
98ed8adfe3 | ||
|
|
f5938110f4 | ||
|
|
93e00ed436 | ||
|
|
acd8a33b4a | ||
|
|
33bdbd6d08 | ||
|
|
7ab2b3b546 | ||
|
|
b490e4f5b9 | ||
|
|
fe82336937 | ||
|
|
35a7ed5b35 | ||
|
|
56def56b58 | ||
|
|
6074078f5d | ||
|
|
428adb5186 | ||
|
|
1cbce9ad03 | ||
|
|
2138896d43 | ||
|
|
c40ee9c8cc | ||
|
|
d33183ca5e | ||
|
|
9ff9529402 | ||
|
|
51a8d6d3a0 | ||
|
|
c22663505c | ||
|
|
efa30f4ee3 | ||
|
|
9b589a0e69 | ||
|
|
401a7d65a0 | ||
|
|
91242e74b0 | ||
|
|
b0b9c69ad2 | ||
|
|
f8f2ba1f92 | ||
|
|
e3792eff57 | ||
|
|
5a3fa2a6ba | ||
|
|
081c79b85b | ||
|
|
5c0909e356 | ||
|
|
c1fdb68d96 | ||
|
|
b7da976819 | ||
|
|
41e37766b7 | ||
|
|
44612081bc | ||
|
|
4929ed30bc | ||
|
|
8f1de1c396 | ||
|
|
9b84ff9452 | ||
|
|
e4222e7b03 | ||
|
|
eea4e0069d | ||
|
|
2b69b8d72b | ||
|
|
1f130098ee | ||
|
|
5a4ab62e97 | ||
|
|
c86c498ab9 | ||
|
|
139a14fd3d | ||
|
|
6e7402fd63 | ||
|
|
2e91ab319f | ||
|
|
d537f56b9d | ||
|
|
7c4710e2e7 | ||
|
|
ea368f9162 | ||
|
|
7cab3f6556 | ||
|
|
a53eaaf533 | ||
|
|
302ea84cde | ||
|
|
7d470fd681 | ||
|
|
b64c4c66ab | ||
|
|
15ac549532 | ||
|
|
9bff669769 | ||
|
|
8a53ac8b9f | ||
|
|
d3a18f95db | ||
|
|
11649c3fb1 | ||
|
|
09fd8bc4dc | ||
|
|
5a704146a5 | ||
|
|
e25cd91df1 | ||
|
|
71f2e596fe | ||
|
|
7e60f0dd05 | ||
|
|
a0cc882a4b | ||
|
|
a94f9414a4 | ||
|
|
7f69bc69bc | ||
|
|
4b1058cff3 | ||
|
|
a6bab3fa0b | ||
|
|
d6c0f89de5 | ||
|
|
f3ae3da2a5 | ||
|
|
c44fae8d13 | ||
|
|
bcb214448c | ||
|
|
d5c91e733b | ||
|
|
ea6dfa7558 | ||
|
|
6129002b38 | ||
|
|
65db17a319 | ||
|
|
6969669027 | ||
|
|
38a698f07b | ||
|
|
9f121505d1 | ||
|
|
e11cb11ec9 | ||
|
|
6add41254d | ||
|
|
85bc4aea53 | ||
|
|
a95a96dfc0 | ||
|
|
9167da1bc5 | ||
|
|
5be94b499d | ||
|
|
69dfc2a1f5 | ||
|
|
b1a699252b | ||
|
|
f66454256b | ||
|
|
a0886abd38 | ||
|
|
9383c17484 | ||
|
|
512bd6d8eb | ||
|
|
b8b66fe610 | ||
|
|
154569304c | ||
|
|
cc3432ca06 | ||
|
|
68b9c5fa5e | ||
|
|
6620ac7279 | ||
|
|
a9a094d04a | ||
|
|
5d4a04ecf2 | ||
|
|
1b28260680 | ||
|
|
83cb3f8728 | ||
|
|
7d69d3c21d | ||
|
|
ebde50f58b | ||
|
|
b8924d161f | ||
|
|
ccb52ea94f | ||
|
|
72abbe1c53 | ||
|
|
f318f61b4a | ||
|
|
45d8314e29 | ||
|
|
886a1c8667 | ||
|
|
378729720d | ||
|
|
c2a3d4b8a8 | ||
|
|
8444de8e98 | ||
|
|
874e01996a | ||
|
|
fb855fd74e | ||
|
|
78f963fbea | ||
|
|
cf0116b5c6 | ||
|
|
80b07c462f | ||
|
|
5a8ab1343f | ||
|
|
67349e24d8 | ||
|
|
f59697a2f2 | ||
|
|
8c197bee04 | ||
|
|
f866fbf153 | ||
|
|
d7b4fd3f71 | ||
|
|
1c07167f1a | ||
|
|
d5c42f761e | ||
|
|
29449cc597 | ||
|
|
7615bccf04 | ||
|
|
831e7ee987 | ||
|
|
f5f27d78f1 | ||
|
|
ebc46ff7d4 | ||
|
|
2513baf48e | ||
|
|
ac2483d690 | ||
|
|
a85f87f3fc | ||
|
|
68e002776c | ||
|
|
9322f52c9a | ||
|
|
f15e52573b | ||
|
|
2c9807f9b8 | ||
|
|
fcf32800fe | ||
|
|
f8f4dc0f2e | ||
|
|
49bd59c639 | ||
|
|
a96c587559 | ||
|
|
6bd7a28458 | ||
|
|
053517324d | ||
|
|
256802e698 | ||
|
|
851e8a461e | ||
|
|
d8d49f23c4 | ||
|
|
1511792e3b | ||
|
|
0544495d70 | ||
|
|
045a25f3ae | ||
|
|
b6d1ba6766 | ||
|
|
e8e0e07189 | ||
|
|
1672c6c6ba | ||
|
|
ac251c2c00 | ||
|
|
5d7334a4de | ||
|
|
9b9c0b39fd | ||
|
|
802a91a96d | ||
|
|
31bca2b98f | ||
|
|
bf94591035 | ||
|
|
d523b60311 | ||
|
|
e0990a40df | ||
|
|
20c1c455c4 | ||
|
|
dab76add73 | ||
|
|
101cb70893 | ||
|
|
348b11e201 | ||
|
|
a9fdda3f5e | ||
|
|
89d22e55c7 | ||
|
|
40f2a78717 | ||
|
|
80ee1c05ff | ||
|
|
021f9f28f6 | ||
|
|
d7990a6ee5 | ||
|
|
3561a5dc39 | ||
|
|
247a009eef | ||
|
|
fcd4db8217 | ||
|
|
3e03d47520 | ||
|
|
414afea783 | ||
|
|
df7c455881 | ||
|
|
1644765ce2 | ||
|
|
db16cdb79b | ||
|
|
800547d1ef | ||
|
|
5614be7877 | ||
|
|
0644e49161 | ||
|
|
44cd1d354a | ||
|
|
15b81eef97 | ||
|
|
5ddf83d1fd | ||
|
|
6326f46bf2 | ||
|
|
f75719ca37 | ||
|
|
21cf86baff | ||
|
|
6583bc9972 | ||
|
|
886ea37702 | ||
|
|
23116db988 | ||
|
|
8283523327 | ||
|
|
33159befc3 | ||
|
|
c567b19fb2 | ||
|
|
d8487d7cd7 | ||
|
|
347c9f1d3b | ||
|
|
a731a6408b | ||
|
|
c0ac1f6ed5 | ||
|
|
544c3697bd | ||
|
|
33a8ce97d3 | ||
|
|
6ee9d464fb | ||
|
|
df5072bae7 | ||
|
|
ae94e3bf2a | ||
|
|
2276445ff6 | ||
|
|
e12dce1f0f | ||
|
|
612592ec2a | ||
|
|
d0457fc285 | ||
|
|
e04fd4077e | ||
|
|
63d32f0a39 | ||
|
|
99565dd652 | ||
|
|
2b9fa490d4 | ||
|
|
7e03437ab6 | ||
|
|
5f9d19ac65 | ||
|
|
f23d4117d7 | ||
|
|
e4a56d68e0 | ||
|
|
cf5d08aaab | ||
|
|
7ad566d74f | ||
|
|
c312186d91 | ||
|
|
e3f7b08c69 | ||
|
|
6e3ef7e56a | ||
|
|
0a96fee6c3 | ||
|
|
dc7d24e2bf | ||
|
|
089ae12dd1 | ||
|
|
da0d49d306 | ||
|
|
670225a655 | ||
|
|
fa35bfc340 | ||
|
|
f4a5d28a29 | ||
|
|
c735aeba6d | ||
|
|
3c058ec107 | ||
|
|
327e82e057 | ||
|
|
012fc44f08 | ||
|
|
0ab04ab819 | ||
|
|
580b931610 | ||
|
|
dd7df775e2 | ||
|
|
18c2a2e4dc | ||
|
|
fbdd04b4dd | ||
|
|
72fd372fe0 | ||
|
|
acdadcbb6f | ||
|
|
7a49de71ea | ||
|
|
56e4419e77 | ||
|
|
3abb4dd4bd | ||
|
|
726a284ab5 | ||
|
|
a45243390b | ||
|
|
1faed9bc3d | ||
|
|
9bd700eeb7 | ||
|
|
5cc3b9c8cf | ||
|
|
208895c7d5 | ||
|
|
46578ce97b | ||
|
|
0ff5bd5e20 | ||
|
|
f08e637e69 | ||
|
|
a600e056b8 | ||
|
|
671c80972e | ||
|
|
d07230b582 | ||
|
|
35c24407ac | ||
|
|
cf33756548 | ||
|
|
1ef98298bc | ||
|
|
b1c2a95ec4 | ||
|
|
147b2fad8d | ||
|
|
b629088406 | ||
|
|
b508d4393c | ||
|
|
430a067280 | ||
|
|
8a71e8f773 | ||
|
|
ff556ce1ec | ||
|
|
9ed7aed4b4 | ||
|
|
d257151718 | ||
|
|
9e14297488 | ||
|
|
8e70706ed5 | ||
|
|
3e0529cf87 | ||
|
|
91af2bed92 | ||
|
|
1ecefb91dc | ||
|
|
7b60c30548 | ||
|
|
cf5c8906c3 | ||
|
|
72d9895902 | ||
|
|
249c9a5a6e | ||
|
|
41fa214137 | ||
|
|
1565f25a03 | ||
|
|
c5c2926d99 | ||
|
|
a78b830a05 | ||
|
|
879cf783b6 | ||
|
|
895a55f367 | ||
|
|
536c77ff08 | ||
|
|
55456f9220 | ||
|
|
37e70e7af8 | ||
|
|
cf1686c348 | ||
|
|
f7833bcd9f | ||
|
|
5a621053a4 | ||
|
|
2a6451ef2a | ||
|
|
87e044276c | ||
|
|
f1b440c8dd | ||
|
|
cd3e87c1c9 | ||
|
|
a67e54ca6e | ||
|
|
53d9e63c36 | ||
|
|
009c4cf590 | ||
|
|
3c45427bff | ||
|
|
56cbe9915c | ||
|
|
cf3103db46 | ||
|
|
b4623d19e5 | ||
|
|
700bff6e38 | ||
|
|
d77c4e43d4 | ||
|
|
6e11d2b16a | ||
|
|
405842bc0b | ||
|
|
879499b595 | ||
|
|
bf8d7f2124 | ||
|
|
ba98b37306 | ||
|
|
aa8ed65fd8 | ||
|
|
936a4410b3 | ||
|
|
58ec76f9e5 | ||
|
|
c1a77c8e48 | ||
|
|
477e8e4631 | ||
|
|
4f9d65a3a7 | ||
| e199498a8e | |||
|
|
b1799d8ccb | ||
|
|
86833e7d6b | ||
|
|
59cf57898b | ||
|
|
fb9382e3a0 | ||
|
|
dae4697cd2 | ||
|
|
1b2e892f74 | ||
|
|
c66c640f75 | ||
|
|
30849416b6 | ||
|
|
5edcee8da5 | ||
|
|
311beed2a7 | ||
|
|
eb5fdfb635 | ||
|
|
78bcde9ef2 | ||
|
|
630e2a16ad | ||
|
|
82ecee9941 | ||
|
|
e1fe031f25 | ||
|
|
855ba7dc9e | ||
|
|
3a72e73d5d | ||
|
|
4cb13a1419 | ||
|
|
8dd84a5255 | ||
|
|
c0e62f48b7 | ||
|
|
b992225e28 | ||
|
|
2f04562a34 | ||
| 4ee1d87d04 | |||
|
|
39268e2162 | ||
|
|
d6b755c234 | ||
|
|
a889f97bd6 | ||
|
|
a77b968a17 | ||
|
|
da3d712e97 | ||
|
|
bb662aefe3 | ||
|
|
7bbffccd21 | ||
|
|
d3a452cfd8 | ||
|
|
d81b8cdf38 | ||
|
|
39a417368a | ||
|
|
adfce5d2f7 | ||
|
|
977286d6b3 | ||
|
|
c33000045a | ||
|
|
b995ac378a | ||
|
|
0de115ad9e | ||
|
|
ec67414cb6 | ||
|
|
6bea64f345 | ||
|
|
94886e255e | ||
|
|
45f66afe52 | ||
|
|
b9105c1e77 | ||
|
|
909d306942 | ||
|
|
f7273457e9 | ||
|
|
c30e8b4891 | ||
|
|
2e5ad2f65d | ||
|
|
7d5d82e7fc | ||
|
|
776e9c5837 | ||
|
|
0d4979d3d9 | ||
|
|
686c7dd273 | ||
|
|
d41b308c6d | ||
|
|
84dac247d2 | ||
|
|
f8439bb40a | ||
|
|
d268d920e7 | ||
|
|
f730ef1e3a | ||
|
|
af1ce32063 | ||
|
|
678ff2d09d | ||
|
|
48f674b6ef | ||
|
|
02f0820a69 | ||
|
|
ca8605fd6e | ||
|
|
6d5e96421b | ||
|
|
bcc29007bf | ||
|
|
bdf904078d | ||
|
|
e37cfa5066 | ||
|
|
f1bff23bbc | ||
|
|
53106ddb5c | ||
|
|
3a04882fe5 | ||
|
|
19202a5e81 | ||
|
|
7b311ff673 | ||
|
|
9dba98e0ee | ||
|
|
71338670f0 | ||
|
|
7dcdfabce2 | ||
|
|
ddfe1723c9 | ||
|
|
57b5f76db7 | ||
|
|
9ac3524877 | ||
|
|
ca82a0a74b | ||
|
|
23007c3bf2 | ||
|
|
5d69d7612a | ||
|
|
ddd8930af4 | ||
|
|
757f2ec20a | ||
|
|
30caa79424 | ||
|
|
e3f83a0b98 | ||
|
|
147a3ed77b | ||
|
|
5d35d950b3 | ||
|
|
6874508d3f | ||
|
|
33f468209a | ||
|
|
e8ef2816df | ||
|
|
e38d7bbffa | ||
|
|
2f1265c47a | ||
|
|
66b6b60505 | ||
|
|
249d14320d | ||
|
|
313b90ad31 | ||
|
|
2ebc90e974 | ||
|
|
640257dd55 | ||
|
|
c1a3ce8068 | ||
|
|
0080e9c26e | ||
|
|
2ccafe622d | ||
|
|
d7a515ed9a | ||
| cd82b71b77 | |||
|
|
9d6a7dcd9c | ||
|
|
46c2affcc8 | ||
|
|
3d00a80588 | ||
|
|
a3c1fe154f | ||
|
|
07dce5a27e | ||
| 60083183c5 | |||
|
|
255cf026a6 | ||
|
|
840ea56c42 | ||
|
|
09917cc9c9 | ||
|
|
4c9fe192f2 | ||
|
|
32ec55d44e | ||
|
|
527cf89d1a | ||
|
|
ac7b57c0ae | ||
|
|
8be1a8968e | ||
|
|
999ccf64ad | ||
| 8fbd4f3952 | |||
|
|
03352f3aa8 | ||
|
|
61a58fc661 | ||
|
|
4268fa3198 | ||
|
|
2048b6f2db | ||
|
|
f6b62c6c7e | ||
|
|
b4cbc1c190 | ||
|
|
1871f6f656 | ||
|
|
409f9836a6 | ||
|
|
b3f40ee683 | ||
|
|
aa07b51663 | ||
|
|
19b77ed005 | ||
|
|
ea6fca405b | ||
|
|
06503fd079 | ||
|
|
2321dacd2a | ||
|
|
a8b4e91b95 | ||
|
|
a5075bef43 | ||
|
|
f4ffbc1c86 | ||
|
|
6cafa284c7 | ||
|
|
049c0e7a0f | ||
|
|
377ffc6e10 | ||
|
|
858431e86e | ||
|
|
70fca5ca41 | ||
|
|
e972d14a9a | ||
|
|
9bc5eba0d6 | ||
|
|
b8c56c8868 | ||
| 9785837980 | |||
|
|
977a4e11ee | ||
|
|
21e42709a7 | ||
|
|
f8a43042db | ||
|
|
a9ee7aa925 | ||
|
|
811aedaaf4 | ||
| 172b4a4856 | |||
|
|
447ee401cb | ||
|
|
5f8e9954fe | ||
|
|
f8a234822d | ||
| 09245fdfda | |||
|
|
3dafe8d1f6 | ||
|
|
c7606df740 | ||
|
|
e5c40d11d3 | ||
|
|
c9d8bb87de | ||
|
|
f7c2adf58c | ||
|
|
363288a141 | ||
|
|
b1dbacffcc | ||
|
|
3089f8911e | ||
|
|
83ec17343a | ||
|
|
ef9db9ddf6 | ||
|
|
1e8da20c44 | ||
|
|
d9b2b6b567 | ||
|
|
636c7a5939 | ||
|
|
15f6cf0b4c | ||
|
|
c024c304d5 | ||
|
|
a6e100b5c2 | ||
|
|
48bac47c6b | ||
|
|
24a147afaf | ||
|
|
5b17c9e497 | ||
|
|
79f143c22c | ||
|
|
a8764fe627 | ||
|
|
6a0ed31cdc | ||
|
|
8a2e21a794 | ||
|
|
51226fbfb4 | ||
|
|
af5ac7d29a | ||
|
|
0b98a1f697 | ||
|
|
f66cd875fb | ||
|
|
795a6fabee | ||
|
|
1f7becef0a | ||
|
|
aa4f11bf44 | ||
|
|
0b6a08a977 | ||
|
|
5089e769da | ||
|
|
c36f402528 | ||
|
|
1f6a13951f | ||
| 4b69b44df5 | |||
| 5643c625ef | |||
| 1607c97b82 | |||
| d0ac6d4e2e | |||
| 0ad9d546cd | |||
| f8d54e35c9 | |||
|
|
be2a077bba | ||
|
|
cb5dfebb59 | ||
|
|
71d23cbc32 | ||
|
|
93315776da | ||
|
|
0d5cbe6459 | ||
|
|
9a88364d8b | ||
|
|
c0ec4893c8 | ||
|
|
24cd0ff101 | ||
|
|
7e92659217 | ||
|
|
e8fefab74e | ||
|
|
78c86be8a0 | ||
|
|
8f8c9f8395 | ||
|
|
7d5635560d | ||
|
|
e83bf43bc8 | ||
|
|
f89ba87fef | ||
|
|
ca8a4128fb | ||
|
|
21621c2056 | ||
|
|
22797a8ae8 | ||
|
|
374b6feef3 | ||
|
|
c1902f978a | ||
|
|
b431ae70a5 | ||
|
|
8e57bcfd25 | ||
|
|
9e5a000383 | ||
|
|
f4771892aa | ||
|
|
842f09cc90 | ||
|
|
2cb92eaf69 | ||
|
|
02eb368a45 | ||
|
|
4c7b5c8b55 | ||
|
|
7aebab3734 | ||
|
|
d26fb9af85 | ||
|
|
28213cde43 | ||
|
|
c21af696fe | ||
|
|
ebd8821e64 | ||
|
|
361fdf6959 | ||
|
|
60dc02010d | ||
|
|
7c420c7c95 | ||
| a78e7049cf | |||
|
|
ef3796c34f | ||
|
|
c38855acf8 | ||
|
|
a2672d300f | ||
|
|
bfaf0e6aaf | ||
|
|
7fe0f5d84d | ||
|
|
1eeddb20c5 | ||
|
|
52b61ec34a | ||
|
|
faefef7d2f | ||
|
|
938679cbda | ||
|
|
83aefc5dde | ||
|
|
0157ec50d3 | ||
|
|
2f7c947708 | ||
|
|
4c16c39243 | ||
|
|
693ed533f9 | ||
|
|
584b25d9fc | ||
|
|
1fa59d163e | ||
|
|
c94f9c5943 | ||
|
|
2480ae1c0b | ||
|
|
440dc81182 | ||
|
|
0b64302b54 | ||
|
|
0e4e8e09e6 | ||
|
|
0b05f40e65 | ||
|
|
ff0b3a40cd | ||
|
|
fe541886d5 | ||
|
|
6406ed0e57 | ||
|
|
1aa2f2382a | ||
|
|
197a962c0d | ||
|
|
ac923d5943 | ||
|
|
92fe93b4dc | ||
|
|
a26301af1e | ||
|
|
6aa07dc756 | ||
|
|
f5faa054b3 | ||
|
|
5ada366f17 | ||
|
|
80a41dd559 | ||
|
|
7031d4cdd4 | ||
|
|
f72b79c628 | ||
|
|
490db476dd | ||
|
|
1bae6e55e0 | ||
|
|
d2503348fd | ||
|
|
03710d6811 | ||
|
|
322dccfbc1 | ||
|
|
0d0603058c | ||
|
|
acef786c56 | ||
|
|
4e726913f1 | ||
|
|
f699f6f3ba | ||
|
|
e35356a8c6 | ||
|
|
9152f14430 | ||
|
|
faa3fa546b | ||
|
|
5c31093c28 | ||
|
|
eee652bd1f | ||
|
|
b7b66ad28d | ||
|
|
29e092421c | ||
|
|
0022e259ca | ||
|
|
0a711ee3ce |
@@ -1,5 +1,5 @@
|
||||
# 历史路径-哈希带井号标识
|
||||
VITE_HISTORY_HASH = false
|
||||
VITE_HISTORY_HASH = true
|
||||
|
||||
# 历史路径-前缀URL如:/h5
|
||||
VITE_HISTORY_BASE_URL = "/"
|
||||
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
|
||||
VITE_APP_CODE = "OMC"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.241123-fix"
|
||||
VITE_APP_VERSION = "local-dev"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
|
||||
VITE_APP_CODE = "OMC"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.241123-fix"
|
||||
VITE_APP_VERSION = "local-prod"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
38
CHANGELOG.md
@@ -1,5 +1,43 @@
|
||||
# 版本发布日志
|
||||
|
||||
## 2.2510.4-20251024
|
||||
|
||||
- 修复 AMF配置WhiteList Content导入index0无效问题
|
||||
- 新增 更新背景图片固定BA的
|
||||
- 新增 基站状态补充randId列
|
||||
- 新增 Roaming CDR自定义导出功能
|
||||
- 优化 基站名称和位置信息改为非必填
|
||||
- 修复 网元信息更新响应修复
|
||||
- 新增 UDM鉴权cnFlag添加5G/4G接入选择
|
||||
- 新增 更新getAllNeConfig函数,支持传入neId参数
|
||||
- 修复 更新根网管节点处理逻辑,支持无OMC情况
|
||||
- 优化 移除ID列显示
|
||||
- 优化 操作日志信息json结构格式美化
|
||||
- 优化 备份网元日志文件数据查看
|
||||
- 优化 悬浮标签修改
|
||||
|
||||
## 2.2510.2-20251011
|
||||
|
||||
- 新增 UDM-auth数据导出按钮权限定义
|
||||
- 新增 SMSC-CDR添加结果原因说明
|
||||
- 优化 移除CDR/UE/网元版本/授权列表显示ID列
|
||||
- 修复 MML回车undefined问题,关闭搜索匹配
|
||||
|
||||
## 2.2408.1-20250815
|
||||
|
||||
- 修复 给config.js加随机数避免缓存
|
||||
- 优化 UDM鉴权用户显示创建时间
|
||||
- 修复 系统用户登录主页重复刷新问题
|
||||
- 新增 kpi自定义仪表盘需求更改
|
||||
- 修复 租户主页暗色模式显示不一致
|
||||
- 修复 租户和系统用户的主页显示差异
|
||||
- 修复 图片上传取值fileName失败
|
||||
- 优化 第三方用户不可删除和修改密码
|
||||
- 修复 恢复显示快速PLMN修改窗口
|
||||
- 新增 第三方登录认证功能和管理页
|
||||
- 修复 回退看板,修复切换upf的流量统计显示
|
||||
|
||||
|
||||
## 2.2404.1-20240402
|
||||
|
||||
- 新增 网元安装流程相关页面与操作相关接口联调
|
||||
|
||||
28
README.md
@@ -46,5 +46,31 @@ export NODE_OPTIONS=--max-old-space-size=50000
|
||||
|
||||
```text
|
||||
https://192.168.5.23/
|
||||
admin / admin
|
||||
admin
|
||||
admin
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 多租户涉及页面
|
||||
ems_frontend_vue3\src\views\dashboard\smfCDR\index.vue
|
||||
ems_frontend_vue3\src\views\dashboard\imsCDR\index.vue
|
||||
ems_frontend_vue3\src\views\dashboard\amfUE\index.vue
|
||||
ems_frontend_vue3\src\views\dashboard\mmeUE\index.vue
|
||||
ems_frontend_vue3\src\views\system\user\index.vue
|
||||
ems_frontend_vue3\src\views\system\tenant\index.vue
|
||||
ems_frontend_vue3\src\views\system\log\operate\index.vue
|
||||
ems_frontend_vue3\src\views\neUser\sub\index.vue
|
||||
ems_frontend_vue3\src\views\neUser\ims\index.vue
|
||||
ems_frontend_vue3\src\views\neUser\ue\index.vue
|
||||
ems_frontend_vue3\src\views\neUser\base5G\index.vue
|
||||
|
||||
ems_frontend_vue3\src\views\tenant\amfUE\index.vue
|
||||
ems_frontend_vue3\src\views\tenant\base5G\index.vue
|
||||
ems_frontend_vue3\src\views\tenant\ims\index.vue
|
||||
ems_frontend_vue3\src\views\tenant\imsCDR\index.vue
|
||||
ems_frontend_vue3\src\views\tenant\mmeUE\index.vue
|
||||
ems_frontend_vue3\src\views\tenant\operate\index.vue
|
||||
ems_frontend_vue3\src\views\tenant\smfCDR\index.vue
|
||||
ems_frontend_vue3\src\views\tenant\sub\index.vue
|
||||
ems_frontend_vue3\src\views\tenant\ue\index.vue
|
||||
12
index.html
@@ -2,14 +2,18 @@
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="google" content="notranslate">
|
||||
<meta name="google" content="notranslate" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>loading...</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="preload" href="/loading.js" as="script">
|
||||
<link rel="preload" href="/loading.js" as="script"/>
|
||||
<script async src="/loading.js"></script>
|
||||
<link rel="preload" href="/config.js" as="script">
|
||||
<script async src="/config.js"></script>
|
||||
<script>
|
||||
var script = document.createElement('script');
|
||||
script.src = '/config.js?nocache=' + new Date().getTime();
|
||||
script.async = true;
|
||||
document.head.appendChild(script);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
81
package.json
@@ -8,54 +8,55 @@
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc && vite build",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@antv/g6": "~4.8.24",
|
||||
"@codemirror/lang-javascript": "^6.2.2",
|
||||
"@codemirror/lang-yaml": "^6.1.1",
|
||||
"@codemirror/merge": "^6.7.2",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@tato30/vue-pdf": "^1.11.2",
|
||||
"@vueuse/core": "11.2.0",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"ant-design-vue": "^4.2.5",
|
||||
"antdv-pro-layout": "^4.1.9",
|
||||
"antdv-pro-modal": "^4.0.5",
|
||||
"codemirror": "^6.0.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.11",
|
||||
"echarts": "~5.5.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"grid-layout-plus": "^1.0.5",
|
||||
"intl-tel-input": "^24.6.0",
|
||||
"@ant-design/icons-vue": "7.0.1",
|
||||
"@antv/g6": "4.8.24",
|
||||
"@codemirror/lang-javascript": "6.2.3",
|
||||
"@codemirror/lang-yaml": "6.1.2",
|
||||
"@codemirror/merge": "6.10.0",
|
||||
"@codemirror/theme-one-dark": "6.1.2",
|
||||
"@tato30/vue-pdf": "1.11.3",
|
||||
"@vueuse/core": "13.0.0",
|
||||
"@xterm/addon-fit": "0.10.0",
|
||||
"@xterm/xterm": "5.5.0",
|
||||
"ant-design-vue": "4.2.6",
|
||||
"antdv-pro-layout": "4.2.0",
|
||||
"antdv-pro-modal": "4.0.6",
|
||||
"codemirror": "6.0.1",
|
||||
"crypto-js": "4.2.0",
|
||||
"dayjs": "1.11.13",
|
||||
"echarts": "5.6.0",
|
||||
"echarts-liquidfill": "^3.1.0",
|
||||
"file-saver": "2.0.5",
|
||||
"grid-layout-plus": "1.0.6",
|
||||
"intl-tel-input": "25.2.0",
|
||||
"js-base64": "^3.7.7",
|
||||
"js-cookie": "^3.0.5",
|
||||
"localforage": "^1.10.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"p-queue": "~8.0.1",
|
||||
"pinia": "2.2.6",
|
||||
"vue": "^3.5.12",
|
||||
"vue-i18n": "^10.0.4",
|
||||
"vue-router": "^4.4.5",
|
||||
"vue3-smooth-dnd": "^0.0.6",
|
||||
"xlsx": "~0.18.5"
|
||||
"p-queue": "8.0.1",
|
||||
"pinia": "2.3.0",
|
||||
"vue": "3.5.13",
|
||||
"vue-i18n": "11.1.2",
|
||||
"vue-router": "4.5.0",
|
||||
"vue3-smooth-dnd": "0.0.6",
|
||||
"xlsx": "0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^22.7.7",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@vitejs/plugin-vue": "^5.1.4",
|
||||
"less": "^4.2.0",
|
||||
"typescript": "^5.6.3",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"vite": "5.4.10",
|
||||
"vite-plugin-compression": "~0.5.1",
|
||||
"vue-tsc": "^2.1.8"
|
||||
"@types/crypto-js": "4.2.2",
|
||||
"@types/file-saver": "2.0.7",
|
||||
"@types/js-cookie": "3.0.6",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/nprogress": "0.2.3",
|
||||
"@vitejs/plugin-vue": "5.2.3",
|
||||
"less": "4.2.2",
|
||||
"typescript": "5.8.2",
|
||||
"unplugin-vue-components": "0.28.0",
|
||||
"vite": "6.2.2",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vue-tsc": "2.2.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# 实训教学模块
|
||||
|
||||
网元固定一套,ne_id 默认使用`001`
|
||||
|
||||
## 静态资源
|
||||
|
||||
将目录下文件放置到对应目录 替换约18个文件
|
||||
|
||||
- i18n 对应覆盖 src\i18n
|
||||
- views 对应覆盖 src\views
|
||||
|
||||
|
||||
## 涉及文件
|
||||
|
||||
- src\i18n\locales\en-US.ts
|
||||
- src\i18n\locales\zh-CN.ts
|
||||
- src\views\monitor\topologyArchitecture\index.vue
|
||||
- src\views\configManage\configParamTreeTable
|
||||
- src\views\configManage\configParamApply
|
||||
- src\views\ne\neInfo\index.vue
|
||||
- src\plugins\auth-user.ts
|
||||
- src\views\dashboard\amfUE\index.vue
|
||||
- src\views\dashboard\mmeUE\index.vue
|
||||
- src\views\dashboard\imsCDR\index.vue
|
||||
- src\views\dashboard\smfCDR\index.vue
|
||||
- src\views\dashboard\smscCDR\index.vue
|
||||
- src\store\modules\user.ts
|
||||
@@ -1,120 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 保存为示例配置 (仅管理员操作)
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function ptSaveAsDefault(neType: string, neid: string) {
|
||||
return request({
|
||||
url: `/pt/neConfigData/saveAsDefault`,
|
||||
method: 'post',
|
||||
data: { neType, neid },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置为示例配置 (仅学生/教师操作)
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function ptResetAsDefault(neType: string) {
|
||||
return request({
|
||||
url: `/pt/neConfigData/resetAsDefault`,
|
||||
method: 'post',
|
||||
data: { neType },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据比较示例
|
||||
* @param params 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function ptContrastAsDefault(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData/contrast`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置数据导出Excel
|
||||
* @param student 仅教师 student
|
||||
* @returns object
|
||||
*/
|
||||
export function ptExport(student: string | undefined) {
|
||||
return request({
|
||||
url: `/pt/neConfigData/export`,
|
||||
method: 'get',
|
||||
params: { student },
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置数据导出Excel (仅教师全量)
|
||||
* @returns object
|
||||
*/
|
||||
export function ptExportAll() {
|
||||
return request({
|
||||
url: `/pt/neConfigData/export-all`,
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置信息
|
||||
* @param params 数据 {neType,paramName}
|
||||
* @returns object
|
||||
*/
|
||||
export function getPtNeConfigData(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置数据更新
|
||||
* @param data 数据 {neType,paramName:"参数名",paramData:{参数},loc:"层级index仅array"}
|
||||
* @returns object
|
||||
*/
|
||||
export function editPtNeConfigData(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置新增(array)
|
||||
* @param data 数据 {neType,paramName:"参数名",paramData:{参数},loc:"层级index"}
|
||||
* @returns object
|
||||
*/
|
||||
export function addPtNeConfigData(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置删除(array)
|
||||
* @param params 数据 {neType,paramName:"参数名",loc:"层级index"}
|
||||
* @returns object
|
||||
*/
|
||||
export function delPtNeConfigData(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData`,
|
||||
method: 'delete',
|
||||
params,
|
||||
});
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 班级学生列表 (仅教师操作)
|
||||
* @param params 数据 {userName}
|
||||
* @returns object
|
||||
*/
|
||||
export function getPtClassStudents(params?: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigApply/students`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置应用申请列表
|
||||
* @param params 数据 {neType,paramName}
|
||||
* @returns object
|
||||
*/
|
||||
export function getPtNeConfigApplyList(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigApply/list`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置应用申请提交(仅学生操作)
|
||||
* @param data 数据 { "neType": "MME", "status": "1" }
|
||||
* @returns object
|
||||
*/
|
||||
export function stuPtNeConfigApply(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigApply`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置应用申请状态变更(仅管理员/教师操作)
|
||||
* @param data 数据 { "applyId": "1", "neType": "MME", "status": "3", "backInfo": "sgw参数错误" }
|
||||
* @returns object
|
||||
*/
|
||||
export function updatePtNeConfigApply(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigApply`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 网元参数配置数据变更日志信息
|
||||
* @param params 数据 {neType,paramName}
|
||||
* @returns object
|
||||
*/
|
||||
export function getPtNeConfigDataLogList(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigDataLog`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置数据变更日志还原到数据
|
||||
* @param data 数据 { "id": "1", "value": "old" }
|
||||
* @returns object
|
||||
*/
|
||||
export function restorePtNeConfigDataLog(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigDataLog/restore`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 导入用户模板数据
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importData(data: FormData) {
|
||||
return request({
|
||||
url: '/pt/system/user/importData',
|
||||
method: 'post',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入用户模板下载
|
||||
* @returns bolb
|
||||
*/
|
||||
export function importTemplate() {
|
||||
return request({
|
||||
url: '/pt/system/user/importTemplate',
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户列表导出
|
||||
* @param query 查询参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUser(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/pt/system/user/export',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
import { ADMIN_PERMISSION, ADMIN_ROLE_KEY } from '@/constants/admin-constants';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
/**
|
||||
* 是否系统管理员
|
||||
* @returns true | false
|
||||
*/
|
||||
export function isSystemAdmin(): boolean {
|
||||
const userPermissions = useUserStore().permissions;
|
||||
if (userPermissions.includes(ADMIN_PERMISSION)) return true;
|
||||
const userRoles = useUserStore().roles;
|
||||
if (userRoles.includes(ADMIN_ROLE_KEY)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 只需含有其中权限
|
||||
* @param role 权限字符数组
|
||||
* @returns true | false
|
||||
*/
|
||||
export function hasPermissions(permissions: string[]): boolean {
|
||||
if (!permissions || permissions.length === 0) return false;
|
||||
const userPermissions = useUserStore().permissions;
|
||||
if (!userPermissions || userPermissions.length === 0) return false;
|
||||
if (userPermissions.includes(ADMIN_PERMISSION)) return true;
|
||||
return permissions.some(p => userPermissions.some(up => up === p));
|
||||
}
|
||||
|
||||
/**
|
||||
* 同时匹配其中权限
|
||||
* @param role 权限字符数组
|
||||
* @returns true | false
|
||||
*/
|
||||
export function matchPermissions(permissions: string[]): boolean {
|
||||
if (!permissions || permissions.length === 0) return false;
|
||||
const userPermissions = useUserStore().permissions;
|
||||
if (!userPermissions || userPermissions.length === 0) return false;
|
||||
if (userPermissions.includes(ADMIN_PERMISSION)) return true;
|
||||
return permissions.every(p => userPermissions.some(up => up === p));
|
||||
}
|
||||
|
||||
/**
|
||||
* 只需含有其中角色
|
||||
* @param role 角色字符数组
|
||||
* @returns true | false
|
||||
*/
|
||||
export function hasRoles(roles: string[]): boolean {
|
||||
if (!roles || roles.length === 0) return false;
|
||||
const userRoles = useUserStore().roles;
|
||||
if (!userRoles || userRoles.length === 0) return false;
|
||||
if (userRoles.includes(ADMIN_ROLE_KEY)) return true;
|
||||
return roles.some(r => userRoles.some(ur => ur === r));
|
||||
}
|
||||
|
||||
/**
|
||||
* 同时匹配其中角色
|
||||
* @param role 角色字符数组
|
||||
* @returns true | false
|
||||
*/
|
||||
export function matchRoles(roles: string[]): boolean {
|
||||
if (!roles || roles.length === 0) return false;
|
||||
const userRoles = useUserStore().roles;
|
||||
if (!userRoles || userRoles.length === 0) return false;
|
||||
if (userRoles.includes(ADMIN_ROLE_KEY)) return true;
|
||||
return roles.every(r => userRoles.some(ur => ur === r));
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
import defaultAvatar from '@/assets/images/default_avatar.png';
|
||||
import useLayoutStore from './layout';
|
||||
import { login, logout, getInfo } from '@/api/login';
|
||||
import { setToken, removeToken } from '@/plugins/auth-token';
|
||||
import { defineStore } from 'pinia';
|
||||
import { TOKEN_RESPONSE_FIELD } from '@/constants/token-constants';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
|
||||
/**用户信息类型 */
|
||||
type UserInfo = {
|
||||
/**用户ID */
|
||||
userId: string;
|
||||
/**登录账号 */
|
||||
userName: string;
|
||||
/**用户角色 字符串数组 */
|
||||
roles: string[];
|
||||
/**用户权限 字符串数组 */
|
||||
permissions: string[];
|
||||
/**用户头像 */
|
||||
avatar: string;
|
||||
/**用户昵称 */
|
||||
nickName: string;
|
||||
/**用户手机号 */
|
||||
phonenumber: string;
|
||||
/**用户邮箱 */
|
||||
email: string;
|
||||
/**用户性别 */
|
||||
sex: string | undefined;
|
||||
/**其他信息 */
|
||||
profile: Record<string, any>;
|
||||
};
|
||||
|
||||
const useUserStore = defineStore('user', {
|
||||
state: (): UserInfo => ({
|
||||
userId: '',
|
||||
userName: '',
|
||||
roles: [],
|
||||
permissions: [],
|
||||
avatar: '',
|
||||
nickName: '',
|
||||
phonenumber: '',
|
||||
email: '',
|
||||
sex: undefined,
|
||||
profile: {},
|
||||
}),
|
||||
getters: {
|
||||
/**
|
||||
* 获取正确头像地址
|
||||
* @param state 内部属性不用传入
|
||||
* @returns 头像地址url
|
||||
*/
|
||||
getAvatar(state) {
|
||||
if (!state.avatar) {
|
||||
return defaultAvatar;
|
||||
}
|
||||
return parseUrlPath(state.avatar);
|
||||
},
|
||||
/**
|
||||
* 获取基础信息属性
|
||||
* @param state 内部属性不用传入
|
||||
* @returns 基础信息
|
||||
*/
|
||||
getBaseInfo(state) {
|
||||
return {
|
||||
nickName: state.nickName,
|
||||
phonenumber: state.phonenumber,
|
||||
email: state.email,
|
||||
sex: state.sex,
|
||||
};
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
/**
|
||||
* 更新基础信息属性
|
||||
* @param data 变更信息
|
||||
*/
|
||||
setBaseInfo(data: Record<string, any>) {
|
||||
this.nickName = data.nickName;
|
||||
this.phonenumber = data.phonenumber;
|
||||
this.email = data.email;
|
||||
this.sex = data.sex;
|
||||
},
|
||||
/**
|
||||
* 更新头像
|
||||
* @param avatar 上传后的地址
|
||||
*/
|
||||
setAvatar(avatar: string) {
|
||||
this.avatar = avatar;
|
||||
},
|
||||
/**
|
||||
* 获取正确头像地址
|
||||
* @param avatar
|
||||
*/
|
||||
fnAvatar(avatar: string) {
|
||||
if (!avatar) {
|
||||
return defaultAvatar;
|
||||
}
|
||||
return parseUrlPath(avatar);
|
||||
},
|
||||
// 登录
|
||||
async fnLogin(loginBody: Record<string, string>) {
|
||||
const res = await login(loginBody);
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
const token = res.data[TOKEN_RESPONSE_FIELD];
|
||||
setToken(token);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
// 获取用户信息
|
||||
async fnGetInfo() {
|
||||
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;
|
||||
// 用户头像
|
||||
this.avatar = user.avatar;
|
||||
// 基础信息
|
||||
this.nickName = user.nickName;
|
||||
this.phonenumber = user.phonenumber;
|
||||
this.email = user.email;
|
||||
this.sex = user.sex;
|
||||
|
||||
// 验证返回的roles是否是一个非空数组
|
||||
if (Array.isArray(roles) && roles.length > 0) {
|
||||
this.roles = roles;
|
||||
this.permissions = permissions;
|
||||
} else {
|
||||
this.roles = ['ROLE_DEFAULT'];
|
||||
this.permissions = [];
|
||||
}
|
||||
|
||||
// 水印文字信息=用户昵称 手机号
|
||||
let waterMarkContent = this.userName;
|
||||
if (this.phonenumber) {
|
||||
waterMarkContent = `${this.userName} ${this.phonenumber}`;
|
||||
}
|
||||
// useLayoutStore().changeWaterMark(waterMarkContent);
|
||||
useLayoutStore().changeWaterMark('');
|
||||
// 学生布局用不一样的
|
||||
if (this.roles.includes('student')) {
|
||||
useLayoutStore().changeConf('layout', 'side');
|
||||
useLayoutStore().changeConf('menuTheme', 'dark');
|
||||
useLayoutStore().changeConf('tabRender', false);
|
||||
}
|
||||
}
|
||||
// 网络错误时退出登录状态
|
||||
if (res.code === 0) {
|
||||
removeToken();
|
||||
window.location.reload();
|
||||
}
|
||||
return res;
|
||||
},
|
||||
// 退出系统
|
||||
async fnLogOut() {
|
||||
try {
|
||||
await logout();
|
||||
} catch (error) {
|
||||
throw error;
|
||||
} finally {
|
||||
this.roles = [];
|
||||
this.permissions = [];
|
||||
removeToken();
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default useUserStore;
|
||||
@@ -1,327 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, watch } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import CodemirrorEditeDiff from '@/components/CodemirrorEditeDiff/index.vue';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import {
|
||||
getPtNeConfigDataLogList,
|
||||
restorePtNeConfigDataLog,
|
||||
} from '@/api/pt/neConfigDataLog';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**网元类型 */
|
||||
neType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**参数名 */
|
||||
paramName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**学生用户账号 */
|
||||
student: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const { getDict } = useDictStore();
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
/**业务类型 */
|
||||
sysBusinessType: DictType[];
|
||||
} = reactive({
|
||||
sysBusinessType: [],
|
||||
});
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type StateType = {
|
||||
/**新增框或修改框是否显示 */
|
||||
openByList: boolean;
|
||||
/**差异比较框是否显示 */
|
||||
openByDiff: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**加载状态 */
|
||||
loading: boolean;
|
||||
/**数据 */
|
||||
data: Record<string, any>[];
|
||||
/**差异数据 */
|
||||
dataDiff: Record<string, any>;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let state: StateType = reactive({
|
||||
openByList: false,
|
||||
openByDiff: false,
|
||||
title: '操作参数名称-学生账号',
|
||||
loading: false,
|
||||
data: [],
|
||||
dataDiff: {},
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
function onClose() {
|
||||
state.loading = false;
|
||||
state.openByList = false;
|
||||
state.openByDiff = false;
|
||||
state.data = [];
|
||||
state.dataDiff = {};
|
||||
emit('cancel');
|
||||
emit('update:open', false);
|
||||
queryParams = {
|
||||
neType: '',
|
||||
paramName: '',
|
||||
student: '',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
}
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: '',
|
||||
/**可用属性值 */
|
||||
paramName: '',
|
||||
/**学生账号 */
|
||||
student: '',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (state.loading) return;
|
||||
state.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
if (pageNum === 1) state.data = [];
|
||||
}
|
||||
getPtNeConfigDataLogList(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
// tablePagination.total = res.total;
|
||||
state.data = state.data.concat(res.rows);
|
||||
// 去首个做标题
|
||||
if (queryParams.pageNum === 1 && state.data.length > 0) {
|
||||
const item = state.data[0];
|
||||
state.title = `${item.paramDisplay} - ${item.createBy}`;
|
||||
}
|
||||
if (state.data.length <= res.total && res.rows.length > 0) {
|
||||
queryParams.pageNum++;
|
||||
}
|
||||
}
|
||||
state.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**差异比较框打开 */
|
||||
function fnMergeCellOpen(row: Record<string, any>) {
|
||||
state.dataDiff = row;
|
||||
state.dataDiff.paramJsonOld = JSON.stringify(
|
||||
JSON.parse(state.dataDiff.paramJsonOld),
|
||||
null,
|
||||
2
|
||||
);
|
||||
state.dataDiff.paramJsonNew = JSON.stringify(
|
||||
JSON.parse(state.dataDiff.paramJsonNew),
|
||||
null,
|
||||
2
|
||||
);
|
||||
state.openByDiff = true;
|
||||
}
|
||||
|
||||
/**差异比较框关闭 */
|
||||
function fnMergeCellClose() {
|
||||
state.openByDiff = false;
|
||||
state.dataDiff = {};
|
||||
}
|
||||
|
||||
/**差异比较还原 */
|
||||
function fnMergeCellRestore(value: 'old' | 'new') {
|
||||
if (state.confirmLoading) return;
|
||||
const id = state.dataDiff.id;
|
||||
restorePtNeConfigDataLog({ id, value })
|
||||
.then((res: any) => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
fnMergeCellClose();
|
||||
fnGetList(1);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
state.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
if (val) {
|
||||
if (props.neType && props.paramName) {
|
||||
state.title = '';
|
||||
state.openByList = true;
|
||||
// 根据条件查询数据
|
||||
queryParams.neType = props.neType;
|
||||
queryParams.paramName = props.paramName;
|
||||
if (props.student) {
|
||||
queryParams.student = props.student;
|
||||
}
|
||||
fnGetList();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([getDict('sys_oper_type')]).then(resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
dict.sysBusinessType = resArr[0].value;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<a-drawer
|
||||
:width="500"
|
||||
:title="state.title"
|
||||
placement="right"
|
||||
:open="state.openByList"
|
||||
@close="onClose"
|
||||
>
|
||||
<a-list
|
||||
class="demo-loadmore-list"
|
||||
item-layout="horizontal"
|
||||
:data-source="state.data"
|
||||
>
|
||||
<template #loadMore>
|
||||
<div
|
||||
:style="{
|
||||
textAlign: 'center',
|
||||
marginTop: '12px',
|
||||
height: '32px',
|
||||
lineHeight: '32px',
|
||||
}"
|
||||
>
|
||||
<a-button @click="fnGetList()" :loading="state.loading">
|
||||
{{ t('views.configManage.configParamForm.ptDiffLoad') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>
|
||||
<template #actions>
|
||||
<a-tooltip>
|
||||
<template #title>
|
||||
{{ t('views.configManage.configParamForm.ptDiffMerge') }}
|
||||
</template>
|
||||
<a-button type="primary" @click.prevent="fnMergeCellOpen(item)">
|
||||
<template #icon><MergeCellsOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<DictTag
|
||||
:options="dict.sysBusinessType"
|
||||
:value="item.operaType"
|
||||
/>
|
||||
</template>
|
||||
<template #description>
|
||||
{{ parseDateToStr(item.createTime) }}
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</a-drawer>
|
||||
|
||||
<a-modal
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:mask-closable="false"
|
||||
v-model:open="state.openByDiff"
|
||||
:footer="null"
|
||||
:body-style="{ padding: 0, maxHeight: '650px', 'overflow-y': 'auto' }"
|
||||
@ok="fnMergeCellClose()"
|
||||
@cancel="fnMergeCellClose()"
|
||||
>
|
||||
<template #title>
|
||||
<DictTag
|
||||
:options="dict.sysBusinessType"
|
||||
:value="state.dataDiff.operaType"
|
||||
/>
|
||||
{{ parseDateToStr(state.dataDiff.createTime) }}
|
||||
</template>
|
||||
<div class="diffBack">
|
||||
<div>
|
||||
<a-button
|
||||
type="text"
|
||||
:loading="state.confirmLoading"
|
||||
@click.prevent="fnMergeCellRestore('old')"
|
||||
>
|
||||
<template #icon><MergeCellsOutlined /></template>
|
||||
{{ t('views.configManage.configParamForm.ptDiffRest') }}
|
||||
</a-button>
|
||||
</div>
|
||||
<div>
|
||||
<a-button
|
||||
type="text"
|
||||
:loading="state.confirmLoading"
|
||||
@click.prevent="fnMergeCellRestore('new')"
|
||||
>
|
||||
<template #icon><MergeCellsOutlined /></template>
|
||||
{{ t('views.configManage.configParamForm.ptDiffRest') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<CodemirrorEditeDiff
|
||||
:old-area="state.dataDiff.paramJsonOld"
|
||||
:new-area="state.dataDiff.paramJsonNew"
|
||||
></CodemirrorEditeDiff>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.diffBack {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
& > div:first-child {
|
||||
flex: 1;
|
||||
background: #fa9;
|
||||
}
|
||||
& > div:last-child {
|
||||
flex: 1;
|
||||
background: #8f8;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,407 +0,0 @@
|
||||
import {
|
||||
addPtNeConfigData,
|
||||
delPtNeConfigData,
|
||||
editPtNeConfigData,
|
||||
} from '@/api/pt/neConfig';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { Modal, message } from 'ant-design-vue/es';
|
||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||
import { reactive, watch } from 'vue';
|
||||
|
||||
/**
|
||||
* 参数配置array类型
|
||||
* @param param 父级传入 { t, treeState, fnActiveConfigNode, ruleVerification, modalState, fnModalCancel}
|
||||
* @returns
|
||||
*/
|
||||
export default function useConfigArray({
|
||||
t,
|
||||
treeState,
|
||||
fnActiveConfigNode,
|
||||
ruleVerification,
|
||||
modalState,
|
||||
fnModalCancel,
|
||||
}: any) {
|
||||
/**多列列表状态类型 */
|
||||
type ArrayStateType = {
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**多列嵌套记录字段 */
|
||||
columns: Record<string, any>[];
|
||||
/**表格字段列排序 */
|
||||
columnsDnd: Record<string, any>[];
|
||||
/**多列记录数据 */
|
||||
columnsData: Record<string, any>[];
|
||||
/**多列嵌套展开key */
|
||||
arrayChildExpandKeys: any[];
|
||||
|
||||
/**多列记录数据 */
|
||||
data: Record<string, any>[];
|
||||
/**多列记录规则 */
|
||||
dataRule: Record<string, any>;
|
||||
};
|
||||
|
||||
/**多列列表状态 */
|
||||
let arrayState: ArrayStateType = reactive({
|
||||
size: 'small',
|
||||
columns: [],
|
||||
columnsDnd: [],
|
||||
columnsData: [],
|
||||
arrayChildExpandKeys: [],
|
||||
data: [],
|
||||
dataRule: {},
|
||||
});
|
||||
|
||||
/**多列表编辑 */
|
||||
function arrayEdit(rowIndex: Record<string, any>) {
|
||||
const item = arrayState.data.find((s: any) => s.key === rowIndex.value);
|
||||
if (!item) return;
|
||||
const from = arrayInitEdit(item, arrayState.dataRule);
|
||||
// 处理信息
|
||||
const row: Record<string, any> = {};
|
||||
for (const v of from.record) {
|
||||
if (Array.isArray(v.array)) {
|
||||
continue;
|
||||
}
|
||||
row[v.name] = Object.assign({}, v);
|
||||
}
|
||||
|
||||
// 特殊SMF-upfid选择
|
||||
if (treeState.neType === 'SMF' && Reflect.has(row, 'upfId')) {
|
||||
const v = row.upfId.value;
|
||||
if (typeof v === 'string') {
|
||||
if (v === '') {
|
||||
row.upfId.value = [];
|
||||
} else if (v.includes(';')) {
|
||||
row.upfId.value = v.split(';');
|
||||
} else if (v.includes(',')) {
|
||||
row.upfId.value = v.split(',');
|
||||
} else {
|
||||
row.upfId.value = [v];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modalState.from = row;
|
||||
modalState.type = 'arrayEdit';
|
||||
modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`;
|
||||
modalState.key = from.key;
|
||||
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||
modalState.open = true;
|
||||
|
||||
// 关闭嵌套
|
||||
arrayState.arrayChildExpandKeys = [];
|
||||
}
|
||||
|
||||
/**多列表编辑关闭 */
|
||||
function arrayEditClose() {
|
||||
arrayState.arrayChildExpandKeys = [];
|
||||
fnModalCancel();
|
||||
}
|
||||
|
||||
/**多列表编辑确认 */
|
||||
function arrayEditOk(from: Record<string, any>) {
|
||||
const loc = `${from['index']['value']}`;
|
||||
|
||||
// 特殊SMF-upfid选择
|
||||
if (treeState.neType === 'SMF' && Reflect.has(from, 'upfId')) {
|
||||
const v = from.upfId.value;
|
||||
if (Array.isArray(v)) {
|
||||
from.upfId.value = v.join(';');
|
||||
}
|
||||
}
|
||||
|
||||
// 遍历提取属性和值
|
||||
let data: Record<string, any> = {};
|
||||
for (const key in from) {
|
||||
// 子嵌套的不插入
|
||||
if (from[key]['array']) {
|
||||
continue;
|
||||
}
|
||||
// 检查规则
|
||||
const [ok, msg] = ruleVerification(from[key]);
|
||||
if (!ok) {
|
||||
message.warning({
|
||||
content: `${msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
return;
|
||||
}
|
||||
data[key] = from[key]['value'];
|
||||
}
|
||||
|
||||
// 发送
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
editPtNeConfigData({
|
||||
neType: treeState.neType,
|
||||
paramName: treeState.selectNode.paramName,
|
||||
paramData: data,
|
||||
loc: loc,
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.ne.neConfig.updateItem', {
|
||||
num: modalState.title,
|
||||
}),
|
||||
duration: 3,
|
||||
});
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.ne.neConfig.updateItemErr'),
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
arrayEditClose();
|
||||
});
|
||||
}
|
||||
|
||||
/**多列表删除单行 */
|
||||
function arrayDelete(rowIndex: Record<string, any>) {
|
||||
const loc = `${rowIndex.value}`;
|
||||
const title = `${treeState.selectNode.paramDisplay} Index-${loc}`;
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.neConfig.delItemTip', {
|
||||
num: title,
|
||||
}),
|
||||
onOk() {
|
||||
delPtNeConfigData({
|
||||
neType: treeState.neType,
|
||||
paramName: treeState.selectNode.paramName,
|
||||
loc: loc,
|
||||
}).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.ne.neConfig.delItemOk', {
|
||||
num: title,
|
||||
}),
|
||||
duration: 2,
|
||||
});
|
||||
arrayEditClose();
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**多列表新增单行 */
|
||||
function arrayAdd() {
|
||||
const from = arrayInitAdd(arrayState.data, arrayState.dataRule);
|
||||
|
||||
// 处理信息
|
||||
const row: Record<string, any> = {};
|
||||
for (const v of from.record) {
|
||||
if (Array.isArray(v.array)) {
|
||||
continue;
|
||||
}
|
||||
row[v.name] = Object.assign({}, v);
|
||||
}
|
||||
|
||||
// 特殊SMF-upfid选择
|
||||
if (treeState.neType === 'SMF' && Reflect.has(row, 'upfId')) {
|
||||
const v = row.upfId.value;
|
||||
if (typeof v === 'string') {
|
||||
if (v === '') {
|
||||
row.upfId.value = [];
|
||||
} else if (v.includes(';')) {
|
||||
row.upfId.value = v.split(';');
|
||||
} else if (v.includes(',')) {
|
||||
row.upfId.value = v.split(',');
|
||||
} else {
|
||||
row.upfId.value = [v];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modalState.from = row;
|
||||
modalState.type = 'arrayAdd';
|
||||
modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`;
|
||||
modalState.key = from.key;
|
||||
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||
modalState.open = true;
|
||||
}
|
||||
|
||||
/**多列表新增单行确认 */
|
||||
function arrayAddOk(from: Record<string, any>) {
|
||||
// 特殊SMF-upfid选择
|
||||
if (treeState.neType === 'SMF' && Reflect.has(from, 'upfId')) {
|
||||
const v = from.upfId.value;
|
||||
if (Array.isArray(v)) {
|
||||
from.upfId.value = v.join(';');
|
||||
}
|
||||
}
|
||||
|
||||
// 遍历提取属性和值
|
||||
let data: Record<string, any> = {};
|
||||
for (const key in from) {
|
||||
// 子嵌套的不插入
|
||||
if (from[key]['array']) {
|
||||
continue;
|
||||
}
|
||||
// 检查规则
|
||||
const [ok, msg] = ruleVerification(from[key]);
|
||||
if (!ok) {
|
||||
message.warning({
|
||||
content: `${msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
return;
|
||||
}
|
||||
data[key] = from[key]['value'];
|
||||
}
|
||||
|
||||
// 发送
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
addPtNeConfigData({
|
||||
neType: treeState.neType,
|
||||
paramName: treeState.selectNode.paramName,
|
||||
paramData: data,
|
||||
loc: `${from['index']['value']}`,
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.ne.neConfig.addItemOk', {
|
||||
num: modalState.title,
|
||||
}),
|
||||
duration: 3,
|
||||
});
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.ne.neConfig.addItemErr'),
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
arrayEditClose();
|
||||
});
|
||||
}
|
||||
|
||||
/**多列表编辑行数据初始化 */
|
||||
function arrayInitEdit(data: Record<string, any>, dataRule: any) {
|
||||
const dataFrom = data.record;
|
||||
const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule)));
|
||||
for (const row of ruleFrom.record) {
|
||||
// 子嵌套的不初始
|
||||
if (row.array) {
|
||||
row.value = [];
|
||||
continue;
|
||||
}
|
||||
// 查找项的值
|
||||
const item = dataFrom.find((s: any) => s.name === row.name);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
// 可选的
|
||||
row.optional = 'true';
|
||||
// 根据规则类型转值
|
||||
if (['enum', 'int'].includes(row.type)) {
|
||||
row.value = Number(item.value);
|
||||
} else if ('bool' === row.type) {
|
||||
row.value = Boolean(item.value);
|
||||
} else {
|
||||
row.value = item.value;
|
||||
}
|
||||
}
|
||||
ruleFrom.key = data.key;
|
||||
ruleFrom.title = data.title;
|
||||
return ruleFrom;
|
||||
}
|
||||
|
||||
/**多列表新增行数据初始化 */
|
||||
function arrayInitAdd(data: any[], dataRule: any) {
|
||||
// 有数据时取得最后的index
|
||||
let dataLastIndex = 0;
|
||||
if (data.length !== 0) {
|
||||
const lastFrom = Object.assign(
|
||||
{},
|
||||
JSON.parse(JSON.stringify(data.at(-1)))
|
||||
);
|
||||
if (lastFrom.record.length > 0) {
|
||||
dataLastIndex = parseInt(lastFrom.key);
|
||||
dataLastIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule)));
|
||||
for (const row of ruleFrom.record) {
|
||||
// 子嵌套的不初始
|
||||
if (row.array) {
|
||||
row.value = [];
|
||||
continue;
|
||||
}
|
||||
// 可选的
|
||||
row.optional = 'true';
|
||||
// index值
|
||||
if (row.name === 'index') {
|
||||
let newIndex =
|
||||
dataLastIndex !== 0 ? dataLastIndex : parseInt(row.value);
|
||||
if (isNaN(newIndex)) {
|
||||
newIndex = 0;
|
||||
}
|
||||
row.value = newIndex;
|
||||
ruleFrom.key = newIndex;
|
||||
ruleFrom.title = `Index-${newIndex}`;
|
||||
continue;
|
||||
}
|
||||
// 根据规则类型转值
|
||||
if (['enum', 'int'].includes(row.type)) {
|
||||
row.value = Number(row.value);
|
||||
}
|
||||
if ('bool' === row.type) {
|
||||
row.value = Boolean(row.value);
|
||||
}
|
||||
|
||||
// 特殊SMF-upfid选择
|
||||
if (treeState.neType === 'SMF' && row.name === 'upfId') {
|
||||
const v = row.value;
|
||||
if (typeof v === 'string') {
|
||||
if (v === '') {
|
||||
row.value = [];
|
||||
} else if (v.includes(';')) {
|
||||
row.value = v.split(';');
|
||||
} else if (v.includes(',')) {
|
||||
row.value = v.split(',');
|
||||
} else {
|
||||
row.value = [v];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ruleFrom;
|
||||
}
|
||||
|
||||
// 监听表格字段列排序变化关闭展开
|
||||
watch(
|
||||
() => arrayState.columnsDnd,
|
||||
() => {
|
||||
arrayEditClose();
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
arrayState,
|
||||
arrayEdit,
|
||||
arrayEditClose,
|
||||
arrayEditOk,
|
||||
arrayDelete,
|
||||
arrayAdd,
|
||||
arrayAddOk,
|
||||
arrayInitEdit,
|
||||
arrayInitAdd,
|
||||
};
|
||||
}
|
||||
@@ -1,348 +0,0 @@
|
||||
import {
|
||||
addPtNeConfigData,
|
||||
delPtNeConfigData,
|
||||
editPtNeConfigData,
|
||||
} from '@/api/pt/neConfig';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { Modal, message } from 'ant-design-vue/es';
|
||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||
import { nextTick, reactive } from 'vue';
|
||||
|
||||
/**
|
||||
* 参数配置array类型的嵌套array
|
||||
* @param param 父级传入 { t, treeState, fnActiveConfigNode, ruleVerification, modalState, arrayState, arrayInitEdit, arrayInitAdd, arrayEditClose}
|
||||
* @returns
|
||||
*/
|
||||
export default function useConfigArrayChild({
|
||||
t,
|
||||
treeState,
|
||||
fnActiveConfigNode,
|
||||
ruleVerification,
|
||||
modalState,
|
||||
arrayState,
|
||||
arrayInitEdit,
|
||||
arrayInitAdd,
|
||||
arrayEditClose,
|
||||
}: any) {
|
||||
/**多列嵌套列表状态类型 */
|
||||
type ArrayChildStateType = {
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**层级index */
|
||||
loc: string;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**多列嵌套记录字段 */
|
||||
columns: Record<string, any>[];
|
||||
/**表格字段列排序 */
|
||||
columnsDnd: Record<string, any>[];
|
||||
/**多列记录数据 */
|
||||
columnsData: Record<string, any>[];
|
||||
|
||||
/**多列嵌套记录数据 */
|
||||
data: Record<string, any>[];
|
||||
/**多列嵌套记录规则 */
|
||||
dataRule: Record<string, any>;
|
||||
};
|
||||
|
||||
/**多列嵌套表格状态 */
|
||||
let arrayChildState: ArrayChildStateType = reactive({
|
||||
title: '',
|
||||
loc: '',
|
||||
size: 'small',
|
||||
columns: [],
|
||||
columnsDnd: [],
|
||||
columnsData: [],
|
||||
data: [],
|
||||
dataRule: {},
|
||||
});
|
||||
|
||||
/**多列表展开嵌套行 */
|
||||
function arrayChildExpand(
|
||||
indexRow: Record<string, any>,
|
||||
row: Record<string, any>
|
||||
) {
|
||||
const loc = indexRow.value;
|
||||
if (arrayChildState.loc === `${loc}/${row.name}`) {
|
||||
arrayChildState.loc = '';
|
||||
arrayState.arrayChildExpandKeys = [];
|
||||
return;
|
||||
}
|
||||
arrayChildState.loc = '';
|
||||
arrayState.arrayChildExpandKeys = [];
|
||||
const from = Object.assign({}, JSON.parse(JSON.stringify(row)));
|
||||
// 无数据时
|
||||
if (!Array.isArray(from.value)) {
|
||||
from.value = [];
|
||||
}
|
||||
const dataArr = Object.freeze(from.value);
|
||||
const ruleArr = Object.freeze(from.array);
|
||||
|
||||
// 列表项数据
|
||||
const dataArray: Record<string, any>[] = [];
|
||||
for (const item of dataArr) {
|
||||
const index = item['index'];
|
||||
let record: Record<string, any>[] = [];
|
||||
for (const key of Object.keys(item)) {
|
||||
// 规则为准
|
||||
for (const rule of ruleArr) {
|
||||
if (rule['name'] === key) {
|
||||
const ruleItem = Object.assign({ optional: 'true' }, rule, {
|
||||
value: item[key],
|
||||
});
|
||||
record.push(ruleItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// dataArray.push(record);
|
||||
dataArray.push({ title: `Index-${index}`, key: index, record });
|
||||
}
|
||||
arrayChildState.data = dataArray;
|
||||
|
||||
// 无数据时,用于新增
|
||||
arrayChildState.dataRule = {
|
||||
title: `Index-0`,
|
||||
key: 0,
|
||||
record: ruleArr,
|
||||
};
|
||||
|
||||
// 列表数据
|
||||
const columnsData: Record<string, any>[] = [];
|
||||
for (const v of arrayChildState.data) {
|
||||
const row: Record<string, any> = {};
|
||||
for (const item of v.record) {
|
||||
row[item.name] = item;
|
||||
}
|
||||
columnsData.push(row);
|
||||
}
|
||||
arrayChildState.columnsData = columnsData;
|
||||
|
||||
// 列表字段
|
||||
const columns: Record<string, any>[] = [];
|
||||
for (const rule of arrayChildState.dataRule.record) {
|
||||
columns.push({
|
||||
title: rule.display,
|
||||
dataIndex: rule.name,
|
||||
align: 'left',
|
||||
resizable: true,
|
||||
width: 50,
|
||||
minWidth: 50,
|
||||
maxWidth: 250,
|
||||
});
|
||||
}
|
||||
columns.push({
|
||||
title: t('common.operate'),
|
||||
dataIndex: 'index',
|
||||
key: 'index',
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
width: 100,
|
||||
});
|
||||
arrayChildState.columns = columns;
|
||||
|
||||
nextTick(() => {
|
||||
// 设置展开key
|
||||
arrayState.arrayChildExpandKeys = [indexRow];
|
||||
// 层级标识
|
||||
arrayChildState.loc = `${loc}/${from['name']}`;
|
||||
// 设置展开列表标题
|
||||
arrayChildState.title = `${from['display']}`;
|
||||
});
|
||||
}
|
||||
|
||||
/**多列表嵌套行编辑 */
|
||||
function arrayChildEdit(rowIndex: Record<string, any>) {
|
||||
const item = arrayChildState.data.find(
|
||||
(s: any) => s.key === rowIndex.value
|
||||
);
|
||||
if (!item) return;
|
||||
const from = arrayInitEdit(item, arrayChildState.dataRule);
|
||||
// 处理信息
|
||||
const row: Record<string, any> = {};
|
||||
for (const v of from.record) {
|
||||
if (Array.isArray(v.array)) {
|
||||
continue;
|
||||
}
|
||||
row[v.name] = Object.assign({}, v);
|
||||
}
|
||||
|
||||
modalState.from = row;
|
||||
modalState.type = 'arrayChildEdit';
|
||||
modalState.title = `${arrayChildState.title} ${from.title}`;
|
||||
modalState.key = from.key;
|
||||
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||
modalState.open = true;
|
||||
}
|
||||
|
||||
/**多列表嵌套行编辑确认 */
|
||||
function arrayChildEditOk(from: Record<string, any>) {
|
||||
const loc = `${arrayChildState.loc}/${from['index']['value']}`;
|
||||
|
||||
let data: Record<string, any> = {};
|
||||
for (const key in from) {
|
||||
// 子嵌套的不插入
|
||||
if (from[key]['array']) {
|
||||
continue;
|
||||
}
|
||||
// 检查规则
|
||||
const [ok, msg] = ruleVerification(from[key]);
|
||||
if (!ok) {
|
||||
message.warning({
|
||||
content: `${msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
return;
|
||||
}
|
||||
data[key] = from[key]['value'];
|
||||
}
|
||||
|
||||
// 发送
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
editPtNeConfigData({
|
||||
neType: treeState.neType,
|
||||
paramName: treeState.selectNode.paramName,
|
||||
paramData: data,
|
||||
loc,
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.ne.neConfig.updateItem', {
|
||||
num: modalState.title,
|
||||
}),
|
||||
duration: 3,
|
||||
});
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.ne.neConfig.updateItemErr'),
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
arrayEditClose();
|
||||
});
|
||||
}
|
||||
|
||||
/**多列表嵌套行删除单行 */
|
||||
function arrayChildDelete(rowIndex: Record<string, any>) {
|
||||
const index = rowIndex.value;
|
||||
const loc = `${arrayChildState.loc}/${index}`;
|
||||
const title = `${arrayChildState.title} Index-${index}`;
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.neConfig.delItemTip', {
|
||||
num: title,
|
||||
}),
|
||||
onOk() {
|
||||
delPtNeConfigData({
|
||||
neType: treeState.neType,
|
||||
paramName: treeState.selectNode.paramName,
|
||||
loc,
|
||||
}).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.ne.neConfig.delItemOk', {
|
||||
num: title,
|
||||
}),
|
||||
duration: 2,
|
||||
});
|
||||
arrayEditClose();
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**多列表嵌套行新增单行 */
|
||||
function arrayChildAdd() {
|
||||
const from = arrayInitAdd(arrayChildState.data, arrayChildState.dataRule);
|
||||
// 处理信息
|
||||
const row: Record<string, any> = {};
|
||||
for (const v of from.record) {
|
||||
if (Array.isArray(v.array)) {
|
||||
continue;
|
||||
}
|
||||
row[v.name] = Object.assign({}, v);
|
||||
}
|
||||
|
||||
modalState.from = row;
|
||||
modalState.type = 'arrayChildAdd';
|
||||
modalState.title = `${arrayChildState.title} ${from.title}`;
|
||||
modalState.key = from.key;
|
||||
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||
modalState.open = true;
|
||||
}
|
||||
|
||||
/**多列表新增单行确认 */
|
||||
function arrayChildAddOk(from: Record<string, any>) {
|
||||
const loc = `${arrayChildState.loc}/${from['index']['value']}`;
|
||||
|
||||
let data: Record<string, any> = {};
|
||||
for (const key in from) {
|
||||
// 子嵌套的不插入
|
||||
if (from[key]['array']) {
|
||||
continue;
|
||||
}
|
||||
// 检查规则
|
||||
const [ok, msg] = ruleVerification(from[key]);
|
||||
if (!ok) {
|
||||
message.warning({
|
||||
content: `${msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
return;
|
||||
}
|
||||
data[key] = from[key]['value'];
|
||||
}
|
||||
|
||||
// 发送
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
addPtNeConfigData({
|
||||
neType: treeState.neType,
|
||||
paramName: treeState.selectNode.paramName,
|
||||
paramData: data,
|
||||
loc,
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.ne.neConfig.addItemOk', {
|
||||
num: modalState.title,
|
||||
}),
|
||||
duration: 3,
|
||||
});
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.ne.neConfig.addItemErr'),
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
arrayEditClose();
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
arrayChildState,
|
||||
arrayChildExpand,
|
||||
arrayChildEdit,
|
||||
arrayChildEditOk,
|
||||
arrayChildDelete,
|
||||
arrayChildAdd,
|
||||
arrayChildAddOk,
|
||||
};
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
import { editPtNeConfigData } from '@/api/pt/neConfig';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||
import { message } from 'ant-design-vue/es';
|
||||
import { reactive, toRaw } from 'vue';
|
||||
|
||||
/**
|
||||
* list类型参数处理
|
||||
* @param param 父级传入 {t, treeState, ruleVerification}
|
||||
* @returns
|
||||
*/
|
||||
export default function useConfigList({ t, treeState, ruleVerification }: any) {
|
||||
/**单列表状态类型 */
|
||||
type ListStateType = {
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**单列记录字段 */
|
||||
columns: Record<string, any>[];
|
||||
/**单列记录数据 */
|
||||
data: Record<string, any>[];
|
||||
/**编辑行记录 */
|
||||
editRecord: Record<string, any>;
|
||||
/**确认提交等待 */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**单列表状态 */
|
||||
let listState: ListStateType = reactive({
|
||||
size: 'small',
|
||||
columns: [
|
||||
{
|
||||
title: 'Key',
|
||||
dataIndex: 'display',
|
||||
align: 'left',
|
||||
width: '30%',
|
||||
},
|
||||
{
|
||||
title: 'Value',
|
||||
dataIndex: 'value',
|
||||
align: 'left',
|
||||
width: '70%',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
confirmLoading: false,
|
||||
editRecord: {},
|
||||
});
|
||||
|
||||
/**单列表编辑 */
|
||||
function listEdit(row: Record<string, any>) {
|
||||
if (
|
||||
listState.confirmLoading ||
|
||||
['read-only', 'read', 'ro'].includes(row.access)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
listState.editRecord = Object.assign({}, row);
|
||||
}
|
||||
|
||||
/**单列表编辑关闭 */
|
||||
function listEditClose() {
|
||||
listState.confirmLoading = false;
|
||||
listState.editRecord = {};
|
||||
}
|
||||
|
||||
/**单列表编辑确认 */
|
||||
function listEditOk() {
|
||||
if (listState.confirmLoading) return;
|
||||
const from = toRaw(listState.editRecord);
|
||||
// 检查规则
|
||||
const [ok, msg] = ruleVerification(from);
|
||||
if (!ok) {
|
||||
message.warning({
|
||||
content: `${msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 发送
|
||||
listState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
editPtNeConfigData({
|
||||
neType: treeState.neType,
|
||||
paramName: treeState.selectNode.paramName,
|
||||
paramData: {
|
||||
[from['name']]: from['value'],
|
||||
},
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.ne.neConfig.updateValue', {
|
||||
num: from['display'],
|
||||
}),
|
||||
duration: 3,
|
||||
});
|
||||
// 改变表格数据
|
||||
const item = listState.data.find(
|
||||
(item: Record<string, any>) => from['name'] === item['name']
|
||||
);
|
||||
if (item) {
|
||||
Object.assign(item, listState.editRecord);
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.ne.neConfig.updateValueErr'),
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
listState.confirmLoading = false;
|
||||
listState.editRecord = {};
|
||||
});
|
||||
}
|
||||
|
||||
/**表格分页器参数 */
|
||||
let tablePagination = reactive({
|
||||
/**当前页数 */
|
||||
current: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 10,
|
||||
/**默认的每页条数 */
|
||||
defaultPageSize: 10,
|
||||
/**指定每页可以显示多少条 */
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
/**只有一页时是否隐藏分页器 */
|
||||
hideOnSinglePage: true,
|
||||
/**是否可以快速跳转至某页 */
|
||||
showQuickJumper: true,
|
||||
/**是否可以改变 pageSize */
|
||||
showSizeChanger: true,
|
||||
/**数据总数 */
|
||||
total: 0,
|
||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
||||
onChange: (page: number, pageSize: number) => {
|
||||
tablePagination.current = page;
|
||||
tablePagination.pageSize = pageSize;
|
||||
},
|
||||
});
|
||||
|
||||
return { tablePagination, listState, listEdit, listEditClose, listEditOk };
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
import { getNeConfigData } from '@/api/ne/neConfig';
|
||||
import { regExpIPv4, regExpIPv6, validURL } from '@/utils/regular-utils';
|
||||
import { ref } from 'vue';
|
||||
|
||||
/**
|
||||
* 参数公共函数
|
||||
* @param param 父级传入 {t}
|
||||
* @returns
|
||||
*/
|
||||
export default function useOptions({ t }: any) {
|
||||
/**规则校验 */
|
||||
function ruleVerification(row: Record<string, 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.ne.neConfig.requireInt', {
|
||||
display,
|
||||
filter,
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'ipv4':
|
||||
if (!regExpIPv4.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireIpv4', { display }),
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'ipv6':
|
||||
if (!regExpIPv6.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireIpv6', { display }),
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'enum':
|
||||
if (filter && filter.indexOf('{') === 1) {
|
||||
let filterJson: Record<string, any> = {};
|
||||
try {
|
||||
filterJson = JSON.parse(filter); //string---json
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if (!Object.keys(filterJson).includes(`${value}`)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireEnum', { display }),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'bool':
|
||||
// filter: '{"0":"false", "1":"true"}'
|
||||
|
||||
if (filter && filter.indexOf('{') === 1) {
|
||||
let filterJson: Record<string, any> = {};
|
||||
try {
|
||||
filterJson = JSON.parse(filter); //string---json
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if (!Object.values(filterJson).includes(`${value}`)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireBool', { display }),
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
// filter: "0~128"
|
||||
|
||||
// 字符串长度判断
|
||||
if (filter && 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.ne.neConfig.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
// 字符串http判断
|
||||
if (value.startsWith('http')) {
|
||||
try {
|
||||
if (!validURL(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'regex':
|
||||
// filter: "^[0-9]{3}$"
|
||||
|
||||
if (filter) {
|
||||
try {
|
||||
let regex = new RegExp(filter);
|
||||
if (!regex.test(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return [
|
||||
false,
|
||||
t('views.ne.neConfig.requireUn', { display }),
|
||||
];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**upfId可选择 */
|
||||
const smfByUPFIdOptions = ref<{ value: string; label: string }[]>([]);
|
||||
/**加载smf配置的upfId */
|
||||
function smfByUPFIdLoadData(neId: string) {
|
||||
getNeConfigData({
|
||||
neType: 'SMF',
|
||||
neId: neId,
|
||||
paramName: 'upfConfig',
|
||||
}).then(res => {
|
||||
smfByUPFIdOptions.value = [];
|
||||
for (const s of res.data) {
|
||||
smfByUPFIdOptions.value.push({
|
||||
value: s.id,
|
||||
label: s.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
ruleVerification,
|
||||
smfByUPFIdLoadData,
|
||||
smfByUPFIdOptions,
|
||||
};
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
import { ptSaveAsDefault, ptResetAsDefault } from '@/api/pt/neConfig';
|
||||
import {
|
||||
getPtClassStudents,
|
||||
stuPtNeConfigApply,
|
||||
updatePtNeConfigApply,
|
||||
} from '@/api/pt/neConfigApply';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { Modal } from 'ant-design-vue/es';
|
||||
import { message } from 'ant-design-vue/lib';
|
||||
import { computed, reactive } from 'vue';
|
||||
|
||||
/**
|
||||
* 实训教学函数
|
||||
* @param param 父级传入 {t,fnActiveConfigNode}
|
||||
* @returns
|
||||
*/
|
||||
export default function usePtOptions({ t, fnActiveConfigNode }: any) {
|
||||
const ptConfigState = reactive({
|
||||
saveLoading: false,
|
||||
restLoading: false,
|
||||
applyLoading: false,
|
||||
});
|
||||
/**(管理员)保存网元下所有配置为示例配置 */
|
||||
function ptConfigSave(neType: string) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.configManage.configParamForm.ptLoadTip'),
|
||||
onOk() {
|
||||
ptConfigState.saveLoading = true;
|
||||
ptSaveAsDefault(neType, '001')
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
ptConfigState.saveLoading = false;
|
||||
fnActiveConfigNode('#');
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**重置网元下所有配置 */
|
||||
function ptConfigReset(neType: string) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.configManage.configParamForm.ptResetTip'),
|
||||
onOk() {
|
||||
ptConfigState.restLoading = true;
|
||||
ptResetAsDefault(neType)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
ptConfigState.restLoading = false;
|
||||
fnActiveConfigNode('#');
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**配置下方应用(学生)申请撤回和(管理/教师)应用退回 */
|
||||
function ptConfigApply(
|
||||
neType: string,
|
||||
status: '0' | '1' | '2' | '3',
|
||||
student?: string
|
||||
) {
|
||||
let result: any;
|
||||
if (status === '2' || status === '3') {
|
||||
let from: {
|
||||
neType: string;
|
||||
status: string;
|
||||
student?: string;
|
||||
backInfo?: string;
|
||||
} = {
|
||||
neType,
|
||||
status: '2',
|
||||
};
|
||||
if (student) {
|
||||
if (status === '2') {
|
||||
from = { neType, status, student };
|
||||
}
|
||||
if (status === '3') {
|
||||
from = { neType, status, student, backInfo: '请重新检查配置' };
|
||||
}
|
||||
}
|
||||
result = updatePtNeConfigApply(from);
|
||||
}
|
||||
if (status === '0' || status === '1') {
|
||||
result = stuPtNeConfigApply({ neType, status });
|
||||
}
|
||||
if (!result) return;
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.configManage.configParamForm.ptApplyStuTip', {
|
||||
ne: neType,
|
||||
}),
|
||||
onOk() {
|
||||
ptConfigState.applyLoading = true;
|
||||
result
|
||||
.then((res: any) => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
// 教师修改学生时改变状态
|
||||
if (student) {
|
||||
const item = classState.studentOptionsDef.find(
|
||||
s => s.value === classState.student
|
||||
);
|
||||
if (item) {
|
||||
item.applyStatus = status;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
ptConfigState.applyLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const classState = reactive<{
|
||||
/**学生账号 */
|
||||
student: string | undefined;
|
||||
/**学生可选择列表 */
|
||||
studentOptions: {
|
||||
value: string;
|
||||
label: string;
|
||||
applyId: string;
|
||||
applyStatus: string;
|
||||
}[];
|
||||
studentOptionsDef: {
|
||||
value: string;
|
||||
label: string;
|
||||
applyId: string;
|
||||
applyStatus: string;
|
||||
}[];
|
||||
}>({
|
||||
student: undefined,
|
||||
studentOptions: [],
|
||||
studentOptionsDef: [],
|
||||
});
|
||||
|
||||
/**学生选择搜索 */
|
||||
function studentChange(v: any) {
|
||||
if (!v) {
|
||||
Object.assign(classState.studentOptions, classState.studentOptionsDef);
|
||||
}
|
||||
fnActiveConfigNode('#');
|
||||
}
|
||||
|
||||
let timeout: any;
|
||||
|
||||
/**学生选择搜索 */
|
||||
function studentSearch(neType: string, val: string) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
if (!val) {
|
||||
Object.assign(classState.studentOptions, classState.studentOptionsDef);
|
||||
return;
|
||||
}
|
||||
timeout = setTimeout(() => classStudents(neType, val), 500);
|
||||
}
|
||||
|
||||
/**班级学生列表 */
|
||||
function classStudents(neType: string, val?: string) {
|
||||
getPtClassStudents({ neType, userName: val }).then(res => {
|
||||
classState.studentOptions = [];
|
||||
if (!Array.isArray(res.data) || res.data.length <= 0) {
|
||||
return;
|
||||
}
|
||||
for (const v of res.data) {
|
||||
classState.studentOptions.push({
|
||||
value: v.userName,
|
||||
label: v.userName,
|
||||
applyId: v.applyId,
|
||||
applyStatus: v.applyStatus,
|
||||
});
|
||||
// 设为最新状态
|
||||
const item = classState.studentOptionsDef.find(
|
||||
s => s.value === v.userName
|
||||
);
|
||||
if (item) {
|
||||
item.applyStatus = v.applyStatus;
|
||||
}
|
||||
}
|
||||
if (!val) {
|
||||
Object.assign(classState.studentOptionsDef, classState.studentOptions);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 学生状态
|
||||
const studentStatus = computed(() => {
|
||||
const item = classState.studentOptionsDef.find(
|
||||
s => s.value === classState.student
|
||||
);
|
||||
if (item) return item.applyStatus;
|
||||
return '';
|
||||
});
|
||||
|
||||
return {
|
||||
ptConfigState,
|
||||
ptConfigSave,
|
||||
ptConfigReset,
|
||||
ptConfigApply,
|
||||
classState,
|
||||
classStudents,
|
||||
studentStatus,
|
||||
studentSearch,
|
||||
studentChange,
|
||||
};
|
||||
}
|
||||
@@ -1,368 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, nextTick, watch } from 'vue';
|
||||
import * as echarts from 'echarts/core';
|
||||
import { GridComponent, GridComponentOption } from 'echarts/components';
|
||||
import {
|
||||
BarChart,
|
||||
BarSeriesOption,
|
||||
PictorialBarChart,
|
||||
PictorialBarSeriesOption,
|
||||
} from 'echarts/charts';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
import { graphNodeClickID, graphNodeState } from '../../hooks/useTopology';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { markRaw } from 'vue';
|
||||
const { t } = useI18n();
|
||||
|
||||
echarts.use([GridComponent, BarChart, PictorialBarChart, CanvasRenderer]);
|
||||
|
||||
type EChartsOption = echarts.ComposeOption<
|
||||
GridComponentOption | BarSeriesOption | PictorialBarSeriesOption
|
||||
>;
|
||||
|
||||
/**图DOM节点实例对象 */
|
||||
const neResourcesDom = ref<HTMLElement | undefined>(undefined);
|
||||
|
||||
/**图实例对象 */
|
||||
const neResourcesChart = ref<any>(null);
|
||||
|
||||
// 类别
|
||||
const category = ref<any>([
|
||||
{
|
||||
name: t('views.dashboard.overview.resources.sysDisk'),
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: t('views.dashboard.overview.resources.sysMem'),
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: t('views.dashboard.overview.resources.sysCpu'),
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: t('views.dashboard.overview.resources.neCpu'),
|
||||
value: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
// 数据总数
|
||||
const total = 100;
|
||||
|
||||
/**图数据 */
|
||||
const optionData: EChartsOption = {
|
||||
xAxis: {
|
||||
max: total,
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
top: '1%', // 设置条形图的边距
|
||||
bottom: '12%',
|
||||
left: '25%',
|
||||
right: '25%',
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
inverse: false,
|
||||
data: category.value,
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
// 内
|
||||
type: 'bar',
|
||||
barWidth: 10,
|
||||
legendHoverLink: false,
|
||||
silent: true,
|
||||
itemStyle: {
|
||||
color: function (params) {
|
||||
// 红色
|
||||
if (params.value && +params.value >= 70) {
|
||||
return new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: '#fff1f0' },
|
||||
{ offset: 0.5, color: '#ffa39e' },
|
||||
{ offset: 1, color: '#f5222d' },
|
||||
]);
|
||||
}
|
||||
// 蓝色
|
||||
if (params.value && +params.value >= 30) {
|
||||
return new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: '#f0f5ff' },
|
||||
{ offset: 0.5, color: '#adc6ff' },
|
||||
{ offset: 1, color: '#2f54eb' },
|
||||
]);
|
||||
}
|
||||
// 绿色
|
||||
return new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: '#f6ffed' },
|
||||
{ offset: 0.5, color: '#b7eb8f' },
|
||||
{ offset: 1, color: '#52c41a' },
|
||||
]);
|
||||
},
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'left',
|
||||
formatter: '{b}: ',
|
||||
fontSize: 15,
|
||||
color: '#fff',
|
||||
},
|
||||
data: category.value,
|
||||
z: 1,
|
||||
animationEasing: 'elasticOut',
|
||||
},
|
||||
{
|
||||
// 分隔
|
||||
type: 'pictorialBar',
|
||||
itemStyle: {
|
||||
color: '#0a3ca0',
|
||||
},
|
||||
symbolRepeat: 'fixed',
|
||||
symbolMargin: 6,
|
||||
symbol: 'rect',
|
||||
symbolClip: true,
|
||||
symbolSize: [1, 12],
|
||||
symbolPosition: 'start',
|
||||
symbolOffset: [0, -1],
|
||||
symbolBoundingData: total,
|
||||
data: category.value,
|
||||
z: 2,
|
||||
animationEasing: 'elasticOut',
|
||||
},
|
||||
{
|
||||
// 外边框
|
||||
type: 'pictorialBar',
|
||||
symbol: 'rect',
|
||||
symbolBoundingData: total,
|
||||
itemStyle: {
|
||||
color: 'transparent',
|
||||
},
|
||||
label: {
|
||||
formatter: params => {
|
||||
var text = `{a| ${params.value}%} `;
|
||||
if (params.value && +params.value >= 70) {
|
||||
text = `{c| ${params.value}%} `;
|
||||
} else if (params.value && +params.value >= 30) {
|
||||
text = `{b| ${params.value}%} `;
|
||||
}
|
||||
return text;
|
||||
},
|
||||
rich: {
|
||||
a: {
|
||||
color: '#52c41a', // 绿
|
||||
fontSize: 16,
|
||||
},
|
||||
b: {
|
||||
color: '#2f54eb', // 蓝
|
||||
fontSize: 16,
|
||||
},
|
||||
c: {
|
||||
color: '#f5222d', // 红
|
||||
fontSize: 16,
|
||||
},
|
||||
f: {
|
||||
color: '#ffffff', // 默认
|
||||
fontSize: 16,
|
||||
},
|
||||
},
|
||||
position: 'right',
|
||||
distance: 0, // 向右偏移位置
|
||||
show: true,
|
||||
},
|
||||
data: category.value,
|
||||
z: 0,
|
||||
animationEasing: 'elasticOut',
|
||||
},
|
||||
{
|
||||
name: '外框',
|
||||
type: 'bar',
|
||||
barGap: '-120%', // 设置外框粗细
|
||||
data: [total, total, total],
|
||||
barWidth: 14,
|
||||
itemStyle: {
|
||||
color: 'transparent', // 填充色
|
||||
borderColor: '#0a3ca0', // 边框色
|
||||
borderWidth: 1, // 边框宽度
|
||||
borderRadius: 1, //圆角半径
|
||||
},
|
||||
label: {
|
||||
// 标签显示位置
|
||||
show: false,
|
||||
position: 'top', // insideTop 或者横向的 insideLeft
|
||||
},
|
||||
z: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/**图数据渲染 */
|
||||
function handleRanderChart(
|
||||
container: HTMLElement | undefined,
|
||||
option: EChartsOption
|
||||
) {
|
||||
if (!container) return;
|
||||
neResourcesChart.value = markRaw(echarts.init(container, 'light'));
|
||||
option && neResourcesChart.value.setOption(option);
|
||||
|
||||
// 创建 ResizeObserver 实例
|
||||
var observer = new ResizeObserver(entries => {
|
||||
if (neResourcesChart.value) {
|
||||
neResourcesChart.value.resize();
|
||||
}
|
||||
});
|
||||
// 监听元素大小变化
|
||||
observer.observe(container);
|
||||
}
|
||||
|
||||
function fnChangeData(data: any[], itemID: string) {
|
||||
let info = data.find((item: any) => item.id === itemID);
|
||||
if (!info || !info.neState.online) return;
|
||||
// if (!info.neState.online) {
|
||||
// info = data.find((item: any) => item.id === itemID);
|
||||
// graphNodeClickID.value = itemID;
|
||||
// }
|
||||
// console.log(info.id);
|
||||
// console.log(info.neState.cpu.nfCpuUsage);
|
||||
// console.log(info.neState.cpu.sysCpuUsage);
|
||||
// console.log(info.neState.mem);
|
||||
// console.log(info.neState.disk);
|
||||
let sysCpuUsage = 0;
|
||||
let nfCpuUsage = 0;
|
||||
if (info.neState.cpu) {
|
||||
nfCpuUsage = info.neState.cpu.nfCpuUsage;
|
||||
const nfCpu = +(info.neState.cpu.nfCpuUsage / 100);
|
||||
nfCpuUsage = +nfCpu.toFixed(2);
|
||||
if (nfCpuUsage > 100) {
|
||||
nfCpuUsage = 100;
|
||||
}
|
||||
|
||||
sysCpuUsage = info.neState.cpu.sysCpuUsage;
|
||||
let sysCpu = +(info.neState.cpu.sysCpuUsage / 100);
|
||||
sysCpuUsage = +sysCpu.toFixed(2);
|
||||
if (sysCpuUsage > 100) {
|
||||
sysCpuUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysMemUsage = 0;
|
||||
if (info.neState.mem) {
|
||||
const men = info.neState.mem.sysMemUsage;
|
||||
sysMemUsage = +(men / 100).toFixed(2);
|
||||
if (sysMemUsage > 100) {
|
||||
sysMemUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysDiskUsage = 0;
|
||||
if (info.neState.disk && Array.isArray(info.neState.disk.partitionInfo)) {
|
||||
let disks: any[] = info.neState.disk.partitionInfo;
|
||||
disks = disks.sort((a, b) => +b.used - +a.used);
|
||||
if (disks.length > 0) {
|
||||
const { total, used } = disks[0];
|
||||
sysDiskUsage = +((used / total) * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
category.value[0].value = sysDiskUsage;
|
||||
category.value[1].value = sysMemUsage;
|
||||
category.value[2].value = sysCpuUsage;
|
||||
category.value[3].value = nfCpuUsage;
|
||||
neResourcesChart.value.setOption({
|
||||
series: [
|
||||
{
|
||||
data: category.value,
|
||||
},
|
||||
{
|
||||
data: category.value,
|
||||
},
|
||||
{
|
||||
data: category.value,
|
||||
},
|
||||
{
|
||||
data: category.value,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
graphNodeState,
|
||||
v => {
|
||||
fnChangeData(v, graphNodeClickID.value);
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
|
||||
watch(graphNodeClickID, v => {
|
||||
fnChangeData(graphNodeState.value, v);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// setInterval(function () {
|
||||
// var ndata = [
|
||||
// {
|
||||
// name: '系统内存',
|
||||
// value: Math.round(Math.random() * 100),
|
||||
// },
|
||||
// {
|
||||
// name: '系统CPU',
|
||||
// value: Math.round(Math.random() * 100),
|
||||
// },
|
||||
// {
|
||||
// name: '网元CPU',
|
||||
// value: Math.round(Math.random() * 100),
|
||||
// },
|
||||
// ];
|
||||
// neResourcesChart.value.setOption({
|
||||
// series: [
|
||||
// {
|
||||
// data: ndata,
|
||||
// },
|
||||
// {
|
||||
// data: ndata,
|
||||
// },
|
||||
// {
|
||||
// data: ndata,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// }, 2000);
|
||||
nextTick(() => {
|
||||
handleRanderChart(neResourcesDom.value, optionData);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="neResourcesDom" class="chart"></div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.chart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,493 +0,0 @@
|
||||
<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 './components/Topology/index.vue';
|
||||
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 { 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 './hooks/useTopology';
|
||||
import { upfTotalFlow, upfTFActive } from './hooks/useUPFTotalFlow';
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import useWS from './hooks/useWS';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { hasRoles } from '@/plugins/auth-user';
|
||||
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');
|
||||
|
||||
clearInterval(interval10s.value);
|
||||
interval10s.value = setInterval(() => {
|
||||
if (!interval10s.value) return
|
||||
if (upfTFActive.value === '0') {
|
||||
upfTFSend('7');
|
||||
upfTFActive.value = '7';
|
||||
} else if (upfTFActive.value === '7') {
|
||||
upfTFSend('30');
|
||||
upfTFActive.value = '30';
|
||||
} else if (upfTFActive.value === '30') {
|
||||
upfTFSend('0');
|
||||
upfTFActive.value = '0';
|
||||
}
|
||||
}, 10_000);
|
||||
|
||||
clearInterval(interval5s.value);
|
||||
interval5s.value = setInterval(() => {
|
||||
if (!interval5s.value) return
|
||||
fnGetSkim(); // 获取概览信息
|
||||
fnGetNeState(); // 获取网元状态
|
||||
}, 5_000);
|
||||
}
|
||||
|
||||
/**栏目信息跳转 */
|
||||
function fnToRouter(name: string, query?: any) {
|
||||
if (hasRoles(['student'])) return;
|
||||
router.push({ name, query });
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fnGetSkim().then(() => {
|
||||
loadData();
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(interval10s.value);
|
||||
interval10s.value = null;
|
||||
clearInterval(interval5s.value);
|
||||
interval5s.value = null;
|
||||
});
|
||||
</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" /> 5G
|
||||
{{ 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>
|
||||
</div>
|
||||
<div class="skim panel base">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
<GlobalOutlined style="color: #68d8fe" /> 4G
|
||||
{{ t('views.dashboard.overview.skim.baseTitle') }}
|
||||
</h3>
|
||||
<div class="data">
|
||||
<div
|
||||
class="item toRouter"
|
||||
@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 === v }"
|
||||
v-for="v in ['0', '7', '30']"
|
||||
:key="v"
|
||||
@click="
|
||||
() => {
|
||||
upfTFActive = v;
|
||||
}
|
||||
"
|
||||
>
|
||||
{{
|
||||
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>
|
||||
<!-- 告警统计 -->
|
||||
<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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import url('./css/index.css');
|
||||
</style>
|
||||
@@ -1,554 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, ref, onBeforeUnmount } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import {
|
||||
RESULT_CODE_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
} from '@/constants/result-constants';
|
||||
import { listAllNeInfo } from '@/api/ne/neInfo';
|
||||
import { message } from 'ant-design-vue/es';
|
||||
import { getGraphData } from '@/api/monitor/topology';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { Graph, GraphData, Menu, Tooltip } from '@antv/g6';
|
||||
import {
|
||||
edgeCubicAnimateCircleMove,
|
||||
edgeCubicAnimateLineDash,
|
||||
edgeLineAnimateState,
|
||||
} from '../topologyBuild/hooks/registerEdge';
|
||||
import {
|
||||
nodeCircleAnimateShapeR,
|
||||
nodeCircleAnimateShapeStroke,
|
||||
nodeImageAnimateState,
|
||||
nodeRectAnimateState,
|
||||
} from '../topologyBuild/hooks/registerNode';
|
||||
import useNeOptions from '@/views/ne/neInfo/hooks/useNeOptions';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||
import { hasRoles } from '@/plugins/auth-user';
|
||||
import { parseBasePath } from '@/plugins/file-static-url';
|
||||
const { t } = useI18n();
|
||||
const { fnNeRestart, fnNeStop, fnNeLogFile } = useNeOptions();
|
||||
const ws = new WS();
|
||||
|
||||
/**图DOM节点实例对象 */
|
||||
const graphG6Dom = ref<HTMLElement | undefined>(undefined);
|
||||
|
||||
/**图状态 */
|
||||
const graphState = reactive<Record<string, any>>({
|
||||
/**当前图组名 */
|
||||
group: '5GC System Architecture',
|
||||
/**图数据 */
|
||||
data: {
|
||||
combos: [],
|
||||
edges: [],
|
||||
nodes: [],
|
||||
},
|
||||
});
|
||||
|
||||
/**非网元元素 */
|
||||
const notNeNodes = [
|
||||
'5GC',
|
||||
'DN',
|
||||
'UE',
|
||||
'Base',
|
||||
'lan',
|
||||
'lan1',
|
||||
'lan2',
|
||||
'lan3',
|
||||
'lan4',
|
||||
'lan5',
|
||||
'lan6',
|
||||
'lan7',
|
||||
'LAN',
|
||||
'NR',
|
||||
];
|
||||
|
||||
/**图实例对象 */
|
||||
const graphG6 = ref<any>(null);
|
||||
|
||||
/**图节点右击菜单 */
|
||||
const graphNodeMenu = new Menu({
|
||||
offsetX: 6,
|
||||
offseY: 10,
|
||||
itemTypes: ['node'],
|
||||
getContent(evt) {
|
||||
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
|
||||
const { id, label, neState }: any = evt.item?.getModel();
|
||||
if (notNeNodes.includes(id)) {
|
||||
return `<div><span>${label || id}</span></div>`;
|
||||
}
|
||||
if (!neState) {
|
||||
return `<div><span>${label || id}</span></div>`;
|
||||
}
|
||||
if (hasRoles(['student'])) {
|
||||
return 'Student';
|
||||
}
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
"
|
||||
>
|
||||
<h3 style="margin-bottom: 8px">
|
||||
${t('views.monitor.topology.name')}:
|
||||
${neState.neName ?? '--'}
|
||||
</h3>
|
||||
<div id="restart" style="cursor: pointer; margin-bottom: 4px">
|
||||
> ${t('views.ne.common.restart')}
|
||||
</div>
|
||||
<div id="stop" style="cursor: pointer; margin-bottom: 4px;">
|
||||
> ${t('views.ne.common.stop')}
|
||||
</div>
|
||||
<div id="log" style="cursor: pointer; margin-bottom: 4px;">
|
||||
> ${t('views.ne.common.log')}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
const { neInfo }: any = item?.getModel();
|
||||
const { neName, neType, neId } = neInfo;
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'restart':
|
||||
fnNeRestart({ neName, neType, neId });
|
||||
break;
|
||||
case 'stop':
|
||||
fnNeStop({ neName, neType, neId });
|
||||
break;
|
||||
case 'log':
|
||||
fnNeLogFile({ neType, neId });
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**图节点展示 */
|
||||
const graphNodeTooltip = new Tooltip({
|
||||
offsetX: 10,
|
||||
offsetY: 20,
|
||||
getContent(evt) {
|
||||
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
|
||||
const { id, label, neState }: any = evt.item?.getModel();
|
||||
if (notNeNodes.includes(id)) {
|
||||
return `<div><span>${label || id}</span></div>`;
|
||||
}
|
||||
if (!neState) {
|
||||
return `<div><span>${label || id}</span></div>`;
|
||||
}
|
||||
let notStudentInfo = '';
|
||||
if (hasRoles(['teacher', 'admin'])) {
|
||||
notStudentInfo = `
|
||||
<div><strong>${t('views.monitor.topology.serialNum')}:</strong><span>
|
||||
${neState.sn ?? '--'}
|
||||
</span></div>
|
||||
<div><strong>${t('views.monitor.topology.expiryDate')}:</strong><span>
|
||||
${neState.expire ?? '--'}
|
||||
</span></div> `;
|
||||
}
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 200px;
|
||||
"
|
||||
>
|
||||
<div><strong>${t('views.monitor.topology.state')}:</strong><span>
|
||||
${
|
||||
neState.online
|
||||
? t('views.monitor.topology.normalcy')
|
||||
: t('views.monitor.topology.exceptions')
|
||||
}
|
||||
</span></div>
|
||||
<div><strong>${t('views.monitor.topology.refreshTime')}:</strong><span>
|
||||
${neState.refreshTime ?? '--'}
|
||||
</span></div>
|
||||
<div>========================</div>
|
||||
<div><strong>ID:</strong><span>${neState.neId}</span></div>
|
||||
<div><strong>${t('views.monitor.topology.name')}:</strong><span>
|
||||
${neState.neName ?? '--'}
|
||||
</span></div>
|
||||
<div><strong>IP:</strong><span>${neState.neIP}</span></div>
|
||||
<div><strong>${t('views.monitor.topology.version')}:</strong><span>
|
||||
${neState.version ?? '--'}
|
||||
</span></div>
|
||||
${notStudentInfo}
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
itemTypes: ['node'],
|
||||
});
|
||||
|
||||
/**注册自定义边或节点 */
|
||||
function registerEdgeNode() {
|
||||
// 边
|
||||
edgeCubicAnimateLineDash();
|
||||
edgeCubicAnimateCircleMove();
|
||||
edgeLineAnimateState();
|
||||
// 节点
|
||||
nodeCircleAnimateShapeR();
|
||||
nodeCircleAnimateShapeStroke();
|
||||
nodeRectAnimateState();
|
||||
nodeImageAnimateState();
|
||||
}
|
||||
|
||||
/**图数据渲染 */
|
||||
function handleRanderGraph(
|
||||
container: HTMLElement | undefined,
|
||||
data: GraphData
|
||||
) {
|
||||
if (!container) return;
|
||||
const { clientHeight, clientWidth } = container;
|
||||
|
||||
// 注册自定义边或节点
|
||||
registerEdgeNode();
|
||||
|
||||
const graph = new Graph({
|
||||
container: container,
|
||||
width: clientWidth,
|
||||
height: clientHeight,
|
||||
fitCenter: true,
|
||||
fitView: true,
|
||||
fitViewPadding: [40],
|
||||
autoPaint: true,
|
||||
modes: {
|
||||
default: [
|
||||
'drag-combo',
|
||||
'drag-canvas',
|
||||
'zoom-canvas',
|
||||
'collapse-expand-combo',
|
||||
],
|
||||
},
|
||||
groupByTypes: false,
|
||||
nodeStateStyles: {
|
||||
selected: {
|
||||
fill: 'transparent',
|
||||
},
|
||||
},
|
||||
plugins: [graphNodeMenu, graphNodeTooltip],
|
||||
animate: true, // 是否使用动画过度,默认为 false
|
||||
animateCfg: {
|
||||
duration: 500, // Number,一次动画的时长
|
||||
easing: 'linearEasing', // String,动画函数
|
||||
},
|
||||
});
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
|
||||
graphG6.value = graph;
|
||||
|
||||
// 创建 ResizeObserver 实例
|
||||
var observer = new ResizeObserver(function (entries) {
|
||||
// 当元素大小发生变化时触发回调函数
|
||||
entries.forEach(function (entry) {
|
||||
if (!graphG6.value) {
|
||||
return;
|
||||
}
|
||||
graphG6.value.changeSize(
|
||||
entry.contentRect.width,
|
||||
entry.contentRect.height - 30
|
||||
);
|
||||
graphG6.value.fitCenter();
|
||||
});
|
||||
});
|
||||
// 监听元素大小变化
|
||||
observer.observe(container);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图组数据渲染到画布
|
||||
* @param reload 是否重载数据
|
||||
*/
|
||||
function fnGraphDataLoad(reload: boolean = false) {
|
||||
Promise.all([
|
||||
getGraphData(graphState.group),
|
||||
listAllNeInfo({
|
||||
bandStatus: false,
|
||||
}),
|
||||
])
|
||||
.then(resArr => {
|
||||
const graphRes = resArr[0];
|
||||
const neRes = resArr[1];
|
||||
if (
|
||||
graphRes.code === RESULT_CODE_SUCCESS &&
|
||||
Array.isArray(graphRes.data.nodes) &&
|
||||
graphRes.data.nodes.length > 0 &&
|
||||
neRes.code === RESULT_CODE_SUCCESS &&
|
||||
Array.isArray(neRes.data) &&
|
||||
neRes.data.length > 0
|
||||
) {
|
||||
return {
|
||||
graphData: graphRes.data,
|
||||
neList: neRes.data,
|
||||
};
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.monitor.topology.noData'),
|
||||
duration: 5,
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
if (!res) return;
|
||||
const { combos, edges, nodes } = res.graphData;
|
||||
|
||||
// 节点过滤
|
||||
const nf: Record<string, any>[] = nodes.filter(
|
||||
(node: Record<string, any>) => {
|
||||
Reflect.set(node, 'neState', { online: false });
|
||||
// 图片路径处理
|
||||
if (node.img) node.img = parseBasePath(node.img);
|
||||
if (node.icon.show && node.icon?.img)
|
||||
node.icon.img = parseBasePath(node.icon.img);
|
||||
// 遍历是否有网元数据
|
||||
const nodeID: string = node.id;
|
||||
const hasNe = res.neList.some(ne => {
|
||||
Reflect.set(node, 'neInfo', ne.neType === nodeID ? ne : {});
|
||||
return ne.neType === nodeID;
|
||||
});
|
||||
if (hasNe) {
|
||||
return true;
|
||||
}
|
||||
if (notNeNodes.includes(nodeID)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
// 边过滤
|
||||
const ef: Record<string, any>[] = edges.filter(
|
||||
(edge: Record<string, any>) => {
|
||||
const edgeSource: string = edge.source;
|
||||
const edgeTarget: string = edge.target;
|
||||
const hasNeS = nf.some(n => n.id === edgeSource);
|
||||
const hasNeT = nf.some(n => n.id === edgeTarget);
|
||||
// console.log(hasNeS, edgeSource, hasNeT, edgeTarget);
|
||||
if (hasNeS && hasNeT) {
|
||||
return true;
|
||||
}
|
||||
if (hasNeS && notNeNodes.includes(edgeTarget)) {
|
||||
return true;
|
||||
}
|
||||
if (hasNeT && notNeNodes.includes(edgeSource)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
// 分组过滤
|
||||
combos.forEach((combo: Record<string, any>) => {
|
||||
const comboChildren: Record<string, any>[] = combo.children;
|
||||
combo.children = comboChildren.filter(c => nf.some(n => n.id === c.id));
|
||||
return combo;
|
||||
});
|
||||
|
||||
// 图数据
|
||||
graphState.data = { combos, edges: ef, nodes: nf };
|
||||
})
|
||||
.finally(() => {
|
||||
if (graphState.data.length < 0) return;
|
||||
// 重载数据
|
||||
if (reload) {
|
||||
graphG6.value.read(graphState.data);
|
||||
} else {
|
||||
handleRanderGraph(graphG6Dom.value, graphState.data);
|
||||
}
|
||||
clearInterval(interval10s.value);
|
||||
interval10s.value = null;
|
||||
fnGetState();
|
||||
interval10s.value = setInterval(async () => {
|
||||
if (!interval10s.value) return;
|
||||
fnGetState(); // 获取网元状态
|
||||
}, 20_000);
|
||||
});
|
||||
}
|
||||
|
||||
/**网元状态调度器 */
|
||||
const interval10s = ref<any>(null);
|
||||
|
||||
/**查询网元状态 */
|
||||
function fnGetState() {
|
||||
// 获取节点状态
|
||||
for (const node of graphState.data.nodes) {
|
||||
if (notNeNodes.includes(node.id)) continue;
|
||||
const { neType, neId } = node.neInfo;
|
||||
if (!neType || !neId) continue;
|
||||
ws.send({
|
||||
requestId: `${neType}_${neId}`,
|
||||
type: 'ne_state',
|
||||
data: {
|
||||
neType: neType,
|
||||
neId: neId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**接收数据后回调 */
|
||||
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 (!requestId) return;
|
||||
const [neType, neId] = requestId.split('_');
|
||||
const { combos, edges, nodes } = graphState.data;
|
||||
const node = nodes.find((item: Record<string, any>) => item.id === neType);
|
||||
|
||||
// 更新网元状态
|
||||
const newNeState = Object.assign(node.neState, data, {
|
||||
refreshTime: parseDateToStr(data.refreshTime, 'HH:mm:ss'),
|
||||
online: !!data.cpu,
|
||||
});
|
||||
|
||||
// 通过 ID 查询节点实例
|
||||
const item = graphG6.value.findById(node.id);
|
||||
if (item) {
|
||||
const stateColor = newNeState.online ? '#52c41a' : '#f5222d'; // 状态颜色
|
||||
// 图片类型不能填充
|
||||
if (node.type.startsWith('image')) {
|
||||
// 更新节点
|
||||
if (node.label !== newNeState.neName) {
|
||||
graphG6.value.updateItem(item, {
|
||||
label: newNeState.neName,
|
||||
});
|
||||
}
|
||||
// 设置状态
|
||||
graphG6.value.setItemState(item, 'top-right-dot', stateColor);
|
||||
} else {
|
||||
// 更新节点
|
||||
graphG6.value.updateItem(item, {
|
||||
label: newNeState.neName,
|
||||
// neState: newNeState,
|
||||
style: {
|
||||
fill: stateColor, // 填充色
|
||||
stroke: stateColor, // 填充色
|
||||
},
|
||||
// labelCfg: {
|
||||
// style: {
|
||||
// fill: '#ffffff', // 标签文本色
|
||||
// },
|
||||
// },
|
||||
});
|
||||
// 设置状态
|
||||
graphG6.value.setItemState(item, 'stroke', newNeState.online);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置边状态
|
||||
for (const edge of edges) {
|
||||
const edgeSource: string = edge.source;
|
||||
const edgeTarget: string = edge.target;
|
||||
const neS = nodes.find((n: any) => n.id === edgeSource);
|
||||
const neT = nodes.find((n: any) => n.id === edgeTarget);
|
||||
// console.log(neS, edgeSource, neT, edgeTarget);
|
||||
|
||||
if (neS && neT) {
|
||||
// 通过 ID 查询节点实例
|
||||
// const item = graphG6.value.findById(edge.id);
|
||||
// console.log(
|
||||
// `${edgeSource} - ${edgeTarget}`,
|
||||
// neS.neState.online && neT.neState.online
|
||||
// );
|
||||
// const stateColor = neS.neState.online && neT.neState.online ? '#000000' : '#ff4d4f'; // 状态颜色
|
||||
// 更新边
|
||||
// graphG6.value.updateItem(item, {
|
||||
// label: `${edgeSource} - ${edgeTarget}`,
|
||||
// style: {
|
||||
// stroke: stateColor, // 填充色
|
||||
// },
|
||||
// labelCfg: {
|
||||
// style: {
|
||||
// fill: '#ffffff', // 标签文本色
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// 设置状态
|
||||
graphG6.value.setItemState(
|
||||
edge.id,
|
||||
'circle-move',
|
||||
neS.neState.online && neT.neState.online
|
||||
);
|
||||
}
|
||||
if (neS && notNeNodes.includes(edgeTarget)) {
|
||||
graphG6.value.setItemState(edge.id, 'line-dash', neS.neState.online);
|
||||
}
|
||||
if (neT && notNeNodes.includes(edgeSource)) {
|
||||
graphG6.value.setItemState(edge.id, 'line-dash', neT.neState.online);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fnGraphDataLoad(false);
|
||||
|
||||
// 建立链接
|
||||
const options: OptionsType = {
|
||||
url: '/ws',
|
||||
onmessage: wsMessage,
|
||||
onerror: wsError,
|
||||
};
|
||||
ws.connect(options);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
ws.close();
|
||||
clearInterval(interval10s.value);
|
||||
interval10s.value = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px' }"
|
||||
size="small"
|
||||
>
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<span>
|
||||
{{ t('views.monitor.topologyBuild.graphGroup') }}:
|
||||
{{ graphState.group }}
|
||||
</span>
|
||||
</a-space>
|
||||
</template>
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-button
|
||||
type="default"
|
||||
size="small"
|
||||
@click.prevent="fnGraphDataLoad(true)"
|
||||
>
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
{{ t('common.reloadText') }}
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<div ref="graphG6Dom" class="chart"></div>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.chart {
|
||||
width: 100%;
|
||||
height: calc(100vh - 300px);
|
||||
background-color: rgb(43, 47, 51);
|
||||
}
|
||||
</style>
|
||||
@@ -1,374 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRaw, watch } from 'vue';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import { Form, Modal, Upload, message, notification } from 'ant-design-vue/es';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface';
|
||||
import { FileType, UploadFile } from 'ant-design-vue/es/upload/interface';
|
||||
import {
|
||||
exportNeConfigBackup,
|
||||
importNeConfigBackup,
|
||||
listNeConfigBackup,
|
||||
} from '@/api/ne/neConfigBackup';
|
||||
import saveAs from 'file-saver';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**网元ID */
|
||||
neId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
neType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
/**导入状态数据 */
|
||||
const importState = reactive({
|
||||
typeOption: [
|
||||
{ label: t('views.ne.neInfo.backConf.server'), value: 'backup' },
|
||||
{ label: t('views.ne.neInfo.backConf.local'), value: 'upload' },
|
||||
],
|
||||
backupData: <any[]>[],
|
||||
});
|
||||
|
||||
/**查询网元远程服务器备份文件 */
|
||||
function backupSearch(name?: string) {
|
||||
const { neType, neId } = modalState.from;
|
||||
listNeConfigBackup({
|
||||
neType,
|
||||
neId,
|
||||
name,
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
}).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
importState.backupData = [];
|
||||
res.rows.forEach((item: any) => {
|
||||
importState.backupData.push({
|
||||
label: item.name,
|
||||
value: item.path,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**服务器备份文件选择切换 */
|
||||
function backupChange(value: any) {
|
||||
if (!value) {
|
||||
backupSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/**类型切换 */
|
||||
function typeChange(value: any) {
|
||||
modalState.from.path = undefined;
|
||||
if (value === 'backup') {
|
||||
backupSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**新增框或修改框是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**表单数据 */
|
||||
from: {
|
||||
neType: string;
|
||||
neId: string;
|
||||
type: 'upload' | 'backup';
|
||||
path: string | undefined;
|
||||
};
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
/**上传文件 */
|
||||
uploadFiles: any[];
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByEdit: false,
|
||||
title: '配置文件导入',
|
||||
from: {
|
||||
neType: '',
|
||||
neId: '',
|
||||
type: 'upload',
|
||||
path: undefined,
|
||||
},
|
||||
confirmLoading: false,
|
||||
uploadFiles: [],
|
||||
});
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
path: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.neInfo.backConf.pathPlease'),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalOk() {
|
||||
if (modalState.confirmLoading) return;
|
||||
const from = toRaw(modalState.from);
|
||||
modalStateFrom
|
||||
.validate()
|
||||
.then(e => {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
importNeConfigBackup(from)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
// 返回无引用信息
|
||||
emit('ok', JSON.parse(JSON.stringify(from)));
|
||||
fnModalCancel();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.confirmLoading = false;
|
||||
modalStateFrom.resetFields();
|
||||
modalState.uploadFiles = [];
|
||||
emit('cancel');
|
||||
emit('update:open', false);
|
||||
}
|
||||
|
||||
/**表单上传前删除 */
|
||||
function fnBeforeRemoveFile(file: UploadFile) {
|
||||
modalState.from.path = undefined;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**表单上传前检查或转换压缩 */
|
||||
function fnBeforeUploadFile(file: FileType) {
|
||||
if (modalState.confirmLoading) return false;
|
||||
if (!file.name.endsWith('.zip')) {
|
||||
const msg = `${t('components.UploadModal.onlyAllow')} .zip`;
|
||||
message.error(msg, 3);
|
||||
return Upload.LIST_IGNORE;
|
||||
}
|
||||
const isLt3M = file.size / 1024 / 1024 < 100;
|
||||
if (!isLt3M) {
|
||||
const msg = `${t('components.UploadModal.allowFilter')} 100MB`;
|
||||
message.error(msg, 3);
|
||||
return Upload.LIST_IGNORE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**表单上传文件 */
|
||||
function fnUploadFile(up: UploadRequestOption) {
|
||||
// 发送请求
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
modalState.confirmLoading = true;
|
||||
let formData = new FormData();
|
||||
formData.append('file', up.file);
|
||||
formData.append('subPath', 'import');
|
||||
uploadFile(formData)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// 改为完成状态
|
||||
const file = modalState.uploadFiles[0];
|
||||
file.percent = 100;
|
||||
file.status = 'done';
|
||||
// 预置到表单
|
||||
const { fileName } = res.data;
|
||||
modalState.from.path = fileName;
|
||||
} else {
|
||||
message.error(res.msg, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
if (val) {
|
||||
if (props.neType && props.neId) {
|
||||
modalState.from.neType = props.neType;
|
||||
modalState.from.neId = props.neId;
|
||||
modalState.title = t('views.ne.neInfo.backConf.title');
|
||||
modalState.openByEdit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 网元导出配置
|
||||
* @param row 网元编号ID
|
||||
*/
|
||||
function fnExportConf(neType: string, neId: string) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.neInfo.backConf.exportTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
exportNeConfigBackup({ neType, neId })
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
notification.success({
|
||||
message: t('common.tipTitle'),
|
||||
description: t('views.ne.neInfo.backConf.exportMsg'),
|
||||
});
|
||||
saveAs(
|
||||
res.data,
|
||||
`${neType}_${neId}_config_backup_${Date.now()}.zip`
|
||||
);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 给组件设置属性 ref="xxxBackConf"
|
||||
// setup内使用 const xxxBackConf = ref();
|
||||
defineExpose({
|
||||
/**导出文件 */
|
||||
exportConf: fnExportConf,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form name="modalStateFrom" layout="horizontal" :label-col="{ span: 6 }">
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.common.neType')" name="neType">
|
||||
{{ modalState.from.neType }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.backConf.importType')"
|
||||
name="type"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.type"
|
||||
default-value="server"
|
||||
:options="importState.typeOption"
|
||||
@change="typeChange"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.common.neId')" name="neId">
|
||||
{{ modalState.from.neId }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.backConf.server')"
|
||||
name="fileName"
|
||||
v-bind="modalStateFrom.validateInfos.path"
|
||||
v-if="modalState.from.type === 'backup'"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.path"
|
||||
:options="importState.backupData"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:show-search="true"
|
||||
:default-active-first-option="false"
|
||||
:show-arrow="false"
|
||||
:allow-clear="true"
|
||||
:filter-option="false"
|
||||
:not-found-content="null"
|
||||
@search="backupSearch"
|
||||
@change="backupChange"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.backConf.local')"
|
||||
name="file"
|
||||
v-bind="modalStateFrom.validateInfos.path"
|
||||
v-if="modalState.from.type === 'upload'"
|
||||
>
|
||||
<a-upload
|
||||
name="file"
|
||||
v-model:file-list="modalState.uploadFiles"
|
||||
accept=".zip"
|
||||
list-type="text"
|
||||
:max-count="1"
|
||||
:show-upload-list="{
|
||||
showPreviewIcon: false,
|
||||
showRemoveIcon: true,
|
||||
showDownloadIcon: false,
|
||||
}"
|
||||
:remove="fnBeforeRemoveFile"
|
||||
:before-upload="fnBeforeUploadFile"
|
||||
:custom-request="fnUploadFile"
|
||||
:disabled="modalState.confirmLoading"
|
||||
>
|
||||
<a-button type="primary">
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
{{ t('views.ne.neInfo.backConf.localUpload') }}
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -1,834 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, watch } from 'vue';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import { message, Form, Modal } from 'ant-design-vue/es';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
|
||||
import { getNeInfo, addNeInfo, updateNeInfo } from '@/api/ne/neInfo';
|
||||
import { neHostAuthorizedRSA, testNeHost } from '@/api/ne/neHost';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { getDict } = useDictStore();
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
editId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
/**主机类型 */
|
||||
neHostType: DictType[];
|
||||
/**分组 */
|
||||
neHostGroupId: DictType[];
|
||||
/**认证模式 */
|
||||
neHostAuthMode: DictType[];
|
||||
} = reactive({
|
||||
neHostType: [],
|
||||
neHostGroupId: [],
|
||||
neHostAuthMode: [],
|
||||
});
|
||||
|
||||
/**
|
||||
* 测试主机连接
|
||||
*/
|
||||
function fnHostTest(row: Record<string, any>) {
|
||||
if (modalState.confirmLoading || !row.addr || !row.port) return;
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
testNeHost(row)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: `${row.addr}:${row.port} ${t('views.ne.neHost.testOk')}`,
|
||||
duration: 2,
|
||||
});
|
||||
} else {
|
||||
message.error({
|
||||
content: `${row.addr}:${row.port} ${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**测试主机连接-免密直连 */
|
||||
function fnHostAuthorized(row: Record<string, any>) {
|
||||
if (modalState.confirmLoading) return;
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.neHost.authRSATip'),
|
||||
onOk: () => {
|
||||
modalState.confirmLoading = true;
|
||||
neHostAuthorizedRSA(row).then(res => {
|
||||
modalState.confirmLoading = false;
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
} else {
|
||||
message.error(t('common.operateErr'), 3);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**新增框或修改框是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**表单数据 */
|
||||
from: Record<string, any>;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByEdit: false,
|
||||
title: '网元',
|
||||
from: {
|
||||
id: undefined,
|
||||
neId: '001',
|
||||
neType: 'AMF',
|
||||
neName: '',
|
||||
ip: '',
|
||||
port: 33030,
|
||||
pvFlag: 'PNF',
|
||||
rmUid: '4400HXAMF001',
|
||||
neAddress: '',
|
||||
dn: '',
|
||||
vendorName: '',
|
||||
province: '',
|
||||
remark: '',
|
||||
// 主机
|
||||
hosts: [
|
||||
{
|
||||
hostId: undefined,
|
||||
hostType: 'ssh',
|
||||
groupId: '1',
|
||||
title: 'SSH_NE_22',
|
||||
addr: '',
|
||||
port: 22,
|
||||
user: 'omcuser',
|
||||
authMode: '2',
|
||||
password: '',
|
||||
privateKey: '',
|
||||
passPhrase: '',
|
||||
remark: '',
|
||||
},
|
||||
{
|
||||
hostId: undefined,
|
||||
hostType: 'telnet',
|
||||
groupId: '1',
|
||||
title: 'Telnet_NE_4100',
|
||||
addr: '',
|
||||
port: 4100,
|
||||
user: 'admin',
|
||||
authMode: '0',
|
||||
password: 'admin',
|
||||
remark: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
neType: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.common.neTypePlease'),
|
||||
},
|
||||
],
|
||||
neId: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.common.neIdPlease'),
|
||||
},
|
||||
],
|
||||
rmUid: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.common.rmUidPlease'),
|
||||
},
|
||||
],
|
||||
ip: [
|
||||
{
|
||||
required: true,
|
||||
validator: modalStateFromEqualIPV4AndIPV6,
|
||||
},
|
||||
],
|
||||
neName: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.common.neNamePlease'),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**表单验证IP地址是否有效 */
|
||||
function modalStateFromEqualIPV4AndIPV6(
|
||||
rule: Record<string, any>,
|
||||
value: string,
|
||||
callback: (error?: string) => void
|
||||
) {
|
||||
if (!value) {
|
||||
return Promise.reject(t('views.ne.common.ipAddrPlease'));
|
||||
}
|
||||
|
||||
if (value.indexOf('.') === -1 && value.indexOf(':') === -1) {
|
||||
return Promise.reject(t('valid.ipPlease'));
|
||||
}
|
||||
if (value.indexOf('.') !== -1 && !regExpIPv4.test(value)) {
|
||||
return Promise.reject(t('valid.ipv4Reg'));
|
||||
}
|
||||
if (value.indexOf(':') !== -1 && !regExpIPv6.test(value)) {
|
||||
return Promise.reject(t('valid.ipv6Reg'));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出显示为 新增或者修改
|
||||
* @param editId 网元id, 不传为新增
|
||||
*/
|
||||
function fnModalVisibleByEdit(editId: string) {
|
||||
if (!editId) {
|
||||
modalStateFrom.resetFields();
|
||||
modalState.title = t('views.ne.neInfo.addTitle');
|
||||
modalState.openByEdit = true;
|
||||
} else {
|
||||
if (modalState.confirmLoading) return;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
modalState.confirmLoading = true;
|
||||
getNeInfo(editId).then(res => {
|
||||
modalState.confirmLoading = false;
|
||||
hide();
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
Object.assign(modalState.from, res.data);
|
||||
modalState.title = t('views.ne.neInfo.editTitle');
|
||||
modalState.openByEdit = true;
|
||||
} else {
|
||||
message.error(t('common.getInfoFail'), 2);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalOk() {
|
||||
modalStateFrom
|
||||
.validate()
|
||||
.then(e => {
|
||||
modalState.confirmLoading = true;
|
||||
const from = toRaw(modalState.from);
|
||||
const result = from.id ? updateNeInfo(from) : addNeInfo(from);
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
result
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
// 返回无引用信息
|
||||
emit('ok', JSON.parse(JSON.stringify(from)));
|
||||
fnModalCancel();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.confirmLoading = false;
|
||||
modalStateFrom.resetFields();
|
||||
emit('cancel');
|
||||
emit('update:open', false);
|
||||
}
|
||||
|
||||
/**表单修改网元类型 */
|
||||
function fnNeTypeChange(v: any) {
|
||||
// 网元默认只含22和4100
|
||||
if (modalState.from.hosts.length === 3) {
|
||||
modalState.from.hosts.pop();
|
||||
}
|
||||
const hostsLen = modalState.from.hosts.length;
|
||||
// UPF标准版本可支持5002
|
||||
if (hostsLen === 2 && v === 'UPF') {
|
||||
modalState.from.hosts.push({
|
||||
hostId: undefined,
|
||||
hostType: 'telnet',
|
||||
groupId: '1',
|
||||
title: 'Telnet_NE_5002',
|
||||
addr: modalState.from.ip,
|
||||
port: 5002,
|
||||
user: 'admin',
|
||||
authMode: '0',
|
||||
password: 'admin',
|
||||
remark: '',
|
||||
});
|
||||
}
|
||||
// UDM可支持6379
|
||||
if (hostsLen === 2 && v === 'UDM') {
|
||||
modalState.from.hosts.push({
|
||||
hostId: undefined,
|
||||
hostType: 'redis',
|
||||
groupId: '1',
|
||||
title: 'REDIS_NE_6379',
|
||||
addr: modalState.from.ip,
|
||||
port: 6379,
|
||||
user: 'udmdb',
|
||||
authMode: '0',
|
||||
password: 'helloearth',
|
||||
dbName: '0',
|
||||
remark: '',
|
||||
});
|
||||
}
|
||||
|
||||
modalState.from.rmUid = `4400HX${v}${modalState.from.neId}`; // 4400HX1AMF001
|
||||
}
|
||||
|
||||
/**表单修改网元neId */
|
||||
function fnNeIdChange(e: any) {
|
||||
const v = e.target.value;
|
||||
if (v.length < 1) return;
|
||||
modalState.from.rmUid = `4400HX${modalState.from.neType}${v}`; // 4400HX1AMF001
|
||||
}
|
||||
|
||||
/**表单修改网元IP */
|
||||
function fnNeIPChange(e: any) {
|
||||
const v = e.target.value;
|
||||
if (v.length < 7) return;
|
||||
for (const host of modalState.from.hosts) {
|
||||
host.addr = v;
|
||||
}
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
if (val) fnModalVisibleByEdit(props.editId);
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([
|
||||
getDict('ne_host_type'),
|
||||
getDict('ne_host_groupId'),
|
||||
getDict('ne_host_authMode'),
|
||||
]).then(resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
dict.neHostType = resArr[0].value;
|
||||
}
|
||||
if (resArr[1].status === 'fulfilled') {
|
||||
dict.neHostGroupId = resArr[1].value;
|
||||
}
|
||||
if (resArr[2].status === 'fulfilled') {
|
||||
dict.neHostAuthMode = resArr[2].value;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:width="800"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.neType')"
|
||||
name="neType"
|
||||
v-bind="modalStateFrom.validateInfos.neType"
|
||||
>
|
||||
<a-auto-complete
|
||||
v-model:value="modalState.from.neType"
|
||||
:options="NE_TYPE_LIST.map(v => ({ value: v }))"
|
||||
@change="fnNeTypeChange"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="32"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.ne.common.neTypeTip') }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-auto-complete>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.pvflag')"
|
||||
name="pvFlag"
|
||||
v-bind="modalStateFrom.validateInfos.pvFlag"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.pvFlag"
|
||||
default-value="PNF"
|
||||
>
|
||||
<a-select-opt-group :label="t('views.ne.neInfo.pnf')">
|
||||
<a-select-option value="PNF">PNF</a-select-option>
|
||||
</a-select-opt-group>
|
||||
<a-select-opt-group :label="t('views.ne.neInfo.vnf')">
|
||||
<a-select-option value="VNF">VNF</a-select-option>
|
||||
</a-select-opt-group>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.neId')"
|
||||
name="neId"
|
||||
v-bind="modalStateFrom.validateInfos.neId"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.neId"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="32"
|
||||
@change="fnNeIdChange"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
{{ t('views.ne.common.neIdTip') }}
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.neName')"
|
||||
name="neName"
|
||||
v-bind="modalStateFrom.validateInfos.neName"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.neName"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.ipAddr')"
|
||||
name="ip"
|
||||
v-bind="modalStateFrom.validateInfos.ip"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.ip"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="128"
|
||||
@change="fnNeIPChange"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
<div>
|
||||
{{ t('views.ne.common.ipAddrTip') }}
|
||||
</div>
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.port')"
|
||||
name="port"
|
||||
v-bind="modalStateFrom.validateInfos.port"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.port"
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
:maxlength="5"
|
||||
placeholder="<=65535"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
<div>{{ t('views.ne.common.portTip') }}</div>
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.ne.common.rmUid')"
|
||||
name="rmUid"
|
||||
v-bind="modalStateFrom.validateInfos.rmUid"
|
||||
:label-col="{ span: 3 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.rmUid"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="40"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
<div>
|
||||
{{ t('views.ne.common.rmUidTip') }}
|
||||
</div>
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.neInfo.neAddress')" name="neAddress">
|
||||
<a-input
|
||||
v-model:value="modalState.from.neAddress"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="64"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
<div>{{ t('views.ne.neInfo.neAddressTip') }}</div>
|
||||
</template>
|
||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.neInfo.dn')" name="dn">
|
||||
<a-input
|
||||
v-model:value="modalState.from.dn"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="255"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.vendorName')"
|
||||
name="vendorName"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.vendorName"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.neInfo.province')" name="province">
|
||||
<a-input
|
||||
v-model:value="modalState.from.province"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
:maxlength="32"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item
|
||||
:label="t('common.remark')"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.remark"
|
||||
:auto-size="{ minRows: 1, maxRows: 6 }"
|
||||
:maxlength="450"
|
||||
:show-count="true"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 主机连接配置 -->
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.ne.neInfo.hostConfig') }}
|
||||
</a-divider>
|
||||
<a-collapse class="collapse" ghost>
|
||||
<a-collapse-panel
|
||||
v-for="host in modalState.from.hosts.filter(
|
||||
(s:any) => !(s.hostType === 'telnet' && modalState.from.neType === 'OMC')
|
||||
)"
|
||||
:key="host.title"
|
||||
>
|
||||
<template #header>
|
||||
<span v-if="host.hostType === 'redis'"> DB {{ host.port }} </span>
|
||||
<span v-else>
|
||||
{{ `${host.hostType.toUpperCase()} ${host.port}` }}
|
||||
</span>
|
||||
</template>
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.neHost.addr')">
|
||||
<a-input
|
||||
v-model:value="host.addr"
|
||||
allow-clear
|
||||
:maxlength="128"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neHost.port')"
|
||||
name="neHost.port"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="host.port"
|
||||
:min="10"
|
||||
:max="65535"
|
||||
:step="1"
|
||||
:maxlength="5"
|
||||
style="width: 100%"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item
|
||||
v-if="host.hostType === 'telnet'"
|
||||
:label="t('views.ne.neHost.user')"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="host.user"
|
||||
allow-clear
|
||||
:maxlength="32"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-row v-if="host.hostType === 'ssh'">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.neHost.user')">
|
||||
<a-input
|
||||
v-model:value="host.user"
|
||||
allow-clear
|
||||
:maxlength="32"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.neHost.authMode')">
|
||||
<a-select
|
||||
v-model:value="host.authMode"
|
||||
default-value="0"
|
||||
:options="dict.neHostAuthMode"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item
|
||||
v-if="host.authMode === '0'"
|
||||
:label="t('views.ne.neHost.password')"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-input-password
|
||||
v-model:value="host.password"
|
||||
:maxlength="128"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
<template v-if="host.authMode === '1'">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neHost.privateKey')"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="host.privateKey"
|
||||
:auto-size="{ minRows: 4, maxRows: 6 }"
|
||||
:maxlength="3000"
|
||||
:show-count="true"
|
||||
:placeholder="t('views.ne.neHost.privateKeyPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.ne.neHost.passPhrase')"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-input-password
|
||||
v-model:value="host.passPhrase"
|
||||
:maxlength="128"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<a-form-item
|
||||
v-if="host.hostType === 'mysql'"
|
||||
:label="t('views.ne.neHost.database')"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="host.dbName"
|
||||
allow-clear
|
||||
:maxlength="32"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('common.remark')"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="host.remark"
|
||||
:auto-size="{ minRows: 1, maxRows: 6 }"
|
||||
:maxlength="450"
|
||||
:show-count="true"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 测试 -->
|
||||
<a-form-item
|
||||
:label="t('views.ne.neHost.test')"
|
||||
name="test"
|
||||
:label-col="{ span: 3 }"
|
||||
:label-wrap="true"
|
||||
>
|
||||
<a-button
|
||||
type="primary"
|
||||
shape="round"
|
||||
@click="fnHostTest(host)"
|
||||
:loading="modalState.confirmLoading"
|
||||
>
|
||||
<template #icon><LinkOutlined /></template>
|
||||
</a-button>
|
||||
|
||||
<a-button
|
||||
type="link"
|
||||
@click="fnHostAuthorized(host)"
|
||||
:loading="modalState.confirmLoading"
|
||||
v-if="host.hostType === 'ssh' && host.authMode !== '2'"
|
||||
>
|
||||
{{ t('views.ne.neHost.authRSA') }}
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.collapse :deep(.ant-collapse-item) > .ant-collapse-header {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.collapse-header {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
@@ -1,322 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRaw, watch } from 'vue';
|
||||
import { ProModal } from 'antdv-pro-modal';
|
||||
import { message, Form } from 'ant-design-vue/es';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { getOAMFile, saveOAMFile } from '@/api/ne/neInfo';
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**网元ID */
|
||||
neId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
neType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**新增框或修改框是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**是否同步 */
|
||||
sync: boolean;
|
||||
/**表单数据 */
|
||||
from: Record<string, any>;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByEdit: false,
|
||||
title: 'OAM Configuration',
|
||||
sync: true,
|
||||
from: {
|
||||
omcIP: '',
|
||||
oamEnable: true,
|
||||
oamPort: 33030,
|
||||
snmpEnable: true,
|
||||
snmpPort: 4957,
|
||||
kpiEnable: true,
|
||||
kpiTimer: 60,
|
||||
},
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
kpiTimer: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.ne.neInfo.oam.kpiTimerPlease'),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* 对话框弹出显示为 新增或者修改
|
||||
* @param neType 网元类型
|
||||
* @param neId 网元ID
|
||||
*/
|
||||
function fnModalVisibleByTypeAndId(neType: string, neId: string) {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
getOAMFile(neType, neId)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
const data = res.data;
|
||||
Object.assign(modalState.from, {
|
||||
omcIP: data.oamConfig[data.oamConfig.ipType],
|
||||
oamEnable: data.oamConfig.enable,
|
||||
oamPort: data.oamConfig.port,
|
||||
snmpEnable: data.snmpConfig.enable,
|
||||
snmpPort: data.snmpConfig.port,
|
||||
kpiEnable: data.kpiConfig.enable,
|
||||
kpiTimer: data.kpiConfig.timer,
|
||||
});
|
||||
modalState.title = t('views.ne.neInfo.oam.title');
|
||||
modalState.openByEdit = true;
|
||||
} else {
|
||||
message.error(res.msg, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
modalState.confirmLoading = false;
|
||||
hide();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalOk() {
|
||||
modalStateFrom
|
||||
.validate()
|
||||
.then(e => {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
const from = toRaw(modalState.from);
|
||||
saveOAMFile({
|
||||
neType: props.neType,
|
||||
neId: props.neId,
|
||||
content: from,
|
||||
sync: modalState.sync,
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
emit('ok');
|
||||
fnModalCancel();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.openByEdit = false;
|
||||
modalState.confirmLoading = false;
|
||||
modalStateFrom.resetFields();
|
||||
emit('cancel');
|
||||
emit('update:open', false);
|
||||
}
|
||||
|
||||
/**监听是否显示,初始数据 */
|
||||
watch(
|
||||
() => props.open,
|
||||
val => {
|
||||
if (val) {
|
||||
if (props.neType && props.neId) {
|
||||
fnModalVisibleByTypeAndId(props.neType, props.neId);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProModal
|
||||
:drag="true"
|
||||
:destroyOnClose="true"
|
||||
:body-style="{ maxHeight: '600px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:open="modalState.openByEdit"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 12 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.sync')"
|
||||
name="sync"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-switch
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
v-model:checked="modalState.sync"
|
||||
></a-switch>
|
||||
</a-form-item>
|
||||
|
||||
<a-collapse class="collapse" ghost>
|
||||
<a-collapse-panel header="OAM">
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.oamEnable')"
|
||||
name="oamEnable"
|
||||
>
|
||||
<a-switch
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
v-model:checked="modalState.from.oamEnable"
|
||||
></a-switch>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.oamPort')"
|
||||
name="oamPort"
|
||||
v-bind="modalStateFrom.validateInfos.oamPort"
|
||||
>
|
||||
<a-input-number
|
||||
:min="3000"
|
||||
:max="65535"
|
||||
:step="1"
|
||||
:maxlength="5"
|
||||
v-model:value="modalState.from.oamPort"
|
||||
style="width: 100%"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.omcIP')"
|
||||
name="omcIP"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.omcIP"
|
||||
:maxlength="128"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-collapse-panel>
|
||||
<a-collapse-panel header="SNMP">
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.snmpEnable')"
|
||||
name="snmpEnable"
|
||||
>
|
||||
<a-switch
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
v-model:checked="modalState.from.snmpEnable"
|
||||
></a-switch>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.snmpPort')"
|
||||
name="snmpPort"
|
||||
v-bind="modalStateFrom.validateInfos.snmpPort"
|
||||
>
|
||||
<a-input-number
|
||||
:min="3000"
|
||||
:max="65535"
|
||||
:step="1"
|
||||
:maxlength="5"
|
||||
v-model:value="modalState.from.snmpPort"
|
||||
style="width: 100%"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-collapse-panel>
|
||||
<a-collapse-panel header="KPI">
|
||||
<a-row>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.kpiEnable')"
|
||||
name="kpiEnable"
|
||||
>
|
||||
<a-switch
|
||||
:checked-children="t('common.switch.open')"
|
||||
:un-checked-children="t('common.switch.shut')"
|
||||
v-model:checked="modalState.from.kpiEnable"
|
||||
></a-switch>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.ne.neInfo.oam.kpiTimer')"
|
||||
name="kpiTimer"
|
||||
v-bind="modalStateFrom.validateInfos.kpiTimer"
|
||||
>
|
||||
<a-input-number
|
||||
:min="5"
|
||||
:max="3600"
|
||||
:step="1"
|
||||
:maxlength="4"
|
||||
v-model:value="modalState.from.kpiTimer"
|
||||
style="width: 100%"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</a-form>
|
||||
</ProModal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.collapse :deep(.ant-collapse-item) > .ant-collapse-header {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.collapse-header {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
@@ -1,153 +0,0 @@
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { Modal, message } from 'ant-design-vue/es';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { updateNeConfigReload } from '@/api/configManage/configParam';
|
||||
import { serviceNeAction } from '@/api/ne/neInfo';
|
||||
import useMaskStore from '@/store/modules/mask';
|
||||
|
||||
export default function useNeOptions() {
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const maskStore = useMaskStore();
|
||||
|
||||
/**
|
||||
* 网元启动
|
||||
* @param row {neName,neType,neId}
|
||||
*/
|
||||
function fnNeStart(row: Record<string, any>) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.common.startTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
serviceNeAction({
|
||||
neType: row.neType,
|
||||
neId: row.neId,
|
||||
action: 'start',
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元重启
|
||||
* @param row {neName,neType,neId}
|
||||
*/
|
||||
function fnNeRestart(row: Record<string, any>) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.common.restartTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
serviceNeAction({
|
||||
neType: row.neType,
|
||||
neId: row.neId,
|
||||
action: 'restart',
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// OMC自升级
|
||||
if (row.neType.toUpperCase() === 'OMC') {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
maskStore.handleMaskType('reload');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
message.success(t('common.operateOk'), 3);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元停止
|
||||
* @param row {neName,neType,neId}
|
||||
*/
|
||||
function fnNeStop(row: Record<string, any>) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.common.stopTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
serviceNeAction({
|
||||
neType: row.neType,
|
||||
neId: row.neId,
|
||||
action: 'stop',
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元重新加载
|
||||
* @param row {neName,neType,neId}
|
||||
*/
|
||||
function fnNeReload(row: Record<string, any>) {
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.ne.common.reloadTip'),
|
||||
onOk() {
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
updateNeConfigReload(row.neType, row.neId)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
} else {
|
||||
message.error(`${res.msg}`, 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转网元日志文件页面
|
||||
* @param row {neType,neId}
|
||||
*/
|
||||
function fnNeLogFile(row: Record<string, any>) {
|
||||
router.push({
|
||||
name: 'NeFile_2123',
|
||||
query: {
|
||||
neType: row.neType,
|
||||
neId: row.neId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return { fnNeStart, fnNeRestart, fnNeStop, fnNeReload, fnNeLogFile };
|
||||
}
|
||||
@@ -1,790 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, toRaw, defineAsyncComponent, ref } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { message, Modal } from 'ant-design-vue/es';
|
||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
|
||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { listNeInfo, delNeInfo, stateNeInfo } from '@/api/ne/neInfo';
|
||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||
import { hasRoles } from '@/plugins/auth-user';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import useNeOptions from './hooks/useNeOptions';
|
||||
const { getDict } = useDictStore();
|
||||
const { t } = useI18n();
|
||||
const { fnNeStart, fnNeRestart, fnNeStop, fnNeReload, fnNeLogFile } =
|
||||
useNeOptions();
|
||||
// 异步加载组件
|
||||
const EditModal = defineAsyncComponent(
|
||||
() => import('./components/EditModal.vue')
|
||||
);
|
||||
const OAMModal = defineAsyncComponent(
|
||||
() => import('./components/OAMModal.vue')
|
||||
);
|
||||
// 配置备份文件导入
|
||||
const BackConfModal = defineAsyncComponent(
|
||||
() => import('./components/BackConfModal.vue')
|
||||
);
|
||||
const backConf = ref(); // 引用句柄,取导出函数
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
/**网元信息状态 */
|
||||
neInfoStatus: DictType[];
|
||||
} = reactive({
|
||||
neInfoStatus: [],
|
||||
});
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: '',
|
||||
/**带状态信息 */
|
||||
bandStatus: true,
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
queryParams = Object.assign(queryParams, {
|
||||
neType: '',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: Record<string, any>[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: false,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('views.ne.common.neType'),
|
||||
dataIndex: 'neType',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.neId'),
|
||||
dataIndex: 'neId',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.rmUid'),
|
||||
dataIndex: 'rmUid',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.neName'),
|
||||
dataIndex: 'neName',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.ipAddr'),
|
||||
dataIndex: 'ip',
|
||||
align: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.common.port'),
|
||||
dataIndex: 'port',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.ne.neInfo.state'),
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
align: 'left',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
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 = {
|
||||
/**配置备份框是否显示 */
|
||||
openByBackConf: boolean;
|
||||
/**OAM文件配置框是否显示 */
|
||||
openByOAM: boolean;
|
||||
/**新增框或修改框是否显示 */
|
||||
openByEdit: boolean;
|
||||
/**新增框或修改框ID */
|
||||
editId: string;
|
||||
/**OAM框网元类型ID */
|
||||
neId: string;
|
||||
neType: string;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
openByBackConf: false,
|
||||
openByOAM: false,
|
||||
openByEdit: false,
|
||||
editId: '',
|
||||
neId: '',
|
||||
neType: '',
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* 对话框弹出显示为 新增或者修改
|
||||
* @param noticeId 网元id, 不传为新增
|
||||
*/
|
||||
function fnModalVisibleByEdit(row?: Record<string, any>) {
|
||||
if (!row) {
|
||||
modalState.editId = '';
|
||||
} else {
|
||||
modalState.editId = row.id;
|
||||
}
|
||||
modalState.openByEdit = !modalState.openByEdit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出确认执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalEditOk(from: Record<string, any>) {
|
||||
// 新增时刷新列表
|
||||
if (!from.id) {
|
||||
fnGetList();
|
||||
return;
|
||||
}
|
||||
// 编辑时局部更新信息
|
||||
stateNeInfo(from.neType, from.neId)
|
||||
.then(res => {
|
||||
// 找到编辑更新的网元
|
||||
const item = tableState.data.find(s => s.id === from.id);
|
||||
if (item && res.code === RESULT_CODE_SUCCESS) {
|
||||
item.neType = from.neType;
|
||||
item.neId = from.neId;
|
||||
item.rmUid = from.rmUid;
|
||||
item.neName = from.neName;
|
||||
item.ip = from.ip;
|
||||
item.port = from.port;
|
||||
if (item.status !== '2') {
|
||||
item.status = res.data.online ? '1' : '0';
|
||||
}
|
||||
Object.assign(item.serverState, res.data);
|
||||
const resouresUsage = parseResouresUsage(item.serverState);
|
||||
Reflect.set(item, 'resoures', resouresUsage);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
useNeInfoStore().fnRefreshNelist();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalEditCancel() {
|
||||
modalState.editId = '';
|
||||
modalState.openByEdit = false;
|
||||
modalState.openByOAM = false;
|
||||
modalState.openByBackConf = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录删除
|
||||
* @param id 编号
|
||||
*/
|
||||
function fnRecordDelete(id: string) {
|
||||
if (!id || modalState.confirmLoading) return;
|
||||
let msg = t('views.ne.neInfo.delTip');
|
||||
if (id === '0') {
|
||||
msg = `${msg} ...${tableState.selectedRowKeys.length}`;
|
||||
id = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: msg,
|
||||
onOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
delNeInfo(id)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success(t('common.operateOk'), 3);
|
||||
// 过滤掉删除的id
|
||||
tableState.data = tableState.data.filter(item => {
|
||||
if (id.indexOf(',') > -1) {
|
||||
return !tableState.selectedRowKeys.includes(item.id);
|
||||
} else {
|
||||
return item.id !== id;
|
||||
}
|
||||
});
|
||||
// 刷新缓存
|
||||
useNeInfoStore().fnRefreshNelist();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录多项选择
|
||||
*/
|
||||
function fnRecordMore(type: string | number, row: Record<string, any>) {
|
||||
switch (type) {
|
||||
case 'delete':
|
||||
fnRecordDelete(row.id);
|
||||
break;
|
||||
case 'start':
|
||||
fnNeStart(row);
|
||||
break;
|
||||
case 'restart':
|
||||
fnNeRestart(row);
|
||||
break;
|
||||
case 'stop':
|
||||
fnNeStop(row);
|
||||
break;
|
||||
case 'reload':
|
||||
fnNeReload(row);
|
||||
break;
|
||||
case 'log':
|
||||
fnNeLogFile(row);
|
||||
break;
|
||||
case 'oam':
|
||||
modalState.neId = row.neId;
|
||||
modalState.neType = row.neType;
|
||||
modalState.openByOAM = !modalState.openByOAM;
|
||||
break;
|
||||
case 'backConfExport':
|
||||
backConf.value.exportConf(row.neType, row.neId);
|
||||
break;
|
||||
case 'backConfImport':
|
||||
modalState.neId = row.neId;
|
||||
modalState.neType = row.neType;
|
||||
modalState.openByBackConf = !modalState.openByBackConf;
|
||||
break;
|
||||
default:
|
||||
console.warn(type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
listNeInfo(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;
|
||||
// 遍历处理资源情况数值
|
||||
tableState.data = res.rows.map(item => {
|
||||
let resouresUsage = {
|
||||
sysDiskUsage: 0,
|
||||
sysMemUsage: 0,
|
||||
sysCpuUsage: 0,
|
||||
nfCpuUsage: 0,
|
||||
};
|
||||
const neState = item.serverState;
|
||||
if (neState) {
|
||||
resouresUsage = parseResouresUsage(neState);
|
||||
} else {
|
||||
item.serverState = { online: false };
|
||||
}
|
||||
Reflect.set(item, 'resoures', resouresUsage);
|
||||
return item;
|
||||
});
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**解析网元状态携带的资源利用率 */
|
||||
function parseResouresUsage(neState: Record<string, any>) {
|
||||
let sysCpuUsage = 0;
|
||||
let nfCpuUsage = 0;
|
||||
if (neState.cpu) {
|
||||
nfCpuUsage = neState.cpu.nfCpuUsage;
|
||||
const nfCpu = +(nfCpuUsage / 100);
|
||||
nfCpuUsage = +nfCpu.toFixed(2);
|
||||
if (nfCpuUsage > 100) {
|
||||
nfCpuUsage = 100;
|
||||
}
|
||||
|
||||
sysCpuUsage = neState.cpu.sysCpuUsage;
|
||||
const sysCpu = +(sysCpuUsage / 100);
|
||||
sysCpuUsage = +sysCpu.toFixed(2);
|
||||
if (sysCpuUsage > 100) {
|
||||
sysCpuUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysMemUsage = 0;
|
||||
if (neState.mem) {
|
||||
const men = neState.mem.sysMemUsage;
|
||||
sysMemUsage = +(men / 100).toFixed(2);
|
||||
if (sysMemUsage > 100) {
|
||||
sysMemUsage = 100;
|
||||
}
|
||||
}
|
||||
|
||||
let sysDiskUsage = 0;
|
||||
if (neState.disk && Array.isArray(neState.disk.partitionInfo)) {
|
||||
let disks: any[] = neState.disk.partitionInfo;
|
||||
disks = disks.sort((a, b) => +b.used - +a.used);
|
||||
if (disks.length > 0) {
|
||||
const { total, used } = disks[0];
|
||||
sysDiskUsage = +((used / total) * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
sysDiskUsage,
|
||||
sysMemUsage,
|
||||
sysCpuUsage,
|
||||
nfCpuUsage,
|
||||
};
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始字典数据
|
||||
Promise.allSettled([getDict('ne_info_status')]).then(resArr => {
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
dict.neInfoStatus = resArr[0].value;
|
||||
}
|
||||
});
|
||||
|
||||
// 刷新缓存的网元信息
|
||||
useNeInfoStore()
|
||||
.fnRefreshNelist()
|
||||
.finally(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.ne.common.neType')" name="neType ">
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="NE_TYPE_LIST.map(v => ({ value: v }))"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</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" v-roles:has="['admin']">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
{{ t('common.addText') }}
|
||||
</a-button>
|
||||
<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-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 }"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
columnWidth: '48px',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'status'">
|
||||
<DictTag :options="dict.neInfoStatus" :value="record.status" />
|
||||
</template>
|
||||
<template v-if="column.key === 'id'">
|
||||
<a-space :size="8" align="center">
|
||||
<span v-roles:has="['admin']">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.editText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record)"
|
||||
>
|
||||
<template #icon><FormOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span v-roles:has="['admin', 'teacher']">
|
||||
<a-tooltip>
|
||||
<template #title>
|
||||
{{ t('views.ne.common.restart') }}
|
||||
</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordMore('restart', record)"
|
||||
>
|
||||
<template #icon><UndoOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
|
||||
<a-tooltip placement="left">
|
||||
<template #title>{{ t('common.moreText') }}</template>
|
||||
<a-dropdown placement="bottomRight" trigger="click">
|
||||
<a-button type="link">
|
||||
<template #icon><EllipsisOutlined /> </template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu @click="({ key }:any) => fnRecordMore(key, record)">
|
||||
<a-menu-item key="log">
|
||||
<FileTextOutlined />
|
||||
{{ t('views.ne.common.log') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="start" v-if="hasRoles(['admin'])">
|
||||
<ThunderboltOutlined />
|
||||
{{ t('views.ne.common.start') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="stop" v-if="hasRoles(['admin'])">
|
||||
<CloseSquareOutlined />
|
||||
{{ t('views.ne.common.stop') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="reload"
|
||||
v-if="
|
||||
!['OMC', 'PCF', 'IMS', 'MME'].includes(
|
||||
record.neType
|
||||
) && hasRoles(['admin'])
|
||||
"
|
||||
>
|
||||
<SyncOutlined />
|
||||
{{ t('views.ne.common.reload') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="delete" v-if="hasRoles(['admin'])">
|
||||
<DeleteOutlined />
|
||||
{{ t('common.deleteText') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="oam" v-if="hasRoles(['admin'])">
|
||||
<FileTextOutlined />
|
||||
{{ t('views.ne.common.oam') }}
|
||||
</a-menu-item>
|
||||
<!-- 配置备份 -->
|
||||
<a-menu-item key="backConfExport">
|
||||
<ExportOutlined />
|
||||
{{ t('views.ne.neInfo.backConf.export') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="backConfImport">
|
||||
<ImportOutlined />
|
||||
{{ t('views.ne.neInfo.backConf.import') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #expandedRowRender="{ record }">
|
||||
<a-row :gutter="16">
|
||||
<a-col :offset="2" :lg="8" :md="8" :xs="8">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.ne.neInfo.info') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.serviceState') }}:</span>
|
||||
<a-tag
|
||||
:color="record.serverState.online ? 'processing' : 'error'"
|
||||
>
|
||||
{{
|
||||
record.serverState.online
|
||||
? t('views.ne.common.normalcy')
|
||||
: t('views.ne.common.exceptions')
|
||||
}}
|
||||
</a-tag>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neVersion.version') }}:</span>
|
||||
<span>{{ record.serverState.version }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.serialNum') }}:</span>
|
||||
<span>{{ record.serverState.sn }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.common.expiryDate') }}:</span>
|
||||
<span>{{ record.serverState.expire }}</span>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :offset="2" :lg="8" :md="8" :xs="8">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.ne.neInfo.resourceInfo') }}
|
||||
</a-divider>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.neCpu') }}:</span>
|
||||
<a-progress
|
||||
status="normal"
|
||||
:stroke-color="
|
||||
record.resoures.nfCpuUsage < 30
|
||||
? '#52c41a'
|
||||
: record.resoures.nfCpuUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
"
|
||||
:percent="record.resoures.nfCpuUsage"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.sysCpu') }}:</span>
|
||||
<a-progress
|
||||
status="normal"
|
||||
:stroke-color="
|
||||
record.resoures.sysCpuUsage < 30
|
||||
? '#52c41a'
|
||||
: record.resoures.sysCpuUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
"
|
||||
:percent="record.resoures.sysCpuUsage"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.sysMem') }}:</span>
|
||||
<a-progress
|
||||
status="normal"
|
||||
:stroke-color="
|
||||
record.resoures.sysMemUsage < 30
|
||||
? '#52c41a'
|
||||
: record.resoures.sysMemUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
"
|
||||
:percent="record.resoures.sysMemUsage"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{ t('views.ne.neInfo.sysDisk') }}:</span>
|
||||
<a-progress
|
||||
status="normal"
|
||||
:stroke-color="
|
||||
record.resoures.sysDiskUsage < 30
|
||||
? '#52c41a'
|
||||
: record.resoures.sysDiskUsage > 70
|
||||
? '#ff4d4f'
|
||||
: '#1890ff'
|
||||
"
|
||||
:percent="record.resoures.sysDiskUsage"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<EditModal
|
||||
v-model:open="modalState.openByEdit"
|
||||
:edit-id="modalState.editId"
|
||||
@ok="fnModalEditOk"
|
||||
@cancel="fnModalEditCancel"
|
||||
></EditModal>
|
||||
|
||||
<!-- OAM编辑框 -->
|
||||
<OAMModal
|
||||
v-model:open="modalState.openByOAM"
|
||||
:ne-id="modalState.neId"
|
||||
:ne-type="modalState.neType"
|
||||
@cancel="fnModalEditCancel"
|
||||
></OAMModal>
|
||||
|
||||
<!-- 配置文件备份框 -->
|
||||
<BackConfModal
|
||||
ref="backConf"
|
||||
v-model:open="modalState.openByBackConf"
|
||||
:ne-id="modalState.neId"
|
||||
:ne-type="modalState.neType"
|
||||
@cancel="fnModalEditCancel"
|
||||
></BackConfModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
BIN
public/background/dark.jpg
Normal file
|
After Width: | Height: | Size: 216 KiB |
BIN
public/background/light.jpg
Normal file
|
After Width: | Height: | Size: 216 KiB |
@@ -10,12 +10,19 @@
|
||||
*
|
||||
*/
|
||||
(function () {
|
||||
// host = ip:port
|
||||
// const host = '192.168.8.100:33030';
|
||||
const host = `${window.location.hostname}:33030`;
|
||||
// baseUrl = protocol://ip:port
|
||||
// baseUrl = 'http://192.168.8.100:33030';
|
||||
const protocol = window.location.protocol
|
||||
let wsprotocol = "ws:"
|
||||
const hostname = window.location.hostname
|
||||
let host = `${hostname}:33030`;
|
||||
if (protocol === 'https:') {
|
||||
host = `${hostname}:33443`;
|
||||
wsprotocol = "wss:"
|
||||
}
|
||||
|
||||
// Service Address
|
||||
sessionStorage.setItem('baseUrl', `http://${host}`);
|
||||
sessionStorage.setItem('baseUrl', `${protocol}//${host}`);
|
||||
// websocket Address
|
||||
sessionStorage.setItem('wsUrl', `ws://${host}`);
|
||||
sessionStorage.setItem('wsUrl', `${wsprotocol}//${host}`);
|
||||
})();
|
||||
|
||||
BIN
public/nbStateImput/en.xlsx
Normal file
BIN
public/nbStateImput/zh.xlsx
Normal file
BIN
public/neDataImput/import_amf_imeiWhitelist_template.xlsx
Normal file
BIN
public/neDataImput/import_amf_whitelist_template.xlsx
Normal file
BIN
public/neDataImput/import_mme_imeiWhitelist_template.xlsx
Normal file
1
public/neDataImput/pcf_template.txt
Normal file
@@ -0,0 +1 @@
|
||||
001012082101039,1234,internet|ims_sig,internet|ims_sig,321321,255,321312,32131,32131
|
||||
2
public/neDataImput/udm_auth_template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
001011100001157,1234567890ABCDEF1234567890ABCDEF,0,8000,11111111111111111111111111111111
|
||||
001011100001158,1234567890ABCDEF1234567890ABCDEF,0,8000,11111111111111111111111111111111
|
||||
2
public/neDataImput/udm_sub_template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
001011100001157,62357000583,def_ambr,def_nssai,def_arfb,def_sar,0,3,def_snssai,1-000001&internet&ims,1,64,24,65,def_eps,1,010200000000,-
|
||||
001011100001158,62357000585,def_ambr,def_nssai,def_arfb,def_sar,0,3,def_snssai,1-000001&internet&ims,1,64,24,65,def_eps,1,010200000000,-
|
||||
2
public/neDataImput/udm_voip_template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
62357000580,123456
|
||||
62357000581,123456
|
||||
2
public/neDataImput/udm_volte_template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
001012082101039,62357000580,1,ims.mnc001.mcc001.3gppnetwork.org
|
||||
62357000581,62357000581,0,ims.mnc001.mcc001.3gppnetwork.org
|
||||
28
public/svg/base4G.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<svg width="1024" height="1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
|
||||
|
||||
<g>
|
||||
<title>background</title>
|
||||
<rect fill="none" id="canvas_background" height="1026" width="1026" y="-1" x="-1"/>
|
||||
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
|
||||
<rect fill="url(#gridpattern)" stroke-width="0" y="1" x="1" height="768" width="1024"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>Layer 1</title>
|
||||
<g stroke="null" id="svg_15">
|
||||
<path stroke="null" id="svg_4" fill="#B5D6FB" d="m512.094844,961.632039c-1.327621,0 -2.560412,-0.405439 -3.793202,-1.114958l-405.588164,-251.575028c-2.275921,-1.419037 -3.698372,-4.054392 -3.698372,-6.892467l0,-90.007504c0,-2.838074 1.422451,-5.473429 3.698372,-6.892467l405.588164,-255.426701c1.137961,-0.709519 2.465582,-1.114958 3.793202,-1.114958s2.655242,0.405439 3.793202,1.114958l405.493334,255.426701c2.275921,1.419037 3.698372,4.054392 3.698372,6.892467l0,90.007504c0,2.838074 -1.422451,5.473429 -3.698372,6.892467l-405.588164,251.575028c-1.137961,0.709519 -2.465582,1.114958 -3.698372,1.114958z"/>
|
||||
<path stroke="null" id="svg_5" fill="#0276F7" d="m512.094844,356.615382l405.398504,255.426701l0,90.007504l-66.096551,40.94936l-339.301952,210.625668l-339.491613,-210.625668l-66.096551,-40.94936l0,-90.007504l405.588164,-255.426701m0,-16.014849c-2.655242,0 -5.215653,0.709519 -7.586405,2.229916l-405.588164,255.426701c-4.551843,2.838074 -7.396745,8.108784 -7.396745,13.784933l0,90.007504c0,5.676149 2.844902,10.946859 7.491575,13.886293l66.096551,41.05072l339.491613,210.625668c2.275921,1.419037 4.931163,2.128556 7.491575,2.128556s5.215653,-0.709519 7.491575,-2.128556l339.301952,-210.625668l66.096551,-40.94936c4.646673,-2.838074 7.491575,-8.108784 7.491575,-13.886293l0,-90.007504c0,-5.676149 -2.844902,-10.946859 -7.396745,-13.784933l-405.398504,-255.426701c-2.370751,-1.520397 -5.025993,-2.331275 -7.586405,-2.331275z"/>
|
||||
<path stroke="null" id="svg_6" fill="#FFFFFF" d="m106.50668,612.042083l405.493334,253.298145l405.493334,-253.298145l-405.398504,-255.426701l-405.588164,255.426701z"/>
|
||||
<path stroke="null" id="svg_7" fill="#D4E4FC" d="m501.473877,64.192353l-254.9032,498.487506l263.343075,161.162085l266.662127,-162.074323l-275.102002,-497.575268z"/>
|
||||
<path stroke="null" id="svg_8" fill="#0276F7" d="m229.975417,602.311542c-1.232791,0 -2.465582,-0.304079 -3.698372,-1.013598c-3.603542,-2.128556 -4.931163,-6.993826 -2.844902,-10.845499l279.653845,-532.13896c1.327621,-2.533995 3.793202,-4.054392 6.543274,-4.054392c2.655242,0 5.120823,1.520397 6.543274,4.054392l284.395348,532.13896c2.086261,3.851672 0.75864,8.716943 -2.750072,10.946859c-3.603542,2.128556 -8.155385,0.810878 -10.241646,-2.939434l-277.852074,-519.874424l-273.205401,519.671704c-1.422451,2.635355 -3.982862,4.054392 -6.543274,4.054392z"/>
|
||||
<path stroke="null" id="svg_9" fill="#0276F7" d="m509.913752,755.567562c-4.172523,0 -7.491575,-3.547593 -7.491575,-8.007424l0,-666.744777c0,-4.459831 3.319052,-8.007424 7.491575,-8.007424s7.491575,3.547593 7.491575,8.007424l0,666.846137c0,4.358471 -3.413882,7.906065 -7.491575,7.906065z"/>
|
||||
<path stroke="null" id="svg_10" fill="#0276F7" d="m509.913752,731.849369c-1.327621,0 -2.560412,-0.405439 -3.698372,-1.013598l-263.343075,-161.162085c-3.603542,-2.229916 -4.836333,-7.095186 -2.750072,-10.946859c2.086261,-3.851672 6.638104,-5.16935 10.241646,-2.939434l259.549873,158.83081l262.963755,-159.844408c3.603542,-2.229916 8.155385,-0.810878 10.241646,3.040794c2.086261,3.851672 0.75864,8.716943 -2.844902,10.946859l-266.662127,162.074323c-1.137961,0.709519 -2.465582,1.013598 -3.698372,1.013598z"/>
|
||||
<path stroke="null" id="svg_11" fill="#0276F7" d="m509.913752,579.708306c-1.327621,0 -2.560412,-0.405439 -3.793202,-1.114958l-201.988026,-125.686154c-3.603542,-2.229916 -4.741503,-7.095186 -2.750072,-10.946859c2.086261,-3.851672 6.638104,-5.16935 10.241646,-2.838074l198.289654,123.354879l201.798366,-122.138561c3.603542,-2.229916 8.155385,-0.810878 10.241646,3.040794c2.086261,3.851672 0.75864,8.716943 -2.844902,10.845499l-205.496739,124.469837c-1.137961,0.709519 -2.465582,1.013598 -3.698372,1.013598zm-2.465582,-157.513132c-1.232791,0 -2.370751,-0.304079 -3.508712,-0.912238l-140.917468,-79.668804c-3.698372,-2.128556 -5.025993,-6.892467 -3.129392,-10.845499c1.896601,-3.953032 6.448444,-5.37207 10.146816,-3.344873l137.503586,77.742968l143.00373,-79.871524c3.698372,-2.027196 8.155385,-0.506799 10.146816,3.344873c1.896601,3.953032 0.47415,8.716943 -3.129392,10.845499l-146.512442,81.79736c-1.232791,0.608159 -2.370751,0.912238 -3.603542,0.912238zm2.465582,-148.49211c-1.232791,0 -2.465582,-0.304079 -3.508712,-0.912238l-82.312492,-47.436387c-3.603542,-2.128556 -5.025993,-6.993826 -3.034562,-10.845499c1.991431,-3.953032 6.543274,-5.27071 10.146816,-3.243514l78.708949,45.409191l78.329629,-47.537747c3.603542,-2.229916 8.155385,-0.810878 10.241646,3.040794c2.086261,3.851672 0.75864,8.716943 -2.844902,10.946859l-81.933171,49.666303c-1.232791,0.608159 -2.560412,0.912238 -3.793202,0.912238z"/>
|
||||
<path stroke="null" id="svg_12" fill="#0276F7" d="m509.913752,579.708306l-0.28449,0l-263.248245,-9.021022c-4.172523,-0.10136 -7.396745,-3.851672 -7.207085,-8.210144c0.09483,-4.459831 4.077693,-7.703345 7.681235,-7.703345l263.343075,9.021022c4.172523,0.10136 7.396745,3.851672 7.207085,8.210144c-0.18966,4.257112 -3.508712,7.703345 -7.491575,7.703345zm0,152.141063c-1.612111,0 -3.224222,-0.608159 -4.646673,-1.723117c-3.224222,-2.736715 -3.793202,-7.804705 -1.232791,-11.250938l205.496739,-276.610899c2.560412,-3.446233 7.301915,-4.054392 10.526137,-1.317677c3.224222,2.736715 3.793202,7.804705 1.232791,11.250938l-205.496739,276.610899c-1.517281,2.027196 -3.698372,3.040794 -5.879464,3.040794z"/>
|
||||
<path stroke="null" id="svg_13" fill="#0276F7" d="m509.913752,579.708306c-1.422451,0 -2.750072,-0.405439 -4.077693,-1.216318c-3.508712,-2.432635 -4.457013,-7.297906 -2.275921,-11.048218l144.14169,-239.310492c2.275921,-3.750313 6.922594,-4.763911 10.336476,-2.432635c3.508712,2.432635 4.457013,7.297906 2.275921,11.048218l-144.14169,239.310492c-1.422451,2.331275 -3.793202,3.648953 -6.258784,3.648953zm-2.465582,-157.513132c-1.043131,0 -2.086261,-0.20272 -3.129392,-0.709519c-3.793202,-1.824476 -5.405313,-6.588387 -3.698372,-10.642779l84.398753,-198.158413c1.706941,-4.054392 6.069124,-5.777509 9.957156,-3.953032c3.793202,1.824476 5.405313,6.588387 3.698372,10.642779l-84.303923,198.158413c-1.327621,2.939434 -4.077693,4.662551 -6.922594,4.662551z"/>
|
||||
<path stroke="null" id="svg_14" fill="#0276F7" d="m591.846924,375.062866c-2.750072,0 -5.405313,-1.621757 -6.732934,-4.459831c-1.801771,-3.953032 -0.28449,-8.716943 3.413882,-10.642779l129.253371,-67.302908l-365.759539,-178.089172l20.862613,208.091673l133.994874,-64.262114c3.698372,-1.824476 8.155385,0 9.862326,4.054392c1.706941,4.054392 0,8.716943 -3.793202,10.541419l-143.38305,68.823305c-2.181091,1.013598 -4.646673,0.912238 -6.827764,-0.405439c-2.086261,-1.317677 -3.413882,-3.547593 -3.698372,-6.081588l-23.328195,-233.026185c-0.28449,-2.838074 0.853471,-5.676149 3.034562,-7.297906c2.181091,-1.621757 5.025993,-2.027196 7.491575,-0.810878l392.217126,190.961867c2.655242,1.317677 4.362183,4.054392 4.362183,7.196546c0,3.142154 -1.612111,5.980228 -4.172523,7.297906l-143.57271,74.600814c-1.043131,0.608159 -2.181091,0.810878 -3.224222,0.810878zm-283.921198,78.959286c-3.603542,0 -6.827764,-2.838074 -7.396745,-6.791107c-0.56898,-4.358471 2.181091,-8.412864 6.258784,-9.122382l199.617275,-31.826978c4.077693,-0.608159 7.870895,2.331275 8.534705,6.689747c0.56898,4.358471 -2.181091,8.412864 -6.258784,9.122382l-199.617275,31.826978c-0.47415,0.10136 -0.853471,0.10136 -1.137961,0.10136z"/>
|
||||
</g>
|
||||
<text stroke="null" font-style="italic" transform="matrix(6.577099502228161,0,0,7.449448263868419,-1073.2057632249744,-908.8606073938396) " xml:space="preserve" text-anchor="start" font-family="Arvo, sans-serif" font-size="24" id="svg_16" y="177.898525" x="178.621382" stroke-width="0" fill="#B5D6FB">4G</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.9 KiB |
28
public/svg/base5G.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<svg width="1024" height="1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
|
||||
|
||||
<g>
|
||||
<title>background</title>
|
||||
<rect fill="none" id="canvas_background" height="1026" width="1026" y="-1" x="-1"/>
|
||||
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
|
||||
<rect fill="url(#gridpattern)" stroke-width="0" y="1" x="1" height="768" width="1024"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>Layer 1</title>
|
||||
<g stroke="null" id="svg_15">
|
||||
<path stroke="null" id="svg_4" fill="#B5D6FB" d="m512.094844,961.632039c-1.327621,0 -2.560412,-0.405439 -3.793202,-1.114958l-405.588164,-251.575028c-2.275921,-1.419037 -3.698372,-4.054392 -3.698372,-6.892467l0,-90.007504c0,-2.838074 1.422451,-5.473429 3.698372,-6.892467l405.588164,-255.426701c1.137961,-0.709519 2.465582,-1.114958 3.793202,-1.114958s2.655242,0.405439 3.793202,1.114958l405.493334,255.426701c2.275921,1.419037 3.698372,4.054392 3.698372,6.892467l0,90.007504c0,2.838074 -1.422451,5.473429 -3.698372,6.892467l-405.588164,251.575028c-1.137961,0.709519 -2.465582,1.114958 -3.698372,1.114958z"/>
|
||||
<path stroke="null" id="svg_5" fill="#0276F7" d="m512.094844,356.615382l405.398504,255.426701l0,90.007504l-66.096551,40.94936l-339.301952,210.625668l-339.491613,-210.625668l-66.096551,-40.94936l0,-90.007504l405.588164,-255.426701m0,-16.014849c-2.655242,0 -5.215653,0.709519 -7.586405,2.229916l-405.588164,255.426701c-4.551843,2.838074 -7.396745,8.108784 -7.396745,13.784933l0,90.007504c0,5.676149 2.844902,10.946859 7.491575,13.886293l66.096551,41.05072l339.491613,210.625668c2.275921,1.419037 4.931163,2.128556 7.491575,2.128556s5.215653,-0.709519 7.491575,-2.128556l339.301952,-210.625668l66.096551,-40.94936c4.646673,-2.838074 7.491575,-8.108784 7.491575,-13.886293l0,-90.007504c0,-5.676149 -2.844902,-10.946859 -7.396745,-13.784933l-405.398504,-255.426701c-2.370751,-1.520397 -5.025993,-2.331275 -7.586405,-2.331275z"/>
|
||||
<path stroke="null" id="svg_6" fill="#FFFFFF" d="m106.50668,612.042083l405.493334,253.298145l405.493334,-253.298145l-405.398504,-255.426701l-405.588164,255.426701z"/>
|
||||
<path stroke="null" id="svg_7" fill="#D4E4FC" d="m501.473877,64.192353l-254.9032,498.487506l263.343075,161.162085l266.662127,-162.074323l-275.102002,-497.575268z"/>
|
||||
<path stroke="null" id="svg_8" fill="#0276F7" d="m229.975417,602.311542c-1.232791,0 -2.465582,-0.304079 -3.698372,-1.013598c-3.603542,-2.128556 -4.931163,-6.993826 -2.844902,-10.845499l279.653845,-532.13896c1.327621,-2.533995 3.793202,-4.054392 6.543274,-4.054392c2.655242,0 5.120823,1.520397 6.543274,4.054392l284.395348,532.13896c2.086261,3.851672 0.75864,8.716943 -2.750072,10.946859c-3.603542,2.128556 -8.155385,0.810878 -10.241646,-2.939434l-277.852074,-519.874424l-273.205401,519.671704c-1.422451,2.635355 -3.982862,4.054392 -6.543274,4.054392z"/>
|
||||
<path stroke="null" id="svg_9" fill="#0276F7" d="m509.913752,755.567562c-4.172523,0 -7.491575,-3.547593 -7.491575,-8.007424l0,-666.744777c0,-4.459831 3.319052,-8.007424 7.491575,-8.007424s7.491575,3.547593 7.491575,8.007424l0,666.846137c0,4.358471 -3.413882,7.906065 -7.491575,7.906065z"/>
|
||||
<path stroke="null" id="svg_10" fill="#0276F7" d="m509.913752,731.849369c-1.327621,0 -2.560412,-0.405439 -3.698372,-1.013598l-263.343075,-161.162085c-3.603542,-2.229916 -4.836333,-7.095186 -2.750072,-10.946859c2.086261,-3.851672 6.638104,-5.16935 10.241646,-2.939434l259.549873,158.83081l262.963755,-159.844408c3.603542,-2.229916 8.155385,-0.810878 10.241646,3.040794c2.086261,3.851672 0.75864,8.716943 -2.844902,10.946859l-266.662127,162.074323c-1.137961,0.709519 -2.465582,1.013598 -3.698372,1.013598z"/>
|
||||
<path stroke="null" id="svg_11" fill="#0276F7" d="m509.913752,579.708306c-1.327621,0 -2.560412,-0.405439 -3.793202,-1.114958l-201.988026,-125.686154c-3.603542,-2.229916 -4.741503,-7.095186 -2.750072,-10.946859c2.086261,-3.851672 6.638104,-5.16935 10.241646,-2.838074l198.289654,123.354879l201.798366,-122.138561c3.603542,-2.229916 8.155385,-0.810878 10.241646,3.040794c2.086261,3.851672 0.75864,8.716943 -2.844902,10.845499l-205.496739,124.469837c-1.137961,0.709519 -2.465582,1.013598 -3.698372,1.013598zm-2.465582,-157.513132c-1.232791,0 -2.370751,-0.304079 -3.508712,-0.912238l-140.917468,-79.668804c-3.698372,-2.128556 -5.025993,-6.892467 -3.129392,-10.845499c1.896601,-3.953032 6.448444,-5.37207 10.146816,-3.344873l137.503586,77.742968l143.00373,-79.871524c3.698372,-2.027196 8.155385,-0.506799 10.146816,3.344873c1.896601,3.953032 0.47415,8.716943 -3.129392,10.845499l-146.512442,81.79736c-1.232791,0.608159 -2.370751,0.912238 -3.603542,0.912238zm2.465582,-148.49211c-1.232791,0 -2.465582,-0.304079 -3.508712,-0.912238l-82.312492,-47.436387c-3.603542,-2.128556 -5.025993,-6.993826 -3.034562,-10.845499c1.991431,-3.953032 6.543274,-5.27071 10.146816,-3.243514l78.708949,45.409191l78.329629,-47.537747c3.603542,-2.229916 8.155385,-0.810878 10.241646,3.040794c2.086261,3.851672 0.75864,8.716943 -2.844902,10.946859l-81.933171,49.666303c-1.232791,0.608159 -2.560412,0.912238 -3.793202,0.912238z"/>
|
||||
<path stroke="null" id="svg_12" fill="#0276F7" d="m509.913752,579.708306l-0.28449,0l-263.248245,-9.021022c-4.172523,-0.10136 -7.396745,-3.851672 -7.207085,-8.210144c0.09483,-4.459831 4.077693,-7.703345 7.681235,-7.703345l263.343075,9.021022c4.172523,0.10136 7.396745,3.851672 7.207085,8.210144c-0.18966,4.257112 -3.508712,7.703345 -7.491575,7.703345zm0,152.141063c-1.612111,0 -3.224222,-0.608159 -4.646673,-1.723117c-3.224222,-2.736715 -3.793202,-7.804705 -1.232791,-11.250938l205.496739,-276.610899c2.560412,-3.446233 7.301915,-4.054392 10.526137,-1.317677c3.224222,2.736715 3.793202,7.804705 1.232791,11.250938l-205.496739,276.610899c-1.517281,2.027196 -3.698372,3.040794 -5.879464,3.040794z"/>
|
||||
<path stroke="null" id="svg_13" fill="#0276F7" d="m509.913752,579.708306c-1.422451,0 -2.750072,-0.405439 -4.077693,-1.216318c-3.508712,-2.432635 -4.457013,-7.297906 -2.275921,-11.048218l144.14169,-239.310492c2.275921,-3.750313 6.922594,-4.763911 10.336476,-2.432635c3.508712,2.432635 4.457013,7.297906 2.275921,11.048218l-144.14169,239.310492c-1.422451,2.331275 -3.793202,3.648953 -6.258784,3.648953zm-2.465582,-157.513132c-1.043131,0 -2.086261,-0.20272 -3.129392,-0.709519c-3.793202,-1.824476 -5.405313,-6.588387 -3.698372,-10.642779l84.398753,-198.158413c1.706941,-4.054392 6.069124,-5.777509 9.957156,-3.953032c3.793202,1.824476 5.405313,6.588387 3.698372,10.642779l-84.303923,198.158413c-1.327621,2.939434 -4.077693,4.662551 -6.922594,4.662551z"/>
|
||||
<path stroke="null" id="svg_14" fill="#0276F7" d="m591.846924,375.062866c-2.750072,0 -5.405313,-1.621757 -6.732934,-4.459831c-1.801771,-3.953032 -0.28449,-8.716943 3.413882,-10.642779l129.253371,-67.302908l-365.759539,-178.089172l20.862613,208.091673l133.994874,-64.262114c3.698372,-1.824476 8.155385,0 9.862326,4.054392c1.706941,4.054392 0,8.716943 -3.793202,10.541419l-143.38305,68.823305c-2.181091,1.013598 -4.646673,0.912238 -6.827764,-0.405439c-2.086261,-1.317677 -3.413882,-3.547593 -3.698372,-6.081588l-23.328195,-233.026185c-0.28449,-2.838074 0.853471,-5.676149 3.034562,-7.297906c2.181091,-1.621757 5.025993,-2.027196 7.491575,-0.810878l392.217126,190.961867c2.655242,1.317677 4.362183,4.054392 4.362183,7.196546c0,3.142154 -1.612111,5.980228 -4.172523,7.297906l-143.57271,74.600814c-1.043131,0.608159 -2.181091,0.810878 -3.224222,0.810878zm-283.921198,78.959286c-3.603542,0 -6.827764,-2.838074 -7.396745,-6.791107c-0.56898,-4.358471 2.181091,-8.412864 6.258784,-9.122382l199.617275,-31.826978c4.077693,-0.608159 7.870895,2.331275 8.534705,6.689747c0.56898,4.358471 -2.181091,8.412864 -6.258784,9.122382l-199.617275,31.826978c-0.47415,0.10136 -0.853471,0.10136 -1.137961,0.10136z"/>
|
||||
</g>
|
||||
<text stroke="null" font-style="italic" transform="matrix(6.577099502228161,0,0,7.449448263868419,-1073.2057632249744,-908.8606073938396) " xml:space="preserve" text-anchor="start" font-family="Arvo, sans-serif" font-size="24" id="svg_16" y="177.898525" x="178.621382" stroke-width="0" fill="#D4E4FC">5G</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.9 KiB |
@@ -9,6 +9,8 @@ import advancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import useLayoutStore from '@/store/modules/layout';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { CACHE_LOCAL_PROCONFIG } from './constants/cache-keys-constants';
|
||||
import { localRemove } from './utils/cache-local-utils';
|
||||
const { t, currentLocale } = useI18n();
|
||||
const { themeConfig, initPrimaryColor, changeConf } = useLayoutStore();
|
||||
dayjs.extend(advancedFormat);
|
||||
@@ -34,6 +36,7 @@ onBeforeMount(() => {
|
||||
maxCount: 15,
|
||||
});
|
||||
initPrimaryColor();
|
||||
localRemove(CACHE_LOCAL_PROCONFIG);
|
||||
|
||||
// 输出应用版本号
|
||||
const appStore = useAppStore();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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 { parseDateToStr, YYYY_MM_DD_HH_MM_SS } from '@/utils/date-utils';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
/**
|
||||
@@ -122,7 +122,7 @@ export function updateConfirm(data: Record<string, any>) {
|
||||
const userName = useUserStore().userName;
|
||||
let finalData = {
|
||||
alarm: {
|
||||
ack_time: parseDateToStr(time),
|
||||
ack_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
||||
ack_user: userName,
|
||||
ack_state: '1',
|
||||
},
|
||||
@@ -145,7 +145,7 @@ export function cancelConfirm(data: (string | number)[]) {
|
||||
const userName = useUserStore().userName;
|
||||
let finalData = {
|
||||
alarm: {
|
||||
ack_time: parseDateToStr(time),
|
||||
ack_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
||||
ack_user: '',
|
||||
ack_state: '0',
|
||||
},
|
||||
@@ -211,12 +211,12 @@ export function getPass() {
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function clearAlarm(data: Record<string, any>) {
|
||||
export function clearAlarm2(data: Record<string, any>) {
|
||||
var time = new Date();
|
||||
const userName = useUserStore().userName;
|
||||
let finalData = {
|
||||
data: {
|
||||
clear_time: parseDateToStr(time),
|
||||
clear_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
||||
clear_type: '2',
|
||||
alarm_status: '0',
|
||||
clear_user: userName,
|
||||
@@ -232,6 +232,19 @@ export function clearAlarm(data: Record<string, any>) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除告警信息
|
||||
* @param ids 记录ID
|
||||
* @returns object
|
||||
*/
|
||||
export function clearAlarm(ids: string[]) {
|
||||
return request({
|
||||
url: `/neData/alarm/clear`,
|
||||
method: 'PUT',
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 手工同步
|
||||
* @param data 鉴权对象
|
||||
@@ -360,3 +373,137 @@ export async function top3Sel(filterFlag?: string) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
export async function alarmDashGetAct() {
|
||||
let totalSQL = `select count(*) as total from alarm where alarm_status='1' `;
|
||||
let rowsSQL = `select ne_type,alarm_id,alarm_title,orig_severity,event_time from alarm WHERE alarm_status='1' and orig_severity!='Event' order by event_time desc limit 0,10 `;
|
||||
// 查询
|
||||
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: totalSQL,
|
||||
rowsSQL: rowsSQL,
|
||||
},
|
||||
});
|
||||
|
||||
// 解析数据
|
||||
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['alarm'];
|
||||
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;
|
||||
}
|
||||
|
||||
export async function alarmDashGetHis() {
|
||||
let totalSQL = `select count(*) as total from alarm where alarm_status='0' `;
|
||||
let rowsSQL = `select ne_type,alarm_id,alarm_title,orig_severity,event_time from alarm WHERE alarm_status='0' and orig_severity!='Event' order by event_time desc limit 0,10 `;
|
||||
// 查询
|
||||
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: totalSQL,
|
||||
rowsSQL: rowsSQL,
|
||||
},
|
||||
});
|
||||
|
||||
// 解析数据
|
||||
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['alarm'];
|
||||
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;
|
||||
}
|
||||
export async function getAlarmTrend(params: any) {
|
||||
const days = Number(params.days || 1);
|
||||
let groupFormat = days === 1 ? '%H:00' : '%Y-%m-%d';
|
||||
let timeCondition = days === 1
|
||||
? `event_time >= DATE_SUB(NOW(), INTERVAL 1 DAY)`
|
||||
: `event_time >= DATE_SUB(CURDATE(), INTERVAL ${days} DAY)`;
|
||||
let totalSQL = `select count(*) as total from alarm where alarm_status='0' `;
|
||||
|
||||
let rowsSQL = ` SELECT
|
||||
DATE_FORMAT(event_time, '${groupFormat}') AS time,
|
||||
SUM(CASE WHEN orig_severity='Critical' THEN 1 ELSE 0 END) AS Critical,
|
||||
SUM(CASE WHEN orig_severity='Major' THEN 1 ELSE 0 END) AS Major,
|
||||
SUM(CASE WHEN orig_severity='Minor' THEN 1 ELSE 0 END) AS Minor,
|
||||
SUM(CASE WHEN orig_severity='Warning' THEN 1 ELSE 0 END) AS Warning
|
||||
FROM alarm
|
||||
WHERE alarm_status='0'
|
||||
AND ${timeCondition}
|
||||
GROUP BY time
|
||||
ORDER BY time ASC `;
|
||||
// 查询
|
||||
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/alarm`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: totalSQL,
|
||||
rowsSQL: rowsSQL,
|
||||
},
|
||||
});
|
||||
|
||||
// 解析数据
|
||||
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['alarm'];
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
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';
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
|
||||
@@ -63,7 +63,11 @@ export async function getAlarmSet() {
|
||||
}
|
||||
}
|
||||
if (Object.keys(resultData).length === 0) {
|
||||
return { code: RESULT_CODE_ERROR, msg: RESULT_MSG_ERROR[language], data: {} };
|
||||
return {
|
||||
code: RESULT_CODE_ERROR,
|
||||
msg: RESULT_MSG_ERROR[language],
|
||||
data: {},
|
||||
};
|
||||
}
|
||||
return {
|
||||
code: RESULT_CODE_SUCCESS,
|
||||
@@ -117,7 +121,11 @@ export async function updateAlarmSet(data: Record<string, any>) {
|
||||
}
|
||||
// 无变更时
|
||||
if (resultNum === 0) {
|
||||
return { code: RESULT_CODE_ERROR, msg: RESULT_MSG_ERROR[language], data: 0 };
|
||||
return {
|
||||
code: RESULT_CODE_ERROR,
|
||||
msg: RESULT_MSG_ERROR[language],
|
||||
data: 0,
|
||||
};
|
||||
}
|
||||
return {
|
||||
code: RESULT_CODE_SUCCESS,
|
||||
@@ -166,11 +174,10 @@ export async function getForwardSet() {
|
||||
*/
|
||||
export async function updateForwardSet(data: Record<string, any>) {
|
||||
// return false;
|
||||
console.log(data)
|
||||
let obj:any=[
|
||||
{interface:"Email",to_user:data.emailObj},
|
||||
{interface:"SMS",to_user:data.smsObj}
|
||||
]
|
||||
let obj: any = [
|
||||
{ interface: 'Email', to_user: data.emailObj },
|
||||
{ interface: 'SMS', to_user: data.smsObj },
|
||||
];
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/omc_db/config?WHERE=config_tag='forwardAlarm'`,
|
||||
method: 'put',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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 { parseDateToStr, YYYY_MM_DD_HH_MM_SS } from '@/utils/date-utils';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
/**
|
||||
@@ -79,7 +79,7 @@ export function updateConfirm(data: Record<string, any>) {
|
||||
const userName = useUserStore().userName;
|
||||
let finalData = {
|
||||
alarm: {
|
||||
ack_time: parseDateToStr(time),
|
||||
ack_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
||||
ack_user: userName,
|
||||
ack_state: '1',
|
||||
},
|
||||
@@ -101,7 +101,7 @@ export function cancelConfirm(data: (string | number)[]) {
|
||||
var time = new Date();
|
||||
let finalData = {
|
||||
alarm: {
|
||||
ack_time: parseDateToStr(time),
|
||||
ack_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
||||
ack_user: '',
|
||||
ack_state: '0',
|
||||
},
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
||||
import { sessionGet } from '@/utils/cache-session-utils';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
@@ -51,3 +53,43 @@ export function delFile(query: Record<string, any>) {
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新FTP信息
|
||||
* @param data 数据
|
||||
* @returns object
|
||||
*/
|
||||
export function updateFTPInfo(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/lm/table/ftp`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取FTP信息
|
||||
* @param data 数据
|
||||
* @returns object
|
||||
*/
|
||||
export function getFTPInfo() {
|
||||
return request({
|
||||
url: `/lm/table/ftp`,
|
||||
method: 'get',
|
||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送FTP文件
|
||||
* @param data 数据
|
||||
* @returns object
|
||||
*/
|
||||
export function putFTPInfo(filePath: string, fileName: string) {
|
||||
return request({
|
||||
url: `/lm/table/ftp`,
|
||||
method: 'put',
|
||||
data: { filePath, fileName },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
||||
import { sessionGet } from '@/utils/cache-session-utils';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
// 登录方法
|
||||
@@ -7,7 +9,7 @@ export function login(data: Record<string, string>) {
|
||||
method: 'post',
|
||||
data: data,
|
||||
whithToken: false,
|
||||
crypto: true,
|
||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,7 +24,7 @@ export function register(data: Record<string, any>) {
|
||||
method: 'post',
|
||||
data: data,
|
||||
whithToken: false,
|
||||
crypto: true,
|
||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -59,3 +61,69 @@ export function getCaptchaImage() {
|
||||
whithToken: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录认证源
|
||||
* @returns object
|
||||
*/
|
||||
export function getLoginSource() {
|
||||
return request({
|
||||
url: '/auth/login/source',
|
||||
method: 'GET',
|
||||
whithToken: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP登录
|
||||
* @returns object
|
||||
*/
|
||||
export function loginLDAP(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/auth/login/ldap',
|
||||
method: 'POST',
|
||||
data: data,
|
||||
whithToken: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP登录
|
||||
* @returns object
|
||||
*/
|
||||
export function loginSMTP(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/auth/login/smtp',
|
||||
method: 'POST',
|
||||
data: data,
|
||||
whithToken: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录认证源OAuth2跳转登录URL
|
||||
* @returns object
|
||||
*/
|
||||
export function loginOAuth2URL(state: string): string {
|
||||
// 兼容旧前端可改配置文件
|
||||
const baseUrl = import.meta.env.PROD
|
||||
? sessionGet('baseUrl') || import.meta.env.VITE_API_BASE_URL
|
||||
: import.meta.env.VITE_API_BASE_URL;
|
||||
return `${baseUrl}/auth/login/oauth2/authorize?state=${state}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录认证源OAuth2认证登录
|
||||
* @returns object
|
||||
*/
|
||||
export function loginOAuth2Token(code: string, state: string) {
|
||||
return request({
|
||||
url: '/auth/login/oauth2/token',
|
||||
method: 'POST',
|
||||
data: {
|
||||
code,
|
||||
state,
|
||||
},
|
||||
whithToken: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@ import { request } from '@/plugins/http-fetch';
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function getAllNeConfig(neType: string) {
|
||||
export function getAllNeConfig(neType: string, neId: string) {
|
||||
return request({
|
||||
url: `/ne/config/list/${neType}`,
|
||||
method: 'get',
|
||||
params: { neId },
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
||||
import { sessionGet } from '@/utils/cache-session-utils';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
@@ -36,7 +38,7 @@ export function addNeInfo(data: Record<string, any>) {
|
||||
url: `/ne/info`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
crypto: true,
|
||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
@@ -51,7 +53,7 @@ export function updateNeInfo(data: Record<string, any>) {
|
||||
url: `/ne/info`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
crypto: true,
|
||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ export function listAMFDataUE(query: Record<string, any>) {
|
||||
url: '/neData/amf/ue/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,6 +38,93 @@ export function exportAMFDataUE(data: Record<string, any>) {
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AMF-接入基站信息列表
|
||||
* @param query 查询参数 neId=001&id=1
|
||||
* @returns object
|
||||
*/
|
||||
export function listAMFNblist(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/amf/nb/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AMF-接入基站状态信息列表
|
||||
* @param query 查询参数 neId=001&state=1
|
||||
* @returns object
|
||||
*/
|
||||
export function listAMFNbStatelist(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/amf/nb/list-cfg',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AMF-接入基站状态信息新增
|
||||
* @param neId 网元ID
|
||||
* @param data 数据 { "index": 1, "name": "Gnb", "address": "192.168.8.1", "position": "Area-B" }
|
||||
* @returns object
|
||||
*/
|
||||
export function addAMFNbState(neId: string, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/config/data`,
|
||||
method: 'post',
|
||||
data: {
|
||||
neType: 'AMF',
|
||||
neId: neId,
|
||||
paramName: 'gnbList',
|
||||
paramData: data,
|
||||
loc: `${data.index}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AMF-接入基站状态信息修改
|
||||
* @param neId 网元ID
|
||||
* @param data 数据 { "index": 1, "name": "Gnb", "address": "192.168.8.1", "position": "Area-B" }
|
||||
* @returns object
|
||||
*/
|
||||
export function editAMFNbState(neId: string, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/config/data`,
|
||||
method: 'put',
|
||||
data: {
|
||||
neType: 'AMF',
|
||||
neId: neId,
|
||||
paramName: 'gnbList',
|
||||
paramData: data,
|
||||
loc: `${data.index}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AMF-接入基站状态信息删除
|
||||
* @param neId 网元ID
|
||||
* @param index 数据index
|
||||
* @returns object
|
||||
*/
|
||||
export function delAMFNbState(neId: string, index: string | number) {
|
||||
return request({
|
||||
url: `/ne/config/data`,
|
||||
method: 'delete',
|
||||
params: {
|
||||
neType: 'AMF',
|
||||
neId: neId,
|
||||
paramName: 'gnbList',
|
||||
loc: `${index}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
68
src/api/neData/backup.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 备份文件-获取FTP配置
|
||||
* @returns object
|
||||
*/
|
||||
export function getBackupFTP() {
|
||||
return request({
|
||||
url: '/neData/backup/ftp',
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份文件-文件FTP发送
|
||||
* @param data 对象
|
||||
* @returns object
|
||||
*/
|
||||
export function pushBackupFTP(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/backup/ftp',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份文件-更新FTP配置
|
||||
* @param data 对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateBackupFTP(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/backup/ftp',
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份文件-导出OMC
|
||||
* @returns object
|
||||
*/
|
||||
export function exportBackupOMC() {
|
||||
return request({
|
||||
url: '/neData/backup/export-omc',
|
||||
method: 'POST',
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份文件-导入OMC
|
||||
* @param filePath 备份文件上传返回的/upload 路径
|
||||
* @returns object
|
||||
*/
|
||||
export function importBackupOMC(filePath: string) {
|
||||
return request({
|
||||
url: '/neData/backup/import-omc',
|
||||
method: 'POST',
|
||||
data: {
|
||||
neType: 'OMC',
|
||||
path: filePath,
|
||||
},
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -10,6 +10,7 @@ export function listIMSDataCDR(query: Record<string, any>) {
|
||||
url: '/neData/ims/cdr/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,6 +38,6 @@ export function exportIMSDataCDR(data: Record<string, any>) {
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
148
src/api/neData/ims_sub.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* UDM签约用户重载数据
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function resetIMSSub(neId: string) {
|
||||
return request({
|
||||
url: `/ue/udm/imsuser/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listIMSSub(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ue/udm/imsuser/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户信息
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @returns object
|
||||
*/
|
||||
export function getIMSSub(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ue/udm/imsuser/${neId}/${imsi}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户新增
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addIMSSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ue/udm/imsuser/${data.neId}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户批量新增
|
||||
* @param data 签约对象
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchAddIMSSub(data: Record<string, any>, num: number) {
|
||||
return request({
|
||||
url: `/ue/udm/imsuser/${data.neId}/${num}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户修改
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
// export function updateIMSSub(data: Record<string, any>) {
|
||||
// return request({
|
||||
// url: `/ue/udm/imsuser/${data.neId}`,
|
||||
// method: 'put',
|
||||
// data: data,
|
||||
// timeout: 180_000,
|
||||
// });
|
||||
// }
|
||||
|
||||
/**
|
||||
* UDM签约用户删除
|
||||
* @param data 签约对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delIMSSub(neId: string, imsi_msisdn: string, tag: string) {
|
||||
return request({
|
||||
url: `/ue/udm/imsuser/${neId}/${imsi_msisdn}`,
|
||||
method: 'delete',
|
||||
params: { volte: tag },
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户批量删除
|
||||
* @param neId 网元ID
|
||||
* @param imsi IMSI
|
||||
* @param num 数量
|
||||
* @returns object
|
||||
*/
|
||||
export function batchDelIMSSub(
|
||||
neId: string,
|
||||
imsi: string,
|
||||
num: number,
|
||||
tag: string
|
||||
) {
|
||||
return request({
|
||||
url: `/ue/udm/imsuser/${neId}/${imsi}/${num}`,
|
||||
method: 'delete',
|
||||
params: { volte: tag },
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户导出
|
||||
* @param data 数据参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportIMSSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ue/udm/imsuser/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户导入
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importIMSSub(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ue/udm/imsuser/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -10,6 +10,7 @@ export function listMMEDataUE(query: Record<string, any>) {
|
||||
url: '/neData/mme/ue/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,6 +38,93 @@ export function exportMMEDataUE(data: Record<string, any>) {
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-接入基站信息列表
|
||||
* @param query 查询参数 neId=001&id=1
|
||||
* @returns object
|
||||
*/
|
||||
export function listMMENblist(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/mme/nb/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-接入基站状态信息列表
|
||||
* @param query 查询参数 neId=001&state=1
|
||||
* @returns object
|
||||
*/
|
||||
export function listMMENbStatelist(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/mme/nb/list-cfg',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-接入基站状态信息新增
|
||||
* @param neId 网元ID
|
||||
* @param data 数据 { "index": 1, "name": "Enb", "address": "192.168.8.1", "position": "Area-B" }
|
||||
* @returns object
|
||||
*/
|
||||
export function addMMENbState(neId: string, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/config/data`,
|
||||
method: 'post',
|
||||
data: {
|
||||
neType: 'MME',
|
||||
neId: neId,
|
||||
paramName: 'enbList',
|
||||
paramData: data,
|
||||
loc: `${data.index}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-接入基站状态信息修改
|
||||
* @param neId 网元ID
|
||||
* @param data 数据 { "index": 1, "name": "Enb", "address": "192.168.8.1", "position": "Area-B" }
|
||||
* @returns object
|
||||
*/
|
||||
export function editMMENbState(neId: string, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ne/config/data`,
|
||||
method: 'put',
|
||||
data: {
|
||||
neType: 'MME',
|
||||
neId: neId,
|
||||
paramName: 'enbList',
|
||||
paramData: data,
|
||||
loc: `${data.index}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* MME-接入基站状态信息删除
|
||||
* @param neId 网元ID
|
||||
* @param index 数据index
|
||||
* @returns object
|
||||
*/
|
||||
export function delMMENbState(neId: string, index: string | number) {
|
||||
return request({
|
||||
url: `/ne/config/data`,
|
||||
method: 'delete',
|
||||
params: {
|
||||
neType: 'MME',
|
||||
neId: neId,
|
||||
paramName: 'enbList',
|
||||
loc: `${index}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
30
src/api/neData/nb-state.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 历史记录列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listNBState(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/nb-state/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 历史记录列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportNBState(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/nb-state/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
43
src/api/neData/sgwc.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询SGWC-CDR会话事件
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSGWCDataCDR(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/sgwc/cdr/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SGWC-CDR会话删除
|
||||
* @param id 信息ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delSGWCDataCDR(cdrIds: string | number) {
|
||||
return request({
|
||||
url: `/neData/sgwc/cdr/${cdrIds}`,
|
||||
method: 'delete',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SGWC-CDR会话列表导出
|
||||
* @param data 查询列表条件
|
||||
* @returns object
|
||||
*/
|
||||
export function exportSGWCDataCDR(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/sgwc/cdr/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
@@ -10,6 +10,7 @@ export function listSMFDataCDR(query: Record<string, any>) {
|
||||
url: '/neData/smf/cdr/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,7 +38,20 @@ export function exportSMFDataCDR(data: Record<string, any>) {
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* SMF-在线订阅用户数量
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSMFSubNum(neId: string) {
|
||||
return request({
|
||||
url: '/neData/smf/sub/num',
|
||||
method: 'get',
|
||||
params: { neId },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -46,9 +60,9 @@ export function exportSMFDataCDR(data: Record<string, any>) {
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listSMFSubscribers(query: Record<string, any>) {
|
||||
export function listSMFSubList(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/smf/subscribers',
|
||||
url: '/neData/smf/sub/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ export function listSMSCDataCDR(query: Record<string, any>) {
|
||||
url: '/neData/smsc/cdr/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,6 +38,6 @@ export function exportSMSCDataCDR(data: Record<string, any>) {
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -140,3 +140,17 @@ export function exportUDMAuth(data: Record<string, any>) {
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导出DecAuth
|
||||
* @param neId 网元ID
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUDMDecAuth(neId: string) {
|
||||
return request({
|
||||
url: `/neData/udm/auth/export-dec?neId=${neId}`,
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
142
src/api/neData/voip_auth.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* UDM鉴权用户重载数据
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function resetUDMAuth(neId: string) {
|
||||
return request({
|
||||
url: `/ue/udm/voipauth/resetData/${neId}`,
|
||||
method: 'put',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listUDMAuth(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ue/udm/voipauth/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户信息
|
||||
* @param neId 网元ID
|
||||
* @param userName 用户名
|
||||
* @returns object
|
||||
*/
|
||||
export function getUDMAuth(neId: string, userName: string) {
|
||||
return request({
|
||||
url: `/ue/udm/voipauth/${neId}/${userName}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户新增
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ue/udm/voipauth/${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: `/ue/udm/voipauth/${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: `/ue/udm/voipauth/${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: `/ue/udm/voipauth/${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: `/ue/udm/voipauth/${neId}/${imsi}/${num}`,
|
||||
method: 'delete',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导入
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ue/udm/voipauth/import`,
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导出
|
||||
* @param data 数据参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUDMAuth(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ue/udm/voipauth/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
51
src/api/neUser/exportFile.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
||||
import { sessionGet } from '@/utils/cache-session-utils';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
/**
|
||||
* 获取下拉框数据
|
||||
* @returns object
|
||||
*/
|
||||
export function getBakFile() {
|
||||
return request({
|
||||
url: '/ue/table/list',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取对应类型的文件列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function getBakFileList(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ue/file/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 下载远端文件
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function downFile(query: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ue/file/${query.fileName}`,
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 删除远端获取文件
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function delFile(query: Record<string, any>) {
|
||||
return request({
|
||||
url: `/ue/file/${query.fileName}`,
|
||||
method: 'delete',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
@@ -21,12 +21,14 @@ export async function listUEInfoBySMF(query: Record<string, any>) {
|
||||
};
|
||||
// 解析数据
|
||||
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;
|
||||
if (result.data.total && result.data.data) {
|
||||
data.total = result.data.total;
|
||||
data.rows = result.data.data;
|
||||
} else {
|
||||
Object.assign(data, result.data);
|
||||
Object.assign(data, {
|
||||
total: result.data.length,
|
||||
rows: result.data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
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';
|
||||
|
||||
/**
|
||||
* 新 查询自定义指标数据
|
||||
@@ -14,6 +11,7 @@ export async function listCustomData(query: Record<string, any>) {
|
||||
url: `/pm/kpiC/report`,
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
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';
|
||||
|
||||
/**
|
||||
* 查询自定义指标
|
||||
|
||||
@@ -110,78 +110,52 @@ export async function getKPITitle(neType: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Todo 废弃
|
||||
* 查询UPF上下行速率数据
|
||||
* @param query 查询参数
|
||||
* 查询黄金指标数据kpi.id转换title
|
||||
* @param neType 网元类型
|
||||
* @returns object
|
||||
*/
|
||||
export async function listUPFData(timeArr: any) {
|
||||
const initTime: Date = new Date();
|
||||
const twentyFourHoursAgo: Date = new Date(
|
||||
initTime.getTime() - 10 * 60 * 1000
|
||||
);
|
||||
|
||||
return await Promise.allSettled([
|
||||
// 获取参数规则
|
||||
request({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/gold_kpi`,
|
||||
export async function getKPITitleList(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/kpi/title/list',
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: `SELECT gold_kpi.*,kpi_title.en_title FROM gold_kpi LEFT JOIN kpi_title on gold_kpi.kpi_id=kpi_title.kpi_id where 1=1 and gold_kpi.kpi_id ='UPF.03' AND timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 10 MINUTE) AND NOW()`,
|
||||
},
|
||||
timeout: 60_000,
|
||||
}),
|
||||
// 获取对应信息
|
||||
request({
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/gold_kpi`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: `SELECT gold_kpi.*,kpi_title.en_title FROM gold_kpi LEFT JOIN kpi_title on gold_kpi.kpi_id=kpi_title.kpi_id where 1=1 and gold_kpi.kpi_id ='UPF.06' AND timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 10 MINUTE) AND NOW()`,
|
||||
},
|
||||
timeout: 60_000,
|
||||
}),
|
||||
]).then(resArr => {
|
||||
let upData: any = [];
|
||||
let downData: any = [];
|
||||
|
||||
// 规则数据
|
||||
if (resArr[0].status === 'fulfilled') {
|
||||
const itemV: any = resArr[0].value;
|
||||
// 解析数据
|
||||
if (
|
||||
itemV.code === RESULT_CODE_SUCCESS &&
|
||||
Array.isArray(itemV.data?.data)
|
||||
) {
|
||||
let itemData = itemV.data.data;
|
||||
let data = itemData[0]['gold_kpi'];
|
||||
if (Array.isArray(data)) {
|
||||
try {
|
||||
upData = data.map(v => parseObjLineToHump(v));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
const data = itemData[0]['gold_kpi'];
|
||||
if (Array.isArray(data)) {
|
||||
try {
|
||||
downData = data.map(v => parseObjLineToHump(v));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return { upData, downData };
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改指标标题
|
||||
* @param data 指标标题对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateKPITitle(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/kpi/title',
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
//忙时呼叫
|
||||
export async function getbusyhour(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/ims/kpi/busy-hour',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
//MOS指标
|
||||
export async function getMosHour(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/ims/cdr/mos-hour',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
//CCT指标
|
||||
export async function getCctHour(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/neData/ims/cdr/cct-hour',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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';
|
||||
|
||||
/**
|
||||
* 查询任务列表
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 保存为示例配置 (仅管理员操作)
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function ptSaveAsDefault(neType: string, neid: string) {
|
||||
return request({
|
||||
url: `/pt/neConfigData/saveAsDefault`,
|
||||
method: 'post',
|
||||
data: { neType, neid },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置为示例配置 (仅学生/教师操作)
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function ptResetAsDefault(neType: string) {
|
||||
return request({
|
||||
url: `/pt/neConfigData/resetAsDefault`,
|
||||
method: 'post',
|
||||
data: { neType },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据比较示例
|
||||
* @param params 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function ptContrastAsDefault(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData/contrast`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置数据导出Excel
|
||||
* @param student 仅教师 student
|
||||
* @returns object
|
||||
*/
|
||||
export function ptExport(student: string | undefined) {
|
||||
return request({
|
||||
url: `/pt/neConfigData/export`,
|
||||
method: 'get',
|
||||
params: { student },
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置数据导出Excel (仅教师全量)
|
||||
* @returns object
|
||||
*/
|
||||
export function ptExportAll() {
|
||||
return request({
|
||||
url: `/pt/neConfigData/export-all`,
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置信息
|
||||
* @param params 数据 {neType,paramName}
|
||||
* @returns object
|
||||
*/
|
||||
export function getPtNeConfigData(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置数据更新
|
||||
* @param data 数据 {neType,paramName:"参数名",paramData:{参数},loc:"层级index仅array"}
|
||||
* @returns object
|
||||
*/
|
||||
export function editPtNeConfigData(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置新增(array)
|
||||
* @param data 数据 {neType,paramName:"参数名",paramData:{参数},loc:"层级index"}
|
||||
* @returns object
|
||||
*/
|
||||
export function addPtNeConfigData(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置删除(array)
|
||||
* @param params 数据 {neType,paramName:"参数名",loc:"层级index"}
|
||||
* @returns object
|
||||
*/
|
||||
export function delPtNeConfigData(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigData`,
|
||||
method: 'delete',
|
||||
params,
|
||||
});
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 班级学生列表 (仅教师操作)
|
||||
* @param params 数据 {userName}
|
||||
* @returns object
|
||||
*/
|
||||
export function getPtClassStudents(params?: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigApply/students`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置应用申请列表
|
||||
* @param params 数据 {neType,paramName}
|
||||
* @returns object
|
||||
*/
|
||||
export function getPtNeConfigApplyList(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigApply/list`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置应用申请提交(仅学生操作)
|
||||
* @param data 数据 { "neType": "MME", "status": "1" }
|
||||
* @returns object
|
||||
*/
|
||||
export function stuPtNeConfigApply(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigApply`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置应用申请状态变更(仅管理员/教师操作)
|
||||
* @param data 数据 { "applyId": "1", "neType": "MME", "status": "3", "backInfo": "sgw参数错误" }
|
||||
* @returns object
|
||||
*/
|
||||
export function updatePtNeConfigApply(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigApply`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 网元参数配置数据变更日志信息
|
||||
* @param params 数据 {neType,paramName}
|
||||
* @returns object
|
||||
*/
|
||||
export function getPtNeConfigDataLogList(params: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigDataLog`,
|
||||
params,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 网元参数配置数据变更日志还原到数据
|
||||
* @param data 数据 { "id": "1", "value": "old" }
|
||||
* @returns object
|
||||
*/
|
||||
export function restorePtNeConfigDataLog(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/pt/neConfigDataLog/restore`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 导入用户模板数据
|
||||
* @param data 表单数据对象
|
||||
* @returns object
|
||||
*/
|
||||
export function importData(data: FormData) {
|
||||
return request({
|
||||
url: '/pt/system/user/importData',
|
||||
method: 'post',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入用户模板下载
|
||||
* @returns bolb
|
||||
*/
|
||||
export function importTemplate() {
|
||||
return request({
|
||||
url: '/pt/system/user/importTemplate',
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户列表导出
|
||||
* @param query 查询参数
|
||||
* @returns bolb
|
||||
*/
|
||||
export function exportUser(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/pt/system/user/export',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
64
src/api/system/login-source.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询登录源列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listLoginSource(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/system/login-source/list',
|
||||
method: 'GET',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询登录源详细
|
||||
* @param id 登录源ID
|
||||
* @returns object
|
||||
*/
|
||||
export function getLoginSource(id: string | number) {
|
||||
return request({
|
||||
url: `/system/login-source/${id}`,
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增登录源
|
||||
* @param data 登录源对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addLoginSource(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/system/login-source',
|
||||
method: 'POST',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改登录源
|
||||
* @param data 登录源对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateLoginSource(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/system/login-source',
|
||||
method: 'PUT',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证源删除
|
||||
* @param id 登录源ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delLoginSource(id: string | number) {
|
||||
return request({
|
||||
url: `/system/login-source/${id}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
99
src/api/system/tenant.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询部门列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listTenant(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/system/tenant/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部门列表(排除节点)
|
||||
* @param tenantId 部门ID
|
||||
* @returns object
|
||||
*/
|
||||
export function listTenantExcludeChild(tenantId: string | number) {
|
||||
return request({
|
||||
url: `/system/tenant/list/exclude/${tenantId}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部门详细
|
||||
* @param tenantId 部门ID
|
||||
* @returns object
|
||||
*/
|
||||
export function getTenant(tenantId: string | number) {
|
||||
return request({
|
||||
url: `/system/tenant/${tenantId}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增部门
|
||||
* @param data 部门对象
|
||||
* @returns object
|
||||
*/
|
||||
export function addTenant(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/system/tenant',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改部门
|
||||
* @param data 部门对象
|
||||
* @returns object
|
||||
*/
|
||||
export function updateTenant(data: Record<string, any>) {
|
||||
return request({
|
||||
url: '/system/tenant',
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部门
|
||||
* @param TenantId 部门ID
|
||||
* @returns object
|
||||
*/
|
||||
export function delTenant(TenantId: string | number) {
|
||||
return request({
|
||||
url: `/system/tenant/${TenantId}`,
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部门下拉树结构
|
||||
* @returns object
|
||||
*/
|
||||
export function tenantTreeSelect() {
|
||||
return request({
|
||||
url: '/system/tenant/treeSelect',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门树结构列表(指定角色)
|
||||
* @param roleId 角色ID
|
||||
* @returns object
|
||||
*/
|
||||
export function roleTenantTreeSelect(roleId: string | number) {
|
||||
return request({
|
||||
url: `/system/tenant/roleDeptTreeSelect/${roleId}`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import { encode } from 'js-base64';
|
||||
export async function downloadFile(filePath: string, range?: string) {
|
||||
return request({
|
||||
url: `/file/download/${encode(filePath)}`,
|
||||
method: 'get',
|
||||
method: 'GET',
|
||||
headers: range ? { range } : {},
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
@@ -76,8 +76,8 @@ export async function downloadFileChunk(
|
||||
*/
|
||||
export function uploadFile(data: FormData) {
|
||||
return request({
|
||||
url: '/file/upload',
|
||||
method: 'post',
|
||||
url: '/file/upload2',
|
||||
method: 'POST',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 180_000,
|
||||
@@ -169,7 +169,7 @@ export async function uploadFileChunk(
|
||||
export function chunkCheck(identifier: string, fileName: string) {
|
||||
return request({
|
||||
url: '/file/chunkCheck',
|
||||
method: 'post',
|
||||
method: 'POST',
|
||||
data: { identifier, fileName },
|
||||
timeout: 60_000,
|
||||
});
|
||||
@@ -189,7 +189,7 @@ export function chunkMerge(
|
||||
) {
|
||||
return request({
|
||||
url: '/file/chunkMerge',
|
||||
method: 'post',
|
||||
method: 'POST',
|
||||
data: { identifier, fileName, subPath },
|
||||
timeout: 60_000,
|
||||
});
|
||||
@@ -203,13 +203,57 @@ export function chunkMerge(
|
||||
export function chunkUpload(data: FormData) {
|
||||
return request({
|
||||
url: '/file/chunkUpload',
|
||||
method: 'post',
|
||||
method: 'POST',
|
||||
data,
|
||||
dataType: 'form-data',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地文件列表
|
||||
* @param path 文件路径
|
||||
* @param search search prefix
|
||||
* @returns object
|
||||
*/
|
||||
export async function listFile(query: Record<string, any>) {
|
||||
return request({
|
||||
url: `/file/list`,
|
||||
method: 'GET',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地文件获取下载
|
||||
* @param path 文件路径
|
||||
* @param fileName 文件名
|
||||
* @returns object
|
||||
*/
|
||||
export async function getFile(path: string, fileName: string) {
|
||||
return request({
|
||||
url: `/file`,
|
||||
method: 'GET',
|
||||
params: { path, fileName },
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地文件删除
|
||||
* @param path 文件路径
|
||||
* @param fileName 文件名
|
||||
* @returns object
|
||||
*/
|
||||
export async function delFile(path: string, fileName: string) {
|
||||
return request({
|
||||
url: `/file`,
|
||||
method: 'DELETE',
|
||||
params: { path, fileName },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 转存上传文件到静态资源
|
||||
* @returns object
|
||||
@@ -217,7 +261,7 @@ export function chunkUpload(data: FormData) {
|
||||
export function transferStaticFile(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/file/transferStaticFile`,
|
||||
method: 'post',
|
||||
method: 'POST',
|
||||
data,
|
||||
timeout: 60_000,
|
||||
});
|
||||
@@ -241,11 +285,12 @@ export async function uploadFileToNE(
|
||||
if (uploadChunkRes.code === RESULT_CODE_SUCCESS) {
|
||||
const transferToNeFileRes = await request({
|
||||
url: `/ne/action/pushFile`,
|
||||
method: 'post',
|
||||
method: 'POST',
|
||||
data: {
|
||||
uploadPath: uploadChunkRes.data.fileName,
|
||||
neType,
|
||||
neId,
|
||||
delTemp: true,
|
||||
},
|
||||
timeout: 60_000,
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ export function getNeFile(query: Record<string, any>) {
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
timeout: 600_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export function getNeDirZip(data: Record<string, any>) {
|
||||
method: 'get',
|
||||
params: data,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
timeout: 600_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -45,6 +45,6 @@ export function getNeViewFile(data: Record<string, any>) {
|
||||
url: '/ne/action/viewFile',
|
||||
method: 'get',
|
||||
params: data,
|
||||
timeout: 60_000,
|
||||
timeout: 600_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,3 +8,12 @@ export function pingV(data: Record<string, string>) {
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
|
||||
// ping RTT 时延抖动
|
||||
export function pingRTT(data: Record<string, string>) {
|
||||
return request({
|
||||
url: '/tool/ping/rtt',
|
||||
method: 'POST',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||
|
||||
/**
|
||||
* 查询信令列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export async function listTraceData(query: Record<string, any>) {
|
||||
let totalSQL = 'select count(*) as total from trace_data where 1=1 ';
|
||||
let rowsSQL = 'select * from trace_data where 1=1 ';
|
||||
|
||||
// 查询
|
||||
let querySQL = '';
|
||||
if (query.imsi) {
|
||||
querySQL += ` and imsi like '%${query.imsi}%' `;
|
||||
}
|
||||
if (query.msisdn) {
|
||||
querySQL += ` and msisdn like '%${query.msisdn}%' `;
|
||||
}
|
||||
|
||||
// 分页
|
||||
const pageNum = (query.pageNum - 1) * query.pageSize;
|
||||
const limtSql = ` limit ${pageNum},${query.pageSize} `;
|
||||
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/omc_db/trace_data`,
|
||||
method: 'get',
|
||||
params: {
|
||||
totalSQL: totalSQL + querySQL,
|
||||
rowsSQL: rowsSQL + querySQL + limtSql,
|
||||
},
|
||||
});
|
||||
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
const data: DataList = {
|
||||
total: 0,
|
||||
rows: [],
|
||||
code: result.code,
|
||||
msg: result.msg,
|
||||
};
|
||||
result.data.data.forEach((item: any) => {
|
||||
const itemData = item['trace_data'];
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 信令数据解析HTML
|
||||
* @param id 任务ID
|
||||
* @returns
|
||||
*/
|
||||
export function getTraceRawInfo(id: Record<string, string>) {
|
||||
return request({
|
||||
url: `/api/rest/traceManagement/v1/decMessage/${id}`,
|
||||
method: 'get',
|
||||
responseType: 'text',
|
||||
});
|
||||
}
|
||||
@@ -62,3 +62,18 @@ export function packetKeep(taskNo: string, duration: number = 120) {
|
||||
data: { taskNo, duration },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 信令跟踪文件
|
||||
* @param taskNo 对象
|
||||
* @returns object
|
||||
*/
|
||||
export function packetPCAPFile(taskNo: string) {
|
||||
return request({
|
||||
url: '/trace/packet/filePull',
|
||||
method: 'get',
|
||||
params: { taskNo },
|
||||
responseType: 'blob',
|
||||
timeout: 680_000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||
|
||||
/**
|
||||
* 查询跟踪任务列表
|
||||
@@ -76,29 +74,31 @@ export function filePullTask(traceId: string) {
|
||||
method: 'get',
|
||||
params: { traceId },
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
timeout: 600_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取网元跟踪接口列表
|
||||
* 跟踪任务数据列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export async function getNeTraceInterfaceAll() {
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/ne_info`,
|
||||
export async function listTraceData(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/trace/data/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询跟踪任务数据信息
|
||||
* @param id ID
|
||||
* @returns object
|
||||
*/
|
||||
export async function getTraceData(id: string | number) {
|
||||
return request({
|
||||
url: `/trace/data/${id}`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: `SELECT ne_type,interface FROM trace_info GROUP BY ne_type,interface`,
|
||||
},
|
||||
});
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
||||
let data = result.data.data[0];
|
||||
return Object.assign(result, {
|
||||
data: parseObjLineToHump(data['trace_info']),
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,6 @@ export function filePullTaskHLR(query: Record<string, any>) {
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob',
|
||||
timeout: 60_000,
|
||||
timeout: 600_000,
|
||||
});
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 70 KiB |
1
src/assets/svg/4gEvent.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1721721606045" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7339" width="200" height="200"><path d="M610.6 234.24L627 294.6c90.88-24.73 184.58 28.77 209.45 119.65l60.36-16.4C862.92 273.5 734.67 200.37 610.6 234.24z m-34.42-126.22l16.4 60.36c160.51-43.83 326.13 50.81 369.96 211.33l60.36-16.4C969.94 169.45 770.03 55.18 576.18 108.02zM179.47 922.27V827.5H0v-84.83l179.47-261.74h92.22v274.24h62.38v72.33h-62.38v94.77h-92.22z m0-167.09V598.02L72.33 755.18h107.14z m0 0" p-id="7340" fill="#ffffff"></path><path d="M695.69 752.62h-89.8v-77.29h186.99v231.9c-33.34 9.95-67.35 14.92-102.17 14.92-26.62 3.37-61.57 4.97-104.72 4.97-141.29-8.33-213.62-86.44-216.97-234.31 3.36-151.24 75.69-231.9 216.97-241.85 144.65 0 216.03 49.88 214.42 149.63H695.69c0-51.49-30.79-77.3-92.23-77.3-84.83 1.62-127.98 58.21-129.59 169.52 1.61 109.7 44.9 165.49 129.59 167.1 24.87 0 54.05-3.36 87.25-9.95-1.61 1.61 0 1.61 4.98 0v-97.34z m0 0" p-id="7341" fill="#ffffff"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/svg/5gEvent.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1721721630123" class="icon" viewBox="0 0 1216 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="54141" width="200" height="200"><path d="M747.264 190.912l18.368 67.328a190.272 190.272 0 0 1 233.728 133.44l67.264-18.368a260.032 260.032 0 0 0-319.36-182.4z m-38.4-140.736l18.368 67.328a336.192 336.192 0 0 1 412.8 235.776l67.328-18.368A405.952 405.952 0 0 0 708.864 50.176z m133.376 719.232h-100.16v-86.272h208.64v258.752c-37.12 11.136-75.072 16.704-114.048 16.704a984.96 984.96 0 0 1-116.864 5.568c-157.632-9.28-238.336-96.448-242.048-261.504 3.712-168.768 84.416-258.752 242.048-269.888 161.344 0 241.088 55.68 239.296 166.912H842.24c0-57.472-34.368-86.208-102.912-86.208-94.592 1.856-142.848 64.896-144.64 189.184 1.792 122.368 50.048 184.576 144.64 186.368 27.776 0 60.16-3.712 97.344-11.136-1.92 1.92 0 1.92 5.568 0v-108.48zM234.24 969.216c-86.016 0-148.992-30.72-201.216-80.64l71.424-85.248c40.704 36.864 80.64 58.368 128.256 58.368 55.296 0 89.856-26.88 89.856-74.496v-1.536c0-46.08-39.168-72.96-95.232-72.96-33.792 0-64.512 9.216-89.856 19.968L69.12 687.36l15.36-264.96h330.24v103.68H185.856l-6.144 92.928a262.976 262.976 0 0 1 70.656-9.216c104.448 0 188.16 50.688 188.16 172.032v1.536c0 113.664-80.64 185.856-204.288 185.856z" p-id="54142" fill="#ffffff"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
3
src/assets/svg/basefff.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720074329868" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4280" width="64" height="64"><path d="M616.5 151.3l-28.3 28.3c19.7 19.6 31.8 46.6 31.8 76.5 0 29.8-12.2 56.9-31.8 76.5l28.3 28.3c26.8-27 43.5-64 43.5-104.9s-16.7-77.9-43.5-104.7zM435.8 179.5l-28.3-28.3C380.7 178.1 364 215.1 364 256s16.7 77.9 43.5 104.7l28.3-28.3C416.2 312.9 404 285.8 404 256c0-29.9 12.2-56.9 31.8-76.5zM346.6 134.3L318.3 106c-38.5 38.4-62.3 91.5-62.3 150s23.8 111.6 62.3 150l28.3-28.3C315.3 346.6 296 303.5 296 256s19.3-90.6 50.6-121.7zM705.7 106l-28.3 28.3C708.7 165.4 728 208.5 728 256s-19.3 90.6-50.6 121.7l28.3 28.3c38.5-38.4 62.3-91.5 62.3-150s-23.8-111.6-62.3-150zM815.2 60.8l-0.1-0.1L786.7 89c0.1 0 0.1 0.1 0.2 0.1C831.5 133.7 856 193 856 256s-24.5 122.3-69.1 166.9c0 0-0.1 0.1-0.2 0.1l28.3 28.3 0.1-0.1C867.3 399 896 329.7 896 256s-28.7-143-80.8-195.2zM237.3 89L209 60.7l-0.1 0.1C156.7 113 128 182.3 128 256s28.7 143 80.8 195.2l0.1 0.1 28.3-28.3c-0.1 0-0.1-0.1-0.2-0.1-44.5-44.6-69-103.9-69-166.9s24.5-122.3 69.1-166.9c0.1 0 0.1-0.1 0.2-0.1zM511.712 256.002l0.283-0.283 0.283 0.283-0.283 0.283z" p-id="4281" fill="#ffffff"></path><path d="M511.719 256.021l0.282-0.282 0.283 0.282-0.283 0.283z" p-id="4282" fill="#ffffff"></path><path d="M708.4 616l-14.2-26.1-7.6-13.9-11.6-21.2L512 256 337.5 576l-21.8 40L128 960h74l33.8-64 28.9-53h494.6l28.9 53 33.8 64h74L708.4 616zM512 389.6L613.7 576H410.3L512 389.6zM388.5 616H569L305.6 768.1 388.5 616z m-63.4 187l313.6-181.1L737.5 803H325.1z" p-id="4283" fill="#ffffff"></path></svg>
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
src/assets/svg/smscCdr.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1729046804258" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1511" width="200" height="200"><path d="M958.359001 286.941198c0-64.308655-52.132334-116.440989-116.440989-116.440989L181.453678 170.500209c-64.308655 0-116.440989 52.132334-116.440989 116.440989l0 448.63995c0 64.308655 52.132334 116.440989 116.440989 116.440989l660.464333 0c64.308655 0 116.440989-52.132334 116.440989-116.440989L958.359001 286.941198zM843.814198 212.455763c12.059664 0 23.444968 3.465938 33.519418 8.598842L530.749016 549.347606c-1.227967 1.161453-1.156336 0.916882-1.752924 1.868557-1.426489 1.067308-6.055926 3.922333-15.449877 3.922333-9.397021 0-14.025435-2.75474-15.4509-3.818979-0.676405-1.077541-0.662079-0.716314-1.995447-1.940189l-353.122503-324.412624c11.609409-7.557116 25.445532-12.509918 40.300868-12.509918L843.814198 212.456786zM916.403446 736.484727c0 40.857547-31.730679 73.582879-72.589248 73.582879L183.27721 810.067606c-40.85857 0-75.28566-32.725332-75.28566-73.582879L107.99155 287.657512c0-10.630105 2.860141-20.735253 6.909363-29.882588l351.486236 322.096882c4.91187 5.302773 19.479657 17.676591 47.009663 17.676591 27.799136 0 42.303478-12.618389 47.076178-17.830087l346.800517-328.899822c6.251378 10.860349 9.129938 23.433712 9.129938 36.838L916.403446 736.484727z" fill="#ffffff" p-id="1512"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
479
src/components/ExportCustomModal/index.vue
Normal file
@@ -0,0 +1,479 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:open="visible"
|
||||
:title="t('common.exportCustom')"
|
||||
width="750px"
|
||||
:confirm-loading="confirmLoading"
|
||||
@ok="handleOk"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<div class="export-custom-container">
|
||||
<!-- 列配置区域 -->
|
||||
<div class="columns-config">
|
||||
<div class="config-header">
|
||||
<h4>{{ t('common.exportColumns') }}</h4>
|
||||
<a-button type="link" @click="resetToDefault">
|
||||
{{ t('common.resetToDefault') }}
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<div class="columns-list">
|
||||
<Container
|
||||
@drop="onDrop"
|
||||
:get-child-payload="getChildPayload"
|
||||
drag-class="drag-ghost"
|
||||
drop-class="drop-ghost"
|
||||
drag-handle-selector=".drag-handle"
|
||||
:non-drag-area-selector="'.column-name, .ant-checkbox-wrapper'"
|
||||
>
|
||||
<Draggable
|
||||
v-for="(column, index) in customColumns"
|
||||
:key="column.key"
|
||||
class="column-item"
|
||||
>
|
||||
<div class="column-controls">
|
||||
<a-checkbox
|
||||
v-model:checked="column.visible"
|
||||
@change="updateColumnVisibility(column)"
|
||||
/>
|
||||
<div class="drag-handle">
|
||||
<HolderOutlined />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column-info">
|
||||
<div class="column-name">
|
||||
<a-input
|
||||
v-model:value="column.title"
|
||||
:placeholder="t('common.columnName')"
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<!-- 隐藏col_数字标签,不影响用户使用 -->
|
||||
<!-- <div class="column-key">
|
||||
<a-tag size="small" color="blue">{{ column.key }}</a-tag>
|
||||
</div> -->
|
||||
</div>
|
||||
</Draggable>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预览区域 -->
|
||||
<div class="preview-section">
|
||||
<h4>{{ t('common.preview') }}</h4>
|
||||
<div class="preview-table">
|
||||
<a-table
|
||||
:columns="previewColumns"
|
||||
:data-source="previewData"
|
||||
:pagination="false"
|
||||
size="small"
|
||||
:scroll="{ x: 400 }"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import { Modal, message } from 'ant-design-vue/es';
|
||||
import { Container, Draggable } from 'vue3-smooth-dnd';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
||||
|
||||
interface CustomColumn {
|
||||
key: string;
|
||||
title: string;
|
||||
visible: boolean;
|
||||
originalTitle: string;
|
||||
dataIndex?: string;
|
||||
customRender?: any;
|
||||
columnIndex?: number; // Excel列索引
|
||||
}
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
originalColumns: ColumnsType;
|
||||
sampleData: any[];
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:open', value: boolean): void;
|
||||
(e: 'confirm', config: CustomColumn[]): void;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const emit = defineEmits<Emits>();
|
||||
const { t } = useI18n();
|
||||
|
||||
const visible = ref(false);
|
||||
const confirmLoading = ref(false);
|
||||
const customColumns = ref<CustomColumn[]>([]);
|
||||
|
||||
// 监听props变化
|
||||
watch(() => props.open, (newVal) => {
|
||||
visible.value = newVal;
|
||||
if (newVal) {
|
||||
initCustomColumns();
|
||||
}
|
||||
});
|
||||
|
||||
watch(visible, (newVal) => {
|
||||
emit('update:open', newVal);
|
||||
});
|
||||
|
||||
// 初始化自定义列配置
|
||||
function initCustomColumns() {
|
||||
// 如果传入的是完整的列配置(包含columnIndex),直接使用
|
||||
if (props.originalColumns.length > 0 && (props.originalColumns[0] as any).columnIndex !== undefined) {
|
||||
const columns: CustomColumn[] = props.originalColumns.map(col => ({
|
||||
key: (col as any).key,
|
||||
title: (col as any).title,
|
||||
visible: true,
|
||||
originalTitle: (col as any).originalTitle || (col as any).title,
|
||||
dataIndex: (col as any).dataIndex,
|
||||
columnIndex: (col as any).columnIndex
|
||||
}));
|
||||
|
||||
// 尝试从本地存储加载配置
|
||||
const savedConfig = localStorage.getItem('sgwc-cdr-export-config');
|
||||
if (savedConfig) {
|
||||
try {
|
||||
const saved = JSON.parse(savedConfig);
|
||||
console.log('Loaded saved config:', saved);
|
||||
|
||||
// 基于originalTitle匹配保存的配置
|
||||
const mergedColumns = columns.map(col => {
|
||||
const savedCol = saved.find((s: any) => s.originalTitle === col.originalTitle);
|
||||
if (savedCol) {
|
||||
console.log(`Matched column: ${col.originalTitle}, visible: ${savedCol.visible}, title: ${savedCol.title}`);
|
||||
return {
|
||||
...col,
|
||||
visible: savedCol.visible !== undefined ? savedCol.visible : true,
|
||||
title: savedCol.title || col.title
|
||||
};
|
||||
}
|
||||
return col;
|
||||
});
|
||||
|
||||
// 按照保存的顺序排列(如果存在)
|
||||
const sortedColumns = sortColumnsByConfig(mergedColumns, saved);
|
||||
console.log('Final columns after merge and sort:', sortedColumns);
|
||||
customColumns.value = sortedColumns;
|
||||
} catch (error) {
|
||||
console.error('Failed to load saved export config:', error);
|
||||
customColumns.value = columns;
|
||||
}
|
||||
} else {
|
||||
console.log('No saved config found, using default columns');
|
||||
customColumns.value = columns;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 兼容旧的表格列配置
|
||||
const columns: CustomColumn[] = props.originalColumns
|
||||
.filter(col => col.key !== 'id' && (col as any).dataIndex) // 过滤掉操作列
|
||||
.map(col => ({
|
||||
key: col.key as string,
|
||||
title: col.title as string,
|
||||
visible: true,
|
||||
originalTitle: col.title as string,
|
||||
dataIndex: (col as any).dataIndex as string,
|
||||
customRender: (col as any).customRender
|
||||
}));
|
||||
|
||||
// 尝试从本地存储加载配置
|
||||
const savedConfig = localStorage.getItem('sgwc-cdr-export-config');
|
||||
if (savedConfig) {
|
||||
try {
|
||||
const saved = JSON.parse(savedConfig);
|
||||
// 合并保存的配置和当前列,只合并特定字段
|
||||
const mergedColumns = columns.map(col => {
|
||||
const savedCol = saved.find((s: CustomColumn) => s.key === col.key);
|
||||
if (savedCol) {
|
||||
return {
|
||||
...col,
|
||||
visible: savedCol.visible, // 只合并可见性
|
||||
title: savedCol.title !== savedCol.originalTitle ? savedCol.title : col.title // 只合并自定义的标题
|
||||
};
|
||||
}
|
||||
return col;
|
||||
});
|
||||
customColumns.value = mergedColumns;
|
||||
} catch (error) {
|
||||
console.error('Failed to load saved export config:', error);
|
||||
customColumns.value = columns;
|
||||
}
|
||||
} else {
|
||||
customColumns.value = columns;
|
||||
}
|
||||
}
|
||||
|
||||
// 按照保存的配置排序列
|
||||
function sortColumnsByConfig(columns: CustomColumn[], savedConfig: CustomColumn[]): CustomColumn[] {
|
||||
if (!savedConfig || savedConfig.length === 0) {
|
||||
return columns;
|
||||
}
|
||||
|
||||
// 创建一个映射:originalTitle -> savedOrder
|
||||
const orderMap = new Map<string, number>();
|
||||
savedConfig.forEach((col, index) => {
|
||||
orderMap.set(col.originalTitle, index);
|
||||
});
|
||||
|
||||
// 排序:已保存的列按保存顺序,新列放在最后
|
||||
return [...columns].sort((a, b) => {
|
||||
const orderA = orderMap.has(a.originalTitle) ? orderMap.get(a.originalTitle)! : 9999;
|
||||
const orderB = orderMap.has(b.originalTitle) ? orderMap.get(b.originalTitle)! : 9999;
|
||||
return orderA - orderB;
|
||||
});
|
||||
}
|
||||
|
||||
// 预览列配置
|
||||
const previewColumns = computed(() => {
|
||||
return customColumns.value
|
||||
.filter(col => col.visible)
|
||||
.map(col => ({
|
||||
title: col.title,
|
||||
dataIndex: col.dataIndex || col.key,
|
||||
key: col.key,
|
||||
customRender: col.customRender
|
||||
}));
|
||||
});
|
||||
|
||||
// 预览数据(只显示前2条,降低预览高度)
|
||||
const previewData = computed(() => {
|
||||
return props.sampleData.slice(0, 1);
|
||||
});
|
||||
|
||||
// 更新列可见性
|
||||
function updateColumnVisibility(column: CustomColumn) {
|
||||
// 确保至少有一列可见
|
||||
const visibleCount = customColumns.value.filter(col => col.visible).length;
|
||||
if (visibleCount === 0) {
|
||||
column.visible = true;
|
||||
message.warning(t('common.atLeastOneColumn'));
|
||||
}
|
||||
}
|
||||
|
||||
// 拖拽相关函数
|
||||
function getChildPayload(index: number) {
|
||||
return customColumns.value[index];
|
||||
}
|
||||
|
||||
function onDrop(dropResult: any) {
|
||||
const { removedIndex, addedIndex } = dropResult;
|
||||
if (removedIndex !== null && addedIndex !== null) {
|
||||
const item = customColumns.value[removedIndex];
|
||||
customColumns.value.splice(removedIndex, 1);
|
||||
customColumns.value.splice(addedIndex, 0, item);
|
||||
}
|
||||
}
|
||||
|
||||
// 重置为默认配置
|
||||
function resetToDefault() {
|
||||
Modal.confirm({
|
||||
title: t('common.confirm'),
|
||||
content: t('common.resetConfirm'),
|
||||
onOk() {
|
||||
// 清除本地存储的配置
|
||||
localStorage.removeItem('sgwc-cdr-export-config');
|
||||
// 重新初始化
|
||||
initCustomColumns();
|
||||
message.success(t('common.resetSuccess'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 确认导出
|
||||
function handleOk() {
|
||||
const visibleColumns = customColumns.value.filter(col => col.visible);
|
||||
if (visibleColumns.length === 0) {
|
||||
message.error(t('common.selectAtLeastOneColumn'));
|
||||
return;
|
||||
}
|
||||
|
||||
confirmLoading.value = true;
|
||||
|
||||
// 保存配置到本地存储
|
||||
try {
|
||||
// 保存时只保存必要的字段,用于下次加载时恢复配置
|
||||
const configToSave = customColumns.value.map((col, index) => ({
|
||||
originalTitle: col.originalTitle || col.title, // 用于匹配列
|
||||
title: col.title, // 自定义标题
|
||||
visible: col.visible, // 可见性
|
||||
order: index // 顺序
|
||||
}));
|
||||
localStorage.setItem('sgwc-cdr-export-config', JSON.stringify(configToSave));
|
||||
console.log('Export config saved:', configToSave);
|
||||
} catch (error) {
|
||||
console.error('Failed to save export config:', error);
|
||||
}
|
||||
|
||||
// 延迟一下让用户看到loading状态
|
||||
setTimeout(() => {
|
||||
emit('confirm', customColumns.value);
|
||||
confirmLoading.value = false;
|
||||
visible.value = false;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// 取消
|
||||
function handleCancel() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.open) {
|
||||
initCustomColumns();
|
||||
}
|
||||
});
|
||||
|
||||
// 调试功能:清除有问题的缓存
|
||||
function clearProblematicCache() {
|
||||
localStorage.removeItem('sgwc-cdr-export-config');
|
||||
console.log('Cleared problematic cache');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.export-custom-container {
|
||||
.columns-config {
|
||||
margin-bottom: 12px;
|
||||
|
||||
.config-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
h4 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.columns-list {
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 6px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
|
||||
.column-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 10px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.column-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 12px;
|
||||
|
||||
.drag-handle {
|
||||
margin-left: 8px;
|
||||
cursor: grab;
|
||||
color: #999;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
&:active {
|
||||
cursor: grabbing;
|
||||
color: #0050b3;
|
||||
background-color: #e6f7ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.column-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
pointer-events: auto;
|
||||
cursor: default;
|
||||
|
||||
.column-name {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.column-key {
|
||||
display: none; // 隐藏标签
|
||||
}
|
||||
}
|
||||
|
||||
// 禁止复选框触发拖拽
|
||||
:deep(.ant-checkbox-wrapper) {
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preview-section {
|
||||
h4 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.preview-table {
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
max-height: 180px;
|
||||
|
||||
:deep(.ant-table-wrapper) {
|
||||
.ant-table {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-table-thead > tr > th {
|
||||
padding: 8px 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-table-tbody > tr > td {
|
||||
padding: 6px 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-table-body {
|
||||
max-height: 120px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 拖拽样式
|
||||
.drag-ghost {
|
||||
opacity: 0.5;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.drop-ghost {
|
||||
background: #e6f7ff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||
import { message } from 'ant-design-vue/es';
|
||||
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||
import { FitAddon } from '@xterm/addon-fit';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import '@xterm/xterm/css/xterm.css';
|
||||
@@ -31,8 +32,91 @@ const terminalDom = ref<HTMLElement | undefined>(undefined);
|
||||
/**终端输入实例对象 */
|
||||
const terminal = ref<any>(null);
|
||||
|
||||
/**终端输入命令 */
|
||||
const terminalCmd = ref<string>('');
|
||||
/**终端输入文字状态 */
|
||||
const terminalState = reactive<{
|
||||
/**输入值 */
|
||||
text: string;
|
||||
/**历史 */
|
||||
history: {
|
||||
label?: string;
|
||||
value: string;
|
||||
}[];
|
||||
}>({
|
||||
text: '',
|
||||
history: [
|
||||
{
|
||||
value: 'info server',
|
||||
},
|
||||
{
|
||||
value: 'info replication',
|
||||
},
|
||||
{
|
||||
value: 'keys ausf:*',
|
||||
},
|
||||
{
|
||||
value: 'quit',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
/**自动完成根据输入项进行筛选 */
|
||||
function fnAutoCompleteFilter(input: string, option: any) {
|
||||
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
}
|
||||
|
||||
/**自动完成按键触发 */
|
||||
function fnAutoCompleteKeydown(evt: KeyboardEvent) {
|
||||
if (evt.key === 'Enter') {
|
||||
// 阻止默认的换行行为
|
||||
evt.preventDefault();
|
||||
// 按下 Shift + Enter 键时换行
|
||||
if (evt.shiftKey && evt.target) {
|
||||
// 插入换行符
|
||||
const textarea = evt.target as HTMLInputElement;
|
||||
const start = textarea.selectionStart || 0;
|
||||
const end = textarea.selectionEnd || 0;
|
||||
const text = textarea.value;
|
||||
textarea.value = text.substring(0, start) + '\n' + text.substring(end);
|
||||
terminalState.text = textarea.value;
|
||||
// 更新光标位置
|
||||
textarea.selectionStart = textarea.selectionEnd = start + 1;
|
||||
} else {
|
||||
// ws未连接
|
||||
if (ws.state() !== WebSocket.OPEN) {
|
||||
message.error('disconnected');
|
||||
return;
|
||||
}
|
||||
|
||||
// 输入历史
|
||||
const cmdStr = terminalState.text.trim().replace(/\n/g, '\r\n');
|
||||
const hisIndex = terminalState.history.findIndex(
|
||||
item => item.value === cmdStr
|
||||
);
|
||||
if (hisIndex === -1) {
|
||||
terminalState.history.push({
|
||||
value: cmdStr,
|
||||
});
|
||||
}
|
||||
|
||||
// 发送文本
|
||||
terminal.value.scrollToBottom();
|
||||
terminal.value.writeln('\r\n> ' + cmdStr);
|
||||
ws.send({
|
||||
requestId: `redis_${props.hostId}`,
|
||||
type: 'redis',
|
||||
data: `${cmdStr}\r\n`,
|
||||
});
|
||||
terminalState.text = '';
|
||||
|
||||
// 退出登录
|
||||
if (['q', 'quit', 'exit'].includes(cmdStr)) {
|
||||
setTimeout(() => {
|
||||
ws.close();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**终端输入渲染 */
|
||||
function handleRanderXterm(container: HTMLElement | undefined) {
|
||||
@@ -49,47 +133,13 @@ function handleRanderXterm(container: HTMLElement | undefined) {
|
||||
scrollback: 1000,
|
||||
scrollSensitivity: 15,
|
||||
tabStopWidth: 4,
|
||||
disableStdin: false, // 禁止输入
|
||||
disableStdin: true, // 禁止输入
|
||||
});
|
||||
// 挂载
|
||||
xterm.open(container);
|
||||
// 自适应尺寸
|
||||
const fitAddon = new FitAddon();
|
||||
xterm.loadAddon(fitAddon);
|
||||
// 终端输入字符按键监听
|
||||
xterm.onKey(({ key, domEvent }) => {
|
||||
// console.log(key, domEvent);
|
||||
// 单键输入
|
||||
switch (domEvent.key) {
|
||||
case 'Enter':
|
||||
const cmdStr = terminalCmd.value.trim();
|
||||
// 发送文本
|
||||
terminal.value.scrollToBottom();
|
||||
terminal.value.writeln('\r\n');
|
||||
ws.send({
|
||||
requestId: `redis_${props.hostId}`,
|
||||
type: 'redis',
|
||||
data: `${cmdStr}\r\n`,
|
||||
});
|
||||
terminalCmd.value = '';
|
||||
|
||||
// 退出登录
|
||||
if ('quit' === cmdStr) {
|
||||
setTimeout(() => {
|
||||
ws.close();
|
||||
}, 1000);
|
||||
}
|
||||
break;
|
||||
case 'Backspace':
|
||||
// 处理退格键,删除最后一个字符
|
||||
xterm.write('\b \b');
|
||||
break;
|
||||
default:
|
||||
xterm.write(key);
|
||||
terminalCmd.value += key;
|
||||
return;
|
||||
}
|
||||
});
|
||||
// 创建 ResizeObserver 实例
|
||||
var observer = new ResizeObserver(entries => {
|
||||
fitAddon.fit();
|
||||
@@ -213,7 +263,21 @@ defineExpose({
|
||||
|
||||
<template>
|
||||
<div class="terminal">
|
||||
<div ref="terminalDom" :id="id" class="terminal"></div>
|
||||
<div ref="terminalDom" style="height: calc(100% - 36px)" :id="id"></div>
|
||||
<a-auto-complete
|
||||
v-model:value="terminalState.text"
|
||||
:dropdown-match-select-width="500"
|
||||
style="width: 100%"
|
||||
:options="terminalState.history"
|
||||
:filter-option="fnAutoCompleteFilter"
|
||||
:defaultActiveFirstOption="false"
|
||||
>
|
||||
<a-textarea
|
||||
:auto-size="{ minRows: 1, maxRows: 6 }"
|
||||
placeholder="Execute command. Shift+Enter to line feed, Enter to send"
|
||||
@keypress="fnAutoCompleteKeydown"
|
||||
/>
|
||||
</a-auto-complete>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -80,16 +80,16 @@ function fnAutoCompleteFilter(input: string, option: any) {
|
||||
}
|
||||
|
||||
/**自动完成按键触发 */
|
||||
function fnAutoCompleteKeydown(evt: any) {
|
||||
function fnAutoCompleteKeydown(evt: KeyboardEvent) {
|
||||
if (evt.key === 'Enter') {
|
||||
// 阻止默认的换行行为
|
||||
evt.preventDefault();
|
||||
// 按下 Shift + Enter 键时换行
|
||||
if (evt.shiftKey) {
|
||||
if (evt.shiftKey && evt.target) {
|
||||
// 插入换行符
|
||||
const textarea = evt.target;
|
||||
const start = textarea.selectionStart;
|
||||
const end = textarea.selectionEnd;
|
||||
const textarea = evt.target as HTMLInputElement;
|
||||
const start = textarea.selectionStart || 0;
|
||||
const end = textarea.selectionEnd || 0;
|
||||
const text = textarea.value;
|
||||
textarea.value = text.substring(0, start) + '\n' + text.substring(end);
|
||||
terminalState.text = textarea.value;
|
||||
@@ -121,7 +121,7 @@ function fnAutoCompleteKeydown(evt: any) {
|
||||
type: 'telnet',
|
||||
data: `${cmdStr}\r\n`,
|
||||
});
|
||||
terminalState.text = ' ';
|
||||
terminalState.text = '';
|
||||
|
||||
// 退出登录
|
||||
if (['q', 'quit', 'exit'].includes(cmdStr)) {
|
||||
@@ -296,11 +296,12 @@ defineExpose({
|
||||
style="width: 100%"
|
||||
:options="terminalState.history"
|
||||
:filter-option="fnAutoCompleteFilter"
|
||||
@keydown="fnAutoCompleteKeydown"
|
||||
:defaultActiveFirstOption="false"
|
||||
>
|
||||
<a-textarea
|
||||
:auto-size="{ minRows: 1, maxRows: 6 }"
|
||||
placeholder="Execute command. Shift+Enter to line feed, Enter to send"
|
||||
@keypress="fnAutoCompleteKeydown"
|
||||
/>
|
||||
</a-auto-complete>
|
||||
</div>
|
||||
|
||||
@@ -3,3 +3,6 @@ export const ADMIN_ROLE_KEY = 'system';
|
||||
|
||||
/**系统管理员-系统指定权限 */
|
||||
export const ADMIN_PERMISSION = '*:*:*';
|
||||
|
||||
/**次级系统管理员 */
|
||||
export const TENANTADMIN_ROLE_KEY = 'admin';
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**会话缓存-接口加密 */
|
||||
export const CACHE_SESSION_CRYPTO_API = 'cache:session:cryptoApi';
|
||||
|
||||
/**会话缓存-网络请求 */
|
||||
export const CACHE_SESSION_FATCH = 'cache:session:fatch';
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ export const NE_TYPE_LIST = [
|
||||
'IMS',
|
||||
'AMF',
|
||||
'AUSF',
|
||||
'UDR',
|
||||
'UDM',
|
||||
'SMF',
|
||||
'PCF',
|
||||
@@ -19,6 +20,8 @@ export const NE_TYPE_LIST = [
|
||||
'SMSF',
|
||||
'CBC',
|
||||
'CHF',
|
||||
'HLR',
|
||||
'SGWC',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
47
src/hooks/useRangePicker.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
/**日期快捷选择 */
|
||||
export function dayjsRanges() {
|
||||
return [
|
||||
{
|
||||
label: 'Today',
|
||||
value: [dayjs().startOf('day'), dayjs()],
|
||||
},
|
||||
{
|
||||
label: 'Last 1 hour',
|
||||
value: [
|
||||
dayjs().subtract(1, 'hour').startOf('hour'),
|
||||
dayjs().subtract(1, 'hour').endOf('hour'),
|
||||
],
|
||||
},
|
||||
// {
|
||||
// label: 'Last 3 hour',
|
||||
// value: [dayjs().subtract(3, 'hours'), dayjs()],
|
||||
// },
|
||||
// {
|
||||
// label: 'Last 6 hour',
|
||||
// value: [dayjs().subtract(6, 'hours'), dayjs()],
|
||||
// },
|
||||
{
|
||||
label: 'Last 1 day',
|
||||
value: [
|
||||
dayjs().subtract(1, 'day').startOf('day'),
|
||||
dayjs().subtract(1, 'day').endOf('day'),
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Last 7 day',
|
||||
value: [
|
||||
dayjs().subtract(7, 'day').startOf('day'),
|
||||
dayjs().subtract(1, 'day').endOf('day'),
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Last 15 day',
|
||||
value: [
|
||||
dayjs().subtract(15, 'day').startOf('day'),
|
||||
dayjs().subtract(1, 'day').endOf('day'),
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -10,13 +10,14 @@ export default {
|
||||
desc: 'Core Network Management Platform',
|
||||
loading: 'Please wait...',
|
||||
inputPlease: 'Please input',
|
||||
searchPlease: 'Search menus...',
|
||||
searchTip: 'Enter keywords to search menus',
|
||||
selectPlease: 'please select',
|
||||
tipTitle: 'Prompt',
|
||||
msgSuccess: 'Success {msg}',
|
||||
errorFields: 'Please fill in the required information in {num} correctly!',
|
||||
tablePaginationTotal: 'Total {total} items',
|
||||
noData: "No Data",
|
||||
zebra:'Tabular zebra pattern',
|
||||
ok: 'Ok',
|
||||
cancel: 'Cancel',
|
||||
close: 'Close',
|
||||
@@ -29,6 +30,7 @@ export default {
|
||||
editText: 'Edit',
|
||||
deleteText: 'Delete',
|
||||
downloadText: 'Download',
|
||||
CloudServerText:'Sync',
|
||||
import:'Import',
|
||||
export:'Export',
|
||||
uploadText: 'Upload',
|
||||
@@ -39,6 +41,11 @@ export default {
|
||||
columnSetText: 'Column Setting',
|
||||
columnSetTitle: 'Column Display / Sorting',
|
||||
sizeText: 'Density',
|
||||
preview:'Preview',
|
||||
exportCustom:'Custom Export',
|
||||
exportColumns:'Column Definition',
|
||||
resetToDefault:'Reset to default columns',
|
||||
exportDefault:'Export',
|
||||
size: {
|
||||
default: 'Default',
|
||||
middle: 'Medium',
|
||||
@@ -131,7 +138,7 @@ export default {
|
||||
},
|
||||
LockScreen: {
|
||||
inputPlacePwd:'Lock Screen Password',
|
||||
validSucc:'Validation Passed',
|
||||
enter:'Enter',
|
||||
validError:'Validation Failure',
|
||||
backLogin:'Logout to Relogin',
|
||||
backReload:'Restarting now, please wait...',
|
||||
@@ -143,7 +150,7 @@ export default {
|
||||
|
||||
// 静态路由
|
||||
router: {
|
||||
index: "Home",
|
||||
index: "Overview",
|
||||
login: "Sign In",
|
||||
register: 'Registrations',
|
||||
page403: 'No Access',
|
||||
@@ -222,12 +229,11 @@ export default {
|
||||
capability: 'Capability',
|
||||
serialNum: 'Serial Number',
|
||||
expiryDate: 'Expiry Date',
|
||||
neStatus: 'NE status is abnormal',
|
||||
runStatus:'Running Status',
|
||||
mark:'Brief Information',
|
||||
neStatus: 'Status Abnormal',
|
||||
runStatus: 'Runing Status',
|
||||
mark:'Information',
|
||||
object:'Object',
|
||||
versionNum:'Version',
|
||||
systemStatus:'Status',
|
||||
realNeStatus:'Status',
|
||||
reloadTime:'Refresh Time',
|
||||
Critical:'Critical',
|
||||
@@ -255,12 +261,16 @@ export default {
|
||||
login: {
|
||||
tabPane1: 'Account password login',
|
||||
tabPane2: 'Login with phone number',
|
||||
registerBtn: 'Register an account',
|
||||
registerBtn: 'Register Account',
|
||||
loginBtn: 'Sign In',
|
||||
loginSuccess: 'Login Successful',
|
||||
loginMethod: 'Other login methods:',
|
||||
loginMethodWX: 'WeChat Scan Login',
|
||||
loginMethodQQ: 'QQ Scan Code Login',
|
||||
otherMethod: 'Other Methods',
|
||||
backBtn: 'Back',
|
||||
backBtnLogin: 'Return Login',
|
||||
authorizedNotfound: 'Authorized Not Found',
|
||||
authorizedFailed: 'Authorized Failed',
|
||||
authorizedSuccess: 'Authorized Successful',
|
||||
redirectHome: 'Redirect to home page in {i} seconds',
|
||||
},
|
||||
register: {
|
||||
registerBtn: 'Register',
|
||||
@@ -341,7 +351,7 @@ export default {
|
||||
profile: {
|
||||
phonenumber: "Phone",
|
||||
email: "Email",
|
||||
deptName: "Class",
|
||||
deptName: "Department",
|
||||
postGroup: "Possession of posts",
|
||||
roleGroup: "Ownership",
|
||||
loginIp: "Log in",
|
||||
@@ -351,199 +361,39 @@ export default {
|
||||
description: "No data yet, try refreshing",
|
||||
},
|
||||
},
|
||||
configManage: {
|
||||
neManage: {
|
||||
addNe:'Add Network Element',
|
||||
delSure:'Confirm deleting the data item with network element name {msg}',
|
||||
editNe:'Edit Network Element',
|
||||
exportSure:'Confirm exporting the configuration information with the network element name {msg}',
|
||||
exportTip:'Export successful, please go to backup management for download',
|
||||
getInfo:'Failed to get network element information',
|
||||
neType:'NE Type',
|
||||
neTypePlease: 'Select network element type',
|
||||
neId:'NE ID',
|
||||
neName:'NE Name',
|
||||
neTypeTip:'Fill in the type of network element created, such as:SMF',
|
||||
uid:'RM UID',
|
||||
uidTip:'Please enter a unique resource identifier',
|
||||
ip:'IP Address',
|
||||
mac:'NE MAC address',
|
||||
macTip:'Able to locate the physical address (MAC) of the network element',
|
||||
port:'Port',
|
||||
portTip:'Maximum range 0~65535',
|
||||
pvflag:'PV Flag',
|
||||
pnf:'Physical Network Element',
|
||||
vnf:'Virtual Network Element',
|
||||
province:'Region',
|
||||
vendorName:'Vendor Name',
|
||||
dn:'Network Identification',
|
||||
reload: 'Reload',
|
||||
restart: 'Restart',
|
||||
totalSure:'Confirm the network element with {operator} network element name {msg}',
|
||||
stop: 'Stop',
|
||||
start: 'Start',
|
||||
log: 'Logs',
|
||||
export: 'Export',
|
||||
import: 'Import',
|
||||
fileForm:'File Source',
|
||||
selectPlease:'Please select the source of the import file',
|
||||
server:'Server File',
|
||||
local:'Local File',
|
||||
fileSelect:'Please select the current import file',
|
||||
sync:'Synchronize to NE',
|
||||
open:'Open',
|
||||
close:'Close',
|
||||
addFail:'Add failed',
|
||||
operFail:'Operation Failed'
|
||||
},
|
||||
backupManage: {
|
||||
setBackupTask: 'Set automatic backup time',
|
||||
neTypePlease: 'Query network element type',
|
||||
neType: 'NE Type',
|
||||
neID: 'NE ID',
|
||||
fileName: 'File Name',
|
||||
createAt: 'Create at',
|
||||
remark:'Remark',
|
||||
edit:'Edit Backup File',
|
||||
totalSure:'Confirm that {oper} records item number {id}?',
|
||||
},
|
||||
softwareManage: {
|
||||
sendBtn: 'Distribute',
|
||||
runBtn: 'Activate',
|
||||
backBtn: 'Rollback',
|
||||
historyBtn: 'Distribution Record',
|
||||
neTypePlease: 'Select network element type',
|
||||
neType: 'NE Type',
|
||||
fileName: 'File Name',
|
||||
version: 'Version',
|
||||
versionPlease: 'Version number cannot be empty',
|
||||
updateTime: 'Uploaded Time',
|
||||
description: 'Description',
|
||||
deleteTip: 'Are you sure to delete the data item with software [{fileName}]?',
|
||||
downloadTip: 'Are you sure to download the data item with software [{fileName}]?',
|
||||
updateComment: 'Comment',
|
||||
updateCommentPlease: 'Please enter the software description',
|
||||
updateFile: 'Software File',
|
||||
updateFilePlease: 'Please upload the updated software file',
|
||||
verifyFile: 'Verify File',
|
||||
selectFile: 'SELECT FILE',
|
||||
sendTitle: 'Distribute software version',
|
||||
sendContent: 'Are you sure to send the file with the software package [{fileName}] to the corresponding network element?',
|
||||
runTitle: 'Activate software version',
|
||||
runContent: 'Are you sure to activate the software version of [{fileName}] that has been issued to the corresponding network element?',
|
||||
backTitle: 'Fallback software version',
|
||||
backContent: 'Confirm that the software version of [{fileName}] has been issued for the corresponding network element rollback?',
|
||||
neId: 'Corresponding network element',
|
||||
neIdPlease: 'Please select the corresponding network element',
|
||||
versions:'Version',
|
||||
upVersions:'Version before upgrade',
|
||||
backVersions:'Version before rollback',
|
||||
status:'Status',
|
||||
letUpTime:'Activation time',
|
||||
createTime:'Creation time',
|
||||
onlyAble:'Only upload file format {fileText} is supported',
|
||||
nullVersion:'There is no rollback version for the current network element.',
|
||||
},
|
||||
license: {
|
||||
neTypePlease: 'Select network element type',
|
||||
neType: 'NE Type',
|
||||
serialNum: 'Serial Num',
|
||||
createTime: 'Time',
|
||||
comment: 'Description',
|
||||
updateComment: 'License Description',
|
||||
updateCommentPlease: 'Please enter a license description',
|
||||
updateFile: 'License File',
|
||||
updateFilePlease: 'Please upload and update the License file',
|
||||
selectFile: 'SELECT FILE',
|
||||
neId: 'NE ID',
|
||||
neIdPlease: 'Please select the corresponding network element',
|
||||
},
|
||||
configParam:{
|
||||
dataNull:'No configuration item data yet',
|
||||
editSuss:'Modification successful',
|
||||
editFail:'Edit failed',
|
||||
Unable:'Illegal operation of attribute value',
|
||||
delSure:'Confirm to delete the data item with Index [{value}]?',
|
||||
addSuss:'Add successfully',
|
||||
addFail:'Add failed',
|
||||
delArraySure:'Confirm to delete the data item with {arrayChildTitle} Index as [{value}]?',
|
||||
parUnable:'The parameter value is not within the reasonable range',
|
||||
ipv4Tip:'Not a legal IPV4 address',
|
||||
ipv6Tip:'Not a legal IPV6 address',
|
||||
enumTip:'Not a reasonable enumeration value',
|
||||
boolTip:'Not a reasonable Boolean value',
|
||||
default:'The input value is of unknown type',
|
||||
reloadSuss:'Network element reloading completed',
|
||||
reloadFail:'Network element reloading failed',
|
||||
neNUll:'No network element list data yet',
|
||||
reload:'Reload',
|
||||
post:'Submit',
|
||||
editSure:'Are you sure you want to update this attribute value? ',
|
||||
arraryEdit:'Are you sure to submit the record whose updated Index is [{value}]? ',
|
||||
addSure:'Are you sure to submit the new record of Index: [{value}]? '
|
||||
},
|
||||
configParamForm: {
|
||||
treeTitle: "Navigation Configuration",
|
||||
treeSelectTip: "Select configuration item information in the left configuration navigation!",
|
||||
neType: 'NE Type',
|
||||
neTypePleace: "Please select the network element type",
|
||||
noConfigData: "No data on configuration items",
|
||||
updateValue: "[ {num} ] parameter value modified successfully.",
|
||||
updateValueErr: "Attribute value modification failure",
|
||||
updateItem: "Modify Index to {num}.",
|
||||
updateItemErr: "Record modification failure",
|
||||
delItemOk: "Deleting Index as {num} succeeded",
|
||||
addItemOk: "Add Index as {num} Record Succeeded",
|
||||
addItemErr: "Record addition failure",
|
||||
requireUn: "[ {display} ] input value is of unknown type",
|
||||
requireString: "[ {display} ] parameter value is invalid.",
|
||||
requireInt: "[ {display} ] parameter value not in reasonable range {filter}",
|
||||
requireIpv4: "[ {display} ] not a legitimate IPV4 address",
|
||||
requireIpv6: "[ {display} ] not a legitimate IPV6 address.",
|
||||
requireEnum: "[ {display} ] is not a reasonable enumeration value.",
|
||||
requireBool: "[ {display} ] is not a reasonable boolean value.",
|
||||
editOkTip: "Confirm updating the value of this [ {num} ] attribute?",
|
||||
updateItemTip: "Confirm updating the data item with Index [{num}]?",
|
||||
delItemTip: "Confirm deleting the data item with Index [{num}]?",
|
||||
arrayMore: "Expand",
|
||||
ptDiff: 'Comparison Example',
|
||||
ptDiffExample: 'Example Configuration',
|
||||
ptDiffSelf: 'Current Individuals',
|
||||
ptDiffLoad: 'Load More',
|
||||
ptDiffMerge: 'Comparative Differences',
|
||||
ptDiffRest: 'Restore this version',
|
||||
ptHistory: 'History',
|
||||
ptReset: 'Reset To Example',
|
||||
ptResetTip: 'Confirmed to reset to the sample configuration?',
|
||||
ptLoad: 'Load Current Configuration',
|
||||
ptLoadTip: 'Confirm that you want to load the current network element configuration?',
|
||||
ptExport: "Export Excel",
|
||||
ptExportTip: "Confirm that you want to export the network element configuration data to an Excel file?",
|
||||
ptExportAll: "导出所有学生配置",
|
||||
ptApplyShow: 'View Student',
|
||||
ptApply: 'request',
|
||||
ptApplyNE: 'Application To NE',
|
||||
ptApplyStu: 'Application To {ne}',
|
||||
ptApplyStuTip: 'Confirm that you want to initiate a Configure Application to {ne} request to the teacher?',
|
||||
ptApplyStuRack: 'Return Request',
|
||||
ptApplyStuNE: 'Application Request',
|
||||
},
|
||||
},
|
||||
dashboard: {
|
||||
overview:{
|
||||
title: "Core Network Dashboard",
|
||||
fullscreen: "Click on the full-screen display",
|
||||
fullscreen: "Full Screen Display",
|
||||
toRouter: "Click to jump to the detail page",
|
||||
Users:"UDM Subscription Data",
|
||||
VoNR:"IMS Online Users",
|
||||
sessions:"PDU Sessions in SMF",
|
||||
FivegNodeN:"Online gNB in AMF",
|
||||
Fiveusers:"Active users in AMF",
|
||||
FourgNodeN:"Online eNB in MME",
|
||||
Fourusers:"Active users in MME",
|
||||
UPFjump:"Key Performance Indicators",
|
||||
Networkjump:"5GC System Architecture",
|
||||
Alarmjump:"Active Alarms",
|
||||
IMSUsers:"UDM IMS User Data",
|
||||
VoIPUsers:"UDM VoIP User Data",
|
||||
skim: {
|
||||
users: "Users",
|
||||
userTitle:'User Information',
|
||||
users: "Total Subscriber Base",
|
||||
userTitle:'Subscriber Information',
|
||||
imsUeNum: "VoNR/VoLTE",
|
||||
smfUeNum: "Data Sessions",
|
||||
smfUeNum: "User Sessions",
|
||||
gnbBase: "Online gNodeB",
|
||||
gnbSumBase: "Total gNodeB",
|
||||
enbBase: "Online eNodeB",
|
||||
enbSumBase: "Total eNodeB",
|
||||
gnbUeNum:'5G Active Users',
|
||||
enbUeNum:'4G Active Users',
|
||||
baseTitle:'Online Information',
|
||||
nodeBInfo: 'NodeB Information',
|
||||
onlineinfo:'UE Online Information',
|
||||
ims:'VoLTE',
|
||||
voip:'VoIP'
|
||||
},
|
||||
upfFlow:{
|
||||
title: "UPF Throughput",
|
||||
@@ -573,6 +423,7 @@ export default {
|
||||
},
|
||||
userActivity: {
|
||||
title: "User Activity",
|
||||
imsTitle: "IMS Activity",
|
||||
type: "Type",
|
||||
duration: "Duration",
|
||||
caller: "Caller",
|
||||
@@ -591,23 +442,32 @@ export default {
|
||||
rowInfo: "Info",
|
||||
type: "Type",
|
||||
duration: "Duration",
|
||||
mosAverage: "MOS",
|
||||
callConnectionTime: "Call Connection Time",
|
||||
seizureTime: "Call Start Time",
|
||||
releaseTime: "Hangup Time",
|
||||
caller: "Caller",
|
||||
called: "Called",
|
||||
result: "Result",
|
||||
resultCode: "Result Code",
|
||||
resultCause: "Result Cause",
|
||||
resultOk: "Success",
|
||||
resultFail: "Fail",
|
||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
|
||||
smfChargingID: 'Charging ID',
|
||||
tenantName: "Tenant Name",
|
||||
exportTip: "Do you confirm to export the current query conditions of the CDR data?",
|
||||
chargingID: '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',
|
||||
durationTime: 'Duration',
|
||||
invocationTime: 'Invocation Time',
|
||||
sgwcServedIMSI: 'IMSI',
|
||||
sgwcServedMSISDN: 'MSISDN',
|
||||
sgwcVolumeGPRSUplink: 'GPRS Uplink',
|
||||
sgwcVolumeGPRSDownlink: 'GPRS Downlink',
|
||||
},
|
||||
ue: {
|
||||
eventType: "Event Type",
|
||||
@@ -619,7 +479,7 @@ export default {
|
||||
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.)",
|
||||
exportTip: "Do you confirm to export the event data of the current query condition?",
|
||||
},
|
||||
},
|
||||
ne: {
|
||||
@@ -642,6 +502,8 @@ export default {
|
||||
portTip: "Network element port default:33030",
|
||||
serialNum: 'Serial Number',
|
||||
expiryDate: 'Expiry Date',
|
||||
ueNumber: 'UE Number',
|
||||
nbNumber: 'Radio Number',
|
||||
normalcy: 'Normal',
|
||||
exceptions: 'Abnormal',
|
||||
restart: 'Restart',
|
||||
@@ -679,7 +541,7 @@ export default {
|
||||
delTip: 'Confirm deletion of network element information data items?',
|
||||
oam: {
|
||||
title: 'OAM Configuration',
|
||||
sync: 'Sync to NE',
|
||||
restart: 'Restart NE',
|
||||
oamEnable: 'Service',
|
||||
oamPort: 'Port',
|
||||
snmpEnable: 'Service',
|
||||
@@ -782,14 +644,15 @@ export default {
|
||||
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',
|
||||
noPath: 'Package File Not Found',
|
||||
},
|
||||
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?",
|
||||
reloadBatch: "Refresh License Status",
|
||||
reloadBatchTip: "Do you perform a license status information refresh for the current list of NE?",
|
||||
updateTtile: "Update License",
|
||||
downCodeTop: "Confirmed to save the license activation code to a file?",
|
||||
activationRequestCode: "License Activation Code",
|
||||
@@ -805,7 +668,9 @@ export default {
|
||||
treeSelectTip: "Select configuration item information in the left configuration navigation!",
|
||||
neType: 'NE Type',
|
||||
neTypePleace: "Please select the network element type",
|
||||
neIdSyncPleace: "Please select the synchronized network element",
|
||||
noConfigData: "No data on configuration items",
|
||||
noConfigdDisabled: "The configuration item is not normal",
|
||||
updateValue: "[ {num} ] parameter value modified successfully.",
|
||||
updateValueErr: "Attribute value modification failure",
|
||||
updateItem: "Modify Index to {num}.",
|
||||
@@ -829,6 +694,19 @@ export default {
|
||||
name: "Name",
|
||||
downTip: 'Confirmed to download the backup file [{txt}]?',
|
||||
title: "Modify Backup {txt}",
|
||||
backupModal: {
|
||||
pushFileOper: "Send Current File To Remote Backup",
|
||||
title: "Setting Remote Backup Service",
|
||||
enable: "Enable",
|
||||
toIp: "Service IP",
|
||||
toIpPleace: "Please input the remote backup server IP address",
|
||||
toPort: "Service Port",
|
||||
username: "UserName",
|
||||
usernamePleace: 'Please enter the service login username',
|
||||
password: "Password",
|
||||
dir: "Save Dir",
|
||||
dirPleace: 'Please enter the service address target file directory',
|
||||
}
|
||||
},
|
||||
neQuickSetup: {
|
||||
reloadPara5G: 'Reload',
|
||||
@@ -866,7 +744,7 @@ export default {
|
||||
installSourceUpload: 'New Upload',
|
||||
installSelect: 'Select Record',
|
||||
installUpload: 'Upload File',
|
||||
installText: 'Installed',
|
||||
installText: 'Install',
|
||||
licenseTitle: "Licenses",
|
||||
licenseDesc: "Network element service authorization certification",
|
||||
licenseResultTitle: "Whether to authorize activation immediately",
|
||||
@@ -879,9 +757,61 @@ export default {
|
||||
licenseTip2: '2. Clicking [Finish] will end the installation process.',
|
||||
},
|
||||
},
|
||||
neData: {
|
||||
common: {
|
||||
startIMSI: 'Starting IMSI',
|
||||
imsi: 'IMSI',
|
||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||
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.',
|
||||
imsiPlease: "Please enter IMSI correctly",
|
||||
msisdn: 'Mobile Customer Identification Number',
|
||||
msisdnPlease: "Please enter the Mobile Customer Identification Number correctly",
|
||||
loadDataConfirm: 'Confirmed to reload data?',
|
||||
loadData: 'Load Data',
|
||||
loadDataTip: 'Successfully fetched loaded data: {num} items, the system is internally updating the data, it will take about {timer} seconds, please wait!!!!!.',
|
||||
batchOper: 'Batch Operation',
|
||||
batchAddText: 'Batch Addition',
|
||||
batchDelText: 'Batch Deletion',
|
||||
batchUpdateText: 'Batch Update',
|
||||
batchNum: 'Number of releases',
|
||||
checkDel:'Check Delete',
|
||||
importTemplate: 'Download Template',
|
||||
},
|
||||
baseStation: {
|
||||
list: "List",
|
||||
topology: "Topology",
|
||||
nbName: "RAN Node Name",
|
||||
nbId: "RAN Node ID",
|
||||
ueNum: "UE Number",
|
||||
topologyTitle: "Radio State Graph",
|
||||
name: "Name",
|
||||
namePlease: "text content length 0~64",
|
||||
position: "Position",
|
||||
positionPlease: "location description. Prohibition of spaces, length of text content 0-64",
|
||||
address: "IP Address",
|
||||
addressPlease: "text content length 0~64",
|
||||
state: "State",
|
||||
online: "Online",
|
||||
offline: "Offline",
|
||||
time: "Change Time",
|
||||
addRadio: "Add Radio Info",
|
||||
editRadio: "Edit Radio Info",
|
||||
history: "Status History",
|
||||
exportTip: "Confirm exporting xlsx table files based on search criteria?",
|
||||
importDataEmpty: "Imported data is empty",
|
||||
},
|
||||
backupData: {
|
||||
auth: "UDM Authentication",
|
||||
sub: "UDM Subscribers",
|
||||
voip: "VoIP Authentication",
|
||||
volte: "IMS Subscribers",
|
||||
}
|
||||
},
|
||||
neUser: {
|
||||
auth: {
|
||||
authInfo:' Authentication Info',
|
||||
authInfo:' Authentication of Info',
|
||||
neTypePlease: 'Query network element Object',
|
||||
neType: 'UDM Object',
|
||||
export: 'Export',
|
||||
@@ -889,13 +819,14 @@ export default {
|
||||
checkExport : 'Check Export',
|
||||
checkExportConfirm: 'Confirm exporting the checked authenticated user data?',
|
||||
import: 'Import',
|
||||
importFail: 'Failure Record',
|
||||
loadDataConfirm: 'Are you sure you want to reload the data?',
|
||||
loadData: 'Load Data',
|
||||
loadDataTip: 'Successfully fetched loaded data: {num} items, the system is internally updating the data, it will take about {timer} seconds, please wait!!!!!.',
|
||||
startIMSI: 'Start IMSI',
|
||||
batchAddText: 'Batch Add',
|
||||
batchDelText: 'Batch Delete',
|
||||
numAdd: 'Number of releases',
|
||||
numAdd: 'Number of authentication profiles',
|
||||
numDel: 'Number of deleted',
|
||||
checkDel: 'Check Delete',
|
||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||
@@ -908,19 +839,22 @@ export default {
|
||||
opcTip: 'The authentication key, OPC, is calculated from Ki and OP, OP is the root key of the operator, ki is the authentication key, and the maximum length is 32.',
|
||||
delSure:'Are you sure you want to delete the user with IMSI number: {imsi} ?',
|
||||
imsiConfirm:'The length of the IMSI must be 15',
|
||||
startUserName:'Start username',
|
||||
},
|
||||
sub: {
|
||||
subInfo:' Subscription Info',
|
||||
neType: 'UDM Object',
|
||||
imsType:'IMS Object',
|
||||
export: 'Export',
|
||||
exportConfirm: 'Are you sure to export all signed user data?',
|
||||
checkExport : 'Check Export',
|
||||
checkExportConfirm: 'Are you sure to export the data of the checked subscribers?',
|
||||
import: 'Import',
|
||||
importFail: 'Failure Record',
|
||||
loadDataConfirm: 'Are you sure you want to reload the data?',
|
||||
loadData: 'Load Data',
|
||||
loadDataTip: 'Successfully fetched loaded data: {num} items, the system is internally updating the data, it will take about {timer} seconds, please wait!!!!!.',
|
||||
numAdd: 'Number of releases',
|
||||
numAdd: 'Number of subscriber profiles',
|
||||
numDel: 'Number of deleted',
|
||||
checkDel: 'Check Delete',
|
||||
batchAddText: 'Batch Add',
|
||||
@@ -940,6 +874,10 @@ export default {
|
||||
rfspTip:'RFSP index, in NG-RAN, the index of a specific RRM configuration, parameter between 0 and 127',
|
||||
ueTypeTip: 'Operator-defined subscriber UE Usage Type, integer, parameter between 0 and 127',
|
||||
cnFlag: 'Whether to enable 5G Core Network service',
|
||||
cnFlag0: 'No Access Allowed',
|
||||
cnFlag1: 'Access Only 5G',
|
||||
cnFlag2: 'Access Only 4G',
|
||||
cnFlag3: 'Access 4G/5G',
|
||||
epsFlagTip: 'Whether to enable 4G EPS service',
|
||||
contextIdTip: 'To sign up for an APN Context ID, you must select it from the APN Context list.',
|
||||
apnContextTip: 'The list of APNs available to the phone, up to six, is defined in the HSS.',
|
||||
@@ -949,6 +887,12 @@ export default {
|
||||
ardTip:'Access-Restriction-Data (Access-Restriction-Data), can be used to distinguish between 2G/3G/LTE users, to facilitate the coexistence of 2G/3G/LTE network for different types of users to distinguish between the service',
|
||||
smDataTip:'The IP in sm_data=1-000001&internet-1.2.3.4&ims-1.2.3.5: 1.2.3.4 is the static IP assigned to the APN of 5G user internet, and 1.2.3.5 is the static IP assigned to the APN of 5G user ims. If it is dynamic allocation, just remove the IP and the previous connector. Need to support multiple dnn uses & connections',
|
||||
smDataArrTip:'SST,DNN/APN is required',
|
||||
tenantName:'Tenant Name',
|
||||
imsiMode:'IMSI Matching Mode',
|
||||
fuzzyMatch:'Fuzzy Match',
|
||||
prefixMatch:'Prefix Match',
|
||||
fullMatch:'Full Match',
|
||||
suffixMatch:'Suffix Match',
|
||||
},
|
||||
pcf: {
|
||||
neType: 'PCF Object',
|
||||
@@ -982,7 +926,9 @@ export default {
|
||||
rfsfTip:'RAT Frequency Selection Priority',
|
||||
},
|
||||
base5G: {
|
||||
neType: 'NE Object',
|
||||
neType: 'Radio Type',
|
||||
gnb:'5G Radios',
|
||||
enb:'4G Radios',
|
||||
},
|
||||
n3iwf: {
|
||||
neType: 'N3IWF Object',
|
||||
@@ -1094,8 +1040,13 @@ export default {
|
||||
expression:'Expression',
|
||||
description:' Description',
|
||||
kpiSet:' Statistical Settings',
|
||||
sixHoursAgo:'Six hours ago',
|
||||
threeHoursAgo:'Three hours ago.',
|
||||
ago1Hour:'Last 1 hour',
|
||||
ago3Hour:'Last 3 hour',
|
||||
ago6Hour:'Last 6 hour',
|
||||
toDay:'Today',
|
||||
ago1Day:'Last 1 day',
|
||||
ago7Day:'Last 7 day',
|
||||
ago15Day:'Last 15 day',
|
||||
delCustomTip:'Confirm deletion of data item with record Custom Indicator {num}?',
|
||||
delCustom:' Successfully delete record number {num} custom indicator',
|
||||
addCustom:' Add custom indicator',
|
||||
@@ -1111,6 +1062,12 @@ export default {
|
||||
expressionModal:'Expression Modal',
|
||||
expressionErrorTip:'Please check the expression, the wrong indicator is {kpiId}',
|
||||
expressionNoIdTip:'Please check the expression, no valid indicator is found',
|
||||
unitSelect:'To better display the image, the same unit needs to be selected. The current unit is:',
|
||||
avg:'(average)',
|
||||
total:'(total)',
|
||||
ago1:'Past 24 hrs value',
|
||||
ago7:'Past 7 days value',
|
||||
ago30:'Past 30 days value',
|
||||
},
|
||||
kpiKeyTarget:{
|
||||
"time":"Time",
|
||||
@@ -1129,35 +1086,38 @@ export default {
|
||||
},
|
||||
kpiOverView:{
|
||||
"kpiName":"NE Metrics Name",
|
||||
"maxValue":"Max Value",
|
||||
"minValue":"Min Value",
|
||||
"maxValue":"Max",
|
||||
"maxValueTip":"The max value of metric data within the user's filtered time range.",
|
||||
"minValue":"Min",
|
||||
"minValueTip":"The min value of metric data within the user's filtered time range.",
|
||||
"avgValue":"Avg",
|
||||
"avgValueTip":"The average value of metric data within the user's filtered time range.",
|
||||
"totalValue":"Sum",
|
||||
"totalValueTip":"The sum value of metric data within the user's filtered time range.",
|
||||
"kpiChartTitle":"Overview of NE metrics",
|
||||
"changeLine":"Change to Line Charts",
|
||||
"changeBar":"Change to Bar Charts",
|
||||
"chooseShowMetrics":"Select the metric you want to display",
|
||||
"chooseMetrics":"Select an indicator",
|
||||
"tips":"The percentages and rates are averages,the counts are statistical values.",
|
||||
},
|
||||
voiceOverView:{
|
||||
"voiceTitle":"Voice Calls Dashboard",
|
||||
"tips":"Voice Call Statistics Per Minute",
|
||||
"ne":"NE",
|
||||
"now":"Now",
|
||||
"last":"Past",
|
||||
"calls":"Calls",
|
||||
"activeCall":"Active Calls",
|
||||
"callMOMT":"MO/MT Call Success Rate",
|
||||
"failedcall":"Failed Calls",
|
||||
"registration":"Registrations",
|
||||
"activeregistration":"Active Registrations",
|
||||
"registrationsuccess":"Registration Success Rate",
|
||||
"failedregistration":"Failed Registrations",
|
||||
},
|
||||
},
|
||||
traceManage: {
|
||||
analysis: {
|
||||
imsi: 'IMSI',
|
||||
imsiPlease: 'Please enter IMSI',
|
||||
msisdn: 'MSISDN',
|
||||
msisdnPlease: 'Please enter MSISDN',
|
||||
trackTaskId: 'Task ID',
|
||||
srcIp: 'Source IP Address',
|
||||
dstIp: 'Destination IP Address',
|
||||
signalType: 'Signaling Type',
|
||||
msgDirect: 'Message Direction',
|
||||
msgType: 'Message Type',
|
||||
rowTime: 'Record Time',
|
||||
signalData: 'Signaling Data',
|
||||
signalDetail: 'Signaling Details',
|
||||
noData: 'No information content',
|
||||
taskTitle: 'Task {num}',
|
||||
taskDownText: 'Download HTML',
|
||||
taskDownTip: 'Confirm downloading the signaling details HTML file?',
|
||||
},
|
||||
pcap: {
|
||||
capArgPlease: 'Please enter tcpdump -i any support parameter',
|
||||
cmd: 'Command',
|
||||
@@ -1192,6 +1152,7 @@ export default {
|
||||
},
|
||||
task: {
|
||||
traceId: 'Tracing No',
|
||||
title: 'Tracing Title',
|
||||
trackType: 'Tracing Type',
|
||||
trackTypePlease: 'Please select a tracing type',
|
||||
creater: 'Created by',
|
||||
@@ -1208,30 +1169,35 @@ export default {
|
||||
imsiTip: 'Mobile communication IMSI number',
|
||||
srcIp: 'Source IP Address',
|
||||
srcIpPlease: 'Please enter the IP address',
|
||||
srcIpTip: 'Current sender IPv4 address',
|
||||
srcIpTip: 'sending IPv4 address',
|
||||
dstIp: 'Destination IP Address',
|
||||
dstIpPlease: 'Please enter the IP address',
|
||||
dstIpTip: 'IPv4 address of the receiving end of the other party',
|
||||
dstIpTip: 'receiving end IPv4 address',
|
||||
interfaces: 'Signaling Interface',
|
||||
interfacesPlease: 'Please enter the signaling interface',
|
||||
signalPort: 'Signal Port',
|
||||
signalPortPlease: 'Please enter the signaling port',
|
||||
signalPortTip: 'Port of the side corresponding to the destination IP address or source IP address',
|
||||
rangePicker: 'Start/End Time',
|
||||
rangePicker: 'Task Time',
|
||||
rangePickerPlease: 'Please select the start and end time of the task',
|
||||
remark: 'Remark',
|
||||
remarkPlease: 'Task description can be entered',
|
||||
addTask: 'Add Task',
|
||||
editTask: 'Modify Task',
|
||||
viewTask: 'View Task',
|
||||
errorTaskInfo: 'Failed to obtain task information',
|
||||
delTaskTip: 'Are you sure to delete the data item with record ID {id} ?',
|
||||
stopTask: 'Successful cessation of tasks {id}',
|
||||
stopTaskTip: 'Confirm stopping the task with record ID {id} ?',
|
||||
pcapView: "Tracking Data Analysis",
|
||||
traceFile: "Tracking File",
|
||||
pcapView: "Track Data Analysis",
|
||||
traceFile: "Track File",
|
||||
errMsg: "Error Message",
|
||||
imsiORmsisdn: "imsi or msisdn is null, cannot start task",
|
||||
dataView: "Track Data",
|
||||
protocolOrInterface: "Protocol/Interface",
|
||||
msgNe: 'Network Element',
|
||||
msgEvent: 'Event',
|
||||
msgType: 'Type',
|
||||
msgDirect: 'Direction',
|
||||
msgLen: 'Length',
|
||||
rowTime: 'Time',
|
||||
taskInfo: 'Task information',
|
||||
},
|
||||
},
|
||||
faultManage: {
|
||||
@@ -1251,7 +1217,7 @@ export default {
|
||||
clear: 'Clear',
|
||||
mySelf: 'Personalization',
|
||||
exportAll: 'Export All',
|
||||
disPlayFilfter: 'Display Filters',
|
||||
disPlayFilfter: 'Filter out Alerts',
|
||||
alarmId:'ID',
|
||||
alarmTitle:'Title',
|
||||
clearUser:'Clear User',
|
||||
@@ -1341,22 +1307,30 @@ export default {
|
||||
size: "Size",
|
||||
modifiedTime: "Modified Time",
|
||||
fileName: "File Name",
|
||||
downTipZip: "Confirm downloading the directory [{fileName}] as a ZIP file?",
|
||||
downTip: "Confirm the download file name is [{fileName}] File?",
|
||||
downTipErr: "Failed to get file",
|
||||
dirCd: "Enter Dir",
|
||||
viewAs: 'View Action',
|
||||
reload: "Reload",
|
||||
follow: 'Monitoring Content',
|
||||
follow: 'Enable Instant Update',
|
||||
tailChar: 'End Characters',
|
||||
tailLines: 'End Lines',
|
||||
},
|
||||
exportFile:{
|
||||
fileName:'File Source',
|
||||
fileSource:'File Source',
|
||||
fileSourcePlease:'Please select the source of the document',
|
||||
downTip: "Confirm the download file name is [{fileName}] File?",
|
||||
downTipErr: "Failed to get file",
|
||||
deleteTip: "Confirm the delete file name is [{fileName}] File?",
|
||||
deleteTipErr: "Failed to delete file",
|
||||
selectTip:"Please select File Name",
|
||||
sysloginLog:'System Login Log',
|
||||
sysOperateLog:'System Operation Log',
|
||||
neLog:'NE Log',
|
||||
cdrIMS:'CDR Voice',
|
||||
cdrSMF:'CDR Data',
|
||||
cdrSMSC:'CDR SMS',
|
||||
cdrSGWC:'CDR Roaming Data',
|
||||
}
|
||||
},
|
||||
monitor: {
|
||||
@@ -1729,7 +1703,9 @@ export default {
|
||||
account: 'Account',
|
||||
userName: 'Nick Name',
|
||||
permission: 'Role',
|
||||
className: 'Class',
|
||||
className: 'Department',
|
||||
userType: 'User Type',
|
||||
tenntName:'Tenant Name',
|
||||
loginIp: 'Login Address',
|
||||
loginTime: 'Login Time',
|
||||
status: 'Status',
|
||||
@@ -1754,7 +1730,8 @@ export default {
|
||||
userTop:'User profile',
|
||||
sex:'User Gender',
|
||||
email:'E-mail',
|
||||
fromClass:'Class',
|
||||
fromClass:'Department',
|
||||
fromTenant:'Tenant',
|
||||
userWork:'User position',
|
||||
userWorkPlease: 'Please select user post',
|
||||
userTip:'User Description',
|
||||
@@ -1768,6 +1745,7 @@ export default {
|
||||
lock:'Lock',
|
||||
inactive:'Inactive',
|
||||
active:'Active',
|
||||
permissionTip:'If want to select a tenant role, make sure there is at least one tenant in the tenant management.',
|
||||
},
|
||||
config: {
|
||||
configName: "Config Name",
|
||||
@@ -1792,6 +1770,55 @@ export default {
|
||||
refreshCacheTip: "Are you sure you want to refresh the parameter configuration cache?",
|
||||
refreshCacheOk: "Refresh Cache Successful",
|
||||
},
|
||||
loginSource: {
|
||||
uid: "UID",
|
||||
name: "Name",
|
||||
namePlease: 'Please enter the authentication source name correctly',
|
||||
icon: "Icon",
|
||||
iconPlease: 'You can enter the image link or upload the image path address',
|
||||
type: "Type",
|
||||
activeFlag: "Status",
|
||||
remark: "Remark",
|
||||
createTime: "Create Time",
|
||||
updateTime: "Update Time",
|
||||
ldapUrl: "Server Address",
|
||||
ldapUrlPlease: 'Please enter the LDAP server address correctly',
|
||||
ldapBaseDN: "Base DN",
|
||||
baseDnPlease: 'Please enter the LDAP base DN correctly',
|
||||
ldapUserFilter: "User Filter",
|
||||
userFilterPlease: 'Please enter the LDAP user filter correctly',
|
||||
ldapBindDN: "Bind DN",
|
||||
ldapBindPassword: "Bind Password",
|
||||
smtpHost: 'Server Address',
|
||||
smtpHostPlease: 'Please enter the SMTP server address correctly',
|
||||
smtpPort: 'Port Number',
|
||||
smtpPortPlease: 'Please enter the SMTP port number correctly',
|
||||
oauth2ClientID: 'Client ID',
|
||||
oauth2ClientIDPlease: 'Please enter the OAuth2 client ID correctly',
|
||||
oauth2ClientSecret: 'Client Secret',
|
||||
oauth2ClientSecretPlease: 'Please enter the OAuth2 client secret correctly',
|
||||
oauth2AuthURL: 'Authorization URL',
|
||||
oauth2AuthURLPlease: 'Please enter the OAuth2 authorization URL correctly',
|
||||
oauth2TokenURL: 'Token URL',
|
||||
oauth2TokenURLPlease: 'Please enter the OAuth2 token URL correctly',
|
||||
oauth2UserURL: 'User Info URL',
|
||||
oauth2UserURLPlease: 'Please enter the OAuth2 user info URL correctly',
|
||||
oauth2AccountField: 'Account Field',
|
||||
oauth2AccountFieldPlease: 'Please enter the OAuth2 account field correctly',
|
||||
oauth2Scopes: 'Scopes',
|
||||
oauth2ScopesPlease: 'Please enter the OAuth2 scopes correctly',
|
||||
oauth2RedirectURL: 'Redirect URL',
|
||||
oauth2RedirectURLPlease: 'Please enter the OAuth2 redirect URL correctly',
|
||||
oauth2RedirectURLTip: 'Please jump to the specified path (omchost/#/login/oauth2), redirect with code and state address parameters',
|
||||
uploadFileTip: 'Confirm to upload the authentication source icon?',
|
||||
uploadFileOk: 'Authentication source icon upload successful',
|
||||
uploadFileErr: 'Authentication source icon upload failed',
|
||||
viewInfoErr: "Failed to get authentication source information",
|
||||
addInfo: "Add Authentication Source",
|
||||
editInfo: "Modify Authentication Source",
|
||||
delTip: "Confirm deleting the authentication source number [{num}] data item?",
|
||||
delOk: "Deleted Successfully",
|
||||
},
|
||||
setting: {
|
||||
charMaxLen: 'characters length',
|
||||
saveSubmit: 'Submit&Save',
|
||||
@@ -1851,12 +1878,16 @@ export default {
|
||||
home: 'Home Page',
|
||||
homeTip:'Do you want to submit the current interface as the system interface?',
|
||||
homeSet:'Home Page Settings',
|
||||
backup: 'System Backup',
|
||||
backupInstruction: 'System backup will back up the net element information records and configuration files running on the current system, and can restore the system to the previous state!',
|
||||
backupExportTip: 'Confirm to export system backup?',
|
||||
backupImportTip: 'Confirm to import system backup?',
|
||||
},
|
||||
role:{
|
||||
allScopeOptions:'All data permissions',
|
||||
byMyselfScopeOptions:'Custom data permissions',
|
||||
onlyClassScopeOptions:'Data permissions of this class',
|
||||
classAllScopeOptions:'Data permissions for this class and the following',
|
||||
onlyClassScopeOptions:'Data permissions of this department',
|
||||
classAllScopeOptions:'Data permissions for this department and the following',
|
||||
myselfScopeOptions:'Only personal data permissions',
|
||||
roleId:'Role Number',
|
||||
roleName:'Role Name',
|
||||
@@ -1895,26 +1926,58 @@ export default {
|
||||
cancelGive:'Cancel authorization',
|
||||
cancelSure:'Confirm to cancel the authorization of the data item with user number [{userId}]?',
|
||||
batchCancel:'Batch cancellation of authorization',
|
||||
selectUser:'Assign Users',
|
||||
},
|
||||
dept:{
|
||||
classInfo:' Class Information',
|
||||
className:'Class Name',
|
||||
classId:'Class Number',
|
||||
classSort:'Class Sorting',
|
||||
status:'Class Status',
|
||||
classInfo:' Department Information',
|
||||
className:'Department Name',
|
||||
classId:'Department Number',
|
||||
classSort:'Department Sorting',
|
||||
status:'Department Status',
|
||||
createTime:'Creation Time',
|
||||
highClass:'Higher Office',
|
||||
emailTip:'Please input the correct email address',
|
||||
phoneTip:'Please enter the correct phone number',
|
||||
node:'Root Node',
|
||||
delSure:'Are you sure to delete the data item with class number [{deptId}]?',
|
||||
delSure:'Are you sure to delete the data item with department number [{deptId}]?',
|
||||
open:'Exhibition',
|
||||
close:'Fold',
|
||||
addClass:'Add new sub-class',
|
||||
addClass:'Add new sub-department',
|
||||
admin:'Principal',
|
||||
phone:'Contact Number',
|
||||
email:'Mail',
|
||||
},
|
||||
tenant:{
|
||||
classInfo:' Tenant Information',
|
||||
className:'Name',
|
||||
classId:'Number',
|
||||
classSort:'Sorting',
|
||||
status:'Status',
|
||||
type:' Tenancy Asset',
|
||||
createTime:'Creation Time',
|
||||
highClass:'Root Level',
|
||||
key:'Asset Key',
|
||||
emailTip:'Please input the correct email address',
|
||||
phoneTip:'Please enter the correct phone number',
|
||||
node:'Root Node',
|
||||
delSure:'Are you sure to delete the data item with TenantName: {title}?',
|
||||
delTypeSure:'Are you sure to delete the data item with Tenancy Asset: {tenancyAsset}, Asset Key: {tenancyKey}?',
|
||||
open:'Exhibition',
|
||||
close:'Fold',
|
||||
addClass:'Add Tenant',
|
||||
admin:'Principal',
|
||||
phone:'Contact Number',
|
||||
email:'Mail',
|
||||
SDSST:'Network Slice',
|
||||
APN:'Access Point Name',
|
||||
IMSI:'SIM Card',
|
||||
treeSelectTip:'Please select a tenant from the tenant list on the left for configuration',
|
||||
upfTip:'Please select from the drop-down list of UPF Resource UIDs',
|
||||
imsiTip:'Please select the matching type and fill in the SIM card number fragment',
|
||||
radioTip:'Please select from the drop-down list of radio type and radio ID',
|
||||
defaultTip:'Please select from the drop-down list of Tenancy Asset, and then fill the Asset Key',
|
||||
patternTip:'The Asset Key cannot contain special characters',
|
||||
},
|
||||
post:{
|
||||
positionInfo:'Position Information',
|
||||
positionId:'Position Number',
|
||||
@@ -1937,7 +2000,7 @@ export default {
|
||||
requestMe:'Request Method',
|
||||
host:'Request Host',
|
||||
operStatus:'Status',
|
||||
operDate:'Time',
|
||||
operDate:'Time Stamp',
|
||||
useTime:'Time Lap',
|
||||
logInfo:'Operation Log Information',
|
||||
delSure:'Are you sure to delete the data item with access number [{ids}]?',
|
||||
|
||||