Compare commits
50
Commits
main
..
2fb3467fb5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb3467fb5 | ||
|
|
63d7d11350 | ||
|
|
2bd98540be | ||
|
|
630c63e23f | ||
|
|
ada1f388fc | ||
|
|
b9cf34714f | ||
|
|
53200d5f41 | ||
|
|
52d5b9b732 | ||
|
|
292488f20c | ||
|
|
b0b844f0f6 | ||
|
|
0819fbdb44 | ||
|
|
a88ae826cc | ||
|
|
76499d98e0 | ||
|
|
94ccb45f8c | ||
|
|
79e2b4ac26 | ||
|
|
b2510c0eb3 | ||
|
|
f977b6ea53 | ||
|
|
1e9c6a51be | ||
|
|
d68a773214 | ||
|
|
f60f26ae89 | ||
|
|
c35a5a9c33 | ||
|
|
4d755cea5d | ||
|
|
c87458bc23 | ||
|
|
cfd04ba1b6 | ||
|
|
4af02693a4 | ||
|
|
66eb27813f | ||
|
|
65c8c6f809 | ||
|
|
ecaa0ce077 | ||
|
|
99140f0641 | ||
|
|
f3c46976ae | ||
|
|
efa8764bd1 | ||
|
|
bc0e463191 | ||
|
|
45bf9fe115 | ||
|
|
4c85c61f05 | ||
|
|
318f84504f | ||
|
|
53fa36eace | ||
|
|
9123484bf5 | ||
|
|
e7e4557e96 | ||
|
|
6b1fe4a582 | ||
|
|
2610ab17ad | ||
|
|
b84a08d825 | ||
|
|
824c38593b | ||
|
|
69fb3df7ec | ||
|
|
42827796c7 | ||
|
|
eb38211e3b | ||
|
|
fd1d2a5bad | ||
|
|
2d5bfb9842 | ||
|
|
c0a7f28958 | ||
|
|
5f4e47e998 | ||
|
|
19a91936de |
No files matched your search
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
# 历史路径-哈希带井号标识
|
# 历史路径-哈希带井号标识
|
||||||
VITE_HISTORY_HASH = true
|
VITE_HISTORY_HASH = false
|
||||||
|
|
||||||
# 历史路径-前缀URL如:/h5
|
# 历史路径-前缀URL如:/h5
|
||||||
VITE_HISTORY_BASE_URL = "/"
|
VITE_HISTORY_BASE_URL = "/"
|
||||||
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
|
|||||||
VITE_APP_CODE = "OMC"
|
VITE_APP_CODE = "OMC"
|
||||||
|
|
||||||
# 应用版本
|
# 应用版本
|
||||||
VITE_APP_VERSION = "2.250509"
|
VITE_APP_VERSION = "2.241115"
|
||||||
|
|
||||||
# 接口基础URL地址-不带/后缀
|
# 接口基础URL地址-不带/后缀
|
||||||
VITE_API_BASE_URL = "/omc-api"
|
VITE_API_BASE_URL = "/omc-api"
|
||||||
+1
-1
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network OMC"
|
|||||||
VITE_APP_CODE = "OMC"
|
VITE_APP_CODE = "OMC"
|
||||||
|
|
||||||
# 应用版本
|
# 应用版本
|
||||||
VITE_APP_VERSION = "2.250509"
|
VITE_APP_VERSION = "2.241115"
|
||||||
|
|
||||||
# 接口基础URL地址-不带/后缀
|
# 接口基础URL地址-不带/后缀
|
||||||
VITE_API_BASE_URL = "/omc-api"
|
VITE_API_BASE_URL = "/omc-api"
|
||||||
+39
-39
@@ -12,50 +12,50 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons-vue": "7.0.1",
|
"@ant-design/icons-vue": "^7.0.1",
|
||||||
"@antv/g6": "4.8.24",
|
"@antv/g6": "~4.8.24",
|
||||||
"@codemirror/lang-javascript": "6.2.3",
|
"@codemirror/lang-javascript": "^6.2.2",
|
||||||
"@codemirror/lang-yaml": "6.1.2",
|
"@codemirror/lang-yaml": "^6.1.1",
|
||||||
"@codemirror/merge": "6.10.0",
|
"@codemirror/merge": "^6.7.2",
|
||||||
"@codemirror/theme-one-dark": "6.1.2",
|
"@codemirror/theme-one-dark": "^6.1.2",
|
||||||
"@tato30/vue-pdf": "1.11.3",
|
"@tato30/vue-pdf": "^1.11.2",
|
||||||
"@vueuse/core": "13.0.0",
|
"@vueuse/core": "11.2.0",
|
||||||
"@xterm/addon-fit": "0.10.0",
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
"@xterm/xterm": "5.5.0",
|
"@xterm/xterm": "^5.5.0",
|
||||||
"ant-design-vue": "4.2.6",
|
"ant-design-vue": "^4.2.5",
|
||||||
"antdv-pro-layout": "4.2.0",
|
"antdv-pro-layout": "^4.1.9",
|
||||||
"antdv-pro-modal": "4.0.6",
|
"antdv-pro-modal": "^4.0.5",
|
||||||
"codemirror": "6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"crypto-js": "4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"dayjs": "1.11.13",
|
"dayjs": "^1.11.11",
|
||||||
"echarts": "5.6.0",
|
"echarts": "~5.5.0",
|
||||||
"file-saver": "2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"grid-layout-plus": "1.0.6",
|
"grid-layout-plus": "^1.0.5",
|
||||||
"intl-tel-input": "25.2.0",
|
"intl-tel-input": "^24.6.0",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"p-queue": "8.0.1",
|
"p-queue": "~8.0.1",
|
||||||
"pinia": "2.3.0",
|
"pinia": "2.2.6",
|
||||||
"vue": "3.5.13",
|
"vue": "^3.5.12",
|
||||||
"vue-i18n": "11.1.2",
|
"vue-i18n": "^10.0.4",
|
||||||
"vue-router": "4.5.0",
|
"vue-router": "^4.4.5",
|
||||||
"vue3-smooth-dnd": "0.0.6",
|
"vue3-smooth-dnd": "^0.0.6",
|
||||||
"xlsx": "0.18.5"
|
"xlsx": "~0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/crypto-js": "4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/file-saver": "2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/js-cookie": "3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/node": "^18.0.0",
|
"@types/node": "^22.7.7",
|
||||||
"@types/nprogress": "0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@vitejs/plugin-vue": "5.2.3",
|
"@vitejs/plugin-vue": "^5.1.4",
|
||||||
"less": "4.2.2",
|
"less": "^4.2.0",
|
||||||
"typescript": "5.8.2",
|
"typescript": "^5.6.3",
|
||||||
"unplugin-vue-components": "0.28.0",
|
"unplugin-vue-components": "^0.27.4",
|
||||||
"vite": "6.2.2",
|
"vite": "5.4.10",
|
||||||
"vite-plugin-compression": "0.5.1",
|
"vite-plugin-compression": "~0.5.1",
|
||||||
"vue-tsc": "2.2.8"
|
"vue-tsc": "^2.1.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* =============== Configuration File Description ===============
|
* =============== Configuration File Description ===============
|
||||||
*
|
*
|
||||||
* - Nginx Deployment
|
* - Nginx Deployment
|
||||||
* Delete the file with the same name under the same level of loading.js, Nginx proxy address: /omc-api
|
* Delete the file with the same name under the same level of loading.js, Nginx proxy address: /omc-api
|
||||||
*
|
*
|
||||||
@@ -10,19 +10,12 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
(function () {
|
(function () {
|
||||||
// baseUrl = protocol://ip:port
|
// host = ip:port
|
||||||
// baseUrl = 'http://192.168.8.100:33030';
|
// const host = '192.168.8.100:33030';
|
||||||
const protocol = window.location.protocol
|
const host = `${window.location.hostname}:33030`;
|
||||||
let wsprotocol = "ws:"
|
|
||||||
const hostname = window.location.hostname
|
|
||||||
let host = `${hostname}:33030`;
|
|
||||||
if (protocol === 'https:') {
|
|
||||||
host = `${hostname}:33443`;
|
|
||||||
wsprotocol = "wss:"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Service Address
|
// Service Address
|
||||||
sessionStorage.setItem('baseUrl', `${protocol}//${host}`);
|
sessionStorage.setItem('baseUrl', `http://${host}`);
|
||||||
// websocket Address
|
// websocket Address
|
||||||
sessionStorage.setItem('wsUrl', `${wsprotocol}//${host}`);
|
sessionStorage.setItem('wsUrl', `ws://${host}`);
|
||||||
})();
|
})();
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,28 +0,0 @@
|
|||||||
<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>
|
|
||||||
|
Before Width: | Height: | Size: 7.9 KiB |
@@ -1,28 +0,0 @@
|
|||||||
<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>
|
|
||||||
|
Before Width: | Height: | Size: 7.9 KiB |
@@ -1,7 +1,7 @@
|
|||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
import { parseDateToStr, YYYY_MM_DD_HH_MM_SS } from '@/utils/date-utils';
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,7 +122,7 @@ export function updateConfirm(data: Record<string, any>) {
|
|||||||
const userName = useUserStore().userName;
|
const userName = useUserStore().userName;
|
||||||
let finalData = {
|
let finalData = {
|
||||||
alarm: {
|
alarm: {
|
||||||
ack_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
ack_time: parseDateToStr(time),
|
||||||
ack_user: userName,
|
ack_user: userName,
|
||||||
ack_state: '1',
|
ack_state: '1',
|
||||||
},
|
},
|
||||||
@@ -145,7 +145,7 @@ export function cancelConfirm(data: (string | number)[]) {
|
|||||||
const userName = useUserStore().userName;
|
const userName = useUserStore().userName;
|
||||||
let finalData = {
|
let finalData = {
|
||||||
alarm: {
|
alarm: {
|
||||||
ack_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
ack_time: parseDateToStr(time),
|
||||||
ack_user: '',
|
ack_user: '',
|
||||||
ack_state: '0',
|
ack_state: '0',
|
||||||
},
|
},
|
||||||
@@ -216,7 +216,7 @@ export function clearAlarm(data: Record<string, any>) {
|
|||||||
const userName = useUserStore().userName;
|
const userName = useUserStore().userName;
|
||||||
let finalData = {
|
let finalData = {
|
||||||
data: {
|
data: {
|
||||||
clear_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
clear_time: parseDateToStr(time),
|
||||||
clear_type: '2',
|
clear_type: '2',
|
||||||
alarm_status: '0',
|
alarm_status: '0',
|
||||||
clear_user: userName,
|
clear_user: userName,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
|
import useUserStore from '@/store/modules/user';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询列表
|
* 查询列表
|
||||||
|
|||||||
@@ -63,11 +63,7 @@ export async function getAlarmSet() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Object.keys(resultData).length === 0) {
|
if (Object.keys(resultData).length === 0) {
|
||||||
return {
|
return { code: RESULT_CODE_ERROR, msg: RESULT_MSG_ERROR[language], data: {} };
|
||||||
code: RESULT_CODE_ERROR,
|
|
||||||
msg: RESULT_MSG_ERROR[language],
|
|
||||||
data: {},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
code: RESULT_CODE_SUCCESS,
|
code: RESULT_CODE_SUCCESS,
|
||||||
@@ -121,11 +117,7 @@ export async function updateAlarmSet(data: Record<string, any>) {
|
|||||||
}
|
}
|
||||||
// 无变更时
|
// 无变更时
|
||||||
if (resultNum === 0) {
|
if (resultNum === 0) {
|
||||||
return {
|
return { code: RESULT_CODE_ERROR, msg: RESULT_MSG_ERROR[language], data: 0 };
|
||||||
code: RESULT_CODE_ERROR,
|
|
||||||
msg: RESULT_MSG_ERROR[language],
|
|
||||||
data: 0,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
code: RESULT_CODE_SUCCESS,
|
code: RESULT_CODE_SUCCESS,
|
||||||
@@ -174,10 +166,11 @@ export async function getForwardSet() {
|
|||||||
*/
|
*/
|
||||||
export async function updateForwardSet(data: Record<string, any>) {
|
export async function updateForwardSet(data: Record<string, any>) {
|
||||||
// return false;
|
// return false;
|
||||||
let obj: any = [
|
console.log(data)
|
||||||
{ interface: 'Email', to_user: data.emailObj },
|
let obj:any=[
|
||||||
{ interface: 'SMS', to_user: data.smsObj },
|
{interface:"Email",to_user:data.emailObj},
|
||||||
];
|
{interface:"SMS",to_user:data.smsObj}
|
||||||
|
]
|
||||||
const result = await request({
|
const result = await request({
|
||||||
url: `/api/rest/databaseManagement/v1/omc_db/config?WHERE=config_tag='forwardAlarm'`,
|
url: `/api/rest/databaseManagement/v1/omc_db/config?WHERE=config_tag='forwardAlarm'`,
|
||||||
method: 'put',
|
method: 'put',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
import { parseDateToStr, YYYY_MM_DD_HH_MM_SS } from '@/utils/date-utils';
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,7 +79,7 @@ export function updateConfirm(data: Record<string, any>) {
|
|||||||
const userName = useUserStore().userName;
|
const userName = useUserStore().userName;
|
||||||
let finalData = {
|
let finalData = {
|
||||||
alarm: {
|
alarm: {
|
||||||
ack_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
ack_time: parseDateToStr(time),
|
||||||
ack_user: userName,
|
ack_user: userName,
|
||||||
ack_state: '1',
|
ack_state: '1',
|
||||||
},
|
},
|
||||||
@@ -101,7 +101,7 @@ export function cancelConfirm(data: (string | number)[]) {
|
|||||||
var time = new Date();
|
var time = new Date();
|
||||||
let finalData = {
|
let finalData = {
|
||||||
alarm: {
|
alarm: {
|
||||||
ack_time: parseDateToStr(time, YYYY_MM_DD_HH_MM_SS),
|
ack_time: parseDateToStr(time),
|
||||||
ack_user: '',
|
ack_user: '',
|
||||||
ack_state: '0',
|
ack_state: '0',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
|
||||||
import { sessionGet } from '@/utils/cache-session-utils';
|
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,43 +51,3 @@ export function delFile(query: Record<string, any>) {
|
|||||||
params: query,
|
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 },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
+2
-4
@@ -1,5 +1,3 @@
|
|||||||
import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
|
||||||
import { sessionGet } from '@/utils/cache-session-utils';
|
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
// 登录方法
|
// 登录方法
|
||||||
@@ -9,7 +7,7 @@ export function login(data: Record<string, string>) {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
whithToken: false,
|
whithToken: false,
|
||||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
crypto: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +22,7 @@ export function register(data: Record<string, any>) {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
whithToken: false,
|
whithToken: false,
|
||||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
crypto: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
|
||||||
import { sessionGet } from '@/utils/cache-session-utils';
|
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,7 +36,7 @@ export function addNeInfo(data: Record<string, any>) {
|
|||||||
url: `/ne/info`,
|
url: `/ne/info`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
crypto: true,
|
||||||
timeout: 30_000,
|
timeout: 30_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -53,7 +51,7 @@ export function updateNeInfo(data: Record<string, any>) {
|
|||||||
url: `/ne/info`,
|
url: `/ne/info`,
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data,
|
data: data,
|
||||||
crypto: sessionGet(CACHE_SESSION_CRYPTO_API) !== 'false',
|
crypto: true,
|
||||||
timeout: 30_000,
|
timeout: 30_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ export function listAMFDataUE(query: Record<string, any>) {
|
|||||||
url: '/neData/amf/ue/list',
|
url: '/neData/amf/ue/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
timeout: 60_000,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,90 +40,3 @@ export function exportAMFDataUE(data: Record<string, any>) {
|
|||||||
timeout: 60_000,
|
timeout: 60_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}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,6 @@ export function listIMSDataCDR(query: Record<string, any>) {
|
|||||||
url: '/neData/ims/cdr/list',
|
url: '/neData/ims/cdr/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
timeout: 60_000,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ export function listMMEDataUE(query: Record<string, any>) {
|
|||||||
url: '/neData/mme/ue/list',
|
url: '/neData/mme/ue/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
timeout: 60_000,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,90 +40,3 @@ export function exportMMEDataUE(data: Record<string, any>) {
|
|||||||
timeout: 60_000,
|
timeout: 60_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}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
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: 60_000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
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: 60_000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
+2
-16
@@ -10,7 +10,6 @@ export function listSMFDataCDR(query: Record<string, any>) {
|
|||||||
url: '/neData/smf/cdr/list',
|
url: '/neData/smf/cdr/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
timeout: 60_000,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,27 +41,14 @@ export function exportSMFDataCDR(data: Record<string, any>) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* SMF-在线订阅用户数量
|
|
||||||
* @param query 查询参数
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export function listSMFSubNum(neId: string) {
|
|
||||||
return request({
|
|
||||||
url: '/neData/smf/sub/num',
|
|
||||||
method: 'get',
|
|
||||||
params: { neId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SMF-在线订阅用户列表信息
|
* SMF-在线订阅用户列表信息
|
||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
export function listSMFSubList(query: Record<string, any>) {
|
export function listSMFSubscribers(query: Record<string, any>) {
|
||||||
return request({
|
return request({
|
||||||
url: '/neData/smf/sub/list',
|
url: '/neData/smf/subscribers',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ export function listSMSCDataCDR(query: Record<string, any>) {
|
|||||||
url: '/neData/smsc/cdr/list',
|
url: '/neData/smsc/cdr/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
timeout: 60_000,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新 查询自定义指标数据
|
* 新 查询自定义指标数据
|
||||||
@@ -11,7 +14,6 @@ export async function listCustomData(query: Record<string, any>) {
|
|||||||
url: `/pm/kpiC/report`,
|
url: `/pm/kpiC/report`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
timeout: 60_000,
|
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询自定义指标
|
* 查询自定义指标
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
import { parseObjLineToHump } from '@/utils/parse-utils';
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询任务列表
|
* 查询任务列表
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function getNeFile(query: Record<string, any>) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
timeout: 600_000,
|
timeout: 180_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ export function getNeDirZip(data: Record<string, any>) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
params: data,
|
params: data,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
timeout: 600_000,
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
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,18 +62,3 @@ export function packetKeep(taskNo: string, duration: number = 120) {
|
|||||||
data: { taskNo, duration },
|
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
+19
-19
@@ -1,4 +1,6 @@
|
|||||||
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询跟踪任务列表
|
* 查询跟踪任务列表
|
||||||
@@ -74,31 +76,29 @@ export function filePullTask(traceId: string) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
params: { traceId },
|
params: { traceId },
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
timeout: 600_000,
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跟踪任务数据列表
|
* 获取网元跟踪接口列表
|
||||||
* @param query 查询参数
|
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
export async function listTraceData(query: Record<string, any>) {
|
export async function getNeTraceInterfaceAll() {
|
||||||
return request({
|
// 发起请求
|
||||||
url: '/trace/data/list',
|
const result = await request({
|
||||||
method: 'get',
|
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/ne_info`,
|
||||||
params: query,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询跟踪任务数据信息
|
|
||||||
* @param id ID
|
|
||||||
* @returns object
|
|
||||||
*/
|
|
||||||
export async function getTraceData(id: string | number) {
|
|
||||||
return request({
|
|
||||||
url: `/trace/data/${id}`,
|
|
||||||
method: 'get',
|
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',
|
method: 'get',
|
||||||
params: query,
|
params: query,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
timeout: 600_000,
|
timeout: 60_000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { message } from 'ant-design-vue/es';
|
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||||
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
|
||||||
import { FitAddon } from '@xterm/addon-fit';
|
import { FitAddon } from '@xterm/addon-fit';
|
||||||
import { Terminal } from '@xterm/xterm';
|
import { Terminal } from '@xterm/xterm';
|
||||||
import '@xterm/xterm/css/xterm.css';
|
import '@xterm/xterm/css/xterm.css';
|
||||||
@@ -32,91 +31,8 @@ const terminalDom = ref<HTMLElement | undefined>(undefined);
|
|||||||
/**终端输入实例对象 */
|
/**终端输入实例对象 */
|
||||||
const terminal = ref<any>(null);
|
const terminal = ref<any>(null);
|
||||||
|
|
||||||
/**终端输入文字状态 */
|
/**终端输入命令 */
|
||||||
const terminalState = reactive<{
|
const terminalCmd = ref<string>('');
|
||||||
/**输入值 */
|
|
||||||
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) {
|
function handleRanderXterm(container: HTMLElement | undefined) {
|
||||||
@@ -133,13 +49,47 @@ function handleRanderXterm(container: HTMLElement | undefined) {
|
|||||||
scrollback: 1000,
|
scrollback: 1000,
|
||||||
scrollSensitivity: 15,
|
scrollSensitivity: 15,
|
||||||
tabStopWidth: 4,
|
tabStopWidth: 4,
|
||||||
disableStdin: true, // 禁止输入
|
disableStdin: false, // 禁止输入
|
||||||
});
|
});
|
||||||
// 挂载
|
// 挂载
|
||||||
xterm.open(container);
|
xterm.open(container);
|
||||||
// 自适应尺寸
|
// 自适应尺寸
|
||||||
const fitAddon = new FitAddon();
|
const fitAddon = new FitAddon();
|
||||||
xterm.loadAddon(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 实例
|
// 创建 ResizeObserver 实例
|
||||||
var observer = new ResizeObserver(entries => {
|
var observer = new ResizeObserver(entries => {
|
||||||
fitAddon.fit();
|
fitAddon.fit();
|
||||||
@@ -263,21 +213,7 @@ defineExpose({
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="terminal">
|
<div class="terminal">
|
||||||
<div ref="terminalDom" style="height: calc(100% - 36px)" :id="id"></div>
|
<div ref="terminalDom" :id="id" class="terminal"></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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -80,16 +80,16 @@ function fnAutoCompleteFilter(input: string, option: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**自动完成按键触发 */
|
/**自动完成按键触发 */
|
||||||
function fnAutoCompleteKeydown(evt: KeyboardEvent) {
|
function fnAutoCompleteKeydown(evt: any) {
|
||||||
if (evt.key === 'Enter') {
|
if (evt.key === 'Enter') {
|
||||||
// 阻止默认的换行行为
|
// 阻止默认的换行行为
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
// 按下 Shift + Enter 键时换行
|
// 按下 Shift + Enter 键时换行
|
||||||
if (evt.shiftKey && evt.target) {
|
if (evt.shiftKey) {
|
||||||
// 插入换行符
|
// 插入换行符
|
||||||
const textarea = evt.target as HTMLInputElement;
|
const textarea = evt.target;
|
||||||
const start = textarea.selectionStart || 0;
|
const start = textarea.selectionStart;
|
||||||
const end = textarea.selectionEnd || 0;
|
const end = textarea.selectionEnd;
|
||||||
const text = textarea.value;
|
const text = textarea.value;
|
||||||
textarea.value = text.substring(0, start) + '\n' + text.substring(end);
|
textarea.value = text.substring(0, start) + '\n' + text.substring(end);
|
||||||
terminalState.text = textarea.value;
|
terminalState.text = textarea.value;
|
||||||
@@ -121,7 +121,7 @@ function fnAutoCompleteKeydown(evt: KeyboardEvent) {
|
|||||||
type: 'telnet',
|
type: 'telnet',
|
||||||
data: `${cmdStr}\r\n`,
|
data: `${cmdStr}\r\n`,
|
||||||
});
|
});
|
||||||
terminalState.text = '';
|
terminalState.text = ' ';
|
||||||
|
|
||||||
// 退出登录
|
// 退出登录
|
||||||
if (['q', 'quit', 'exit'].includes(cmdStr)) {
|
if (['q', 'quit', 'exit'].includes(cmdStr)) {
|
||||||
@@ -296,12 +296,11 @@ defineExpose({
|
|||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:options="terminalState.history"
|
:options="terminalState.history"
|
||||||
:filter-option="fnAutoCompleteFilter"
|
:filter-option="fnAutoCompleteFilter"
|
||||||
:defaultActiveFirstOption="false"
|
@keydown="fnAutoCompleteKeydown"
|
||||||
>
|
>
|
||||||
<a-textarea
|
<a-textarea
|
||||||
:auto-size="{ minRows: 1, maxRows: 6 }"
|
:auto-size="{ minRows: 1, maxRows: 6 }"
|
||||||
placeholder="Execute command. Shift+Enter to line feed, Enter to send"
|
placeholder="Execute command. Shift+Enter to line feed, Enter to send"
|
||||||
@keypress="fnAutoCompleteKeydown"
|
|
||||||
/>
|
/>
|
||||||
</a-auto-complete>
|
</a-auto-complete>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
/**会话缓存-接口加密 */
|
|
||||||
export const CACHE_SESSION_CRYPTO_API = 'cache:session:cryptoApi';
|
|
||||||
|
|
||||||
/**会话缓存-网络请求 */
|
/**会话缓存-网络请求 */
|
||||||
export const CACHE_SESSION_FATCH = 'cache:session:fatch';
|
export const CACHE_SESSION_FATCH = 'cache:session:fatch';
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ export const NE_TYPE_LIST = [
|
|||||||
'IMS',
|
'IMS',
|
||||||
'AMF',
|
'AMF',
|
||||||
'AUSF',
|
'AUSF',
|
||||||
'UDR',
|
|
||||||
'UDM',
|
'UDM',
|
||||||
'SMF',
|
'SMF',
|
||||||
'PCF',
|
'PCF',
|
||||||
@@ -20,8 +19,6 @@ export const NE_TYPE_LIST = [
|
|||||||
'SMSF',
|
'SMSF',
|
||||||
'CBC',
|
'CBC',
|
||||||
'CHF',
|
'CHF',
|
||||||
'HLR',
|
|
||||||
'SGWC',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+199
-67
@@ -16,6 +16,7 @@ export default {
|
|||||||
errorFields: 'Please fill in the required information in {num} correctly!',
|
errorFields: 'Please fill in the required information in {num} correctly!',
|
||||||
tablePaginationTotal: 'Total {total} items',
|
tablePaginationTotal: 'Total {total} items',
|
||||||
noData: "No Data",
|
noData: "No Data",
|
||||||
|
zebra:'Tabular zebra pattern',
|
||||||
ok: 'Ok',
|
ok: 'Ok',
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
close: 'Close',
|
close: 'Close',
|
||||||
@@ -130,7 +131,7 @@ export default {
|
|||||||
},
|
},
|
||||||
LockScreen: {
|
LockScreen: {
|
||||||
inputPlacePwd:'Lock Screen Password',
|
inputPlacePwd:'Lock Screen Password',
|
||||||
enter:'Enter',
|
validSucc:'Validation Passed',
|
||||||
validError:'Validation Failure',
|
validError:'Validation Failure',
|
||||||
backLogin:'Logout to Relogin',
|
backLogin:'Logout to Relogin',
|
||||||
backReload:'Restarting now, please wait...',
|
backReload:'Restarting now, please wait...',
|
||||||
@@ -221,11 +222,12 @@ export default {
|
|||||||
capability: 'Capability',
|
capability: 'Capability',
|
||||||
serialNum: 'Serial Number',
|
serialNum: 'Serial Number',
|
||||||
expiryDate: 'Expiry Date',
|
expiryDate: 'Expiry Date',
|
||||||
neStatus: 'Status Abnormal',
|
neStatus: 'NE status is abnormal',
|
||||||
runStatus: 'Runing Status',
|
runStatus:'Running Status',
|
||||||
mark:'Information',
|
mark:'Brief Information',
|
||||||
object:'Object',
|
object:'Object',
|
||||||
versionNum:'Version',
|
versionNum:'Version',
|
||||||
|
systemStatus:'Status',
|
||||||
realNeStatus:'Status',
|
realNeStatus:'Status',
|
||||||
reloadTime:'Refresh Time',
|
reloadTime:'Refresh Time',
|
||||||
Critical:'Critical',
|
Critical:'Critical',
|
||||||
@@ -349,6 +351,163 @@ export default {
|
|||||||
description: "No data yet, try refreshing",
|
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",
|
||||||
|
},
|
||||||
|
},
|
||||||
dashboard: {
|
dashboard: {
|
||||||
overview:{
|
overview:{
|
||||||
title: "Core Network Dashboard",
|
title: "Core Network Dashboard",
|
||||||
@@ -420,18 +579,14 @@ export default {
|
|||||||
resultFail: "Fail",
|
resultFail: "Fail",
|
||||||
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
delTip: "Confirm deletion of the data item numbered [{msg}]?",
|
||||||
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
|
exportTip: "Do you confirm to export the current query conditions of the CDR data? (Maximum 10,000 items can be exported.)",
|
||||||
chargingID: 'Charging ID',
|
smfChargingID: 'Charging ID',
|
||||||
smfSubscriptionIDData: 'Subscription ID Data',
|
smfSubscriptionIDData: 'Subscription ID Data',
|
||||||
smfSubscriptionIDType: 'Subscription ID Type',
|
smfSubscriptionIDType: 'Subscription ID Type',
|
||||||
smfDataVolumeUplink: 'Data Volume Uplink',
|
smfDataVolumeUplink: 'Data Volume Uplink',
|
||||||
smfDataVolumeDownlink: 'Data Volume Downlink',
|
smfDataVolumeDownlink: 'Data Volume Downlink',
|
||||||
smfDataTotalVolume: 'Data Total Volume',
|
smfDataTotalVolume: 'Data Total Volume',
|
||||||
durationTime: 'Duration',
|
smfDuration: 'Duration',
|
||||||
invocationTime: 'Invocation Time',
|
smfInvocationTime: 'Invocation Time',
|
||||||
sgwcServedIMSI: 'IMSI',
|
|
||||||
sgwcServedMSISDN: 'MSISDN',
|
|
||||||
sgwcVolumeGPRSUplink: 'GPRS Uplink',
|
|
||||||
sgwcVolumeGPRSDownlink: 'GPRS Downlink',
|
|
||||||
},
|
},
|
||||||
ue: {
|
ue: {
|
||||||
eventType: "Event Type",
|
eventType: "Event Type",
|
||||||
@@ -503,7 +658,7 @@ export default {
|
|||||||
delTip: 'Confirm deletion of network element information data items?',
|
delTip: 'Confirm deletion of network element information data items?',
|
||||||
oam: {
|
oam: {
|
||||||
title: 'OAM Configuration',
|
title: 'OAM Configuration',
|
||||||
restart: 'Restart NE',
|
sync: 'Sync to NE',
|
||||||
oamEnable: 'Service',
|
oamEnable: 'Service',
|
||||||
oamPort: 'Port',
|
oamPort: 'Port',
|
||||||
snmpEnable: 'Service',
|
snmpEnable: 'Service',
|
||||||
@@ -606,7 +761,6 @@ export default {
|
|||||||
upgradeDone: 'Update complete, service being reloaded',
|
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!',
|
upgradeFail: 'The update fails, please check whether the software file exists and whether the service terminal environment is available!',
|
||||||
upgradeModal: 'Network Element Version Updates',
|
upgradeModal: 'Network Element Version Updates',
|
||||||
noPath: 'Package File Not Found',
|
|
||||||
},
|
},
|
||||||
neLicense: {
|
neLicense: {
|
||||||
status: "License Status",
|
status: "License Status",
|
||||||
@@ -630,9 +784,7 @@ export default {
|
|||||||
treeSelectTip: "Select configuration item information in the left configuration navigation!",
|
treeSelectTip: "Select configuration item information in the left configuration navigation!",
|
||||||
neType: 'NE Type',
|
neType: 'NE Type',
|
||||||
neTypePleace: "Please select the network element type",
|
neTypePleace: "Please select the network element type",
|
||||||
neIdSyncPleace: "Please select the synchronized network element",
|
|
||||||
noConfigData: "No data on configuration items",
|
noConfigData: "No data on configuration items",
|
||||||
noConfigdDisabled: "The configuration item is not normal",
|
|
||||||
updateValue: "[ {num} ] parameter value modified successfully.",
|
updateValue: "[ {num} ] parameter value modified successfully.",
|
||||||
updateValueErr: "Attribute value modification failure",
|
updateValueErr: "Attribute value modification failure",
|
||||||
updateItem: "Modify Index to {num}.",
|
updateItem: "Modify Index to {num}.",
|
||||||
@@ -693,7 +845,7 @@ export default {
|
|||||||
installSourceUpload: 'New Upload',
|
installSourceUpload: 'New Upload',
|
||||||
installSelect: 'Select Record',
|
installSelect: 'Select Record',
|
||||||
installUpload: 'Upload File',
|
installUpload: 'Upload File',
|
||||||
installText: 'Install',
|
installText: 'Installed',
|
||||||
licenseTitle: "Licenses",
|
licenseTitle: "Licenses",
|
||||||
licenseDesc: "Network element service authorization certification",
|
licenseDesc: "Network element service authorization certification",
|
||||||
licenseResultTitle: "Whether to authorize activation immediately",
|
licenseResultTitle: "Whether to authorize activation immediately",
|
||||||
@@ -706,30 +858,6 @@ export default {
|
|||||||
licenseTip2: '2. Clicking [Finish] will end the installation process.',
|
licenseTip2: '2. Clicking [Finish] will end the installation process.',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
neData: {
|
|
||||||
baseStation: {
|
|
||||||
list: "List",
|
|
||||||
topology: "Topology",
|
|
||||||
nbName: "RanNodeName",
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
neUser: {
|
neUser: {
|
||||||
auth: {
|
auth: {
|
||||||
authInfo:' Authentication Info',
|
authInfo:' Authentication Info',
|
||||||
@@ -740,7 +868,6 @@ export default {
|
|||||||
checkExport : 'Check Export',
|
checkExport : 'Check Export',
|
||||||
checkExportConfirm: 'Confirm exporting the checked authenticated user data?',
|
checkExportConfirm: 'Confirm exporting the checked authenticated user data?',
|
||||||
import: 'Import',
|
import: 'Import',
|
||||||
importFail: 'Failure Record',
|
|
||||||
loadDataConfirm: 'Are you sure you want to reload the data?',
|
loadDataConfirm: 'Are you sure you want to reload the data?',
|
||||||
loadData: 'Load 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!!!!!.',
|
loadDataTip: 'Successfully fetched loaded data: {num} items, the system is internally updating the data, it will take about {timer} seconds, please wait!!!!!.',
|
||||||
@@ -769,7 +896,6 @@ export default {
|
|||||||
checkExport : 'Check Export',
|
checkExport : 'Check Export',
|
||||||
checkExportConfirm: 'Are you sure to export the data of the checked subscribers?',
|
checkExportConfirm: 'Are you sure to export the data of the checked subscribers?',
|
||||||
import: 'Import',
|
import: 'Import',
|
||||||
importFail: 'Failure Record',
|
|
||||||
loadDataConfirm: 'Are you sure you want to reload the data?',
|
loadDataConfirm: 'Are you sure you want to reload the data?',
|
||||||
loadData: 'Load 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!!!!!.',
|
loadDataTip: 'Successfully fetched loaded data: {num} items, the system is internally updating the data, it will take about {timer} seconds, please wait!!!!!.',
|
||||||
@@ -964,7 +1090,6 @@ export default {
|
|||||||
expressionModal:'Expression Modal',
|
expressionModal:'Expression Modal',
|
||||||
expressionErrorTip:'Please check the expression, the wrong indicator is {kpiId}',
|
expressionErrorTip:'Please check the expression, the wrong indicator is {kpiId}',
|
||||||
expressionNoIdTip:'Please check the expression, no valid indicator is found',
|
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:',
|
|
||||||
},
|
},
|
||||||
kpiKeyTarget:{
|
kpiKeyTarget:{
|
||||||
"time":"Time",
|
"time":"Time",
|
||||||
@@ -983,14 +1108,8 @@ export default {
|
|||||||
},
|
},
|
||||||
kpiOverView:{
|
kpiOverView:{
|
||||||
"kpiName":"NE Metrics Name",
|
"kpiName":"NE Metrics Name",
|
||||||
"maxValue":"Max",
|
"maxValue":"Max Value",
|
||||||
"maxValueTip":"The max value of metric data within the user's filtered time range.",
|
"minValue":"Min Value",
|
||||||
"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",
|
"kpiChartTitle":"Overview of NE metrics",
|
||||||
"changeLine":"Change to Line Charts",
|
"changeLine":"Change to Line Charts",
|
||||||
"changeBar":"Change to Bar Charts",
|
"changeBar":"Change to Bar Charts",
|
||||||
@@ -999,6 +1118,25 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
traceManage: {
|
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: {
|
pcap: {
|
||||||
capArgPlease: 'Please enter tcpdump -i any support parameter',
|
capArgPlease: 'Please enter tcpdump -i any support parameter',
|
||||||
cmd: 'Command',
|
cmd: 'Command',
|
||||||
@@ -1049,35 +1187,30 @@ export default {
|
|||||||
imsiTip: 'Mobile communication IMSI number',
|
imsiTip: 'Mobile communication IMSI number',
|
||||||
srcIp: 'Source IP Address',
|
srcIp: 'Source IP Address',
|
||||||
srcIpPlease: 'Please enter the IP address',
|
srcIpPlease: 'Please enter the IP address',
|
||||||
srcIpTip: 'sending IPv4 address',
|
srcIpTip: 'Current sender IPv4 address',
|
||||||
dstIp: 'Destination IP Address',
|
dstIp: 'Destination IP Address',
|
||||||
dstIpPlease: 'Please enter the IP address',
|
dstIpPlease: 'Please enter the IP address',
|
||||||
dstIpTip: 'receiving end IPv4 address',
|
dstIpTip: 'IPv4 address of the receiving end of the other party',
|
||||||
interfaces: 'Signaling Interface',
|
interfaces: 'Signaling Interface',
|
||||||
interfacesPlease: 'Please enter the signaling interface',
|
interfacesPlease: 'Please enter the signaling interface',
|
||||||
rangePicker: 'Task Time',
|
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',
|
||||||
rangePickerPlease: 'Please select the start and end time of the task',
|
rangePickerPlease: 'Please select the start and end time of the task',
|
||||||
remark: 'Remark',
|
remark: 'Remark',
|
||||||
remarkPlease: 'Task description can be entered',
|
remarkPlease: 'Task description can be entered',
|
||||||
addTask: 'Add Task',
|
addTask: 'Add Task',
|
||||||
|
editTask: 'Modify Task',
|
||||||
viewTask: 'View Task',
|
viewTask: 'View Task',
|
||||||
errorTaskInfo: 'Failed to obtain task information',
|
errorTaskInfo: 'Failed to obtain task information',
|
||||||
delTaskTip: 'Are you sure to delete the data item with record ID {id} ?',
|
delTaskTip: 'Are you sure to delete the data item with record ID {id} ?',
|
||||||
stopTask: 'Successful cessation of tasks {id}',
|
stopTask: 'Successful cessation of tasks {id}',
|
||||||
stopTaskTip: 'Confirm stopping the task with record ID {id} ?',
|
stopTaskTip: 'Confirm stopping the task with record ID {id} ?',
|
||||||
pcapView: "Track Data Analysis",
|
pcapView: "Tracking Data Analysis",
|
||||||
traceFile: "Track File",
|
traceFile: "Tracking File",
|
||||||
errMsg: "Error Message",
|
errMsg: "Error Message",
|
||||||
imsiORmsisdn: "imsi or msisdn is null, cannot start task",
|
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: {
|
faultManage: {
|
||||||
@@ -1187,13 +1320,12 @@ export default {
|
|||||||
size: "Size",
|
size: "Size",
|
||||||
modifiedTime: "Modified Time",
|
modifiedTime: "Modified Time",
|
||||||
fileName: "File Name",
|
fileName: "File Name",
|
||||||
downTipZip: "Confirm downloading the directory [{fileName}] as a ZIP file?",
|
|
||||||
downTip: "Confirm the download file name is [{fileName}] File?",
|
downTip: "Confirm the download file name is [{fileName}] File?",
|
||||||
downTipErr: "Failed to get file",
|
downTipErr: "Failed to get file",
|
||||||
dirCd: "Enter Dir",
|
dirCd: "Enter Dir",
|
||||||
viewAs: 'View Action',
|
viewAs: 'View Action',
|
||||||
reload: "Reload",
|
reload: "Reload",
|
||||||
follow: 'Enable Instant Update',
|
follow: 'Monitoring Content',
|
||||||
tailChar: 'End Characters',
|
tailChar: 'End Characters',
|
||||||
tailLines: 'End Lines',
|
tailLines: 'End Lines',
|
||||||
},
|
},
|
||||||
|
|||||||
+193
-61
@@ -16,6 +16,7 @@ export default {
|
|||||||
errorFields: '请正确填写 {num} 处必填信息!',
|
errorFields: '请正确填写 {num} 处必填信息!',
|
||||||
tablePaginationTotal: '总共 {total} 条',
|
tablePaginationTotal: '总共 {total} 条',
|
||||||
noData: "暂无数据",
|
noData: "暂无数据",
|
||||||
|
zebra:'表格斑马纹',
|
||||||
ok: '确定',
|
ok: '确定',
|
||||||
cancel: '取消',
|
cancel: '取消',
|
||||||
close: '关闭',
|
close: '关闭',
|
||||||
@@ -130,7 +131,7 @@ export default {
|
|||||||
},
|
},
|
||||||
LockScreen: {
|
LockScreen: {
|
||||||
inputPlacePwd:'请输入锁屏密码',
|
inputPlacePwd:'请输入锁屏密码',
|
||||||
enter:'进入',
|
validSucc:'校验通过',
|
||||||
validError:'校验失败',
|
validError:'校验失败',
|
||||||
backLogin:'退出并重新登录',
|
backLogin:'退出并重新登录',
|
||||||
backReload:'正在重启,请稍等...',
|
backReload:'正在重启,请稍等...',
|
||||||
@@ -221,12 +222,13 @@ export default {
|
|||||||
capability: '用户容量',
|
capability: '用户容量',
|
||||||
serialNum: '序列号',
|
serialNum: '序列号',
|
||||||
expiryDate: '许可证到期日期',
|
expiryDate: '许可证到期日期',
|
||||||
neStatus:'状态异常',
|
neStatus:'网元状态异常',
|
||||||
runStatus:'运行状态',
|
runStatus:'运行状态',
|
||||||
mark:'信息',
|
mark:'简略信息',
|
||||||
object:'对象',
|
object:'对象',
|
||||||
versionNum:'版本号',
|
versionNum:'版本号',
|
||||||
realNeStatus:'状态',
|
systemStatus:'系统状态',
|
||||||
|
realNeStatus:'网元状态',
|
||||||
reloadTime:'刷新时间',
|
reloadTime:'刷新时间',
|
||||||
Critical:'严重告警',
|
Critical:'严重告警',
|
||||||
Major:'主要告警',
|
Major:'主要告警',
|
||||||
@@ -349,6 +351,163 @@ export default {
|
|||||||
description: "暂无数据,尝试刷新看看",
|
description: "暂无数据,尝试刷新看看",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
configManage: {
|
||||||
|
neManage: {
|
||||||
|
addNe:'添加网元',
|
||||||
|
delSure:'确认删除网元名称为{msg}的数据项 ',
|
||||||
|
editNe:'修改网元',
|
||||||
|
exportSure:'确认导出网元名称为 {msg} 的配置信息',
|
||||||
|
exportTip:'导出成功,请到备份管理进行下载',
|
||||||
|
getInfo:'获取网元信息失败',
|
||||||
|
neType:'网元类型',
|
||||||
|
neTypePlease: '请输入网元类型',
|
||||||
|
neId:'网元内部标识',
|
||||||
|
neName:'网元名称',
|
||||||
|
neTypeTip:'填写创建的网元类型,如:SMF',
|
||||||
|
uid:'资源唯一标识',
|
||||||
|
uidTip:'请输入资源唯一标识',
|
||||||
|
ip:'IP地址',
|
||||||
|
mac:'网元物理地址',
|
||||||
|
macTip:'能够定位网元的物理地址(MAC)',
|
||||||
|
port:'端口',
|
||||||
|
portTip:'最大范围0~65535',
|
||||||
|
pvflag:'网元虚拟化标识',
|
||||||
|
pnf:'物理网元',
|
||||||
|
vnf:'虚拟网元',
|
||||||
|
province:'网元服务省份',
|
||||||
|
vendorName:'厂商名称',
|
||||||
|
dn:'网络标识',
|
||||||
|
reload: '重载',
|
||||||
|
restart: '重启',
|
||||||
|
totalSure:'确认{oper}网元名称为 {msg} 的网元',
|
||||||
|
stop: '停止',
|
||||||
|
start: '启动',
|
||||||
|
log: '日志',
|
||||||
|
export: '导出',
|
||||||
|
import: '导入',
|
||||||
|
fileForm:'文件来源',
|
||||||
|
selectPlease:'请选择导入文件来源',
|
||||||
|
server:'服务器文件',
|
||||||
|
local:'本地文件',
|
||||||
|
fileSelect:'请选择当前导入文件',
|
||||||
|
sync:'同步到网元',
|
||||||
|
open:'开',
|
||||||
|
close:'关',
|
||||||
|
addFail:'新增失败',
|
||||||
|
operFail:'操作失败'
|
||||||
|
},
|
||||||
|
backupManage: {
|
||||||
|
setBackupTask: '设置自动备份时间',
|
||||||
|
neTypePlease: '查询网元类型',
|
||||||
|
neType: '网元类型',
|
||||||
|
neID: '网元内部标识',
|
||||||
|
fileName: '文件名',
|
||||||
|
createAt: '创建时间',
|
||||||
|
remark:'备份说明',
|
||||||
|
edit:'编辑备份文件',
|
||||||
|
totalSure:'确认{oper}记录编号为 {id} 的数据项?',
|
||||||
|
},
|
||||||
|
softwareManage: {
|
||||||
|
sendBtn: '下发',
|
||||||
|
runBtn: '激活',
|
||||||
|
backBtn: '回退',
|
||||||
|
historyBtn: '下发记录',
|
||||||
|
neTypePlease: '选择网元类型',
|
||||||
|
neType: '网元类型',
|
||||||
|
fileName: '文件名',
|
||||||
|
version: '版本号',
|
||||||
|
versionPlease: '版本号不能为空',
|
||||||
|
updateTime: '上传时间',
|
||||||
|
description: '功能描述',
|
||||||
|
deleteTip: '确认删除 【{fileName}】 的软件数据项?',
|
||||||
|
downloadTip: '确认下载 【{fileName}】 的软件数据项?',
|
||||||
|
updateComment: '软件说明',
|
||||||
|
updateCommentPlease: '请输入软件说明',
|
||||||
|
updateFile: '软件文件',
|
||||||
|
updateFilePlease: '请上传更新软件文件',
|
||||||
|
verifyFile: '校验文件',
|
||||||
|
selectFile: '选择文件',
|
||||||
|
sendTitle: '下发软件版本',
|
||||||
|
sendContent: '确认下发软件包为【{fileName}】的文件到对应网元?',
|
||||||
|
runTitle: '激活软件版本',
|
||||||
|
runContent: '确认在对应网元激活已下发【{fileName}】的软件版本?',
|
||||||
|
backTitle: '回退软件版本',
|
||||||
|
backContent: '确认在对应网元回退已下发【{fileName}】的软件版本?',
|
||||||
|
neId: '对应网元',
|
||||||
|
neIdPlease: '请选择对应网元',
|
||||||
|
versions:'版本',
|
||||||
|
upVersions:'升级前版本',
|
||||||
|
backVersions:'回退前版本',
|
||||||
|
status:'状态',
|
||||||
|
letUpTime:'激活时间',
|
||||||
|
createTime:'创建时间',
|
||||||
|
onlyAble:'只支持上传文件格式 {fileText}',
|
||||||
|
nullVersion:'当前网元无可回退版本',
|
||||||
|
},
|
||||||
|
license: {
|
||||||
|
neTypePlease: '选择网元类型',
|
||||||
|
neType: '网元类型',
|
||||||
|
serialNum: '序列号',
|
||||||
|
createTime: '时间',
|
||||||
|
comment: '说明',
|
||||||
|
updateComment: 'License说明',
|
||||||
|
updateCommentPlease: '请输入License说明',
|
||||||
|
updateFile: 'License文件',
|
||||||
|
updateFilePlease: '请上传更新License文件',
|
||||||
|
selectFile: '选择文件',
|
||||||
|
neId: '网元内部标识',
|
||||||
|
neIdPlease: '请选择对应网元',
|
||||||
|
},
|
||||||
|
configParam:{
|
||||||
|
dataNull:'暂无配置项数据',
|
||||||
|
editSuss:'修改成功',
|
||||||
|
editFail:'修改失败',
|
||||||
|
unable:'非法操作属性值',
|
||||||
|
delSure:'确认删除Index为 【{value}】 的数据项?',
|
||||||
|
addSuss:'新增成功',
|
||||||
|
addFail:'新增失败',
|
||||||
|
delArraySure:'确认删除{arrayChildTitle} Index 为 【{value}】 的数据项?',
|
||||||
|
parUnable:'参数值不在合理范围',
|
||||||
|
ipv4Tip:'不是合法的IPV4地址',
|
||||||
|
ipv6Tip:'不是合法的IPV6地址',
|
||||||
|
enumTip:'不是合理的枚举值',
|
||||||
|
boolTip:'不是合理的布尔类型的值',
|
||||||
|
default:'输入值是未知类型',
|
||||||
|
reloadSuss:'网元重新加载完成',
|
||||||
|
reloadFail:'网元重新加载失败',
|
||||||
|
neNUll:'暂无网元列表数据',
|
||||||
|
reload:'重载',
|
||||||
|
post:'提交',
|
||||||
|
editSure:'确认更新该属性值吗?',
|
||||||
|
arraryEdit:'确认提交更新 Index 为 【{value}】 的记录吗?',
|
||||||
|
addSure:'确认提交新增 Index :【{value}】 的记录吗?',
|
||||||
|
},
|
||||||
|
configParamForm: {
|
||||||
|
treeTitle: "配置导航",
|
||||||
|
treeSelectTip: "左侧配置导航中选择配置项信息!",
|
||||||
|
neType: "网元类型",
|
||||||
|
neTypePleace: "请选择网元类型",
|
||||||
|
noConfigData: "暂无配置项数据",
|
||||||
|
updateValue: "【 {num} 】 属性值修改成功",
|
||||||
|
updateValueErr: "属性值修改失败",
|
||||||
|
updateItem: "修改 Index 为 {num} 记录成功",
|
||||||
|
updateItemErr: "记录修改失败",
|
||||||
|
delItemOk: "删除 Index 为 {num} 记录成功",
|
||||||
|
addItemOk: "新增 Index 为 {num} 记录成功",
|
||||||
|
addItemErr: "记录新增失败",
|
||||||
|
requireUn: "【 {display} 】输入值是未知类型",
|
||||||
|
requireString: "【 {display} 】参数值不合理",
|
||||||
|
requireInt: "【 {display} 】参数值不在合理范围 {filter}",
|
||||||
|
requireIpv4: "【 {display} 】不是合法的IPV4地址",
|
||||||
|
requireIpv6: "【 {display} 】不是合法的IPV6地址",
|
||||||
|
requireEnum: "【 {display} 】不是合理的枚举值",
|
||||||
|
requireBool: "【 {display} 】不是合理的布尔类型的值",
|
||||||
|
editOkTip: "确认更新该【 {num} 】属性值吗?",
|
||||||
|
updateItemTip: "确认更新Index为 【{num}】 的数据项?",
|
||||||
|
delItemTip: "确认删除Index为 【{num}】 的数据项?",
|
||||||
|
arrayMore: "展开",
|
||||||
|
},
|
||||||
|
},
|
||||||
dashboard: {
|
dashboard: {
|
||||||
overview:{
|
overview:{
|
||||||
title: "核心网系统看板",
|
title: "核心网系统看板",
|
||||||
@@ -420,18 +579,14 @@ export default {
|
|||||||
resultFail: "失败",
|
resultFail: "失败",
|
||||||
delTip: "确认删除编号为【{msg}】的数据项?",
|
delTip: "确认删除编号为【{msg}】的数据项?",
|
||||||
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
|
exportTip: "确认导出当前查询条件的话单数据吗?(导出最大支持一万条)",
|
||||||
chargingID: '计费ID',
|
smfChargingID: '计费ID',
|
||||||
smfSubscriptionIDData: '订阅 ID 数据',
|
smfSubscriptionIDData: '订阅 ID 数据',
|
||||||
smfSubscriptionIDType: '订阅 ID 类型',
|
smfSubscriptionIDType: '订阅 ID 类型',
|
||||||
smfDataVolumeUplink: '数据量上行链路',
|
smfDataVolumeUplink: '数据量上行链路',
|
||||||
smfDataVolumeDownlink: '数据量下行链路',
|
smfDataVolumeDownlink: '数据量下行链路',
|
||||||
smfDataTotalVolume: '数据总量',
|
smfDataTotalVolume: '数据总量',
|
||||||
durationTime: '持续时间',
|
smfDuration: '持续时间',
|
||||||
invocationTime: '调用时间',
|
smfInvocationTime: '调用时间',
|
||||||
sgwcServedIMSI: 'IMSI',
|
|
||||||
sgwcServedMSISDN: 'MSISDN',
|
|
||||||
sgwcVolumeGPRSUplink: 'GPRS 上行链路',
|
|
||||||
sgwcVolumeGPRSDownlink: 'GPRS 下行链路',
|
|
||||||
},
|
},
|
||||||
ue: {
|
ue: {
|
||||||
eventType: "事件类型",
|
eventType: "事件类型",
|
||||||
@@ -503,7 +658,7 @@ export default {
|
|||||||
delTip: '确认删除网元信息数据项吗?',
|
delTip: '确认删除网元信息数据项吗?',
|
||||||
oam: {
|
oam: {
|
||||||
title: 'OAM配置',
|
title: 'OAM配置',
|
||||||
restart: '下发后重启网元',
|
sync: '同步到网元',
|
||||||
oamEnable: '服务',
|
oamEnable: '服务',
|
||||||
oamPort: '端口',
|
oamPort: '端口',
|
||||||
snmpEnable: '服务',
|
snmpEnable: '服务',
|
||||||
@@ -606,7 +761,6 @@ export default {
|
|||||||
upgradeDone: '更新完成,服务正在重载',
|
upgradeDone: '更新完成,服务正在重载',
|
||||||
upgradeFail: '更新失败,请检查软件文件是否存在且服务终端环境是否可用!',
|
upgradeFail: '更新失败,请检查软件文件是否存在且服务终端环境是否可用!',
|
||||||
upgradeModal: '网元版本更新',
|
upgradeModal: '网元版本更新',
|
||||||
noPath: '软件包文件未发现',
|
|
||||||
},
|
},
|
||||||
neLicense: {
|
neLicense: {
|
||||||
status: "许可证状态",
|
status: "许可证状态",
|
||||||
@@ -630,9 +784,7 @@ export default {
|
|||||||
treeSelectTip: "左侧配置导航中选择配置项信息!",
|
treeSelectTip: "左侧配置导航中选择配置项信息!",
|
||||||
neType: "网元类型",
|
neType: "网元类型",
|
||||||
neTypePleace: "请选择网元类型",
|
neTypePleace: "请选择网元类型",
|
||||||
neIdSyncPleace: "请选择同步网元",
|
|
||||||
noConfigData: "暂无配置项数据",
|
noConfigData: "暂无配置项数据",
|
||||||
noConfigdDisabled: "配置项网元未正常服务",
|
|
||||||
updateValue: "【 {num} 】 属性值修改成功",
|
updateValue: "【 {num} 】 属性值修改成功",
|
||||||
updateValueErr: "属性值修改失败",
|
updateValueErr: "属性值修改失败",
|
||||||
updateItem: "修改 Index 为 {num} 记录成功",
|
updateItem: "修改 Index 为 {num} 记录成功",
|
||||||
@@ -706,30 +858,6 @@ export default {
|
|||||||
licenseTip2: '2. 点击【结束】将结束安装过程',
|
licenseTip2: '2. 点击【结束】将结束安装过程',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
neData: {
|
|
||||||
baseStation: {
|
|
||||||
list: "列表",
|
|
||||||
topology: "拓扑图",
|
|
||||||
nbName: "设备名称",
|
|
||||||
ueNum: "在线用户数",
|
|
||||||
topologyTitle: "基站状态关系图",
|
|
||||||
name: "基站名称",
|
|
||||||
namePlease: "文本内容长度0~64",
|
|
||||||
position: "基站位置",
|
|
||||||
positionPlease: "位置描述。禁止空格,文本内容长度0-64",
|
|
||||||
address: "IP地址",
|
|
||||||
addressPlease: "文本内容长度0~64",
|
|
||||||
state: "基站状态",
|
|
||||||
online: "在线",
|
|
||||||
offline: "离线",
|
|
||||||
time: "变更时间",
|
|
||||||
addRadio: "添加基站信息",
|
|
||||||
editRadio: "更新基站信息",
|
|
||||||
history: "历史记录",
|
|
||||||
exportTip: "确认根据搜索条件导出xlsx表格文件吗?",
|
|
||||||
importDataEmpty: "导入数据为空",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
neUser: {
|
neUser: {
|
||||||
auth: {
|
auth: {
|
||||||
authInfo:'鉴权信息',
|
authInfo:'鉴权信息',
|
||||||
@@ -740,7 +868,6 @@ export default {
|
|||||||
checkExport : '勾选导出',
|
checkExport : '勾选导出',
|
||||||
checkExportConfirm: '确认导出已勾选的鉴权用户数据吗?',
|
checkExportConfirm: '确认导出已勾选的鉴权用户数据吗?',
|
||||||
import: '导入',
|
import: '导入',
|
||||||
importFail: '失败记录',
|
|
||||||
loadDataConfirm: '确认要重新加载数据吗?',
|
loadDataConfirm: '确认要重新加载数据吗?',
|
||||||
loadData: '加载数据',
|
loadData: '加载数据',
|
||||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,大约需要{timer}秒,请稍候!!!',
|
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,大约需要{timer}秒,请稍候!!!',
|
||||||
@@ -769,7 +896,6 @@ export default {
|
|||||||
checkExport : '勾选导出',
|
checkExport : '勾选导出',
|
||||||
checkExportConfirm: '确认导出已勾选的签约用户数据吗?',
|
checkExportConfirm: '确认导出已勾选的签约用户数据吗?',
|
||||||
import: '导入',
|
import: '导入',
|
||||||
importFail: '失败记录',
|
|
||||||
loadDataConfirm: '确认要重新加载数据吗?',
|
loadDataConfirm: '确认要重新加载数据吗?',
|
||||||
loadData: '加载数据',
|
loadData: '加载数据',
|
||||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,大约需要{timer}秒,请稍候!!!',
|
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新,大约需要{timer}秒,请稍候!!!',
|
||||||
@@ -964,7 +1090,6 @@ export default {
|
|||||||
expressionModal:'表达式模块',
|
expressionModal:'表达式模块',
|
||||||
expressionErrorTip:'请检查表达式,错误的指标为{kpiId}',
|
expressionErrorTip:'请检查表达式,错误的指标为{kpiId}',
|
||||||
expressionNoIdTip:'请检查表达式,没有找到任何有效的指标',
|
expressionNoIdTip:'请检查表达式,没有找到任何有效的指标',
|
||||||
unitSelect:'为更好展示图需选择相同单位,当前单位为:',
|
|
||||||
},
|
},
|
||||||
kpiKeyTarget:{
|
kpiKeyTarget:{
|
||||||
"time":"时间",
|
"time":"时间",
|
||||||
@@ -984,13 +1109,7 @@ export default {
|
|||||||
kpiOverView:{
|
kpiOverView:{
|
||||||
"kpiName":"指标名",
|
"kpiName":"指标名",
|
||||||
"maxValue":"最大值",
|
"maxValue":"最大值",
|
||||||
"maxValueTip":"用户筛选时间范围内度量数据的最大值。",
|
|
||||||
"minValue":"最小值",
|
"minValue":"最小值",
|
||||||
"minValueTip":"用户筛选时间范围内度量数据的最小值。",
|
|
||||||
"avgValue":"平均值",
|
|
||||||
"avgValueTip":"用户筛选时间范围内度量数据的平均值。",
|
|
||||||
"totalValue":"总值",
|
|
||||||
"totalValueTip":"用户筛选时间范围内度量数据的总值。",
|
|
||||||
"kpiChartTitle":"网元指标概览",
|
"kpiChartTitle":"网元指标概览",
|
||||||
"changeLine":"切换为折线图",
|
"changeLine":"切换为折线图",
|
||||||
"changeBar":"切换为柱状图",
|
"changeBar":"切换为柱状图",
|
||||||
@@ -999,6 +1118,25 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
traceManage: {
|
traceManage: {
|
||||||
|
analysis: {
|
||||||
|
imsi: 'IMSI',
|
||||||
|
imsiPlease: '请输入IMSI',
|
||||||
|
msisdn: 'MSISDN',
|
||||||
|
msisdnPlease: '请输入MSISDN',
|
||||||
|
trackTaskId: '跟踪任务标记',
|
||||||
|
srcIp: '源IP地址',
|
||||||
|
dstIp: '目标IP地址',
|
||||||
|
signalType: '信令类型',
|
||||||
|
msgDirect: '消息元',
|
||||||
|
msgType: '消息类型',
|
||||||
|
rowTime: '记录时间',
|
||||||
|
signalData: '信令数据',
|
||||||
|
signalDetail: '信令详情',
|
||||||
|
noData: '无信息内容',
|
||||||
|
taskTitle: '任务 {num}',
|
||||||
|
taskDownText: '下载HTML',
|
||||||
|
taskDownTip: '确认下载信令详情HTML文件?',
|
||||||
|
},
|
||||||
pcap: {
|
pcap: {
|
||||||
capArgPlease: '请输入tcpdump -i any支持参数',
|
capArgPlease: '请输入tcpdump -i any支持参数',
|
||||||
cmd: '命令',
|
cmd: '命令',
|
||||||
@@ -1049,17 +1187,21 @@ export default {
|
|||||||
imsiTip: '移动通信IMSI编号',
|
imsiTip: '移动通信IMSI编号',
|
||||||
srcIp: '源IP地址',
|
srcIp: '源IP地址',
|
||||||
srcIpPlease: '请输入源IP地址',
|
srcIpPlease: '请输入源IP地址',
|
||||||
srcIpTip: '发送端IPv4地址',
|
srcIpTip: '当前发送端IPv4地址',
|
||||||
dstIp: '目标IP地址',
|
dstIp: '目标IP地址',
|
||||||
dstIpPlease: '请输入目标IP地址',
|
dstIpPlease: '请输入目标IP地址',
|
||||||
dstIpTip: '接收端IPv4地址',
|
dstIpTip: '对方接收端IPv4地址',
|
||||||
interfaces: '信令接口',
|
interfaces: '信令接口',
|
||||||
interfacesPlease: '请输入信令接口',
|
interfacesPlease: '请输入信令接口',
|
||||||
rangePicker: '任务时间',
|
signalPort: '信令端口',
|
||||||
|
signalPortPlease: '请输入信令端口',
|
||||||
|
signalPortTip: '目标IP地址或源IP地址对应一方的端口',
|
||||||
|
rangePicker: '开始结束时间',
|
||||||
rangePickerPlease: '请选择任务时间开始结束时间',
|
rangePickerPlease: '请选择任务时间开始结束时间',
|
||||||
remark: '说明',
|
remark: '说明',
|
||||||
remarkPlease: '可输入任务说明',
|
remarkPlease: '可输入任务说明',
|
||||||
addTask: '添加任务',
|
addTask: '添加任务',
|
||||||
|
editTask: '修改任务',
|
||||||
viewTask: '查看任务',
|
viewTask: '查看任务',
|
||||||
errorTaskInfo: '获取任务信息失败',
|
errorTaskInfo: '获取任务信息失败',
|
||||||
delTaskTip: '确认删除记录编号为 {id} 的数据项?',
|
delTaskTip: '确认删除记录编号为 {id} 的数据项?',
|
||||||
@@ -1069,15 +1211,6 @@ export default {
|
|||||||
traceFile: "跟踪文件",
|
traceFile: "跟踪文件",
|
||||||
errMsg: "错误信息",
|
errMsg: "错误信息",
|
||||||
imsiORmsisdn: "imsi 或 msisdn 是空值,不能开始任务",
|
imsiORmsisdn: "imsi 或 msisdn 是空值,不能开始任务",
|
||||||
dataView: "跟踪数据",
|
|
||||||
protocolOrInterface: "协议/接口",
|
|
||||||
msgNe: '消息网元',
|
|
||||||
msgEvent: '消息事件',
|
|
||||||
msgType: '消息类型',
|
|
||||||
msgDirect: '消息方向',
|
|
||||||
msgLen: '消息长度',
|
|
||||||
rowTime: '消息时间',
|
|
||||||
taskInfo: '任务信息',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
faultManage: {
|
faultManage: {
|
||||||
@@ -1187,7 +1320,6 @@ export default {
|
|||||||
size: "文件大小",
|
size: "文件大小",
|
||||||
modifiedTime: "修改时间",
|
modifiedTime: "修改时间",
|
||||||
fileName: "文件名称",
|
fileName: "文件名称",
|
||||||
downTipZip: "确认将目录 【{fileName}】 下载为ZIP文件?",
|
|
||||||
downTip: "确认下载文件名为 【{fileName}】 文件?",
|
downTip: "确认下载文件名为 【{fileName}】 文件?",
|
||||||
downTipErr: "文件获取失败",
|
downTipErr: "文件获取失败",
|
||||||
dirCd: "进入目录",
|
dirCd: "进入目录",
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ function beforeRequest(options: OptionsType): OptionsType | Promise<any> {
|
|||||||
if (options.method === 'get') return options;
|
if (options.method === 'get') return options;
|
||||||
|
|
||||||
// 非get参数提交
|
// 非get参数提交
|
||||||
let body = options.data;
|
let body = options.data
|
||||||
if (body instanceof FormData) {
|
if (body instanceof FormData) {
|
||||||
options.body = body;
|
options.body = body;
|
||||||
} else if (body) {
|
} else if (body) {
|
||||||
|
|||||||
@@ -119,15 +119,17 @@ export class WS {
|
|||||||
};
|
};
|
||||||
// 用于指定当从服务器接受到信息时的回调函数。
|
// 用于指定当从服务器接受到信息时的回调函数。
|
||||||
ws.onmessage = ev => {
|
ws.onmessage = ev => {
|
||||||
if (ev.type !== 'message') return;
|
|
||||||
// 解析文本消息
|
// 解析文本消息
|
||||||
try {
|
if (ev.type === 'message') {
|
||||||
const jsonData = JSON.parse(ev.data);
|
const data = ev.data;
|
||||||
if (typeof options.onmessage === 'function') {
|
try {
|
||||||
options.onmessage(jsonData);
|
const jsonData = JSON.parse(data);
|
||||||
|
if (typeof options.onmessage === 'function') {
|
||||||
|
options.onmessage(jsonData);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('websocket message formatting error', error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error('websocket message formatting error', error);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 用于指定连接关闭后的回调函数。
|
// 用于指定连接关闭后的回调函数。
|
||||||
@@ -219,7 +221,7 @@ export class WS {
|
|||||||
this.heartInterval = window.setInterval(() => {
|
this.heartInterval = window.setInterval(() => {
|
||||||
this.send({
|
this.send({
|
||||||
requestId: `${Date.now()}`,
|
requestId: `${Date.now()}`,
|
||||||
type: 'PING',
|
type: 'ping',
|
||||||
});
|
});
|
||||||
}, heartTimer);
|
}, heartTimer);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-6
@@ -182,12 +182,7 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
next({ name: 'Index' });
|
next({ name: 'Index' });
|
||||||
}
|
}
|
||||||
|
|
||||||
let token = getToken();
|
const token = getToken();
|
||||||
|
|
||||||
// 免用户登录认证
|
|
||||||
if (!appStore.loginAuth) {
|
|
||||||
token = '== Not Login Auth ==';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 没有token
|
// 没有token
|
||||||
if (!token) {
|
if (!token) {
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { getSysConf } from '@/api';
|
import { getSysConf } from '@/api';
|
||||||
import { CACHE_LOCAL_I18N, CACHE_SESSION_CRYPTO_API } from '@/constants/cache-keys-constants';
|
import { CACHE_LOCAL_I18N } from '@/constants/cache-keys-constants';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { removeToken } from '@/plugins/auth-token';
|
import { removeToken } from '@/plugins/auth-token';
|
||||||
import { parseUrlPath } from '@/plugins/file-static-url';
|
import { parseUrlPath } from '@/plugins/file-static-url';
|
||||||
import { localGet, localSet } from '@/utils/cache-local-utils';
|
import { localGet, localSet } from '@/utils/cache-local-utils';
|
||||||
import { sessionSet } from '@/utils/cache-session-utils';
|
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
/**应用参数类型 */
|
/**应用参数类型 */
|
||||||
@@ -21,10 +20,6 @@ type AppStore = {
|
|||||||
buildTime: string;
|
buildTime: string;
|
||||||
/**系统引导使用 */
|
/**系统引导使用 */
|
||||||
bootloader: boolean;
|
bootloader: boolean;
|
||||||
// 用户登录认证
|
|
||||||
loginAuth: boolean;
|
|
||||||
// 用户接口加密
|
|
||||||
cryptoApi: boolean;
|
|
||||||
// 序列号
|
// 序列号
|
||||||
serialNum: string;
|
serialNum: string;
|
||||||
/**应用版权声明 */
|
/**应用版权声明 */
|
||||||
@@ -57,8 +52,6 @@ const useAppStore = defineStore('app', {
|
|||||||
version: `-`,
|
version: `-`,
|
||||||
buildTime: `-`,
|
buildTime: `-`,
|
||||||
bootloader: false,
|
bootloader: false,
|
||||||
loginAuth: true,
|
|
||||||
cryptoApi: true,
|
|
||||||
serialNum: `-`,
|
serialNum: `-`,
|
||||||
copyright: `Copyright ©2023 For ${import.meta.env.VITE_APP_NAME}`,
|
copyright: `Copyright ©2023 For ${import.meta.env.VITE_APP_NAME}`,
|
||||||
logoType: 'icon',
|
logoType: 'icon',
|
||||||
@@ -92,9 +85,6 @@ const useAppStore = defineStore('app', {
|
|||||||
if (this.bootloader) {
|
if (this.bootloader) {
|
||||||
removeToken();
|
removeToken();
|
||||||
}
|
}
|
||||||
this.loginAuth = res.data.loginAuth !== 'false';
|
|
||||||
this.cryptoApi = res.data.cryptoApi !== 'false';
|
|
||||||
sessionSet(CACHE_SESSION_CRYPTO_API, res.data.cryptoApi);
|
|
||||||
this.serialNum = res.data.serialNum;
|
this.serialNum = res.data.serialNum;
|
||||||
this.appName = res.data.title;
|
this.appName = res.data.title;
|
||||||
this.copyright = res.data.copyright;
|
this.copyright = res.data.copyright;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type MaskStateType = {
|
|||||||
const useMaskStore = defineStore('mask', {
|
const useMaskStore = defineStore('mask', {
|
||||||
state: (): MaskStateType => ({
|
state: (): MaskStateType => ({
|
||||||
type: (localGet(CACHE_LOCAL_MASK) || 'none') as MaskStateType['type'],
|
type: (localGet(CACHE_LOCAL_MASK) || 'none') as MaskStateType['type'],
|
||||||
lockPasswd: atob(localGet(CACHE_LOCAL_LOCK_PASSWD) || ''),
|
lockPasswd: localGet(CACHE_LOCAL_LOCK_PASSWD) || '',
|
||||||
lockTimeout: 0,
|
lockTimeout: 0,
|
||||||
}),
|
}),
|
||||||
getters: {},
|
getters: {},
|
||||||
@@ -59,7 +59,7 @@ const useMaskStore = defineStore('mask', {
|
|||||||
}, 5_000);
|
}, 5_000);
|
||||||
}
|
}
|
||||||
if (type === 'lock') {
|
if (type === 'lock') {
|
||||||
localSet(CACHE_LOCAL_LOCK_PASSWD, btoa(this.lockPasswd));
|
localSet(CACHE_LOCAL_LOCK_PASSWD, this.lockPasswd);
|
||||||
} else {
|
} else {
|
||||||
localRemove(CACHE_LOCAL_LOCK_PASSWD);
|
localRemove(CACHE_LOCAL_LOCK_PASSWD);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia';
|
|||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { listAllNeInfo } from '@/api/ne/neInfo';
|
import { listAllNeInfo } from '@/api/ne/neInfo';
|
||||||
import { parseDataToOptions } from '@/utils/parse-tree-utils';
|
import { parseDataToOptions } from '@/utils/parse-tree-utils';
|
||||||
|
import { getNeTraceInterfaceAll } from '@/api/trace/task';
|
||||||
import { getNePerformanceList } from '@/api/perfManage/taskManage';
|
import { getNePerformanceList } from '@/api/perfManage/taskManage';
|
||||||
|
|
||||||
/**网元信息类型 */
|
/**网元信息类型 */
|
||||||
@@ -12,6 +13,8 @@ type NeInfo = {
|
|||||||
neCascaderOptions: Record<string, any>[];
|
neCascaderOptions: Record<string, any>[];
|
||||||
/**选择器单级父类型 */
|
/**选择器单级父类型 */
|
||||||
neSelectOtions: Record<string, any>[];
|
neSelectOtions: Record<string, any>[];
|
||||||
|
/**跟踪接口列表 */
|
||||||
|
traceInterfaceList: Record<string, any>[];
|
||||||
/**性能测量数据集 */
|
/**性能测量数据集 */
|
||||||
perMeasurementList: Record<string, any>[];
|
perMeasurementList: Record<string, any>[];
|
||||||
};
|
};
|
||||||
@@ -21,6 +24,7 @@ const useNeInfoStore = defineStore('neinfo', {
|
|||||||
neList: [],
|
neList: [],
|
||||||
neCascaderOptions: [],
|
neCascaderOptions: [],
|
||||||
neSelectOtions: [],
|
neSelectOtions: [],
|
||||||
|
traceInterfaceList: [],
|
||||||
perMeasurementList: [],
|
perMeasurementList: [],
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
@@ -57,7 +61,7 @@ const useNeInfoStore = defineStore('neinfo', {
|
|||||||
const res = await listAllNeInfo({
|
const res = await listAllNeInfo({
|
||||||
bandStatus: false,
|
bandStatus: false,
|
||||||
});
|
});
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
// 原始列表
|
// 原始列表
|
||||||
this.neList = JSON.parse(JSON.stringify(res.data));
|
this.neList = JSON.parse(JSON.stringify(res.data));
|
||||||
|
|
||||||
@@ -75,6 +79,24 @@ const useNeInfoStore = defineStore('neinfo', {
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
// 刷新跟踪接口列表
|
||||||
|
async fnRefreshNeTraceInterface() {
|
||||||
|
this.traceInterfaceList = [];
|
||||||
|
const res = await this.fnNeTraceInterface();
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
// 获取跟踪接口列表
|
||||||
|
async fnNeTraceInterface() {
|
||||||
|
// 有数据不请求
|
||||||
|
if (this.traceInterfaceList.length > 0) {
|
||||||
|
return { code: 1, data: this.traceInterfaceList, msg: 'success' };
|
||||||
|
}
|
||||||
|
const res = await getNeTraceInterfaceAll();
|
||||||
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
|
this.traceInterfaceList = res.data;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
// 获取性能测量数据集列表
|
// 获取性能测量数据集列表
|
||||||
async fnNeTaskPerformance() {
|
async fnNeTaskPerformance() {
|
||||||
// 有数据不请求
|
// 有数据不请求
|
||||||
@@ -82,7 +104,7 @@ const useNeInfoStore = defineStore('neinfo', {
|
|||||||
return { code: 1, data: this.perMeasurementList, msg: 'success' };
|
return { code: 1, data: this.perMeasurementList, msg: 'success' };
|
||||||
}
|
}
|
||||||
const res = await getNePerformanceList();
|
const res = await getNePerformanceList();
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
this.perMeasurementList = res.data;
|
this.perMeasurementList = res.data;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
Vendored
-2
@@ -7,10 +7,8 @@ declare module '*.vue' {
|
|||||||
export default component;
|
export default component;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "vue3-smooth-dnd": "^0.0.6"
|
|
||||||
declare module 'vue3-smooth-dnd';
|
declare module 'vue3-smooth-dnd';
|
||||||
|
|
||||||
// "intl-tel-input": "^25.2.0"
|
|
||||||
declare module 'intl-tel-input/intlTelInputWithUtils' {
|
declare module 'intl-tel-input/intlTelInputWithUtils' {
|
||||||
import intlTelInput from 'intl-tel-input';
|
import intlTelInput from 'intl-tel-input';
|
||||||
export default intlTelInput;
|
export default intlTelInput;
|
||||||
|
|||||||
@@ -20,9 +20,6 @@ export const YYYYMMDDHHMMSS = 'YYYYMMDDHHmmss';
|
|||||||
/**年-月-日 时:分:秒 列如:2022-12-30 01:01:59 */
|
/**年-月-日 时:分:秒 列如:2022-12-30 01:01:59 */
|
||||||
export const YYYY_MM_DD_HH_MM_SS = 'YYYY-MM-DD HH:mm:ss';
|
export const YYYY_MM_DD_HH_MM_SS = 'YYYY-MM-DD HH:mm:ss';
|
||||||
|
|
||||||
/**年-月-日 时:分:秒 列如:2022-12-30T01:01:59+08:00 */
|
|
||||||
export const YYYY_MM_DD_HH_MM_SSZ = 'YYYY-MM-DDTHH:mm:ssZZ';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式时间字符串
|
* 格式时间字符串
|
||||||
* @param dateStr 时间字符串
|
* @param dateStr 时间字符串
|
||||||
@@ -39,12 +36,12 @@ export function parseStrToDate(
|
|||||||
/**
|
/**
|
||||||
* 格式时间
|
* 格式时间
|
||||||
* @param date 可转的Date对象
|
* @param date 可转的Date对象
|
||||||
* @param formatStr 时间格式 默认YYYY-MM-DD HH:mm:ssZZ
|
* @param formatStr 时间格式 默认YYYY-MM-DD HH:mm:ss
|
||||||
* @returns 时间格式字符串
|
* @returns 时间格式字符串
|
||||||
*/
|
*/
|
||||||
export function parseDateToStr(
|
export function parseDateToStr(
|
||||||
date: string | number | Date,
|
date: string | number | Date,
|
||||||
formatStr: string = YYYY_MM_DD_HH_MM_SSZ
|
formatStr: string = YYYY_MM_DD_HH_MM_SS
|
||||||
): string {
|
): string {
|
||||||
return dayjs(date).format(formatStr);
|
return dayjs(date).format(formatStr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export async function readLoalXlsx(
|
|||||||
/**
|
/**
|
||||||
* 读取表格数据 工作表
|
* 读取表格数据 工作表
|
||||||
* @param fileBolb 文件对象
|
* @param fileBolb 文件对象
|
||||||
* @param index SheetName索引
|
* @param index 文件保存路径
|
||||||
* @return 表格对象列表
|
* @return 表格对象列表
|
||||||
*/
|
*/
|
||||||
export async function readSheet(
|
export async function readSheet(
|
||||||
|
|||||||
@@ -13,41 +13,13 @@ export function generateColorHEX(): string {
|
|||||||
* @returns rgb(24 144 255) / rgba(0,0,0,.85)
|
* @returns rgb(24 144 255) / rgba(0,0,0,.85)
|
||||||
*/
|
*/
|
||||||
export function generateColorRGBA(hasAlpha: boolean = false) {
|
export function generateColorRGBA(hasAlpha: boolean = false) {
|
||||||
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
const red = Math.floor(Math.random() * 256);
|
||||||
|
const green = Math.floor(Math.random() * 256);
|
||||||
let red: number;
|
const blue = Math.floor(Math.random() * 256);
|
||||||
let green: number;
|
|
||||||
let blue: number;
|
|
||||||
|
|
||||||
if (isDark) {
|
|
||||||
// 暗色模式下生成较亮的颜色
|
|
||||||
red = Math.floor(Math.random() * 156) + 100; // 100-255
|
|
||||||
green = Math.floor(Math.random() * 156) + 100; // 100-255
|
|
||||||
blue = Math.floor(Math.random() * 156) + 100; // 100-255
|
|
||||||
|
|
||||||
// 确保至少有一个通道的值较高,使颜色更明亮
|
|
||||||
const brightChannel = Math.floor(Math.random() * 3);
|
|
||||||
switch (brightChannel) {
|
|
||||||
case 0:
|
|
||||||
red = Math.min(255, red + 50);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
green = Math.min(255, green + 50);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
blue = Math.min(255, blue + 50);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 亮色模式下生成正常的颜色
|
|
||||||
red = Math.floor(Math.random() * 256); // 0-255
|
|
||||||
green = Math.floor(Math.random() * 256); // 0-255
|
|
||||||
blue = Math.floor(Math.random() * 256); // 0-255
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasAlpha) {
|
if (hasAlpha) {
|
||||||
const alpha = Math.floor(Math.random() * 100);
|
const alpha = Math.floor(Math.random() * 100);
|
||||||
return `rgba(${red}, ${green}, ${blue}, 0.${alpha})`;
|
return `rgb(${red}, ${green}, ${blue}, 0.${alpha})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `rgb(${red}, ${green}, ${blue})`;
|
return `rgb(${red}, ${green}, ${blue})`;
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ export function parseDataToTreeExclude(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析树结构数据转出所有一维id数组
|
* 解析树结构数据转出一维id数组
|
||||||
*
|
*
|
||||||
* @param data 数组数据
|
* @param data 数组数据
|
||||||
* @param fieldId 读取节点字段 默认 'id'
|
* @param fieldId 读取节点字段 默认 'id'
|
||||||
@@ -158,7 +158,7 @@ export function parseTreeKeys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析树结构数据转出根节点的一维id数组
|
* 解析树结构数据转出含子节点的一维id数组
|
||||||
*
|
*
|
||||||
* @param data 数组数据
|
* @param data 数组数据
|
||||||
* @param fieldId 读取节点字段 默认 'id'
|
* @param fieldId 读取节点字段 默认 'id'
|
||||||
@@ -221,43 +221,3 @@ export function parseDataToOptions(
|
|||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析树结构数据转出子节点关联根节点的一维id数组
|
|
||||||
*
|
|
||||||
* @param data 数组数据
|
|
||||||
* @param checkedKeys 子节点数组数据
|
|
||||||
* @param fieldId 读取节点字段 默认 'id'
|
|
||||||
* @param fieldChildren 读取子节点字段 默认 'children'
|
|
||||||
* @returns 层级数组
|
|
||||||
*/
|
|
||||||
export function parseTreeNodeKeysByChecked(
|
|
||||||
data: Record<string, any>[],
|
|
||||||
checkedKeys: (string | number)[],
|
|
||||||
fieldId: string = 'id',
|
|
||||||
fieldChildren: string = 'children'
|
|
||||||
) {
|
|
||||||
// 节点id
|
|
||||||
let treeIds: (string | number)[] = [];
|
|
||||||
componet(data);
|
|
||||||
/**闭包递归函数 */
|
|
||||||
function componet(data: Record<string, any>[]) {
|
|
||||||
if (data.length <= 0) return false;
|
|
||||||
let hasKey = false;
|
|
||||||
for (const iterator of data) {
|
|
||||||
const key = iterator[fieldId];
|
|
||||||
if (checkedKeys.includes(key)) {
|
|
||||||
hasKey = true;
|
|
||||||
}
|
|
||||||
let nodes = iterator[fieldChildren];
|
|
||||||
if (Array.isArray(nodes) && nodes.length > 0) {
|
|
||||||
if (componet(nodes)) {
|
|
||||||
treeIds.push(key);
|
|
||||||
hasKey = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hasKey;
|
|
||||||
}
|
|
||||||
return treeIds;
|
|
||||||
}
|
|
||||||
@@ -171,8 +171,8 @@ export function parseSizeFromKbs(sizeByte: number, timeInterval: number): any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 位数据转换单位
|
* 字节数转换单位
|
||||||
* @param bits 位Bit大小 64009540 = 512.08 MB
|
* @param bits 字节Bit大小 64009540 = 512.08 MB
|
||||||
* @returns xx B / KB / MB / GB / TB / PB / EB / ZB / YB
|
* @returns xx B / KB / MB / GB / TB / PB / EB / ZB / YB
|
||||||
*/
|
*/
|
||||||
export function parseSizeFromBits(bits: number | string): string {
|
export function parseSizeFromBits(bits: number | string): string {
|
||||||
@@ -181,42 +181,7 @@ export function parseSizeFromBits(bits: number | string): string {
|
|||||||
bits = bits * 8;
|
bits = bits * 8;
|
||||||
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
const unitIndex = Math.floor(Math.log2(bits) / 10);
|
const unitIndex = Math.floor(Math.log2(bits) / 10);
|
||||||
const value = bits / Math.pow(1000, unitIndex);
|
const value = (bits / Math.pow(1000, unitIndex)).toFixed(2);
|
||||||
const unti = units[unitIndex];
|
const unti = units[unitIndex];
|
||||||
if (unitIndex > 0) {
|
|
||||||
return `${value.toFixed(2)} ${unti}`;
|
|
||||||
}
|
|
||||||
return `${value} ${unti}`;
|
return `${value} ${unti}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 字节数转换单位
|
|
||||||
* @param byte 字节Byte大小 64009540 = 512.08 MB
|
|
||||||
* @param unit 指定单位 B / KB / MB / GB / TB / PB / EB / ZB / YB
|
|
||||||
* @returns xx B / KB / MB / GB / TB / PB / EB / ZB / YB
|
|
||||||
*/
|
|
||||||
export function parseSizeFromByte(
|
|
||||||
byte: number | string,
|
|
||||||
unit?: string
|
|
||||||
): string {
|
|
||||||
byte = Number(byte) || 0;
|
|
||||||
if (byte <= 0) return '0 B';
|
|
||||||
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
||||||
let unitIndex = 0;
|
|
||||||
let unitStr = 'B';
|
|
||||||
if (unit) {
|
|
||||||
const index = units.indexOf(unit);
|
|
||||||
if (index > -1) {
|
|
||||||
unitIndex = index;
|
|
||||||
unitStr = unit;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unitIndex = Math.floor(Math.log2(byte) / 10);
|
|
||||||
unitStr = units[unitIndex];
|
|
||||||
}
|
|
||||||
const value = byte / Math.pow(1000, unitIndex);
|
|
||||||
if (unitIndex > 0) {
|
|
||||||
return `${value.toFixed(2)} ${unitStr}`;
|
|
||||||
}
|
|
||||||
return `${value} ${unitStr}`;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -2,14 +2,7 @@
|
|||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
import { ColumnsType } from 'ant-design-vue/es/table';
|
||||||
import { message } from 'ant-design-vue/es';
|
import { message } from 'ant-design-vue/es';
|
||||||
import {
|
import { reactive, ref, onMounted, onBeforeUnmount, markRaw } from 'vue';
|
||||||
reactive,
|
|
||||||
ref,
|
|
||||||
onMounted,
|
|
||||||
onBeforeUnmount,
|
|
||||||
markRaw,
|
|
||||||
useTemplateRef,
|
|
||||||
} from 'vue';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { TooltipComponent } from 'echarts/components';
|
import { TooltipComponent } from 'echarts/components';
|
||||||
import { GaugeChart } from 'echarts/charts';
|
import { GaugeChart } from 'echarts/charts';
|
||||||
@@ -39,12 +32,24 @@ echarts.use([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
/**图DOM节点实例对象 */
|
/**图DOM节点实例对象 */
|
||||||
const statusBar = useTemplateRef<HTMLDivElement>('statusBar');
|
const statusBar = ref<HTMLElement | undefined>(undefined);
|
||||||
|
|
||||||
/**图实例对象 */
|
/**图实例对象 */
|
||||||
const statusBarChart = ref<any>(null);
|
const statusBarChart = ref<any>(null);
|
||||||
|
|
||||||
|
/**网元状态字典数据 */
|
||||||
|
let indexColor = ref<DictType[]>([
|
||||||
|
{ label: 'Normal', value: 'normal', tagType: '', tagClass: '#91cc75' },
|
||||||
|
{
|
||||||
|
label: 'Abnormal',
|
||||||
|
value: 'abnormal',
|
||||||
|
tagType: '',
|
||||||
|
tagClass: '#ee6666',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
/**表格字段列 */
|
/**表格字段列 */
|
||||||
|
//customRender(){} ----单元格处理
|
||||||
let tableColumns: ColumnsType = [
|
let tableColumns: ColumnsType = [
|
||||||
{
|
{
|
||||||
title: t('views.index.object'),
|
title: t('views.index.object'),
|
||||||
@@ -62,9 +67,7 @@ let tableColumns: ColumnsType = [
|
|||||||
dataIndex: 'serverState',
|
dataIndex: 'serverState',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
if (opt.value?.refreshTime) {
|
if (opt.value?.refreshTime) return parseDateToStr(opt.value?.refreshTime);
|
||||||
return parseDateToStr(opt.value?.refreshTime, 'HH:mm:ss');
|
|
||||||
}
|
|
||||||
return '-';
|
return '-';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -101,13 +104,12 @@ let tableColumns: ColumnsType = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**表格状态类型 */
|
/**表格状态类型 */
|
||||||
type TabeStateType = {
|
type TabeStateType = {
|
||||||
/**加载等待 */
|
/**加载等待 */
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
/**记录数据 */
|
/**记录数据 */
|
||||||
data: Record<string, any>[];
|
data: object[];
|
||||||
/**勾选记录 */
|
/**勾选记录 */
|
||||||
selectedRowKeys: (string | number)[];
|
selectedRowKeys: (string | number)[];
|
||||||
};
|
};
|
||||||
@@ -119,92 +121,114 @@ let tableState: TabeStateType = reactive({
|
|||||||
selectedRowKeys: [],
|
selectedRowKeys: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
/**状态 */
|
/**表格状态 */
|
||||||
let serverState: any = ref({});
|
let nfInfo: any = reactive({
|
||||||
|
obj: 'OMC',
|
||||||
|
version: appStore.version,
|
||||||
|
status: t('views.index.normal'),
|
||||||
|
outTimeDate: '',
|
||||||
|
serialNum: appStore.serialNum,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**表格状态类型 */
|
||||||
|
type nfStateType = {
|
||||||
|
/**主机名 */
|
||||||
|
hostName: string;
|
||||||
|
/**操作系统信息 */
|
||||||
|
osInfo: string;
|
||||||
|
/**IP地址 */
|
||||||
|
ipAddress: string;
|
||||||
|
/**版本 */
|
||||||
|
version: string;
|
||||||
|
/**CPU利用率 */
|
||||||
|
cpuUse: string;
|
||||||
|
/**内存使用 */
|
||||||
|
memoryUse: string;
|
||||||
|
/**用户容量 */
|
||||||
|
capability: number;
|
||||||
|
/**序列号 */
|
||||||
|
serialNum: string;
|
||||||
|
/**许可证到期日期 */
|
||||||
|
/* selectedRowKeys: (string | number)[];*/
|
||||||
|
expiryDate: string;
|
||||||
|
};
|
||||||
|
/**网元详细信息 */
|
||||||
|
let pronInfo: nfStateType = reactive({
|
||||||
|
hostName: '5gc',
|
||||||
|
osInfo: 'Linux 5gc 4.15.0-112-generic 2020 x86_64 GNU/Linux',
|
||||||
|
ipAddress: '-',
|
||||||
|
version: '-',
|
||||||
|
cpuUse: '-',
|
||||||
|
memoryUse: '-',
|
||||||
|
capability: 0,
|
||||||
|
serialNum: '-',
|
||||||
|
expiryDate: '-',
|
||||||
|
});
|
||||||
|
|
||||||
/**查询网元状态列表 */
|
/**查询网元状态列表 */
|
||||||
async function fnGetList(reload: boolean = false) {
|
function fnGetList(one: boolean) {
|
||||||
tableState.loading = !reload;
|
if (tableState.loading) return;
|
||||||
try {
|
one && (tableState.loading = true);
|
||||||
const res = await listAllNeInfo({ bandStatus: true });
|
listAllNeInfo({ bandStatus: true }).then(res => {
|
||||||
tableState.data = res.data;
|
tableState.data = res.data;
|
||||||
} catch (error) {
|
tableState.loading = false;
|
||||||
console.error(error);
|
var rightNum = 0;
|
||||||
tableState.data = [];
|
var errorNum = 0;
|
||||||
}
|
res.data.forEach((item: any) => {
|
||||||
tableState.loading = false;
|
if (item.serverState.online) {
|
||||||
if (tableState.data.length == 0) {
|
rightNum++;
|
||||||
return;
|
} else {
|
||||||
}
|
errorNum++;
|
||||||
|
}
|
||||||
var rightNum = 0;
|
});
|
||||||
var errorNum = 0;
|
const optionData: any = {
|
||||||
for (const v of tableState.data) {
|
title: {
|
||||||
if (v?.serverState?.online) {
|
text: '',
|
||||||
rightNum++;
|
subtext: '',
|
||||||
} else {
|
left: 'center',
|
||||||
errorNum++;
|
},
|
||||||
}
|
tooltip: {
|
||||||
}
|
trigger: 'item',
|
||||||
|
},
|
||||||
// 初始
|
legend: {
|
||||||
if (!reload) {
|
orient: 'vertical',
|
||||||
// 选择第一个
|
left: 'left',
|
||||||
if (tableState.data.length > 0) {
|
},
|
||||||
const id = tableState.data[0].id;
|
color: indexColor.value.map(item => item.tagClass),
|
||||||
fnTableSelectedRowKeys([id]);
|
|
||||||
} else {
|
|
||||||
fnTableSelectedRowKeys(tableState.selectedRowKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (statusBar.value) {
|
|
||||||
fnDesign(statusBar.value, rightNum, errorNum);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
statusBarChart.value.setOption({
|
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
|
name: t('views.index.realNeStatus'),
|
||||||
|
type: 'pie',
|
||||||
|
radius: '70%',
|
||||||
|
center: ['50%', '50%'],
|
||||||
data: [
|
data: [
|
||||||
{ value: rightNum, name: t('views.index.normal') },
|
{ value: rightNum, name: t('views.index.normal') },
|
||||||
{ value: errorNum, name: t('views.index.abnormal') },
|
{ value: errorNum, name: t('views.index.abnormal') },
|
||||||
],
|
],
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
label: {},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
};
|
||||||
}
|
|
||||||
|
fnDesign(statusBar.value, optionData);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function fnDesign(container: HTMLElement, rightNum: number, errorNum: number) {
|
function fnDesign(container: HTMLElement | undefined, option: any) {
|
||||||
/// 图表数据
|
if (!container) return;
|
||||||
const optionData: any = {
|
|
||||||
title: {
|
if (!statusBarChart.value) {
|
||||||
text: '',
|
statusBarChart.value = markRaw(echarts.init(container, 'light'));
|
||||||
subtext: '',
|
}
|
||||||
left: 'center',
|
option && statusBarChart.value.setOption(option);
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
left: 'left',
|
|
||||||
},
|
|
||||||
color: dict.indexStatus.map(item => item.tagClass),
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: t('views.index.runStatus'),
|
|
||||||
type: 'pie',
|
|
||||||
radius: '70%',
|
|
||||||
center: ['50%', '50%'],
|
|
||||||
data: [
|
|
||||||
{ value: rightNum, name: t('views.index.normal') },
|
|
||||||
{ value: errorNum, name: t('views.index.abnormal') },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
statusBarChart.value = markRaw(echarts.init(container, 'light'));
|
|
||||||
statusBarChart.value.setOption(optionData);
|
|
||||||
|
|
||||||
// 创建 ResizeObserver 实例
|
// 创建 ResizeObserver 实例
|
||||||
var observer = new ResizeObserver(entries => {
|
var observer = new ResizeObserver(entries => {
|
||||||
@@ -216,43 +240,66 @@ function fnDesign(container: HTMLElement, rightNum: number, errorNum: number) {
|
|||||||
observer.observe(container);
|
observer.observe(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**表格多选 */
|
/**抽屉 网元详细信息 */
|
||||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
const open = ref(false);
|
||||||
if (keys.length <= 0) return;
|
const closeDrawer = () => {
|
||||||
const id = keys[0];
|
open.value = false;
|
||||||
const row: any = tableState.data.find((item: any) => item.id === id);
|
};
|
||||||
if (!row) {
|
/**抽屉 网元详细信息 */
|
||||||
message.error(t('views.index.neStatus'), 2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const neState = row.serverState;
|
|
||||||
if (!neState?.online) {
|
|
||||||
message.error(t('views.index.neStatus'), 2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tableState.selectedRowKeys = keys;
|
|
||||||
// Mem 将KB转换为MB
|
|
||||||
const totalMemInKB = neState.mem?.totalMem;
|
|
||||||
const nfUsedMemInKB = neState.mem?.nfUsedMem;
|
|
||||||
const sysMemUsageInKB = neState.mem?.sysMemUsage;
|
|
||||||
const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
|
|
||||||
const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
|
|
||||||
const sysMemUsageInMB = Math.round((sysMemUsageInKB / 1024) * 100) / 100;
|
|
||||||
|
|
||||||
// CPU
|
/**监听表格行事件*/
|
||||||
const nfCpu = neState.cpu?.nfCpuUsage;
|
function rowClick(record: any, index: any) {
|
||||||
const sysCpu = neState.cpu?.sysCpuUsage;
|
return {
|
||||||
const nfCpuP = Math.round(nfCpu) / 100;
|
onClick: (event: any) => {
|
||||||
const sysCpuP = Math.round(sysCpu) / 100;
|
let pronData = JSON.parse(JSON.stringify(record.serverState));
|
||||||
|
if (!pronData.online) {
|
||||||
|
message.error(t('views.index.neStatus'), 2);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
const totalMemInKB = pronData.mem?.totalMem;
|
||||||
|
const nfUsedMemInKB = pronData.mem?.nfUsedMem;
|
||||||
|
const sysMemUsageInKB = pronData.mem?.sysMemUsage;
|
||||||
|
|
||||||
serverState.value = Object.assign(
|
// 将KB转换为MB
|
||||||
{
|
const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
|
||||||
cpuUse: `NE:${nfCpuP}%; SYS:${sysCpuP}%`,
|
const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
|
||||||
memoryUse: `Total: ${totalMemInMB}MB; NE: ${nfUsedMemInMB}MB; SYS: ${sysMemUsageInMB}MB`,
|
const sysMemUsageInMB =
|
||||||
|
Math.round((sysMemUsageInKB / 1024) * 100) / 100;
|
||||||
|
|
||||||
|
//渲染详细信息
|
||||||
|
pronInfo = {
|
||||||
|
hostName: pronData.hostname,
|
||||||
|
osInfo: pronData.os,
|
||||||
|
ipAddress: pronData.neIP,
|
||||||
|
version: pronData.version,
|
||||||
|
cpuUse:
|
||||||
|
pronData.neName +
|
||||||
|
':' +
|
||||||
|
pronData.cpu?.nfCpuUsage / 100 +
|
||||||
|
'%; ' +
|
||||||
|
'SYS:' +
|
||||||
|
pronData.cpu?.sysCpuUsage / 100 +
|
||||||
|
'%',
|
||||||
|
memoryUse:
|
||||||
|
'Total:' +
|
||||||
|
totalMemInMB +
|
||||||
|
'MB; ' +
|
||||||
|
pronData.name +
|
||||||
|
':' +
|
||||||
|
nfUsedMemInMB +
|
||||||
|
'MB; SYS:' +
|
||||||
|
sysMemUsageInMB +
|
||||||
|
'MB',
|
||||||
|
capability: pronData.capability,
|
||||||
|
serialNum: pronData.sn,
|
||||||
|
expiryDate: pronData.expire,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
open.value = true;
|
||||||
},
|
},
|
||||||
neState
|
};
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
let timer: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 国际化翻译转换
|
* 国际化翻译转换
|
||||||
@@ -265,48 +312,63 @@ function fnLocale() {
|
|||||||
appStore.setTitle(title);
|
appStore.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**字典数据 */
|
|
||||||
let dict: {
|
|
||||||
/**网元信息状态 */
|
|
||||||
neInfoStatus: DictType[];
|
|
||||||
/**主页状态 */
|
|
||||||
indexStatus: DictType[];
|
|
||||||
} = reactive({
|
|
||||||
neInfoStatus: [],
|
|
||||||
indexStatus: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
let timer: any;
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 初始字典数据
|
getDict('index_status')
|
||||||
Promise.allSettled([getDict('ne_info_status'), getDict('index_status')])
|
.then(res => {
|
||||||
.then(resArr => {
|
if (res.length > 0) {
|
||||||
if (resArr[0].status === 'fulfilled') {
|
indexColor.value = res;
|
||||||
dict.neInfoStatus = resArr[0].value;
|
|
||||||
}
|
|
||||||
if (resArr[1].status === 'fulfilled') {
|
|
||||||
dict.indexStatus = resArr[1].value;
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(async () => {
|
.finally(() => {
|
||||||
fnLocale();
|
fnLocale();
|
||||||
await fnGetList(false);
|
fnGetList(true);
|
||||||
timer = setInterval(() => {
|
timer = setInterval(() => fnGetList(false), 10000); // 每隔10秒执行一次
|
||||||
if (!timer) return;
|
|
||||||
fnGetList(true);
|
|
||||||
}, 10_000); // 每隔10秒执行一次
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 在组件卸载之前清除定时器
|
// 在组件卸载之前清除定时器
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
timer = null;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PageContainer :breadcrumb="{}">
|
<PageContainer :breadcrumb="{}">
|
||||||
|
<div>
|
||||||
|
<a-drawer :open="open" @close="closeDrawer" :width="700">
|
||||||
|
<a-descriptions bordered :column="1" :label-style="{ width: '160px' }">
|
||||||
|
<a-descriptions-item :label="t('views.index.hostName')">{{
|
||||||
|
pronInfo.hostName
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.osInfo')">{{
|
||||||
|
pronInfo.osInfo
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.ipAddress')">{{
|
||||||
|
pronInfo.ipAddress
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.version')">{{
|
||||||
|
pronInfo.version
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.capability')">{{
|
||||||
|
pronInfo.capability
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.cpuUse')">{{
|
||||||
|
pronInfo.cpuUse
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.memoryUse')">{{
|
||||||
|
pronInfo.memoryUse
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
||||||
|
pronInfo.serialNum
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
||||||
|
pronInfo.expiryDate
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</a-drawer>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="14" :md="16" :xs="24">
|
<a-col :lg="14" :md="16" :xs="24">
|
||||||
<!-- 表格列表 -->
|
<!-- 表格列表 -->
|
||||||
@@ -315,20 +377,20 @@ onBeforeUnmount(() => {
|
|||||||
row-key="id"
|
row-key="id"
|
||||||
size="small"
|
size="small"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
:data-source="tableState.data"
|
|
||||||
:loading="tableState.loading"
|
:loading="tableState.loading"
|
||||||
|
:data-source="tableState.data"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:scroll="{ x: true }"
|
:scroll="{ x: true }"
|
||||||
:row-selection="{
|
:customRow="rowClick"
|
||||||
type: 'radio',
|
|
||||||
columnWidth: '48px',
|
|
||||||
selectedRowKeys: tableState.selectedRowKeys,
|
|
||||||
onChange: fnTableSelectedRowKeys,
|
|
||||||
}"
|
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
<DictTag :options="dict.neInfoStatus" :value="record.status" />
|
<div v-if="record.serverState.online">
|
||||||
|
<a-tag color="blue">{{ t('views.index.normal') }}</a-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<a-tag color="pink">{{ t('views.index.abnormal') }}</a-tag>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
@@ -342,8 +404,7 @@ onBeforeUnmount(() => {
|
|||||||
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
|
<div style="width: 100%; min-height: 200px" ref="statusBar"></div>
|
||||||
</a-card>
|
</a-card>
|
||||||
<a-card
|
<a-card
|
||||||
:loading="tableState.loading"
|
:title="t('views.index.mark')"
|
||||||
:title="`${t('views.index.mark')} - ${serverState.neName || 'OMC'}`"
|
|
||||||
style="margin-top: 16px"
|
style="margin-top: 16px"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
@@ -352,33 +413,25 @@ onBeforeUnmount(() => {
|
|||||||
:column="1"
|
:column="1"
|
||||||
:label-style="{ width: '160px' }"
|
:label-style="{ width: '160px' }"
|
||||||
>
|
>
|
||||||
<a-descriptions-item :label="t('views.index.hostName')">
|
<a-descriptions-item :label="t('views.index.object')">{{
|
||||||
{{ serverState.hostname }}
|
nfInfo.obj
|
||||||
</a-descriptions-item>
|
}}</a-descriptions-item>
|
||||||
<a-descriptions-item :label="t('views.index.osInfo')">
|
<template v-if="nfInfo.obj === 'OMC'">
|
||||||
{{ serverState.os }}
|
<a-descriptions-item :label="t('views.index.versionNum')">{{
|
||||||
</a-descriptions-item>
|
nfInfo.version
|
||||||
<a-descriptions-item :label="t('views.index.ipAddress')">
|
}}</a-descriptions-item>
|
||||||
{{ serverState.neIP }}
|
<a-descriptions-item :label="t('views.index.systemStatus')">{{
|
||||||
</a-descriptions-item>
|
nfInfo.status
|
||||||
<a-descriptions-item :label="t('views.index.version')">
|
}}</a-descriptions-item>
|
||||||
{{ serverState.version }}
|
</template>
|
||||||
</a-descriptions-item>
|
<template v-else>
|
||||||
<a-descriptions-item :label="t('views.index.capability')">
|
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
||||||
{{ serverState.capability }}
|
nfInfo.serialNum
|
||||||
</a-descriptions-item>
|
}}</a-descriptions-item>
|
||||||
<a-descriptions-item :label="t('views.index.cpuUse')">
|
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
||||||
{{ serverState.cpuUse }}
|
nfInfo.outTimeDate
|
||||||
</a-descriptions-item>
|
}}</a-descriptions-item>
|
||||||
<a-descriptions-item :label="t('views.index.memoryUse')">
|
</template>
|
||||||
{{ serverState.memoryUse }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.serialNum')">
|
|
||||||
{{ serverState.sn }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item :label="t('views.index.expiryDate')">
|
|
||||||
{{ serverState.expire }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
</a-descriptions>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|||||||
+123
-181
@@ -11,21 +11,14 @@ import {
|
|||||||
RESULT_CODE_SUCCESS,
|
RESULT_CODE_SUCCESS,
|
||||||
} from '@/constants/result-constants';
|
} from '@/constants/result-constants';
|
||||||
import useDictStore from '@/store/modules/dict';
|
import useDictStore from '@/store/modules/dict';
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
|
||||||
import { listAMFDataUE, delAMFDataUE, exportAMFDataUE } from '@/api/neData/amf';
|
import { listAMFDataUE, delAMFDataUE, exportAMFDataUE } from '@/api/neData/amf';
|
||||||
import { parseDateToStr } from '@/utils/date-utils';
|
|
||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
import { useClipboard } from '@vueuse/core';
|
|
||||||
const { copy } = useClipboard({ legacy: true });
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { getDict } = useDictStore();
|
const { getDict } = useDictStore();
|
||||||
const ws = new WS();
|
const ws = new WS();
|
||||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||||
/**网元可选 */
|
|
||||||
let neOtions = ref<Record<string, any>[]>([]);
|
|
||||||
|
|
||||||
/**字典数据 */
|
/**字典数据 */
|
||||||
let dict: {
|
let dict: {
|
||||||
@@ -42,10 +35,7 @@ let dict: {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**开始结束时间 */
|
/**开始结束时间 */
|
||||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>([
|
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||||
dayjs().startOf('hour'),
|
|
||||||
dayjs().endOf('hour'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
/**查询参数 */
|
||||||
let queryParams = reactive({
|
let queryParams = reactive({
|
||||||
@@ -57,9 +47,9 @@ let queryParams = reactive({
|
|||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
/**开始时间 */
|
/**开始时间 */
|
||||||
startTime: undefined as undefined | number,
|
startTime: '',
|
||||||
/**结束时间 */
|
/**结束时间 */
|
||||||
endTime: undefined as undefined | number,
|
endTime: '',
|
||||||
/**当前页数 */
|
/**当前页数 */
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
/**每页条数 */
|
/**每页条数 */
|
||||||
@@ -77,7 +67,7 @@ function fnQueryReset() {
|
|||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
});
|
});
|
||||||
queryRangePicker.value = [dayjs().startOf('hour'), dayjs().endOf('hour')];
|
queryRangePicker.value = ['', ''];
|
||||||
tablePagination.current = 1;
|
tablePagination.current = 1;
|
||||||
tablePagination.pageSize = 20;
|
tablePagination.pageSize = 20;
|
||||||
fnGetList();
|
fnGetList();
|
||||||
@@ -151,15 +141,9 @@ let tableColumns: ColumnsType = [
|
|||||||
{
|
{
|
||||||
title: t('views.dashboard.ue.time'),
|
title: t('views.dashboard.ue.time'),
|
||||||
dataIndex: 'eventJSON',
|
dataIndex: 'eventJSON',
|
||||||
|
key: 'time',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 150,
|
width: 150,
|
||||||
customRender(opt) {
|
|
||||||
const record = opt.value;
|
|
||||||
if (record?.time) {
|
|
||||||
return record.time;
|
|
||||||
}
|
|
||||||
return parseDateToStr(+record.timestamp * 1000);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('common.operate'),
|
title: t('common.operate'),
|
||||||
@@ -268,19 +252,11 @@ function fnGetList(pageNum?: number) {
|
|||||||
if (pageNum) {
|
if (pageNum) {
|
||||||
queryParams.pageNum = pageNum;
|
queryParams.pageNum = pageNum;
|
||||||
}
|
}
|
||||||
|
if (!queryRangePicker.value) {
|
||||||
// 时间范围
|
queryRangePicker.value = ['', ''];
|
||||||
if (
|
|
||||||
Array.isArray(queryRangePicker.value) &&
|
|
||||||
queryRangePicker.value.length > 0
|
|
||||||
) {
|
|
||||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
|
||||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
|
||||||
} else {
|
|
||||||
queryParams.startTime = undefined;
|
|
||||||
queryParams.endTime = undefined;
|
|
||||||
}
|
}
|
||||||
|
queryParams.startTime = queryRangePicker.value[0];
|
||||||
|
queryParams.endTime = queryRangePicker.value[1];
|
||||||
listAMFDataUE(toRaw(queryParams)).then(res => {
|
listAMFDataUE(toRaw(queryParams)).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
// 取消勾选
|
// 取消勾选
|
||||||
@@ -348,18 +324,6 @@ function fnExportList() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制CDR
|
|
||||||
* @param jsonStr JSON字符串
|
|
||||||
*/
|
|
||||||
function fnRecordCopy(jsonStr: string) {
|
|
||||||
if (!jsonStr) return;
|
|
||||||
const text = JSON.stringify(jsonStr, null, 2);
|
|
||||||
copy(text).then(() => {
|
|
||||||
message.success(t('common.copyOk'), 3);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**实时数据开关 */
|
/**实时数据开关 */
|
||||||
const realTimeData = ref<boolean>(false);
|
const realTimeData = ref<boolean>(false);
|
||||||
|
|
||||||
@@ -369,30 +333,31 @@ const realTimeData = ref<boolean>(false);
|
|||||||
function fnRealTime() {
|
function fnRealTime() {
|
||||||
realTimeData.value = !realTimeData.value;
|
realTimeData.value = !realTimeData.value;
|
||||||
if (realTimeData.value) {
|
if (realTimeData.value) {
|
||||||
tableState.seached = false;
|
|
||||||
// 建立链接
|
// 建立链接
|
||||||
const options: OptionsType = {
|
const options: OptionsType = {
|
||||||
url: '/ws',
|
url: '/ws',
|
||||||
params: {
|
params: {
|
||||||
/**订阅通道组
|
/**订阅通道组
|
||||||
*
|
*
|
||||||
* AMF_UE会话事件(GroupID:1010_neId)
|
* AMF_UE会话事件(GroupID:1010)
|
||||||
*/
|
*/
|
||||||
subGroupID: `1010_${queryParams.neId}`,
|
subGroupID: '1010',
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: (ev: any) => {
|
onerror: wsError,
|
||||||
console.error(ev);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
} else {
|
} else {
|
||||||
ws.close();
|
ws.close();
|
||||||
tableState.seached = true;
|
|
||||||
fnGetList(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**接收数据后回调 */
|
||||||
|
function wsError(ev: any) {
|
||||||
|
// 接收数据后回调
|
||||||
|
console.error(ev);
|
||||||
|
}
|
||||||
|
|
||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsMessage(res: Record<string, any>) {
|
function wsMessage(res: Record<string, any>) {
|
||||||
const { code, requestId, data } = res;
|
const { code, requestId, data } = res;
|
||||||
@@ -406,7 +371,7 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// ueEvent AMF_UE会话事件
|
// ueEvent AMF_UE会话事件
|
||||||
if (data.groupId === `1010_${queryParams.neId}`) {
|
if (data.groupId === '1010') {
|
||||||
const ueEvent = data.data;
|
const ueEvent = data.data;
|
||||||
queue.add(async () => {
|
queue.add(async () => {
|
||||||
modalState.maxId += 1;
|
modalState.maxId += 1;
|
||||||
@@ -434,40 +399,16 @@ onMounted(() => {
|
|||||||
getDict('ue_auth_code'),
|
getDict('ue_auth_code'),
|
||||||
getDict('ue_event_type'),
|
getDict('ue_event_type'),
|
||||||
getDict('ue_event_cm_state'),
|
getDict('ue_event_cm_state'),
|
||||||
]).then(resArr => {
|
])
|
||||||
if (resArr[0].status === 'fulfilled') {
|
.then(resArr => {
|
||||||
dict.ueAauthCode = resArr[0].value;
|
if (resArr[0].status === 'fulfilled') {
|
||||||
}
|
dict.ueAauthCode = resArr[0].value;
|
||||||
if (resArr[1].status === 'fulfilled') {
|
}
|
||||||
dict.ueEventType = resArr[1].value;
|
if (resArr[1].status === 'fulfilled') {
|
||||||
}
|
dict.ueEventType = resArr[1].value;
|
||||||
if (resArr[2].status === 'fulfilled') {
|
}
|
||||||
dict.ueEventCmState = resArr[2].value;
|
if (resArr[2].status === 'fulfilled') {
|
||||||
}
|
dict.ueEventCmState = resArr[2].value;
|
||||||
});
|
|
||||||
|
|
||||||
// 获取网元网元列表
|
|
||||||
useNeInfoStore()
|
|
||||||
.fnNelist()
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
if (res.data.length > 0) {
|
|
||||||
let arr: Record<string, any>[] = [];
|
|
||||||
res.data.forEach(i => {
|
|
||||||
if (i.neType === 'AMF') {
|
|
||||||
arr.push({ value: i.neId, label: i.neName });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
neOtions.value = arr;
|
|
||||||
if (arr.length > 0) {
|
|
||||||
queryParams.neId = arr[0].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message.warning({
|
|
||||||
content: t('common.noData'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -493,16 +434,6 @@ onBeforeUnmount(() => {
|
|||||||
<!-- 表格搜索栏 -->
|
<!-- 表格搜索栏 -->
|
||||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
|
||||||
<a-form-item label="AMF" name="neId ">
|
|
||||||
<a-select
|
|
||||||
v-model:value="queryParams.neId"
|
|
||||||
:options="neOtions"
|
|
||||||
:placeholder="t('common.selectPlease')"
|
|
||||||
@change="fnGetList(1)"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.dashboard.ue.eventType')"
|
:label="t('views.dashboard.ue.eventType')"
|
||||||
@@ -517,7 +448,7 @@ onBeforeUnmount(() => {
|
|||||||
></a-select>
|
></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
<a-col :lg="4" :md="12" :xs="24">
|
||||||
<a-form-item label="IMSI" name="imsi ">
|
<a-form-item label="IMSI" name="imsi ">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="queryParams.imsi"
|
v-model:value="queryParams.imsi"
|
||||||
@@ -526,20 +457,6 @@ onBeforeUnmount(() => {
|
|||||||
></a-input>
|
></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</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-col :lg="8" :md="12" :xs="24">
|
<a-col :lg="8" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.dashboard.cdr.time')"
|
:label="t('views.dashboard.cdr.time')"
|
||||||
@@ -556,6 +473,20 @@ onBeforeUnmount(() => {
|
|||||||
></a-range-picker>
|
></a-range-picker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</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-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-card>
|
</a-card>
|
||||||
@@ -591,7 +522,6 @@ onBeforeUnmount(() => {
|
|||||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||||
:loading="modalState.confirmLoading"
|
:loading="modalState.confirmLoading"
|
||||||
@click.prevent="fnRecordDelete('0')"
|
@click.prevent="fnRecordDelete('0')"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon><DeleteOutlined /></template>
|
<template #icon><DeleteOutlined /></template>
|
||||||
{{ t('common.deleteText') }}
|
{{ t('common.deleteText') }}
|
||||||
@@ -614,7 +544,6 @@ onBeforeUnmount(() => {
|
|||||||
:checked-children="t('common.switch.show')"
|
:checked-children="t('common.switch.show')"
|
||||||
:un-checked-children="t('common.switch.hide')"
|
:un-checked-children="t('common.switch.hide')"
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="realTimeData"
|
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
@@ -675,7 +604,7 @@ onBeforeUnmount(() => {
|
|||||||
<span v-if="record.eventType === 'auth-result'">
|
<span v-if="record.eventType === 'auth-result'">
|
||||||
<DictTag
|
<DictTag
|
||||||
:options="dict.ueAauthCode"
|
:options="dict.ueAauthCode"
|
||||||
:value="record.eventJSON.result"
|
:value="record.eventJSON.authCode"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="record.eventType === 'detach'">
|
<span v-if="record.eventType === 'detach'">
|
||||||
@@ -684,29 +613,37 @@ onBeforeUnmount(() => {
|
|||||||
<span v-if="record.eventType === 'cm-state'">
|
<span v-if="record.eventType === 'cm-state'">
|
||||||
<DictTag
|
<DictTag
|
||||||
:options="dict.ueEventCmState"
|
:options="dict.ueEventCmState"
|
||||||
:value="record.eventJSON.result"
|
:value="record.eventJSON.status"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="column.key === 'time'">
|
||||||
|
<span
|
||||||
|
v-if="record.eventType === 'auth-result'"
|
||||||
|
:title="record.eventJSON.authTime"
|
||||||
|
>
|
||||||
|
{{ record.eventJSON.authTime }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="record.eventType === 'detach'"
|
||||||
|
:title="record.eventJSON.detachTime"
|
||||||
|
>
|
||||||
|
{{ record.eventJSON.detachTime }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="record.eventType === 'cm-state'"
|
||||||
|
:title="record.eventJSON.changeTime"
|
||||||
|
>
|
||||||
|
{{ record.eventJSON.changeTime }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<template v-if="column.key === 'id'">
|
<template v-if="column.key === 'id'">
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.copyText') }}</template>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
@click.prevent="fnRecordCopy(record.eventJSON)"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<CopyOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.deleteText') }}</template>
|
<template #title>{{ t('common.deleteText') }}</template>
|
||||||
<a-button
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
@click.prevent="fnRecordDelete(record.id)"
|
@click.prevent="fnRecordDelete(record.id)"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<DeleteOutlined />
|
<DeleteOutlined />
|
||||||
@@ -717,60 +654,65 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template #expandedRowRender="{ record }">
|
<template #expandedRowRender="{ record }">
|
||||||
<a-row :gutter="16">
|
<div style="width: 46%; padding-left: 32px; padding-bottom: 16px">
|
||||||
<a-col :lg="8" :md="12" :xs="24" :offset="2">
|
<a-divider orientation="left">
|
||||||
<a-divider orientation="left">
|
{{ t('views.dashboard.ue.ueInfo') }}
|
||||||
{{ t('views.dashboard.ue.ueInfo') }}
|
</a-divider>
|
||||||
</a-divider>
|
<div>
|
||||||
<div>
|
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
<span>{{ record.neName }}</span>
|
||||||
<span>{{ record.neName }}</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
<span>{{ record.rmUID }}</span>
|
||||||
<span>{{ record.rmUID }}</span>
|
</div>
|
||||||
</div>
|
<a-divider orientation="left">
|
||||||
</a-col>
|
{{ t('views.dashboard.ue.rowInfo') }}
|
||||||
<a-col :lg="8" :md="12" :xs="24">
|
</a-divider>
|
||||||
<a-divider orientation="left">
|
<div>
|
||||||
{{ t('views.dashboard.ue.rowInfo') }}
|
<span>{{ t('views.dashboard.ue.time') }}: </span>
|
||||||
</a-divider>
|
<span
|
||||||
<div>
|
v-if="record.eventType === 'auth-result'"
|
||||||
<span>{{ t('views.dashboard.ue.time') }}: </span>
|
:title="record.eventJSON.authTime"
|
||||||
<template v-if="record.eventJSON?.time">
|
>
|
||||||
{{ record.eventJSON.time }}
|
{{ record.eventJSON.authTime }}
|
||||||
</template>
|
</span>
|
||||||
<template v-else>
|
<span
|
||||||
{{ parseDateToStr(record.eventJSON.timestamp * 1000) }}
|
v-if="record.eventType === 'detach'"
|
||||||
</template>
|
:title="record.eventJSON.detachTime"
|
||||||
</div>
|
>
|
||||||
<div>
|
{{ record.eventJSON.detachTime }}
|
||||||
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="record.eventType === 'cm-state'"
|
||||||
|
:title="record.eventJSON.changeTime"
|
||||||
|
>
|
||||||
|
{{ record.eventJSON.changeTime }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
||||||
|
<DictTag :options="dict.ueEventType" :value="record.eventType" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
||||||
|
<span v-if="record.eventType === 'auth-result'">
|
||||||
<DictTag
|
<DictTag
|
||||||
:options="dict.ueEventType"
|
:options="dict.ueAauthCode"
|
||||||
:value="record.eventType"
|
:value="record.eventJSON.authCode"
|
||||||
/>
|
/>
|
||||||
</div>
|
</span>
|
||||||
<div>
|
<span v-if="record.eventType === 'detach'">
|
||||||
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
{{ t('views.dashboard.ue.resultOk') }}
|
||||||
<span v-if="record.eventType === 'auth-result'">
|
</span>
|
||||||
<DictTag
|
<span v-if="record.eventType === 'cm-state'">
|
||||||
:options="dict.ueAauthCode"
|
<DictTag
|
||||||
:value="record.eventJSON.result"
|
:options="dict.ueEventCmState"
|
||||||
/>
|
:value="record.eventJSON.status"
|
||||||
</span>
|
/>
|
||||||
<span v-if="record.eventType === 'detach'">
|
</span>
|
||||||
{{ t('views.dashboard.ue.resultOk') }}
|
</div>
|
||||||
</span>
|
</div>
|
||||||
<span v-if="record.eventType === 'cm-state'">
|
|
||||||
<DictTag
|
|
||||||
:options="dict.ueEventCmState"
|
|
||||||
:value="record.eventJSON.result"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|||||||
@@ -21,9 +21,6 @@ import { parseDateToStr, parseDuration } from '@/utils/date-utils';
|
|||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
import { useClipboard } from '@vueuse/core';
|
|
||||||
import dayjs, { type Dayjs } from 'dayjs';
|
|
||||||
const { copy } = useClipboard({ legacy: true });
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { getDict } = useDictStore();
|
const { getDict } = useDictStore();
|
||||||
const ws = new WS();
|
const ws = new WS();
|
||||||
@@ -44,25 +41,7 @@ let dict: {
|
|||||||
let neOtions = ref<Record<string, any>[]>([]);
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
/**开始结束时间 */
|
/**开始结束时间 */
|
||||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>([
|
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||||
dayjs().startOf('hour'),
|
|
||||||
dayjs().endOf('hour'),
|
|
||||||
]);
|
|
||||||
/**时间范围 */
|
|
||||||
let rangePickerPresets = ref([
|
|
||||||
{
|
|
||||||
label: 'Now hour',
|
|
||||||
value: [dayjs().startOf('hour'), dayjs().endOf('hour')],
|
|
||||||
},
|
|
||||||
{ label: 'Today', value: [dayjs().startOf('day'), dayjs().endOf('day')] },
|
|
||||||
{
|
|
||||||
label: 'Yesterday',
|
|
||||||
value: [
|
|
||||||
dayjs().subtract(1, 'day').startOf('day'),
|
|
||||||
dayjs().subtract(1, 'day').endOf('day'),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
/**查询参数 */
|
||||||
let queryParams = reactive({
|
let queryParams = reactive({
|
||||||
@@ -75,9 +54,9 @@ let queryParams = reactive({
|
|||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
/**开始时间 */
|
/**开始时间 */
|
||||||
startTime: undefined as undefined | number,
|
startTime: '',
|
||||||
/**结束时间 */
|
/**结束时间 */
|
||||||
endTime: undefined as undefined | number,
|
endTime: '',
|
||||||
/**当前页数 */
|
/**当前页数 */
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
/**每页条数 */
|
/**每页条数 */
|
||||||
@@ -91,12 +70,12 @@ function fnQueryReset() {
|
|||||||
recordType: '',
|
recordType: '',
|
||||||
callerParty: '',
|
callerParty: '',
|
||||||
calledParty: '',
|
calledParty: '',
|
||||||
startTime: undefined,
|
startTime: '',
|
||||||
endTime: undefined,
|
endTime: '',
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
});
|
});
|
||||||
queryRangePicker.value = [dayjs().startOf('hour'), dayjs().endOf('hour')];
|
queryRangePicker.value = ['', ''];
|
||||||
tablePagination.current = 1;
|
tablePagination.current = 1;
|
||||||
tablePagination.pageSize = 20;
|
tablePagination.pageSize = 20;
|
||||||
fnGetList();
|
fnGetList();
|
||||||
@@ -328,18 +307,6 @@ function fnRecordDelete(id: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制CDR
|
|
||||||
* @param jsonStr JSON字符串
|
|
||||||
*/
|
|
||||||
function fnRecordCopy(jsonStr: string) {
|
|
||||||
if (!jsonStr) return;
|
|
||||||
const text = JSON.stringify(jsonStr, null, 2);
|
|
||||||
copy(text).then(() => {
|
|
||||||
message.success(t('common.copyOk'), 3);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**查询列表, pageNum初始页数 */
|
/**查询列表, pageNum初始页数 */
|
||||||
function fnGetList(pageNum?: number) {
|
function fnGetList(pageNum?: number) {
|
||||||
if (tableState.loading) return;
|
if (tableState.loading) return;
|
||||||
@@ -347,17 +314,11 @@ function fnGetList(pageNum?: number) {
|
|||||||
if (pageNum) {
|
if (pageNum) {
|
||||||
queryParams.pageNum = pageNum;
|
queryParams.pageNum = pageNum;
|
||||||
}
|
}
|
||||||
// 时间范围
|
if (!queryRangePicker.value) {
|
||||||
if (
|
queryRangePicker.value = ['', ''];
|
||||||
Array.isArray(queryRangePicker.value) &&
|
|
||||||
queryRangePicker.value.length > 0
|
|
||||||
) {
|
|
||||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
|
||||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
|
||||||
} else {
|
|
||||||
queryParams.startTime = undefined;
|
|
||||||
queryParams.endTime = undefined;
|
|
||||||
}
|
}
|
||||||
|
queryParams.startTime = queryRangePicker.value[0];
|
||||||
|
queryParams.endTime = queryRangePicker.value[1];
|
||||||
listIMSDataCDR(toRaw(queryParams)).then(res => {
|
listIMSDataCDR(toRaw(queryParams)).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
// 取消勾选
|
// 取消勾选
|
||||||
@@ -446,9 +407,7 @@ function fnRealTime() {
|
|||||||
subGroupID: `1005_${queryParams.neId}`,
|
subGroupID: `1005_${queryParams.neId}`,
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: (ev: any) => {
|
onerror: wsError,
|
||||||
console.error(ev);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
} else {
|
} else {
|
||||||
@@ -458,6 +417,12 @@ function fnRealTime() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**接收数据后回调 */
|
||||||
|
function wsError(ev: any) {
|
||||||
|
// 接收数据后回调
|
||||||
|
console.error(ev);
|
||||||
|
}
|
||||||
|
|
||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsMessage(res: Record<string, any>) {
|
function wsMessage(res: Record<string, any>) {
|
||||||
const { code, requestId, data } = res;
|
const { code, requestId, data } = res;
|
||||||
@@ -557,7 +522,6 @@ onBeforeUnmount(() => {
|
|||||||
v-model:value="queryParams.neId"
|
v-model:value="queryParams.neId"
|
||||||
:options="neOtions"
|
:options="neOtions"
|
||||||
:placeholder="t('common.selectPlease')"
|
:placeholder="t('common.selectPlease')"
|
||||||
@change="fnQueryReset()"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -620,12 +584,12 @@ onBeforeUnmount(() => {
|
|||||||
>
|
>
|
||||||
<a-range-picker
|
<a-range-picker
|
||||||
v-model:value="queryRangePicker"
|
v-model:value="queryRangePicker"
|
||||||
:presets="rangePickerPresets"
|
allow-clear
|
||||||
:bordered="true"
|
bordered
|
||||||
:allow-clear="false"
|
|
||||||
style="width: 100%"
|
|
||||||
:show-time="{ format: 'HH:mm:ss' }"
|
:show-time="{ format: 'HH:mm:ss' }"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
value-format="x"
|
||||||
|
style="width: 100%"
|
||||||
></a-range-picker>
|
></a-range-picker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -664,7 +628,6 @@ onBeforeUnmount(() => {
|
|||||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||||
:loading="modalState.confirmLoading"
|
:loading="modalState.confirmLoading"
|
||||||
@click.prevent="fnRecordDelete('0')"
|
@click.prevent="fnRecordDelete('0')"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon><DeleteOutlined /></template>
|
<template #icon><DeleteOutlined /></template>
|
||||||
{{ t('common.deleteText') }}
|
{{ t('common.deleteText') }}
|
||||||
@@ -761,23 +724,11 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'id'">
|
<template v-if="column.key === 'id'">
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.copyText') }}</template>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
@click.prevent="fnRecordCopy(record.cdrJSON)"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<CopyOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.deleteText') }}</template>
|
<template #title>{{ t('common.deleteText') }}</template>
|
||||||
<a-button
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
@click.prevent="fnRecordDelete(record.id)"
|
@click.prevent="fnRecordDelete(record.id)"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<DeleteOutlined />
|
<DeleteOutlined />
|
||||||
@@ -789,7 +740,7 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
<template #expandedRowRender="{ record }">
|
<template #expandedRowRender="{ record }">
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
<a-col :lg="8" :md="12" :xs="24" :offset="2">
|
<a-col :lg="5" :md="12" :xs="24">
|
||||||
<a-divider orientation="left">
|
<a-divider orientation="left">
|
||||||
{{ t('views.dashboard.cdr.cdrInfo') }}
|
{{ t('views.dashboard.cdr.cdrInfo') }}
|
||||||
</a-divider>
|
</a-divider>
|
||||||
@@ -812,7 +763,7 @@ onBeforeUnmount(() => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="8" :md="12" :xs="24">
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
<a-divider orientation="left">
|
<a-divider orientation="left">
|
||||||
{{ t('views.dashboard.cdr.rowInfo') }}
|
{{ t('views.dashboard.cdr.rowInfo') }}
|
||||||
</a-divider>
|
</a-divider>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
|
||||||
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
|
import { reactive, onMounted, toRaw, ref, onBeforeUnmount } from 'vue';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { message, Modal } from 'ant-design-vue/es';
|
import { message, Modal } from 'ant-design-vue/es';
|
||||||
@@ -18,8 +17,6 @@ import { parseDateToStr } from '@/utils/date-utils';
|
|||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
import { useClipboard } from '@vueuse/core';
|
|
||||||
const { copy } = useClipboard({ legacy: true });
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { getDict } = useDictStore();
|
const { getDict } = useDictStore();
|
||||||
const ws = new WS();
|
const ws = new WS();
|
||||||
@@ -43,10 +40,7 @@ let dict: {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**开始结束时间 */
|
/**开始结束时间 */
|
||||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>([
|
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||||
dayjs().startOf('hour'),
|
|
||||||
dayjs().endOf('hour'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
/**查询参数 */
|
||||||
let queryParams = reactive({
|
let queryParams = reactive({
|
||||||
@@ -58,9 +52,9 @@ let queryParams = reactive({
|
|||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
/**开始时间 */
|
/**开始时间 */
|
||||||
startTime: undefined as undefined | number,
|
startTime: '',
|
||||||
/**结束时间 */
|
/**结束时间 */
|
||||||
endTime: undefined as undefined | number,
|
endTime: '',
|
||||||
/**当前页数 */
|
/**当前页数 */
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
/**每页条数 */
|
/**每页条数 */
|
||||||
@@ -78,7 +72,7 @@ function fnQueryReset() {
|
|||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
});
|
});
|
||||||
queryRangePicker.value = [dayjs().startOf('hour'), dayjs().endOf('hour')];
|
queryRangePicker.value = ['', ''];
|
||||||
tablePagination.current = 1;
|
tablePagination.current = 1;
|
||||||
tablePagination.pageSize = 20;
|
tablePagination.pageSize = 20;
|
||||||
fnGetList();
|
fnGetList();
|
||||||
@@ -155,11 +149,8 @@ let tableColumns: ColumnsType = [
|
|||||||
align: 'left',
|
align: 'left',
|
||||||
width: 150,
|
width: 150,
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
const record = opt.value;
|
const cdrJSON = opt.value;
|
||||||
if (record?.time) {
|
return parseDateToStr(+cdrJSON.timestamp * 1000);
|
||||||
return record.time;
|
|
||||||
}
|
|
||||||
return parseDateToStr(+record.timestamp * 1000);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -269,19 +260,11 @@ function fnGetList(pageNum?: number) {
|
|||||||
if (pageNum) {
|
if (pageNum) {
|
||||||
queryParams.pageNum = pageNum;
|
queryParams.pageNum = pageNum;
|
||||||
}
|
}
|
||||||
|
if (!queryRangePicker.value) {
|
||||||
// 时间范围
|
queryRangePicker.value = ['', ''];
|
||||||
if (
|
|
||||||
Array.isArray(queryRangePicker.value) &&
|
|
||||||
queryRangePicker.value.length > 0
|
|
||||||
) {
|
|
||||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
|
||||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
|
||||||
} else {
|
|
||||||
queryParams.startTime = undefined;
|
|
||||||
queryParams.endTime = undefined;
|
|
||||||
}
|
}
|
||||||
|
queryParams.startTime = queryRangePicker.value[0];
|
||||||
|
queryParams.endTime = queryRangePicker.value[1];
|
||||||
listMMEDataUE(toRaw(queryParams)).then(res => {
|
listMMEDataUE(toRaw(queryParams)).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
// 取消勾选
|
// 取消勾选
|
||||||
@@ -349,18 +332,6 @@ function fnExportList() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制CDR
|
|
||||||
* @param jsonStr JSON字符串
|
|
||||||
*/
|
|
||||||
function fnRecordCopy(jsonStr: string) {
|
|
||||||
if (!jsonStr) return;
|
|
||||||
const text = JSON.stringify(jsonStr, null, 2);
|
|
||||||
copy(text).then(() => {
|
|
||||||
message.success(t('common.copyOk'), 3);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**实时数据开关 */
|
/**实时数据开关 */
|
||||||
const realTimeData = ref<boolean>(false);
|
const realTimeData = ref<boolean>(false);
|
||||||
|
|
||||||
@@ -377,14 +348,12 @@ function fnRealTime() {
|
|||||||
params: {
|
params: {
|
||||||
/**订阅通道组
|
/**订阅通道组
|
||||||
*
|
*
|
||||||
* MME_UE会话事件(GroupID:1011_neId)
|
* MME_UE会话事件(GroupID:1011)
|
||||||
*/
|
*/
|
||||||
subGroupID: `1011_${queryParams.neId}`,
|
subGroupID: `1011_${queryParams.neId}`,
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: (ev: any) => {
|
onerror: wsError,
|
||||||
console.error(ev);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
} else {
|
} else {
|
||||||
@@ -394,6 +363,12 @@ function fnRealTime() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**接收数据后回调 */
|
||||||
|
function wsError(ev: any) {
|
||||||
|
// 接收数据后回调
|
||||||
|
console.error(ev);
|
||||||
|
}
|
||||||
|
|
||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsMessage(res: Record<string, any>) {
|
function wsMessage(res: Record<string, any>) {
|
||||||
const { code, requestId, data } = res;
|
const { code, requestId, data } = res;
|
||||||
@@ -440,7 +415,7 @@ onMounted(() => {
|
|||||||
dict.ueAauthCode = resArr[0].value;
|
dict.ueAauthCode = resArr[0].value;
|
||||||
}
|
}
|
||||||
if (resArr[1].status === 'fulfilled') {
|
if (resArr[1].status === 'fulfilled') {
|
||||||
const ueEventType: any[] = JSON.parse(JSON.stringify(resArr[1].value));
|
const ueEventType: any[] = JSON.parse(JSON.stringify(resArr[1]));
|
||||||
dict.ueEventType = ueEventType.map(item => {
|
dict.ueEventType = ueEventType.map(item => {
|
||||||
if (item.value === 'cm-state') {
|
if (item.value === 'cm-state') {
|
||||||
item.label = item.label.replace('CM', 'ECM');
|
item.label = item.label.replace('CM', 'ECM');
|
||||||
@@ -506,7 +481,6 @@ onBeforeUnmount(() => {
|
|||||||
v-model:value="queryParams.neId"
|
v-model:value="queryParams.neId"
|
||||||
:options="neOtions"
|
:options="neOtions"
|
||||||
:placeholder="t('common.selectPlease')"
|
:placeholder="t('common.selectPlease')"
|
||||||
@change="fnGetList(1)"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -524,7 +498,7 @@ onBeforeUnmount(() => {
|
|||||||
></a-select>
|
></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
<a-col :lg="4" :md="12" :xs="24">
|
||||||
<a-form-item label="IMSI" name="imsi ">
|
<a-form-item label="IMSI" name="imsi ">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="queryParams.imsi"
|
v-model:value="queryParams.imsi"
|
||||||
@@ -533,20 +507,6 @@ onBeforeUnmount(() => {
|
|||||||
></a-input>
|
></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</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-col :lg="8" :md="12" :xs="24">
|
<a-col :lg="8" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.dashboard.cdr.time')"
|
:label="t('views.dashboard.cdr.time')"
|
||||||
@@ -563,6 +523,20 @@ onBeforeUnmount(() => {
|
|||||||
></a-range-picker>
|
></a-range-picker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</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-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-card>
|
</a-card>
|
||||||
@@ -598,7 +572,6 @@ onBeforeUnmount(() => {
|
|||||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||||
:loading="modalState.confirmLoading"
|
:loading="modalState.confirmLoading"
|
||||||
@click.prevent="fnRecordDelete('0')"
|
@click.prevent="fnRecordDelete('0')"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon><DeleteOutlined /></template>
|
<template #icon><DeleteOutlined /></template>
|
||||||
{{ t('common.deleteText') }}
|
{{ t('common.deleteText') }}
|
||||||
@@ -697,23 +670,11 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'id'">
|
<template v-if="column.key === 'id'">
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.copyText') }}</template>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
@click.prevent="fnRecordCopy(record.eventJSON)"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<CopyOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.deleteText') }}</template>
|
<template #title>{{ t('common.deleteText') }}</template>
|
||||||
<a-button
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
@click.prevent="fnRecordDelete(record.id)"
|
@click.prevent="fnRecordDelete(record.id)"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<DeleteOutlined />
|
<DeleteOutlined />
|
||||||
@@ -724,60 +685,48 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template #expandedRowRender="{ record }">
|
<template #expandedRowRender="{ record }">
|
||||||
<a-row :gutter="16">
|
<div style="width: 46%; padding-left: 32px; padding-bottom: 16px">
|
||||||
<a-col :lg="8" :md="12" :xs="24" :offset="2">
|
<a-divider orientation="left">
|
||||||
<a-divider orientation="left">
|
{{ t('views.dashboard.ue.ueInfo') }}
|
||||||
{{ t('views.dashboard.ue.ueInfo') }}
|
</a-divider>
|
||||||
</a-divider>
|
<div>
|
||||||
<div>
|
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
<span>{{ record.neName }}</span>
|
||||||
<span>{{ record.neName }}</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
<span>{{ record.rmUID }}</span>
|
||||||
<span>{{ record.rmUID }}</span>
|
</div>
|
||||||
</div>
|
<a-divider orientation="left">
|
||||||
</a-col>
|
{{ t('views.dashboard.ue.rowInfo') }}
|
||||||
<a-col :lg="8" :md="12" :xs="24">
|
</a-divider>
|
||||||
<a-divider orientation="left">
|
<div>
|
||||||
{{ t('views.dashboard.ue.rowInfo') }}
|
<span>{{ t('views.dashboard.ue.time') }}: </span>
|
||||||
</a-divider>
|
{{ parseDateToStr(record.eventJSON.timestamp * 1000) }}
|
||||||
<div>
|
</div>
|
||||||
<span>{{ t('views.dashboard.ue.time') }}: </span>
|
<div>
|
||||||
<template v-if="record.eventJSON?.time">
|
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
||||||
{{ record.eventJSON.time }}
|
<DictTag :options="dict.ueEventType" :value="record.eventType" />
|
||||||
</template>
|
</div>
|
||||||
<template v-else>
|
<div>
|
||||||
{{ parseDateToStr(record.eventJSON.timestamp * 1000) }}
|
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
||||||
</template>
|
<span v-if="record.eventType === 'auth-result'">
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>{{ t('views.dashboard.ue.eventType') }}: </span>
|
|
||||||
<DictTag
|
<DictTag
|
||||||
:options="dict.ueEventType"
|
:options="dict.ueAauthCode"
|
||||||
:value="record.eventType"
|
:value="record.eventJSON.result"
|
||||||
/>
|
/>
|
||||||
</div>
|
</span>
|
||||||
<div>
|
<span v-if="record.eventType === 'detach'">
|
||||||
<span>{{ t('views.dashboard.ue.result') }}: </span>
|
{{ t('views.dashboard.ue.resultOk') }}
|
||||||
<span v-if="record.eventType === 'auth-result'">
|
</span>
|
||||||
<DictTag
|
<span v-if="record.eventType === 'cm-state'">
|
||||||
:options="dict.ueAauthCode"
|
<DictTag
|
||||||
:value="record.eventJSON.result"
|
:options="dict.ueEventCmState"
|
||||||
/>
|
:value="record.eventJSON.result"
|
||||||
</span>
|
/>
|
||||||
<span v-if="record.eventType === 'detach'">
|
</span>
|
||||||
{{ t('views.dashboard.ue.resultOk') }}
|
</div>
|
||||||
</span>
|
</div>
|
||||||
<span v-if="record.eventType === 'cm-state'">
|
|
||||||
<DictTag
|
|
||||||
:options="dict.ueEventCmState"
|
|
||||||
:value="record.eventJSON.result"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|||||||
@@ -77,12 +77,8 @@ onMounted(() => {
|
|||||||
<div></div>
|
<div></div>
|
||||||
<div>
|
<div>
|
||||||
{{ t('views.dashboard.overview.userActivity.time') }}:
|
{{ t('views.dashboard.overview.userActivity.time') }}:
|
||||||
<span :title="item.data.releaseTime">
|
<span :title="parseDateToStr(item.data.releaseTime * 1000)">
|
||||||
{{
|
{{ parseDateToStr(item.data.releaseTime * 1000) }}
|
||||||
typeof item.data.releaseTime === 'number'
|
|
||||||
? parseDateToStr(+item.data.releaseTime * 1000)
|
|
||||||
: item.data.releaseTime
|
|
||||||
}}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -137,12 +133,18 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{ t('views.dashboard.overview.userActivity.time') }}:
|
{{ t('views.dashboard.overview.userActivity.time') }}:
|
||||||
<template v-if="item.data?.time">
|
<span
|
||||||
{{ item.data.time }}
|
v-if="item.type === 'auth-result'"
|
||||||
</template>
|
:title="item.data.authTime"
|
||||||
<template v-else>
|
>
|
||||||
{{ parseDateToStr(+item.data.timestamp * 1000) }}
|
{{ item.data.authTime }}
|
||||||
</template>
|
</span>
|
||||||
|
<span v-if="item.type === 'detach'" :title="item.data.detachTime">
|
||||||
|
{{ item.data.detachTime }}
|
||||||
|
</span>
|
||||||
|
<span v-if="item.type === 'cm-state'" :title="item.data.changeTime">
|
||||||
|
{{ item.data.changeTime }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -161,7 +163,7 @@ onMounted(() => {
|
|||||||
<div v-if="item.type === 'auth-result'">
|
<div v-if="item.type === 'auth-result'">
|
||||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||||
<span>
|
<span>
|
||||||
<DictTag :options="dict.ueAauthCode" :value="item.data.result" />
|
<DictTag :options="dict.ueAauthCode" :value="item.data.authCode" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="item.type === 'detach'">
|
<div v-if="item.type === 'detach'">
|
||||||
@@ -171,7 +173,7 @@ onMounted(() => {
|
|||||||
<div class="card-ue-w33" v-if="item.type === 'cm-state'">
|
<div class="card-ue-w33" v-if="item.type === 'cm-state'">
|
||||||
{{ t('views.dashboard.overview.userActivity.result') }}:
|
{{ t('views.dashboard.overview.userActivity.result') }}:
|
||||||
<span>
|
<span>
|
||||||
<DictTag :options="dict.ueEventCmState" :value="item.data.result" />
|
<DictTag :options="dict.ueEventCmState" :value="item.data.status" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -196,16 +198,12 @@ onMounted(() => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
IMSI: <span :title="item.data?.imsi">{{ item.data?.imsi }}</span>
|
IMSI: <span :title="item.data.imsi">{{ item.data.imsi }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{ t('views.dashboard.overview.userActivity.time') }}:
|
{{ t('views.dashboard.overview.userActivity.time') }}:
|
||||||
<span :title="item.data?.timestamp">
|
<span :title="item.data.timestamp">
|
||||||
{{
|
{{ parseDateToStr(+item.data.timestamp * 1000) }}
|
||||||
typeof item.data?.timestamp === 'number'
|
|
||||||
? parseDateToStr(+item.data?.timestamp * 1000)
|
|
||||||
: item.data?.timestamp
|
|
||||||
}}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
.column {
|
.column {
|
||||||
flex: 3;
|
flex: 3;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 边框 */
|
/* 边框 */
|
||||||
@@ -81,14 +79,13 @@
|
|||||||
.upfFlow .inner .chart {
|
.upfFlow .inner .chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-top: 0rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 网络拓扑 */
|
/* 网络拓扑 */
|
||||||
.topology {
|
.topology {
|
||||||
/* min-height: 27.8rem; */
|
/* min-height: 27.8rem; */
|
||||||
height: 56.4%;
|
height: 56.4%;
|
||||||
flex: 1;
|
|
||||||
}
|
}
|
||||||
.topology .inner h3 {
|
.topology .inner h3 {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -182,7 +179,6 @@
|
|||||||
.userActivity {
|
.userActivity {
|
||||||
/* min-height: 35.8rem; */
|
/* min-height: 35.8rem; */
|
||||||
height: 54.6%;
|
height: 54.6%;
|
||||||
flex: 1;
|
|
||||||
}
|
}
|
||||||
.userActivity .inner .chart {
|
.userActivity .inner .chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -263,7 +259,6 @@
|
|||||||
.alarmType {
|
.alarmType {
|
||||||
/* min-height: 25rem; */
|
/* min-height: 25rem; */
|
||||||
height: 46%;
|
height: 46%;
|
||||||
flex: 1;
|
|
||||||
}
|
}
|
||||||
.alarmType .inner .chart {
|
.alarmType .inner .chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ export function upfFlowParse(data: Record<string, string>) {
|
|||||||
upfFlowData.value.lineYDown.shift();
|
upfFlowData.value.lineYDown.shift();
|
||||||
upfFlowData.value.cap -= 1;
|
upfFlowData.value.cap -= 1;
|
||||||
}
|
}
|
||||||
|
// UPF-总流量数0天 当天24小时
|
||||||
|
upfTFParse('0', {
|
||||||
|
up: upfTotalFlow.value['0'].up + +data['UPF.03'],
|
||||||
|
down: upfTotalFlow.value['0'].down + +data['UPF.06'],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
type TFType = {
|
type TFType = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { RESULT_CODE_ERROR } from '@/constants/result-constants';
|
import { RESULT_CODE_ERROR } from '@/constants/result-constants';
|
||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
import { onBeforeUnmount, ref } from 'vue';
|
import { onBeforeUnmount, onMounted } from 'vue';
|
||||||
import {
|
import {
|
||||||
eventListParse,
|
eventListParse,
|
||||||
eventItemParseAndPush,
|
eventItemParseAndPush,
|
||||||
@@ -12,15 +12,9 @@ import {
|
|||||||
upfFlowParse,
|
upfFlowParse,
|
||||||
upfTotalFlowReset,
|
upfTotalFlowReset,
|
||||||
} from './useUPFTotalFlow';
|
} from './useUPFTotalFlow';
|
||||||
import { topologyReset, neStateParse, neStateRequestMap } from './useTopology';
|
import { topologyReset, neStateParse } from './useTopology';
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
|
|
||||||
/**UPF-的Id */
|
|
||||||
export const upfWhoId = ref<any>('');
|
|
||||||
|
|
||||||
/**UPF-的RmUid */
|
|
||||||
export const upfWhoRmUid = ref<any>('');
|
|
||||||
|
|
||||||
/**websocket连接 */
|
/**websocket连接 */
|
||||||
export default function useWS() {
|
export default function useWS() {
|
||||||
const ws = new WS();
|
const ws = new WS();
|
||||||
@@ -33,12 +27,13 @@ export default function useWS() {
|
|||||||
|
|
||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsMessage(res: Record<string, any>) {
|
function wsMessage(res: Record<string, any>) {
|
||||||
//console.log(res);
|
// console.log(res);
|
||||||
const { code, requestId, data } = res;
|
const { code, requestId, data } = res;
|
||||||
if (code === RESULT_CODE_ERROR) {
|
if (code === RESULT_CODE_ERROR) {
|
||||||
console.warn(res.msg);
|
console.warn(res.msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网元状态
|
// 网元状态
|
||||||
if (requestId && requestId.startsWith('neState')) {
|
if (requestId && requestId.startsWith('neState')) {
|
||||||
const neType = requestId.split('_')[1];
|
const neType = requestId.split('_')[1];
|
||||||
@@ -49,7 +44,7 @@ export default function useWS() {
|
|||||||
// 普通信息
|
// 普通信息
|
||||||
switch (requestId) {
|
switch (requestId) {
|
||||||
// AMF_UE会话事件
|
// AMF_UE会话事件
|
||||||
case 'amf_1010_001':
|
case 'amf_1010':
|
||||||
if (Array.isArray(data.rows)) {
|
if (Array.isArray(data.rows)) {
|
||||||
eventListParse('amf_ue', data);
|
eventListParse('amf_ue', data);
|
||||||
}
|
}
|
||||||
@@ -77,19 +72,20 @@ export default function useWS() {
|
|||||||
upfTFParse('30', data);
|
upfTFParse('30', data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 订阅组信息
|
// 订阅组信息
|
||||||
if (!data?.groupId) {
|
if (!data?.groupId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (data.groupId) {
|
switch (data.groupId) {
|
||||||
// kpiEvent 指标UPF
|
// kpiEvent 指标UPF
|
||||||
case '10_UPF_' + upfWhoId.value:
|
case '12_001':
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
upfFlowParse(data.data);
|
upfFlowParse(data.data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// AMF_UE会话事件
|
// AMF_UE会话事件
|
||||||
case '1010_001':
|
case '1010':
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
queue.add(() => eventItemParseAndPush('amf_ue', data.data));
|
queue.add(() => eventItemParseAndPush('amf_ue', data.data));
|
||||||
}
|
}
|
||||||
@@ -132,7 +128,7 @@ export default function useWS() {
|
|||||||
function userActivitySend() {
|
function userActivitySend() {
|
||||||
// AMF_UE会话事件
|
// AMF_UE会话事件
|
||||||
ws.send({
|
ws.send({
|
||||||
requestId: 'amf_1010_001',
|
requestId: 'amf_1010',
|
||||||
type: 'amf_ue',
|
type: 'amf_ue',
|
||||||
data: {
|
data: {
|
||||||
neType: 'AMF',
|
neType: 'AMF',
|
||||||
@@ -172,28 +168,18 @@ export default function useWS() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**重新发送至UPF 10_UPF_neId */
|
onMounted(() => {
|
||||||
function reSendUPF(neId: string) {
|
|
||||||
upfWhoId.value = neId;
|
|
||||||
//初始时时无需还原全部属性以及关闭
|
|
||||||
if (ws.state() === WebSocket.OPEN) {
|
|
||||||
ws.close();
|
|
||||||
// userActivityReset();
|
|
||||||
upfTotalFlowReset();
|
|
||||||
neStateRequestMap.value = new Map();
|
|
||||||
//topologyReset();
|
|
||||||
}
|
|
||||||
const options: OptionsType = {
|
const options: OptionsType = {
|
||||||
url: '/ws',
|
url: '/ws',
|
||||||
params: {
|
params: {
|
||||||
/**订阅通道组
|
/**订阅通道组
|
||||||
*
|
*
|
||||||
* 指标UPF (GroupID:10_neType_neId)
|
* 指标UPF (GroupID:12_neId)
|
||||||
* AMF_UE会话事件(GroupID:1010_neId)
|
* AMF_UE会话事件(GroupID:1010)
|
||||||
* MME_UE会话事件(GroupID:1011_neId)
|
* MME_UE会话事件(GroupID:1011_neId)
|
||||||
* IMS_CDR会话事件(GroupID:1005_neId)
|
* IMS_CDR会话事件(GroupID:1005_neId)
|
||||||
*/
|
*/
|
||||||
subGroupID: '10_UPF_' + neId + ',1010_001,1011_001,1005_001',
|
subGroupID: '12_001,1010,1011_001,1005_001',
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: (ev: any) => {
|
onerror: (ev: any) => {
|
||||||
@@ -201,20 +187,18 @@ export default function useWS() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
}
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
ws.close();
|
ws.close();
|
||||||
userActivityReset();
|
userActivityReset();
|
||||||
upfTotalFlowReset();
|
upfTotalFlowReset();
|
||||||
topologyReset();
|
topologyReset();
|
||||||
upfWhoId.value = '';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
wsSend,
|
wsSend,
|
||||||
userActivitySend,
|
userActivitySend,
|
||||||
upfTFSend,
|
upfTFSend,
|
||||||
reSendUPF,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -26,15 +26,10 @@ import useWS from './hooks/useWS';
|
|||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
import { upfWhoId } from './hooks/useWS';
|
|
||||||
|
|
||||||
const neInfoStore = useNeInfoStore();
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { wsSend, userActivitySend, upfTFSend, reSendUPF } = useWS();
|
const { wsSend, userActivitySend, upfTFSend } = useWS();
|
||||||
|
|
||||||
/**概览状态类型 */
|
/**概览状态类型 */
|
||||||
type SkimStateType = {
|
type SkimStateType = {
|
||||||
@@ -65,14 +60,10 @@ let skimState: SkimStateType = reactive({
|
|||||||
enbUeNum: 0,
|
enbUeNum: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**网元参数 */
|
|
||||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
|
||||||
|
|
||||||
/**总览节点 */
|
/**总览节点 */
|
||||||
const viewportDom = ref<HTMLElement | null>(null);
|
const viewportDom = ref<HTMLElement | null>(null);
|
||||||
const { isFullscreen, toggle } = useFullscreen(viewportDom);
|
const { isFullscreen, toggle } = useFullscreen(viewportDom);
|
||||||
|
|
||||||
let initFlag = false;
|
|
||||||
/**10s调度器 */
|
/**10s调度器 */
|
||||||
const interval10s = ref<any>(null);
|
const interval10s = ref<any>(null);
|
||||||
|
|
||||||
@@ -103,104 +94,62 @@ function fnGetNeState() {
|
|||||||
|
|
||||||
/**获取概览信息 */
|
/**获取概览信息 */
|
||||||
async function fnGetSkim() {
|
async function fnGetSkim() {
|
||||||
const neHandlers = new Map([
|
const resArr = await Promise.allSettled([
|
||||||
// [
|
listUDMSub({
|
||||||
// 'UDM',
|
neid: '001',
|
||||||
// {
|
pageNum: 1,
|
||||||
// request: (neId: string) =>
|
pageSize: 1,
|
||||||
// listUDMSub({ neId: neId, pageNum: 1, pageSize: 1 }),
|
}),
|
||||||
// process: (res: any) =>
|
listUENumBySMF('001'),
|
||||||
// res.code === RESULT_CODE_SUCCESS &&
|
listUENumByIMS('001'),
|
||||||
// (skimState.udmSubNum += res.total),
|
listBase5G({
|
||||||
// },
|
neType: 'AMF',
|
||||||
// ],
|
neId: '001',
|
||||||
[
|
}),
|
||||||
'SMF',
|
listBase5G({
|
||||||
{
|
neType: 'MME',
|
||||||
request: (neId: string) => listUENumBySMF(neId),
|
neId: '001',
|
||||||
process: (res: any) =>
|
}),
|
||||||
res.code === RESULT_CODE_SUCCESS && (skimState.smfUeNum += res.data),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'IMS',
|
|
||||||
{
|
|
||||||
request: (neId: string) => listUENumByIMS(neId),
|
|
||||||
process: (res: any) =>
|
|
||||||
res.code === RESULT_CODE_SUCCESS && (skimState.imsUeNum += res.data),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'AMF',
|
|
||||||
{
|
|
||||||
request: (neId: string) => listBase5G({ neType: 'AMF', neId }),
|
|
||||||
process: (res: any) => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
skimState.gnbNum += res.total;
|
|
||||||
skimState.gnbUeNum += res.rows.reduce(
|
|
||||||
(sum: number, item: any) => sum + item.ueNum,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'MME',
|
|
||||||
{
|
|
||||||
request: (neId: string) => listBase5G({ neType: 'MME', neId }),
|
|
||||||
process: (res: any) => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
skimState.enbNum += res.total;
|
|
||||||
skimState.enbUeNum += res.rows.reduce(
|
|
||||||
(sum: number, item: any) => sum + item.ueNum,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const requests = neCascaderOptions.value.flatMap(
|
if (resArr[0].status === 'fulfilled') {
|
||||||
(ne: any) =>
|
const res0 = resArr[0].value;
|
||||||
ne.children
|
if (res0.code === RESULT_CODE_SUCCESS) {
|
||||||
?.map((child: any) => {
|
skimState.udmSubNum = res0.total;
|
||||||
const handler = neHandlers.get(child.neType);
|
|
||||||
return handler
|
|
||||||
? {
|
|
||||||
promise: handler.request(child.neId),
|
|
||||||
process: handler.process,
|
|
||||||
}
|
|
||||||
: null;
|
|
||||||
})
|
|
||||||
.filter(Boolean) || []
|
|
||||||
);
|
|
||||||
|
|
||||||
const results = await Promise.allSettled(requests.map(r => r.promise));
|
|
||||||
|
|
||||||
// 重置
|
|
||||||
Object.assign(skimState, {
|
|
||||||
udmSubNum: 0,
|
|
||||||
smfUeNum: 0,
|
|
||||||
imsUeNum: 0,
|
|
||||||
gnbNum: 0,
|
|
||||||
gnbUeNum: 0,
|
|
||||||
enbNum: 0,
|
|
||||||
enbUeNum: 0,
|
|
||||||
});
|
|
||||||
results.forEach((result, index) => {
|
|
||||||
if (result.status === 'fulfilled') {
|
|
||||||
requests[index].process(result.value);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
if (resArr[1].status === 'fulfilled') {
|
||||||
// UDM
|
const res1 = resArr[1].value;
|
||||||
listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
|
if (res1.code === RESULT_CODE_SUCCESS) {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
skimState.smfUeNum = res1.data;
|
||||||
skimState.udmSubNum = res.total;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**初始数据函数 */
|
/**初始数据函数 */
|
||||||
@@ -213,7 +162,7 @@ function loadData() {
|
|||||||
|
|
||||||
clearInterval(interval10s.value);
|
clearInterval(interval10s.value);
|
||||||
interval10s.value = setInterval(() => {
|
interval10s.value = setInterval(() => {
|
||||||
if (!interval10s.value) return;
|
if (!interval10s.value) return
|
||||||
if (upfTFActive.value === '0') {
|
if (upfTFActive.value === '0') {
|
||||||
upfTFSend('7');
|
upfTFSend('7');
|
||||||
upfTFActive.value = '7';
|
upfTFActive.value = '7';
|
||||||
@@ -228,7 +177,7 @@ function loadData() {
|
|||||||
|
|
||||||
clearInterval(interval5s.value);
|
clearInterval(interval5s.value);
|
||||||
interval5s.value = setInterval(() => {
|
interval5s.value = setInterval(() => {
|
||||||
if (!interval5s.value || !initFlag) return;
|
if (!interval5s.value) return
|
||||||
fnGetSkim(); // 获取概览信息
|
fnGetSkim(); // 获取概览信息
|
||||||
fnGetNeState(); // 获取网元状态
|
fnGetNeState(); // 获取网元状态
|
||||||
}, 5_000);
|
}, 5_000);
|
||||||
@@ -239,101 +188,10 @@ function fnToRouter(name: string, query?: any) {
|
|||||||
router.push({ name, query });
|
router.push({ name, query });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**网元参数 */
|
|
||||||
let neOtions = ref<Record<string, any>[]>([]);
|
|
||||||
|
|
||||||
// UPF实时流量下拉框选择
|
|
||||||
function fnSelectNe(value: any, option: any) {
|
|
||||||
upfWhoId.value = value;
|
|
||||||
reSendUPF(value);
|
|
||||||
// upfTotalFlow.value.map((item: any) => {
|
|
||||||
// item.requestFlag = false;
|
|
||||||
// });
|
|
||||||
|
|
||||||
for (var key in upfTotalFlow.value) {
|
|
||||||
upfTotalFlow.value[key].requestFlag = false;
|
|
||||||
}
|
|
||||||
// loadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
let udmNeId = ref<string>('001');
|
|
||||||
let udmOtions = ref<Record<string, any>[]>([]);
|
|
||||||
/**用户数量-选择UDM */
|
|
||||||
function fnSelectUDM(e: any) {
|
|
||||||
udmNeId.value = e.key;
|
|
||||||
listUDMSub({ neId: udmNeId.value, pageNum: 1, pageSize: 1 }).then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
skimState.udmSubNum = res.total;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定义一个方法返回 views 容器
|
|
||||||
const getPopupContainer = () => {
|
|
||||||
// 使用 ref 或其他方式来引用你的 views 容器
|
|
||||||
// 如果 views 容器直接在这个组件内部,你可以使用 ref
|
|
||||||
// 但在这个例子中,我们假设它是通过类名来获取的
|
|
||||||
return document.querySelector('.viewport');
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
neInfoStore
|
fnGetSkim().then(() => {
|
||||||
.fnNelist()
|
loadData();
|
||||||
.then(res => {
|
});
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
if (res.data.length > 0) {
|
|
||||||
// UPF
|
|
||||||
let arr: Record<string, any>[] = [];
|
|
||||||
res.data.forEach(i => {
|
|
||||||
if (i.neType === 'UPF') {
|
|
||||||
arr.push({ value: i.neId, label: i.neName, rmUid: i.rmUid });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
neOtions.value = arr;
|
|
||||||
if (arr.length > 0) {
|
|
||||||
//queryParams.neRealId = arr[0].value;
|
|
||||||
fnSelectNe(arr[0].value, arr[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// UDM
|
|
||||||
let arr1: Record<string, any>[] = [];
|
|
||||||
res.data.forEach((v: any) => {
|
|
||||||
if (v.neType === 'UDM') {
|
|
||||||
arr1.push({ value: v.neId, label: v.neName, rmUid: v.rmUid });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
udmOtions.value = arr1;
|
|
||||||
if (arr1.length > 0) {
|
|
||||||
fnSelectUDM({ key: arr1[0].value });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤不可用的网元
|
|
||||||
neCascaderOptions.value = neInfoStore.getNeCascaderOptions.filter(
|
|
||||||
(item: any) => {
|
|
||||||
return ['UDM', 'SMF', 'IMS', 'AMF', 'MME'].includes(item.value);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (neCascaderOptions.value.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('common.noData'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message.warning({
|
|
||||||
content: t('common.noData'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
initFlag = true;
|
|
||||||
fnGetSkim().then(() => {
|
|
||||||
loadData();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
@@ -341,7 +199,6 @@ onBeforeUnmount(() => {
|
|||||||
interval10s.value = null;
|
interval10s.value = null;
|
||||||
clearInterval(interval5s.value);
|
clearInterval(interval5s.value);
|
||||||
interval5s.value = null;
|
interval5s.value = null;
|
||||||
initFlag = false;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -371,28 +228,17 @@ onBeforeUnmount(() => {
|
|||||||
<div class="data">
|
<div class="data">
|
||||||
<div
|
<div
|
||||||
class="item toRouter"
|
class="item toRouter"
|
||||||
|
@click="fnToRouter('Sub_2010')"
|
||||||
:title="t('views.dashboard.overview.toRouter')"
|
:title="t('views.dashboard.overview.toRouter')"
|
||||||
>
|
>
|
||||||
<div @click="fnToRouter('Sub_2010')">
|
<div>
|
||||||
<UserOutlined
|
<UserOutlined
|
||||||
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
|
style="color: #4096ff; margin-right: 8px; font-size: 1.1rem"
|
||||||
/>
|
/>
|
||||||
{{ skimState.udmSubNum }}
|
{{ skimState.udmSubNum }}
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
<a-dropdown :trigger="['click']">
|
{{ t('views.dashboard.overview.skim.users') }}
|
||||||
<div class="toDeep-text">
|
|
||||||
{{ t('views.dashboard.overview.skim.users') }}
|
|
||||||
<DownOutlined style="margin-left: 12px; font-size: 12px" />
|
|
||||||
</div>
|
|
||||||
<template #overlay>
|
|
||||||
<a-menu @click="fnSelectUDM">
|
|
||||||
<a-menu-item v-for="v in udmOtions" :key="v.value" :disabled="udmNeId === v.value">
|
|
||||||
{{ v.label }}
|
|
||||||
</a-menu-item>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -400,7 +246,6 @@ onBeforeUnmount(() => {
|
|||||||
@click="fnToRouter('Ims_2080')"
|
@click="fnToRouter('Ims_2080')"
|
||||||
:title="t('views.dashboard.overview.toRouter')"
|
:title="t('views.dashboard.overview.toRouter')"
|
||||||
style="margin: 0 12px"
|
style="margin: 0 12px"
|
||||||
v-perms:has="['dashboard:overview:imsUeNum']"
|
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<img :src="svgUserIMS" style="width: 18px; margin-right: 8px" />
|
<img :src="svgUserIMS" style="width: 18px; margin-right: 8px" />
|
||||||
@@ -414,7 +259,6 @@ onBeforeUnmount(() => {
|
|||||||
class="item toRouter"
|
class="item toRouter"
|
||||||
@click="fnToRouter('Ue_2081')"
|
@click="fnToRouter('Ue_2081')"
|
||||||
:title="t('views.dashboard.overview.toRouter')"
|
:title="t('views.dashboard.overview.toRouter')"
|
||||||
v-perms:has="['dashboard:overview:smfUeNum']"
|
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<img :src="svgUserSMF" style="width: 18px; margin-right: 8px" />
|
<img :src="svgUserSMF" style="width: 18px; margin-right: 8px" />
|
||||||
@@ -427,7 +271,7 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="skim panel base" v-perms:has="['dashboard:overview:gnbBase']">
|
<div class="skim panel base">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>
|
<h3>
|
||||||
<GlobalOutlined style="color: #68d8fe" /> 5G
|
<GlobalOutlined style="color: #68d8fe" /> 5G
|
||||||
@@ -436,7 +280,7 @@ onBeforeUnmount(() => {
|
|||||||
<div class="data">
|
<div class="data">
|
||||||
<div
|
<div
|
||||||
class="item toRouter"
|
class="item toRouter"
|
||||||
@click="fnToRouter('BaseStation_2096', { neType: 'AMF' })"
|
@click="fnToRouter('Base5G_2082', { neType: 'AMF' })"
|
||||||
:title="t('views.dashboard.overview.toRouter')"
|
:title="t('views.dashboard.overview.toRouter')"
|
||||||
>
|
>
|
||||||
<div style="align-items: flex-start">
|
<div style="align-items: flex-start">
|
||||||
@@ -450,7 +294,7 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="item toRouter"
|
class="item toRouter"
|
||||||
@click="fnToRouter('BaseStation_2096', { neType: 'AMF' })"
|
@click="fnToRouter('Base5G_2082', { neType: 'AMF' })"
|
||||||
:title="t('views.dashboard.overview.toRouter')"
|
:title="t('views.dashboard.overview.toRouter')"
|
||||||
>
|
>
|
||||||
<div style="align-items: flex-start">
|
<div style="align-items: flex-start">
|
||||||
@@ -464,7 +308,7 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="skim panel base" v-perms:has="['dashboard:overview:enbBase']">
|
<div class="skim panel base">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>
|
<h3>
|
||||||
<GlobalOutlined style="color: #68d8fe" /> 4G
|
<GlobalOutlined style="color: #68d8fe" /> 4G
|
||||||
@@ -473,7 +317,7 @@ onBeforeUnmount(() => {
|
|||||||
<div class="data">
|
<div class="data">
|
||||||
<div
|
<div
|
||||||
class="item toRouter"
|
class="item toRouter"
|
||||||
@click="fnToRouter('BaseStation_2096', { neType: 'MME' })"
|
@click="fnToRouter('Base5G_2082', { neType: 'MME' })"
|
||||||
:title="t('views.dashboard.overview.toRouter')"
|
:title="t('views.dashboard.overview.toRouter')"
|
||||||
>
|
>
|
||||||
<div style="align-items: flex-start">
|
<div style="align-items: flex-start">
|
||||||
@@ -487,7 +331,7 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="item toRouter"
|
class="item toRouter"
|
||||||
@click="fnToRouter('BaseStation_2096', { neType: 'MME' })"
|
@click="fnToRouter('Base5G_2082', { neType: 'MME' })"
|
||||||
:title="t('views.dashboard.overview.toRouter')"
|
:title="t('views.dashboard.overview.toRouter')"
|
||||||
>
|
>
|
||||||
<div style="align-items: flex-start">
|
<div style="align-items: flex-start">
|
||||||
@@ -521,23 +365,12 @@ onBeforeUnmount(() => {
|
|||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3
|
<h3
|
||||||
class="toRouter"
|
class="toRouter"
|
||||||
|
@click="fnToRouter('GoldTarget_2104')"
|
||||||
:title="t('views.dashboard.overview.toRouter')"
|
:title="t('views.dashboard.overview.toRouter')"
|
||||||
style="display: flex; align-items: center"
|
|
||||||
>
|
>
|
||||||
<AreaChartOutlined style="color: #68d8fe" />
|
<AreaChartOutlined style="color: #68d8fe" />
|
||||||
<span @click="fnToRouter('GoldTarget_2104')">{{
|
{{ t('views.dashboard.overview.upfFlow.title') }}
|
||||||
t('views.dashboard.overview.upfFlow.title')
|
|
||||||
}}</span>
|
|
||||||
<a-select
|
|
||||||
v-model:value="upfWhoId"
|
|
||||||
:options="neOtions"
|
|
||||||
:get-Popup-Container="getPopupContainer"
|
|
||||||
class="toDeep"
|
|
||||||
style="width: 100px; color: #fff; margin-left: auto"
|
|
||||||
@change="fnSelectNe"
|
|
||||||
/>
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="chart">
|
<div class="chart">
|
||||||
<UPFFlow />
|
<UPFFlow />
|
||||||
</div>
|
</div>
|
||||||
@@ -655,30 +488,4 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@import url('./css/index.css');
|
@import url('./css/index.css');
|
||||||
.toDeep {
|
|
||||||
--editor-background-color: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toDeep :deep(.ant-select-selector) {
|
|
||||||
background-color: #101129;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toDeep :deep(.ant-select-arrow) {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toDeep :deep(.ant-select-selection-item) {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.toDeep-text {
|
|
||||||
color: #4c9bfd !important;
|
|
||||||
font-size: 0.844rem !important;
|
|
||||||
position: relative !important;
|
|
||||||
line-height: 2rem !important;
|
|
||||||
white-space: nowrap !important;
|
|
||||||
text-align: start !important;
|
|
||||||
text-overflow: ellipsis !important;
|
|
||||||
overflow: hidden !important;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -1,850 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { reactive, onMounted, toRaw, onBeforeUnmount, ref } from 'vue';
|
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
|
||||||
import { Modal, message } from 'ant-design-vue/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 useNeInfoStore from '@/store/modules/neinfo';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
import {
|
|
||||||
RESULT_CODE_ERROR,
|
|
||||||
RESULT_CODE_SUCCESS,
|
|
||||||
} from '@/constants/result-constants';
|
|
||||||
import {
|
|
||||||
delSGWCDataCDR,
|
|
||||||
exportSGWCDataCDR,
|
|
||||||
listSGWCDataCDR,
|
|
||||||
} from '@/api/neData/sgwc';
|
|
||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
|
||||||
import PQueue from 'p-queue';
|
|
||||||
import saveAs from 'file-saver';
|
|
||||||
import { useClipboard } from '@vueuse/core';
|
|
||||||
import dayjs, { type Dayjs } from 'dayjs';
|
|
||||||
const { copy } = useClipboard({ legacy: true });
|
|
||||||
const { t } = useI18n();
|
|
||||||
const ws = new WS();
|
|
||||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
|
||||||
|
|
||||||
/**网元可选 */
|
|
||||||
let neOtions = ref<Record<string, any>[]>([]);
|
|
||||||
|
|
||||||
/**开始结束时间 */
|
|
||||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>([
|
|
||||||
dayjs().startOf('hour'),
|
|
||||||
dayjs().endOf('hour'),
|
|
||||||
]);
|
|
||||||
/**时间范围 */
|
|
||||||
let rangePickerPresets = ref([
|
|
||||||
{
|
|
||||||
label: 'Now hour',
|
|
||||||
value: [dayjs().startOf('hour'), dayjs().endOf('hour')],
|
|
||||||
},
|
|
||||||
{ label: 'Today', value: [dayjs().startOf('day'), dayjs().endOf('day')] },
|
|
||||||
{
|
|
||||||
label: 'Yesterday',
|
|
||||||
value: [
|
|
||||||
dayjs().subtract(1, 'day').startOf('day'),
|
|
||||||
dayjs().subtract(1, 'day').endOf('day'),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
|
||||||
let queryParams = reactive({
|
|
||||||
/**网元类型 */
|
|
||||||
neType: 'SGWC',
|
|
||||||
neId: '001',
|
|
||||||
imsi: '',
|
|
||||||
msisdn: '',
|
|
||||||
sortField: 'timestamp',
|
|
||||||
sortOrder: 'desc',
|
|
||||||
/**开始时间 */
|
|
||||||
startTime: undefined as undefined | number,
|
|
||||||
/**结束时间 */
|
|
||||||
endTime: undefined as undefined | number,
|
|
||||||
/**当前页数 */
|
|
||||||
pageNum: 1,
|
|
||||||
/**每页条数 */
|
|
||||||
pageSize: 20,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**查询参数重置 */
|
|
||||||
function fnQueryReset() {
|
|
||||||
queryParams = Object.assign(queryParams, {
|
|
||||||
imsi: '',
|
|
||||||
msisdn: '',
|
|
||||||
startTime: undefined,
|
|
||||||
endTime: undefined,
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 20,
|
|
||||||
});
|
|
||||||
queryRangePicker.value = [dayjs().startOf('hour'), dayjs().endOf('hour')];
|
|
||||||
tablePagination.current = 1;
|
|
||||||
tablePagination.pageSize = 20;
|
|
||||||
fnGetList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**表格状态类型 */
|
|
||||||
type TabeStateType = {
|
|
||||||
/**加载等待 */
|
|
||||||
loading: boolean;
|
|
||||||
/**紧凑型 */
|
|
||||||
size: SizeType;
|
|
||||||
/**搜索栏 */
|
|
||||||
seached: boolean;
|
|
||||||
/**记录数据 */
|
|
||||||
data: object[];
|
|
||||||
/**勾选记录 */
|
|
||||||
selectedRowKeys: (string | number)[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**表格状态 */
|
|
||||||
let tableState: TabeStateType = reactive({
|
|
||||||
loading: false,
|
|
||||||
size: 'middle',
|
|
||||||
seached: true,
|
|
||||||
data: [],
|
|
||||||
selectedRowKeys: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格字段列 */
|
|
||||||
let tableColumns: ColumnsType = [
|
|
||||||
{
|
|
||||||
title: t('common.rowId'),
|
|
||||||
dataIndex: 'id',
|
|
||||||
align: 'left',
|
|
||||||
width: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.dashboard.cdr.chargingID'), // 计费ID
|
|
||||||
dataIndex: 'cdrJSON',
|
|
||||||
align: 'left',
|
|
||||||
width: 100,
|
|
||||||
customRender(opt) {
|
|
||||||
const cdrJSON = opt.value;
|
|
||||||
return cdrJSON.chargingID;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.dashboard.cdr.sgwcServedIMSI'), // IMSI
|
|
||||||
dataIndex: 'cdrJSON',
|
|
||||||
align: 'left',
|
|
||||||
width: 150,
|
|
||||||
customRender(opt) {
|
|
||||||
const cdrJSON = opt.value;
|
|
||||||
return cdrJSON.servedIMSI;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.dashboard.cdr.sgwcServedMSISDN'), // MSISDN
|
|
||||||
dataIndex: 'cdrJSON',
|
|
||||||
align: 'left',
|
|
||||||
width: 150,
|
|
||||||
customRender(opt) {
|
|
||||||
const cdrJSON = opt.value;
|
|
||||||
return cdrJSON.servedMSISDN;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.dashboard.cdr.sgwcVolumeGPRSUplink'), // GPRS 上行链路
|
|
||||||
dataIndex: 'cdrJSON',
|
|
||||||
align: 'left',
|
|
||||||
width: 150,
|
|
||||||
customRender(opt) {
|
|
||||||
const cdrJSON = opt.value;
|
|
||||||
const listOfTrafficVolumes = cdrJSON.listOfTrafficVolumes;
|
|
||||||
if (
|
|
||||||
!Array.isArray(listOfTrafficVolumes) ||
|
|
||||||
listOfTrafficVolumes.length < 1
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let dataVolumeGPRSUplink = 0;
|
|
||||||
for (const used of listOfTrafficVolumes) {
|
|
||||||
const v = +used.dataVolumeGPRSUplink;
|
|
||||||
dataVolumeGPRSUplink += isNaN(v) ? 0 : v;
|
|
||||||
}
|
|
||||||
return dataVolumeGPRSUplink;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.dashboard.cdr.sgwcVolumeGPRSDownlink'), // GPRS 下行链路
|
|
||||||
dataIndex: 'cdrJSON',
|
|
||||||
align: 'left',
|
|
||||||
width: 180,
|
|
||||||
customRender(opt) {
|
|
||||||
const cdrJSON = opt.value;
|
|
||||||
const listOfTrafficVolumes = cdrJSON.listOfTrafficVolumes;
|
|
||||||
if (
|
|
||||||
!Array.isArray(listOfTrafficVolumes) ||
|
|
||||||
listOfTrafficVolumes.length < 1
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let dataVolumeGPRSDownlink = 0;
|
|
||||||
for (const used of listOfTrafficVolumes) {
|
|
||||||
const v = +used.dataVolumeGPRSDownlink;
|
|
||||||
dataVolumeGPRSDownlink += isNaN(v) ? 0 : v;
|
|
||||||
}
|
|
||||||
return dataVolumeGPRSDownlink;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.dashboard.cdr.durationTime'), // 持续时间
|
|
||||||
dataIndex: 'cdrJSON',
|
|
||||||
align: 'left',
|
|
||||||
width: 100,
|
|
||||||
customRender(opt) {
|
|
||||||
const cdrJSON = opt.value;
|
|
||||||
return cdrJSON.duration;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.dashboard.cdr.invocationTime'), // 操作时间
|
|
||||||
dataIndex: 'cdrJSON',
|
|
||||||
align: 'left',
|
|
||||||
width: 200,
|
|
||||||
customRender(opt) {
|
|
||||||
const cdrJSON = opt.value;
|
|
||||||
return cdrJSON.recordOpeningTime;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('common.operate'),
|
|
||||||
key: 'id',
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
/**表格分页器参数 */
|
|
||||||
let tablePagination = reactive({
|
|
||||||
/**当前页数 */
|
|
||||||
current: 1,
|
|
||||||
/**每页条数 */
|
|
||||||
pageSize: 20,
|
|
||||||
/**默认的每页条数 */
|
|
||||||
defaultPageSize: 20,
|
|
||||||
/**指定每页可以显示多少条 */
|
|
||||||
pageSizeOptions: ['10', '20', '50', '100'],
|
|
||||||
/**只有一页时是否隐藏分页器 */
|
|
||||||
hideOnSinglePage: false,
|
|
||||||
/**是否可以快速跳转至某页 */
|
|
||||||
showQuickJumper: true,
|
|
||||||
/**是否可以改变 pageSize */
|
|
||||||
showSizeChanger: true,
|
|
||||||
/**数据总数 */
|
|
||||||
total: 0,
|
|
||||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
|
||||||
onChange: (page: number, pageSize: number) => {
|
|
||||||
tablePagination.current = page;
|
|
||||||
tablePagination.pageSize = pageSize;
|
|
||||||
queryParams.pageNum = page;
|
|
||||||
queryParams.pageSize = pageSize;
|
|
||||||
fnGetList();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格紧凑型变更操作 */
|
|
||||||
function fnTableSize({ key }: MenuInfo) {
|
|
||||||
tableState.size = key as SizeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**表格多选 */
|
|
||||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
|
||||||
tableState.selectedRowKeys = keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**对话框对象信息状态类型 */
|
|
||||||
type ModalStateType = {
|
|
||||||
/**确定按钮 loading */
|
|
||||||
confirmLoading: boolean;
|
|
||||||
/**最大ID值 */
|
|
||||||
maxId: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**对话框对象信息状态 */
|
|
||||||
let modalState: ModalStateType = reactive({
|
|
||||||
confirmLoading: false,
|
|
||||||
maxId: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 记录删除
|
|
||||||
* @param id 编号
|
|
||||||
*/
|
|
||||||
function fnRecordDelete(id: string) {
|
|
||||||
if (!id || modalState.confirmLoading) return;
|
|
||||||
let msg = id;
|
|
||||||
if (id === '0') {
|
|
||||||
msg = `${id}... ${tableState.selectedRowKeys.length}`;
|
|
||||||
id = tableState.selectedRowKeys.join(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
Modal.confirm({
|
|
||||||
title: t('common.tipTitle'),
|
|
||||||
content: t('views.dashboard.cdr.delTip', { msg }),
|
|
||||||
onOk() {
|
|
||||||
modalState.confirmLoading = true;
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
delSGWCDataCDR(id)
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success({
|
|
||||||
content: t('common.operateOk'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
fnGetList(1);
|
|
||||||
} else {
|
|
||||||
message.error({
|
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
modalState.confirmLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制CDR
|
|
||||||
* @param jsonStr JSON字符串
|
|
||||||
*/
|
|
||||||
function fnRecordCopy(jsonStr: string) {
|
|
||||||
if (!jsonStr) return;
|
|
||||||
const text = JSON.stringify(jsonStr, null, 2);
|
|
||||||
copy(text).then(() => {
|
|
||||||
message.success(t('common.copyOk'), 3);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**查询列表, pageNum初始页数 */
|
|
||||||
function fnGetList(pageNum?: number) {
|
|
||||||
if (tableState.loading) return;
|
|
||||||
tableState.loading = true;
|
|
||||||
if (pageNum) {
|
|
||||||
queryParams.pageNum = pageNum;
|
|
||||||
}
|
|
||||||
// 时间范围
|
|
||||||
if (
|
|
||||||
Array.isArray(queryRangePicker.value) &&
|
|
||||||
queryRangePicker.value.length > 0
|
|
||||||
) {
|
|
||||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
|
||||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
|
||||||
} else {
|
|
||||||
queryParams.startTime = undefined;
|
|
||||||
queryParams.endTime = undefined;
|
|
||||||
}
|
|
||||||
listSGWCDataCDR(toRaw(queryParams)).then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
|
||||||
// 取消勾选
|
|
||||||
if (tableState.selectedRowKeys.length > 0) {
|
|
||||||
tableState.selectedRowKeys = [];
|
|
||||||
}
|
|
||||||
tablePagination.total = res.total;
|
|
||||||
// 遍历处理cdr字符串数据
|
|
||||||
tableState.data = res.rows.map(item => {
|
|
||||||
let cdrJSON = item.cdrJSON;
|
|
||||||
if (!cdrJSON) {
|
|
||||||
Reflect.set(item, 'cdrJSON', {});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
cdrJSON = JSON.parse(cdrJSON);
|
|
||||||
Reflect.set(item, 'cdrJSON', cdrJSON);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
Reflect.set(item, 'cdrJSON', {});
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 取最大值ID用作实时累加
|
|
||||||
if (res.total > 0) {
|
|
||||||
modalState.maxId = Number(res.rows[0].id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tableState.loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**列表导出 */
|
|
||||||
function fnExportList() {
|
|
||||||
if (modalState.confirmLoading) return;
|
|
||||||
Modal.confirm({
|
|
||||||
title: t('common.tipTitle'),
|
|
||||||
content: t('views.dashboard.cdr.exportTip'),
|
|
||||||
onOk() {
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
const querys = toRaw(queryParams);
|
|
||||||
querys.pageSize = 10000;
|
|
||||||
exportSGWCDataCDR(querys)
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success({
|
|
||||||
content: t('common.operateOk'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
saveAs(res.data, `sgwc_cdr_event_export_${Date.now()}.xlsx`);
|
|
||||||
} else {
|
|
||||||
message.error({
|
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
modalState.confirmLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**实时数据开关 */
|
|
||||||
const realTimeData = ref<boolean>(false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实时数据
|
|
||||||
*/
|
|
||||||
function fnRealTime() {
|
|
||||||
realTimeData.value = !realTimeData.value;
|
|
||||||
if (realTimeData.value) {
|
|
||||||
tableState.seached = false;
|
|
||||||
// 建立链接
|
|
||||||
const options: OptionsType = {
|
|
||||||
url: '/ws',
|
|
||||||
params: {
|
|
||||||
/**订阅通道组
|
|
||||||
*
|
|
||||||
* CDR会话事件-SGWC (GroupID:1008)
|
|
||||||
*/
|
|
||||||
subGroupID: `1008_${queryParams.neId}`,
|
|
||||||
},
|
|
||||||
onmessage: wsMessage,
|
|
||||||
onerror: (ev: any) => {
|
|
||||||
console.error(ev);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ws.connect(options);
|
|
||||||
} else {
|
|
||||||
ws.close();
|
|
||||||
tableState.seached = true;
|
|
||||||
fnGetList(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**接收数据后回调 */
|
|
||||||
function wsMessage(res: Record<string, any>) {
|
|
||||||
const { code, requestId, data } = res;
|
|
||||||
if (code === RESULT_CODE_ERROR) {
|
|
||||||
console.warn(res.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 订阅组信息
|
|
||||||
if (!data?.groupId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// cdrEvent CDR会话事件
|
|
||||||
if (data.groupId === `1008_${queryParams.neId}`) {
|
|
||||||
const cdrEvent = data.data;
|
|
||||||
queue.add(async () => {
|
|
||||||
modalState.maxId += 1;
|
|
||||||
tableState.data.unshift({
|
|
||||||
id: modalState.maxId,
|
|
||||||
neType: cdrEvent.neType,
|
|
||||||
neName: cdrEvent.neName,
|
|
||||||
rmUID: cdrEvent.rmUID,
|
|
||||||
timestamp: cdrEvent.timestamp,
|
|
||||||
cdrJSON: cdrEvent.CDR,
|
|
||||||
});
|
|
||||||
tablePagination.total += 1;
|
|
||||||
if (tableState.data.length > 100) {
|
|
||||||
tableState.data.pop();
|
|
||||||
}
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 800));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// 获取网元网元列表
|
|
||||||
useNeInfoStore()
|
|
||||||
.fnNelist()
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
if (res.data.length > 0) {
|
|
||||||
let arr: Record<string, any>[] = [];
|
|
||||||
res.data.forEach(i => {
|
|
||||||
if (i.neType === 'SGWC') {
|
|
||||||
arr.push({ value: i.neId, label: i.neName });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
neOtions.value = arr;
|
|
||||||
if (arr.length > 0) {
|
|
||||||
queryParams.neId = arr[0].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message.warning({
|
|
||||||
content: t('common.noData'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
// 获取列表数据
|
|
||||||
fnGetList();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
if (ws.state() !== -1) {
|
|
||||||
ws.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<PageContainer>
|
|
||||||
<a-card
|
|
||||||
v-show="tableState.seached"
|
|
||||||
:bordered="false"
|
|
||||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
|
||||||
>
|
|
||||||
<!-- 表格搜索栏 -->
|
|
||||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
|
||||||
<a-row :gutter="16">
|
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
|
||||||
<a-form-item label="SGWC" name="neId ">
|
|
||||||
<a-select
|
|
||||||
v-model:value="queryParams.neId"
|
|
||||||
:options="neOtions"
|
|
||||||
:placeholder="t('common.selectPlease')"
|
|
||||||
@change="fnQueryReset()"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.dashboard.cdr.sgwcServedIMSI')"
|
|
||||||
name="imsi"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="queryParams.imsi"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="40"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.dashboard.cdr.sgwcServedMSISDN')"
|
|
||||||
name="msisdn"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="queryParams.msisdn"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="40"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="4" :md="12" :xs="24">
|
|
||||||
<a-form-item>
|
|
||||||
<a-space :size="8">
|
|
||||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
|
||||||
<template #icon><SearchOutlined /></template>
|
|
||||||
{{ t('common.search') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="default" @click.prevent="fnQueryReset">
|
|
||||||
<template #icon><ClearOutlined /></template>
|
|
||||||
{{ t('common.reset') }}
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="8" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.dashboard.cdr.time')"
|
|
||||||
name="queryRangePicker"
|
|
||||||
>
|
|
||||||
<a-range-picker
|
|
||||||
v-model:value="queryRangePicker"
|
|
||||||
:presets="rangePickerPresets"
|
|
||||||
:bordered="true"
|
|
||||||
:allow-clear="false"
|
|
||||||
style="width: 100%"
|
|
||||||
:show-time="{ format: 'HH:mm:ss' }"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
></a-range-picker>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-form>
|
|
||||||
</a-card>
|
|
||||||
|
|
||||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
|
||||||
<!-- 插槽-卡片左侧侧 -->
|
|
||||||
<template #title>
|
|
||||||
<a-space :size="8" align="center">
|
|
||||||
<a-popconfirm
|
|
||||||
placement="bottomLeft"
|
|
||||||
:title="
|
|
||||||
!realTimeData
|
|
||||||
? t('views.dashboard.cdr.realTimeDataStart')
|
|
||||||
: t('views.dashboard.cdr.realTimeDataStop')
|
|
||||||
"
|
|
||||||
ok-text="Yes"
|
|
||||||
cancel-text="No"
|
|
||||||
@confirm="fnRealTime()"
|
|
||||||
>
|
|
||||||
<a-button type="primary" :danger="realTimeData">
|
|
||||||
<template #icon><FundOutlined /> </template>
|
|
||||||
{{
|
|
||||||
!realTimeData
|
|
||||||
? t('views.dashboard.cdr.realTimeDataStart')
|
|
||||||
: t('views.dashboard.cdr.realTimeDataStop')
|
|
||||||
}}
|
|
||||||
</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
|
|
||||||
<a-button
|
|
||||||
type="default"
|
|
||||||
danger
|
|
||||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
|
||||||
:loading="modalState.confirmLoading"
|
|
||||||
@click.prevent="fnRecordDelete('0')"
|
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
|
||||||
<template #icon><DeleteOutlined /></template>
|
|
||||||
{{ t('common.deleteText') }}
|
|
||||||
</a-button>
|
|
||||||
|
|
||||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
|
||||||
<template #icon><ExportOutlined /></template>
|
|
||||||
{{ t('common.export') }}
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 插槽-卡片右侧 -->
|
|
||||||
<template #extra>
|
|
||||||
<a-space :size="8" align="center">
|
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.searchBarText') }}</template>
|
|
||||||
<a-switch
|
|
||||||
v-model:checked="tableState.seached"
|
|
||||||
:checked-children="t('common.switch.show')"
|
|
||||||
:un-checked-children="t('common.switch.hide')"
|
|
||||||
size="small"
|
|
||||||
:disabled="realTimeData"
|
|
||||||
/>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
|
||||||
<a-button type="text" @click.prevent="fnGetList()">
|
|
||||||
<template #icon><ReloadOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.sizeText') }}</template>
|
|
||||||
<a-dropdown trigger="click" placement="bottomRight">
|
|
||||||
<a-button type="text">
|
|
||||||
<template #icon><ColumnHeightOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
<template #overlay>
|
|
||||||
<a-menu
|
|
||||||
:selected-keys="[tableState.size as string]"
|
|
||||||
@click="fnTableSize"
|
|
||||||
>
|
|
||||||
<a-menu-item key="default">
|
|
||||||
{{ t('common.size.default') }}
|
|
||||||
</a-menu-item>
|
|
||||||
<a-menu-item key="middle">
|
|
||||||
{{ t('common.size.middle') }}
|
|
||||||
</a-menu-item>
|
|
||||||
<a-menu-item key="small">
|
|
||||||
{{ t('common.size.small') }}
|
|
||||||
</a-menu-item>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
</a-tooltip>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 表格列表 -->
|
|
||||||
<a-table
|
|
||||||
class="table"
|
|
||||||
row-key="id"
|
|
||||||
:columns="tableColumns"
|
|
||||||
:loading="tableState.loading"
|
|
||||||
:data-source="tableState.data"
|
|
||||||
:size="tableState.size"
|
|
||||||
:pagination="tablePagination"
|
|
||||||
:scroll="{ x: tableColumns.length * 150, y: 'calc(100vh - 480px)' }"
|
|
||||||
:row-selection="{
|
|
||||||
type: 'checkbox',
|
|
||||||
columnWidth: '48px',
|
|
||||||
selectedRowKeys: tableState.selectedRowKeys,
|
|
||||||
onChange: fnTableSelectedRowKeys,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.key === 'id'">
|
|
||||||
<a-space :size="8" align="center">
|
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.copyText') }}</template>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
@click.prevent="fnRecordCopy(record.cdrJSON)"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<CopyOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.deleteText') }}</template>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
@click.prevent="fnRecordDelete(record.id)"
|
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<DeleteOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
<template #expandedRowRender="{ record }">
|
|
||||||
<a-row :gutter="16">
|
|
||||||
<a-col :lg="8" :md="12" :xs="24" :offset="2">
|
|
||||||
<a-divider orientation="left">
|
|
||||||
{{ t('views.dashboard.cdr.cdrInfo') }}
|
|
||||||
</a-divider>
|
|
||||||
<div>
|
|
||||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
|
||||||
<span>{{ record.neName }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
|
||||||
<span>{{ record.rmUID }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>{{ t('views.dashboard.cdr.time') }}: </span>
|
|
||||||
<span>{{ record.cdrJSON.recordOpeningTime }}</span>
|
|
||||||
</div>
|
|
||||||
<a-divider orientation="left">
|
|
||||||
{{ t('views.dashboard.cdr.rowInfo') }}
|
|
||||||
</a-divider>
|
|
||||||
<div>
|
|
||||||
<span>Record Type: </span>
|
|
||||||
<span>{{ record.cdrJSON.recordType }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Record Opening Time: </span>
|
|
||||||
<span>{{ record.cdrJSON.recordOpeningTime }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Charging ID: </span>
|
|
||||||
<span>{{ record.cdrJSON.chargingID }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Duration: </span>
|
|
||||||
<span>{{ record.cdrJSON.duration }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Record Access Point Name NI: </span>
|
|
||||||
<span>{{ record.cdrJSON.accessPointNameNI }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Record Cause For Rec Closing: </span>
|
|
||||||
<span>{{ record.cdrJSON.causeForRecClosing }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Record Sequence Number: </span>
|
|
||||||
<span>{{ record.cdrJSON.recordSequenceNumber }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Local Record Sequence Number: </span>
|
|
||||||
<span>{{ record.cdrJSON.localRecordSequenceNumber }}</span>
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="8" :md="12" :xs="24">
|
|
||||||
<a-divider orientation="left"> Server Information </a-divider>
|
|
||||||
<div>
|
|
||||||
<span>IMSI: </span>
|
|
||||||
<span> {{ record.cdrJSON.servedIMSI }} </span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>MSISDN: </span>
|
|
||||||
<span> {{ record.cdrJSON.servedMSISDN }} </span>
|
|
||||||
</div>
|
|
||||||
<div v-if="record.cdrJSON.pGWAddressUsed">
|
|
||||||
<span>PGW Address: </span>
|
|
||||||
<span> {{ record.cdrJSON.pGWAddressUsed }} </span>
|
|
||||||
</div>
|
|
||||||
<div v-if="record.cdrJSON.GGSNAddress">
|
|
||||||
<span>GGSN Address: </span>
|
|
||||||
<span> {{ record.cdrJSON.GGSNAddress }} </span>
|
|
||||||
</div>
|
|
||||||
<div v-if="record.cdrJSON.sGWAddress">
|
|
||||||
<span>SGW Address: </span>
|
|
||||||
<span> {{ record.cdrJSON.sGWAddress }} </span>
|
|
||||||
</div>
|
|
||||||
<div v-if="record.cdrJSON.SGSNAddress">
|
|
||||||
<span>SGSN Address: </span>
|
|
||||||
<span> {{ record.cdrJSON.SGSNAddress }} </span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>RAT Type: </span>
|
|
||||||
<span> {{ record.cdrJSON.rATType }} </span>
|
|
||||||
</div>
|
|
||||||
<a-divider orientation="left"> PDPPD Information </a-divider>
|
|
||||||
<div>
|
|
||||||
<span>PDPPDN Type: </span>
|
|
||||||
<span> {{ record.cdrJSON.pdpPDNType }} </span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>PDPPDN Address: </span>
|
|
||||||
<span> {{ record.cdrJSON.servedPDPPDNAddress }} </span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Node Address: </span>
|
|
||||||
<span>
|
|
||||||
{{ record.cdrJSON.servingNodeAddress?.join(', ') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Node Type: </span>
|
|
||||||
<span>
|
|
||||||
<template v-for="item in record.cdrJSON.servingNodeType">
|
|
||||||
{{ item.servingNodeType }}
|
|
||||||
</template>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</a-card>
|
|
||||||
</PageContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.table :deep(.ant-pagination) {
|
|
||||||
padding: 0 24px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -19,10 +19,6 @@ import {
|
|||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
|
||||||
import { useClipboard } from '@vueuse/core';
|
|
||||||
import { parseSizeFromByte } from '@/utils/parse-utils';
|
|
||||||
const { copy } = useClipboard({ legacy: true });
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const ws = new WS();
|
const ws = new WS();
|
||||||
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
const queue = new PQueue({ concurrency: 1, autoStart: true });
|
||||||
@@ -31,25 +27,7 @@ const queue = new PQueue({ concurrency: 1, autoStart: true });
|
|||||||
let neOtions = ref<Record<string, any>[]>([]);
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
/**开始结束时间 */
|
/**开始结束时间 */
|
||||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>([
|
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||||
dayjs().startOf('hour'),
|
|
||||||
dayjs().endOf('hour'),
|
|
||||||
]);
|
|
||||||
/**时间范围 */
|
|
||||||
let rangePickerPresets = ref([
|
|
||||||
{
|
|
||||||
label: 'Now hour',
|
|
||||||
value: [dayjs().startOf('hour'), dayjs().endOf('hour')],
|
|
||||||
},
|
|
||||||
{ label: 'Today', value: [dayjs().startOf('day'), dayjs().endOf('day')] },
|
|
||||||
{
|
|
||||||
label: 'Yesterday',
|
|
||||||
value: [
|
|
||||||
dayjs().subtract(1, 'day').startOf('day'),
|
|
||||||
dayjs().subtract(1, 'day').endOf('day'),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
/**查询参数 */
|
||||||
let queryParams = reactive({
|
let queryParams = reactive({
|
||||||
@@ -60,9 +38,9 @@ let queryParams = reactive({
|
|||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
/**开始时间 */
|
/**开始时间 */
|
||||||
startTime: undefined as undefined | number,
|
startTime: '',
|
||||||
/**结束时间 */
|
/**结束时间 */
|
||||||
endTime: undefined as undefined | number,
|
endTime: '',
|
||||||
/**当前页数 */
|
/**当前页数 */
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
/**每页条数 */
|
/**每页条数 */
|
||||||
@@ -73,10 +51,12 @@ let queryParams = reactive({
|
|||||||
function fnQueryReset() {
|
function fnQueryReset() {
|
||||||
queryParams = Object.assign(queryParams, {
|
queryParams = Object.assign(queryParams, {
|
||||||
subscriberID: '',
|
subscriberID: '',
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
});
|
});
|
||||||
queryRangePicker.value = [dayjs().startOf('hour'), dayjs().endOf('hour')];
|
queryRangePicker.value = ['', ''];
|
||||||
tablePagination.current = 1;
|
tablePagination.current = 1;
|
||||||
tablePagination.pageSize = 20;
|
tablePagination.pageSize = 20;
|
||||||
fnGetList();
|
fnGetList();
|
||||||
@@ -106,7 +86,7 @@ let tableState: TabeStateType = reactive({
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**表格字段列 */
|
/**表格字段列 */
|
||||||
let tableColumns = ref<ColumnsType>([
|
let tableColumns: ColumnsType = [
|
||||||
{
|
{
|
||||||
title: t('common.rowId'),
|
title: t('common.rowId'),
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
@@ -114,7 +94,7 @@ let tableColumns = ref<ColumnsType>([
|
|||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.dashboard.cdr.chargingID'), // 计费ID
|
title: t('views.dashboard.cdr.smfChargingID'), // 计费ID
|
||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 100,
|
width: 100,
|
||||||
@@ -157,15 +137,11 @@ let tableColumns = ref<ColumnsType>([
|
|||||||
) {
|
) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let dataVolumeUplink = 0;
|
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||||
for (const v of listOfMultipleUnitUsage) {
|
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||||
if (Array.isArray(v.usedUnitContainer)) {
|
return 0;
|
||||||
for (const used of v.usedUnitContainer) {
|
|
||||||
dataVolumeUplink += +used.dataVolumeUplink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return parseSizeFromByte(dataVolumeUplink, 'MB');
|
return usedUnitContainer[0].dataVolumeUplink;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -182,15 +158,11 @@ let tableColumns = ref<ColumnsType>([
|
|||||||
) {
|
) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let dataVolumeDownlink = 0;
|
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||||
for (const v of listOfMultipleUnitUsage) {
|
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||||
if (Array.isArray(v.usedUnitContainer)) {
|
return 0;
|
||||||
for (const used of v.usedUnitContainer) {
|
|
||||||
dataVolumeDownlink += +used.dataVolumeDownlink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return parseSizeFromByte(dataVolumeDownlink, 'MB');
|
return usedUnitContainer[0].dataVolumeDownlink;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -207,19 +179,15 @@ let tableColumns = ref<ColumnsType>([
|
|||||||
) {
|
) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let dataTotalVolume = 0;
|
const usedUnitContainer = listOfMultipleUnitUsage[0].usedUnitContainer;
|
||||||
for (const v of listOfMultipleUnitUsage) {
|
if (!Array.isArray(usedUnitContainer) || usedUnitContainer.length < 1) {
|
||||||
if (Array.isArray(v.usedUnitContainer)) {
|
return 0;
|
||||||
for (const used of v.usedUnitContainer) {
|
|
||||||
dataTotalVolume += +used.dataTotalVolume;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return parseSizeFromByte(dataTotalVolume, 'MB');
|
return usedUnitContainer[0].dataTotalVolume;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.dashboard.cdr.durationTime'), // 持续时间
|
title: t('views.dashboard.cdr.smfDuration'), // 持续时间
|
||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 100,
|
width: 100,
|
||||||
@@ -229,7 +197,7 @@ let tableColumns = ref<ColumnsType>([
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.dashboard.cdr.invocationTime'), // 调用时间
|
title: t('views.dashboard.cdr.smfInvocationTime'), // 调用时间
|
||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 200,
|
width: 200,
|
||||||
@@ -243,7 +211,7 @@ let tableColumns = ref<ColumnsType>([
|
|||||||
key: 'id',
|
key: 'id',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
]);
|
];
|
||||||
|
|
||||||
/**表格分页器参数 */
|
/**表格分页器参数 */
|
||||||
let tablePagination = reactive({
|
let tablePagination = reactive({
|
||||||
@@ -338,18 +306,6 @@ function fnRecordDelete(id: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制CDR
|
|
||||||
* @param jsonStr JSON字符串
|
|
||||||
*/
|
|
||||||
function fnRecordCopy(jsonStr: string) {
|
|
||||||
if (!jsonStr) return;
|
|
||||||
const text = JSON.stringify(jsonStr, null, 2);
|
|
||||||
copy(text).then(() => {
|
|
||||||
message.success(t('common.copyOk'), 3);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**查询列表, pageNum初始页数 */
|
/**查询列表, pageNum初始页数 */
|
||||||
function fnGetList(pageNum?: number) {
|
function fnGetList(pageNum?: number) {
|
||||||
if (tableState.loading) return;
|
if (tableState.loading) return;
|
||||||
@@ -357,19 +313,11 @@ function fnGetList(pageNum?: number) {
|
|||||||
if (pageNum) {
|
if (pageNum) {
|
||||||
queryParams.pageNum = pageNum;
|
queryParams.pageNum = pageNum;
|
||||||
}
|
}
|
||||||
|
if (!queryRangePicker.value) {
|
||||||
// 时间范围
|
queryRangePicker.value = ['', ''];
|
||||||
if (
|
|
||||||
Array.isArray(queryRangePicker.value) &&
|
|
||||||
queryRangePicker.value.length > 0
|
|
||||||
) {
|
|
||||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
|
||||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
|
||||||
} else {
|
|
||||||
queryParams.startTime = undefined;
|
|
||||||
queryParams.endTime = undefined;
|
|
||||||
}
|
}
|
||||||
|
queryParams.startTime = queryRangePicker.value[0];
|
||||||
|
queryParams.endTime = queryRangePicker.value[1];
|
||||||
listSMFDataCDR(toRaw(queryParams)).then(res => {
|
listSMFDataCDR(toRaw(queryParams)).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
// 取消勾选
|
// 取消勾选
|
||||||
@@ -458,9 +406,7 @@ function fnRealTime() {
|
|||||||
subGroupID: `1006_${queryParams.neId}`,
|
subGroupID: `1006_${queryParams.neId}`,
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: (ev: any) => {
|
onerror: wsError,
|
||||||
console.error(ev);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
} else {
|
} else {
|
||||||
@@ -470,6 +416,12 @@ function fnRealTime() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**接收数据后回调 */
|
||||||
|
function wsError(ev: any) {
|
||||||
|
// 接收数据后回调
|
||||||
|
console.error(ev);
|
||||||
|
}
|
||||||
|
|
||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsMessage(res: Record<string, any>) {
|
function wsMessage(res: Record<string, any>) {
|
||||||
const { code, requestId, data } = res;
|
const { code, requestId, data } = res;
|
||||||
@@ -558,7 +510,6 @@ onBeforeUnmount(() => {
|
|||||||
v-model:value="queryParams.neId"
|
v-model:value="queryParams.neId"
|
||||||
:options="neOtions"
|
:options="neOtions"
|
||||||
:placeholder="t('common.selectPlease')"
|
:placeholder="t('common.selectPlease')"
|
||||||
@change="fnQueryReset()"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -582,12 +533,12 @@ onBeforeUnmount(() => {
|
|||||||
>
|
>
|
||||||
<a-range-picker
|
<a-range-picker
|
||||||
v-model:value="queryRangePicker"
|
v-model:value="queryRangePicker"
|
||||||
:presets="rangePickerPresets"
|
allow-clear
|
||||||
:bordered="true"
|
bordered
|
||||||
:allow-clear="false"
|
|
||||||
style="width: 100%"
|
|
||||||
:show-time="{ format: 'HH:mm:ss' }"
|
:show-time="{ format: 'HH:mm:ss' }"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
value-format="x"
|
||||||
|
style="width: 100%"
|
||||||
></a-range-picker>
|
></a-range-picker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -640,7 +591,6 @@ onBeforeUnmount(() => {
|
|||||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||||
:loading="modalState.confirmLoading"
|
:loading="modalState.confirmLoading"
|
||||||
@click.prevent="fnRecordDelete('0')"
|
@click.prevent="fnRecordDelete('0')"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon><DeleteOutlined /></template>
|
<template #icon><DeleteOutlined /></template>
|
||||||
{{ t('common.deleteText') }}
|
{{ t('common.deleteText') }}
|
||||||
@@ -719,23 +669,11 @@ onBeforeUnmount(() => {
|
|||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'id'">
|
<template v-if="column.key === 'id'">
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.copyText') }}</template>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
@click.prevent="fnRecordCopy(record.cdrJSON)"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<CopyOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.deleteText') }}</template>
|
<template #title>{{ t('common.deleteText') }}</template>
|
||||||
<a-button
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
@click.prevent="fnRecordDelete(record.id)"
|
@click.prevent="fnRecordDelete(record.id)"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<DeleteOutlined />
|
<DeleteOutlined />
|
||||||
@@ -804,33 +742,24 @@ onBeforeUnmount(() => {
|
|||||||
<a-divider orientation="left">
|
<a-divider orientation="left">
|
||||||
List Of Multiple Unit Usage
|
List Of Multiple Unit Usage
|
||||||
</a-divider>
|
</a-divider>
|
||||||
|
|
||||||
<div v-for="u in record.cdrJSON.listOfMultipleUnitUsage">
|
<div v-for="u in record.cdrJSON.listOfMultipleUnitUsage">
|
||||||
<!-- <div>RatingGroup: {{ u.ratingGroup }}</div> -->
|
<div>RatingGroup: {{ u.ratingGroup }}</div>
|
||||||
<div
|
<div v-for="udata in u.usedUnitContainer">
|
||||||
v-for="(udata, i) in u.usedUnitContainer"
|
|
||||||
style="display: flex"
|
|
||||||
>
|
|
||||||
<!-- <strong style="margin-right: 12px">
|
|
||||||
{{ i }}
|
|
||||||
</strong> -->
|
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<span>Data Total Volume: </span>
|
||||||
<span>Data Total Volume: </span>
|
<span>{{ udata.dataTotalVolume }}</span>
|
||||||
<span>{{ udata.dataTotalVolume }}</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<span>Data Volume Downlink: </span>
|
||||||
<span>Data Volume Downlink: </span>
|
<span>{{ udata.dataVolumeDownlink }}</span>
|
||||||
<span>{{ udata.dataVolumeDownlink }}</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<span>Data Volume Uplink: </span>
|
||||||
<span>Data Volume Uplink: </span>
|
<span>{{ udata.dataVolumeUplink }}</span>
|
||||||
<span>{{ udata.dataVolumeUplink }}</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<!-- <div>
|
<span>Time: </span>
|
||||||
<span>Time: </span>
|
<span>{{ udata.time }}</span>
|
||||||
<span>{{ udata.time }}</span>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,699 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import * as echarts from 'echarts/core';
|
|
||||||
import {
|
|
||||||
TitleComponent,
|
|
||||||
ToolboxComponent,
|
|
||||||
TooltipComponent,
|
|
||||||
GridComponent,
|
|
||||||
LegendComponent,
|
|
||||||
DataZoomComponent,
|
|
||||||
} from 'echarts/components';
|
|
||||||
import { LineChart } from 'echarts/charts';
|
|
||||||
import { UniversalTransition } from 'echarts/features';
|
|
||||||
import { CanvasRenderer } from 'echarts/renderers';
|
|
||||||
|
|
||||||
echarts.use([
|
|
||||||
TitleComponent,
|
|
||||||
ToolboxComponent,
|
|
||||||
TooltipComponent,
|
|
||||||
GridComponent,
|
|
||||||
LegendComponent,
|
|
||||||
DataZoomComponent,
|
|
||||||
LineChart,
|
|
||||||
CanvasRenderer,
|
|
||||||
UniversalTransition,
|
|
||||||
]);
|
|
||||||
|
|
||||||
import { reactive, onMounted, toRaw, onBeforeUnmount, ref } from 'vue';
|
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
|
||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
import { listSMFDataCDR } from '@/api/neData/smf';
|
|
||||||
import {
|
|
||||||
RESULT_CODE_ERROR,
|
|
||||||
RESULT_CODE_SUCCESS,
|
|
||||||
} from '@/constants/result-constants';
|
|
||||||
import { parseSizeFromByte } from '@/utils/parse-utils';
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
|
||||||
const { t, currentLocale } = useI18n();
|
|
||||||
const ws = new WS();
|
|
||||||
|
|
||||||
/**图DOM节点实例对象 */
|
|
||||||
const cdrChartDom = ref<HTMLElement | undefined>(undefined);
|
|
||||||
/**图实例对象 */
|
|
||||||
let cdrChart: echarts.ECharts | null = null;
|
|
||||||
/**图表配置 */
|
|
||||||
const option = {
|
|
||||||
title: {
|
|
||||||
text: 'Data Usage Report',
|
|
||||||
left: 'left',
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: {
|
|
||||||
animation: true,
|
|
||||||
},
|
|
||||||
formatter: (params: any) => {
|
|
||||||
const title = params[0].name;
|
|
||||||
let uplinkValue = 0;
|
|
||||||
let downlinkValue = 0;
|
|
||||||
if (params[0].seriesName === 'Uplink') {
|
|
||||||
uplinkValue = params[0].value;
|
|
||||||
} else {
|
|
||||||
downlinkValue = params[0].value;
|
|
||||||
}
|
|
||||||
if (params[1].seriesName === 'Uplink') {
|
|
||||||
uplinkValue = params[1].value;
|
|
||||||
} else {
|
|
||||||
downlinkValue = params[1].value;
|
|
||||||
}
|
|
||||||
const uplinkValueF = parseSizeFromByte(uplinkValue, 'MB');
|
|
||||||
const downlinkValueF = parseSizeFromByte(downlinkValue, 'MB');
|
|
||||||
return `
|
|
||||||
<div style="font-weight: bold;">${title}</div>
|
|
||||||
<div>Downlink: ${downlinkValueF}</div>
|
|
||||||
<div>Uplink: ${uplinkValueF}</div>
|
|
||||||
`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
toolbox: {
|
|
||||||
feature: {
|
|
||||||
dataZoom: {
|
|
||||||
yAxisIndex: 'none',
|
|
||||||
},
|
|
||||||
saveAsImage: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
axisPointer: {
|
|
||||||
link: [
|
|
||||||
{
|
|
||||||
xAxisIndex: 'all',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
dataZoom: [
|
|
||||||
{
|
|
||||||
show: false,
|
|
||||||
realtime: true,
|
|
||||||
start: 0,
|
|
||||||
end: 100,
|
|
||||||
xAxisIndex: [0, 1],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'inside',
|
|
||||||
realtime: true,
|
|
||||||
start: 0,
|
|
||||||
end: 100,
|
|
||||||
xAxisIndex: [0, 1],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
grid: [
|
|
||||||
{
|
|
||||||
left: '10%',
|
|
||||||
right: 50,
|
|
||||||
height: '40%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
left: '10%',
|
|
||||||
right: 50,
|
|
||||||
top: '50%',
|
|
||||||
height: '40%',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
xAxis: [
|
|
||||||
{
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
axisLine: { onZero: true },
|
|
||||||
data: [], // x轴初始数据
|
|
||||||
axisLabel: {
|
|
||||||
show: false, // 显示标签
|
|
||||||
rotate: 15, // 设置倾斜角度(如15度)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gridIndex: 1,
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
axisLine: { onZero: true },
|
|
||||||
data: [], // x轴初始数据
|
|
||||||
axisLabel: {
|
|
||||||
show: false, // 隐藏第二个 x 轴的标签
|
|
||||||
},
|
|
||||||
position: 'top',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
yAxis: [
|
|
||||||
{
|
|
||||||
name: 'Downlink (Byte)',
|
|
||||||
type: 'value',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gridIndex: 1,
|
|
||||||
name: 'Uplink (Byte)',
|
|
||||||
type: 'value',
|
|
||||||
inverse: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'Downlink',
|
|
||||||
type: 'line',
|
|
||||||
data: [], // y轴初始数据
|
|
||||||
symbol: 'circle', // 数据点形状
|
|
||||||
symbolSize: 6, // 数据点大小
|
|
||||||
smooth: true, // 平滑曲线
|
|
||||||
color: 'rgb(0, 190, 99)',
|
|
||||||
areaStyle: {
|
|
||||||
color: {
|
|
||||||
colorStops: [
|
|
||||||
{ offset: 0, color: 'rgba(0, 190, 99, .5)' },
|
|
||||||
{ offset: 1, color: 'rgba(0, 190, 99, 0.5)' },
|
|
||||||
],
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 0,
|
|
||||||
y2: 1,
|
|
||||||
type: 'linear',
|
|
||||||
global: false,
|
|
||||||
},
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
shadowBlur: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Uplink',
|
|
||||||
type: 'line',
|
|
||||||
xAxisIndex: 1,
|
|
||||||
yAxisIndex: 1,
|
|
||||||
data: [], // y轴初始数据
|
|
||||||
symbol: 'circle', // 数据点形状
|
|
||||||
symbolSize: 6, // 数据点大小
|
|
||||||
smooth: true, // 平滑曲线
|
|
||||||
color: 'rgb(17, 178, 255)',
|
|
||||||
areaStyle: {
|
|
||||||
color: {
|
|
||||||
colorStops: [
|
|
||||||
{ offset: 0, color: 'rgba(17, 178, 255, .5)' },
|
|
||||||
{ offset: 1, color: 'rgba(17, 178, 255, 0.5)' },
|
|
||||||
],
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 0,
|
|
||||||
y2: 1,
|
|
||||||
type: 'linear',
|
|
||||||
global: false,
|
|
||||||
},
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
shadowBlur: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
/**绘制图表 */
|
|
||||||
function fnRanderChart() {
|
|
||||||
const container: HTMLElement | undefined = cdrChartDom.value;
|
|
||||||
if (!container) return;
|
|
||||||
const locale = currentLocale.value.split('_')[0];
|
|
||||||
cdrChart = echarts.init(container, 'light', {
|
|
||||||
// https://github.com/apache/echarts/tree/release/src/i18n 取值langEN.ts ==> EN
|
|
||||||
locale: locale.toUpperCase(),
|
|
||||||
});
|
|
||||||
cdrChart.setOption(option);
|
|
||||||
// cdrChart.showLoading('default', {
|
|
||||||
// text: 'Please enter IMSI to query user traffic',
|
|
||||||
// fontSize: 16, // 字体大小
|
|
||||||
// });
|
|
||||||
|
|
||||||
// 创建 ResizeObserver 实例 监听图表容器大小变化,并在变化时调整图表大小
|
|
||||||
var observer = new ResizeObserver(entries => {
|
|
||||||
if (cdrChart && !cdrChart.isDisposed) {
|
|
||||||
cdrChart.resize();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 监听元素大小变化
|
|
||||||
observer.observe(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**网元可选 */
|
|
||||||
let neOtions = ref<Record<string, any>[]>([]);
|
|
||||||
|
|
||||||
/**开始结束时间 */
|
|
||||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>([
|
|
||||||
dayjs().startOf('hour'),
|
|
||||||
dayjs().endOf('hour'),
|
|
||||||
]);
|
|
||||||
/**时间范围 */
|
|
||||||
let rangePickerPresets = ref([
|
|
||||||
{
|
|
||||||
label: 'Now hour',
|
|
||||||
value: [dayjs().startOf('hour'), dayjs().endOf('hour')],
|
|
||||||
},
|
|
||||||
{ label: 'Today', value: [dayjs().startOf('day'), dayjs().endOf('day')] },
|
|
||||||
{
|
|
||||||
label: 'Yesterday',
|
|
||||||
value: [
|
|
||||||
dayjs().subtract(1, 'day').startOf('day'),
|
|
||||||
dayjs().subtract(1, 'day').endOf('day'),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
|
||||||
let queryParams = reactive({
|
|
||||||
/**网元类型 */
|
|
||||||
neType: 'SMF',
|
|
||||||
neId: '001',
|
|
||||||
subscriberID: '',
|
|
||||||
dnn: '',
|
|
||||||
sortField: 'timestamp',
|
|
||||||
sortOrder: 'desc',
|
|
||||||
/**开始时间 */
|
|
||||||
startTime: undefined as undefined | number,
|
|
||||||
/**结束时间 */
|
|
||||||
endTime: undefined as undefined | number,
|
|
||||||
/**当前页数 */
|
|
||||||
pageNum: 1,
|
|
||||||
/**每页条数 */
|
|
||||||
pageSize: 1000,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**查询参数重置 */
|
|
||||||
function fnQueryReset() {
|
|
||||||
queryParams.subscriberID = '';
|
|
||||||
queryParams.dnn = '';
|
|
||||||
queryRangePicker.value = [dayjs().startOf('hour'), dayjs().endOf('hour')];
|
|
||||||
fnGetList(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let state = reactive({
|
|
||||||
/**表格数据 */
|
|
||||||
data: [] as any[],
|
|
||||||
/**表格总数 */
|
|
||||||
total: 0,
|
|
||||||
/**表格加载状态 */
|
|
||||||
loading: false,
|
|
||||||
/**数据总量 up,down */
|
|
||||||
dataUsage: ['0 B', '0 B'],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**查询列表, pageNum初始页数 */
|
|
||||||
function fnGetList(pageNum?: number) {
|
|
||||||
if (state.loading) return;
|
|
||||||
state.loading = true;
|
|
||||||
if (!queryParams.subscriberID) {
|
|
||||||
message.warning('Please enter IMSI to query user traffic');
|
|
||||||
state.loading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pageNum) {
|
|
||||||
queryParams.pageNum = pageNum;
|
|
||||||
}
|
|
||||||
if (cdrChart) {
|
|
||||||
cdrChart.showLoading('default', {
|
|
||||||
text: 'Loading...',
|
|
||||||
fontSize: 16, // 字体大小
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 时间范围
|
|
||||||
if (
|
|
||||||
Array.isArray(queryRangePicker.value) &&
|
|
||||||
queryRangePicker.value.length > 0
|
|
||||||
) {
|
|
||||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
|
||||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
|
||||||
} else {
|
|
||||||
queryParams.startTime = undefined;
|
|
||||||
queryParams.endTime = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
listSMFDataCDR(toRaw(queryParams))
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
|
||||||
state.total = res.total;
|
|
||||||
// 遍历处理cdr字符串数据
|
|
||||||
state.data = res.rows
|
|
||||||
.map(item => {
|
|
||||||
let cdrJSON = item.cdrJSON;
|
|
||||||
if (!cdrJSON) {
|
|
||||||
Reflect.set(item, 'cdrJSON', {});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
cdrJSON = JSON.parse(cdrJSON);
|
|
||||||
Reflect.set(item, 'cdrJSON', cdrJSON);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
Reflect.set(item, 'cdrJSON', {});
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
})
|
|
||||||
.reverse();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
state.loading = false;
|
|
||||||
fnRanderChartDataLoad();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图表配置数据x轴 */
|
|
||||||
let dataTimeXAxisData: string[] = [];
|
|
||||||
/**图表配置数据y轴 */
|
|
||||||
let dataVolumeUplinkYSeriesData: number[] = [];
|
|
||||||
let dataVolumeDownlinkYSeriesData: number[] = [];
|
|
||||||
/**图表数据渲染 */
|
|
||||||
function fnRanderChartDataLoad() {
|
|
||||||
if (!cdrChart) return;
|
|
||||||
dataTimeXAxisData = [];
|
|
||||||
dataVolumeUplinkYSeriesData = [];
|
|
||||||
dataVolumeDownlinkYSeriesData = [];
|
|
||||||
if (state.data.length > 0) {
|
|
||||||
// 处理数据渲染图表
|
|
||||||
for (const item of state.data) {
|
|
||||||
if (!item.cdrJSON.invocationTimestamp) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 时间
|
|
||||||
const dataTime = item.cdrJSON.invocationTimestamp;
|
|
||||||
const listOfMultipleUnitUsage = item.cdrJSON.listOfMultipleUnitUsage;
|
|
||||||
if (
|
|
||||||
!Array.isArray(listOfMultipleUnitUsage) ||
|
|
||||||
listOfMultipleUnitUsage.length < 1
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// 数据
|
|
||||||
let dataVolumeUplink = 0;
|
|
||||||
let dataVolumeDownlink = 0;
|
|
||||||
for (const v of listOfMultipleUnitUsage) {
|
|
||||||
if (Array.isArray(v.usedUnitContainer)) {
|
|
||||||
for (const used of v.usedUnitContainer) {
|
|
||||||
dataVolumeUplink += +used.dataVolumeUplink;
|
|
||||||
dataVolumeDownlink += +used.dataVolumeDownlink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dataTimeXAxisData.push(dataTime);
|
|
||||||
dataVolumeUplinkYSeriesData.push(dataVolumeUplink);
|
|
||||||
dataVolumeDownlinkYSeriesData.push(dataVolumeDownlink);
|
|
||||||
}
|
|
||||||
// 绘制图数据
|
|
||||||
fnRanderChartDataUpdate();
|
|
||||||
} else {
|
|
||||||
message.warning('No Data');
|
|
||||||
cdrChart.hideLoading();
|
|
||||||
cdrChart.setOption({
|
|
||||||
title: {
|
|
||||||
text: `Data Volume Uplink / Downlink By IMSI ${queryParams.subscriberID}`,
|
|
||||||
},
|
|
||||||
xAxis: [
|
|
||||||
{
|
|
||||||
data: dataTimeXAxisData,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: dataTimeXAxisData,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: dataVolumeUplinkYSeriesData,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: dataVolumeDownlinkYSeriesData,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**图表数据渲染 */
|
|
||||||
function fnRanderChartDataUpdate() {
|
|
||||||
if (cdrChart == null) return;
|
|
||||||
// 绘制图数据
|
|
||||||
cdrChart.setOption({
|
|
||||||
title: {
|
|
||||||
text: `Data Usage Report of IMSI ${queryParams.subscriberID}`,
|
|
||||||
},
|
|
||||||
xAxis: [
|
|
||||||
{
|
|
||||||
data: dataTimeXAxisData,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: dataTimeXAxisData,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: dataVolumeUplinkYSeriesData,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: dataVolumeDownlinkYSeriesData,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
cdrChart.hideLoading();
|
|
||||||
|
|
||||||
// 累加总量
|
|
||||||
let uplinkTotal = 0;
|
|
||||||
let downlinkTotal = 0;
|
|
||||||
for (let index = 0; index < dataVolumeUplinkYSeriesData.length; index++) {
|
|
||||||
uplinkTotal += dataVolumeUplinkYSeriesData[index];
|
|
||||||
downlinkTotal += dataVolumeDownlinkYSeriesData[index];
|
|
||||||
}
|
|
||||||
state.dataUsage = [
|
|
||||||
parseSizeFromByte(uplinkTotal, 'MB'),
|
|
||||||
parseSizeFromByte(downlinkTotal, 'MB'),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实时数据
|
|
||||||
*/
|
|
||||||
function fnRealTime() {
|
|
||||||
if (ws.state() === WebSocket.OPEN) {
|
|
||||||
ws.close();
|
|
||||||
}
|
|
||||||
// 建立链接
|
|
||||||
const options: OptionsType = {
|
|
||||||
url: '/ws',
|
|
||||||
params: {
|
|
||||||
/**订阅通道组
|
|
||||||
*
|
|
||||||
* CDR会话事件-SMF (GroupID:1006)
|
|
||||||
*/
|
|
||||||
subGroupID: `1006_${queryParams.neId}`,
|
|
||||||
},
|
|
||||||
onmessage: (res: Record<string, any>) => {
|
|
||||||
const { code, requestId, data } = res;
|
|
||||||
if (code === RESULT_CODE_ERROR) {
|
|
||||||
console.warn(res.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 订阅组信息
|
|
||||||
if (!data?.groupId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// cdrEvent CDR会话事件
|
|
||||||
if (data.groupId === `1006_${queryParams.neId}`) {
|
|
||||||
const cdrEvent = data.data;
|
|
||||||
// 对应结束时间内
|
|
||||||
if (queryParams.endTime) {
|
|
||||||
const endTime = Math.round(queryParams.endTime / 1000);
|
|
||||||
if (cdrEvent.timestamp > endTime) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const cdrJSON = cdrEvent.CDR;
|
|
||||||
if (!cdrJSON.invocationTimestamp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 对应IMSI
|
|
||||||
if (
|
|
||||||
cdrJSON.subscriberIdentifier.subscriptionIDData !==
|
|
||||||
queryParams.subscriberID
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 时间
|
|
||||||
const dataTime = cdrJSON.invocationTimestamp;
|
|
||||||
const listOfMultipleUnitUsage = cdrJSON.listOfMultipleUnitUsage;
|
|
||||||
if (
|
|
||||||
!Array.isArray(listOfMultipleUnitUsage) ||
|
|
||||||
listOfMultipleUnitUsage.length < 1
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// 数据
|
|
||||||
let dataVolumeUplink = 0;
|
|
||||||
let dataVolumeDownlink = 0;
|
|
||||||
for (const v of listOfMultipleUnitUsage) {
|
|
||||||
if (Array.isArray(v.usedUnitContainer)) {
|
|
||||||
for (const used of v.usedUnitContainer) {
|
|
||||||
dataVolumeUplink += +used.dataVolumeUplink;
|
|
||||||
dataVolumeDownlink += +used.dataVolumeDownlink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 添加数据
|
|
||||||
dataTimeXAxisData.push(dataTime);
|
|
||||||
dataVolumeUplinkYSeriesData.push(dataVolumeUplink);
|
|
||||||
dataVolumeDownlinkYSeriesData.push(dataVolumeDownlink);
|
|
||||||
fnRanderChartDataUpdate();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onerror: (ev: any) => {
|
|
||||||
console.error(ev);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ws.connect(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// 获取网元网元列表
|
|
||||||
useNeInfoStore()
|
|
||||||
.fnNelist()
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
if (res.data.length > 0) {
|
|
||||||
let arr: Record<string, any>[] = [];
|
|
||||||
res.data.forEach((v: any) => {
|
|
||||||
if (v.neType === 'SMF') {
|
|
||||||
arr.push({ value: v.neId, label: v.neName });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
neOtions.value = arr;
|
|
||||||
if (arr.length > 0) {
|
|
||||||
queryParams.neId = arr[0].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message.warning({
|
|
||||||
content: t('common.noData'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
fnRanderChart();
|
|
||||||
fnRealTime();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
ws.close();
|
|
||||||
if (cdrChart) {
|
|
||||||
cdrChart.clear();
|
|
||||||
cdrChart.dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<PageContainer>
|
|
||||||
<a-card
|
|
||||||
: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="SMF" name="neId ">
|
|
||||||
<a-select
|
|
||||||
v-model:value="queryParams.neId"
|
|
||||||
:options="neOtions"
|
|
||||||
:placeholder="t('common.selectPlease')"
|
|
||||||
@change="fnRealTime()"
|
|
||||||
:disabled="state.loading"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
|
||||||
<a-form-item label="IMSI" name="subscriberID" :required="true">
|
|
||||||
<a-input
|
|
||||||
v-model:value="queryParams.subscriberID"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="40"
|
|
||||||
:disabled="state.loading"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
|
||||||
<a-form-item label="DNN" name="dnn">
|
|
||||||
<a-input
|
|
||||||
v-model:value="queryParams.dnn"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="40"
|
|
||||||
:disabled="state.loading"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="4" :md="12" :xs="24">
|
|
||||||
<a-form-item>
|
|
||||||
<a-space :size="8">
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
@click.prevent="fnGetList(1)"
|
|
||||||
:loading="state.loading"
|
|
||||||
>
|
|
||||||
<template #icon><SearchOutlined /></template>
|
|
||||||
{{ t('common.search') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button
|
|
||||||
type="default"
|
|
||||||
@click.prevent="fnQueryReset"
|
|
||||||
:disabled="state.loading"
|
|
||||||
>
|
|
||||||
<template #icon><ClearOutlined /></template>
|
|
||||||
{{ t('common.reset') }}
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="8" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.dashboard.cdr.time')"
|
|
||||||
name="queryRangePicker"
|
|
||||||
>
|
|
||||||
<a-range-picker
|
|
||||||
v-model:value="queryRangePicker"
|
|
||||||
:presets="rangePickerPresets"
|
|
||||||
:bordered="true"
|
|
||||||
:allow-clear="false"
|
|
||||||
style="width: 100%"
|
|
||||||
:show-time="{ format: 'HH:mm:ss' }"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
:disabled="state.loading"
|
|
||||||
></a-range-picker>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-form>
|
|
||||||
</a-card>
|
|
||||||
|
|
||||||
<a-card :bordered="false">
|
|
||||||
<!-- 图数据 -->
|
|
||||||
<div ref="cdrChartDom" style="height: 600px; width: 100%"></div>
|
|
||||||
|
|
||||||
<a-descriptions title="Data Usage" bordered :column="2">
|
|
||||||
<a-descriptions-item label="Total Uplink">
|
|
||||||
{{ state.dataUsage[0] }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="Total Downlink">
|
|
||||||
{{ state.dataUsage[1] }}
|
|
||||||
</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
|
||||||
</a-card>
|
|
||||||
</PageContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
|
||||||
@@ -21,10 +21,6 @@ import { parseDateToStr } from '@/utils/date-utils';
|
|||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
import { useClipboard } from '@vueuse/core';
|
|
||||||
import { hasPermissions } from '@/plugins/auth-user';
|
|
||||||
import dayjs, { type Dayjs } from 'dayjs';
|
|
||||||
const { copy } = useClipboard({ legacy: true });
|
|
||||||
const { getDict } = useDictStore();
|
const { getDict } = useDictStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const ws = new WS();
|
const ws = new WS();
|
||||||
@@ -42,25 +38,7 @@ let dict: {
|
|||||||
let neOtions = ref<Record<string, any>[]>([]);
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
/**开始结束时间 */
|
/**开始结束时间 */
|
||||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>([
|
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||||
dayjs().startOf('hour'),
|
|
||||||
dayjs().endOf('hour'),
|
|
||||||
]);
|
|
||||||
/**时间范围 */
|
|
||||||
let rangePickerPresets = ref([
|
|
||||||
{
|
|
||||||
label: 'Now hour',
|
|
||||||
value: [dayjs().startOf('hour'), dayjs().endOf('hour')],
|
|
||||||
},
|
|
||||||
{ label: 'Today', value: [dayjs().startOf('day'), dayjs().endOf('day')] },
|
|
||||||
{
|
|
||||||
label: 'Yesterday',
|
|
||||||
value: [
|
|
||||||
dayjs().subtract(1, 'day').startOf('day'),
|
|
||||||
dayjs().subtract(1, 'day').endOf('day'),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
/**查询参数 */
|
||||||
let queryParams = reactive({
|
let queryParams = reactive({
|
||||||
@@ -73,9 +51,9 @@ let queryParams = reactive({
|
|||||||
sortField: 'timestamp',
|
sortField: 'timestamp',
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
/**开始时间 */
|
/**开始时间 */
|
||||||
startTime: undefined as undefined | number,
|
startTime: '',
|
||||||
/**结束时间 */
|
/**结束时间 */
|
||||||
endTime: undefined as undefined | number,
|
endTime: '',
|
||||||
/**当前页数 */
|
/**当前页数 */
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
/**每页条数 */
|
/**每页条数 */
|
||||||
@@ -89,12 +67,12 @@ function fnQueryReset() {
|
|||||||
recordType: '',
|
recordType: '',
|
||||||
callerParty: '',
|
callerParty: '',
|
||||||
calledParty: '',
|
calledParty: '',
|
||||||
startTime: undefined,
|
startTime: '',
|
||||||
endTime: undefined,
|
endTime: '',
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
});
|
});
|
||||||
queryRangePicker.value = [dayjs().startOf('hour'), dayjs().endOf('hour')];
|
queryRangePicker.value = ['', ''];
|
||||||
tablePagination.current = 1;
|
tablePagination.current = 1;
|
||||||
tablePagination.pageSize = 20;
|
tablePagination.pageSize = 20;
|
||||||
fnGetList();
|
fnGetList();
|
||||||
@@ -166,7 +144,7 @@ let tableColumns: ColumnsType = [
|
|||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
key: 'callerParty',
|
key: 'callerParty',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 150,
|
width: 120,
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
const cdrJSON = opt.value;
|
const cdrJSON = opt.value;
|
||||||
return cdrJSON.callerParty;
|
return cdrJSON.callerParty;
|
||||||
@@ -177,7 +155,7 @@ let tableColumns: ColumnsType = [
|
|||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
key: 'calledParty',
|
key: 'calledParty',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 150,
|
width: 120,
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
const cdrJSON = opt.value;
|
const cdrJSON = opt.value;
|
||||||
return cdrJSON.calledParty;
|
return cdrJSON.calledParty;
|
||||||
@@ -195,7 +173,7 @@ let tableColumns: ColumnsType = [
|
|||||||
title: t('views.dashboard.cdr.time'),
|
title: t('views.dashboard.cdr.time'),
|
||||||
dataIndex: 'cdrJSON',
|
dataIndex: 'cdrJSON',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 200,
|
width: 150,
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
const cdrJSON = opt.value;
|
const cdrJSON = opt.value;
|
||||||
if (typeof cdrJSON.updateTime === 'number') {
|
if (typeof cdrJSON.updateTime === 'number') {
|
||||||
@@ -304,18 +282,6 @@ function fnRecordDelete(id: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制CDR
|
|
||||||
* @param jsonStr JSON字符串
|
|
||||||
*/
|
|
||||||
function fnRecordCopy(jsonStr: string) {
|
|
||||||
if (!jsonStr) return;
|
|
||||||
const text = JSON.stringify(jsonStr, null, 2);
|
|
||||||
copy(text).then(() => {
|
|
||||||
message.success(t('common.copyOk'), 3);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**查询列表, pageNum初始页数 */
|
/**查询列表, pageNum初始页数 */
|
||||||
function fnGetList(pageNum?: number) {
|
function fnGetList(pageNum?: number) {
|
||||||
if (tableState.loading) return;
|
if (tableState.loading) return;
|
||||||
@@ -323,19 +289,11 @@ function fnGetList(pageNum?: number) {
|
|||||||
if (pageNum) {
|
if (pageNum) {
|
||||||
queryParams.pageNum = pageNum;
|
queryParams.pageNum = pageNum;
|
||||||
}
|
}
|
||||||
|
if (!queryRangePicker.value) {
|
||||||
// 时间范围
|
queryRangePicker.value = ['', ''];
|
||||||
if (
|
|
||||||
Array.isArray(queryRangePicker.value) &&
|
|
||||||
queryRangePicker.value.length > 0
|
|
||||||
) {
|
|
||||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
|
||||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
|
||||||
} else {
|
|
||||||
queryParams.startTime = undefined;
|
|
||||||
queryParams.endTime = undefined;
|
|
||||||
}
|
}
|
||||||
|
queryParams.startTime = queryRangePicker.value[0];
|
||||||
|
queryParams.endTime = queryRangePicker.value[1];
|
||||||
listSMSCDataCDR(toRaw(queryParams)).then(res => {
|
listSMSCDataCDR(toRaw(queryParams)).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
// 取消勾选
|
// 取消勾选
|
||||||
@@ -424,9 +382,7 @@ function fnRealTime() {
|
|||||||
subGroupID: `1007_${queryParams.neId}`,
|
subGroupID: `1007_${queryParams.neId}`,
|
||||||
},
|
},
|
||||||
onmessage: wsMessage,
|
onmessage: wsMessage,
|
||||||
onerror: (ev: any) => {
|
onerror: wsError,
|
||||||
console.error(ev);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
ws.connect(options);
|
ws.connect(options);
|
||||||
} else {
|
} else {
|
||||||
@@ -436,6 +392,12 @@ function fnRealTime() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**接收数据后回调 */
|
||||||
|
function wsError(ev: any) {
|
||||||
|
// 接收数据后回调
|
||||||
|
console.error(ev);
|
||||||
|
}
|
||||||
|
|
||||||
/**接收数据后回调 */
|
/**接收数据后回调 */
|
||||||
function wsMessage(res: Record<string, any>) {
|
function wsMessage(res: Record<string, any>) {
|
||||||
const { code, requestId, data } = res;
|
const { code, requestId, data } = res;
|
||||||
@@ -530,7 +492,6 @@ onBeforeUnmount(() => {
|
|||||||
v-model:value="queryParams.neId"
|
v-model:value="queryParams.neId"
|
||||||
:options="neOtions"
|
:options="neOtions"
|
||||||
:placeholder="t('common.selectPlease')"
|
:placeholder="t('common.selectPlease')"
|
||||||
@change="fnQueryReset()"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -593,12 +554,12 @@ onBeforeUnmount(() => {
|
|||||||
>
|
>
|
||||||
<a-range-picker
|
<a-range-picker
|
||||||
v-model:value="queryRangePicker"
|
v-model:value="queryRangePicker"
|
||||||
:presets="rangePickerPresets"
|
allow-clear
|
||||||
:bordered="true"
|
bordered
|
||||||
:allow-clear="false"
|
|
||||||
style="width: 100%"
|
|
||||||
:show-time="{ format: 'HH:mm:ss' }"
|
:show-time="{ format: 'HH:mm:ss' }"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
value-format="x"
|
||||||
|
style="width: 100%"
|
||||||
></a-range-picker>
|
></a-range-picker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -637,7 +598,6 @@ onBeforeUnmount(() => {
|
|||||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||||
:loading="modalState.confirmLoading"
|
:loading="modalState.confirmLoading"
|
||||||
@click.prevent="fnRecordDelete('0')"
|
@click.prevent="fnRecordDelete('0')"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon><DeleteOutlined /></template>
|
<template #icon><DeleteOutlined /></template>
|
||||||
{{ t('common.deleteText') }}
|
{{ t('common.deleteText') }}
|
||||||
@@ -705,7 +665,7 @@ onBeforeUnmount(() => {
|
|||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: tableColumns.length * 180, y: 'calc(100vh - 480px)' }"
|
:scroll="{ x: tableColumns.length * 150, y: 'calc(100vh - 480px)' }"
|
||||||
:row-selection="{
|
:row-selection="{
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
columnWidth: '48px',
|
columnWidth: '48px',
|
||||||
@@ -729,23 +689,11 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'id'">
|
<template v-if="column.key === 'id'">
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.copyText') }}</template>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
@click.prevent="fnRecordCopy(record.cdrJSON)"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<CopyOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.deleteText') }}</template>
|
<template #title>{{ t('common.deleteText') }}</template>
|
||||||
<a-button
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
@click.prevent="fnRecordDelete(record.id)"
|
@click.prevent="fnRecordDelete(record.id)"
|
||||||
v-perms:has="['cdr:ne:remove']"
|
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<DeleteOutlined />
|
<DeleteOutlined />
|
||||||
@@ -756,79 +704,58 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template #expandedRowRender="{ record }">
|
<template #expandedRowRender="{ record }">
|
||||||
<a-row :gutter="16">
|
<div style="width: 46%; padding-left: 32px; padding-bottom: 16px">
|
||||||
<a-col :lg="8" :md="12" :xs="22" :offset="2">
|
<a-divider orientation="left">
|
||||||
<a-divider orientation="left">
|
{{ t('views.dashboard.cdr.cdrInfo') }}
|
||||||
{{ t('views.dashboard.cdr.cdrInfo') }}
|
</a-divider>
|
||||||
</a-divider>
|
<div>
|
||||||
<div>
|
<span>{{ t('views.ne.common.neName') }}: </span>
|
||||||
<span>{{ t('views.ne.common.neName') }}: </span>
|
<span>{{ record.neName }}</span>
|
||||||
<span>{{ record.neName }}</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
||||||
<span>{{ t('views.ne.common.rmUid') }}: </span>
|
<span>{{ record.rmUID }}</span>
|
||||||
<span>{{ record.rmUID }}</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<span>{{ t('views.dashboard.cdr.time') }}: </span>
|
||||||
<span>{{ t('views.dashboard.cdr.time') }}: </span>
|
<span>
|
||||||
<span>
|
{{
|
||||||
{{
|
typeof record.cdrJSON.updateTime === 'number'
|
||||||
typeof record.cdrJSON.updateTime === 'number'
|
? parseDateToStr(+record.cdrJSON.updateTime * 1000)
|
||||||
? parseDateToStr(+record.cdrJSON.updateTime * 1000)
|
: record.cdrJSON.updateTime
|
||||||
: record.cdrJSON.updateTime
|
}}
|
||||||
}}
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
<a-divider orientation="left">
|
||||||
</a-col>
|
{{ t('views.dashboard.cdr.rowInfo') }}
|
||||||
<a-col :lg="8" :md="12" :xs="24">
|
</a-divider>
|
||||||
<a-divider orientation="left">
|
<div>
|
||||||
{{ t('views.dashboard.cdr.rowInfo') }}
|
<span>{{ t('views.dashboard.cdr.type') }}: </span>
|
||||||
</a-divider>
|
<span>{{ record.cdrJSON.serviceType }}</span>
|
||||||
<div>
|
</div>
|
||||||
<span>{{ t('views.dashboard.cdr.type') }}: </span>
|
<div>
|
||||||
<span>{{ record.cdrJSON.serviceType }}</span>
|
<span>{{ t('views.dashboard.cdr.caller') }}: </span>
|
||||||
</div>
|
<span>{{ record.cdrJSON.callerParty }}</span>
|
||||||
<div>
|
</div>
|
||||||
<span>{{ t('views.dashboard.cdr.caller') }}: </span>
|
<div>
|
||||||
<span>{{ record.cdrJSON.callerParty }}</span>
|
<span>{{ t('views.dashboard.cdr.called') }}: </span>
|
||||||
</div>
|
<span>{{ record.cdrJSON.calledParty }}</span>
|
||||||
<div>
|
</div>
|
||||||
<span>{{ t('views.dashboard.cdr.called') }}: </span>
|
<div>
|
||||||
<span>{{ record.cdrJSON.calledParty }}</span>
|
<span>{{ t('views.dashboard.cdr.result') }}: </span>
|
||||||
</div>
|
<span v-if="record.cdrJSON.result === 0">
|
||||||
<div>
|
{{ t('views.dashboard.cdr.resultFail') }},
|
||||||
<span>{{ t('views.dashboard.cdr.result') }}: </span>
|
<DictTag
|
||||||
<span v-if="record.cdrJSON.result === 0">
|
:options="dict.cdrCauseCode"
|
||||||
{{ t('views.dashboard.cdr.resultFail') }},
|
:value="record.cdrJSON.cause"
|
||||||
<DictTag
|
value-default="0"
|
||||||
:options="dict.cdrCauseCode"
|
/>
|
||||||
:value="record.cdrJSON.cause"
|
</span>
|
||||||
value-default="0"
|
<span v-else>
|
||||||
/>
|
{{ t('views.dashboard.cdr.resultOk') }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
</div>
|
||||||
{{ t('views.dashboard.cdr.resultOk') }}
|
</div>
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
<a-col
|
|
||||||
:lg="16"
|
|
||||||
:md="16"
|
|
||||||
:xs="22"
|
|
||||||
:offset="2"
|
|
||||||
v-if="
|
|
||||||
record.cdrJSON?.smsContent &&
|
|
||||||
hasPermissions(['cdr:smsc:content'])
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-divider orientation="left"> Content </a-divider>
|
|
||||||
<a-typography-paragraph
|
|
||||||
copyable
|
|
||||||
:content="record.cdrJSON.smsContent"
|
|
||||||
>
|
|
||||||
</a-typography-paragraph>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|||||||
@@ -145,54 +145,66 @@ let alarmTableState: TabeStateType = reactive({
|
|||||||
let tableColumns: ColumnsType = [
|
let tableColumns: ColumnsType = [
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.origLevel'),
|
title: t('views.faultManage.activeAlarm.origLevel'),
|
||||||
align: 'left',
|
align: 'center',
|
||||||
key: 'origSeverity',
|
key: 'origSeverity',
|
||||||
dataIndex: 'origSeverity',
|
dataIndex: 'origSeverity',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmTitle'),
|
title: t('views.faultManage.activeAlarm.alarmTitle'),
|
||||||
dataIndex: 'alarmTitle',
|
dataIndex: 'alarmTitle',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 200,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neType'),
|
title: t('views.faultManage.activeAlarm.neType'),
|
||||||
dataIndex: 'neType',
|
dataIndex: 'neType',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.eventTime'),
|
title: t('views.faultManage.activeAlarm.eventTime'),
|
||||||
dataIndex: 'eventTime',
|
dataIndex: 'eventTime',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
sorter: (a: any, b: any) => 1,
|
sorter: (a: any, b: any) => 1,
|
||||||
width: 150,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmCode'),
|
title: t('views.faultManage.activeAlarm.alarmCode'),
|
||||||
dataIndex: 'alarmCode',
|
dataIndex: 'alarmCode',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmType'),
|
title: t('views.faultManage.activeAlarm.alarmType'),
|
||||||
dataIndex: 'alarmType',
|
dataIndex: 'alarmType',
|
||||||
key: 'alarmType',
|
key: 'alarmType',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 120,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neName'),
|
title: t('views.faultManage.activeAlarm.neName'),
|
||||||
dataIndex: 'neName',
|
dataIndex: 'neName',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neId'),
|
title: t('views.faultManage.activeAlarm.neId'),
|
||||||
dataIndex: 'neId',
|
dataIndex: 'neId',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.pvFlag'),
|
||||||
|
dataIndex: 'pvFlag',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.alarmId'),
|
||||||
|
dataIndex: 'alarmId',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -200,20 +212,20 @@ let tableColumns: ColumnsType = [
|
|||||||
dataIndex: 'ackState',
|
dataIndex: 'ackState',
|
||||||
key: 'ackState',
|
key: 'ackState',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.ackUser'),
|
title: t('views.faultManage.activeAlarm.ackUser'),
|
||||||
dataIndex: 'ackUser',
|
dataIndex: 'ackUser',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('common.operate'),
|
title: t('common.operate'),
|
||||||
key: 'alarm_id',
|
key: 'alarm_id',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -1010,12 +1022,12 @@ onMounted(() => {
|
|||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:row-selection="{
|
:row-selection="{
|
||||||
columnWidth: 48,
|
columnWidth: 2,
|
||||||
selectedRowKeys: state.selectedRowKeys,
|
selectedRowKeys: state.selectedRowKeys,
|
||||||
onChange: onSelectChange,
|
onChange: onSelectChange,
|
||||||
}"
|
}"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: tableColumns.length * 150, y: 400 }"
|
:scroll="{ x: 2500, y: 400 }"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'origSeverity'">
|
<template v-if="column.key === 'origSeverity'">
|
||||||
@@ -1200,7 +1212,15 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
{{ modalState.from.alarmType }}
|
{{ modalState.from.alarmType }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.faultManage.activeAlarm.pvFlag')"
|
||||||
|
name="pvFlag"
|
||||||
|
>
|
||||||
|
{{ modalState.from.pvFlag }}
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
@@ -1210,8 +1230,18 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
{{ modalState.from.locationInfo }}
|
{{ modalState.from.locationInfo }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-row> </a-row>
|
||||||
|
|
||||||
<a-row>
|
<a-row>
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.faultManage.activeAlarm.province')"
|
||||||
|
name="province"
|
||||||
|
>
|
||||||
|
{{ modalState.from.province }}
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.faultManage.activeAlarm.origLevel')"
|
:label="t('views.faultManage.activeAlarm.origLevel')"
|
||||||
@@ -1260,7 +1290,7 @@ onMounted(() => {
|
|||||||
:label="t('views.faultManage.activeAlarm.ackState')"
|
:label="t('views.faultManage.activeAlarm.ackState')"
|
||||||
name="ackState"
|
name="ackState"
|
||||||
>
|
>
|
||||||
<DictTag :options="dict.activeAckState" :value="modalState.from.ackState" />
|
{{ modalState.from.ackState }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|||||||
@@ -118,47 +118,61 @@ let tableState: TabeStateType = reactive({
|
|||||||
|
|
||||||
/**表格字段列 */
|
/**表格字段列 */
|
||||||
let tableColumns: ColumnsType = [
|
let tableColumns: ColumnsType = [
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.alarmId'),
|
||||||
|
dataIndex: 'alarmId',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neId'),
|
title: t('views.faultManage.activeAlarm.neId'),
|
||||||
dataIndex: 'neId',
|
dataIndex: 'neId',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 150,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neName'),
|
title: t('views.faultManage.activeAlarm.neName'),
|
||||||
dataIndex: 'neName',
|
dataIndex: 'neName',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 150,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neType'),
|
title: t('views.faultManage.activeAlarm.neType'),
|
||||||
dataIndex: 'neType',
|
dataIndex: 'neType',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 150,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmCode'),
|
title: t('views.faultManage.activeAlarm.alarmCode'),
|
||||||
dataIndex: 'alarmCode',
|
dataIndex: 'alarmCode',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmTitle'),
|
title: t('views.faultManage.activeAlarm.alarmTitle'),
|
||||||
dataIndex: 'alarmTitle',
|
dataIndex: 'alarmTitle',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 200,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.eventTime'),
|
title: t('views.faultManage.activeAlarm.eventTime'),
|
||||||
dataIndex: 'eventTime',
|
dataIndex: 'eventTime',
|
||||||
|
align: 'center',
|
||||||
sorter: (a: any, b: any) => 1,
|
sorter: (a: any, b: any) => 1,
|
||||||
align: 'left',
|
width: 5,
|
||||||
width: 200,
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.pvFlag'),
|
||||||
|
dataIndex: 'pvFlag',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('common.operate'),
|
title: t('common.operate'),
|
||||||
key: 'alarm_id',
|
key: 'alarm_id',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 5,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -302,7 +316,7 @@ function mapKeysWithReduce(data: any, titleMapping: any) {
|
|||||||
const title = titleMapping[key] || key;
|
const title = titleMapping[key] || key;
|
||||||
newItem[title] = item[key];
|
newItem[title] = item[key];
|
||||||
return newItem;
|
return newItem;
|
||||||
}, {});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,7 +626,7 @@ onMounted(() => {
|
|||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<TableColumnsDnd
|
<TableColumnsDnd
|
||||||
cache-id="alarmEvent"
|
cache-id="alarmActive"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
v-model:columns-dnd="tableColumnsDnd"
|
v-model:columns-dnd="tableColumnsDnd"
|
||||||
></TableColumnsDnd>
|
></TableColumnsDnd>
|
||||||
|
|||||||
@@ -122,96 +122,108 @@ let tableState: TabeStateType = reactive({
|
|||||||
|
|
||||||
/**表格字段列 */
|
/**表格字段列 */
|
||||||
let tableColumns: ColumnsType = [
|
let tableColumns: ColumnsType = [
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.alarmId'),
|
||||||
|
dataIndex: 'alarmId',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neId'),
|
title: t('views.faultManage.activeAlarm.neId'),
|
||||||
dataIndex: 'neId',
|
dataIndex: 'neId',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neName'),
|
title: t('views.faultManage.activeAlarm.neName'),
|
||||||
dataIndex: 'neName',
|
dataIndex: 'neName',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.neType'),
|
title: t('views.faultManage.activeAlarm.neType'),
|
||||||
dataIndex: 'neType',
|
dataIndex: 'neType',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.origLevel'),
|
title: t('views.faultManage.activeAlarm.origLevel'),
|
||||||
align: 'left',
|
align: 'left',
|
||||||
dataIndex: 'origSeverity',
|
dataIndex: 'origSeverity',
|
||||||
key: 'origSeverity',
|
key: 'origSeverity',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmCode'),
|
title: t('views.faultManage.activeAlarm.alarmCode'),
|
||||||
dataIndex: 'alarmCode',
|
dataIndex: 'alarmCode',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmTitle'),
|
title: t('views.faultManage.activeAlarm.alarmTitle'),
|
||||||
dataIndex: 'alarmTitle',
|
dataIndex: 'alarmTitle',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 200,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.eventTime'),
|
title: t('views.faultManage.activeAlarm.eventTime'),
|
||||||
dataIndex: 'eventTime',
|
dataIndex: 'eventTime',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
sorter: (a: any, b: any) => 1,
|
sorter: (a: any, b: any) => 1,
|
||||||
width: 150,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.alarmType'),
|
title: t('views.faultManage.activeAlarm.alarmType'),
|
||||||
dataIndex: 'alarmType',
|
dataIndex: 'alarmType',
|
||||||
key: 'alarmType',
|
key: 'alarmType',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 120,
|
width: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('views.faultManage.activeAlarm.pvFlag'),
|
||||||
|
dataIndex: 'pvFlag',
|
||||||
|
align: 'center',
|
||||||
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.clearUser'),
|
title: t('views.faultManage.activeAlarm.clearUser'),
|
||||||
dataIndex: 'clearUser',
|
dataIndex: 'clearUser',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.clearType'),
|
title: t('views.faultManage.activeAlarm.clearType'),
|
||||||
dataIndex: 'clearType',
|
dataIndex: 'clearType',
|
||||||
key: 'clearType',
|
key: 'clearType',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 120,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.clearTime'),
|
title: t('views.faultManage.activeAlarm.clearTime'),
|
||||||
dataIndex: 'clearTime',
|
dataIndex: 'clearTime',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sorter: (a: any, b: any) => 1,
|
sorter: (a: any, b: any) => 1,
|
||||||
width: 150,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.ackState'),
|
title: t('views.faultManage.activeAlarm.ackState'),
|
||||||
dataIndex: 'ackState',
|
dataIndex: 'ackState',
|
||||||
key: 'ackState',
|
key: 'ackState',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.faultManage.activeAlarm.ackUser'),
|
title: t('views.faultManage.activeAlarm.ackUser'),
|
||||||
dataIndex: 'ackUser',
|
dataIndex: 'ackUser',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 100,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('common.operate'),
|
title: t('common.operate'),
|
||||||
key: 'alarm_id',
|
key: 'alarm_id',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 120,
|
width: 5,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -636,7 +648,7 @@ onMounted(() => {
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row :gutter="16">
|
<a-row>
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.faultManage.activeAlarm.alarmCode')"
|
:label="t('views.faultManage.activeAlarm.alarmCode')"
|
||||||
@@ -676,7 +688,22 @@ onMounted(() => {
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row :gutter="16">
|
<a-row>
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.faultManage.activeAlarm.pvFlag')"
|
||||||
|
name="pv_flag"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model:value="queryParams.pv_flag"
|
||||||
|
:placeholder="t('common.selectPlease')"
|
||||||
|
:options="[
|
||||||
|
{ label: 'PNF', value: 'PNF' },
|
||||||
|
{ label: 'VNF', value: 'VNF' },
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.faultManage.activeAlarm.alarmType')"
|
:label="t('views.faultManage.activeAlarm.alarmType')"
|
||||||
@@ -777,12 +804,12 @@ onMounted(() => {
|
|||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:row-selection="{
|
:row-selection="{
|
||||||
columnWidth: 48,
|
columnWidth: 3,
|
||||||
selectedRowKeys: state.selectedRowKeys,
|
selectedRowKeys: state.selectedRowKeys,
|
||||||
onChange: onSelectChange,
|
onChange: onSelectChange,
|
||||||
}"
|
}"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: tableColumns.length * 150, y: 400 }"
|
:scroll="{ x: tableColumns.length * 120, y: 400 }"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'origSeverity'">
|
<template v-if="column.key === 'origSeverity'">
|
||||||
@@ -836,7 +863,6 @@ onMounted(() => {
|
|||||||
@ok="fnModalOk"
|
@ok="fnModalOk"
|
||||||
:ok-text="t('views.faultManage.activeAlarm.confirm')"
|
:ok-text="t('views.faultManage.activeAlarm.confirm')"
|
||||||
@cancel="fnModalCancel"
|
@cancel="fnModalCancel"
|
||||||
:footer="null"
|
|
||||||
>
|
>
|
||||||
<a-form
|
<a-form
|
||||||
name="modalStateFrom"
|
name="modalStateFrom"
|
||||||
@@ -920,6 +946,15 @@ onMounted(() => {
|
|||||||
</a-row>
|
</a-row>
|
||||||
|
|
||||||
<a-row>
|
<a-row>
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.faultManage.activeAlarm.pvFlag')"
|
||||||
|
name="pvFlag"
|
||||||
|
>
|
||||||
|
{{ modalState.from.pvFlag }}
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.faultManage.activeAlarm.alarmType')"
|
:label="t('views.faultManage.activeAlarm.alarmType')"
|
||||||
@@ -938,6 +973,14 @@ onMounted(() => {
|
|||||||
{{ modalState.from.locationInfo }}
|
{{ modalState.from.locationInfo }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-row>
|
<a-row>
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.faultManage.activeAlarm.province')"
|
||||||
|
name="province"
|
||||||
|
>
|
||||||
|
{{ modalState.from.province }}
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.faultManage.activeAlarm.origLevel')"
|
:label="t('views.faultManage.activeAlarm.origLevel')"
|
||||||
@@ -976,10 +1019,7 @@ onMounted(() => {
|
|||||||
:label="t('views.faultManage.activeAlarm.clearType')"
|
:label="t('views.faultManage.activeAlarm.clearType')"
|
||||||
name="clearType"
|
name="clearType"
|
||||||
>
|
>
|
||||||
<DictTag
|
{{ modalState.from.clearType }}
|
||||||
:options="dict.activeClearType"
|
|
||||||
:value="modalState.from.clearType"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
@@ -1006,10 +1046,7 @@ onMounted(() => {
|
|||||||
:label="t('views.faultManage.activeAlarm.ackState')"
|
:label="t('views.faultManage.activeAlarm.ackState')"
|
||||||
name="ackState"
|
name="ackState"
|
||||||
>
|
>
|
||||||
<DictTag
|
{{ modalState.from.ackState }}
|
||||||
:options="dict.activeAckState"
|
|
||||||
:value="modalState.from.ackState"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ onMounted(() => {
|
|||||||
getConfigKey('sys.homePage').then(res => {
|
getConfigKey('sys.homePage').then(res => {
|
||||||
spinning.value = false;
|
spinning.value = false;
|
||||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||||
|
console.log(spinning);
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
const asyncComponent = findView(`${res.data}`);
|
const asyncComponent = findView(`${res.data}`);
|
||||||
currentComponent.value = defineAsyncComponent(asyncComponent);
|
currentComponent.value = defineAsyncComponent(asyncComponent);
|
||||||
|
|||||||
@@ -1,24 +1,19 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { ProModal } from 'antdv-pro-modal';
|
|
||||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
import { ColumnsType } from 'ant-design-vue/es/table';
|
||||||
import { Form, Modal, message } from 'ant-design-vue/es';
|
import { Modal, message } from 'ant-design-vue/es';
|
||||||
import { parseDateToStr } from '@/utils/date-utils';
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import {
|
import {
|
||||||
getBakFile,
|
getBakFile,
|
||||||
getBakFileList,
|
getBakFileList,
|
||||||
downFile,
|
downFile,
|
||||||
delFile,
|
delFile,
|
||||||
updateFTPInfo,
|
|
||||||
getFTPInfo,
|
|
||||||
putFTPInfo,
|
|
||||||
} from '@/api/logManage/exportFile';
|
} from '@/api/logManage/exportFile';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import saveAs from 'file-saver';
|
import saveAs from 'file-saver';
|
||||||
import { regExpIPv4 } from '@/utils/regular-utils';
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
/**网元参数 */
|
/**网元参数 */
|
||||||
@@ -274,131 +269,6 @@ onMounted(() => {
|
|||||||
// fnGetList();
|
// fnGetList();
|
||||||
// });
|
// });
|
||||||
});
|
});
|
||||||
|
|
||||||
/**对象信息状态类型 */
|
|
||||||
type ModalStateType = {
|
|
||||||
/**新增框或修改框是否显示 */
|
|
||||||
openByEdit: boolean;
|
|
||||||
/**标题 */
|
|
||||||
title: string;
|
|
||||||
/**表单数据 */
|
|
||||||
from: Record<string, any>;
|
|
||||||
/**确定按钮 loading */
|
|
||||||
confirmLoading: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**FTP日志对象信息状态 */
|
|
||||||
let modalState: ModalStateType = reactive({
|
|
||||||
openByEdit: false,
|
|
||||||
title: '设置远程备份配置',
|
|
||||||
from: {
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
toIp: '',
|
|
||||||
toPort: 22,
|
|
||||||
enable: false,
|
|
||||||
dir: '',
|
|
||||||
},
|
|
||||||
confirmLoading: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**FTP日志对象信息内表单属性和校验规则 */
|
|
||||||
const modalStateFrom = Form.useForm(
|
|
||||||
modalState.from,
|
|
||||||
reactive({
|
|
||||||
toIp: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
pattern: regExpIPv4,
|
|
||||||
message: 'Please enter the service login IP',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
username: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
trigger: 'blur',
|
|
||||||
message: 'Please enter the service login user name',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
dir: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
trigger: 'blur',
|
|
||||||
message: 'Please enter the service address target file directory',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对话框弹出显示为 新增或者修改
|
|
||||||
* @param configId 参数编号id, 不传为新增
|
|
||||||
*/
|
|
||||||
function fnModalVisibleByEdit() {
|
|
||||||
if (modalState.confirmLoading) return;
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
modalState.confirmLoading = true;
|
|
||||||
getFTPInfo().then(res => {
|
|
||||||
modalState.confirmLoading = false;
|
|
||||||
hide();
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
|
||||||
modalState.from = Object.assign(modalState.from, res.data);
|
|
||||||
modalState.title = 'Setting Remote Backup';
|
|
||||||
modalState.openByEdit = true;
|
|
||||||
} else {
|
|
||||||
message.error(res.msg, 3);
|
|
||||||
modalState.title = 'Setting Remote Backup';
|
|
||||||
modalState.openByEdit = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**FTP对象保存 */
|
|
||||||
function fnModalOk() {
|
|
||||||
modalStateFrom.validate().then(() => {
|
|
||||||
modalState.confirmLoading = true;
|
|
||||||
const from = toRaw(modalState.from);
|
|
||||||
updateFTPInfo(from)
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success(`Configuration saved successfully`, 3);
|
|
||||||
fnModalCancel();
|
|
||||||
} else {
|
|
||||||
message.warning(`Configuration save exception`, 3);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
modalState.confirmLoading = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对话框弹出关闭执行函数
|
|
||||||
* 进行表达规则校验
|
|
||||||
*/
|
|
||||||
function fnModalCancel() {
|
|
||||||
modalState.openByEdit = false;
|
|
||||||
modalStateFrom.resetFields();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步文件到FTP
|
|
||||||
* @param row
|
|
||||||
*/
|
|
||||||
function fnSyncFileToFTP(row: Record<string, any>) {
|
|
||||||
putFTPInfo(row.filePath, row.fileName)
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success(t('common.operateOk'), 3);
|
|
||||||
} else {
|
|
||||||
message.warning(res.msg, 3);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
modalState.confirmLoading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -435,12 +305,6 @@ function fnSyncFileToFTP(row: Record<string, any>) {
|
|||||||
<!-- 插槽-卡片右侧 -->
|
<!-- 插槽-卡片右侧 -->
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-tooltip>
|
|
||||||
<template #title>Setting Remote Backup</template>
|
|
||||||
<a-button type="text" @click.prevent="fnModalVisibleByEdit()">
|
|
||||||
<template #icon><DeliveredProcedureOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
<template #title>{{ t('common.reloadText') }}</template>
|
||||||
<a-button type="text" @click.prevent="fnGetList()">
|
<a-button type="text" @click.prevent="fnGetList()">
|
||||||
@@ -464,14 +328,6 @@ function fnSyncFileToFTP(row: Record<string, any>) {
|
|||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'fileName'">
|
<template v-if="column.key === 'fileName'">
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
:loading="downLoading"
|
|
||||||
@click.prevent="fnSyncFileToFTP(record)"
|
|
||||||
v-if="record.fileType === 'file'"
|
|
||||||
>
|
|
||||||
<template #icon><CloudServerOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
<a-button
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
:loading="downLoading"
|
:loading="downLoading"
|
||||||
@@ -493,106 +349,6 @@ function fnSyncFileToFTP(row: Record<string, any>) {
|
|||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
<!-- 新增框或修改框 -->
|
|
||||||
<ProModal
|
|
||||||
:drag="true"
|
|
||||||
:width="800"
|
|
||||||
:destroyOnClose="true"
|
|
||||||
: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 }"
|
|
||||||
:label-wrap="true"
|
|
||||||
>
|
|
||||||
<a-form-item label="Enable" name="enable" :label-col="{ span: 3 }">
|
|
||||||
<a-switch
|
|
||||||
v-model:checked="modalState.from.enable"
|
|
||||||
:checked-children="t('common.switch.open')"
|
|
||||||
:un-checked-children="t('common.switch.shut')"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<template v-if="modalState.from.enable">
|
|
||||||
<a-row>
|
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
label="Service IP"
|
|
||||||
name="toIp"
|
|
||||||
v-bind="modalStateFrom.validateInfos.toIp"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="modalState.from.toIp"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
label="Service Port"
|
|
||||||
name="toPort"
|
|
||||||
v-bind="modalStateFrom.validateInfos.toPort"
|
|
||||||
>
|
|
||||||
<a-input-number
|
|
||||||
v-model:value="modalState.from.toPort"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
></a-input-number>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
<a-row>
|
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
label="UserName"
|
|
||||||
name="username"
|
|
||||||
v-bind="modalStateFrom.validateInfos.username"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="modalState.from.username"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
label="Password"
|
|
||||||
name="password"
|
|
||||||
v-bind="modalStateFrom.validateInfos.password"
|
|
||||||
>
|
|
||||||
<a-input-password
|
|
||||||
v-model:value="modalState.from.password"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
></a-input-password>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
<a-form-item
|
|
||||||
label="Save Dir"
|
|
||||||
name="dir"
|
|
||||||
v-bind="modalStateFrom.validateInfos.dir"
|
|
||||||
:label-col="{ span: 3 }"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="modalState.from.dir"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</template>
|
|
||||||
</a-form>
|
|
||||||
</ProModal>
|
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ async function fnGetState() {
|
|||||||
graphG6.value.setItemState(neShape, 'neState', ne.serverState.online);
|
graphG6.value.setItemState(neShape, 'neState', ne.serverState.online);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await new Promise(resolve => setTimeout(resolve, 15_000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**查询全部网元数据列表 */
|
/**查询全部网元数据列表 */
|
||||||
|
|||||||
@@ -92,13 +92,13 @@ const graphNodeMenu = new Menu({
|
|||||||
${neState.neName ?? '--'}
|
${neState.neName ?? '--'}
|
||||||
</h3>
|
</h3>
|
||||||
<div id="restart" style="cursor: pointer; margin-bottom: 4px">
|
<div id="restart" style="cursor: pointer; margin-bottom: 4px">
|
||||||
> ${t('views.ne.common.restart')}
|
> ${t('views.configManage.neManage.restart')}
|
||||||
</div>
|
</div>
|
||||||
<div id="stop" style="cursor: pointer; margin-bottom: 4px;">
|
<div id="stop" style="cursor: pointer; margin-bottom: 4px;">
|
||||||
> ${t('views.ne.common.stop')}
|
> ${t('views.configManage.neManage.stop')}
|
||||||
</div>
|
</div>
|
||||||
<div id="log" style="cursor: pointer; margin-bottom: 4px;">
|
<div id="log" style="cursor: pointer; margin-bottom: 4px;">
|
||||||
> ${t('views.ne.common.log')}
|
> ${t('views.configManage.neManage.log')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -130,17 +130,26 @@ export function edgeLineAnimateState() {
|
|||||||
|
|
||||||
// circle-move 圆点沿边运动
|
// circle-move 圆点沿边运动
|
||||||
if (name === 'circle-move') {
|
if (name === 'circle-move') {
|
||||||
const backArr = group.findAll((ele: any) =>
|
let back1 = group.find(
|
||||||
ele.get('name').startsWith('circle-stroke')
|
(ele: any) => ele.get('name') === 'circle-stroke1'
|
||||||
);
|
);
|
||||||
|
if (back1) {
|
||||||
|
back1.remove();
|
||||||
|
back1.destroy();
|
||||||
|
}
|
||||||
|
let back2 = group.find(
|
||||||
|
(ele: any) => ele.get('name') === 'circle-stroke2'
|
||||||
|
);
|
||||||
|
if (back2) {
|
||||||
|
back2.remove();
|
||||||
|
back2.destroy();
|
||||||
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
if (backArr.length > 0) return;
|
|
||||||
|
|
||||||
// 第一个矩形边
|
// 第一个矩形边
|
||||||
const fillColor = typeof value === 'string' ? value : '#1890ff';
|
const fillColor = typeof value === 'string' ? value : '#1890ff';
|
||||||
// 边缘路径的起始位置
|
// 边缘路径的起始位置
|
||||||
const startPoint = keyShape.getPoint(0);
|
const startPoint = keyShape.getPoint(0);
|
||||||
const back1 = group.addShape('circle', {
|
back1 = group.addShape('circle', {
|
||||||
attrs: {
|
attrs: {
|
||||||
x: startPoint.x,
|
x: startPoint.x,
|
||||||
y: startPoint.y,
|
y: startPoint.y,
|
||||||
@@ -150,7 +159,6 @@ export function edgeLineAnimateState() {
|
|||||||
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
|
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
|
||||||
name: 'circle-stroke1',
|
name: 'circle-stroke1',
|
||||||
});
|
});
|
||||||
back1.show();
|
|
||||||
back1.animate(
|
back1.animate(
|
||||||
(ratio: any) => {
|
(ratio: any) => {
|
||||||
// 每帧中的操作。比率范围从 0 到 1,表示动画的进度。返回修改后的配置
|
// 每帧中的操作。比率范围从 0 到 1,表示动画的进度。返回修改后的配置
|
||||||
@@ -169,7 +177,7 @@ export function edgeLineAnimateState() {
|
|||||||
);
|
);
|
||||||
// 第二个矩形边
|
// 第二个矩形边
|
||||||
const endPoint = keyShape.getPoint(1);
|
const endPoint = keyShape.getPoint(1);
|
||||||
const back2 = group.addShape('circle', {
|
back2 = group.addShape('circle', {
|
||||||
zIndex: -2,
|
zIndex: -2,
|
||||||
attrs: {
|
attrs: {
|
||||||
x: endPoint.x,
|
x: endPoint.x,
|
||||||
@@ -180,7 +188,7 @@ export function edgeLineAnimateState() {
|
|||||||
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
|
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
|
||||||
name: 'circle-stroke2',
|
name: 'circle-stroke2',
|
||||||
});
|
});
|
||||||
back2.show();
|
|
||||||
back2.animate(
|
back2.animate(
|
||||||
(ratio: any) => {
|
(ratio: any) => {
|
||||||
// 每帧中的操作。比率范围从 0 到 1,表示动画的进度。返回修改后的配置
|
// 每帧中的操作。比率范围从 0 到 1,表示动画的进度。返回修改后的配置
|
||||||
@@ -197,14 +205,6 @@ export function edgeLineAnimateState() {
|
|||||||
duration: 2 * 1000, // 执行一次的持续时间
|
duration: 2 * 1000, // 执行一次的持续时间
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
if (backArr.length <= 0) return;
|
|
||||||
backArr.forEach((ele: any) => {
|
|
||||||
ele.hide();
|
|
||||||
ele.remove();
|
|
||||||
ele.destroy();
|
|
||||||
});
|
|
||||||
backArr.length = 0;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,11 @@ export function edgeLineAnimateState() {
|
|||||||
// line-dash 虚线运动
|
// line-dash 虚线运动
|
||||||
if (name === 'line-dash') {
|
if (name === 'line-dash') {
|
||||||
if (value) {
|
if (value) {
|
||||||
if (keyShape.cfg.animating) return;
|
keyShape.stopAnimate();
|
||||||
|
keyShape.attr({
|
||||||
|
lineDash: null,
|
||||||
|
lineDashOffset: null,
|
||||||
|
});
|
||||||
let index = 0;
|
let index = 0;
|
||||||
keyShape.animate(
|
keyShape.animate(
|
||||||
() => {
|
() => {
|
||||||
@@ -230,12 +234,6 @@ export function edgeLineAnimateState() {
|
|||||||
duration: 3000, // 执行一次的持续时间
|
duration: 3000, // 执行一次的持续时间
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
keyShape.stopAnimate();
|
|
||||||
keyShape.attr({
|
|
||||||
lineDash: null,
|
|
||||||
lineDashOffset: null,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -248,7 +246,6 @@ export function edgeLineAnimateState() {
|
|||||||
back.remove();
|
back.remove();
|
||||||
back.destroy();
|
back.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
const { path, stroke, lineWidth } = keyShape.attr();
|
const { path, stroke, lineWidth } = keyShape.attr();
|
||||||
back = group.addShape('path', {
|
back = group.addShape('path', {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|||||||
@@ -300,23 +300,12 @@ export function nodeImageAnimateState() {
|
|||||||
ele.get('name').startsWith('circle-shape')
|
ele.get('name').startsWith('circle-shape')
|
||||||
);
|
);
|
||||||
if (value) {
|
if (value) {
|
||||||
const fillColor = typeof value === 'string' ? value : '#f5222d';
|
if (Array.isArray(backArr) && backArr.length === 3) return;
|
||||||
// 移除
|
|
||||||
if (Array.isArray(backArr) && backArr.length >= 3) {
|
|
||||||
for (const back of backArr) {
|
|
||||||
back.stopAnimate();
|
|
||||||
back.hide();
|
|
||||||
back.remove();
|
|
||||||
back.destroy();
|
|
||||||
}
|
|
||||||
backArr.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据大小确定半径
|
|
||||||
const size = Array.isArray(model?.size) ? model?.size : [40, 40];
|
const size = Array.isArray(model?.size) ? model?.size : [40, 40];
|
||||||
const x = size[0] / 2;
|
const x = size[0] / 2;
|
||||||
const y = -size[1] / 2;
|
const y = -size[1] / 2;
|
||||||
const r = 3;
|
const r = 3;
|
||||||
|
const fillColor = typeof value === 'string' ? value : '#f5222d';
|
||||||
|
|
||||||
// 第一个背景圆
|
// 第一个背景圆
|
||||||
const back1 = group.addShape('circle', {
|
const back1 = group.addShape('circle', {
|
||||||
|
|||||||
@@ -1,383 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { reactive, ref, toRaw, watch } from 'vue';
|
|
||||||
import { ProModal } from 'antdv-pro-modal';
|
|
||||||
import { message, Modal } from 'ant-design-vue/es';
|
|
||||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
|
||||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
|
||||||
import { saveAs } from 'file-saver';
|
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
import { exportNBState, listNBState } from '@/api/neData/nb-state';
|
|
||||||
import { Dayjs } from 'dayjs';
|
|
||||||
const { t } = useI18n();
|
|
||||||
const emit = defineEmits(['cancel', 'update:open']);
|
|
||||||
const props = defineProps({
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: '标题',
|
|
||||||
},
|
|
||||||
open: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
/**网元ID */
|
|
||||||
neId: {
|
|
||||||
type: String,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
neType: {
|
|
||||||
type: String,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**开始结束时间 */
|
|
||||||
let queryRangePicker = ref<[Dayjs, Dayjs] | undefined>(undefined);
|
|
||||||
/**状态字典 */
|
|
||||||
const nbStateOptions = ref<DictType[]>([
|
|
||||||
{
|
|
||||||
value: 'ON',
|
|
||||||
label: t('views.neData.baseStation.online'),
|
|
||||||
tagType: 'green',
|
|
||||||
tagClass: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'OFF',
|
|
||||||
label: t('views.neData.baseStation.offline'),
|
|
||||||
tagType: 'red',
|
|
||||||
tagClass: '',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
|
||||||
let queryParams = reactive({
|
|
||||||
/**网元 */
|
|
||||||
neType: '',
|
|
||||||
neId: '',
|
|
||||||
/**排序字段 */
|
|
||||||
sortField: 'id',
|
|
||||||
sortOrder: 'desc',
|
|
||||||
/**状态 */
|
|
||||||
status: undefined as undefined | string,
|
|
||||||
/**开始时间 */
|
|
||||||
startTime: undefined as undefined | number,
|
|
||||||
/**结束时间 */
|
|
||||||
endTime: undefined as undefined | number,
|
|
||||||
/**当前页数 */
|
|
||||||
pageNum: 1,
|
|
||||||
/**每页条数 */
|
|
||||||
pageSize: 20,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**查询参数重置 */
|
|
||||||
function fnQueryReset() {
|
|
||||||
queryParams = Object.assign(queryParams, {
|
|
||||||
status: undefined,
|
|
||||||
startTime: undefined,
|
|
||||||
endTime: undefined,
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 20,
|
|
||||||
});
|
|
||||||
queryRangePicker.value = undefined;
|
|
||||||
tablePagination.current = 1;
|
|
||||||
tablePagination.pageSize = 20;
|
|
||||||
fnGetList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**表格状态类型 */
|
|
||||||
type TabeStateType = {
|
|
||||||
/**加载等待 */
|
|
||||||
loading: boolean;
|
|
||||||
/**紧凑型 */
|
|
||||||
size: SizeType;
|
|
||||||
/**搜索栏 */
|
|
||||||
seached: boolean;
|
|
||||||
/**记录数据 */
|
|
||||||
data: object[];
|
|
||||||
/**勾选记录 */
|
|
||||||
selectedRowKeys: (string | number)[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**表格状态 */
|
|
||||||
let tableState: TabeStateType = reactive({
|
|
||||||
loading: false,
|
|
||||||
size: 'middle',
|
|
||||||
seached: true,
|
|
||||||
data: [],
|
|
||||||
selectedRowKeys: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格字段列 */
|
|
||||||
let tableColumns = ref<ColumnsType>([
|
|
||||||
{
|
|
||||||
title: t('common.rowId'),
|
|
||||||
dataIndex: 'id',
|
|
||||||
align: 'left',
|
|
||||||
width: 80,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.name'),
|
|
||||||
dataIndex: 'name',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 120,
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 250,
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.position'),
|
|
||||||
dataIndex: 'position',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 150,
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 400,
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.address'),
|
|
||||||
dataIndex: 'address',
|
|
||||||
align: 'left',
|
|
||||||
width: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.nbName'),
|
|
||||||
dataIndex: 'nbName',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 100,
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 200,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.state'),
|
|
||||||
dataIndex: 'state',
|
|
||||||
key: 'state',
|
|
||||||
align: 'left',
|
|
||||||
width: 80,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.time'),
|
|
||||||
dataIndex: 'time',
|
|
||||||
align: 'left',
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**表格分页器参数 */
|
|
||||||
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: total }),
|
|
||||||
onChange: (page: number, pageSize: number) => {
|
|
||||||
tablePagination.current = page;
|
|
||||||
tablePagination.pageSize = pageSize;
|
|
||||||
queryParams.pageNum = page;
|
|
||||||
queryParams.pageSize = pageSize;
|
|
||||||
fnGetList();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**列表导出 */
|
|
||||||
function fnExportList() {
|
|
||||||
Modal.confirm({
|
|
||||||
title: t('common.tipTitle'),
|
|
||||||
content: t('views.neData.baseStation.exportTip'),
|
|
||||||
onOk() {
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
const querys = toRaw(queryParams);
|
|
||||||
exportNBState(querys)
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success({
|
|
||||||
content: t('common.operateOk'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
saveAs(res.data, `nb_state_history_records_export_${Date.now()}.xlsx`);
|
|
||||||
} else {
|
|
||||||
message.error({
|
|
||||||
content: `${res.msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**查询字典数据列表, pageNum初始页数 */
|
|
||||||
function fnGetList(pageNum?: number) {
|
|
||||||
if (tableState.loading) return;
|
|
||||||
tableState.loading = true;
|
|
||||||
if (pageNum) {
|
|
||||||
queryParams.pageNum = pageNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 时间范围
|
|
||||||
if (
|
|
||||||
Array.isArray(queryRangePicker.value) &&
|
|
||||||
queryRangePicker.value.length > 0
|
|
||||||
) {
|
|
||||||
queryParams.startTime = queryRangePicker.value[0].valueOf();
|
|
||||||
queryParams.endTime = queryRangePicker.value[1].valueOf();
|
|
||||||
} else {
|
|
||||||
queryParams.startTime = undefined;
|
|
||||||
queryParams.endTime = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
listNBState(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;
|
|
||||||
if (
|
|
||||||
tablePagination.total <=
|
|
||||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
|
||||||
queryParams.pageNum !== 1
|
|
||||||
) {
|
|
||||||
tableState.loading = false;
|
|
||||||
fnGetList(queryParams.pageNum - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tableState.loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**弹框取消按钮事件 */
|
|
||||||
function fnModalCancel() {
|
|
||||||
emit('update:open', false);
|
|
||||||
emit('cancel');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**监听是否显示,初始数据 */
|
|
||||||
watch(
|
|
||||||
() => props.open,
|
|
||||||
val => {
|
|
||||||
if (val) {
|
|
||||||
queryParams.neType = props.neType;
|
|
||||||
queryParams.neId = props.neId;
|
|
||||||
// 获取列表数据
|
|
||||||
fnGetList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<ProModal
|
|
||||||
:drag="true"
|
|
||||||
:destroyOnClose="true"
|
|
||||||
:width="1200"
|
|
||||||
:title="props.title"
|
|
||||||
:open="props.open"
|
|
||||||
:keyboard="false"
|
|
||||||
:mask-closable="false"
|
|
||||||
@cancel="fnModalCancel"
|
|
||||||
:footer="null"
|
|
||||||
>
|
|
||||||
<!-- 表格搜索栏 -->
|
|
||||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
|
||||||
<a-row :gutter="16" style="margin-left: 0; margin-right: 0">
|
|
||||||
<a-col :lg="6" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.neData.baseStation.state')"
|
|
||||||
name="status"
|
|
||||||
>
|
|
||||||
<a-select
|
|
||||||
v-model:value="queryParams.status"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.selectPlease')"
|
|
||||||
:options="nbStateOptions"
|
|
||||||
>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="16" :md="12" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.neData.baseStation.time')"
|
|
||||||
name="queryRangePicker"
|
|
||||||
>
|
|
||||||
<a-range-picker
|
|
||||||
v-model:value="queryRangePicker"
|
|
||||||
:bordered="true"
|
|
||||||
:allow-clear="true"
|
|
||||||
style="width: 100%"
|
|
||||||
:show-time="{ format: 'HH:mm:ss' }"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
></a-range-picker>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="24" :md="24" :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-button type="dashed" @click.prevent="fnExportList()">
|
|
||||||
<template #icon><ExportOutlined /></template>
|
|
||||||
{{ t('common.export') }}
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-form>
|
|
||||||
|
|
||||||
<!-- 表格列表 -->
|
|
||||||
<a-table
|
|
||||||
class="table"
|
|
||||||
row-key="id"
|
|
||||||
:columns="tableColumns"
|
|
||||||
:loading="tableState.loading"
|
|
||||||
:data-source="tableState.data"
|
|
||||||
:size="tableState.size"
|
|
||||||
:pagination="tablePagination"
|
|
||||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
|
||||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.key === 'state'">
|
|
||||||
<DictTag
|
|
||||||
:options="nbStateOptions"
|
|
||||||
:value="record.state"
|
|
||||||
value-default="OFF"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</ProModal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.table :deep(.ant-pagination) {
|
|
||||||
padding: 0 24px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
|
||||||
import ListComponent from './list.vue';
|
|
||||||
import TopologyComponent from './topology.vue';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
const { t } = useI18n();
|
|
||||||
const value = ref<string>('list');
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<PageContainer>
|
|
||||||
<template #extra>
|
|
||||||
<a-radio-group v-model:value="value" button-style="solid">
|
|
||||||
<a-radio-button value="list">
|
|
||||||
{{ t('views.neData.baseStation.list') }}
|
|
||||||
</a-radio-button>
|
|
||||||
<a-radio-button value="topology">
|
|
||||||
{{ t('views.neData.baseStation.topology') }}
|
|
||||||
</a-radio-button>
|
|
||||||
</a-radio-group>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div v-show="value === 'list'">
|
|
||||||
<ListComponent></ListComponent>
|
|
||||||
</div>
|
|
||||||
<div v-if="value === 'topology'">
|
|
||||||
<TopologyComponent></TopologyComponent>
|
|
||||||
</div>
|
|
||||||
</PageContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -1,958 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {
|
|
||||||
reactive,
|
|
||||||
ref,
|
|
||||||
onMounted,
|
|
||||||
toRaw,
|
|
||||||
computed,
|
|
||||||
defineAsyncComponent,
|
|
||||||
} from 'vue';
|
|
||||||
import { Form, message, Modal } from 'ant-design-vue';
|
|
||||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
|
||||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
|
||||||
import { ProModal } from 'antdv-pro-modal';
|
|
||||||
import UploadModal from '@/components/UploadModal/index.vue';
|
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
const { t, currentLocale } = useI18n();
|
|
||||||
import {
|
|
||||||
addAMFNbState,
|
|
||||||
delAMFNbState,
|
|
||||||
editAMFNbState,
|
|
||||||
listAMFNbStatelist,
|
|
||||||
} from '@/api/neData/amf';
|
|
||||||
import {
|
|
||||||
addMMENbState,
|
|
||||||
delMMENbState,
|
|
||||||
editMMENbState,
|
|
||||||
listMMENbStatelist,
|
|
||||||
} from '@/api/neData/mme';
|
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
|
||||||
import saveAs from 'file-saver';
|
|
||||||
import { readSheet, writeSheet } from '@/utils/execl-utils';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
const route = useRoute();
|
|
||||||
// 异步加载组件
|
|
||||||
const HistoryModal = defineAsyncComponent(
|
|
||||||
() => import('./components/history.vue')
|
|
||||||
);
|
|
||||||
|
|
||||||
const nbState = ref<DictType[]>([
|
|
||||||
{
|
|
||||||
value: 'ON',
|
|
||||||
label: t('views.neData.baseStation.online'),
|
|
||||||
tagType: 'green',
|
|
||||||
tagClass: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'OFF',
|
|
||||||
label: t('views.neData.baseStation.offline'),
|
|
||||||
tagType: 'red',
|
|
||||||
tagClass: '',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**网元参数 */
|
|
||||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
|
||||||
/**网元数据 */
|
|
||||||
let neTypeAndId = ref<string[]>([]);
|
|
||||||
/**查询参数 */
|
|
||||||
let queryParams = reactive({
|
|
||||||
/**网元ID */
|
|
||||||
neId: '',
|
|
||||||
/**IMSI */
|
|
||||||
state: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**查询参数重置 */
|
|
||||||
function fnQueryReset() {
|
|
||||||
queryParams = Object.assign(queryParams, {
|
|
||||||
state: undefined,
|
|
||||||
});
|
|
||||||
fnGetList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**表格状态类型 */
|
|
||||||
type TabeStateType = {
|
|
||||||
/**加载等待 */
|
|
||||||
loading: boolean;
|
|
||||||
/**紧凑型 */
|
|
||||||
size: SizeType;
|
|
||||||
/**记录数据 */
|
|
||||||
data: Record<string, any>[];
|
|
||||||
/**勾选记录 */
|
|
||||||
selectedRowKeys: (string | number)[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**表格状态 */
|
|
||||||
let tableState: TabeStateType = reactive({
|
|
||||||
loading: false,
|
|
||||||
size: 'small',
|
|
||||||
data: [],
|
|
||||||
selectedRowKeys: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格字段列 */
|
|
||||||
let tableColumns = ref<ColumnsType>([
|
|
||||||
// {
|
|
||||||
// title: t('common.rowId'),
|
|
||||||
// dataIndex: 'index',
|
|
||||||
// align: 'left',
|
|
||||||
// width: 80,
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.name'),
|
|
||||||
dataIndex: 'name',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 120,
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 250,
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.position'),
|
|
||||||
dataIndex: 'position',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 150,
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 400,
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.address'),
|
|
||||||
dataIndex: 'address',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 100,
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 200,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.nbName'),
|
|
||||||
dataIndex: 'nbName',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 100,
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 200,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.ueNum'),
|
|
||||||
dataIndex: 'ueNum',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 80,
|
|
||||||
minWidth: 80,
|
|
||||||
maxWidth: 120,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.state'),
|
|
||||||
dataIndex: 'state',
|
|
||||||
key: 'state',
|
|
||||||
align: 'left',
|
|
||||||
resizable: true,
|
|
||||||
width: 80,
|
|
||||||
minWidth: 80,
|
|
||||||
maxWidth: 120,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.neData.baseStation.time'),
|
|
||||||
align: 'left',
|
|
||||||
width: 150,
|
|
||||||
customRender(opt) {
|
|
||||||
const record = opt.value;
|
|
||||||
if (record.state === 'OFF') {
|
|
||||||
return record.offTime || '-';
|
|
||||||
}
|
|
||||||
return record.onTime || '-';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**表格分页器参数 */
|
|
||||||
let tablePagination = {
|
|
||||||
/**当前页数 */
|
|
||||||
current: 1,
|
|
||||||
/**每页条数 */
|
|
||||||
pageSize: 20,
|
|
||||||
/**默认的每页条数 */
|
|
||||||
defaultPageSize: 20,
|
|
||||||
/**指定每页可以显示多少条 */
|
|
||||||
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;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**表格多选 */
|
|
||||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
|
||||||
tableState.selectedRowKeys = keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 记录删除
|
|
||||||
* @param index ID
|
|
||||||
*/
|
|
||||||
function fnRecordDelete(index: string) {
|
|
||||||
const [neType, neId] = neTypeAndId.value;
|
|
||||||
if (!neId) return;
|
|
||||||
let msg = `Delete index as:${index}`;
|
|
||||||
if (index === '0') {
|
|
||||||
msg = `Remove the index checkbox:${tableState.selectedRowKeys.length}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
Modal.confirm({
|
|
||||||
title: t('common.tipTitle'),
|
|
||||||
content: msg,
|
|
||||||
onOk() {
|
|
||||||
const reqArr = [];
|
|
||||||
if (index === '0') {
|
|
||||||
if (tableState.selectedRowKeys.length <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const v of tableState.selectedRowKeys) {
|
|
||||||
if (neType === 'MME') {
|
|
||||||
reqArr.push(delMMENbState(neId, v));
|
|
||||||
}
|
|
||||||
if (neType === 'AMF') {
|
|
||||||
reqArr.push(delAMFNbState(neId, v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (neType === 'MME') {
|
|
||||||
reqArr.push(delMMENbState(neId, index));
|
|
||||||
}
|
|
||||||
if (neType === 'AMF') {
|
|
||||||
reqArr.push(delAMFNbState(neId, index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reqArr.length <= 0) return;
|
|
||||||
Promise.all(reqArr).then(res => {
|
|
||||||
const resArr = res.filter(
|
|
||||||
(item: any) => item.code !== RESULT_CODE_SUCCESS
|
|
||||||
);
|
|
||||||
if (resArr.length <= 0) {
|
|
||||||
message.success({
|
|
||||||
content: `${t('common.operateOk')}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
fnGetList();
|
|
||||||
} else {
|
|
||||||
message.error({
|
|
||||||
content: `${t('common.operateErr')}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**查询列表 */
|
|
||||||
function fnGetList() {
|
|
||||||
if (tableState.loading) return;
|
|
||||||
tableState.loading = true;
|
|
||||||
const [neType, neId] = neTypeAndId.value;
|
|
||||||
queryParams.neId = neId;
|
|
||||||
let req = null;
|
|
||||||
if (neType === 'MME') {
|
|
||||||
req = listMMENbStatelist(toRaw(queryParams));
|
|
||||||
}
|
|
||||||
if (neType === 'AMF') {
|
|
||||||
req = listAMFNbStatelist(toRaw(queryParams));
|
|
||||||
}
|
|
||||||
if (req === null) {
|
|
||||||
tableState.data = [];
|
|
||||||
tableState.loading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
// 取消勾选
|
|
||||||
if (tableState.selectedRowKeys.length > 0) {
|
|
||||||
tableState.selectedRowKeys = [];
|
|
||||||
}
|
|
||||||
tableState.data = res.data.filter((item: any) => {
|
|
||||||
// 状态过滤
|
|
||||||
if (queryParams.state) {
|
|
||||||
return item.state === queryParams.state;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
tableState.data = [];
|
|
||||||
}
|
|
||||||
tableState.loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const stateNum = computed(() => {
|
|
||||||
let onNum = 0;
|
|
||||||
let offNum = 0;
|
|
||||||
tableState.data.forEach((item: any) => {
|
|
||||||
if (item.state === 'ON') {
|
|
||||||
onNum += 1;
|
|
||||||
}
|
|
||||||
if (item.state === 'OFF') {
|
|
||||||
offNum += 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return [onNum, offNum];
|
|
||||||
});
|
|
||||||
|
|
||||||
/**对话框对象信息状态类型 */
|
|
||||||
type ModalStateType = {
|
|
||||||
/**新增框或修改框是否显示 */
|
|
||||||
openByEdit: boolean;
|
|
||||||
/**标题 */
|
|
||||||
title: string;
|
|
||||||
/**表单数据 */
|
|
||||||
from: Record<string, any>;
|
|
||||||
/**确定按钮 loading */
|
|
||||||
confirmLoading: boolean;
|
|
||||||
/**历史框 */
|
|
||||||
openByHistory: boolean;
|
|
||||||
/**导入框 */
|
|
||||||
openByImport: boolean;
|
|
||||||
importMsgArr: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**对话框对象信息状态 */
|
|
||||||
let modalState: ModalStateType = reactive({
|
|
||||||
openByEdit: false,
|
|
||||||
title: 'NB Config List',
|
|
||||||
from: {
|
|
||||||
address: '',
|
|
||||||
index: undefined,
|
|
||||||
name: '',
|
|
||||||
nbName: undefined,
|
|
||||||
offTime: undefined,
|
|
||||||
onTime: undefined,
|
|
||||||
position: '',
|
|
||||||
state: undefined,
|
|
||||||
ueNum: undefined,
|
|
||||||
},
|
|
||||||
confirmLoading: false,
|
|
||||||
openByHistory: false,
|
|
||||||
openByImport: false,
|
|
||||||
importMsgArr: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**对话框内表单属性和校验规则 */
|
|
||||||
const modalStateFrom = Form.useForm(
|
|
||||||
modalState.from,
|
|
||||||
reactive({
|
|
||||||
address: [
|
|
||||||
{ required: true, message: t('views.neData.baseStation.addressPlease') },
|
|
||||||
],
|
|
||||||
name: [
|
|
||||||
{ required: true, message: t('views.neData.baseStation.namePlease') },
|
|
||||||
],
|
|
||||||
position: [
|
|
||||||
{ required: true, message: t('views.neData.baseStation.positionPlease') },
|
|
||||||
],
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对话框弹出显示为 新增或者修改
|
|
||||||
* @param noticeId 网元id, 不传为新增
|
|
||||||
*/
|
|
||||||
function fnModalVisibleByEdit(edit?: string | number) {
|
|
||||||
if (!edit) {
|
|
||||||
modalStateFrom.resetFields(); //重置表单
|
|
||||||
modalState.title = t('views.neData.baseStation.addRadio');
|
|
||||||
modalState.openByEdit = true;
|
|
||||||
// 获取最大index
|
|
||||||
if (tableState.data.length <= 0) {
|
|
||||||
modalState.from.index = 1;
|
|
||||||
} else {
|
|
||||||
const last = tableState.data[tableState.data.length - 1];
|
|
||||||
modalState.from.index = last.index + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 编辑
|
|
||||||
if (edit === '0') {
|
|
||||||
const row = tableState.data.find((row: any) => {
|
|
||||||
return row.index === tableState.selectedRowKeys[0];
|
|
||||||
});
|
|
||||||
modalStateFrom.resetFields(); //重置表单
|
|
||||||
Object.assign(modalState.from, row);
|
|
||||||
modalState.title = t('views.neData.baseStation.editRadio');
|
|
||||||
modalState.openByEdit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对话框弹出确认执行函数
|
|
||||||
* 进行表达规则校验
|
|
||||||
*/
|
|
||||||
function fnModalOk() {
|
|
||||||
const [neType, neId] = neTypeAndId.value;
|
|
||||||
if (!neId) return;
|
|
||||||
const from = JSON.parse(JSON.stringify(modalState.from));
|
|
||||||
modalStateFrom
|
|
||||||
.validate()
|
|
||||||
.then(e => {
|
|
||||||
modalState.confirmLoading = true;
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
let result: any = null;
|
|
||||||
if (neType === 'MME') {
|
|
||||||
result = from.state
|
|
||||||
? editMMENbState(neId, from)
|
|
||||||
: addMMENbState(neId, from);
|
|
||||||
}
|
|
||||||
if (neType === 'AMF') {
|
|
||||||
result = from.state
|
|
||||||
? editAMFNbState(neId, from)
|
|
||||||
: addAMFNbState(neId, from);
|
|
||||||
}
|
|
||||||
if (result === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
result
|
|
||||||
.then((res: any) => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success({
|
|
||||||
content: t('common.operateOk'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
fnModalCancel();
|
|
||||||
fnGetList();
|
|
||||||
} else {
|
|
||||||
message.error({
|
|
||||||
content: t('common.operateErr'),
|
|
||||||
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.openByHistory = false;
|
|
||||||
modalStateFrom.resetFields();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**导出当前列表 */
|
|
||||||
function fnExportList() {
|
|
||||||
Modal.confirm({
|
|
||||||
title: t('common.tipTitle'),
|
|
||||||
content: t('views.neData.baseStation.exportTip'),
|
|
||||||
onOk: async () => {
|
|
||||||
if (modalState.confirmLoading) return;
|
|
||||||
modalState.confirmLoading = true;
|
|
||||||
|
|
||||||
let rows: Record<string, any>[] = [];
|
|
||||||
// 勾选的网元数据
|
|
||||||
if (tableState.selectedRowKeys.length > 0) {
|
|
||||||
rows = tableState.data.filter(item =>
|
|
||||||
tableState.selectedRowKeys.includes(item.index)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
rows = tableState.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataArr: Record<string, any>[] = [];
|
|
||||||
for (const row of rows) {
|
|
||||||
let data: any = {};
|
|
||||||
data[t('views.neData.baseStation.name')] = row.name;
|
|
||||||
data[t('views.neData.baseStation.position')] = row.position;
|
|
||||||
data[t('views.neData.baseStation.address')] = row.address;
|
|
||||||
data[t('views.neData.baseStation.nbName')] = row.nbName;
|
|
||||||
data[t('views.neData.baseStation.ueNum')] = row.ueNum;
|
|
||||||
nbState.value.find(item => {
|
|
||||||
if (item.value === row.state) {
|
|
||||||
data[t('views.neData.baseStation.state')] = item.label;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
data[t('views.neData.baseStation.time')] = row.time || '-';
|
|
||||||
dataArr.push(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出
|
|
||||||
writeSheet(dataArr, 'Sheet1', {
|
|
||||||
header: [
|
|
||||||
t('views.neData.baseStation.name'),
|
|
||||||
t('views.neData.baseStation.position'),
|
|
||||||
t('views.neData.baseStation.address'),
|
|
||||||
t('views.neData.baseStation.nbName'),
|
|
||||||
t('views.neData.baseStation.ueNum'),
|
|
||||||
t('views.neData.baseStation.state'),
|
|
||||||
t('views.neData.baseStation.time'),
|
|
||||||
],
|
|
||||||
}).then(fileBlob =>
|
|
||||||
saveAs(fileBlob, `nb_state_records_export_${Date.now()}.xlsx`)
|
|
||||||
);
|
|
||||||
|
|
||||||
modalState.confirmLoading = false;
|
|
||||||
tableState.selectedRowKeys = [];
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**对话框弹出历史窗口 */
|
|
||||||
function fnHistoryView() {
|
|
||||||
modalState.openByHistory = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**对话框表格信息导入弹出窗口 */
|
|
||||||
function fnModalImportOpen() {
|
|
||||||
modalState.openByImport = true;
|
|
||||||
}
|
|
||||||
function fnModalImportClose() {
|
|
||||||
modalState.openByImport = false;
|
|
||||||
fnQueryReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**对话框表格信息导入上传 */
|
|
||||||
function fnModalImportUpload(file: File) {
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
const [neType, neId] = neTypeAndId.value;
|
|
||||||
modalState.importMsgArr = [];
|
|
||||||
|
|
||||||
// 获取最大index
|
|
||||||
let index = 0;
|
|
||||||
if (tableState.data.length <= 0) {
|
|
||||||
index = 1;
|
|
||||||
} else {
|
|
||||||
const last = tableState.data[tableState.data.length - 1];
|
|
||||||
index = last.index + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = function (e: any) {
|
|
||||||
const arrayBuffer = e.target.result;
|
|
||||||
readSheet(arrayBuffer).then(async rows => {
|
|
||||||
console.log(rows);
|
|
||||||
if (rows.length <= 0) {
|
|
||||||
hide();
|
|
||||||
message.error({
|
|
||||||
content: t('views.neData.baseStation.importDataEmpty'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 开始导入
|
|
||||||
modalState.confirmLoading = true;
|
|
||||||
for (const row of rows) {
|
|
||||||
const rowId = row[t('common.rowId')];
|
|
||||||
const name = row[t('views.neData.baseStation.name')];
|
|
||||||
const position = row[t('views.neData.baseStation.position')];
|
|
||||||
const address = row[t('views.neData.baseStation.address')];
|
|
||||||
let result: any = null;
|
|
||||||
// 检查IP地址是否定义
|
|
||||||
const hasAddress = tableState.data.find(
|
|
||||||
item => item.address === address
|
|
||||||
);
|
|
||||||
if (hasAddress) {
|
|
||||||
// 定义则更新名称位置
|
|
||||||
if (neType === 'MME') {
|
|
||||||
result = await editMMENbState(
|
|
||||||
neId,
|
|
||||||
Object.assign({}, hasAddress, {
|
|
||||||
name,
|
|
||||||
position,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (neType === 'AMF') {
|
|
||||||
result = await editAMFNbState(
|
|
||||||
neId,
|
|
||||||
Object.assign({}, hasAddress, {
|
|
||||||
name,
|
|
||||||
position,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let msg = `${t('common.rowId')}: ${rowId} ${t(
|
|
||||||
'views.neData.baseStation.editRadio'
|
|
||||||
)}${t('common.operateErr')}`;
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS) {
|
|
||||||
msg = `${t('common.rowId')}: ${rowId} ${t(
|
|
||||||
'views.neData.baseStation.editRadio'
|
|
||||||
)}${t('common.operateOk')}`;
|
|
||||||
}
|
|
||||||
modalState.importMsgArr.push(msg);
|
|
||||||
} else {
|
|
||||||
// 未定义则新增
|
|
||||||
const form = {
|
|
||||||
index,
|
|
||||||
name: `${name}`,
|
|
||||||
position: `${position}`,
|
|
||||||
address: `${address}`,
|
|
||||||
};
|
|
||||||
if (neType === 'MME') {
|
|
||||||
result = await addMMENbState(neId, form);
|
|
||||||
}
|
|
||||||
if (neType === 'AMF') {
|
|
||||||
result = await addAMFNbState(neId, form);
|
|
||||||
}
|
|
||||||
let msg = `${t('common.rowId')}: ${rowId} ${t(
|
|
||||||
'views.neData.baseStation.addRadio'
|
|
||||||
)}${t('common.operateErr')}`;
|
|
||||||
if (result.code === RESULT_CODE_SUCCESS) {
|
|
||||||
index += 1;
|
|
||||||
msg = `${t('common.rowId')}: ${rowId} ${t(
|
|
||||||
'views.neData.baseStation.addRadio'
|
|
||||||
)}${t('common.operateOk')}`;
|
|
||||||
}
|
|
||||||
modalState.importMsgArr.push(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hide();
|
|
||||||
modalState.confirmLoading = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
reader.onerror = function (e) {
|
|
||||||
hide();
|
|
||||||
console.error('reader file error:', e);
|
|
||||||
};
|
|
||||||
reader.readAsArrayBuffer(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**对话框表格信息导入模板 */
|
|
||||||
async function fnModalImportTemplate() {
|
|
||||||
const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
|
|
||||||
const xlsxUrl = `${
|
|
||||||
baseUrl.length === 1 && baseUrl.indexOf('/') === 0
|
|
||||||
? ''
|
|
||||||
: baseUrl.indexOf('/') === -1
|
|
||||||
? '/' + baseUrl
|
|
||||||
: baseUrl
|
|
||||||
}/nbStateImput`;
|
|
||||||
const lang = currentLocale.value.split('_')[0];
|
|
||||||
saveAs(
|
|
||||||
`${xlsxUrl}/${lang}.xlsx`,
|
|
||||||
`nb_state_records_import_template_${Date.now()}.xlsx`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// 获取网元网元列表
|
|
||||||
useNeInfoStore()
|
|
||||||
.fnNelist()
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
if (res.data.length > 0) {
|
|
||||||
let arr: Record<string, any>[] = [];
|
|
||||||
useNeInfoStore().neCascaderOptions.forEach(item => {
|
|
||||||
if (['AMF', 'MME'].includes(item.value)) {
|
|
||||||
arr.push(JSON.parse(JSON.stringify(item)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
neCascaderOptions.value = arr;
|
|
||||||
// 无查询参数neType时 默认选择AMF
|
|
||||||
const queryNeType = (route.query.neType as string) || 'AMF';
|
|
||||||
const item = arr.find(s => s.value === queryNeType);
|
|
||||||
if (item && item.children) {
|
|
||||||
const info = item.children[0];
|
|
||||||
neTypeAndId.value = [info.neType, info.neId];
|
|
||||||
} else {
|
|
||||||
const info = neCascaderOptions.value[0].children[0];
|
|
||||||
neTypeAndId.value = [info.neType, info.neId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message.warning({
|
|
||||||
content: t('common.noData'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
// 获取列表数据
|
|
||||||
fnGetList();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<a-card
|
|
||||||
: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-cascader
|
|
||||||
v-model:value="neTypeAndId"
|
|
||||||
:options="neCascaderOptions"
|
|
||||||
:allow-clear="false"
|
|
||||||
:placeholder="t('common.selectPlease')"
|
|
||||||
@change="fnGetList"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :lg="4" :md="6" :xs="24">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.neData.baseStation.state')"
|
|
||||||
name="state"
|
|
||||||
>
|
|
||||||
<a-select
|
|
||||||
v-model:value="queryParams.state"
|
|
||||||
:options="nbState"
|
|
||||||
:placeholder="t('common.selectPlease')"
|
|
||||||
@change="fnGetList"
|
|
||||||
/>
|
|
||||||
</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()">
|
|
||||||
<template #icon><SearchOutlined /></template>
|
|
||||||
{{ t('common.search') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="default" @click.prevent="fnQueryReset">
|
|
||||||
<template #icon><ClearOutlined /></template>
|
|
||||||
{{ t('common.reset') }}
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-form>
|
|
||||||
</a-card>
|
|
||||||
|
|
||||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
|
||||||
<!-- 插槽-卡片左侧侧 -->
|
|
||||||
<template #title>
|
|
||||||
<a-space :size="8" align="center">
|
|
||||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
|
||||||
<template #icon>
|
|
||||||
<PlusOutlined />
|
|
||||||
</template>
|
|
||||||
{{ t('common.addText') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button
|
|
||||||
type="default"
|
|
||||||
:disabled="tableState.selectedRowKeys.length != 1"
|
|
||||||
:loading="modalState.confirmLoading"
|
|
||||||
@click.prevent="fnModalVisibleByEdit('0')"
|
|
||||||
>
|
|
||||||
<template #icon><FormOutlined /></template>
|
|
||||||
{{ t('common.editText') }}
|
|
||||||
</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-button type="dashed" @click.prevent="fnModalImportOpen()">
|
|
||||||
<template #icon><ImportOutlined /></template>
|
|
||||||
{{ t('common.import') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
|
||||||
<template #icon><ExportOutlined /></template>
|
|
||||||
{{ t('common.export') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="default" @click.prevent="fnHistoryView()">
|
|
||||||
<template #icon><ContainerOutlined /></template>
|
|
||||||
{{ t('views.neData.baseStation.history') }}
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 插槽-卡片右侧 -->
|
|
||||||
<template #extra>
|
|
||||||
<a-space :size="8" align="center">
|
|
||||||
<div>
|
|
||||||
<template
|
|
||||||
v-if="
|
|
||||||
queryParams.state === undefined || queryParams.state === 'ON'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ t('views.neData.baseStation.online') }}:
|
|
||||||
<strong style="color: green">{{ stateNum[0] }} </strong>
|
|
||||||
</template>
|
|
||||||
<template
|
|
||||||
v-if="
|
|
||||||
queryParams.state === undefined || queryParams.state === 'OFF'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
|
|
||||||
{{ t('views.neData.baseStation.offline') }}:
|
|
||||||
<strong style="color: red">
|
|
||||||
{{ stateNum[1] }}
|
|
||||||
</strong>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
|
||||||
<a-button type="text" @click.prevent="fnGetList()">
|
|
||||||
<template #icon><ReloadOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 表格列表 -->
|
|
||||||
<a-table
|
|
||||||
class="table"
|
|
||||||
row-key="index"
|
|
||||||
:columns="tableColumns"
|
|
||||||
:loading="tableState.loading"
|
|
||||||
:data-source="tableState.data"
|
|
||||||
:size="tableState.size"
|
|
||||||
:pagination="tablePagination"
|
|
||||||
:row-selection="{
|
|
||||||
type: 'checkbox',
|
|
||||||
selectedRowKeys: tableState.selectedRowKeys,
|
|
||||||
onChange: fnTableSelectedRowKeys,
|
|
||||||
}"
|
|
||||||
:scroll="{ x: tableColumns.length * 120, y: 'calc(100vh - 480px)' }"
|
|
||||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.key === 'state'">
|
|
||||||
<DictTag
|
|
||||||
:options="nbState"
|
|
||||||
:value="record.state"
|
|
||||||
value-default="OFF"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</a-card>
|
|
||||||
|
|
||||||
<!-- 新增框或修改框 -->
|
|
||||||
<ProModal
|
|
||||||
:drag="true"
|
|
||||||
:width="500"
|
|
||||||
:destroyOnClose="true"
|
|
||||||
: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-form-item
|
|
||||||
:label="t('views.neData.baseStation.name')"
|
|
||||||
name="name"
|
|
||||||
v-bind="modalStateFrom.validateInfos.name"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="modalState.from.name"
|
|
||||||
allow-clear
|
|
||||||
:maxlength="64"
|
|
||||||
>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
:label="t('views.neData.baseStation.position')"
|
|
||||||
name="position"
|
|
||||||
v-bind="modalStateFrom.validateInfos.position"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="modalState.from.position"
|
|
||||||
allow-clear
|
|
||||||
:maxlength="64"
|
|
||||||
>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
v-if="!modalState.from.state"
|
|
||||||
:label="t('views.neData.baseStation.address')"
|
|
||||||
name="address"
|
|
||||||
v-bind="modalStateFrom.validateInfos.address"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:value="modalState.from.address"
|
|
||||||
allow-clear
|
|
||||||
:maxlength="64"
|
|
||||||
>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</ProModal>
|
|
||||||
|
|
||||||
<!-- 状态历史框 -->
|
|
||||||
<HistoryModal
|
|
||||||
v-model:open="modalState.openByHistory"
|
|
||||||
:title="t('views.neData.baseStation.history')"
|
|
||||||
:ne-type="neTypeAndId[0]"
|
|
||||||
:ne-id="neTypeAndId[1]"
|
|
||||||
@cancel="fnModalCancel"
|
|
||||||
></HistoryModal>
|
|
||||||
|
|
||||||
<!-- 上传导入表格数据文件框 -->
|
|
||||||
<UploadModal
|
|
||||||
:title="t('common.import')"
|
|
||||||
@upload="fnModalImportUpload"
|
|
||||||
@close="fnModalImportClose"
|
|
||||||
v-model:open="modalState.openByImport"
|
|
||||||
:ext="['.xls', '.xlsx']"
|
|
||||||
:size="10"
|
|
||||||
>
|
|
||||||
<template #default>
|
|
||||||
<a-row justify="space-between" align="middle">
|
|
||||||
<a-col :span="12"> </a-col>
|
|
||||||
<a-col :span="6">
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
:title="t('views.system.user.downloadObj')"
|
|
||||||
@click.prevent="fnModalImportTemplate"
|
|
||||||
>
|
|
||||||
{{ t('views.system.user.downloadObj') }}
|
|
||||||
</a-button>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
<a-textarea
|
|
||||||
:disabled="true"
|
|
||||||
:hidden="modalState.importMsgArr.length <= 0"
|
|
||||||
:value="modalState.importMsgArr.join('\r\n')"
|
|
||||||
:auto-size="{ minRows: 2, maxRows: 8 }"
|
|
||||||
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</UploadModal>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.table :deep(.ant-pagination) {
|
|
||||||
padding: 0 24px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,642 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { reactive, onMounted, ref, onBeforeUnmount, useTemplateRef } from 'vue';
|
|
||||||
import { Graph, GraphData, Menu, Tooltip, Util } from '@antv/g6';
|
|
||||||
import { listAMFNbStatelist } from '@/api/neData/amf';
|
|
||||||
import { parseBasePath } from '@/plugins/file-static-url';
|
|
||||||
import { edgeLineAnimateState } from '@/views/monitor/topologyBuild/hooks/registerEdge';
|
|
||||||
import { nodeImageAnimateState } from '@/views/monitor/topologyBuild/hooks/registerNode';
|
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
|
||||||
import { stateNeInfo } from '@/api/ne/neInfo';
|
|
||||||
import { parseDateToStr } from '@/utils/date-utils';
|
|
||||||
import { useFullscreen } from '@vueuse/core';
|
|
||||||
import { listMMENbStatelist } from '@/api/neData/mme';
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
/**图DOM节点实例对象 */
|
|
||||||
const graphG6Dom = useTemplateRef('graphG6Dom');
|
|
||||||
|
|
||||||
/**图数据 */
|
|
||||||
const graphData = reactive<Record<string, any>>({
|
|
||||||
nodes: [
|
|
||||||
{
|
|
||||||
id: 'omc',
|
|
||||||
label: 'OMC',
|
|
||||||
img: parseBasePath('/svg/service_db.svg'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'amf1',
|
|
||||||
label: 'amf1',
|
|
||||||
img: parseBasePath('/svg/service.svg'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'amf2',
|
|
||||||
label: 'amf2',
|
|
||||||
img: parseBasePath('/svg/service.svg'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'base1',
|
|
||||||
label: 'base1',
|
|
||||||
img: parseBasePath('/svg/base.svg'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'base2',
|
|
||||||
label: 'base2',
|
|
||||||
img: parseBasePath('/svg/base.svg'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
edges: [
|
|
||||||
{
|
|
||||||
source: 'omc',
|
|
||||||
target: 'amf1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: 'omc',
|
|
||||||
target: 'amf2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: 'amf1',
|
|
||||||
target: 'base1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: 'amf2',
|
|
||||||
target: 'base1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: 'amf2',
|
|
||||||
target: 'base2',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图实例对象 */
|
|
||||||
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, nType, nInfo }: any = evt.item?.getModel();
|
|
||||||
if (['GNB', 'ENB'].includes(nType)) {
|
|
||||||
return `
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 140px;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
${t('views.neData.baseStation.name')}:
|
|
||||||
${label ?? '--'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
return `
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 140px;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
${t('views.monitor.topology.name')}:
|
|
||||||
${label ?? '--'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图节点展示 */
|
|
||||||
const graphNodeTooltip = new Tooltip({
|
|
||||||
offsetX: 10,
|
|
||||||
offsetY: 20,
|
|
||||||
getContent(evt) {
|
|
||||||
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
|
|
||||||
const { id, label, nType, nInfo }: any = evt.item?.getModel();
|
|
||||||
if (['GNB', 'ENB'].includes(nType)) {
|
|
||||||
return `
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 256px;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div><strong>${t('views.neData.baseStation.state')}:</strong><span>
|
|
||||||
${
|
|
||||||
nInfo.state === 'ON'
|
|
||||||
? t('views.neData.baseStation.online')
|
|
||||||
: t('views.neData.baseStation.offline')
|
|
||||||
}
|
|
||||||
</span></div>
|
|
||||||
<div><strong>${t('views.neData.baseStation.time')}:</strong><span>
|
|
||||||
${nInfo.state === 'ON' ? nInfo.onTime ?? '--' : nInfo.offTime ?? '--'}
|
|
||||||
</span></div>
|
|
||||||
<div>==============================</div>
|
|
||||||
<div><strong>ID:</strong><span>${nInfo.index}</span></div>
|
|
||||||
<div><strong>${t('views.neData.baseStation.address')}:</strong><span>
|
|
||||||
${nInfo.address ?? '--'}</span></div>
|
|
||||||
<div><strong>${t('views.neData.baseStation.nbName')}:</strong><span>
|
|
||||||
${nInfo.nbName ?? '--'}</span></div>
|
|
||||||
<div><strong>${t('views.neData.baseStation.ueNum')}:</strong><span>
|
|
||||||
${nInfo.ueNum ?? '--'}</span></div>
|
|
||||||
<div><strong>${t('views.neData.baseStation.name')}:</strong><span>
|
|
||||||
${nInfo.name ?? '--'}
|
|
||||||
</span></div>
|
|
||||||
<div><strong>${t(
|
|
||||||
'views.neData.baseStation.position'
|
|
||||||
)}:</strong><span style="word-wrap: break-word;">
|
|
||||||
${nInfo.position}
|
|
||||||
</span></div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
return `
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 200px;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div><strong>${t('views.monitor.topology.state')}:</strong><span>
|
|
||||||
${
|
|
||||||
nInfo.online
|
|
||||||
? t('views.monitor.topology.normalcy')
|
|
||||||
: t('views.monitor.topology.exceptions')
|
|
||||||
}
|
|
||||||
</span></div>
|
|
||||||
<div><strong>${t('views.monitor.topology.refreshTime')}:</strong><span>
|
|
||||||
${nInfo.refreshTime ?? '--'}
|
|
||||||
</span></div>
|
|
||||||
<div>========================</div>
|
|
||||||
<div><strong>ID:</strong><span>${nInfo.neId}</span></div>
|
|
||||||
<div><strong>${t('views.monitor.topology.name')}:</strong><span>
|
|
||||||
${nInfo.neName ?? '--'}
|
|
||||||
</span></div>
|
|
||||||
<div><strong>IP:</strong><span>${nInfo.neIP}</span></div>
|
|
||||||
<div><strong>${t('views.monitor.topology.version')}:</strong><span>
|
|
||||||
${nInfo.version ?? '--'}
|
|
||||||
</span></div>
|
|
||||||
<div><strong>${t('views.monitor.topology.serialNum')}:</strong><span>
|
|
||||||
${nInfo.sn ?? '--'}
|
|
||||||
</span></div>
|
|
||||||
<div><strong>${t('views.monitor.topology.expiryDate')}:</strong><span>
|
|
||||||
${nInfo.expire ?? '--'}
|
|
||||||
</span></div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
},
|
|
||||||
itemTypes: ['node'],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**注册自定义边或节点 */
|
|
||||||
function registerEdgeNode() {
|
|
||||||
// 边
|
|
||||||
edgeLineAnimateState();
|
|
||||||
// 节点
|
|
||||||
nodeImageAnimateState();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* format the string
|
|
||||||
* @param {string} str The origin string
|
|
||||||
* @param {number} maxWidth max width
|
|
||||||
* @param {number} fontSize font size
|
|
||||||
* @return {string} the processed result
|
|
||||||
*/
|
|
||||||
function fittingString(str: string, maxWidth: number, fontSize: number) {
|
|
||||||
let currentWidth = 0;
|
|
||||||
let res = str;
|
|
||||||
const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
|
|
||||||
str.split('').forEach((letter, i) => {
|
|
||||||
if (currentWidth > maxWidth) return;
|
|
||||||
if (pattern.test(letter)) {
|
|
||||||
// Chinese charactors
|
|
||||||
currentWidth += fontSize;
|
|
||||||
} else {
|
|
||||||
// get the width of single letter according to the fontSize
|
|
||||||
currentWidth += Util.getLetterWidth(letter, fontSize);
|
|
||||||
}
|
|
||||||
if (currentWidth > maxWidth) {
|
|
||||||
res = `${str.substring(0, i)}\n${str.substring(i)}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图事件 */
|
|
||||||
function graphEvent(graph: Graph) {
|
|
||||||
graph.on('edge:mouseenter', evt => {
|
|
||||||
const { item } = evt;
|
|
||||||
if (!item) return;
|
|
||||||
graph.setItemState(item, 'circle-move', '#b5d6fb');
|
|
||||||
});
|
|
||||||
graph.on('edge:mouseleave', evt => {
|
|
||||||
const { item } = evt;
|
|
||||||
if (!item) return;
|
|
||||||
graph.setItemState(item, 'circle-move', false);
|
|
||||||
graph.setItemState(item, 'circle-move:#b5d6fb', false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图数据渲染 */
|
|
||||||
function handleRanderGraph(container: HTMLElement | null, data: GraphData) {
|
|
||||||
if (!container) return;
|
|
||||||
const { clientHeight, clientWidth } = container;
|
|
||||||
|
|
||||||
// 注册自定义边或节点
|
|
||||||
registerEdgeNode();
|
|
||||||
|
|
||||||
const graph = new Graph({
|
|
||||||
container: container,
|
|
||||||
width: clientWidth,
|
|
||||||
height: clientHeight,
|
|
||||||
fitCenter: false,
|
|
||||||
fitView: true,
|
|
||||||
fitViewPadding: [40, 40, 40, 40],
|
|
||||||
modes: {
|
|
||||||
// default: ['drag-canvas', 'drag-node', 'zoom-canvas'],
|
|
||||||
default: [
|
|
||||||
'zoom-canvas',
|
|
||||||
'drag-canvas',
|
|
||||||
'drag-node',
|
|
||||||
{
|
|
||||||
type: 'drag-combo',
|
|
||||||
onlyChangeComboSize: true, // 不改变层级关系
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'collapse-expand-combo',
|
|
||||||
trigger: 'dblclick',
|
|
||||||
relayout: true, // 收缩展开后,不重新布局
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
groupByTypes: false,
|
|
||||||
plugins: [graphNodeMenu, graphNodeTooltip],
|
|
||||||
layout: {
|
|
||||||
type: 'dagre',
|
|
||||||
rankdir: 'TB', // 布局的方向,TB:从上到下,BT:从下到上,LR:从左到右,RL:从右到左
|
|
||||||
//align: 'UL', // 节点对齐方式 UL、UR、DL、DR
|
|
||||||
controlPoints: true,
|
|
||||||
nodesep: 20,
|
|
||||||
ranksep: 40,
|
|
||||||
},
|
|
||||||
animate: true,
|
|
||||||
defaultNode: {
|
|
||||||
type: 'image-animate-state',
|
|
||||||
labelCfg: {
|
|
||||||
offset: 8,
|
|
||||||
position: 'bottom',
|
|
||||||
style: { fill: '#ffffff', fontSize: 14, fontWeight: 500 },
|
|
||||||
},
|
|
||||||
size: 48,
|
|
||||||
img: parseBasePath('/svg/cloud.svg'),
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
},
|
|
||||||
defaultEdge: {
|
|
||||||
type: 'line-animate-state',
|
|
||||||
labelCfg: {
|
|
||||||
autoRotate: true,
|
|
||||||
refY: 10,
|
|
||||||
refX: 40,
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
stroke: '#fafafa',
|
|
||||||
lineWidth: 1.5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultCombo: {
|
|
||||||
labelCfg: {
|
|
||||||
offset: 16,
|
|
||||||
position: 'bottom',
|
|
||||||
style: { fill: '#ffffff', fontSize: 14, fontWeight: 500 },
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
stroke: '#BDEFDB',
|
|
||||||
fill: '#BDEFDB',
|
|
||||||
opacity: 0.25,
|
|
||||||
},
|
|
||||||
collapsedSubstituteIcon: {
|
|
||||||
show: true,
|
|
||||||
img: parseBasePath('/svg/service.svg'),
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
graph.data(data);
|
|
||||||
graph.render();
|
|
||||||
graphEvent(graph);
|
|
||||||
|
|
||||||
// 创建 ResizeObserver 实例
|
|
||||||
const observer = new ResizeObserver(function (entries) {
|
|
||||||
// 当元素大小发生变化时触发回调函数
|
|
||||||
entries.forEach(function (entry) {
|
|
||||||
if (!graph) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
graph.changeSize(entry.contentRect.width, entry.contentRect.height);
|
|
||||||
graph.fitCenter();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// 监听元素大小变化
|
|
||||||
observer.observe(container);
|
|
||||||
|
|
||||||
return graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取图组数据渲染到画布
|
|
||||||
*/
|
|
||||||
async function fnGraphDataLoad() {
|
|
||||||
// 加载基础网元
|
|
||||||
await useNeInfoStore().fnNelist();
|
|
||||||
const dataNe = await fnGraphDataBase();
|
|
||||||
Object.assign(graphData, dataNe);
|
|
||||||
graphG6.value = handleRanderGraph(graphG6Dom.value, dataNe);
|
|
||||||
// 添加基站
|
|
||||||
const dataNb = await fnGraphDataNb(dataNe);
|
|
||||||
Object.assign(graphData, dataNb);
|
|
||||||
// graphG6.value.clear();
|
|
||||||
graphG6.value.read(dataNb);
|
|
||||||
// 添加状态
|
|
||||||
interval.value = true;
|
|
||||||
repeatFn();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图数据网元构建 */
|
|
||||||
async function fnGraphDataBase() {
|
|
||||||
const data: GraphData = {
|
|
||||||
nodes: [],
|
|
||||||
edges: [],
|
|
||||||
};
|
|
||||||
// 添加基础网元
|
|
||||||
for (const item of useNeInfoStore().getNeSelectOtions) {
|
|
||||||
if ('OMC' === item.value) {
|
|
||||||
if (item.children?.length === 0) continue;
|
|
||||||
// 是否存在OMC保证唯一
|
|
||||||
const hasOMC = data.nodes?.findIndex(v => v.neType === 'OMC');
|
|
||||||
if (hasOMC !== -1) continue;
|
|
||||||
// 根网元
|
|
||||||
const omcInfo = item.children[0];
|
|
||||||
const node = {
|
|
||||||
id: 'OMC',
|
|
||||||
label: omcInfo.neName,
|
|
||||||
img: parseBasePath('/svg/service_db.svg'),
|
|
||||||
nInfo: { online: false, neId: omcInfo.neId, neType: omcInfo.neType },
|
|
||||||
nType: 'OMC',
|
|
||||||
};
|
|
||||||
// 添加OMC节点
|
|
||||||
data.nodes?.push(node);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (['AMF', 'MME'].includes(item.value)) {
|
|
||||||
if (item.children?.length === 0) continue;
|
|
||||||
for (const child of item.children) {
|
|
||||||
const id = `${child.neType}_${child.neId}`;
|
|
||||||
const node = {
|
|
||||||
id: id,
|
|
||||||
label: child.neName,
|
|
||||||
img: parseBasePath('/svg/service.svg'),
|
|
||||||
nInfo: { online: false, neId: child.neId, neType: child.neType },
|
|
||||||
nType: item.value,
|
|
||||||
};
|
|
||||||
// 添加节点
|
|
||||||
data.nodes?.push(node);
|
|
||||||
data.edges?.push({
|
|
||||||
source: 'OMC',
|
|
||||||
target: id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
item.children.forEach((v: any) => {});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图数据基站构建 */
|
|
||||||
async function fnGraphDataNb(data: GraphData) {
|
|
||||||
const arr = data.nodes?.filter((v: any) => ['AMF', 'MME'].includes(v.nType));
|
|
||||||
if (arr === undefined || arr.length === 0) return data;
|
|
||||||
for (const item of arr) {
|
|
||||||
if (item.nType === 'AMF') {
|
|
||||||
const neId = (item.nInfo as any).neId;
|
|
||||||
const res = await listAMFNbStatelist({ neId });
|
|
||||||
if (res.code !== RESULT_CODE_SUCCESS || !Array.isArray(res.data)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const nb of res.data) {
|
|
||||||
const id = `${item.id}_${nb.index}`;
|
|
||||||
data.nodes?.push({
|
|
||||||
id: id,
|
|
||||||
label: fittingString(`${nb.name}`, 80, 14),
|
|
||||||
img: parseBasePath('/svg/base5G.svg'),
|
|
||||||
nInfo: nb,
|
|
||||||
nType: 'GNB',
|
|
||||||
});
|
|
||||||
data.edges?.push({
|
|
||||||
source: item.id,
|
|
||||||
target: id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (item.nType === 'MME') {
|
|
||||||
const neId = (item.nInfo as any).neId;
|
|
||||||
const res = await listMMENbStatelist({ neId });
|
|
||||||
if (res.code !== RESULT_CODE_SUCCESS || !Array.isArray(res.data)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const nb of res.data) {
|
|
||||||
const id = `${item.id}_${nb.index}`;
|
|
||||||
data.nodes?.push({
|
|
||||||
id: id,
|
|
||||||
label: fittingString(`${nb.name}`, 80, 14),
|
|
||||||
img: parseBasePath('/svg/base4G.svg'),
|
|
||||||
nInfo: nb,
|
|
||||||
nType: 'ENB',
|
|
||||||
});
|
|
||||||
data.edges?.push({
|
|
||||||
source: item.id,
|
|
||||||
target: id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 图状态构建
|
|
||||||
* @param reload 是否重载状态
|
|
||||||
*/
|
|
||||||
async function fnGraphState(reload: boolean = false) {
|
|
||||||
// 节点状态
|
|
||||||
if (!Array.isArray(graphData.nodes)) return;
|
|
||||||
|
|
||||||
const onc = graphData.nodes.find((v: any) => v.nType === 'OMC');
|
|
||||||
if (onc) {
|
|
||||||
const { id, nInfo } = onc as any;
|
|
||||||
if (!nInfo) return;
|
|
||||||
const res = await stateNeInfo(nInfo.neType, nInfo.neId);
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
Object.assign(nInfo, res.data, {
|
|
||||||
refreshTime: parseDateToStr(res.data.refreshTime, 'HH:mm:ss'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const stateColor = nInfo.online ? '#52c41a' : '#f5222d'; // 状态颜色
|
|
||||||
graphG6.value.setItemState(id, 'top-right-dot', stateColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
graphData.nodes
|
|
||||||
.filter((v: any) => ['AMF', 'MME'].includes(v.nType))
|
|
||||||
.forEach(async (v: any) => {
|
|
||||||
const { id, nInfo } = v;
|
|
||||||
if (!nInfo) return;
|
|
||||||
const res = await stateNeInfo(nInfo.neType, nInfo.neId);
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
Object.assign(nInfo, res.data, {
|
|
||||||
refreshTime: parseDateToStr(res.data.refreshTime, 'HH:mm:ss'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const stateColor = nInfo.online ? '#52c41a' : '#f5222d'; // 状态颜色
|
|
||||||
graphG6.value.setItemState(id, 'top-right-dot', stateColor);
|
|
||||||
|
|
||||||
// 重载时更新下级基站状态
|
|
||||||
if (reload && nInfo.neType === 'AMF') {
|
|
||||||
const res = await listAMFNbStatelist({ neId: nInfo.neId });
|
|
||||||
if (res.code == RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
for (const nb of res.data) {
|
|
||||||
const nbItem = graphData.nodes.find(
|
|
||||||
(v: any) => v.id === `${id}_${nb.index}`
|
|
||||||
);
|
|
||||||
if (nbItem) {
|
|
||||||
Object.assign(nbItem.nInfo, nb);
|
|
||||||
const stateColor = nb.state === 'ON' ? '#52c41a' : '#f5222d'; // 状态颜色
|
|
||||||
graphG6.value.setItemState(
|
|
||||||
nbItem.id,
|
|
||||||
'top-right-dot',
|
|
||||||
stateColor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reload && nInfo.neType === 'MME') {
|
|
||||||
const res = await listMMENbStatelist({ neId: nInfo.neId });
|
|
||||||
if (res.code == RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
for (const nb of res.data) {
|
|
||||||
const nbItem = graphData.nodes.find(
|
|
||||||
(v: any) => v.id === `${id}_${nb.index}`
|
|
||||||
);
|
|
||||||
if (nbItem) {
|
|
||||||
Object.assign(nbItem.nInfo, nb);
|
|
||||||
const stateColor = nb.state === 'ON' ? '#52c41a' : '#f5222d'; // 状态颜色
|
|
||||||
graphG6.value.setItemState(
|
|
||||||
nbItem.id,
|
|
||||||
'top-right-dot',
|
|
||||||
stateColor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (reload) {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 15_000));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 非重载时使用初始获取的状态
|
|
||||||
graphData.nodes
|
|
||||||
.filter((v: any) => ['GNB', 'ENB'].includes(v.nType))
|
|
||||||
.forEach(async (v: any) => {
|
|
||||||
const { id, nInfo } = v;
|
|
||||||
if (!nInfo) return;
|
|
||||||
const stateColor = nInfo.state === 'ON' ? '#52c41a' : '#f5222d'; // 状态颜色
|
|
||||||
graphG6.value.setItemState(id, 'top-right-dot', stateColor);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**递归调度器 */
|
|
||||||
const interval = ref<boolean>(false);
|
|
||||||
|
|
||||||
/**递归刷新图状态 */
|
|
||||||
function repeatFn(reload: boolean = false) {
|
|
||||||
if (!interval.value || !graphG6Dom.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fnGraphState(reload)
|
|
||||||
.finally(() => {
|
|
||||||
repeatFn(true); // 递归调用自己
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const viewportDom = ref<HTMLElement | null>(null);
|
|
||||||
const { isFullscreen, toggle } = useFullscreen(viewportDom);
|
|
||||||
function fullscreen() {
|
|
||||||
toggle();
|
|
||||||
|
|
||||||
if (!graphG6Dom.value) return;
|
|
||||||
if (isFullscreen.value) {
|
|
||||||
graphG6Dom.value.style.height = 'calc(100vh - 300px)';
|
|
||||||
} else {
|
|
||||||
graphG6Dom.value.style.height = '100vh';
|
|
||||||
}
|
|
||||||
const { clientHeight, clientWidth } = graphG6Dom.value;
|
|
||||||
graphG6.value.changeSize(clientHeight, clientWidth);
|
|
||||||
graphG6.value.fitView(40);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
fnGraphDataLoad();
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
interval.value = false;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<a-card :bordered="false" :body-style="{ padding: '0' }" ref="viewportDom">
|
|
||||||
<!-- 插槽-卡片左侧侧 -->
|
|
||||||
<template #title>
|
|
||||||
<a-space :size="8" align="center">
|
|
||||||
{{ t('views.neData.baseStation.topologyTitle') }}
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
<!-- 插槽-卡片右侧 -->
|
|
||||||
<template #extra>
|
|
||||||
<a-button type="default" @click.prevent="fullscreen()">
|
|
||||||
<template #icon>
|
|
||||||
<FullscreenExitOutlined v-if="isFullscreen" />
|
|
||||||
<FullscreenOutlined v-else />
|
|
||||||
</template>
|
|
||||||
{{ t('loayouts.rightContent.fullscreen') }}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div ref="graphG6Dom" class="chart"></div>
|
|
||||||
</a-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.chart {
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100vh - 300px);
|
|
||||||
background-color: rgb(43, 47, 51);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -195,7 +195,9 @@ function fnActiveConfigNode(key: string | number) {
|
|||||||
}, 300);
|
}, 300);
|
||||||
} else {
|
} else {
|
||||||
message.warning({
|
message.warning({
|
||||||
content: `${param.paramDisplay} ${t('views.ne.neConfig.noConfigData')}`,
|
content: `${param.paramDisplay} ${t(
|
||||||
|
'views.configManage.configParamForm.noConfigData'
|
||||||
|
)}`,
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -207,7 +209,7 @@ function fnGetNeConfig() {
|
|||||||
const neType = neTypeSelect.value[0];
|
const neType = neTypeSelect.value[0];
|
||||||
if (!neType) {
|
if (!neType) {
|
||||||
message.warning({
|
message.warning({
|
||||||
content: t('views.ne.neConfig.neTypePleace'),
|
content: t('views.configManage.configParamForm.neTypePleace'),
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -414,7 +416,7 @@ onMounted(() => {
|
|||||||
<!-- 网元类型 -->
|
<!-- 网元类型 -->
|
||||||
<a-card size="small" :bordered="false" :loading="treeState.loading">
|
<a-card size="small" :bordered="false" :loading="treeState.loading">
|
||||||
<template #title>
|
<template #title>
|
||||||
{{ t('views.ne.neConfig.treeTitle') }}
|
{{ t('views.configManage.configParamForm.treeTitle') }}
|
||||||
</template>
|
</template>
|
||||||
<a-form layout="vertical" autocomplete="off">
|
<a-form layout="vertical" autocomplete="off">
|
||||||
<a-form-item name="neId ">
|
<a-form-item name="neId ">
|
||||||
@@ -425,7 +427,7 @@ onMounted(() => {
|
|||||||
@change="fnGetNeConfig"
|
@change="fnGetNeConfig"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item name="treeStateData">
|
<a-form-item name="listeningPort">
|
||||||
<a-tree
|
<a-tree
|
||||||
:tree-data="treeState.data"
|
:tree-data="treeState.data"
|
||||||
:selected-keys="[treeState.selectNode.paramName]"
|
:selected-keys="[treeState.selectNode.paramName]"
|
||||||
@@ -459,12 +461,12 @@ onMounted(() => {
|
|||||||
{{ treeState.selectNode.paramDisplay }}
|
{{ treeState.selectNode.paramDisplay }}
|
||||||
</a-typography-text>
|
</a-typography-text>
|
||||||
<a-typography-text type="danger" v-else>
|
<a-typography-text type="danger" v-else>
|
||||||
{{ t('views.ne.neConfig.treeSelectTip') }}
|
{{ t('views.configManage.configParamForm.treeSelectTip') }}
|
||||||
</a-typography-text>
|
</a-typography-text>
|
||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<a-space :size="8" align="center" v-show="!treeState.selectLoading">
|
<a-space :size="8" align="center" v-show="!treeState.selectLoading">
|
||||||
<a-tooltip placement="topRight">
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
<template #title>{{ t('common.reloadText') }}</template>
|
||||||
<a-button
|
<a-button
|
||||||
type="default"
|
type="default"
|
||||||
@@ -547,9 +549,10 @@ onMounted(() => {
|
|||||||
<template #title> {{ t('common.ok') }} </template>
|
<template #title> {{ t('common.ok') }} </template>
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
:title="
|
:title="
|
||||||
t('views.ne.neConfig.editOkTip', {
|
t(
|
||||||
num: record['display'],
|
'views.configManage.configParamForm.editOkTip',
|
||||||
})
|
{ num: record['display'] }
|
||||||
|
)
|
||||||
"
|
"
|
||||||
placement="topRight"
|
placement="topRight"
|
||||||
:disabled="listState.confirmLoading"
|
:disabled="listState.confirmLoading"
|
||||||
@@ -607,7 +610,7 @@ onMounted(() => {
|
|||||||
</a-table>
|
</a-table>
|
||||||
|
|
||||||
<!-- array类型 -->
|
<!-- array类型 -->
|
||||||
<template v-else-if="treeState.selectNode.paramType === 'array'">
|
<template v-if="treeState.selectNode.paramType === 'array'">
|
||||||
<a-table
|
<a-table
|
||||||
class="table"
|
class="table"
|
||||||
row-key="index"
|
row-key="index"
|
||||||
@@ -686,7 +689,9 @@ onMounted(() => {
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #icon><BarsOutlined /></template>
|
<template #icon><BarsOutlined /></template>
|
||||||
{{ t('views.ne.neConfig.arrayMore') }}
|
{{
|
||||||
|
t('views.configManage.configParamForm.arrayMore')
|
||||||
|
}}
|
||||||
</a-button>
|
</a-button>
|
||||||
<!--特殊字段拓展显示-->
|
<!--特殊字段拓展显示-->
|
||||||
<span
|
<span
|
||||||
@@ -787,7 +792,11 @@ onMounted(() => {
|
|||||||
<template v-if="text.array">
|
<template v-if="text.array">
|
||||||
<a-button type="default" size="small">
|
<a-button type="default" size="small">
|
||||||
<template #icon><BarsOutlined /></template>
|
<template #icon><BarsOutlined /></template>
|
||||||
{{ t('views.ne.neConfig.arrayMore') }}
|
{{
|
||||||
|
t(
|
||||||
|
'views.configManage.configParamForm.arrayMore'
|
||||||
|
)
|
||||||
|
}}
|
||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -807,10 +816,6 @@ onMounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
|
||||||
<a-alert type="warning" show-icon message="No Data" />
|
|
||||||
</template>
|
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|||||||
@@ -1,513 +0,0 @@
|
|||||||
import {
|
|
||||||
addNeConfigData,
|
|
||||||
delNeConfigData,
|
|
||||||
editNeConfigData,
|
|
||||||
} from '@/api/ne/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, neTypeSelect, neIdSelect, fnActiveConfigNode, ruleVerification, modalState, fnModalCancel}
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export default function useConfigArray({
|
|
||||||
t,
|
|
||||||
treeState,
|
|
||||||
neTypeSelect,
|
|
||||||
neIdSelect,
|
|
||||||
fnActiveConfigNode,
|
|
||||||
ruleVerification,
|
|
||||||
modalState,
|
|
||||||
fnModalCancel,
|
|
||||||
}: any) {
|
|
||||||
/**多列列表状态类型 */
|
|
||||||
type ArrayStateType = {
|
|
||||||
/**紧凑型 */
|
|
||||||
size: SizeType;
|
|
||||||
/**多列嵌套记录字段 */
|
|
||||||
columns: Record<string, any>[];
|
|
||||||
/**表格字段列排序 */
|
|
||||||
columnsDnd: Record<string, any>[];
|
|
||||||
/**多列记录数据 */
|
|
||||||
columnsData: Record<string, any>[];
|
|
||||||
/**多列嵌套展开key */
|
|
||||||
arrayChildExpandKeys: any[];
|
|
||||||
|
|
||||||
/**多列记录数据 */
|
|
||||||
data: Record<string, any>[];
|
|
||||||
/**多列记录规则 */
|
|
||||||
dataRule: Record<string, any>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**多列列表状态 */
|
|
||||||
let arrayState: ArrayStateType = reactive({
|
|
||||||
size: 'small',
|
|
||||||
columns: [],
|
|
||||||
columnsDnd: [],
|
|
||||||
columnsData: [],
|
|
||||||
arrayChildExpandKeys: [],
|
|
||||||
data: [],
|
|
||||||
dataRule: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**多列表编辑 */
|
|
||||||
function arrayEdit(rowIndex: Record<string, any>) {
|
|
||||||
const item = arrayState.data.find((s: any) => s.key === rowIndex.value);
|
|
||||||
if (!item) return;
|
|
||||||
const from = arrayInitEdit(item, arrayState.dataRule);
|
|
||||||
// 处理信息
|
|
||||||
const row: Record<string, any> = {};
|
|
||||||
for (const v of from.record) {
|
|
||||||
if (Array.isArray(v.array)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
row[v.name] = Object.assign({}, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 特殊SMF-upfid选择
|
|
||||||
if (neTypeSelect.value[0] === 'SMF' && Reflect.has(row, 'upfId')) {
|
|
||||||
const v = row.upfId.value;
|
|
||||||
if (typeof v === 'string') {
|
|
||||||
if (v === '') {
|
|
||||||
row.upfId.value = [];
|
|
||||||
} else if (v.includes(';')) {
|
|
||||||
row.upfId.value = v.split(';');
|
|
||||||
} else if (v.includes(',')) {
|
|
||||||
row.upfId.value = v.split(',');
|
|
||||||
} else {
|
|
||||||
row.upfId.value = [v];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modalState.from = row;
|
|
||||||
modalState.type = 'arrayEdit';
|
|
||||||
modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`;
|
|
||||||
modalState.key = from.key;
|
|
||||||
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
|
||||||
modalState.open = true;
|
|
||||||
|
|
||||||
// 关闭嵌套
|
|
||||||
arrayState.arrayChildExpandKeys = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**多列表编辑关闭 */
|
|
||||||
function arrayEditClose() {
|
|
||||||
arrayState.arrayChildExpandKeys = [];
|
|
||||||
fnModalCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**多列表编辑确认 */
|
|
||||||
function arrayEditOk(from: Record<string, any>) {
|
|
||||||
const loc = `${from['index']['value']}`;
|
|
||||||
|
|
||||||
// 特殊SMF-upfid选择
|
|
||||||
if (neTypeSelect.value[0] === 'SMF' && Reflect.has(from, 'upfId')) {
|
|
||||||
const v = from.upfId.value;
|
|
||||||
if (Array.isArray(v)) {
|
|
||||||
from.upfId.value = v.join(';');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历提取属性和值
|
|
||||||
let data: Record<string, any> = {};
|
|
||||||
for (const key in from) {
|
|
||||||
// 子嵌套的不插入
|
|
||||||
if (from[key]['array']) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 检查规则
|
|
||||||
const [ok, msg] = ruleVerification(from[key]);
|
|
||||||
if (!ok) {
|
|
||||||
message.warning({
|
|
||||||
content: `${msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data[key] = from[key]['value'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 请求
|
|
||||||
const reqArr = [];
|
|
||||||
if (neTypeSelect.value[1].startsWith('SYNC')) {
|
|
||||||
for (const neId of neIdSelect.value) {
|
|
||||||
reqArr.push(
|
|
||||||
editNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neId,
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: data,
|
|
||||||
loc: loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reqArr.push(
|
|
||||||
editNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neTypeSelect.value[1],
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: data,
|
|
||||||
loc: loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 无请求提示
|
|
||||||
if (reqArr.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.neIdSyncPleace'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
arrayEditClose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
Promise.allSettled(reqArr)
|
|
||||||
.then(resArr => {
|
|
||||||
const rejected = resArr.find(res => res.status === 'rejected');
|
|
||||||
if (rejected) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.updateItemErr'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
message.success({
|
|
||||||
content: t('views.ne.neConfig.updateItem', {
|
|
||||||
num: modalState.title,
|
|
||||||
}),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const fulfilled = resArr.find(res => res.status === 'fulfilled');
|
|
||||||
if (fulfilled) {
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.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() {
|
|
||||||
// 请求
|
|
||||||
const reqArr = [];
|
|
||||||
if (neTypeSelect.value[1].startsWith('SYNC')) {
|
|
||||||
for (const neId of neIdSelect.value) {
|
|
||||||
reqArr.push(
|
|
||||||
delNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neId,
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
loc: loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reqArr.push(
|
|
||||||
delNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neTypeSelect.value[1],
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
loc: loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 无请求提示
|
|
||||||
if (reqArr.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.neIdSyncPleace'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
arrayEditClose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
Promise.allSettled(reqArr)
|
|
||||||
.then(resArr => {
|
|
||||||
const rejected = resArr.find(res => res.status === 'rejected');
|
|
||||||
if (rejected) {
|
|
||||||
message.error({
|
|
||||||
content: `${rejected.reason}`,
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
message.success({
|
|
||||||
content: t('views.ne.neConfig.delItemOk', {
|
|
||||||
num: title,
|
|
||||||
}),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const fulfilled = resArr.find(res => res.status === 'fulfilled');
|
|
||||||
if (fulfilled) {
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
arrayEditClose();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**多列表新增单行 */
|
|
||||||
function arrayAdd() {
|
|
||||||
const from = arrayInitAdd(arrayState.data, arrayState.dataRule);
|
|
||||||
|
|
||||||
// 处理信息
|
|
||||||
const row: Record<string, any> = {};
|
|
||||||
for (const v of from.record) {
|
|
||||||
if (Array.isArray(v.array)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
row[v.name] = Object.assign({}, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 特殊SMF-upfid选择
|
|
||||||
if (neTypeSelect.value[0] === 'SMF' && Reflect.has(row, 'upfId')) {
|
|
||||||
const v = row.upfId.value;
|
|
||||||
if (typeof v === 'string') {
|
|
||||||
if (v === '') {
|
|
||||||
row.upfId.value = [];
|
|
||||||
} else if (v.includes(';')) {
|
|
||||||
row.upfId.value = v.split(';');
|
|
||||||
} else if (v.includes(',')) {
|
|
||||||
row.upfId.value = v.split(',');
|
|
||||||
} else {
|
|
||||||
row.upfId.value = [v];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modalState.from = row;
|
|
||||||
modalState.type = 'arrayAdd';
|
|
||||||
modalState.title = `${treeState.selectNode.paramDisplay} ${from.title}`;
|
|
||||||
modalState.key = from.key;
|
|
||||||
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
|
||||||
modalState.open = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**多列表新增单行确认 */
|
|
||||||
function arrayAddOk(from: Record<string, any>) {
|
|
||||||
// 特殊SMF-upfid选择
|
|
||||||
if (neTypeSelect.value[0] === 'SMF' && Reflect.has(from, 'upfId')) {
|
|
||||||
const v = from.upfId.value;
|
|
||||||
if (Array.isArray(v)) {
|
|
||||||
from.upfId.value = v.join(';');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历提取属性和值
|
|
||||||
let data: Record<string, any> = {};
|
|
||||||
for (const key in from) {
|
|
||||||
// 子嵌套的不插入
|
|
||||||
if (from[key]['array']) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 检查规则
|
|
||||||
const [ok, msg] = ruleVerification(from[key]);
|
|
||||||
if (!ok) {
|
|
||||||
message.warning({
|
|
||||||
content: `${msg}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data[key] = from[key]['value'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 请求
|
|
||||||
const reqArr = [];
|
|
||||||
if (neTypeSelect.value[1].startsWith('SYNC')) {
|
|
||||||
for (const neId of neIdSelect.value) {
|
|
||||||
reqArr.push(
|
|
||||||
addNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neId,
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: data,
|
|
||||||
loc: `${from['index']['value']}`,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reqArr.push(
|
|
||||||
addNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neTypeSelect.value[1],
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: data,
|
|
||||||
loc: `${from['index']['value']}`,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 无请求提示
|
|
||||||
if (reqArr.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.neIdSyncPleace'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
arrayEditClose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
Promise.allSettled(reqArr)
|
|
||||||
.then(resArr => {
|
|
||||||
const rejected = resArr.find(res => res.status === 'rejected');
|
|
||||||
if (rejected) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.addItemErr'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
message.success({
|
|
||||||
content: t('views.ne.neConfig.addItemOk', {
|
|
||||||
num: modalState.title,
|
|
||||||
}),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const fulfilled = resArr.find(res => res.status === 'fulfilled');
|
|
||||||
if (fulfilled) {
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
arrayEditClose();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**多列表编辑行数据初始化 */
|
|
||||||
function arrayInitEdit(data: Record<string, any>, dataRule: any) {
|
|
||||||
const dataFrom = data.record;
|
|
||||||
const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule)));
|
|
||||||
for (const row of ruleFrom.record) {
|
|
||||||
// 子嵌套的不初始
|
|
||||||
if (row.array) {
|
|
||||||
row.value = [];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 查找项的值
|
|
||||||
const item = dataFrom.find((s: any) => s.name === row.name);
|
|
||||||
if (!item) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 可选的
|
|
||||||
row.optional = 'true';
|
|
||||||
// 根据规则类型转值
|
|
||||||
if (['enum', 'int'].includes(row.type)) {
|
|
||||||
row.value = Number(item.value);
|
|
||||||
} else if ('bool' === row.type) {
|
|
||||||
row.value = Boolean(item.value);
|
|
||||||
} else {
|
|
||||||
row.value = item.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ruleFrom.key = data.key;
|
|
||||||
ruleFrom.title = data.title;
|
|
||||||
return ruleFrom;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**多列表新增行数据初始化 */
|
|
||||||
function arrayInitAdd(data: any[], dataRule: any) {
|
|
||||||
// 有数据时取得最后的index
|
|
||||||
let dataLastIndex = 0;
|
|
||||||
if (data.length !== 0) {
|
|
||||||
const lastFrom = Object.assign(
|
|
||||||
{},
|
|
||||||
JSON.parse(JSON.stringify(data.at(-1)))
|
|
||||||
);
|
|
||||||
if (lastFrom.record.length > 0) {
|
|
||||||
dataLastIndex = parseInt(lastFrom.key);
|
|
||||||
dataLastIndex += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule)));
|
|
||||||
for (const row of ruleFrom.record) {
|
|
||||||
// 子嵌套的不初始
|
|
||||||
if (row.array) {
|
|
||||||
row.value = [];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 可选的
|
|
||||||
row.optional = 'true';
|
|
||||||
// index值
|
|
||||||
if (row.name === 'index') {
|
|
||||||
let newIndex =
|
|
||||||
dataLastIndex !== 0 ? dataLastIndex : parseInt(row.value);
|
|
||||||
if (isNaN(newIndex)) {
|
|
||||||
newIndex = 0;
|
|
||||||
}
|
|
||||||
row.value = newIndex;
|
|
||||||
ruleFrom.key = newIndex;
|
|
||||||
ruleFrom.title = `Index-${newIndex}`;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 根据规则类型转值
|
|
||||||
if (['enum', 'int'].includes(row.type)) {
|
|
||||||
row.value = Number(row.value);
|
|
||||||
}
|
|
||||||
if ('bool' === row.type) {
|
|
||||||
row.value = Boolean(row.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 特殊SMF-upfid选择
|
|
||||||
if (neTypeSelect.value[0] === 'SMF' && row.name === 'upfId') {
|
|
||||||
const v = row.value;
|
|
||||||
if (typeof v === 'string') {
|
|
||||||
if (v === '') {
|
|
||||||
row.value = [];
|
|
||||||
} else if (v.includes(';')) {
|
|
||||||
row.value = v.split(';');
|
|
||||||
} else if (v.includes(',')) {
|
|
||||||
row.value = v.split(',');
|
|
||||||
} else {
|
|
||||||
row.value = [v];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ruleFrom;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听表格字段列排序变化关闭展开
|
|
||||||
watch(
|
|
||||||
() => arrayState.columnsDnd,
|
|
||||||
() => {
|
|
||||||
arrayEditClose();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
arrayState,
|
|
||||||
arrayEdit,
|
|
||||||
arrayEditClose,
|
|
||||||
arrayEditOk,
|
|
||||||
arrayDelete,
|
|
||||||
arrayAdd,
|
|
||||||
arrayAddOk,
|
|
||||||
arrayInitEdit,
|
|
||||||
arrayInitAdd,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,454 +0,0 @@
|
|||||||
import {
|
|
||||||
addNeConfigData,
|
|
||||||
editNeConfigData,
|
|
||||||
delNeConfigData,
|
|
||||||
} from '@/api/ne/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, neTypeSelect, neIdSelect, fnActiveConfigNode, ruleVerification, modalState, arrayState, arrayInitEdit, arrayInitAdd, arrayEditClose}
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export default function useConfigArrayChild({
|
|
||||||
t,
|
|
||||||
treeState,
|
|
||||||
neTypeSelect,
|
|
||||||
neIdSelect,
|
|
||||||
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 reqArr = [];
|
|
||||||
if (neTypeSelect.value[1].startsWith('SYNC')) {
|
|
||||||
for (const neId of neIdSelect.value) {
|
|
||||||
reqArr.push(
|
|
||||||
editNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neId,
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: data,
|
|
||||||
loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reqArr.push(
|
|
||||||
editNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neTypeSelect.value[1],
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: data,
|
|
||||||
loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 无请求提示
|
|
||||||
if (reqArr.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.neIdSyncPleace'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
arrayEditClose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
Promise.allSettled(reqArr)
|
|
||||||
.then(resArr => {
|
|
||||||
const rejected = resArr.find(res => res.status === 'rejected');
|
|
||||||
if (rejected) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.updateItemErr'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
message.success({
|
|
||||||
content: t('views.ne.neConfig.updateItem', {
|
|
||||||
num: modalState.title,
|
|
||||||
}),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const fulfilled = resArr.find(res => res.status === 'fulfilled');
|
|
||||||
if (fulfilled) {
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.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() {
|
|
||||||
// 请求
|
|
||||||
const reqArr = [];
|
|
||||||
if (neTypeSelect.value[1].startsWith('SYNC')) {
|
|
||||||
for (const neId of neIdSelect.value) {
|
|
||||||
reqArr.push(
|
|
||||||
delNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neId,
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reqArr.push(
|
|
||||||
delNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neTypeSelect.value[1],
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 无请求提示
|
|
||||||
if (reqArr.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.neIdSyncPleace'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
arrayEditClose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
Promise.allSettled(reqArr)
|
|
||||||
.then(resArr => {
|
|
||||||
const rejected = resArr.find(res => res.status === 'rejected');
|
|
||||||
if (rejected) {
|
|
||||||
message.error({
|
|
||||||
content: `${rejected.reason}`,
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
message.success({
|
|
||||||
content: t('views.ne.neConfig.delItemOk', {
|
|
||||||
num: title,
|
|
||||||
}),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const fulfilled = resArr.find(res => res.status === 'fulfilled');
|
|
||||||
if (fulfilled) {
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
arrayEditClose();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**多列表嵌套行新增单行 */
|
|
||||||
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 reqArr = [];
|
|
||||||
if (neTypeSelect.value[1].startsWith('SYNC')) {
|
|
||||||
for (const neId of neIdSelect.value) {
|
|
||||||
reqArr.push(
|
|
||||||
addNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neId,
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: data,
|
|
||||||
loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reqArr.push(
|
|
||||||
addNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neTypeSelect.value[1],
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: data,
|
|
||||||
loc,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 无请求提示
|
|
||||||
if (reqArr.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.neIdSyncPleace'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
arrayEditClose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
Promise.allSettled(reqArr)
|
|
||||||
.then(resArr => {
|
|
||||||
const rejected = resArr.find(res => res.status === 'rejected');
|
|
||||||
if (rejected) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.addItemErr'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
message.success({
|
|
||||||
content: t('views.ne.neConfig.addItemOk', {
|
|
||||||
num: modalState.title,
|
|
||||||
}),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const fulfilled = resArr.find(res => res.status === 'fulfilled');
|
|
||||||
if (fulfilled) {
|
|
||||||
fnActiveConfigNode('#');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
arrayEditClose();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
arrayChildState,
|
|
||||||
arrayChildExpand,
|
|
||||||
arrayChildEdit,
|
|
||||||
arrayChildEditOk,
|
|
||||||
arrayChildDelete,
|
|
||||||
arrayChildAdd,
|
|
||||||
arrayChildAddOk,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,187 +0,0 @@
|
|||||||
import { editNeConfigData } from '@/api/ne/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, neTypeSelect, neIdSelect, ruleVerification}
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export default function useConfigList({
|
|
||||||
t,
|
|
||||||
treeState,
|
|
||||||
neTypeSelect,
|
|
||||||
neIdSelect,
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 请求
|
|
||||||
const reqArr = [];
|
|
||||||
if (neTypeSelect.value[1].startsWith('SYNC')) {
|
|
||||||
for (const neId of neIdSelect.value) {
|
|
||||||
reqArr.push(
|
|
||||||
editNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neId,
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: {
|
|
||||||
[from['name']]: from['value'],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reqArr.push(
|
|
||||||
editNeConfigData({
|
|
||||||
neType: neTypeSelect.value[0],
|
|
||||||
neId: neTypeSelect.value[1],
|
|
||||||
paramName: treeState.selectNode.paramName,
|
|
||||||
paramData: {
|
|
||||||
[from['name']]: from['value'],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 无请求提示
|
|
||||||
if (reqArr.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.neIdSyncPleace'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
listState.confirmLoading = false;
|
|
||||||
listState.editRecord = {};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
listState.confirmLoading = true;
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
Promise.allSettled(reqArr)
|
|
||||||
.then(resArr => {
|
|
||||||
const rejected = resArr.find(res => res.status === 'rejected');
|
|
||||||
if (rejected) {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.ne.neConfig.updateValueErr'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
message.success({
|
|
||||||
content: t('views.ne.neConfig.updateValue', {
|
|
||||||
num: from['display'],
|
|
||||||
}),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const fulfilled = resArr.find(res => res.status === 'fulfilled');
|
|
||||||
if (fulfilled) {
|
|
||||||
// 改变表格数据
|
|
||||||
const item = listState.data.find(
|
|
||||||
(item: Record<string, any>) => from['name'] === item['name']
|
|
||||||
);
|
|
||||||
if (item) {
|
|
||||||
Object.assign(item, listState.editRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.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,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -113,7 +113,7 @@ let modalState: ModalStateType = reactive({
|
|||||||
neAddress: '',
|
neAddress: '',
|
||||||
dn: '',
|
dn: '',
|
||||||
vendorName: '',
|
vendorName: '',
|
||||||
province: 'Area',
|
province: '',
|
||||||
remark: '',
|
remark: '',
|
||||||
// 主机
|
// 主机
|
||||||
hosts: [
|
hosts: [
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ProModal } from 'antdv-pro-modal';
|
|||||||
import { message, Form } from 'ant-design-vue/es';
|
import { message, Form } from 'ant-design-vue/es';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { getOAMFile, saveOAMFile, serviceNeAction } from '@/api/ne/neInfo';
|
import { getOAMFile, saveOAMFile } from '@/api/ne/neInfo';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
const emit = defineEmits(['ok', 'cancel', 'update:open']);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -29,8 +29,8 @@ type ModalStateType = {
|
|||||||
openByEdit: boolean;
|
openByEdit: boolean;
|
||||||
/**标题 */
|
/**标题 */
|
||||||
title: string;
|
title: string;
|
||||||
/**是否重启 */
|
/**是否同步 */
|
||||||
restart: boolean;
|
sync: boolean;
|
||||||
/**表单数据 */
|
/**表单数据 */
|
||||||
from: Record<string, any>;
|
from: Record<string, any>;
|
||||||
/**确定按钮 loading */
|
/**确定按钮 loading */
|
||||||
@@ -41,7 +41,7 @@ type ModalStateType = {
|
|||||||
let modalState: ModalStateType = reactive({
|
let modalState: ModalStateType = reactive({
|
||||||
openByEdit: false,
|
openByEdit: false,
|
||||||
title: 'OAM Configuration',
|
title: 'OAM Configuration',
|
||||||
restart: false,
|
sync: true,
|
||||||
from: {
|
from: {
|
||||||
omcIP: '',
|
omcIP: '',
|
||||||
oamEnable: true,
|
oamEnable: true,
|
||||||
@@ -114,19 +114,12 @@ function fnModalOk() {
|
|||||||
neType: props.neType,
|
neType: props.neType,
|
||||||
neId: props.neId,
|
neId: props.neId,
|
||||||
content: from,
|
content: from,
|
||||||
sync: true,
|
sync: modalState.sync,
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
message.success(t('common.operateOk'), 3);
|
message.success(t('common.operateOk'), 3);
|
||||||
emit('ok');
|
emit('ok');
|
||||||
if (modalState.restart) {
|
|
||||||
serviceNeAction({
|
|
||||||
neType: props.neType,
|
|
||||||
neId: props.neId,
|
|
||||||
action: 'restart',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
fnModalCancel();
|
fnModalCancel();
|
||||||
} else {
|
} else {
|
||||||
message.error({
|
message.error({
|
||||||
@@ -152,7 +145,6 @@ function fnModalOk() {
|
|||||||
function fnModalCancel() {
|
function fnModalCancel() {
|
||||||
modalState.openByEdit = false;
|
modalState.openByEdit = false;
|
||||||
modalState.confirmLoading = false;
|
modalState.confirmLoading = false;
|
||||||
modalState.restart = false;
|
|
||||||
modalStateFrom.resetFields();
|
modalStateFrom.resetFields();
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
emit('update:open', false);
|
emit('update:open', false);
|
||||||
@@ -191,15 +183,15 @@ watch(
|
|||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.ne.neInfo.oam.restart')"
|
:label="t('views.ne.neInfo.oam.sync')"
|
||||||
name="restart"
|
name="sync"
|
||||||
:label-col="{ span: 6 }"
|
:label-col="{ span: 6 }"
|
||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-switch
|
<a-switch
|
||||||
:checked-children="t('common.switch.open')"
|
:checked-children="t('common.switch.open')"
|
||||||
:un-checked-children="t('common.switch.shut')"
|
:un-checked-children="t('common.switch.shut')"
|
||||||
v-model:checked="modalState.restart"
|
v-model:checked="modalState.sync"
|
||||||
></a-switch>
|
></a-switch>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
|||||||
@@ -237,13 +237,8 @@ function fnModalEditOk(from: Record<string, any>) {
|
|||||||
item.neName = from.neName;
|
item.neName = from.neName;
|
||||||
item.ip = from.ip;
|
item.ip = from.ip;
|
||||||
item.port = from.port;
|
item.port = from.port;
|
||||||
if (res.data.online) {
|
if (item.status !== '2') {
|
||||||
item.status = '1';
|
item.status = res.data.online ? '1' : '0';
|
||||||
if (res.data.standby) {
|
|
||||||
item.status = '3';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
item.status = '0';
|
|
||||||
}
|
}
|
||||||
Object.assign(item.serverState, res.data);
|
Object.assign(item.serverState, res.data);
|
||||||
const resouresUsage = parseResouresUsage(item.serverState);
|
const resouresUsage = parseResouresUsage(item.serverState);
|
||||||
@@ -362,38 +357,33 @@ function fnGetList(pageNum?: number) {
|
|||||||
if (pageNum) {
|
if (pageNum) {
|
||||||
queryParams.pageNum = pageNum;
|
queryParams.pageNum = pageNum;
|
||||||
}
|
}
|
||||||
listNeInfo(toRaw(queryParams))
|
listNeInfo(toRaw(queryParams)).then(res => {
|
||||||
.then(res => {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
// 取消勾选
|
||||||
// 取消勾选
|
if (tableState.selectedRowKeys.length > 0) {
|
||||||
if (tableState.selectedRowKeys.length > 0) {
|
tableState.selectedRowKeys = [];
|
||||||
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;
|
tablePagination.total = res.total;
|
||||||
})
|
// 遍历处理资源情况数值
|
||||||
.finally(() => {
|
tableState.data = res.rows.map(item => {
|
||||||
// 刷新缓存的网元信息
|
let resouresUsage = {
|
||||||
useNeInfoStore().fnRefreshNelist();
|
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;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**解析网元状态携带的资源利用率 */
|
/**解析网元状态携带的资源利用率 */
|
||||||
@@ -451,8 +441,13 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取列表数据
|
// 刷新缓存的网元信息
|
||||||
fnGetList();
|
useNeInfoStore()
|
||||||
|
.fnRefreshNelist()
|
||||||
|
.finally(() => {
|
||||||
|
// 获取列表数据
|
||||||
|
fnGetList();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -667,7 +662,15 @@ onMounted(() => {
|
|||||||
</a-divider>
|
</a-divider>
|
||||||
<div>
|
<div>
|
||||||
<span>{{ t('views.ne.neInfo.serviceState') }}:</span>
|
<span>{{ t('views.ne.neInfo.serviceState') }}:</span>
|
||||||
<DictTag :options="dict.neInfoStatus" :value="record.status" />
|
<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>
|
||||||
<div>
|
<div>
|
||||||
<span>{{ t('views.ne.neVersion.version') }}:</span>
|
<span>{{ t('views.ne.neVersion.version') }}:</span>
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ let tableColumns = ref<TableColumnsType>([
|
|||||||
title: t('views.ne.common.serialNum'),
|
title: t('views.ne.common.serialNum'),
|
||||||
dataIndex: 'serialNum',
|
dataIndex: 'serialNum',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 120,
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.ne.common.expiryDate'),
|
title: t('views.ne.common.expiryDate'),
|
||||||
@@ -126,12 +126,12 @@ let tableColumns = ref<TableColumnsType>([
|
|||||||
{
|
{
|
||||||
title: t('common.updateTime'),
|
title: t('common.updateTime'),
|
||||||
dataIndex: 'updateTime',
|
dataIndex: 'updateTime',
|
||||||
align: 'left',
|
align: 'center',
|
||||||
customRender(opt) {
|
customRender(opt) {
|
||||||
if (!opt.value) return '';
|
if (!opt.value) return '';
|
||||||
return parseDateToStr(opt.value);
|
return parseDateToStr(opt.value);
|
||||||
},
|
},
|
||||||
width: 200,
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('common.operate'),
|
title: t('common.operate'),
|
||||||
@@ -413,7 +413,7 @@ onMounted(() => {
|
|||||||
:loading="modalState.confirmLoading"
|
:loading="modalState.confirmLoading"
|
||||||
@click.prevent="fnRecordStateBatch()"
|
@click.prevent="fnRecordStateBatch()"
|
||||||
>
|
>
|
||||||
<template #icon><SyncOutlined /></template>
|
<template #icon><CloudSyncOutlined /></template>
|
||||||
{{ t('views.ne.neLicense.reloadBatch') }}
|
{{ t('views.ne.neLicense.reloadBatch') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
@@ -508,7 +508,7 @@ onMounted(() => {
|
|||||||
<a-tooltip placement="topRight">
|
<a-tooltip placement="topRight">
|
||||||
<template #title>{{ t('views.ne.neLicense.reload') }}</template>
|
<template #title>{{ t('views.ne.neLicense.reload') }}</template>
|
||||||
<a-button type="link" @click.prevent="fnRecordState(record)">
|
<a-button type="link" @click.prevent="fnRecordState(record)">
|
||||||
<template #icon><SyncOutlined /> </template>
|
<template #icon><CloudSyncOutlined /> </template>
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip placement="topRight">
|
<a-tooltip placement="topRight">
|
||||||
@@ -517,7 +517,7 @@ onMounted(() => {
|
|||||||
type="link"
|
type="link"
|
||||||
@click.prevent="fnModalVisibleByEdit(record.id)"
|
@click.prevent="fnModalVisibleByEdit(record.id)"
|
||||||
>
|
>
|
||||||
<template #icon><UploadOutlined /> </template>
|
<template #icon><CloudUploadOutlined /> </template>
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ let modalState: ModalStateType = reactive({
|
|||||||
neAddress: '',
|
neAddress: '',
|
||||||
dn: '-',
|
dn: '-',
|
||||||
vendorName: '-',
|
vendorName: '-',
|
||||||
province: 'Area',
|
province: '-',
|
||||||
// 主机
|
// 主机
|
||||||
hosts: [
|
hosts: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,10 +50,9 @@ let fromState = ref({
|
|||||||
ims_sip_ip: '192.168.8.110',
|
ims_sip_ip: '192.168.8.110',
|
||||||
upf_type: 'LightUPF',
|
upf_type: 'LightUPF',
|
||||||
upf_driver_type: 'vmxnet3',
|
upf_driver_type: 'vmxnet3',
|
||||||
upfn3_card_name: 'eth0',
|
upf_card_name: 'eth0',
|
||||||
upfn3_pci: '0000:00:00.0',
|
upfn3_pci: '0000:00:00.0',
|
||||||
upfn3_mac: '00:00:00:00:00:00',
|
upfn3_mac: '00:00:00:00:00:00',
|
||||||
upfn6_card_name: 'eth0',
|
|
||||||
upfn6_pci: '0000:00:00.0',
|
upfn6_pci: '0000:00:00.0',
|
||||||
upfn6_mac: '00:00:00:00:00:00',
|
upfn6_mac: '00:00:00:00:00:00',
|
||||||
},
|
},
|
||||||
@@ -244,12 +243,7 @@ watch(
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
:lg="12"
|
|
||||||
:md="12"
|
|
||||||
:xs="24"
|
|
||||||
v-if="fromState.external.upf_type === 'LightUPF'"
|
|
||||||
>
|
|
||||||
<a-form-item label="UE_POOL" name="external.ue_pool">
|
<a-form-item label="UE_POOL" name="external.ue_pool">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="fromState.external.ue_pool"
|
v-model:value="fromState.external.ue_pool"
|
||||||
@@ -266,94 +260,47 @@ watch(
|
|||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row>
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item label="N3_IP" name="external.upfn3_ip">
|
||||||
|
<a-input
|
||||||
|
v-model:value="fromState.external.upfn3_ip"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
:maxlength="50"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<a-tooltip placement="topLeft">
|
||||||
|
<template #title> netwrok ip </template>
|
||||||
|
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="N3_GW" name="external.upfn3_gw">
|
||||||
|
<a-input
|
||||||
|
v-model:value="fromState.external.upfn3_gw"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
:maxlength="50"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<a-tooltip placement="topLeft">
|
||||||
|
<template #title> geteway </template>
|
||||||
|
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col
|
<a-col
|
||||||
:lg="12"
|
:lg="12"
|
||||||
:md="12"
|
:md="12"
|
||||||
:xs="24"
|
:xs="24"
|
||||||
v-if="fromState.external.upf_type === 'StandardUPF'"
|
v-if="fromState.external.upf_type === 'StandardUPF'"
|
||||||
>
|
>
|
||||||
<a-form-item label="DRIVER_TYPE" name="external.upf_driver_type">
|
|
||||||
<a-select
|
|
||||||
v-model:value="fromState.external.upf_driver_type"
|
|
||||||
:placeholder="t('common.selectPlease')"
|
|
||||||
>
|
|
||||||
<a-select-option value="vmxnet3">vmxnet3</a-select-option>
|
|
||||||
<a-select-option value="dpdk">dpdk</a-select-option>
|
|
||||||
<a-select-option value="host">host</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
|
|
||||||
<a-row v-if="fromState.external.upf_type === 'LightUPF'">
|
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
|
||||||
<a-form-item label="N3_IP" name="external.upfn3_ip">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn3_ip"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<a-tooltip placement="topLeft">
|
|
||||||
<template #title> netwrok ip </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="N3_GW" name="external.upfn3_gw">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn3_gw"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<a-tooltip placement="topLeft">
|
|
||||||
<template #title> geteway </template>
|
|
||||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
|
|
||||||
<a-row v-if="fromState.external.upf_type === 'StandardUPF'">
|
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
|
||||||
<a-form-item label="N3_IP" name="external.upfn3_ip">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn3_ip"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<a-tooltip placement="topLeft">
|
|
||||||
<template #title> netwrok ip </template>
|
|
||||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="N3_GW" name="external.upfn3_gw">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn3_gw"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<a-tooltip placement="topLeft">
|
|
||||||
<template #title> geteway </template>
|
|
||||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="N3_PCI" name="external.upfn3_pci">
|
<a-form-item label="N3_PCI" name="external.upfn3_pci">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="fromState.external.upfn3_pci"
|
v-model:value="fromState.external.upfn3_pci"
|
||||||
@@ -391,86 +338,84 @@ watch(
|
|||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="N3_NIC_NAME" name="external.upfn3_card_name">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn3_card_name"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<a-tooltip placement="topLeft">
|
|
||||||
<template #title>
|
|
||||||
use `ip a` show info, to inet name
|
|
||||||
<br />
|
|
||||||
or <br />
|
|
||||||
use `lshw -class network -businfo` show device name
|
|
||||||
</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="N6_IP" name="external.upfn6_ip">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn6_ip"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="N6_GW" name="external.upfn6_gw">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn6_gw"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="N6_PCI" name="external.upfn6_pci">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn6_pci"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="N6_MAC" name="external.upfn6_mac">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn6_mac"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="N6_NIC_NAME" name="external.upfn6_card_name">
|
|
||||||
<a-input
|
|
||||||
v-model:value="fromState.external.upfn6_card_name"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('common.inputPlease')"
|
|
||||||
:maxlength="50"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<a-tooltip placement="topLeft">
|
|
||||||
<template #title>
|
|
||||||
use `ip a` show info, to inet name
|
|
||||||
<br />
|
|
||||||
or <br />
|
|
||||||
use `lshw -class network -businfo` show device name
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined style="opacity: 0.45; color: inherit" />
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
<template v-if="fromState.external.upf_type === 'StandardUPF'">
|
||||||
|
<a-row>
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item label="N6_IP" name="external.upfn6_ip">
|
||||||
|
<a-input
|
||||||
|
v-model:value="fromState.external.upfn6_ip"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
:maxlength="50"
|
||||||
|
>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="N6_GW" name="external.upfn6_gw">
|
||||||
|
<a-input
|
||||||
|
v-model:value="fromState.external.upfn6_gw"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
:maxlength="50"
|
||||||
|
>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="DRIVER_TYPE" name="external.upf_driver_type">
|
||||||
|
<a-select
|
||||||
|
v-model:value="fromState.external.upf_driver_type"
|
||||||
|
:placeholder="t('common.selectPlease')"
|
||||||
|
>
|
||||||
|
<a-select-option value="vmxnet3">vmxnet3</a-select-option>
|
||||||
|
<a-select-option value="dpdk">dpdk</a-select-option>
|
||||||
|
<a-select-option value="host">host</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item label="N6_PCI" name="external.upfn6_pci">
|
||||||
|
<a-input
|
||||||
|
v-model:value="fromState.external.upfn6_pci"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
:maxlength="50"
|
||||||
|
>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="N6_MAC" name="external.upfn6_mac">
|
||||||
|
<a-input
|
||||||
|
v-model:value="fromState.external.upfn6_mac"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
:maxlength="50"
|
||||||
|
>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="NIC_NAME" name="external.upf_card_name">
|
||||||
|
<a-input
|
||||||
|
v-model:value="fromState.external.upf_card_name"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
:maxlength="50"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<a-tooltip placement="topLeft">
|
||||||
|
<template #title>
|
||||||
|
use `ip a` show info, to inet name
|
||||||
|
<br />
|
||||||
|
or <br />
|
||||||
|
use `lshw -class network -businfo` show device name
|
||||||
|
</template>
|
||||||
|
<InfoCircleOutlined
|
||||||
|
style="opacity: 0.45; color: inherit"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</template>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|
||||||
<a-col :lg="8" :md="8" :xs="24">
|
<a-col :lg="8" :md="8" :xs="24">
|
||||||
|
|||||||
@@ -166,8 +166,8 @@ function fnBeforeUploadFile(file: FileType) {
|
|||||||
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
||||||
if (!['.deb', '.rpm'].includes(suff)) {
|
if (!['.deb', '.rpm'].includes(suff)) {
|
||||||
message.error(
|
message.error(
|
||||||
t('views.ne.neSoftware.fileTypeNotEq', {
|
t('views.configManage.softwareManage.onlyAble', {
|
||||||
txt: '(.deb、.rpm)',
|
fileText: '(.deb、.rpm)',
|
||||||
}),
|
}),
|
||||||
3
|
3
|
||||||
);
|
);
|
||||||
@@ -238,8 +238,8 @@ function fnBeforeUploadFileDep(file: FileType) {
|
|||||||
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
||||||
if (!['.deb', '.rpm'].includes(suff)) {
|
if (!['.deb', '.rpm'].includes(suff)) {
|
||||||
message.error(
|
message.error(
|
||||||
t('views.ne.neSoftware.fileTypeNotEq', {
|
t('views.configManage.softwareManage.onlyAble', {
|
||||||
txt: '(.deb、.rpm)',
|
fileText: '(.deb、.rpm)',
|
||||||
}),
|
}),
|
||||||
3
|
3
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -171,8 +171,8 @@ function fnBeforeUploadFile(file: FileType) {
|
|||||||
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
||||||
if (!['.deb', '.rpm'].includes(suff)) {
|
if (!['.deb', '.rpm'].includes(suff)) {
|
||||||
message.error(
|
message.error(
|
||||||
t('views.ne.neSoftware.fileTypeNotEq', {
|
t('views.configManage.softwareManage.onlyAble', {
|
||||||
txt: '(.deb、.rpm)',
|
fileText: '(.deb、.rpm)',
|
||||||
}),
|
}),
|
||||||
3
|
3
|
||||||
);
|
);
|
||||||
@@ -286,8 +286,8 @@ function fnBeforeUploadFileDep(file: FileType) {
|
|||||||
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
||||||
if (!['.deb', '.rpm'].includes(suff)) {
|
if (!['.deb', '.rpm'].includes(suff)) {
|
||||||
message.error(
|
message.error(
|
||||||
t('views.ne.neSoftware.fileTypeNotEq', {
|
t('views.configManage.softwareManage.onlyAble', {
|
||||||
txt: '(.deb、.rpm)',
|
fileText: '(.deb、.rpm)',
|
||||||
}),
|
}),
|
||||||
3
|
3
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ let tableColumns = ref<TableColumnsType>([
|
|||||||
{
|
{
|
||||||
title: t('views.ne.neVersion.preVersion'),
|
title: t('views.ne.neVersion.preVersion'),
|
||||||
dataIndex: 'preVersion',
|
dataIndex: 'preVersion',
|
||||||
key: 'preVersion',
|
|
||||||
align: 'left',
|
align: 'left',
|
||||||
width: 150,
|
width: 150,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
@@ -305,10 +304,6 @@ function fnRecordVersion(
|
|||||||
message.warning(t('views.ne.neVersion.rollbackTipEmpty'), 3);
|
message.warning(t('views.ne.neVersion.rollbackTipEmpty'), 3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (row.prePath === '' || row.prePath === '-') {
|
|
||||||
message.warning(t('views.ne.neVersion.noPath'), 3);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (row.preVersion === row.version) {
|
if (row.preVersion === row.version) {
|
||||||
contentTip = t('views.ne.neVersion.rollbackTipEqual');
|
contentTip = t('views.ne.neVersion.rollbackTipEqual');
|
||||||
}
|
}
|
||||||
@@ -527,7 +522,8 @@ onMounted(() => {
|
|||||||
type="primary"
|
type="primary"
|
||||||
:disabled="tableState.selectedRowKeys.length > 1"
|
:disabled="tableState.selectedRowKeys.length > 1"
|
||||||
@click.prevent="
|
@click.prevent="
|
||||||
() => (modalState.openByMoreFile = !modalState.openByMoreFile)
|
() =>
|
||||||
|
(modalState.openByMoreFile = !modalState.openByMoreFile)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #icon><UploadOutlined /></template>
|
<template #icon><UploadOutlined /></template>
|
||||||
@@ -619,21 +615,6 @@ onMounted(() => {
|
|||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
<DictTag :options="dictStatus" :value="record.status" />
|
<DictTag :options="dictStatus" :value="record.status" />
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'preVersion'">
|
|
||||||
{{ record.preVersion }}
|
|
||||||
<a-tooltip
|
|
||||||
placement="topRight"
|
|
||||||
v-if="
|
|
||||||
record.preVersion &&
|
|
||||||
(record.prePath === '' || record.prePath === '-')
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
{{ t('views.ne.neVersion.noPath') }}
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'id'">
|
<template v-if="column.key === 'id'">
|
||||||
<a-space :size="8" align="center">
|
<a-space :size="8" align="center">
|
||||||
<a-tooltip placement="topRight">
|
<a-tooltip placement="topRight">
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import {
|
|||||||
listUDMAuth,
|
listUDMAuth,
|
||||||
} from '@/api/neData/udm_auth';
|
} from '@/api/neData/udm_auth';
|
||||||
import { uploadFile } from '@/api/tool/file';
|
import { uploadFile } from '@/api/tool/file';
|
||||||
import { getNeViewFile } from '@/api/tool/neFile';
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
/**网元参数 */
|
/**网元参数 */
|
||||||
@@ -99,6 +98,12 @@ let tableColumns = ref<ColumnsType>([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
width: 80,
|
width: 80,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Status',
|
||||||
|
dataIndex: 'status',
|
||||||
|
align: 'center',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// title: 'KI',
|
// title: 'KI',
|
||||||
// dataIndex: 'ki',
|
// dataIndex: 'ki',
|
||||||
@@ -593,8 +598,6 @@ type ModalUploadImportStateType = {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
/**上传结果信息 */
|
/**上传结果信息 */
|
||||||
msg: string;
|
msg: string;
|
||||||
/**含失败信息 */
|
|
||||||
hasFail: boolean;
|
|
||||||
/**导入类型 */
|
/**导入类型 */
|
||||||
typeOptions: { label: string; value: string }[];
|
typeOptions: { label: string; value: string }[];
|
||||||
/**表单 */
|
/**表单 */
|
||||||
@@ -607,7 +610,6 @@ let uploadImportState: ModalUploadImportStateType = reactive({
|
|||||||
title: t('components.UploadModal.uploadTitle'),
|
title: t('components.UploadModal.uploadTitle'),
|
||||||
loading: false,
|
loading: false,
|
||||||
msg: '',
|
msg: '',
|
||||||
hasFail: false,
|
|
||||||
typeOptions: [
|
typeOptions: [
|
||||||
{ label: 'Default', value: 'default' },
|
{ label: 'Default', value: 'default' },
|
||||||
{ label: 'K4', value: 'k4' },
|
{ label: 'K4', value: 'k4' },
|
||||||
@@ -624,37 +626,9 @@ function fnModalUploadImportTypeChange() {
|
|||||||
uploadImportState.msg = '';
|
uploadImportState.msg = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**对话框表格信息导入失败原因 */
|
|
||||||
function fnModalUploadImportFailReason() {
|
|
||||||
const neId = queryParams.neId;
|
|
||||||
if (!neId) return;
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
getNeViewFile({
|
|
||||||
neType: 'UDM',
|
|
||||||
neId: neId,
|
|
||||||
path: '/tmp',
|
|
||||||
fileName: 'import_authdata_err_records.txt',
|
|
||||||
})
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success(t('common.operateOk'), 3);
|
|
||||||
const blob = new Blob([res.data], {
|
|
||||||
type: 'text/plain',
|
|
||||||
});
|
|
||||||
saveAs(blob, `import_authdata_err_records_${Date.now()}.txt`);
|
|
||||||
} else {
|
|
||||||
message.error(`${res.msg}`, 3);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**对话框表格信息导入弹出窗口 */
|
/**对话框表格信息导入弹出窗口 */
|
||||||
function fnModalUploadImportOpen() {
|
function fnModalUploadImportOpen() {
|
||||||
uploadImportState.msg = '';
|
uploadImportState.msg = '';
|
||||||
uploadImportState.hasFail = false;
|
|
||||||
uploadImportState.from.typeVal = 'default';
|
uploadImportState.from.typeVal = 'default';
|
||||||
uploadImportState.from.typeData = undefined;
|
uploadImportState.from.typeData = undefined;
|
||||||
uploadImportState.loading = false;
|
uploadImportState.loading = false;
|
||||||
@@ -701,14 +675,6 @@ function fnModalUploadImportUpload(file: File) {
|
|||||||
.then(res => {
|
.then(res => {
|
||||||
if (!res) return;
|
if (!res) return;
|
||||||
uploadImportState.msg = res.msg;
|
uploadImportState.msg = res.msg;
|
||||||
const regex = /fail num: (\d+)/;
|
|
||||||
const match = res.msg.match(regex);
|
|
||||||
if (match) {
|
|
||||||
const failNum = Number(match[1]);
|
|
||||||
uploadImportState.hasFail = failNum > 0;
|
|
||||||
} else {
|
|
||||||
uploadImportState.hasFail = false;
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
hide();
|
hide();
|
||||||
@@ -1007,7 +973,25 @@ onMounted(() => {
|
|||||||
:label-col="{ span: 6 }"
|
:label-col="{ span: 6 }"
|
||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-row v-show="!modalState.from.id">
|
<a-row>
|
||||||
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.neUser.auth.numAdd')"
|
||||||
|
name="num"
|
||||||
|
v-bind="modalStateFrom.validateInfos.num"
|
||||||
|
v-show="!modalState.from.id"
|
||||||
|
>
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="modalState.from.num"
|
||||||
|
style="width: 100%"
|
||||||
|
:min="1"
|
||||||
|
:max="10000"
|
||||||
|
placeholder="<=10000"
|
||||||
|
></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row>
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="IMSI"
|
label="IMSI"
|
||||||
@@ -1035,20 +1019,11 @@ onMounted(() => {
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="12" :md="12" :xs="24">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item label="Status" name="status">
|
||||||
:label="t('views.neUser.auth.numAdd')"
|
<a-select value="1">
|
||||||
name="num"
|
<a-select-option value="1">Active</a-select-option>
|
||||||
v-bind="modalStateFrom.validateInfos.num"
|
<a-select-option value="0">Inactive</a-select-option>
|
||||||
:label-col="{ span: 10 }"
|
</a-select>
|
||||||
:labelWrap="false"
|
|
||||||
>
|
|
||||||
<a-input-number
|
|
||||||
v-model:value="modalState.from.num"
|
|
||||||
style="width: 100%"
|
|
||||||
:min="1"
|
|
||||||
:max="10000"
|
|
||||||
placeholder="<=10000"
|
|
||||||
></a-input-number>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
@@ -1081,8 +1056,6 @@ onMounted(() => {
|
|||||||
label="Algo Index"
|
label="Algo Index"
|
||||||
name="algo"
|
name="algo"
|
||||||
v-bind="modalStateFrom.validateInfos.algoIndex"
|
v-bind="modalStateFrom.validateInfos.algoIndex"
|
||||||
:label-col="{ span: 10 }"
|
|
||||||
:labelWrap="false"
|
|
||||||
>
|
>
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model:value="modalState.from.algoIndex"
|
v-model:value="modalState.from.algoIndex"
|
||||||
@@ -1168,7 +1141,7 @@ onMounted(() => {
|
|||||||
<a-form
|
<a-form
|
||||||
name="modalStateBatchDelFrom"
|
name="modalStateBatchDelFrom"
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
:label-col="{ span: 8 }"
|
:label-col="{ span: 6 }"
|
||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-row>
|
<a-row>
|
||||||
@@ -1237,23 +1210,13 @@ onMounted(() => {
|
|||||||
v-model:value="uploadImportState.from.typeData"
|
v-model:value="uploadImportState.from.typeData"
|
||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
/>
|
/>
|
||||||
<a-alert
|
<a-textarea
|
||||||
:message="uploadImportState.msg"
|
:disabled="true"
|
||||||
:type="uploadImportState.hasFail ? 'warning' : 'info'"
|
:hidden="!uploadImportState.msg"
|
||||||
v-show="uploadImportState.msg.length > 0"
|
:value="uploadImportState.msg"
|
||||||
>
|
:auto-size="{ minRows: 2, maxRows: 8 }"
|
||||||
<template #action>
|
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)"
|
||||||
<a-button
|
/>
|
||||||
size="small"
|
|
||||||
type="link"
|
|
||||||
danger
|
|
||||||
@click="fnModalUploadImportFailReason"
|
|
||||||
v-if="uploadImportState.hasFail"
|
|
||||||
>
|
|
||||||
{{ t('views.neUser.auth.importFail') }}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</a-alert>
|
|
||||||
</template>
|
</template>
|
||||||
</UploadModal>
|
</UploadModal>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
|
|||||||
@@ -314,7 +314,6 @@ onMounted(() => {
|
|||||||
v-model:value="queryParams.neType"
|
v-model:value="queryParams.neType"
|
||||||
:options="neCascaderOptions"
|
:options="neCascaderOptions"
|
||||||
:placeholder="t('common.selectPlease')"
|
:placeholder="t('common.selectPlease')"
|
||||||
@change="fnGetList(1)"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|||||||
@@ -1,356 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
|
||||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
|
||||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
|
||||||
import { Modal, message } from 'ant-design-vue/es';
|
|
||||||
import { parseDateToStr } from '@/utils/date-utils';
|
|
||||||
import {
|
|
||||||
getBakFile,
|
|
||||||
getBakFileList,
|
|
||||||
downFile,
|
|
||||||
delFile,
|
|
||||||
} from '@/api/neUser/exportFile';
|
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
|
||||||
import useI18n from '@/hooks/useI18n';
|
|
||||||
import saveAs from 'file-saver';
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
/**网元参数 */
|
|
||||||
let logSelect = ref<string[]>([]);
|
|
||||||
|
|
||||||
/**文件列表 */
|
|
||||||
let fileList = ref<any>([]);
|
|
||||||
|
|
||||||
/**查询参数 */
|
|
||||||
let queryParams = reactive({
|
|
||||||
/**读取路径 */
|
|
||||||
path: '',
|
|
||||||
/**表名 */
|
|
||||||
tableName: '',
|
|
||||||
/**当前页数 */
|
|
||||||
pageNum: 1,
|
|
||||||
/**每页条数 */
|
|
||||||
pageSize: 20,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格状态类型 */
|
|
||||||
type TabeStateType = {
|
|
||||||
/**加载等待 */
|
|
||||||
loading: boolean;
|
|
||||||
/**紧凑型 */
|
|
||||||
size: SizeType;
|
|
||||||
/**记录数据 */
|
|
||||||
data: object[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**表格状态 */
|
|
||||||
let tableState: TabeStateType = reactive({
|
|
||||||
loading: false,
|
|
||||||
size: 'small',
|
|
||||||
data: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**表格字段列 */
|
|
||||||
let tableColumns: ColumnsType = [
|
|
||||||
{
|
|
||||||
title: t('views.logManage.neFile.fileMode'),
|
|
||||||
dataIndex: 'fileMode',
|
|
||||||
align: 'center',
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.logManage.neFile.owner'),
|
|
||||||
dataIndex: 'owner',
|
|
||||||
align: 'left',
|
|
||||||
width: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.logManage.neFile.group'),
|
|
||||||
dataIndex: 'group',
|
|
||||||
align: 'left',
|
|
||||||
width: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.logManage.neFile.size'),
|
|
||||||
dataIndex: 'size',
|
|
||||||
align: 'left',
|
|
||||||
width: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.logManage.neFile.modifiedTime'),
|
|
||||||
dataIndex: 'modifiedTime',
|
|
||||||
align: 'left',
|
|
||||||
customRender(opt) {
|
|
||||||
if (!opt.value) return '';
|
|
||||||
return parseDateToStr(opt.value * 1000);
|
|
||||||
},
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.logManage.neFile.fileName'),
|
|
||||||
dataIndex: 'fileName',
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('common.operate'),
|
|
||||||
key: 'fileName',
|
|
||||||
align: 'center',
|
|
||||||
width: 100,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
/**表格分页器参数 */
|
|
||||||
let tablePagination = reactive({
|
|
||||||
/**当前页数 */
|
|
||||||
current: 1,
|
|
||||||
/**每页条数 */
|
|
||||||
pageSize: 20,
|
|
||||||
/**默认的每页条数 */
|
|
||||||
defaultPageSize: 20,
|
|
||||||
/**指定每页可以显示多少条 */
|
|
||||||
pageSizeOptions: ['10', '20', '50', '100'],
|
|
||||||
/**只有一页时是否隐藏分页器 */
|
|
||||||
hideOnSinglePage: false,
|
|
||||||
/**是否可以快速跳转至某页 */
|
|
||||||
showQuickJumper: true,
|
|
||||||
/**是否可以改变 pageSize */
|
|
||||||
showSizeChanger: true,
|
|
||||||
/**数据总数 */
|
|
||||||
total: 0,
|
|
||||||
showTotal: (total: number) => t('common.tablePaginationTotal', { total }),
|
|
||||||
onChange: (page: number, pageSize: number) => {
|
|
||||||
tablePagination.current = page;
|
|
||||||
tablePagination.pageSize = pageSize;
|
|
||||||
queryParams.pageNum = page;
|
|
||||||
queryParams.pageSize = pageSize;
|
|
||||||
fnGetList();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**下载触发等待 */
|
|
||||||
let downLoading = ref<boolean>(false);
|
|
||||||
|
|
||||||
/**删除触发等待 */
|
|
||||||
let delLoading = ref<boolean>(false);
|
|
||||||
|
|
||||||
/**信息文件下载 */
|
|
||||||
function fnDownloadFile(row: Record<string, any>) {
|
|
||||||
if (downLoading.value) return;
|
|
||||||
Modal.confirm({
|
|
||||||
title: t('common.tipTitle'),
|
|
||||||
content: t('views.logManage.exportFile.downTip', {
|
|
||||||
fileName: row.fileName,
|
|
||||||
}),
|
|
||||||
onOk() {
|
|
||||||
downLoading.value = true;
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
downFile({
|
|
||||||
path: queryParams.path,
|
|
||||||
fileName: row.fileName,
|
|
||||||
})
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success({
|
|
||||||
content: t('common.msgSuccess', {
|
|
||||||
msg: t('common.downloadText'),
|
|
||||||
}),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
saveAs(res.data, `${row.fileName}`);
|
|
||||||
} else {
|
|
||||||
message.error({
|
|
||||||
content: t('views.logManage.exportFile.downTipErr'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
downLoading.value = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function fnRecordDelete(row: Record<string, any>) {
|
|
||||||
if (delLoading.value) return;
|
|
||||||
Modal.confirm({
|
|
||||||
title: t('common.tipTitle'),
|
|
||||||
content: t('views.logManage.exportFile.deleteTip', {
|
|
||||||
fileName: row.fileName,
|
|
||||||
}),
|
|
||||||
onOk() {
|
|
||||||
const key = 'delFile';
|
|
||||||
delLoading.value = true;
|
|
||||||
message.loading({ content: t('common.loading'), key });
|
|
||||||
delFile({
|
|
||||||
fileName: row.fileName,
|
|
||||||
path: queryParams.path,
|
|
||||||
})
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success({
|
|
||||||
content: t('views.system.user.delSuss'),
|
|
||||||
key,
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
fnGetList();
|
|
||||||
} else {
|
|
||||||
message.error({
|
|
||||||
content: `${res.msg}`,
|
|
||||||
key: key,
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
delLoading.value = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**网元类型选择对应修改 */
|
|
||||||
function fnNeChange(keys: any, opt: any) {
|
|
||||||
queryParams.tableName = keys;
|
|
||||||
queryParams.path = opt.path;
|
|
||||||
fnGetList(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**查询备份信息列表, pageNum初始页数 */
|
|
||||||
function fnGetList(pageNum?: number) {
|
|
||||||
if (queryParams.tableName === '') {
|
|
||||||
message.warning({
|
|
||||||
content: t('views.logManage.exportFile.selectTip'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (tableState.loading) return;
|
|
||||||
tableState.loading = true;
|
|
||||||
if (pageNum) {
|
|
||||||
queryParams.pageNum = pageNum;
|
|
||||||
}
|
|
||||||
getBakFileList(toRaw(queryParams)).then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
tablePagination.total = res.total;
|
|
||||||
tableState.data = res.data;
|
|
||||||
if (
|
|
||||||
tablePagination.total <=
|
|
||||||
(queryParams.pageNum - 1) * tablePagination.pageSize &&
|
|
||||||
queryParams.pageNum !== 1
|
|
||||||
) {
|
|
||||||
tableState.loading = false;
|
|
||||||
fnGetList(queryParams.pageNum - 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message.error(res.msg, 3);
|
|
||||||
tablePagination.total = 0;
|
|
||||||
tableState.data = [];
|
|
||||||
}
|
|
||||||
tableState.loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getBakFile().then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
res.data.forEach((item: any) => {
|
|
||||||
fileList.value.push({
|
|
||||||
value: item.tableName,
|
|
||||||
label: item.tableDisplay,
|
|
||||||
path: item.filePath,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// .finally(() => {
|
|
||||||
// fnGetList();
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<PageContainer>
|
|
||||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
|
||||||
<!-- 插槽-卡片左侧侧 -->
|
|
||||||
<template #title>
|
|
||||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
|
||||||
<a-row :gutter="16" align="middle">
|
|
||||||
<a-col>
|
|
||||||
<span>{{ t('views.logManage.exportFile.fileName') }}:</span>
|
|
||||||
<a-select
|
|
||||||
v-model:value="logSelect"
|
|
||||||
:options="fileList"
|
|
||||||
@change="fnNeChange"
|
|
||||||
:allow-clear="false"
|
|
||||||
style="width: 200px"
|
|
||||||
/>
|
|
||||||
</a-col>
|
|
||||||
<template v-if="queryParams.path">
|
|
||||||
<span>{{ t('views.logManage.neFile.nePath') }}:</span>
|
|
||||||
<a-col>
|
|
||||||
<a-breadcrumb>
|
|
||||||
<a-breadcrumb-item>
|
|
||||||
{{ queryParams.path }}
|
|
||||||
</a-breadcrumb-item>
|
|
||||||
</a-breadcrumb>
|
|
||||||
</a-col>
|
|
||||||
</template>
|
|
||||||
</a-row>
|
|
||||||
</a-form>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 插槽-卡片右侧 -->
|
|
||||||
<template #extra>
|
|
||||||
<a-space :size="8" align="center">
|
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
|
||||||
<a-button type="text" @click.prevent="fnGetList()">
|
|
||||||
<template #icon><ReloadOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 表格列表 -->
|
|
||||||
<a-table
|
|
||||||
class="table"
|
|
||||||
row-key="fileName"
|
|
||||||
:columns="tableColumns"
|
|
||||||
:loading="tableState.loading"
|
|
||||||
:data-source="tableState.data"
|
|
||||||
:size="tableState.size"
|
|
||||||
:pagination="tablePagination"
|
|
||||||
:scroll="{ x: 800 }"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.key === 'fileName'">
|
|
||||||
<a-space :size="8" align="center">
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
:loading="downLoading"
|
|
||||||
@click.prevent="fnDownloadFile(record)"
|
|
||||||
v-if="record.fileType === 'file'"
|
|
||||||
>
|
|
||||||
<template #icon><DownloadOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
<a-button
|
|
||||||
type="link"
|
|
||||||
:loading="delLoading"
|
|
||||||
@click.prevent="fnRecordDelete(record)"
|
|
||||||
v-if="record.fileType === 'file'"
|
|
||||||
>
|
|
||||||
<template #icon><DeleteOutlined /></template>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</a-card>
|
|
||||||
</PageContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
|
||||||
+24
-107
@@ -25,7 +25,6 @@ import {
|
|||||||
updateUDMSub,
|
updateUDMSub,
|
||||||
} from '@/api/neData/udm_sub';
|
} from '@/api/neData/udm_sub';
|
||||||
import { uploadFile } from '@/api/tool/file';
|
import { uploadFile } from '@/api/tool/file';
|
||||||
import { getNeViewFile } from '@/api/tool/neFile';
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
/**网元参数 */
|
/**网元参数 */
|
||||||
@@ -277,7 +276,7 @@ let modalState: ModalStateType = reactive({
|
|||||||
//
|
//
|
||||||
smData: '',
|
smData: '',
|
||||||
smfSel: 'def_snssai',
|
smfSel: 'def_snssai',
|
||||||
cag: '',
|
cag: 'def_cag',
|
||||||
// 非字段
|
// 非字段
|
||||||
num: 1,
|
num: 1,
|
||||||
remark: '',
|
remark: '',
|
||||||
@@ -545,22 +544,8 @@ function transformFormData(data: any) {
|
|||||||
smStaticIpArr.push(dnnParts);
|
smStaticIpArr.push(dnnParts);
|
||||||
}
|
}
|
||||||
if (!dnnParts.includes('/') && !dnnParts.includes(':')) {
|
if (!dnnParts.includes('/') && !dnnParts.includes(':')) {
|
||||||
const pattern = /^(\d{1,3}\.){3}\d{1,3}$/;
|
//IPV4 没有/ 也没有:
|
||||||
if (pattern.test(dnnParts)) {
|
smStaticIpArr.push(dnnParts);
|
||||||
// 验证数值范围
|
|
||||||
const isValid = dnnParts.split('.').every((num: any) => {
|
|
||||||
const n = parseInt(num, 10);
|
|
||||||
return n >= 0 && n <= 255;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 只有当验证通过时才添加 IP
|
|
||||||
if (isValid) {
|
|
||||||
smStaticIpArr.push(dnnParts);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//无/ 无:也有可能为dnn的字符串
|
|
||||||
smallRowJson.dnn += '-' + dnnParts;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dnnParts.includes('/') && !dnnParts.includes(':')) {
|
if (dnnParts.includes('/') && !dnnParts.includes(':')) {
|
||||||
@@ -973,8 +958,6 @@ type ModalUploadImportStateType = {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
/**上传结果信息 */
|
/**上传结果信息 */
|
||||||
msg: string;
|
msg: string;
|
||||||
/**含失败信息 */
|
|
||||||
hasFail: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**对话框表格信息导入对象信息状态 */
|
/**对话框表格信息导入对象信息状态 */
|
||||||
@@ -983,40 +966,11 @@ let uploadImportState: ModalUploadImportStateType = reactive({
|
|||||||
title: t('components.UploadModal.uploadTitle'),
|
title: t('components.UploadModal.uploadTitle'),
|
||||||
loading: false,
|
loading: false,
|
||||||
msg: '',
|
msg: '',
|
||||||
hasFail: false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**对话框表格信息导入失败原因 */
|
|
||||||
function fnModalUploadImportFailReason() {
|
|
||||||
const neId = queryParams.neId;
|
|
||||||
if (!neId) return;
|
|
||||||
const hide = message.loading(t('common.loading'), 0);
|
|
||||||
getNeViewFile({
|
|
||||||
neType: 'UDM',
|
|
||||||
neId: neId,
|
|
||||||
path: '/tmp',
|
|
||||||
fileName: 'import_udmuser_err_records.txt',
|
|
||||||
})
|
|
||||||
.then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
|
||||||
message.success(t('common.operateOk'), 3);
|
|
||||||
const blob = new Blob([res.data], {
|
|
||||||
type: 'text/plain',
|
|
||||||
});
|
|
||||||
saveAs(blob, `import_udmuser_err_records_${Date.now()}.txt`);
|
|
||||||
} else {
|
|
||||||
message.error(`${res.msg}`, 3);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**对话框表格信息导入弹出窗口 */
|
/**对话框表格信息导入弹出窗口 */
|
||||||
function fnModalUploadImportOpen() {
|
function fnModalUploadImportOpen() {
|
||||||
uploadImportState.msg = '';
|
uploadImportState.msg = '';
|
||||||
uploadImportState.hasFail = false;
|
|
||||||
uploadImportState.loading = false;
|
uploadImportState.loading = false;
|
||||||
uploadImportState.open = true;
|
uploadImportState.open = true;
|
||||||
}
|
}
|
||||||
@@ -1060,14 +1014,6 @@ function fnModalUploadImportUpload(file: File) {
|
|||||||
.then(res => {
|
.then(res => {
|
||||||
if (!res) return;
|
if (!res) return;
|
||||||
uploadImportState.msg = res.msg;
|
uploadImportState.msg = res.msg;
|
||||||
const regex = /fail num: (\d+)/;
|
|
||||||
const match = res.msg.match(regex);
|
|
||||||
if (match) {
|
|
||||||
const failNum = Number(match[1]);
|
|
||||||
uploadImportState.hasFail = failNum > 0;
|
|
||||||
} else {
|
|
||||||
uploadImportState.hasFail = false;
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
hide();
|
hide();
|
||||||
@@ -1276,9 +1222,7 @@ onMounted(() => {
|
|||||||
:loading="modalState.loadDataLoading"
|
:loading="modalState.loadDataLoading"
|
||||||
@click.prevent="fnRecordDelete('0')"
|
@click.prevent="fnRecordDelete('0')"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon><DeleteOutlined /></template>
|
||||||
<DeleteOutlined />
|
|
||||||
</template>
|
|
||||||
{{ t('views.neUser.sub.checkDel') }}
|
{{ t('views.neUser.sub.checkDel') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
@@ -1294,9 +1238,7 @@ onMounted(() => {
|
|||||||
type="default"
|
type="default"
|
||||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon><ExportOutlined /></template>
|
||||||
<ExportOutlined />
|
|
||||||
</template>
|
|
||||||
{{ t('views.neUser.sub.checkExport') }}
|
{{ t('views.neUser.sub.checkExport') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
@@ -1318,24 +1260,19 @@ onMounted(() => {
|
|||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
<template #title>{{ t('common.reloadText') }}</template>
|
||||||
<a-button type="text" @click.prevent="fnGetList()">
|
<a-button type="text" @click.prevent="fnGetList()">
|
||||||
<template #icon>
|
<template #icon><ReloadOutlined /></template>
|
||||||
<ReloadOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<TableColumnsDnd
|
<TableColumnsDnd
|
||||||
cache-id="udmSubData"
|
cache-id="udmSubData"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
v-model:columns-dnd="tableColumnsDnd"
|
v-model:columns-dnd="tableColumnsDnd"
|
||||||
>
|
></TableColumnsDnd>
|
||||||
</TableColumnsDnd>
|
|
||||||
<a-tooltip placement="topRight">
|
<a-tooltip placement="topRight">
|
||||||
<template #title>{{ t('common.sizeText') }}</template>
|
<template #title>{{ t('common.sizeText') }}</template>
|
||||||
<a-dropdown placement="bottomRight" trigger="click">
|
<a-dropdown placement="bottomRight" trigger="click">
|
||||||
<a-button type="text">
|
<a-button type="text">
|
||||||
<template #icon>
|
<template #icon><ColumnHeightOutlined /></template>
|
||||||
<ColumnHeightOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
</a-button>
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<a-menu
|
<a-menu
|
||||||
@@ -1369,7 +1306,7 @@ onMounted(() => {
|
|||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ y: 'calc(100vh - 480px)' }"
|
:scroll="{ y: 'calc(100vh - 480px)' }"
|
||||||
@change="fnTableChange"
|
@change="fnTableChange"
|
||||||
@resizeColumn="(w: number, col: any) => (col.width = w)"
|
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||||
:row-selection="{
|
:row-selection="{
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
selectedRowKeys: tableState.selectedRowKeys,
|
selectedRowKeys: tableState.selectedRowKeys,
|
||||||
@@ -1443,13 +1380,12 @@ onMounted(() => {
|
|||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :lg="12" :md="12" :xs="24" v-show="!modalState.from.id">
|
<a-col :lg="12" :md="12" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label="t('views.neUser.sub.numAdd')"
|
:label="t('views.neUser.sub.numAdd')"
|
||||||
name="num"
|
name="num"
|
||||||
v-bind="modalStateFrom.validateInfos.num"
|
v-bind="modalStateFrom.validateInfos.num"
|
||||||
:label-col="{ span: 12 }"
|
v-show="!modalState.from.id"
|
||||||
:labelWrap="false"
|
|
||||||
>
|
>
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model:value="modalState.from.num"
|
v-model:value="modalState.from.num"
|
||||||
@@ -1568,11 +1504,7 @@ onMounted(() => {
|
|||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="4">
|
<a-col :span="4">
|
||||||
<a-tooltip title="Add DNN">
|
<a-tooltip title="Add DNN">
|
||||||
<a-button
|
<a-button shape="circle" @click="addSmallRow(row.id)">
|
||||||
shape="circle"
|
|
||||||
@click="addSmallRow(row.id)"
|
|
||||||
style="margin-left: 10px"
|
|
||||||
>
|
|
||||||
<template #icon><plus-square-outlined /></template>
|
<template #icon><plus-square-outlined /></template>
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
@@ -1594,7 +1526,7 @@ onMounted(() => {
|
|||||||
:key="String(smallRow.id)"
|
:key="String(smallRow.id)"
|
||||||
>
|
>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :lg="6" :md="6" :xs="24">
|
<a-col :lg="6" :md="7" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="DNN/APN"
|
label="DNN/APN"
|
||||||
name="dnn"
|
name="dnn"
|
||||||
@@ -1605,7 +1537,7 @@ onMounted(() => {
|
|||||||
<a-input v-model:value="smallRow.dnn" allow-clear></a-input>
|
<a-input v-model:value="smallRow.dnn" allow-clear></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="8" :md="8" :xs="24">
|
<a-col :lg="8" :md="6" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="Static IP"
|
label="Static IP"
|
||||||
name="smStaticIp"
|
name="smStaticIp"
|
||||||
@@ -1618,21 +1550,16 @@ onMounted(() => {
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="8" :md="8" :xs="24">
|
<a-col :lg="8" :md="8" :xs="24">
|
||||||
<a-form-item
|
<a-form-item label="Routing Behind MS IP" name="msIp">
|
||||||
label="Routing Behind MS IP"
|
|
||||||
style="margin-left: 10px"
|
|
||||||
name="msIp"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="smallRow.msIp" allow-clear></a-input>
|
<a-input v-model:value="smallRow.msIp" allow-clear></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :lg="2" :md="2" :xs="24" v-if="smallIndex !== 0">
|
<a-col :lg="1" :md="1" :xs="24" v-if="smallIndex !== 0">
|
||||||
<a-tooltip title="Delete DNN">
|
<a-tooltip title="Delete DNN">
|
||||||
<a-button
|
<a-button
|
||||||
danger
|
danger
|
||||||
shape="circle"
|
shape="circle"
|
||||||
@click="delDNN(smallIndex, row.id)"
|
@click="delDNN(smallIndex, row.id)"
|
||||||
style="margin-left: 10px"
|
|
||||||
>
|
>
|
||||||
<template #icon><close-square-outlined /></template>
|
<template #icon><close-square-outlined /></template>
|
||||||
</a-button>
|
</a-button>
|
||||||
@@ -2048,7 +1975,7 @@ onMounted(() => {
|
|||||||
<a-form
|
<a-form
|
||||||
name="modalStateBatchDelFrom"
|
name="modalStateBatchDelFrom"
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
:label-col="{ span: 8 }"
|
:label-col="{ span: 6 }"
|
||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-row>
|
<a-row>
|
||||||
@@ -2107,23 +2034,13 @@ onMounted(() => {
|
|||||||
:size="10"
|
:size="10"
|
||||||
>
|
>
|
||||||
<template #default>
|
<template #default>
|
||||||
<a-alert
|
<a-textarea
|
||||||
:message="uploadImportState.msg"
|
:disabled="true"
|
||||||
:type="uploadImportState.hasFail ? 'warning' : 'info'"
|
:hidden="!uploadImportState.msg"
|
||||||
v-show="uploadImportState.msg.length > 0"
|
:value="uploadImportState.msg"
|
||||||
>
|
:auto-size="{ minRows: 2, maxRows: 8 }"
|
||||||
<template #action>
|
style="background-color: transparent; color: rgba(0, 0, 0, 0.85)"
|
||||||
<a-button
|
/>
|
||||||
size="small"
|
|
||||||
type="link"
|
|
||||||
danger
|
|
||||||
@click="fnModalUploadImportFailReason"
|
|
||||||
v-if="uploadImportState.hasFail"
|
|
||||||
>
|
|
||||||
{{ t('views.neUser.auth.importFail') }}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</a-alert>
|
|
||||||
</template>
|
</template>
|
||||||
</UploadModal>
|
</UploadModal>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { message } from 'ant-design-vue/es';
|
|||||||
import { SizeType } from 'ant-design-vue/es/config-provider';
|
import { SizeType } from 'ant-design-vue/es/config-provider';
|
||||||
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
|
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
|
||||||
import { ColumnsType } from 'ant-design-vue/es/table';
|
import { ColumnsType } from 'ant-design-vue/es/table';
|
||||||
import { listSMFSubList } from '@/api/neData/smf';
|
import { listSMFSubscribers } from '@/api/neData/smf';
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
@@ -224,7 +224,7 @@ function fnGetList(pageNum?: number) {
|
|||||||
if (pageNum) {
|
if (pageNum) {
|
||||||
queryParams.pageNum = pageNum;
|
queryParams.pageNum = pageNum;
|
||||||
}
|
}
|
||||||
listSMFSubList(toRaw(queryParams)).then(res => {
|
listSMFSubscribers(toRaw(queryParams)).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||||
tablePagination.total = res.total;
|
tablePagination.total = res.total;
|
||||||
tableState.data = res.rows;
|
tableState.data = res.rows;
|
||||||
|
|||||||
@@ -154,9 +154,7 @@ function fnTableSize({ key }: MenuInfo) {
|
|||||||
function fnRecordDelete(row: Record<string, any>) {
|
function fnRecordDelete(row: Record<string, any>) {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: t('common.tipTitle'),
|
title: t('common.tipTitle'),
|
||||||
content: t('views.perfManage.customTarget.delCustomTip', {
|
content: t('views.perfManage.customTarget.delCustomTip', { num: row.kpiId }),
|
||||||
num: row.kpiId,
|
|
||||||
}),
|
|
||||||
onOk() {
|
onOk() {
|
||||||
const key = 'delThreshold';
|
const key = 'delThreshold';
|
||||||
message.loading({ content: t('common.loading'), key });
|
message.loading({ content: t('common.loading'), key });
|
||||||
@@ -387,10 +385,8 @@ function fnModalOk() {
|
|||||||
message.error(t('views.perfManage.customTarget.expressionNoIdTip'), 3);
|
message.error(t('views.perfManage.customTarget.expressionNoIdTip'), 3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//modalState.from.expression = result;
|
modalState.from.expression = result;
|
||||||
//const from = toRaw(modalState.from);
|
const from = toRaw(modalState.from);
|
||||||
const from = { ...toRaw(modalState.from) };
|
|
||||||
from.expression = result;
|
|
||||||
//return false;
|
//return false;
|
||||||
modalState.confirmLoading = true;
|
modalState.confirmLoading = true;
|
||||||
const perfTask = from.id ? updateCustom(from) : addCustom(from);
|
const perfTask = from.id ? updateCustom(from) : addCustom(from);
|
||||||
@@ -438,6 +434,7 @@ function fnModalCancel() {
|
|||||||
* 选择性能指标,填充进当前计算公式的值
|
* 选择性能指标,填充进当前计算公式的值
|
||||||
*/
|
*/
|
||||||
function fnSelectPer(s: any, option: any) {
|
function fnSelectPer(s: any, option: any) {
|
||||||
|
console.log(option);
|
||||||
modalState.from.expression += `'${option.label}'`;
|
modalState.from.expression += `'${option.label}'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,6 +695,7 @@ onMounted(() => {
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :lg="24" :md="24" :xs="24">
|
<a-col :lg="24" :md="24" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
@@ -726,7 +724,6 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="modalState.from.expression"
|
v-model:value="modalState.from.expression"
|
||||||
:disabled="modalState.from.id"
|
|
||||||
:maxlength="1024"
|
:maxlength="1024"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
allow-clear
|
allow-clear
|
||||||
@@ -783,6 +780,7 @@ onMounted(() => {
|
|||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
|
|
||||||
</a-auto-complete>
|
</a-auto-complete>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import {
|
|||||||
nextTick,
|
nextTick,
|
||||||
onBeforeUnmount,
|
onBeforeUnmount,
|
||||||
h,
|
h,
|
||||||
watch,
|
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { message, Modal, TableColumnType } from 'ant-design-vue/es';
|
import { message, Modal, TableColumnType } from 'ant-design-vue/es';
|
||||||
@@ -44,8 +43,6 @@ import { generateColorRGBA } from '@/utils/generate-utils';
|
|||||||
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
import { OptionsType, WS } from '@/plugins/ws-websocket';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { LineOutlined } from '@ant-design/icons-vue';
|
import { LineOutlined } from '@ant-design/icons-vue';
|
||||||
import useLayoutStore from '@/store/modules/layout';
|
|
||||||
const layoutStore = useLayoutStore();
|
|
||||||
const neInfoStore = useNeInfoStore();
|
const neInfoStore = useNeInfoStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t, currentLocale } = useI18n();
|
const { t, currentLocale } = useI18n();
|
||||||
@@ -219,25 +216,12 @@ const statsColumns: TableColumnType<any>[] = [
|
|||||||
key: 'title',
|
key: 'title',
|
||||||
width: '65%',
|
width: '65%',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: t('views.perfManage.kpiOverView.totalValue'),
|
|
||||||
dataIndex: 'total',
|
|
||||||
key: 'total',
|
|
||||||
width: '24%',
|
|
||||||
sortDirections: ['ascend', 'descend'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('views.perfManage.kpiOverView.avgValue'),
|
|
||||||
dataIndex: 'avg',
|
|
||||||
key: 'avg',
|
|
||||||
width: '24%',
|
|
||||||
sortDirections: ['ascend', 'descend'],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: t('views.perfManage.kpiOverView.maxValue'),
|
title: t('views.perfManage.kpiOverView.maxValue'),
|
||||||
dataIndex: 'max',
|
dataIndex: 'max',
|
||||||
key: 'max',
|
key: 'max',
|
||||||
width: '17%',
|
width: '17%',
|
||||||
|
sorter: (a: any, b: any) => a.max - b.max, // 添加排序函数
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -245,6 +229,7 @@ const statsColumns: TableColumnType<any>[] = [
|
|||||||
dataIndex: 'min',
|
dataIndex: 'min',
|
||||||
key: 'min',
|
key: 'min',
|
||||||
width: '17%',
|
width: '17%',
|
||||||
|
sorter: (a: any, b: any) => a.min - b.min, // 添加排序函数
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -404,23 +389,11 @@ function fnGetList() {
|
|||||||
const values = tableState.data.map((item: any) => {
|
const values = tableState.data.map((item: any) => {
|
||||||
return item[columns.key] ? Number(item[columns.key]) : 0;
|
return item[columns.key] ? Number(item[columns.key]) : 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 计算总值
|
|
||||||
const total = Number(
|
|
||||||
values.reduce((sum, val) => sum + val, 0).toFixed(2)
|
|
||||||
);
|
|
||||||
|
|
||||||
// 计算平均值
|
|
||||||
const avg =
|
|
||||||
values.length > 0 ? Number((total / values.length).toFixed(2)) : 0;
|
|
||||||
|
|
||||||
kpiStats.value.push({
|
kpiStats.value.push({
|
||||||
kpiId: columns.key,
|
kpiId: columns.key,
|
||||||
title: columns.title,
|
title: columns.title,
|
||||||
max: values.length > 0 ? Math.max(...values) : 0,
|
max: values.length > 0 ? Math.max(...values) : 0,
|
||||||
min: values.length > 0 ? Math.min(...values) : 0,
|
min: values.length > 0 ? Math.min(...values) : 0,
|
||||||
avg: avg,
|
|
||||||
total: total,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,7 +418,6 @@ function fnRanderChart() {
|
|||||||
position: function (pt: any) {
|
position: function (pt: any) {
|
||||||
return [pt[0], '10%'];
|
return [pt[0], '10%'];
|
||||||
},
|
},
|
||||||
confine: true, // 限制 tooltip 显示范围
|
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
//x类别轴
|
//x类别轴
|
||||||
@@ -528,9 +500,6 @@ function fnRanderChartData() {
|
|||||||
key: `${columns.key}`,
|
key: `${columns.key}`,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
symbolSize: 6,
|
|
||||||
smooth: 0.6,
|
|
||||||
showSymbol: true,
|
|
||||||
sampling: 'lttb',
|
sampling: 'lttb',
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: color,
|
color: color,
|
||||||
@@ -580,34 +549,8 @@ function fnRanderChartData() {
|
|||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
axisLabel: {
|
|
||||||
color:
|
|
||||||
document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? '#CACADA'
|
|
||||||
: '#333',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: getSplitLineColor(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data: chartDataXAxisData,
|
data: chartDataXAxisData,
|
||||||
},
|
},
|
||||||
yAxis: {
|
|
||||||
axisLabel: {
|
|
||||||
color:
|
|
||||||
document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? '#CACADA'
|
|
||||||
: '#333',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: getSplitLineColor(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
series: chartDataYSeriesData,
|
series: chartDataYSeriesData,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -704,38 +647,29 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 添加一个变量来跟踪当前选中的行
|
// 添加一个变量来跟踪当前选中的行
|
||||||
const selectedRow = ref<string[]>([]);
|
const selectedRow = ref<string | null>(null);
|
||||||
|
|
||||||
// 添加处理行点击的方法
|
// 添加处理行点击的方法
|
||||||
function handleRowClick(record: any) {
|
function handleRowClick(record: any) {
|
||||||
const index = selectedRow.value.indexOf(record.kpiId);
|
if (selectedRow.value === record.kpiId) {
|
||||||
|
// 如果点击的是当前选中的行,则取消选中
|
||||||
// 如果已经选中,取消选中
|
selectedRow.value = null;
|
||||||
if (index > -1) {
|
// 更新图表,显示所有指标
|
||||||
selectedRow.value.splice(index, 1);
|
for (let key in chartLegendSelected) {
|
||||||
chartLegendSelected[record.title] = false;
|
|
||||||
} else {
|
|
||||||
// 添加新的选中项
|
|
||||||
selectedRow.value.push(record.kpiId);
|
|
||||||
|
|
||||||
// 如果只有一个选中项,重置为 false
|
|
||||||
if (selectedRow.value.length === 1) {
|
|
||||||
Object.keys(chartLegendSelected).forEach(key => {
|
|
||||||
chartLegendSelected[key] = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
chartLegendSelected[record.title] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有选中项,设置所有图例为 true
|
|
||||||
if (selectedRow.value.length === 0) {
|
|
||||||
Object.keys(chartLegendSelected).forEach(key => {
|
|
||||||
chartLegendSelected[key] = true;
|
chartLegendSelected[key] = true;
|
||||||
});
|
}
|
||||||
|
} else {
|
||||||
|
// 选中新行
|
||||||
|
selectedRow.value = record.kpiId;
|
||||||
|
// 更新图表,只显示选中的指标
|
||||||
|
for (let key in chartLegendSelected) {
|
||||||
|
if (key === record.title) {
|
||||||
|
chartLegendSelected[key] = true;
|
||||||
|
} else {
|
||||||
|
chartLegendSelected[key] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新图表设置
|
|
||||||
kpiChart.value.setOption({
|
kpiChart.value.setOption({
|
||||||
legend: {
|
legend: {
|
||||||
selected: chartLegendSelected,
|
selected: chartLegendSelected,
|
||||||
@@ -743,63 +677,6 @@ function handleRowClick(record: any) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加一个函数来获取当前主题下的网格线颜色
|
|
||||||
function getSplitLineColor() {
|
|
||||||
return document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? '#333333'
|
|
||||||
: '#E8E8E8'; // 亮色模式返回 undefined,使用默认颜色
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听主题变化
|
|
||||||
watch(
|
|
||||||
() => layoutStore.proConfig.theme, // 监听的值
|
|
||||||
newValue => {
|
|
||||||
if (kpiChart.value) {
|
|
||||||
const splitLineColor = getSplitLineColor();
|
|
||||||
// 绘制图数据
|
|
||||||
kpiChart.value.setOption({
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
position: function (pt: any) {
|
|
||||||
return [pt[0], '10%'];
|
|
||||||
},
|
|
||||||
confine: true, // 限制 tooltip 显示范围
|
|
||||||
backgroundColor:
|
|
||||||
newValue === 'dark'
|
|
||||||
? 'rgba(48, 48, 48, 0.8)'
|
|
||||||
: 'rgba(255, 255, 255, 0.9)',
|
|
||||||
borderColor: newValue === 'dark' ? '#555' : '#ddd',
|
|
||||||
textStyle: {
|
|
||||||
color: newValue === 'dark' ? '#CACADA' : '#333',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
axisLabel: {
|
|
||||||
color: newValue === 'dark' ? '#CACADA' : '#333',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: splitLineColor,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
axisLabel: {
|
|
||||||
color: newValue === 'dark' ? '#CACADA' : '#333',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: splitLineColor,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 目前支持的 AMF AUSF MME MOCNGW NSSF SMF UDM UPF PCF
|
// 目前支持的 AMF AUSF MME MOCNGW NSSF SMF UDM UPF PCF
|
||||||
// 获取网元网元列表
|
// 获取网元网元列表
|
||||||
@@ -837,16 +714,11 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询当前小时
|
// 查询当前小时
|
||||||
const now = new Date();
|
const nowDate: Date = new Date();
|
||||||
now.setMinutes(0, 0, 0);
|
nowDate.setMinutes(0, 0, 0);
|
||||||
// 设置起始时间为整点前一小时
|
queryRangePicker.value[0] = `${nowDate.getTime()}`;
|
||||||
const startTime = new Date(now);
|
nowDate.setMinutes(59, 59, 59);
|
||||||
startTime.setHours(now.getHours() - 1);
|
queryRangePicker.value[1] = `${nowDate.getTime()}`;
|
||||||
queryRangePicker.value[0] = `${startTime.getTime()}`;
|
|
||||||
// 设置结束时间为整点
|
|
||||||
const endTime = new Date(now);
|
|
||||||
endTime.setMinutes(59, 59, 59);
|
|
||||||
queryRangePicker.value[1] = `${endTime.getTime()}`;
|
|
||||||
fnGetListTitle();
|
fnGetListTitle();
|
||||||
// 绘图
|
// 绘图
|
||||||
fnRanderChart();
|
fnRanderChart();
|
||||||
@@ -928,9 +800,7 @@ onBeforeUnmount(() => {
|
|||||||
:loading="tableState.loading"
|
:loading="tableState.loading"
|
||||||
@click.prevent="fnGetListTitle()"
|
@click.prevent="fnGetListTitle()"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon><SearchOutlined /></template>
|
||||||
<SearchOutlined />
|
|
||||||
</template>
|
|
||||||
{{ t('common.search') }}
|
{{ t('common.search') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
@@ -949,9 +819,7 @@ onBeforeUnmount(() => {
|
|||||||
:loading="tableState.loading"
|
:loading="tableState.loading"
|
||||||
@click.prevent="fnChangShowType()"
|
@click.prevent="fnChangShowType()"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon> <AreaChartOutlined /> </template>
|
||||||
<AreaChartOutlined />
|
|
||||||
</template>
|
|
||||||
{{
|
{{
|
||||||
tableState.showTable
|
tableState.showTable
|
||||||
? t('views.perfManage.goldTarget.kpiChartTitle')
|
? t('views.perfManage.goldTarget.kpiChartTitle')
|
||||||
@@ -978,13 +846,12 @@ onBeforeUnmount(() => {
|
|||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
<template #title>{{ t('common.reloadText') }}</template>
|
||||||
<a-button type="text" @click.prevent="fnGetList()">
|
<a-button type="text" @click.prevent="fnGetList()">
|
||||||
<template #icon>
|
<template #icon><ReloadOutlined /></template>
|
||||||
<ReloadOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<TableColumnsDnd
|
<TableColumnsDnd
|
||||||
v-if="tableColumns.length > 0"
|
v-if="tableColumns.length > 0"
|
||||||
|
:cache-id="`kpiTarget_${state.neType[0]}`"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
v-model:columns-dnd="tableColumnsDnd"
|
v-model:columns-dnd="tableColumnsDnd"
|
||||||
></TableColumnsDnd>
|
></TableColumnsDnd>
|
||||||
@@ -992,9 +859,7 @@ onBeforeUnmount(() => {
|
|||||||
<template #title>{{ t('common.sizeText') }}</template>
|
<template #title>{{ t('common.sizeText') }}</template>
|
||||||
<a-dropdown trigger="click" placement="bottomRight">
|
<a-dropdown trigger="click" placement="bottomRight">
|
||||||
<a-button type="text">
|
<a-button type="text">
|
||||||
<template #icon>
|
<template #icon><ColumnHeightOutlined /></template>
|
||||||
<ColumnHeightOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
</a-button>
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<a-menu
|
<a-menu
|
||||||
@@ -1056,7 +921,7 @@ onBeforeUnmount(() => {
|
|||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: tableColumnsDnd.length * 200, y: 'calc(100vh - 480px)' }"
|
:scroll="{ x: tableColumnsDnd.length * 200, y: 'calc(100vh - 480px)' }"
|
||||||
@resizeColumn="(w: number, col: any) => (col.width = w)"
|
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||||
:show-expand-column="false"
|
:show-expand-column="false"
|
||||||
@change="fnTableChange"
|
@change="fnTableChange"
|
||||||
>
|
>
|
||||||
@@ -1083,67 +948,12 @@ onBeforeUnmount(() => {
|
|||||||
:scroll="{ y: 250 }"
|
:scroll="{ y: 250 }"
|
||||||
size="small"
|
size="small"
|
||||||
:custom-row="
|
:custom-row="
|
||||||
(record:any) => ({
|
record => ({
|
||||||
onClick: () => handleRowClick(record),
|
onClick: () => handleRowClick(record),
|
||||||
class: selectedRow.includes(record.kpiId) ? 'selected-row' : '',
|
class: record.kpiId === selectedRow ? 'selected-row' : '',
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
>
|
/>
|
||||||
<template #headerCell="{ column }">
|
|
||||||
<template v-if="column.key === 'total'">
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.totalValue') }}
|
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.totalValueTip') }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'avg'">
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.avgValue') }}
|
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.avgValueTip') }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'max'">
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.maxValue') }}
|
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.maxValueTip') }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'min'">
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.minValue') }}
|
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.minValueTip') }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import {
|
|||||||
nextTick,
|
nextTick,
|
||||||
onBeforeUnmount,
|
onBeforeUnmount,
|
||||||
h,
|
h,
|
||||||
watch,
|
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
import { message, Modal, TableColumnType } from 'ant-design-vue/es';
|
import { message, Modal, TableColumnType } from 'ant-design-vue/es';
|
||||||
@@ -46,8 +45,6 @@ import { OptionsType, WS } from '@/plugins/ws-websocket';
|
|||||||
import { LineOutlined } from '@ant-design/icons-vue';
|
import { LineOutlined } from '@ant-design/icons-vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
import useLayoutStore from '@/store/modules/layout';
|
|
||||||
const layoutStore = useLayoutStore();
|
|
||||||
const neInfoStore = useNeInfoStore();
|
const neInfoStore = useNeInfoStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t, currentLocale } = useI18n();
|
const { t, currentLocale } = useI18n();
|
||||||
@@ -85,19 +82,12 @@ let queryRangePicker = ref<[string, string]>(['', '']);
|
|||||||
|
|
||||||
/**时间选择 */
|
/**时间选择 */
|
||||||
const ranges = ref([
|
const ranges = ref([
|
||||||
{
|
{label:t('views.perfManage.customTarget.sixHoursAgo'),value:[dayjs().subtract(6, 'hours'),
|
||||||
label: t('views.perfManage.customTarget.sixHoursAgo'),
|
dayjs(),]},
|
||||||
value: [dayjs().subtract(6, 'hours'), dayjs()],
|
{label:t('views.perfManage.customTarget.threeHoursAgo'),value:[dayjs().subtract(3, 'hours'),
|
||||||
},
|
dayjs(),]},
|
||||||
{
|
{label:t('views.monitor.monitor.today'),value:[dayjs().startOf('day'), dayjs()]},
|
||||||
label: t('views.perfManage.customTarget.threeHoursAgo'),
|
])
|
||||||
value: [dayjs().subtract(3, 'hours'), dayjs()],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('views.monitor.monitor.today'),
|
|
||||||
value: [dayjs().startOf('day'), dayjs()],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
/**表格字段列 */
|
/**表格字段列 */
|
||||||
let tableColumns = ref<any[]>([]);
|
let tableColumns = ref<any[]>([]);
|
||||||
@@ -213,13 +203,6 @@ const kpiColors = new Map<string, string>();
|
|||||||
//legend表格数据
|
//legend表格数据
|
||||||
const kpiStats: any = ref([]);
|
const kpiStats: any = ref([]);
|
||||||
|
|
||||||
// 添加一个函数来获取当前主题下的网格线颜色
|
|
||||||
function getSplitLineColor() {
|
|
||||||
return document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? '#333333'
|
|
||||||
: '#E8E8E8'; // 亮色模式返回 undefined,使用默认颜色
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加表格列定义
|
// 添加表格列定义
|
||||||
const statsColumns: TableColumnType<any>[] = [
|
const statsColumns: TableColumnType<any>[] = [
|
||||||
{
|
{
|
||||||
@@ -240,33 +223,22 @@ const statsColumns: TableColumnType<any>[] = [
|
|||||||
title: t('views.perfManage.kpiOverView.kpiName'),
|
title: t('views.perfManage.kpiOverView.kpiName'),
|
||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
key: 'title',
|
key: 'title',
|
||||||
|
width: '65%',
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// title: t('views.perfManage.kpiOverView.totalValue'),
|
|
||||||
// dataIndex: 'total',
|
|
||||||
// key: 'total',
|
|
||||||
// width: '12%',
|
|
||||||
// sortDirections: ['ascend', 'descend'],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: t('views.perfManage.kpiOverView.avgValue'),
|
|
||||||
// dataIndex: 'avg',
|
|
||||||
// key: 'avg',
|
|
||||||
// width: '24%',
|
|
||||||
// sortDirections: ['ascend', 'descend'],
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
title: t('views.perfManage.kpiOverView.maxValue'),
|
title: t('views.perfManage.kpiOverView.maxValue'),
|
||||||
dataIndex: 'max',
|
dataIndex: 'max',
|
||||||
key: 'max',
|
key: 'max',
|
||||||
width: '200px',
|
width: '17%',
|
||||||
|
sorter: (a: any, b: any) => a.max - b.max, // 添加排序函数
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('views.perfManage.kpiOverView.minValue'),
|
title: t('views.perfManage.kpiOverView.minValue'),
|
||||||
dataIndex: 'min',
|
dataIndex: 'min',
|
||||||
key: 'min',
|
key: 'min',
|
||||||
width: '200px',
|
width: '17%',
|
||||||
|
sorter: (a: any, b: any) => a.min - b.min, // 添加排序函数
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -332,8 +304,6 @@ function fnGetListTitle() {
|
|||||||
var language = currentLocale.value.split('_')[0];
|
var language = currentLocale.value.split('_')[0];
|
||||||
if (language === 'zh') language = 'cn';
|
if (language === 'zh') language = 'cn';
|
||||||
|
|
||||||
if (!state.neType[0]) return false;
|
|
||||||
|
|
||||||
// 获取表头文字
|
// 获取表头文字
|
||||||
listCustom({ neType: state.neType[0], status: 'Active' })
|
listCustom({ neType: state.neType[0], status: 'Active' })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
@@ -346,7 +316,6 @@ function fnGetListTitle() {
|
|||||||
tableState.data = [];
|
tableState.data = [];
|
||||||
tableColumns.value = [];
|
tableColumns.value = [];
|
||||||
tableColumnsDnd.value = [];
|
tableColumnsDnd.value = [];
|
||||||
kpiStats.value = []; //清空数据
|
|
||||||
fnRanderChartData();
|
fnRanderChartData();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -362,7 +331,6 @@ function fnGetListTitle() {
|
|||||||
dataIndex: kpiValue,
|
dataIndex: kpiValue,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
key: kpiValue,
|
key: kpiValue,
|
||||||
unit: item[`unit`],
|
|
||||||
resizable: true,
|
resizable: true,
|
||||||
width: 100,
|
width: 100,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
@@ -422,11 +390,6 @@ function fnGetList() {
|
|||||||
content: t('common.noData'),
|
content: t('common.noData'),
|
||||||
duration: 2,
|
duration: 2,
|
||||||
});
|
});
|
||||||
tableState.data = [];
|
|
||||||
// tableColumns.value = [];
|
|
||||||
// tableColumnsDnd.value = [];
|
|
||||||
kpiStats.value = []; //清空数据
|
|
||||||
fnRanderChartData();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -450,42 +413,11 @@ function fnGetList() {
|
|||||||
const values = tableState.data.map((item: any) => {
|
const values = tableState.data.map((item: any) => {
|
||||||
return item[columns.key] ? Number(item[columns.key]) : 0;
|
return item[columns.key] ? Number(item[columns.key]) : 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 计算总值
|
|
||||||
const total = Number(
|
|
||||||
values.reduce((sum, val) => sum + val, 0).toFixed(2)
|
|
||||||
);
|
|
||||||
// 计算平均值
|
|
||||||
const avg =
|
|
||||||
values.length > 0 ? Number((total / values.length).toFixed(2)) : 0;
|
|
||||||
kpiStats.value.push({
|
kpiStats.value.push({
|
||||||
kpiId: columns.key,
|
kpiId: columns.key,
|
||||||
title: columns.title,
|
title: columns.title,
|
||||||
unit: columns.unit,
|
|
||||||
max: values.length > 0 ? Math.max(...values) : 0,
|
max: values.length > 0 ? Math.max(...values) : 0,
|
||||||
min: values.length > 0 ? Math.min(...values) : 0,
|
min: values.length > 0 ? Math.min(...values) : 0,
|
||||||
avg,
|
|
||||||
total: total,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
kpiStats.value = [];
|
|
||||||
for (const columns of tableColumns.value) {
|
|
||||||
if (
|
|
||||||
columns.key === 'neName' ||
|
|
||||||
columns.key === 'startIndex' ||
|
|
||||||
columns.key === 'timeGroup'
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
kpiStats.value.push({
|
|
||||||
kpiId: columns.key,
|
|
||||||
title: columns.title,
|
|
||||||
unit: columns.unit,
|
|
||||||
max: 0,
|
|
||||||
min: 0,
|
|
||||||
avg: 0,
|
|
||||||
total: 0,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -509,21 +441,6 @@ function fnRanderChart() {
|
|||||||
position: function (pt: any) {
|
position: function (pt: any) {
|
||||||
return [pt[0], '10%'];
|
return [pt[0], '10%'];
|
||||||
},
|
},
|
||||||
confine: true, // 限制 tooltip 显示范围
|
|
||||||
backgroundColor:
|
|
||||||
document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? 'rgba(48, 48, 48, 0.8)'
|
|
||||||
: 'rgba(255, 255, 255, 0.9)',
|
|
||||||
borderColor:
|
|
||||||
document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? '#555'
|
|
||||||
: '#ddd',
|
|
||||||
textStyle: {
|
|
||||||
color:
|
|
||||||
document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? '#CACADA'
|
|
||||||
: '#333',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
@@ -602,9 +519,6 @@ function fnRanderChartData() {
|
|||||||
key: `${columns.key}`,
|
key: `${columns.key}`,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
symbolSize: 6,
|
|
||||||
smooth: 0.6,
|
|
||||||
showSymbol: true,
|
|
||||||
sampling: 'lttb',
|
sampling: 'lttb',
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: color,
|
color: color,
|
||||||
@@ -634,7 +548,6 @@ function fnRanderChartData() {
|
|||||||
|
|
||||||
for (const item of orgData) {
|
for (const item of orgData) {
|
||||||
const keys = Object.keys(item);
|
const keys = Object.keys(item);
|
||||||
//console.log(keys,item);
|
|
||||||
for (const y of chartDataYSeriesData) {
|
for (const y of chartDataYSeriesData) {
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
if (y.key === key) {
|
if (y.key === key) {
|
||||||
@@ -644,10 +557,8 @@ function fnRanderChartData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chartDataXAxisData = Array.from(new Set(chartDataXAxisData));
|
///console.log(queryParams.sortOrder, chartDataXAxisData);
|
||||||
|
console.log(chartDataXAxisData, chartDataYSeriesData);
|
||||||
//console.log(queryParams.sortOrder, chartDataXAxisData);
|
|
||||||
//console.log(chartDataXAxisData, chartDataYSeriesData);
|
|
||||||
|
|
||||||
// 绘制图数据
|
// 绘制图数据
|
||||||
kpiChart.value.setOption(
|
kpiChart.value.setOption(
|
||||||
@@ -658,34 +569,8 @@ function fnRanderChartData() {
|
|||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
axisLabel: {
|
|
||||||
color:
|
|
||||||
document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? '#CACADA'
|
|
||||||
: '#333',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: getSplitLineColor(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data: chartDataXAxisData,
|
data: chartDataXAxisData,
|
||||||
},
|
},
|
||||||
yAxis: {
|
|
||||||
axisLabel: {
|
|
||||||
color:
|
|
||||||
document.documentElement.getAttribute('data-theme') === 'dark'
|
|
||||||
? '#CACADA'
|
|
||||||
: '#333',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: getSplitLineColor(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
series: chartDataYSeriesData,
|
series: chartDataYSeriesData,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -694,6 +579,18 @@ function fnRanderChartData() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**图表折线显示全部 */
|
||||||
|
function fnLegendSelected(bool: any) {
|
||||||
|
for (const key of Object.keys(chartLegendSelected)) {
|
||||||
|
chartLegendSelected[key] = bool;
|
||||||
|
}
|
||||||
|
kpiChart.value.setOption({
|
||||||
|
legend: {
|
||||||
|
selected: chartLegendSelected,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**图表实时统计 */
|
/**图表实时统计 */
|
||||||
function fnRealTimeSwitch(bool: any) {
|
function fnRealTimeSwitch(bool: any) {
|
||||||
if (bool) {
|
if (bool) {
|
||||||
@@ -770,54 +667,29 @@ function wsMessage(res: Record<string, any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 添加一个变量来跟踪当前选中的行
|
// 添加一个变量来跟踪当前选中的行
|
||||||
const selectedRow = ref<string[]>([]);
|
const selectedRow = ref<string | null>(null);
|
||||||
|
|
||||||
const selectedUnit = ref<string | null>(null);
|
|
||||||
// 添加处理行点击的方法
|
// 添加处理行点击的方法
|
||||||
function handleRowClick(record: any) {
|
function handleRowClick(record: any) {
|
||||||
const index = selectedRow.value.indexOf(record.kpiId);
|
if (selectedRow.value === record.kpiId) {
|
||||||
// 如果已经选中,取消选中
|
// 如果点击的是当前选中的行,则取消选中
|
||||||
if (index > -1) {
|
selectedRow.value = null;
|
||||||
selectedRow.value.splice(index, 1);
|
// 更新图表,显示所有指标
|
||||||
chartLegendSelected[record.title] = false;
|
for (let key in chartLegendSelected) {
|
||||||
// 如果取消选中的是最后一个,重置 selectedUnit
|
chartLegendSelected[key] = true;
|
||||||
if (selectedRow.value.length === 0) {
|
|
||||||
selectedUnit.value = null;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 检查单位是否一致
|
// 选中新行
|
||||||
if (selectedUnit.value && selectedUnit.value !== record.unit) {
|
selectedRow.value = record.kpiId;
|
||||||
message.error(
|
// 更新图表,只显示选中的指标
|
||||||
`${t('views.perfManage.customTarget.unitSelect')} ${selectedUnit.value}`
|
for (let key in chartLegendSelected) {
|
||||||
);
|
if (key === record.title) {
|
||||||
return;
|
chartLegendSelected[key] = true;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
// 添加新的选中项
|
|
||||||
selectedRow.value.push(record.kpiId);
|
|
||||||
|
|
||||||
// 设置选中的单位
|
|
||||||
if (!selectedUnit.value) {
|
|
||||||
selectedUnit.value = record.unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果只有一个选中项,重置为 false
|
|
||||||
if (selectedRow.value.length === 1) {
|
|
||||||
Object.keys(chartLegendSelected).forEach(key => {
|
|
||||||
chartLegendSelected[key] = false;
|
chartLegendSelected[key] = false;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
chartLegendSelected[record.title] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有选中项,设置所有图例为 true
|
|
||||||
if (selectedRow.value.length === 0) {
|
|
||||||
Object.keys(chartLegendSelected).forEach(key => {
|
|
||||||
chartLegendSelected[key] = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新图表设置
|
|
||||||
kpiChart.value.setOption({
|
kpiChart.value.setOption({
|
||||||
legend: {
|
legend: {
|
||||||
selected: chartLegendSelected,
|
selected: chartLegendSelected,
|
||||||
@@ -825,127 +697,57 @@ function handleRowClick(record: any) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听主题变化
|
|
||||||
watch(
|
|
||||||
() => layoutStore.proConfig.theme, // 监听的值
|
|
||||||
newValue => {
|
|
||||||
if (kpiChart.value) {
|
|
||||||
const splitLineColor = getSplitLineColor();
|
|
||||||
// 绘制图数据
|
|
||||||
kpiChart.value.setOption({
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
position: function (pt: any) {
|
|
||||||
return [pt[0], '10%'];
|
|
||||||
},
|
|
||||||
confine: true, // 限制 tooltip 显示范围
|
|
||||||
backgroundColor:
|
|
||||||
newValue === 'dark'
|
|
||||||
? 'rgba(48, 48, 48, 0.8)'
|
|
||||||
: 'rgba(255, 255, 255, 0.9)',
|
|
||||||
borderColor: newValue === 'dark' ? '#555' : '#ddd',
|
|
||||||
textStyle: {
|
|
||||||
color: newValue === 'dark' ? '#CACADA' : '#333',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
axisLabel: {
|
|
||||||
color: newValue === 'dark' ? '#CACADA' : '#333',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: splitLineColor,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
axisLabel: {
|
|
||||||
color: newValue === 'dark' ? '#CACADA' : '#333',
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: splitLineColor,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 目前支持的 AMF AUSF MME MOCNGW NSSF SMF UDM UPF PCF
|
// 目前支持的 AMF AUSF MME MOCNGW NSSF SMF UDM UPF PCF
|
||||||
// 获取网元网元列表
|
// 获取网元网元列表
|
||||||
listCustom({ status: 'Active' }).then((res: any) => {
|
neInfoStore.fnNelist().then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||||
if (!res.data.length) {
|
if (res.data.length > 0) {
|
||||||
message.warning({
|
// 过滤不可用的网元
|
||||||
content: '无可用的自定义指标,请先添加自定义指标',
|
neCascaderOptions.value = neInfoStore.getNeCascaderOptions.filter(
|
||||||
duration: 2,
|
(item: any) => {
|
||||||
});
|
return !['OMC', 'NSSF', 'NEF', 'NRF', 'LMF', 'N3IWF'].includes(
|
||||||
return false;
|
item.value
|
||||||
}
|
|
||||||
let typeArr: any = [];
|
|
||||||
res.data.forEach((item: any) => {
|
|
||||||
typeArr.push(item.neType);
|
|
||||||
});
|
|
||||||
typeArr = Array.from(new Set(typeArr));
|
|
||||||
neInfoStore.fnNelist().then(res => {
|
|
||||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
|
||||||
if (res.data.length > 0) {
|
|
||||||
// 过滤不可用的网元
|
|
||||||
neCascaderOptions.value = neInfoStore.getNeCascaderOptions.filter(
|
|
||||||
(item: any) => {
|
|
||||||
return typeArr.includes(item.value);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
if (neCascaderOptions.value.length === 0) {
|
|
||||||
message.warning({
|
|
||||||
content: t('common.noData'),
|
|
||||||
duration: 2,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 无查询参数neType时 默认选择UPF
|
|
||||||
const queryNeType = (route.query.neType as string) || 'IMS';
|
|
||||||
const item = neCascaderOptions.value.find(
|
|
||||||
s => s.value === queryNeType
|
|
||||||
);
|
|
||||||
if (item && item.children) {
|
|
||||||
const info = item.children[0];
|
|
||||||
state.neType = [info.neType, info.neId];
|
|
||||||
queryParams.neType = info.neType;
|
|
||||||
queryParams.neId = info.neId;
|
|
||||||
} else {
|
|
||||||
const info = neCascaderOptions.value[0].children[0];
|
|
||||||
state.neType = [info.neType, info.neId];
|
|
||||||
queryParams.neType = info.neType;
|
|
||||||
queryParams.neId = info.neId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询当前小时
|
|
||||||
const now = new Date();
|
|
||||||
now.setMinutes(0, 0, 0);
|
|
||||||
// 设置起始时间为整点前一小时
|
|
||||||
const startTime = new Date(now);
|
|
||||||
startTime.setHours(now.getHours() - 1);
|
|
||||||
queryRangePicker.value[0] = `${startTime.getTime()}`;
|
|
||||||
// 设置结束时间为整点
|
|
||||||
const endTime = new Date(now);
|
|
||||||
endTime.setMinutes(59, 59, 59);
|
|
||||||
queryRangePicker.value[1] = `${endTime.getTime()}`;
|
|
||||||
fnGetListTitle();
|
|
||||||
// 绘图
|
|
||||||
fnRanderChart();
|
|
||||||
}
|
}
|
||||||
} else {
|
);
|
||||||
|
if (neCascaderOptions.value.length === 0) {
|
||||||
message.warning({
|
message.warning({
|
||||||
content: t('common.noData'),
|
content: t('common.noData'),
|
||||||
duration: 2,
|
duration: 2,
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// 无查询参数neType时 默认选择UPF
|
||||||
|
const queryNeType = (route.query.neType as string) || 'UPF';
|
||||||
|
const item = neCascaderOptions.value.find(s => s.value === queryNeType);
|
||||||
|
if (item && item.children) {
|
||||||
|
const info = item.children[0];
|
||||||
|
state.neType = [info.neType, info.neId];
|
||||||
|
queryParams.neType = info.neType;
|
||||||
|
queryParams.neId = info.neId;
|
||||||
|
} else {
|
||||||
|
const info = neCascaderOptions.value[0].children[0];
|
||||||
|
state.neType = [info.neType, info.neId];
|
||||||
|
queryParams.neType = info.neType;
|
||||||
|
queryParams.neId = info.neId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询当前小时
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
now.setMinutes(0, 0, 0);
|
||||||
|
queryRangePicker.value[0] = `${now.getTime()}`;
|
||||||
|
now.setMinutes(59, 59, 59);
|
||||||
|
queryRangePicker.value[1] = `${now.getTime()}`;
|
||||||
|
fnGetListTitle();
|
||||||
|
// 绘图
|
||||||
|
fnRanderChart();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.warning({
|
||||||
|
content: t('common.noData'),
|
||||||
|
duration: 2,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -972,7 +774,6 @@ onBeforeUnmount(() => {
|
|||||||
v-model:value="state.neType"
|
v-model:value="state.neType"
|
||||||
:options="neCascaderOptions"
|
:options="neCascaderOptions"
|
||||||
:allow-clear="false"
|
:allow-clear="false"
|
||||||
@change="fnGetListTitle()"
|
|
||||||
:placeholder="t('common.selectPlease')"
|
:placeholder="t('common.selectPlease')"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -1003,9 +804,7 @@ onBeforeUnmount(() => {
|
|||||||
:loading="tableState.loading"
|
:loading="tableState.loading"
|
||||||
@click.prevent="fnGetListTitle()"
|
@click.prevent="fnGetListTitle()"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon><SearchOutlined /></template>
|
||||||
<SearchOutlined />
|
|
||||||
</template>
|
|
||||||
{{ t('common.search') }}
|
{{ t('common.search') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
@@ -1024,9 +823,7 @@ onBeforeUnmount(() => {
|
|||||||
:loading="tableState.loading"
|
:loading="tableState.loading"
|
||||||
@click.prevent="fnChangShowType()"
|
@click.prevent="fnChangShowType()"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon> <AreaChartOutlined /> </template>
|
||||||
<AreaChartOutlined />
|
|
||||||
</template>
|
|
||||||
{{
|
{{
|
||||||
tableState.showTable
|
tableState.showTable
|
||||||
? t('views.perfManage.goldTarget.kpiChartTitle')
|
? t('views.perfManage.goldTarget.kpiChartTitle')
|
||||||
@@ -1053,13 +850,12 @@ onBeforeUnmount(() => {
|
|||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
<template #title>{{ t('common.reloadText') }}</template>
|
||||||
<a-button type="text" @click.prevent="fnGetList()">
|
<a-button type="text" @click.prevent="fnGetList()">
|
||||||
<template #icon>
|
<template #icon><ReloadOutlined /></template>
|
||||||
<ReloadOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<TableColumnsDnd
|
<TableColumnsDnd
|
||||||
v-if="tableColumns.length > 0"
|
v-if="tableColumns.length > 0"
|
||||||
|
:cache-id="`kpiTarget_${state.neType[0]}`"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
v-model:columns-dnd="tableColumnsDnd"
|
v-model:columns-dnd="tableColumnsDnd"
|
||||||
></TableColumnsDnd>
|
></TableColumnsDnd>
|
||||||
@@ -1067,9 +863,7 @@ onBeforeUnmount(() => {
|
|||||||
<template #title>{{ t('common.sizeText') }}</template>
|
<template #title>{{ t('common.sizeText') }}</template>
|
||||||
<a-dropdown trigger="click" placement="bottomRight">
|
<a-dropdown trigger="click" placement="bottomRight">
|
||||||
<a-button type="text">
|
<a-button type="text">
|
||||||
<template #icon>
|
<template #icon><ColumnHeightOutlined /></template>
|
||||||
<ColumnHeightOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
</a-button>
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<a-menu
|
<a-menu
|
||||||
@@ -1131,7 +925,7 @@ onBeforeUnmount(() => {
|
|||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ x: tableColumnsDnd.length * 200, y: 'calc(100vh - 480px)' }"
|
:scroll="{ x: tableColumnsDnd.length * 200, y: 'calc(100vh - 480px)' }"
|
||||||
@resizeColumn="(w: number, col: any) => (col.width = w)"
|
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||||
:show-expand-column="false"
|
:show-expand-column="false"
|
||||||
@change="fnTableChange"
|
@change="fnTableChange"
|
||||||
>
|
>
|
||||||
@@ -1152,75 +946,13 @@ onBeforeUnmount(() => {
|
|||||||
:pagination="false"
|
:pagination="false"
|
||||||
:scroll="{ y: 250 }"
|
:scroll="{ y: 250 }"
|
||||||
size="small"
|
size="small"
|
||||||
:custom-row="(record:any) => ({
|
:custom-row="
|
||||||
onClick: () => handleRowClick(record),
|
record => ({
|
||||||
class: selectedRow.includes(record.kpiId) ? 'selected-row' : '',
|
onClick: () => handleRowClick(record),
|
||||||
})
|
class: record.kpiId === selectedRow ? 'selected-row' : '',
|
||||||
"
|
})
|
||||||
>
|
"
|
||||||
<template #headerCell="{ column }">
|
/>
|
||||||
<template v-if="column.key === 'total'">
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.totalValue') }}
|
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.totalValueTip') }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'avg'">
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.avgValue') }}
|
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.avgValueTip') }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'max'">
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.maxValue') }}
|
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.maxValueTip') }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'min'">
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.minValue') }}
|
|
||||||
<a-tooltip placement="bottom">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
|
||||||
{{ t('views.perfManage.kpiOverView.minValueTip') }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<InfoCircleOutlined />
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.key === 'avg'">
|
|
||||||
<span v-if="record.unit !== '%'">-</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'total'">
|
|
||||||
<span v-if="record.unit == '%'">-</span>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
Loaded 100 of 122 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user