Compare commits
120 Commits
2.231207.9
...
2.2312.10-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f968839fa | ||
|
|
8523b34c19 | ||
|
|
d09171187d | ||
|
|
7e894c4073 | ||
|
|
6f5d02e479 | ||
|
|
b50c5250bf | ||
|
|
f0ab5d5ea6 | ||
|
|
d9c561e677 | ||
|
|
e4c829a46d | ||
|
|
139cc1bd0d | ||
|
|
7297bd5d0f | ||
|
|
aa0c92a8d1 | ||
|
|
a53fd939e1 | ||
|
|
25b5212588 | ||
|
|
5e463a6ce8 | ||
|
|
fb4babf09a | ||
|
|
04b4c25c38 | ||
|
|
9c61026c88 | ||
|
|
24816eb991 | ||
|
|
b756fe9d56 | ||
|
|
1c8f208453 | ||
|
|
5e8547aff8 | ||
|
|
e6f0dd9f21 | ||
|
|
5e8f65f11b | ||
|
|
ce86edef6c | ||
|
|
167cecba84 | ||
|
|
d8d1b53027 | ||
|
|
9fdf13676e | ||
|
|
f20e9bc000 | ||
|
|
45b04975eb | ||
|
|
6441a1efaf | ||
|
|
7e98f35f5b | ||
|
|
4f34b3bca9 | ||
|
|
b8e8c07704 | ||
|
|
3aea520289 | ||
|
|
b54027bf0f | ||
|
|
0eb7bc9497 | ||
|
|
7c69967148 | ||
|
|
dd14a32329 | ||
|
|
864be2ba3b | ||
|
|
e79d054ceb | ||
|
|
12f810d890 | ||
|
|
715471f950 | ||
| a23cfd209f | |||
|
|
0f3df3a80b | ||
|
|
04754a022f | ||
|
|
61df24059c | ||
|
|
fbd41e2ebf | ||
|
|
cf7d234f91 | ||
|
|
b556dc36e6 | ||
|
|
0c6ea19878 | ||
|
|
0c52f2cf3b | ||
|
|
2470eed417 | ||
|
|
89c7b483d4 | ||
|
|
b26104b4bc | ||
| acd8337606 | |||
|
|
eac0d957aa | ||
|
|
eae2dd5d30 | ||
|
|
fa1bb05548 | ||
|
|
6b855b8ff2 | ||
|
|
11bfae8c0f | ||
|
|
823114a6d0 | ||
|
|
99c6d233e5 | ||
|
|
728d4b00d8 | ||
|
|
8288184f15 | ||
|
|
6fc9a305ce | ||
|
|
e8b95a594b | ||
|
|
859eeda1fe | ||
|
|
3f20faf5be | ||
|
|
208d7a4725 | ||
|
|
1c44651ad2 | ||
|
|
f015f45601 | ||
|
|
dfe06e2098 | ||
|
|
44c05e964e | ||
|
|
e210dd7e33 | ||
|
|
920bca7912 | ||
|
|
b0d7b7d539 | ||
|
|
cf9968a899 | ||
|
|
f67d083e10 | ||
|
|
5124c0c04a | ||
|
|
d56c293ef5 | ||
|
|
e90bc539e9 | ||
|
|
7edcf1703e | ||
|
|
8ee0a4d191 | ||
|
|
bc1f897660 | ||
|
|
ba47d3a303 | ||
|
|
38e5e4a9e0 | ||
|
|
15d7d118c4 | ||
|
|
69d4348df7 | ||
|
|
fe81a2d924 | ||
|
|
cd53fab1f9 | ||
|
|
e6d62da386 | ||
|
|
752f8ccc70 | ||
|
|
3a0c85169e | ||
|
|
f845f3f4de | ||
|
|
63e3f352b2 | ||
|
|
d9ec9fd1e1 | ||
|
|
f198d2b9a2 | ||
|
|
1c3e6db4bc | ||
|
|
8199e16a17 | ||
|
|
0d736966dd | ||
|
|
fe5905ee35 | ||
|
|
9c27c32e26 | ||
|
|
4208ccc358 | ||
|
|
51a190771d | ||
|
|
3376d90b96 | ||
|
|
4105f4ef33 | ||
|
|
e6a4591fb6 | ||
|
|
fafe604323 | ||
|
|
f110d0e697 | ||
|
|
6210b87c84 | ||
|
|
5a761ece4e | ||
|
|
3fa2cffc82 | ||
|
|
e92004a69a | ||
|
|
a612d05429 | ||
|
|
c93dabc6cf | ||
|
|
5056de2c1a | ||
| 8725518450 | |||
| 596ee0bb8d | |||
|
|
d5f593647e |
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network EMS"
|
||||
VITE_APP_CODE = "CN EMS"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.231204.9"
|
||||
VITE_APP_VERSION = "2.2312.9"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
@@ -11,7 +11,7 @@ VITE_APP_NAME = "Core Network EMS"
|
||||
VITE_APP_CODE = "CN EMS"
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION = "2.2312.9"
|
||||
VITE_APP_VERSION = "2.231229.10"
|
||||
|
||||
# 接口基础URL地址-不带/后缀
|
||||
VITE_API_BASE_URL = "/omc-api"
|
||||
|
||||
36
CHANGELOG.md
Normal file
36
CHANGELOG.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# 版本发布日志
|
||||
|
||||
## 2.2312.10-20231229
|
||||
|
||||
- 新增 告警列表记录自定义排序导出
|
||||
- 新增 黄金指标 KPI 数据列表支持排序
|
||||
- 新增 黄金指标 KPI 数据支持选择五分钟颗粒度
|
||||
- 新增 网元管理新增修改时可选同步网元信息的开关
|
||||
- 新增 终端-UDM 数据勾选记录导出和勾选记录删除功能
|
||||
- 修复 配置-参数配置里面的删除按钮,增加二次确认避免误触
|
||||
- 修复 配置-参数配置值类型为字符串 http 判断
|
||||
- 修复 软件版本管理上传版本号截取
|
||||
- 修复 PCF 用户策略控制批量删除表单选项校验异常提示
|
||||
- 修复 打包编译时类型异常问题
|
||||
- 优化 网元管理弹出菜单窗口设置为可移动
|
||||
- 优化 网元管理鼠标悬浮更多时提示靠左显示避免遮挡
|
||||
- 优化 首页网元异常情况展示 SN
|
||||
- 优化 告警详细信息展示方式
|
||||
|
||||
## 2.2312.9-20231222
|
||||
|
||||
- 新增 日志管理查看网元日志文件并下载功能页面
|
||||
- 新增 国际化切换权限控制,系统设置里控制切换默认语言
|
||||
- 新增 性能管理 KPI 指标集功能页面
|
||||
- 新增 UE 管理 PCF 用户策略控制功能页面
|
||||
- 修复 参数配置新增数据类型值不匹配导致的异常失败
|
||||
- 修复 多处英文显示词义不明确的信息提示
|
||||
- 修复 UE 管理 UDM 签约用户数据批量新增时 EPSODB 转换十六进制问题
|
||||
- 优化 网元管理重启接口超时导致网元信息不一致问题
|
||||
- 优化 参数配置新增编辑参数顺序,参数类型格式化
|
||||
- 优化 主页网元状态饼图颜色选择自定义
|
||||
- 优化 MML 操作 UDM 签约用户信息字段,必填项标红
|
||||
- 优化 软件管理回退功能操作页面
|
||||
- 优化 静态文件地址追加随机戳避免缓存
|
||||
- 优化 补充移动端样式适配调整
|
||||
- 主页修改增加 OMC 的序列号,点击网元信息不再覆盖右边信息框
|
||||
10
README.md
10
README.md
@@ -12,6 +12,11 @@
|
||||
Jenkins: http://192.168.2.166:3185/
|
||||
Nginx: http://192.168.2.166:3188/#/index
|
||||
后端暴露端口: http://192.168.2.166:3186 \ http://192.168.2.166:3187
|
||||
|
||||
|
||||
新网管:192.168.5.13
|
||||
旧网管:192.168.5.14
|
||||
登录账户:manager/manager
|
||||
```
|
||||
|
||||
## 程序命令
|
||||
@@ -51,7 +56,8 @@ eyJhbGciOiJSUzI1NiIsImtpZCI6ImZFVUhIb1puLW04M1dfSUYyRU8zWlZueXBpNUh4T0hTRVlzU19j
|
||||
```
|
||||
|
||||
```ssh
|
||||
# https://blog.csdn.net/m0_54706625/article/details/129721121
|
||||
sudo chmod 700 -/.ssh/
|
||||
sudochmod 700 /home/ubuntu #这个尤其容易忽视掉,我就是从这个坑里爬出来。有木有很高兴呀!
|
||||
3sudochmod 600 -/ssh/authorized keys
|
||||
sudo chmod 700 /home/mask/.ssh #这个尤其容易忽视掉,我就是从这个坑里爬出来。有木有很高兴呀!
|
||||
sudo chmod 600 ~/.ssh/authorized_keys
|
||||
```
|
||||
28
package.json
28
package.json
@@ -12,15 +12,15 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"antdv-pro-layout": "^3.2.6",
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@antv/g6": "^4.8.24",
|
||||
"@codemirror/lang-javascript": "^6.2.1",
|
||||
"@codemirror/merge": "^6.1.2",
|
||||
"@codemirror/merge": "^6.4.0",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@tato30/vue-pdf": "^1.8.1",
|
||||
"@vueuse/components": "^10.6.1",
|
||||
"@vueuse/core": "^10.6.1",
|
||||
"@vueuse/core": "^10.7.0",
|
||||
"ant-design-vue": "^3.2.20",
|
||||
"antdv-pro-layout": "^3.2.6",
|
||||
"codemirror": "^6.0.1",
|
||||
"dayjs": "^1.11.10",
|
||||
"echarts": "^5.4.2",
|
||||
@@ -29,24 +29,24 @@
|
||||
"js-cookie": "^3.0.5",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"vue": "^3.3.6",
|
||||
"vue": "^3.3.13",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
"vue-i18n": "^9.5.0",
|
||||
"vue-i18n": "^9.8.0",
|
||||
"vue-router": "^4.2.5",
|
||||
"vue3-smooth-dnd": "^0.0.6",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@types/js-cookie": "^3.0.3",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@vitejs/plugin-vue": "^4.3.4",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@vitejs/plugin-vue": "^4.5.2",
|
||||
"less": "^4.2.0",
|
||||
"typescript": "^5.2.2",
|
||||
"unplugin-vue-components": "^0.25.2",
|
||||
"vite": "^4.5.0",
|
||||
"typescript": "^5.3.3",
|
||||
"unplugin-vue-components": "^0.26.0",
|
||||
"vite": "^5.0.10",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vue-tsc": "^1.8.19"
|
||||
"vue-tsc": "^1.8.25"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*
|
||||
*/
|
||||
(function () {
|
||||
// host = ip:prot
|
||||
// host = ip:port
|
||||
const host = '192.168.8.100:3030';
|
||||
|
||||
// Service Address 服务地址
|
||||
sessionStorage.setItem(baseUrl, `http://${host}`);
|
||||
sessionStorage.setItem('baseUrl', `http://${host}`);
|
||||
// websocket Address
|
||||
sessionStorage.setItem(wsUrl, `ws://${host}`);
|
||||
sessionStorage.setItem('wsUrl', `ws://${host}`);
|
||||
})();
|
||||
|
||||
1
public/svg/base.svg
Normal file
1
public/svg/base.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1702978675818" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4327" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512.1 955.7c-1.4 0-2.7-0.4-4-1.1L80.4 706.4c-2.4-1.4-3.9-4-3.9-6.8v-88.8c0-2.8 1.5-5.4 3.9-6.8l427.7-252c1.2-0.7 2.6-1.1 4-1.1s2.8 0.4 4 1.1l427.6 252c2.4 1.4 3.9 4 3.9 6.8v88.8c0 2.8-1.5 5.4-3.9 6.8L516 954.6c-1.2 0.7-2.6 1.1-3.9 1.1z" fill="#B5D6FB" p-id="4328"></path><path d="M512.1 358.8l427.5 252v88.8L869.9 740 512.1 947.8 154.1 740l-69.7-40.4v-88.8l427.7-252m0-15.8c-2.8 0-5.5 0.7-8 2.2l-427.7 252c-4.8 2.8-7.8 8-7.8 13.6v88.8c0 5.6 3 10.8 7.9 13.7l69.7 40.5 358 207.8c2.4 1.4 5.2 2.1 7.9 2.1s5.5-0.7 7.9-2.1l357.8-207.8 69.7-40.4c4.9-2.8 7.9-8 7.9-13.7v-88.8c0-5.6-3-10.8-7.8-13.6l-427.5-252c-2.5-1.5-5.3-2.3-8-2.3z" fill="#0276F7" p-id="4329"></path><path d="M84.4 610.8L512 860.7l427.6-249.9-427.5-252z" fill="#FFFFFF" p-id="4330"></path><path d="M500.9 70.3L232.1 562.1l277.7 159L791 561.2z" fill="#D4E4FC" p-id="4331"></path><path d="M214.6 601.2c-1.3 0-2.6-0.3-3.9-1-3.8-2.1-5.2-6.9-3-10.7l294.9-525c1.4-2.5 4-4 6.9-4 2.8 0 5.4 1.5 6.9 4l299.9 525c2.2 3.8 0.8 8.6-2.9 10.8-3.8 2.1-8.6 0.8-10.8-2.9l-293-512.9-288.1 512.7c-1.5 2.6-4.2 4-6.9 4z" fill="#0276F7" p-id="4332"></path><path d="M509.8 752.4c-4.4 0-7.9-3.5-7.9-7.9V86.7c0-4.4 3.5-7.9 7.9-7.9s7.9 3.5 7.9 7.9v657.9c0 4.3-3.6 7.8-7.9 7.8z" fill="#0276F7" p-id="4333"></path><path d="M509.8 729c-1.4 0-2.7-0.4-3.9-1L228.2 569c-3.8-2.2-5.1-7-2.9-10.8 2.2-3.8 7-5.1 10.8-2.9L509.8 712l277.3-157.7c3.8-2.2 8.6-0.8 10.8 3 2.2 3.8 0.8 8.6-3 10.8L513.7 728c-1.2 0.7-2.6 1-3.9 1z" fill="#0276F7" p-id="4334"></path><path d="M509.8 578.9c-1.4 0-2.7-0.4-4-1.1l-213-124c-3.8-2.2-5-7-2.9-10.8 2.2-3.8 7-5.1 10.8-2.8l209.1 121.7 212.8-120.5c3.8-2.2 8.6-0.8 10.8 3 2.2 3.8 0.8 8.6-3 10.7L513.7 577.9c-1.2 0.7-2.6 1-3.9 1zM507.2 423.5c-1.3 0-2.5-0.3-3.7-0.9L354.9 344c-3.9-2.1-5.3-6.8-3.3-10.7 2-3.9 6.8-5.3 10.7-3.3l145 76.7 150.8-78.8c3.9-2 8.6-0.5 10.7 3.3 2 3.9 0.5 8.6-3.3 10.7L511 422.6c-1.3 0.6-2.5 0.9-3.8 0.9zM509.8 277c-1.3 0-2.6-0.3-3.7-0.9l-86.8-46.8c-3.8-2.1-5.3-6.9-3.2-10.7 2.1-3.9 6.9-5.2 10.7-3.2l83 44.8 82.6-46.9c3.8-2.2 8.6-0.8 10.8 3 2.2 3.8 0.8 8.6-3 10.8l-86.4 49c-1.3 0.6-2.7 0.9-4 0.9z" fill="#0276F7" p-id="4335"></path><path d="M509.8 578.9h-0.3L231.9 570c-4.4-0.1-7.8-3.8-7.6-8.1 0.1-4.4 4.3-7.6 8.1-7.6l277.7 8.9c4.4 0.1 7.8 3.8 7.6 8.1-0.2 4.2-3.7 7.6-7.9 7.6zM509.8 729c-1.7 0-3.4-0.6-4.9-1.7-3.4-2.7-4-7.7-1.3-11.1l216.7-272.9c2.7-3.4 7.7-4 11.1-1.3 3.4 2.7 4 7.7 1.3 11.1L516 726c-1.6 2-3.9 3-6.2 3z" fill="#0276F7" p-id="4336"></path><path d="M509.8 578.9c-1.5 0-2.9-0.4-4.3-1.2-3.7-2.4-4.7-7.2-2.4-10.9l152-236.1c2.4-3.7 7.3-4.7 10.9-2.4 3.7 2.4 4.7 7.2 2.4 10.9l-152 236.1c-1.5 2.3-4 3.6-6.6 3.6zM507.2 423.5c-1.1 0-2.2-0.2-3.3-0.7-4-1.8-5.7-6.5-3.9-10.5l89-195.5c1.8-4 6.4-5.7 10.5-3.9 4 1.8 5.7 6.5 3.9 10.5l-88.9 195.5c-1.4 2.9-4.3 4.6-7.3 4.6z" fill="#0276F7" p-id="4337"></path><path d="M596.2 377c-2.9 0-5.7-1.6-7.1-4.4-1.9-3.9-0.3-8.6 3.6-10.5L729 295.7 343.3 120l22 205.3 141.3-63.4c3.9-1.8 8.6 0 10.4 4 1.8 4 0 8.6-4 10.4l-151.2 67.9c-2.3 1-4.9 0.9-7.2-0.4-2.2-1.3-3.6-3.5-3.9-6l-24.6-229.9c-0.3-2.8 0.9-5.6 3.2-7.2 2.3-1.6 5.3-2 7.9-0.8l413.6 188.4c2.8 1.3 4.6 4 4.6 7.1 0 3.1-1.7 5.9-4.4 7.2l-151.4 73.6c-1.1 0.6-2.3 0.8-3.4 0.8zM296.8 454.9c-3.8 0-7.2-2.8-7.8-6.7-0.6-4.3 2.3-8.3 6.6-9l210.5-31.4c4.3-0.6 8.3 2.3 9 6.6 0.6 4.3-2.3 8.3-6.6 9L298 454.8c-0.5 0.1-0.9 0.1-1.2 0.1z" fill="#0276F7" p-id="4338"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
1
public/svg/cloud.svg
Normal file
1
public/svg/cloud.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1702978716365" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4633" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M817.3 505c2.7-14 4.3-28.4 4.3-43.2 0-123.8-100.4-224.2-224.2-224.2-81.9 0-153.3 44.1-192.5 109.7-15.1-5.9-31.5-9.2-48.7-9.2-72.6 0-131.6 57.6-134.3 129.5-69 18.6-119.9 81.5-119.9 156.5 0 89.6 72.7 162.3 162.3 162.3h514.3c79.2 0 143.4-64.2 143.4-143.4 0-65.8-44.3-121-104.7-138z" fill="#D4E4FC" p-id="4634"></path><path d="M778.6 793.2H264.3C171 793.2 95.2 717.3 95.2 624c0-74.5 49.2-140.3 120.2-161.8 5.3-73.9 66.2-131.1 140.9-131.1 15.6 0 30.9 2.6 45.8 7.7 42.7-67.8 115.3-108.1 195.4-108.1 127.4 0 231 103.6 231 231 0 12.7-1.1 25.6-3.3 38.4 61.3 20 103.6 77.8 103.6 142.7 0 83-67.4 150.4-150.2 150.4zM356.3 344.9c-68.9 0-124.9 54-127.4 122.9l-0.2 5.1-4.9 1.3c-67.6 18.3-114.9 79.9-114.9 149.9 0 85.7 69.7 155.4 155.4 155.4h514.3c75.3 0 136.5-61.2 136.5-136.5 0-60.9-41-114.9-99.6-131.3l-6.1-1.7 1.2-6.2c2.7-14 4.1-28.1 4.1-41.9 0-119.8-97.5-217.3-217.3-217.3-77.1 0-146.9 39.7-186.6 106.3l-3 5-5.4-2.1c-14.9-5.9-30.4-8.9-46.1-8.9z" fill="#0276F7" p-id="4635"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
public/svg/service.svg
Normal file
1
public/svg/service.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1702974353127" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4174" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M470.9 954.6c-1.2 0-2.3-0.3-3.4-0.9l-240-132.2c-2.2-1.2-3.6-3.6-3.6-6.1V270.6c0-2.5 1.3-4.7 3.4-6L546.9 70.4c1.1-0.7 2.4-1 3.6-1 1.2 0 2.4 0.3 3.4 0.9l242.6 136.9c2.2 1.2 3.6 3.6 3.6 6.1v552.8c0 2.5-1.4 4.9-3.6 6.1L474.4 953.7c-1.1 0.6-2.3 0.9-3.5 0.9z" fill="#B5D6FB" p-id="4175"></path><path d="M550.5 76.4l242.6 136.9v552.8L470.9 947.6l-240-132.2V270.6L550.5 76.4m0-14c-2.5 0-5 0.7-7.3 2L223.6 258.6c-4.2 2.5-6.7 7.1-6.7 12v544.8c0 5.1 2.8 9.8 7.3 12.3l240 132.2c2.1 1.2 4.4 1.7 6.8 1.7 2.4 0 4.7-0.6 6.9-1.8L800 778.3c4.4-2.5 7.1-7.2 7.1-12.2V213.3c0-5.1-2.7-9.7-7.1-12.2L557.4 64.2c-2.1-1.2-4.5-1.8-6.9-1.8z" fill="#0276F7" p-id="4176"></path><path d="M550.5 76.4L230.9 270.6l240 130.5 322.2-187.8z" fill="#FFFFFF" p-id="4177"></path><path d="M470.9 916V401.1" fill="#B5D6FB" p-id="4178"></path><path d="M470.9 923.1c-3.9 0-7-3.1-7-7v-515c0-3.9 3.1-7 7-7s7 3.1 7 7V916c0 3.9-3.1 7.1-7 7.1z" fill="#0276F7" p-id="4179"></path><path d="M754.5 235.8L470.9 401.1" fill="#B5D6FB" p-id="4180"></path><path d="M470.9 408.1c-2.4 0-4.8-1.2-6.1-3.5-1.9-3.3-0.8-7.6 2.5-9.6L751 229.7c3.4-2 7.6-0.8 9.6 2.5 1.9 3.3 0.8 7.6-2.5 9.6L474.5 407.2c-1.1 0.6-2.4 0.9-3.6 0.9z" fill="#0276F7" p-id="4181"></path><path d="M261.5 287.2l209.4 113.9" fill="#B5D6FB" p-id="4182"></path><path d="M470.9 408.1c-1.1 0-2.3-0.3-3.3-0.8L258.1 293.4c-3.4-1.8-4.7-6.1-2.8-9.5 1.9-3.4 6.1-4.6 9.5-2.8L474.3 395c3.4 1.8 4.7 6.1 2.8 9.5-1.3 2.3-3.7 3.6-6.2 3.6z" fill="#0276F7" p-id="4183"></path><path d="M258.2 744.4l177.2 99.3" fill="#B5D6FB" p-id="4184"></path><path d="M435.4 850.7c-1.2 0-2.3-0.3-3.4-0.9l-177.1-99.3c-3.4-1.9-4.6-6.2-2.7-9.5 1.9-3.4 6.1-4.6 9.5-2.7l177.1 99.3c3.4 1.9 4.6 6.2 2.7 9.5-1.3 2.3-3.7 3.6-6.1 3.6z" fill="#0276F7" p-id="4185"></path><path d="M258.2 694.8l177.2 99.3" fill="#B5D6FB" p-id="4186"></path><path d="M435.4 801.1c-1.2 0-2.3-0.3-3.4-0.9l-177.1-99.3c-3.4-1.9-4.6-6.2-2.7-9.5 1.9-3.4 6.1-4.6 9.5-2.7L438.8 788c3.4 1.9 4.6 6.2 2.7 9.5-1.3 2.3-3.7 3.6-6.1 3.6z" fill="#0276F7" p-id="4187"></path><path d="M258.2 645.1l177.2 99.3" fill="#B5D6FB" p-id="4188"></path><path d="M435.4 751.4c-1.2 0-2.3-0.3-3.4-0.9l-177.1-99.3c-3.4-1.9-4.6-6.2-2.7-9.5 1.9-3.4 6.1-4.6 9.5-2.7l177.1 99.3c3.4 1.9 4.6 6.2 2.7 9.5-1.3 2.3-3.7 3.6-6.1 3.6z" fill="#0276F7" p-id="4189"></path><path d="M222.7 538.9l248.2 135.5" fill="#B5D6FB" p-id="4190"></path><path d="M219.335 545.028l6.708-12.289 248.241 135.49-6.707 12.289z" fill="#0276F7" p-id="4191"></path><path d="M393 430.7l40.3 20.1" fill="#B5D6FB" p-id="4192"></path><path d="M433.3 457.8c-1.1 0-2.1-0.2-3.1-0.7L389.9 437c-3.5-1.7-4.9-5.9-3.1-9.4 1.7-3.5 6-4.9 9.4-3.1l40.3 20.1c3.5 1.7 4.9 5.9 3.1 9.4-1.3 2.4-3.8 3.8-6.3 3.8z" fill="#0276F7" p-id="4193"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
1
public/svg/service_db.svg
Normal file
1
public/svg/service_db.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 6.1 KiB |
47
src/App.vue
47
src/App.vue
@@ -92,4 +92,51 @@ body .ant-pro-basicLayout {
|
||||
.ant-table.ant-table-small .ant-table-thead > tr > th {
|
||||
padding: 6px !important;
|
||||
}
|
||||
|
||||
/** ==== 表格头按钮区域 S === **/
|
||||
/* 默认 */
|
||||
.button-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button-container > button,
|
||||
.button-container > span {
|
||||
margin-right: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.button-container > button:last-child,
|
||||
.button-container > span:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
/* 平板端 */
|
||||
@media (max-width: 992px) {
|
||||
.button-container {
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
align-items: left;
|
||||
}
|
||||
.button-container > button,
|
||||
.button-container > span {
|
||||
margin-right: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
/* 手机端 */
|
||||
@media (max-width: 576px) {
|
||||
.button-container {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
align-items: left;
|
||||
}
|
||||
.button-container > button,
|
||||
.button-container > span {
|
||||
margin-right: 0px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
/** ==== 表格头按钮区域 E === **/
|
||||
</style>
|
||||
|
||||
@@ -8,8 +8,26 @@ import { parseObjLineToHump } from '@/utils/parse-utils';
|
||||
* @returns object
|
||||
*/
|
||||
export async function listNeInfo(query: Record<string, any>) {
|
||||
let totalSQL = 'select count(*) as total from ne_info where status=0 ';
|
||||
let rowsSQL = 'select * from ne_info where status=0 ';
|
||||
let totalSQL = 'select count(*) as total from ne_info where (status=0 or status=3)';
|
||||
let rowsSQL = 'select * from ne_info where (status=0 or status=3) ';
|
||||
|
||||
// 系统特定顺序
|
||||
const specificOrder = [
|
||||
'OMC',
|
||||
'MME',
|
||||
'AMF',
|
||||
'AUSF',
|
||||
'UDM',
|
||||
'SMF',
|
||||
'PCF',
|
||||
'UPF',
|
||||
'NRF',
|
||||
'NSSF',
|
||||
'IMS',
|
||||
'N3IWF',
|
||||
'NEF',
|
||||
'LMF',
|
||||
];
|
||||
|
||||
// 查询
|
||||
let querySQL = '';
|
||||
@@ -46,6 +64,14 @@ export async function listNeInfo(query: Record<string, any>) {
|
||||
data.total = itemData[0]['total'];
|
||||
} else {
|
||||
data.rows = itemData.map(v => parseObjLineToHump(v));
|
||||
//通过sort进行冒泡排序
|
||||
data.rows.sort((a: any, b: any) => {
|
||||
const typeA = specificOrder.indexOf(a.neType);
|
||||
const typeB = specificOrder.indexOf(b.neType);
|
||||
if (typeA === -1) return 1; // 如果不在特定顺序中,排到后面
|
||||
if (typeB === -1) return -1; // 如果不在特定顺序中,排到后面
|
||||
return typeA - typeB;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -65,7 +91,7 @@ export async function getNeInfo(id: string | number) {
|
||||
url: `/api/rest/databaseManagement/v1/select/omc_db/ne_info`,
|
||||
method: 'get',
|
||||
params: {
|
||||
SQL: `select * from ne_info where status=0 and id = ${id}`,
|
||||
SQL: `select * from ne_info where (status=0 or status=3) and id = ${id}`,
|
||||
},
|
||||
});
|
||||
// 解析数据
|
||||
@@ -86,7 +112,7 @@ export async function getNeInfo(id: string | number) {
|
||||
export function addNeInfo(data: Record<string, any>) {
|
||||
data.port = `${data.port}`;
|
||||
return request({
|
||||
url: `/api/rest/systemManagement/v1/elementType/${data.neType}/objectType/neInfo`,
|
||||
url: `/api/rest/systemManagement/v1/elementType/${data.neType.toLowerCase()}/objectType/neInfo?sync2ne=${data.sync}`,
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
@@ -100,7 +126,7 @@ export function addNeInfo(data: Record<string, any>) {
|
||||
export function updateNeInfo(data: Record<string, any>) {
|
||||
data.port = `${data.port}`;
|
||||
return request({
|
||||
url: `/api/rest/systemManagement/v1/elementType/${data.neType}/objectType/neInfo`,
|
||||
url: `/api/rest/systemManagement/v1/elementType/${data.neType}/objectType/neInfo?sync2ne=${data.sync}`,
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
@@ -115,6 +141,7 @@ export async function delNeInfo(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/api/rest/systemManagement/v1/elementType/${data.neType}/objectType/neInfo?ne_id=${data.neId}`,
|
||||
method: 'delete',
|
||||
timeout:60*1000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -123,6 +150,23 @@ export async function delNeInfo(data: Record<string, any>) {
|
||||
* @returns object
|
||||
*/
|
||||
export async function getNelistAll() {
|
||||
// 系统特定顺序
|
||||
const specificOrder = [
|
||||
'OMC',
|
||||
'MME',
|
||||
'AMF',
|
||||
'AUSF',
|
||||
'UDM',
|
||||
'SMF',
|
||||
'PCF',
|
||||
'UPF',
|
||||
'NRF',
|
||||
'NSSF',
|
||||
'IMS',
|
||||
'N3IWF',
|
||||
'NEF',
|
||||
'LMF',
|
||||
];
|
||||
// 发起请求
|
||||
const result = await request({
|
||||
url: `/api/rest/databaseManagement/v1/elementType/omc_db/objectType/ne_info`,
|
||||
@@ -134,6 +178,14 @@ export async function getNelistAll() {
|
||||
// 解析数据
|
||||
if (result.code === RESULT_CODE_SUCCESS && Array.isArray(result.data.data)) {
|
||||
let data = result.data.data[0];
|
||||
//通过sort进行冒泡排序
|
||||
data['ne_info'].sort((a: any, b: any) => {
|
||||
const typeA = specificOrder.indexOf(a.ne_type);
|
||||
const typeB = specificOrder.indexOf(b.ne_type);
|
||||
if (typeA === -1) return 1;
|
||||
if (typeB === -1) return -1;
|
||||
return typeA - typeB;
|
||||
});
|
||||
return Object.assign(result, {
|
||||
data: parseObjLineToHump(data['ne_info']),
|
||||
});
|
||||
|
||||
@@ -169,7 +169,7 @@ export function showPass(data: Record<string, any>) {
|
||||
let querySQL = '';
|
||||
querySQL += data.alarm_code ? ` and alarm_code != ${data.alarm_code} ` : '';
|
||||
querySQL += data.alarm_type
|
||||
? ` and alarm_type !=\\' ${data.alarm_type} \\'`
|
||||
? ` and alarm_type !=\\'${data.alarm_type}\\'`
|
||||
: '';
|
||||
querySQL += data.pv_flag ? ` and pv_flag !=\\'${data.pv_flag} \\'` : '';
|
||||
querySQL += data.orig_severity
|
||||
|
||||
@@ -7,6 +7,23 @@ import { parseDateToStr } from '@/utils/date-utils';
|
||||
* @returns object
|
||||
*/
|
||||
export async function listMain() {
|
||||
// 系统特定顺序
|
||||
const specificOrder = [
|
||||
'OMC',
|
||||
'MME',
|
||||
'AMF',
|
||||
'AUSF',
|
||||
'UDM',
|
||||
'SMF',
|
||||
'PCF',
|
||||
'UPF',
|
||||
'NRF',
|
||||
'NSSF',
|
||||
'IMS',
|
||||
'N3IWF',
|
||||
'NEF',
|
||||
'LMF',
|
||||
];
|
||||
const result = await request({
|
||||
url: '/api/rest/systemManagement/v1/elementType/all/objectType/systemState',
|
||||
method: 'get',
|
||||
@@ -19,6 +36,10 @@ export async function listMain() {
|
||||
const [key, value] = Object.entries(obj)[0];
|
||||
const ipAddress = (value as any).ipAddress;
|
||||
const systemState = (value as any).systemState;
|
||||
const serialNum = (value as any).serialNum;
|
||||
const version = (value as any).version;
|
||||
|
||||
|
||||
const errCode = systemState && systemState['errorCode'];
|
||||
var time = new Date();
|
||||
// console.log(key, value);
|
||||
@@ -33,9 +54,10 @@ export async function listMain() {
|
||||
};
|
||||
} else {
|
||||
mergedObj = {
|
||||
version: '-',
|
||||
version,
|
||||
refresh: parseDateToStr(time),
|
||||
ipAddress: ipAddress,
|
||||
ipAddress,
|
||||
serialNum,
|
||||
name: key.split('/').join('_'),
|
||||
status: 'Abnormal',
|
||||
};
|
||||
@@ -43,8 +65,16 @@ export async function listMain() {
|
||||
return mergedObj;
|
||||
});
|
||||
|
||||
// console.log(mergedData);
|
||||
// console.log(rowArr)
|
||||
//通过sort进行冒泡排序
|
||||
mergedData.sort((a: any, b: any) => {
|
||||
const typeA = specificOrder.indexOf(a.name.split('_')[0]);
|
||||
const typeB = specificOrder.indexOf(b.name.split('_')[0]);
|
||||
if (typeA === -1) return 1; // 如果不在特定顺序中,排到后面
|
||||
if (typeB === -1) return -1; // 如果不在特定顺序中,排到后面
|
||||
return typeA - typeB;
|
||||
});
|
||||
//console.log(mergedData);
|
||||
|
||||
return mergedData;
|
||||
}
|
||||
|
||||
@@ -77,15 +107,3 @@ export function getSysConf() {
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 转存上传文件到静态资源
|
||||
* @returns object
|
||||
*/
|
||||
export function transferStaticFile(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/transferStaticFile`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
29
src/api/ne/ne.ts
Normal file
29
src/api/ne/ne.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询网元列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listNe(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询网元状态
|
||||
* @param neType 网元类型
|
||||
* @param neId 网元ID
|
||||
* @returns object
|
||||
*/
|
||||
export function stateNe(neType: string, neId: string) {
|
||||
return request({
|
||||
url: '/ne/state',
|
||||
method: 'get',
|
||||
params: { neType, neId },
|
||||
});
|
||||
}
|
||||
@@ -111,9 +111,9 @@ export function batchAuth(data: Record<string, any>) {
|
||||
* @param data 鉴权对象
|
||||
* @returns object
|
||||
*/
|
||||
export function delAuth(neId: string, data: Record<string, any>) {
|
||||
export function delAuth(neId: string, imsi: string) {
|
||||
return request({
|
||||
url: `/ne/udm/auth/${neId}/${data.imsi}`,
|
||||
url: `/ne/udm/auth/${neId}/${imsi}`,
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -91,6 +91,8 @@ export async function goldData(query: Record<string, any>) {
|
||||
startTime: query.beginTime,
|
||||
endTime: query.endTime,
|
||||
interval: query.particle,
|
||||
sortField:query.sortField,
|
||||
sortOrder:query.sortOrder
|
||||
},
|
||||
timeout: 60_000,
|
||||
});
|
||||
|
||||
@@ -199,6 +199,18 @@ export function chunkUpload(data: FormData) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 转存上传文件到静态资源
|
||||
* @returns object
|
||||
*/
|
||||
export function transferStaticFile(data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/file/transferStaticFile`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传切片文件并发送文件到网元端
|
||||
* @param neType 网元类型, UPF
|
||||
|
||||
29
src/api/tool/neFile.ts
Normal file
29
src/api/tool/neFile.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { request } from '@/plugins/http-fetch';
|
||||
|
||||
/**
|
||||
* 查询文件列表列表
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function listNeFiles(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/action/files',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件
|
||||
* @param query 查询参数
|
||||
* @returns object
|
||||
*/
|
||||
export function getNeFile(query: Record<string, any>) {
|
||||
return request({
|
||||
url: '/ne/action/pullFile',
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob',
|
||||
timeout: 180_000,
|
||||
});
|
||||
}
|
||||
392
src/components/ChartGraphG6/index.vue
Normal file
392
src/components/ChartGraphG6/index.vue
Normal file
@@ -0,0 +1,392 @@
|
||||
<template>
|
||||
<div>
|
||||
<div ref="chartGraphG6Dom" :style="{ height: height, width: width }"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, watch, onMounted, onBeforeUnmount, ref } from 'vue';
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const props = defineProps({
|
||||
/**
|
||||
* 图表主题
|
||||
*
|
||||
* 'dark' | 'light'
|
||||
*/
|
||||
theme: {
|
||||
type: String,
|
||||
default: 'light', // 'dark' | 'light'
|
||||
},
|
||||
/**宽度,默认100% */
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%',
|
||||
},
|
||||
/**高度 */
|
||||
height: {
|
||||
type: String,
|
||||
default: '500px',
|
||||
},
|
||||
});
|
||||
|
||||
const chartGraphG6Dom = ref<HTMLElement | undefined>(undefined);
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
// 0 基站
|
||||
{
|
||||
id: '0',
|
||||
x: 50,
|
||||
y: 150,
|
||||
size: 48,
|
||||
type: 'circle',
|
||||
label: '基站',
|
||||
labelCfg: {
|
||||
position: 'bottom',
|
||||
offset: 10,
|
||||
style: {
|
||||
fill: '#333',
|
||||
stroke: '#fff',
|
||||
lineWidth: 10,
|
||||
},
|
||||
},
|
||||
style: {
|
||||
fill: '#9EC9FF',
|
||||
stroke: '#5B8FF9',
|
||||
lineWidth: 2,
|
||||
},
|
||||
icon: {
|
||||
show: true,
|
||||
// 可更换为其他图片地址
|
||||
img: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',
|
||||
width: 24,
|
||||
height: 24,
|
||||
},
|
||||
},
|
||||
// 1 DM
|
||||
{
|
||||
id: '1',
|
||||
x: 450,
|
||||
y: 450,
|
||||
label: 'DM',
|
||||
labelCfg: {
|
||||
position: 'center',
|
||||
},
|
||||
style: {
|
||||
fill: '#00b050',
|
||||
stroke: '#00b050',
|
||||
lineWidth: 1,
|
||||
},
|
||||
},
|
||||
// 2 O&M
|
||||
{
|
||||
id: '2',
|
||||
x: 50,
|
||||
y: 450,
|
||||
label: 'O&M',
|
||||
},
|
||||
// 100 EMS
|
||||
{
|
||||
id: '100',
|
||||
label: 'EMS',
|
||||
comboId: 'combo-ems',
|
||||
x: 300,
|
||||
y: 450,
|
||||
},
|
||||
// 190 UPF
|
||||
{
|
||||
id: '190',
|
||||
comboId: 'combo-upf',
|
||||
x: 300,
|
||||
y: 350,
|
||||
label: 'UPF',
|
||||
labelCfg: {
|
||||
position: 'center',
|
||||
},
|
||||
style: {
|
||||
fill: '#d580ff',
|
||||
stroke: '#d580ff',
|
||||
lineWidth: 1,
|
||||
},
|
||||
},
|
||||
// EP-IMS
|
||||
{
|
||||
id: '110',
|
||||
comboId: 'combo-ims',
|
||||
x: 600,
|
||||
y: 350,
|
||||
label: 'IMS',
|
||||
labelCfg: {
|
||||
position: 'center',
|
||||
},
|
||||
style: {
|
||||
fill: '#ed7d31',
|
||||
stroke: '#ed7d31',
|
||||
lineWidth: 1,
|
||||
},
|
||||
},
|
||||
// 5GC控制面
|
||||
{
|
||||
id: '170',
|
||||
label: 'NSSF',
|
||||
comboId: 'combo-5gc',
|
||||
x: 300,
|
||||
y: 50,
|
||||
},
|
||||
{
|
||||
id: '130',
|
||||
label: 'AUSF',
|
||||
comboId: 'combo-5gc',
|
||||
x: 450,
|
||||
y: 50,
|
||||
},
|
||||
{
|
||||
id: '140',
|
||||
label: 'UDM',
|
||||
comboId: 'combo-5gc',
|
||||
x: 600,
|
||||
y: 50,
|
||||
},
|
||||
{
|
||||
id: '120',
|
||||
label: 'AMF',
|
||||
comboId: 'combo-5gc',
|
||||
x: 300,
|
||||
y: 150,
|
||||
},
|
||||
{
|
||||
id: '180',
|
||||
label: 'NRF',
|
||||
comboId: 'combo-5gc',
|
||||
x: 450,
|
||||
y: 150,
|
||||
},
|
||||
{
|
||||
id: '150',
|
||||
label: 'SMF',
|
||||
comboId: 'combo-5gc',
|
||||
x: 300,
|
||||
y: 250,
|
||||
},
|
||||
{
|
||||
id: '160',
|
||||
label: 'PCF',
|
||||
comboId: 'combo-5gc',
|
||||
x: 700,
|
||||
y: 250,
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
id: '0-5gc',
|
||||
source: '0',
|
||||
target: 'combo-5gc',
|
||||
},
|
||||
{
|
||||
id: '0-upf',
|
||||
source: '0',
|
||||
target: 'combo-upf',
|
||||
},
|
||||
{
|
||||
id: 'upf-1',
|
||||
source: 'combo-upf',
|
||||
target: '1',
|
||||
},
|
||||
|
||||
{
|
||||
id: 'ems-2',
|
||||
source: 'combo-ems',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
id: '170-120',
|
||||
source: '170',
|
||||
target: '120',
|
||||
},
|
||||
{
|
||||
id: '130-120',
|
||||
source: '130',
|
||||
target: '120',
|
||||
},
|
||||
{
|
||||
id: '140-120',
|
||||
source: '140',
|
||||
target: '120',
|
||||
},
|
||||
{
|
||||
id: '140-180',
|
||||
source: '140',
|
||||
target: '180',
|
||||
},
|
||||
{
|
||||
id: '120-180',
|
||||
source: '120',
|
||||
target: '180',
|
||||
},
|
||||
{
|
||||
id: '130-180',
|
||||
source: '130',
|
||||
target: '180',
|
||||
},
|
||||
{
|
||||
id: '140-150',
|
||||
source: '140',
|
||||
target: '150',
|
||||
},
|
||||
{
|
||||
id: '140-110',
|
||||
source: '140',
|
||||
target: '110',
|
||||
},
|
||||
{
|
||||
id: '120-150',
|
||||
source: '120',
|
||||
target: '150',
|
||||
data: {},
|
||||
},
|
||||
{
|
||||
id: '150-180',
|
||||
source: '150',
|
||||
target: '180',
|
||||
data: {},
|
||||
},
|
||||
{
|
||||
id: '150-160',
|
||||
source: '150',
|
||||
target: '160',
|
||||
},
|
||||
{
|
||||
id: '160-120',
|
||||
source: '160',
|
||||
target: '120',
|
||||
},
|
||||
{
|
||||
id: '160-180',
|
||||
source: '160',
|
||||
target: '180',
|
||||
},
|
||||
{
|
||||
id: '160-110',
|
||||
source: '160',
|
||||
target: '110',
|
||||
},
|
||||
|
||||
{
|
||||
id: '150-190',
|
||||
source: '150',
|
||||
target: '190',
|
||||
},
|
||||
|
||||
{
|
||||
id: 'upf-ims',
|
||||
source: 'combo-upf',
|
||||
target: 'combo-ims',
|
||||
},
|
||||
{
|
||||
id: 'ems-5gc',
|
||||
source: 'combo-ems',
|
||||
target: 'combo-5gc',
|
||||
},
|
||||
{
|
||||
id: 'ems-upf',
|
||||
source: 'combo-ems',
|
||||
target: 'combo-upf',
|
||||
},
|
||||
{
|
||||
id: 'ems-ims',
|
||||
source: 'combo-ems',
|
||||
target: 'combo-ims',
|
||||
},
|
||||
],
|
||||
combos: [
|
||||
{
|
||||
id: 'combo-5gc',
|
||||
data: {
|
||||
text: '5GC控制面',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'combo-upf',
|
||||
data: {
|
||||
keyShape: {
|
||||
opacity: 0.8,
|
||||
padding: [20, 20, 20, 20],
|
||||
radius: 4,
|
||||
lineWidth: 1,
|
||||
stroke: '#d580ff',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'combo-ims',
|
||||
data: {},
|
||||
},
|
||||
{
|
||||
id: 'combo-ems',
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let graph: any = null;
|
||||
|
||||
/**初始化渲染图表 */
|
||||
function initChart() {
|
||||
if (!chartGraphG6Dom.value) return;
|
||||
console.log(chartGraphG6Dom.value.clientWidth);
|
||||
console.log(chartGraphG6Dom.value.clientHeight);
|
||||
graph = new Graph({
|
||||
container: chartGraphG6Dom.value,
|
||||
height: chartGraphG6Dom.value.clientHeight,
|
||||
width: chartGraphG6Dom.value.clientWidth,
|
||||
fitCenter: true,
|
||||
modes: {
|
||||
default: ['drag-canvas', 'zoom-canvas', 'drag-node'], // 允许拖拽画布、放缩画布、拖拽节点
|
||||
},
|
||||
// 全局节点 矩形
|
||||
defaultNode: {
|
||||
type: 'rect',
|
||||
size: [80, 40],
|
||||
style: {
|
||||
fill: '#fff',
|
||||
lineWidth: 1,
|
||||
radius: 8,
|
||||
},
|
||||
labelCfg: {},
|
||||
},
|
||||
// 全局边 三次贝塞尔曲线
|
||||
defaultEdge: {
|
||||
type: 'polyline',
|
||||
style: {
|
||||
offset: 20, // 拐弯处距离节点最小距离
|
||||
radius: 4, // 拐弯处的圆角弧度,若不设置则为直角
|
||||
lineWidth: 1,
|
||||
stroke: '#87e8de',
|
||||
},
|
||||
},
|
||||
// 全局框节点 矩形
|
||||
defaultCombo: {
|
||||
type: 'rect', // Combo 类型
|
||||
size: [40, 40],
|
||||
// ... 其他配置
|
||||
style: {
|
||||
lineWidth: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
graph.data(data); // 加载数据
|
||||
graph.render(); // 渲染
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
initChart();
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -31,11 +31,12 @@ export default function useLocale() {
|
||||
},
|
||||
];
|
||||
|
||||
// 挂载前根据默认语言在设置一次
|
||||
// 挂载前根据默认语言再设置一次
|
||||
onBeforeMount(() => {
|
||||
const localI18n = localGet(CACHE_LOCAL_I18N);
|
||||
if (localI18n) {
|
||||
i18n.locale.value = localI18n;
|
||||
document.documentElement.lang = localI18n.replace('_', '-');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
title: 'Core Network Management Platform',
|
||||
desc: 'Core Network Management Platform',
|
||||
loading: 'Please wait...',
|
||||
ipnutPlease: 'Please input',
|
||||
inputPlease: 'Please input',
|
||||
selectPlease: 'please select',
|
||||
tipTitle: 'Prompt',
|
||||
msgSuccess: 'Success {msg}',
|
||||
@@ -49,7 +49,7 @@ export default {
|
||||
hide: 'Hidden',
|
||||
open: 'Open',
|
||||
shut: 'Shut',
|
||||
launch: 'Launch',
|
||||
launch: 'Expand',
|
||||
fold: 'Fold',
|
||||
},
|
||||
rowId: 'ID',
|
||||
@@ -170,11 +170,11 @@ export default {
|
||||
settings: "Settings",
|
||||
},
|
||||
tabs: {
|
||||
reload: "Refresh current",
|
||||
reload: "Refresh Current Tab",
|
||||
more: "More Options",
|
||||
closeCurrent: "Close Current",
|
||||
closeOther: "Close Other",
|
||||
closeAll: "Close All",
|
||||
closeCurrent: "Close Current Tab",
|
||||
closeOther: "Close Other Tabs",
|
||||
closeAll: "Close All Tabs",
|
||||
}
|
||||
},
|
||||
|
||||
@@ -354,6 +354,9 @@ export default {
|
||||
server:'Server File',
|
||||
local:'Local File',
|
||||
fileSelect:'Please select the current import file',
|
||||
sync:'Synchronize to NE',
|
||||
open:'Open',
|
||||
close:'Close',
|
||||
},
|
||||
backupManage: {
|
||||
setBackupTask: 'Set automatic backup time',
|
||||
@@ -402,6 +405,7 @@ export default {
|
||||
createTime:'Creation time',
|
||||
onlyAble:'Only upload file format {fileText} is supported',
|
||||
nullData:'No network element list data yet',
|
||||
nullVersion:'There is no rollback version for the current network element.',
|
||||
},
|
||||
license: {
|
||||
neTypePlease: 'Select network element type',
|
||||
@@ -455,7 +459,7 @@ export default {
|
||||
addItemOk: "Add Index as {num} Record Succeeded",
|
||||
addItemErr: "Record addition failure",
|
||||
requireUn: "{display} input value is of unknown type",
|
||||
requireString: "The {display} parameter value does not make sense.",
|
||||
requireString: "The {display} parameter value is invalid.",
|
||||
requireInt: "{display} Parameter value not in reasonable range {filter}",
|
||||
requireIpv4: "{display} not a legitimate IPV4 address",
|
||||
requireIpv6: "{display} Not a legitimate IPV6 address.",
|
||||
@@ -464,7 +468,7 @@ export default {
|
||||
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: "commence",
|
||||
arrayMore: "Expand",
|
||||
},
|
||||
},
|
||||
neUser: {
|
||||
@@ -474,6 +478,8 @@ export default {
|
||||
neType: 'UDM Object',
|
||||
export: 'Export',
|
||||
exportConfirm: 'Are you sure to export all authentication user data?',
|
||||
checkExport : 'Check Export',
|
||||
checkExportConfirm: 'Confirm exporting the checked authenticated user data?',
|
||||
import: 'Import',
|
||||
loadDataConfirm: 'Are you sure you want to reload the data?',
|
||||
loadData: 'Load Data',
|
||||
@@ -483,6 +489,7 @@ export default {
|
||||
batchDelText: 'Batch Delete',
|
||||
numAdd: 'Number of releases',
|
||||
numDel: 'Number of deleted',
|
||||
checkDel: 'Check Delete',
|
||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||
imsiTip1: 'MCC=Mobile Country Code, consisting of three digits.',
|
||||
imsiTip2: 'MNC = Mobile Network Number, consisting of two digits',
|
||||
@@ -491,19 +498,22 @@ export default {
|
||||
algoIndexTip: 'Algorithm index, between 0 and 15',
|
||||
kiTip: 'User signing key information, the maximum length of 32',
|
||||
opcTip: 'The authentication key, OPC, is calculated from Ki and OP, OP is the root key of the operator, ki is the authentication key, and the maximum length is 32.',
|
||||
delSure:'Are you sure you want to delete the user with IMSI number: {imsi}?',
|
||||
delSure:'Are you sure you want to delete the user with IMSI number: {imsi} ?',
|
||||
},
|
||||
sub: {
|
||||
subInfo:' Subscription Info',
|
||||
neType: 'UDM Object',
|
||||
export: 'Export',
|
||||
exportConfirm: 'Are you sure to export all signed user data?',
|
||||
checkExport : 'Check Export',
|
||||
checkExportConfirm: 'Are you sure to export the data of the checked subscribers?',
|
||||
import: 'Import',
|
||||
loadDataConfirm: 'Are you sure you want to reload the data?',
|
||||
loadData: 'Load Data',
|
||||
loadDataTip: 'Successfully fetched load data: {num} entries, the system is internally updating the data. You can click reset to refresh the data list after the loading is finished, please don it repeat click to get update!!!!',
|
||||
numAdd: 'Number of releases',
|
||||
numDel: 'Number of deleted',
|
||||
checkDel: 'Check Delete',
|
||||
batchAddText: 'Batch Add',
|
||||
batchDelText: 'Batch Delete',
|
||||
enable:'Enable',
|
||||
@@ -545,6 +555,8 @@ export default {
|
||||
imsiTip2: 'MNC = Mobile Network Number, consisting of two digits',
|
||||
imsiTip3: 'MSIN = Mobile Subscriber Identification Number, consisting of 10 equal digits.',
|
||||
delSure:'Are you sure you want to delete the user with IMSI number: {imsi}?',
|
||||
uploadFileOk: 'File Upload Successful',
|
||||
uploadFileErr: 'File Upload Failed',
|
||||
},
|
||||
base5G: {
|
||||
neType: 'AMF Object',
|
||||
@@ -577,11 +589,11 @@ export default {
|
||||
viewTask:'View Task',
|
||||
editTask:'Edit Task',
|
||||
addTask:'Add Task',
|
||||
stopTask:'Stop Task',
|
||||
stopTask:'Pending',
|
||||
errorTaskInfo: 'Failed to obtain task information',
|
||||
granulOptionPlease:'Please select the measurement granularity',
|
||||
letupSure:'Confirm activation of task with number [{id}]?',
|
||||
stopSure:'Confirm the pending task with number [{row.id}]?',
|
||||
stopSure:'Confirm the pending task with number [{id}]?',
|
||||
letUpWarning:'Prohibit activation of activated tasks',
|
||||
stopWarning: 'Prohibit suspending inactive measurement tasks',
|
||||
weekPlan:'Weekly Plan',
|
||||
@@ -628,7 +640,7 @@ export default {
|
||||
value:'Value',
|
||||
startTime:'Start Time',
|
||||
endTime:'End Time',
|
||||
particle: 'Particle Ssize',
|
||||
particle: 'Granularity',
|
||||
timeFrame: 'Time Range',
|
||||
nullTip:'There are no statistical data within this time range',
|
||||
kpiTitle:'KPI Statistics Chart',
|
||||
@@ -815,7 +827,21 @@ export default {
|
||||
alarmInfo:'Alarm Content',
|
||||
eventTime:'Generation Time',
|
||||
logTime:'Record Time'
|
||||
}
|
||||
},
|
||||
neFile: {
|
||||
neType:'NE Type',
|
||||
neTypePlease:'Please select NE Type',
|
||||
nePath: "Directory Path",
|
||||
fileMode: "File Mode",
|
||||
owner: "Owner",
|
||||
group: "Group",
|
||||
size: "Size",
|
||||
modifiedTime: "Modified Time",
|
||||
fileName: "File Name",
|
||||
downTip: "Confirm the download file name is [{fileName}] File?",
|
||||
downTipErr: "Failed to get file",
|
||||
dirCd: "Enter Dir",
|
||||
},
|
||||
},
|
||||
monitor: {
|
||||
session: {
|
||||
@@ -1287,6 +1313,7 @@ export default {
|
||||
dictData:'Dictionary Data',
|
||||
reload:'Refresh Cache',
|
||||
mark:'Dictionary Description',
|
||||
colorSelect:'Color Picker',
|
||||
},
|
||||
dictData: {
|
||||
dictType: "Dictionary name",
|
||||
@@ -1320,7 +1347,7 @@ export default {
|
||||
cmdNoTip: "{num} no optional command operation",
|
||||
require: "Mandatory parameter: {num}",
|
||||
requireUn: "{display} input value is of unknown type",
|
||||
requireString: "The {display} parameter value does not make sense.",
|
||||
requireString: "The {display} parameter value is invalid.",
|
||||
requireInt: "{display} Parameter value not in reasonable range {filter}",
|
||||
requireIpv4: "{display} not a legitimate IPV4 address",
|
||||
requireIpv6: "{display} Not a legitimate IPV6 address.",
|
||||
@@ -1334,6 +1361,7 @@ export default {
|
||||
cmdAwait: "Waiting for a command to be sent",
|
||||
uploadFileTip: 'Are you sure you want to upload the file?',
|
||||
uploadFileOk: 'File Upload Successful',
|
||||
uploadFileErr: 'File Upload Failed',
|
||||
omcOperate:{
|
||||
noOMC: "No OMC network elements",
|
||||
},
|
||||
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
title: '核心网管理平台',
|
||||
desc: '核心网管理平台',
|
||||
loading: '请稍等...',
|
||||
ipnutPlease: '请输入',
|
||||
inputPlease: '请输入',
|
||||
selectPlease: '请选择',
|
||||
tipTitle: '提示',
|
||||
msgSuccess: '{msg} 成功',
|
||||
@@ -170,11 +170,11 @@ export default {
|
||||
settings: "个人设置",
|
||||
},
|
||||
tabs: {
|
||||
reload: "刷新当前",
|
||||
reload: "刷新当前标签",
|
||||
more: "更多选项",
|
||||
closeCurrent: "关闭当前",
|
||||
closeOther: "关闭其他",
|
||||
closeAll: "关闭全部",
|
||||
closeCurrent: "关闭当前标签",
|
||||
closeOther: "关闭其他标签",
|
||||
closeAll: "关闭全部标签",
|
||||
}
|
||||
},
|
||||
|
||||
@@ -354,6 +354,9 @@ export default {
|
||||
server:'服务器文件',
|
||||
local:'本地文件',
|
||||
fileSelect:'请选择当前导入文件',
|
||||
sync:'同步到网元',
|
||||
open:'开',
|
||||
close:'关',
|
||||
},
|
||||
backupManage: {
|
||||
setBackupTask: '设置自动备份时间',
|
||||
@@ -402,6 +405,7 @@ export default {
|
||||
createTime:'创建时间',
|
||||
onlyAble:'只支持上传文件格式 {fileText}',
|
||||
nullData:'暂无网元列表数据',
|
||||
nullVersion:'当前网元无可回退版本',
|
||||
},
|
||||
license: {
|
||||
neTypePlease: '选择网元类型',
|
||||
@@ -462,8 +466,8 @@ export default {
|
||||
requireEnum: "{display} 不是合理的枚举值",
|
||||
requireBool: "{display} 不是合理的布尔类型的值",
|
||||
editOkTip: "确认更新该{num}属性值吗?",
|
||||
updateItemTip: "确认更新Index为 【{num}】 的数据项?",
|
||||
delItemTip: "确认删除Index为 【{num}】 的数据项?",
|
||||
updateItemTip: "确认更新Index为 【{num}】 的数据项?",
|
||||
delItemTip: "确认删除Index为 【{num}】 的数据项?",
|
||||
arrayMore: "展开",
|
||||
},
|
||||
},
|
||||
@@ -473,9 +477,11 @@ export default {
|
||||
neTypePlease: '查询网元类型',
|
||||
neType: 'UDM网元对象',
|
||||
export: '导出',
|
||||
exportConfirm: '确认导出全部鉴权用户数据吗?',
|
||||
exportConfirm: '确认导出全部鉴权用户数据吗?',
|
||||
checkExport : '勾选导出',
|
||||
checkExportConfirm: '确认导出已勾选的鉴权用户数据吗?',
|
||||
import: '导入',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
loadData: '加载数据',
|
||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新。加载结束后可点击重置刷新数据列表,请勿重复点击获取更新!!!',
|
||||
startIMSI: '起始IMSI',
|
||||
@@ -483,6 +489,7 @@ export default {
|
||||
batchDelText: '批量删除',
|
||||
numAdd: '放号个数',
|
||||
numDel:'删除个数',
|
||||
checkDel:'勾选删除',
|
||||
imsiTip: 'IMSI=MCC+MNC+MSIN',
|
||||
imsiTip1: 'MCC=移动国家号码, 由三位数字组成',
|
||||
imsiTip2: 'MNC=移动网络号,由两位数字组成',
|
||||
@@ -497,13 +504,16 @@ export default {
|
||||
subInfo:'签约信息',
|
||||
neType: 'UDM网元类型',
|
||||
export: '导出',
|
||||
exportConfirm: '确认导出全部签约用户数据吗?',
|
||||
exportConfirm: '确认导出全部签约用户数据吗?',
|
||||
checkExport : '勾选导出',
|
||||
checkExportConfirm: '确认导出已勾选的签约用户数据吗?',
|
||||
import: '导入',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
loadDataConfirm: '确认要重新加载数据吗?',
|
||||
loadData: '加载数据',
|
||||
loadDataTip: '成功获取加载数据:{num}条,系统内部正在进行数据更新。加载结束后可点击重置刷新数据列表,请勿重复点击获取更新!!!',
|
||||
numAdd: '放号个数',
|
||||
numDel: '删除个数',
|
||||
checkDel:'勾选删除',
|
||||
batchAddText: '批量新增',
|
||||
batchDelText: '批量删除',
|
||||
enable:'开启',
|
||||
@@ -545,6 +555,8 @@ export default {
|
||||
imsiTip2: 'MNC=移动网络号,由两位数字组成',
|
||||
imsiTip3: 'MSIN=移动客户识别码,采用等长10位数字构成',
|
||||
delSure:'确认删除IMSI编号为: {imsi} 的用户吗?',
|
||||
uploadFileOk: '文件上传成功',
|
||||
uploadFileErr: '文件上传失败',
|
||||
},
|
||||
base5G: {
|
||||
neType: 'AMF网元对象',
|
||||
@@ -815,7 +827,21 @@ export default {
|
||||
alarmInfo:'告警内容',
|
||||
eventTime:'告警产生时间',
|
||||
logTime:'记录时间'
|
||||
}
|
||||
},
|
||||
neFile: {
|
||||
neType:'网元',
|
||||
neTypePlease:'请选择网元',
|
||||
nePath: "目录路径",
|
||||
fileMode: "文件权限",
|
||||
owner: "所属用户",
|
||||
group: "所属组",
|
||||
size: "文件大小",
|
||||
modifiedTime: "修改时间",
|
||||
fileName: "文件名称",
|
||||
downTip: "确认下载文件名为 【{fileName}】 文件?",
|
||||
downTipErr: "文件获取失败",
|
||||
dirCd: "进入目录",
|
||||
},
|
||||
},
|
||||
monitor: {
|
||||
session: {
|
||||
@@ -1287,6 +1313,7 @@ export default {
|
||||
dictData:'字典数据',
|
||||
reload:'刷新缓存',
|
||||
mark:'字典说明',
|
||||
colorSelect:'取色器',
|
||||
},
|
||||
dictData: {
|
||||
dictType: "字典名称",
|
||||
@@ -1334,6 +1361,7 @@ export default {
|
||||
cmdAwait: "等待发送命令",
|
||||
uploadFileTip: '确认要上传文件吗?',
|
||||
uploadFileOk: '文件上传成功',
|
||||
uploadFileErr: '文件上传失败',
|
||||
omcOperate:{
|
||||
noOMC: "暂无OMC网元",
|
||||
},
|
||||
|
||||
@@ -312,7 +312,7 @@ document.addEventListener('visibilitychange', function () {
|
||||
<template #footerRender="{ width }">
|
||||
<footer class="footer">
|
||||
<div class="footer-fixed" :style="{ width }">
|
||||
<div>
|
||||
<div style="flex: 1;">
|
||||
<span>{{ appStore.copyright }}</span>
|
||||
</div>
|
||||
<a-space direction="horizontal" :size="8">
|
||||
@@ -364,7 +364,7 @@ document.addEventListener('visibilitychange', function () {
|
||||
.footer {
|
||||
z-index: 16;
|
||||
margin: 0px;
|
||||
width: auto;
|
||||
width: auto;
|
||||
margin-top: 52px;
|
||||
&-fixed {
|
||||
position: fixed;
|
||||
@@ -379,6 +379,7 @@ document.addEventListener('visibilitychange', function () {
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px #0015291f;
|
||||
transition: background 0.3s, width 0.2s;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
& #serverTimeDom {
|
||||
|
||||
@@ -6,7 +6,6 @@ import useI18n from '@/hooks/useI18n';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import useAlarmStore from '@/store/modules/alarm';
|
||||
import { sessionGet } from '@/utils/cache-session-utils';
|
||||
const { isFullscreen, toggle } = useFullscreen();
|
||||
const { t, changeLocale, optionsLocale } = useI18n();
|
||||
const userStore = useUserStore();
|
||||
|
||||
@@ -17,5 +17,5 @@ export function parseUrlPath(path: string) {
|
||||
const baseUrl = import.meta.env.PROD
|
||||
? sessionGet('baseUrl') || import.meta.env.VITE_API_BASE_URL
|
||||
: import.meta.env.VITE_API_BASE_URL;
|
||||
return `${baseUrl}${path}`;
|
||||
return `${baseUrl}${path}?r=${Math.random().toFixed(2)}`;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@ type AppStore = {
|
||||
/**应用版本 */
|
||||
appVersion: string;
|
||||
|
||||
/**服务版本 */
|
||||
version: string;
|
||||
buildTime: string;
|
||||
// 序列号
|
||||
serialNum: string;
|
||||
/**应用版权声明 */
|
||||
copyright: string;
|
||||
/**LOGO显示类型 */
|
||||
@@ -41,6 +46,9 @@ const useAppStore = defineStore('app', {
|
||||
appCode: import.meta.env.VITE_APP_CODE,
|
||||
appVersion: import.meta.env.VITE_APP_VERSION,
|
||||
|
||||
version: `-`,
|
||||
buildTime: `-`,
|
||||
serialNum: `-`,
|
||||
copyright: `Copyright ©2023 For ${import.meta.env.VITE_APP_NAME}`,
|
||||
logoType: 'icon',
|
||||
filePathIcon: '',
|
||||
@@ -70,6 +78,9 @@ const useAppStore = defineStore('app', {
|
||||
async fnSysConf() {
|
||||
const res = await getSysConf();
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data) {
|
||||
this.version = res.data.version;
|
||||
this.buildTime = res.data.buildTime;
|
||||
this.serialNum = res.data.serialNum;
|
||||
this.appName = res.data.title;
|
||||
this.copyright = res.data.copyright;
|
||||
this.logoType = res.data.logoType;
|
||||
|
||||
@@ -10,7 +10,7 @@ type NeInfo = {
|
||||
/**网元列表 */
|
||||
neList: Record<string, any>[];
|
||||
/**级联options树结构 */
|
||||
neCascaderOtions: Record<string, any>[];
|
||||
neCascaderOptions: Record<string, any>[];
|
||||
/**选择器单级父类型 */
|
||||
neSelectOtions: Record<string, any>[];
|
||||
/**跟踪接口列表 */
|
||||
@@ -22,7 +22,7 @@ type NeInfo = {
|
||||
const useNeInfoStore = defineStore('neinfo', {
|
||||
state: (): NeInfo => ({
|
||||
neList: [],
|
||||
neCascaderOtions: [],
|
||||
neCascaderOptions: [],
|
||||
neSelectOtions: [],
|
||||
traceInterfaceList: [],
|
||||
perMeasurementList: [],
|
||||
@@ -33,8 +33,8 @@ const useNeInfoStore = defineStore('neinfo', {
|
||||
* @param state 内部属性不用传入
|
||||
* @returns 级联options
|
||||
*/
|
||||
getNeCascaderOtions(state) {
|
||||
return state.neCascaderOtions;
|
||||
getNeCascaderOptions(state) {
|
||||
return state.neCascaderOptions;
|
||||
},
|
||||
/**
|
||||
* 选择器单级父类型
|
||||
@@ -70,7 +70,7 @@ const useNeInfoStore = defineStore('neinfo', {
|
||||
'neName',
|
||||
'neId'
|
||||
);
|
||||
this.neCascaderOtions = options;
|
||||
this.neCascaderOptions = options;
|
||||
|
||||
// 转选择器单级父类型
|
||||
this.neSelectOtions = options.map(item => item);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { read, utils, write } from 'xlsx';
|
||||
import { JSON2SheetOpts, read, utils, write } from 'xlsx';
|
||||
|
||||
// 静态资源路径
|
||||
const baseUrl = import.meta.env.VITE_HISTORY_BASE_URL;
|
||||
@@ -19,7 +19,10 @@ export const xlsxUrl = `${
|
||||
* console.log(res)
|
||||
* });
|
||||
*/
|
||||
export async function readLoalXlsx(lang:string,id: string): Promise<Record<string, any>[]> {
|
||||
export async function readLoalXlsx(
|
||||
lang: string,
|
||||
id: string
|
||||
): Promise<Record<string, any>[]> {
|
||||
let result = await fetch(`${xlsxUrl}/${lang}/${id}.xlsx`);
|
||||
let fileBuffer = await result.arrayBuffer();
|
||||
// 判断是否xlsx文件
|
||||
@@ -62,11 +65,17 @@ export async function readSheet(
|
||||
* );
|
||||
*
|
||||
*/
|
||||
export async function writeSheet(data: any[], sheetName: string) {
|
||||
export async function writeSheet(
|
||||
data: any[],
|
||||
sheetName: string,
|
||||
opts?: JSON2SheetOpts
|
||||
) {
|
||||
if (data.length === 0) {
|
||||
return new Blob([], { type: 'application/octet-stream' });
|
||||
}
|
||||
const workSheet = utils.json_to_sheet(data);
|
||||
|
||||
const workSheet = utils.json_to_sheet(data, opts);
|
||||
|
||||
// 设置列宽度,单位厘米
|
||||
workSheet['!cols'] = Object.keys(data[0]).map(() => {
|
||||
return { wch: 20 };
|
||||
|
||||
@@ -28,7 +28,8 @@ export const regExpUserName = /^[a-zA-Z][a-z0-9A-Z]{4,}$/;
|
||||
*
|
||||
* 密码至少包含大小写字母、数字、特殊符号,且不少于6位
|
||||
*/
|
||||
export const regExpPasswd = /^(?![A-Za-z0-9]+$)(?![a-z0-9\W]+$)(?![A-Za-z\W]+$)(?![A-Z0-9\W]+$)[a-zA-Z0-9\W]{6,}$/;
|
||||
export const regExpPasswd =
|
||||
/^(?![A-Za-z0-9]+$)(?![a-z0-9\W]+$)(?![A-Za-z\W]+$)(?![A-Z0-9\W]+$)[a-zA-Z0-9\W]{6,}$/;
|
||||
|
||||
/**
|
||||
* 有效手机号格式
|
||||
@@ -63,6 +64,44 @@ export function validHttp(link: string): boolean {
|
||||
return regExpHttp.test(link);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有效URL地址
|
||||
* @param str 网络链接
|
||||
* @returns true | false
|
||||
*/
|
||||
export function validURL(str: string) {
|
||||
if (
|
||||
str === '' ||
|
||||
str.length >= 2083 ||
|
||||
str.length <= 3 ||
|
||||
str.startsWith('.')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
let strTemp = str;
|
||||
if (str.includes(':') && !str.includes('://')) {
|
||||
// support no indicated urlscheme but with colon for port number
|
||||
// http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
|
||||
strTemp = 'http://' + str;
|
||||
}
|
||||
debugger;
|
||||
try {
|
||||
new URL(strTemp);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
const u = new URL(strTemp);
|
||||
if (u.host.startsWith('.')) {
|
||||
return false;
|
||||
}
|
||||
if (u.host === '' && u.pathname !== '' && !u.pathname.includes('.')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 正则表达式模式(rxURL)未提供,无法进行具体判断
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为有效手机号格式
|
||||
* @param mobile 手机号字符串
|
||||
|
||||
@@ -20,7 +20,7 @@ import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
|
||||
const { t } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
let neCascaderOtions = ref<Record<string, any>[]>([]);
|
||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**网元类型选择 type,id */
|
||||
let neTypeSelect = ref<string[]>(['', '']);
|
||||
@@ -1068,18 +1068,25 @@ onMounted(() => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length > 0) {
|
||||
// 过滤不可用的网元
|
||||
neCascaderOtions.value = useNeInfoStore().getNeCascaderOtions.filter(
|
||||
neCascaderOptions.value = useNeInfoStore().getNeCascaderOptions.filter(
|
||||
(item: any) => {
|
||||
return !['OMC'].includes(item.value);
|
||||
}
|
||||
);
|
||||
if (neCascaderOptions.value.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOtions.value.find(s => s.value === 'AMF');
|
||||
const item = neCascaderOptions.value.find(s => s.value === 'AMF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOtions.value[0].children[0];
|
||||
const info = neCascaderOptions.value[0]?.children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
}
|
||||
fnGetParamConfigTopTab();
|
||||
@@ -1110,7 +1117,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="neTypeSelect"
|
||||
:options="neCascaderOtions"
|
||||
:options="neCascaderOptions"
|
||||
:allow-clear="false"
|
||||
@change="fnGetParamConfigTopTab"
|
||||
/>
|
||||
|
||||
@@ -19,7 +19,7 @@ import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
const { t } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
let neCascaderOtions = ref<Record<string, any>[]>([]);
|
||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**网元类型选择 type,id */
|
||||
let neTypeSelect = ref<string[]>(['', '']);
|
||||
@@ -989,18 +989,25 @@ onMounted(() => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length > 0) {
|
||||
// 过滤不可用的网元
|
||||
neCascaderOtions.value = useNeInfoStore().getNeCascaderOtions.filter(
|
||||
neCascaderOptions.value = useNeInfoStore().getNeCascaderOptions.filter(
|
||||
(item: any) => {
|
||||
return !['OMC'].includes(item.value);
|
||||
}
|
||||
);
|
||||
if (neCascaderOptions.value.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOtions.value.find(s => s.value === 'AMF');
|
||||
const item = neCascaderOptions.value.find(s => s.value === 'AMF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOtions.value[0].children[0];
|
||||
const info = neCascaderOptions.value[0].children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
}
|
||||
fnGetParamConfigTopTab();
|
||||
@@ -1035,7 +1042,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="neTypeSelect"
|
||||
:options="neCascaderOtions"
|
||||
:options="neCascaderOptions"
|
||||
:allow-clear="false"
|
||||
@change="fnGetParamConfigTopTab"
|
||||
/>
|
||||
|
||||
@@ -16,10 +16,11 @@ import { toRaw } from 'vue';
|
||||
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { DataNode } from 'ant-design-vue/lib/tree';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
let neCascaderOtions = ref<Record<string, any>[]>([]);
|
||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**网元类型选择 type,id */
|
||||
let neTypeSelect = ref<string[]>(['', '']);
|
||||
@@ -1011,35 +1012,40 @@ function fnModalCancel() {
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore()
|
||||
.fnNelist()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length > 0) {
|
||||
// 过滤不可用的网元
|
||||
neCascaderOtions.value = useNeInfoStore().getNeCascaderOtions.filter(
|
||||
(item: any) => {
|
||||
return !['OMC'].includes(item.value);
|
||||
}
|
||||
);
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOtions.value.find(s => s.value === 'AMF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOtions.value[0].children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
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 !['OMC'].includes(item.value);
|
||||
}
|
||||
fnGetParamConfigTopTab();
|
||||
);
|
||||
if (neCascaderOptions.value.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOptions.value.find(s => s.value === 'AMF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOptions.value[0].children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
}
|
||||
fnGetParamConfigTopTab();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1058,7 +1064,7 @@ onMounted(() => {
|
||||
<a-form-item name="neId ">
|
||||
<a-cascader
|
||||
v-model:value="neTypeSelect"
|
||||
:options="neCascaderOtions"
|
||||
:options="neCascaderOptions"
|
||||
:allow-clear="false"
|
||||
@change="fnGetParamConfigTopTab"
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, watch, toRaw, nextTick } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { message } from 'ant-design-vue/lib';
|
||||
import { Modal, message } from 'ant-design-vue/lib';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
@@ -13,13 +13,14 @@ import {
|
||||
addParamConfigInfo,
|
||||
} from '@/api/configManage/configParam';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
|
||||
import { regExpIPv4, regExpIPv6, validURL } from '@/utils/regular-utils';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { DataNode } from 'ant-design-vue/lib/tree';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
let neCascaderOtions = ref<Record<string, any>[]>([]);
|
||||
let neCascaderOptions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**网元类型选择 type,id */
|
||||
let neTypeSelect = ref<string[]>(['', '']);
|
||||
@@ -315,17 +316,21 @@ watch(
|
||||
function arrayEdit(rowIndex: Record<string, any>) {
|
||||
const item = arrayState.data.find((s: any) => s.key === rowIndex.value);
|
||||
if (!item) return;
|
||||
|
||||
const from = arrayEditInit(item, arrayState.dataRule);
|
||||
// 处理信息
|
||||
const row: Record<string, any> = {};
|
||||
for (const v of item.record) {
|
||||
for (const v of from.record) {
|
||||
if (Array.isArray(v.array)) {
|
||||
continue;
|
||||
}
|
||||
row[v.name] = Object.assign({}, v);
|
||||
}
|
||||
|
||||
modalState.from = row;
|
||||
modalState.type = 'arrayEdit';
|
||||
modalState.title = `${treeState.selectNode.topDisplay} ${item.title}`;
|
||||
modalState.key = item.key;
|
||||
modalState.data = item.record.filter((v: any) => !Array.isArray(v.array));
|
||||
modalState.title = `${treeState.selectNode.topDisplay} ${from.title}`;
|
||||
modalState.key = from.key;
|
||||
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||
modalState.visible = true;
|
||||
|
||||
// 关闭嵌套
|
||||
@@ -398,27 +403,37 @@ function arrayEditOk(from: Record<string, any>) {
|
||||
/**多列表删除单行 */
|
||||
function arrayDelete(rowIndex: Record<string, any>) {
|
||||
const index = rowIndex.value;
|
||||
delParamConfigInfo({
|
||||
neType: neTypeSelect.value[0],
|
||||
neId: neTypeSelect.value[1],
|
||||
topTag: treeState.selectNode.topTag,
|
||||
loc: index,
|
||||
}).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.configManage.configParamForm.delItemOk', {
|
||||
num: `${treeState.selectNode.topDisplay} Index-${index}`,
|
||||
}),
|
||||
duration: 2,
|
||||
const title = `${treeState.selectNode.topDisplay} Index-${index}`;
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.configManage.configParamForm.delItemTip', {
|
||||
num: title,
|
||||
}),
|
||||
onOk() {
|
||||
delParamConfigInfo({
|
||||
neType: neTypeSelect.value[0],
|
||||
neId: neTypeSelect.value[1],
|
||||
topTag: treeState.selectNode.topTag,
|
||||
loc: index,
|
||||
}).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.configManage.configParamForm.delItemOk', {
|
||||
num: title,
|
||||
}),
|
||||
duration: 2,
|
||||
});
|
||||
arrayEditClose();
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
arrayEditClose();
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -636,17 +651,21 @@ function arrayChildExpandClose() {
|
||||
function arrayChildEdit(rowIndex: Record<string, any>) {
|
||||
const item = arrayChildState.data.find((s: any) => s.key === rowIndex.value);
|
||||
if (!item) return;
|
||||
|
||||
const from = arrayEditInit(item, arrayChildState.dataRule);
|
||||
// 处理信息
|
||||
const row: Record<string, any> = {};
|
||||
for (const v of item.record) {
|
||||
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} ${item.title}`;
|
||||
modalState.key = item.key;
|
||||
modalState.data = item.record.filter((v: any) => !Array.isArray(v.array));
|
||||
modalState.title = `${arrayChildState.title} ${from.title}`;
|
||||
modalState.key = from.key;
|
||||
modalState.data = from.record.filter((v: any) => !Array.isArray(v.array));
|
||||
modalState.visible = true;
|
||||
}
|
||||
|
||||
@@ -712,27 +731,37 @@ function arrayChildEditOk(from: Record<string, any>) {
|
||||
function arrayChildDelete(rowIndex: Record<string, any>) {
|
||||
const index = rowIndex.value;
|
||||
const loc = `${arrayChildState.loc}/${index}`;
|
||||
delParamConfigInfo({
|
||||
neType: neTypeSelect.value[0],
|
||||
neId: neTypeSelect.value[1],
|
||||
topTag: treeState.selectNode.topTag,
|
||||
loc,
|
||||
}).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.configManage.configParamForm.delItemOk', {
|
||||
num: `${arrayChildState.title} Index-${index}`,
|
||||
}),
|
||||
duration: 2,
|
||||
const title = `${arrayChildState.title} Index-${index}`;
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.configManage.configParamForm.delItemTip', {
|
||||
num: title,
|
||||
}),
|
||||
onOk() {
|
||||
delParamConfigInfo({
|
||||
neType: neTypeSelect.value[0],
|
||||
neId: neTypeSelect.value[1],
|
||||
topTag: treeState.selectNode.topTag,
|
||||
loc,
|
||||
}).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('views.configManage.configParamForm.delItemOk', {
|
||||
num: title,
|
||||
}),
|
||||
duration: 2,
|
||||
});
|
||||
arrayEditClose();
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
arrayEditClose();
|
||||
fnActiveConfigNode('#');
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -813,27 +842,61 @@ function arrayChildAddOk(from: Record<string, any>) {
|
||||
});
|
||||
}
|
||||
|
||||
/**多列表编辑行数据初始化 */
|
||||
function arrayEditInit(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 arrayAddInit(data: any[], dataRule: any) {
|
||||
let newIndex = 0;
|
||||
|
||||
// 有数据时取得最后的index
|
||||
let dataLastIndex = 0;
|
||||
if (data.length !== 0) {
|
||||
const lastFrom = Object.assign({}, JSON.parse(JSON.stringify(data.at(-1))));
|
||||
if (lastFrom.record.length > 0) {
|
||||
newIndex = parseInt(lastFrom.key);
|
||||
dataLastIndex = parseInt(lastFrom.key);
|
||||
dataLastIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const ruleFrom = Object.assign({}, JSON.parse(JSON.stringify(dataRule)));
|
||||
for (const row of ruleFrom.record) {
|
||||
const value = row.value;
|
||||
// 子嵌套的不初始
|
||||
if (row.array) {
|
||||
row.value = [];
|
||||
continue;
|
||||
}
|
||||
// 可选的
|
||||
row.optional = 'true';
|
||||
// index值
|
||||
if (row.name === 'index') {
|
||||
if (newIndex !== 0) {
|
||||
newIndex += 1;
|
||||
} else {
|
||||
newIndex = parseInt(value);
|
||||
}
|
||||
let newIndex = dataLastIndex !== 0 ? dataLastIndex : parseInt(row.value);
|
||||
if (isNaN(newIndex)) {
|
||||
newIndex = 0;
|
||||
}
|
||||
@@ -842,10 +905,12 @@ function arrayAddInit(data: any[], dataRule: any) {
|
||||
ruleFrom.title = `Index-${newIndex}`;
|
||||
continue;
|
||||
}
|
||||
// 子嵌套的不初始
|
||||
if (row.array) {
|
||||
row.value = [];
|
||||
continue;
|
||||
// 根据规则类型转值
|
||||
if (['enum', 'int'].includes(row.type)) {
|
||||
row.value = Number(row.value);
|
||||
}
|
||||
if ('bool' === row.type) {
|
||||
row.value = Boolean(row.value);
|
||||
}
|
||||
}
|
||||
return ruleFrom;
|
||||
@@ -868,7 +933,6 @@ function ruleVerification(row: Record<string, any>): (string | boolean)[] {
|
||||
if (row.optional === 'true' && !value) {
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'int':
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
@@ -938,6 +1002,7 @@ function ruleVerification(row: Record<string, any>): (string | boolean)[] {
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
// 字符串长度判断
|
||||
if (filter && filter.indexOf('~') !== -1) {
|
||||
try {
|
||||
const filterArr = filter.split('~');
|
||||
@@ -956,6 +1021,21 @@ function ruleVerification(row: Record<string, any>): (string | boolean)[] {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
// 字符串http判断
|
||||
if (value.startsWith('http')) {
|
||||
try {
|
||||
if (!validURL(value)) {
|
||||
return [
|
||||
false,
|
||||
t('views.configManage.configParamForm.requireString', {
|
||||
display,
|
||||
}),
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'regex':
|
||||
@@ -1048,42 +1128,47 @@ function fnModalCancel() {
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore()
|
||||
.fnNelist()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length > 0) {
|
||||
// 过滤不可用的网元
|
||||
neCascaderOtions.value = useNeInfoStore().getNeCascaderOtions.filter(
|
||||
(item: any) => {
|
||||
return !['OMC'].includes(item.value);
|
||||
}
|
||||
);
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOtions.value.find(s => s.value === 'UPF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOtions.value[0].children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
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 !['OMC'].includes(item.value);
|
||||
}
|
||||
fnGetParamConfigTopTab();
|
||||
);
|
||||
if (neCascaderOptions.value.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOptions.value.find(s => s.value === 'UPF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOptions.value[0].children[0];
|
||||
neTypeSelect.value = [info.neType, info.neId];
|
||||
}
|
||||
fnGetParamConfigTopTab();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="6">
|
||||
<a-col :lg="6" :md="6" :xs="24" style="margin-bottom: 24px">
|
||||
<!-- 网元类型 -->
|
||||
<a-card
|
||||
size="small"
|
||||
@@ -1095,7 +1180,7 @@ onMounted(() => {
|
||||
<a-form-item name="neId ">
|
||||
<a-cascader
|
||||
v-model:value="neTypeSelect"
|
||||
:options="neCascaderOtions"
|
||||
:options="neCascaderOptions"
|
||||
:allow-clear="false"
|
||||
@change="fnGetParamConfigTopTab"
|
||||
/>
|
||||
@@ -1111,7 +1196,7 @@ onMounted(() => {
|
||||
</a-form>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="18">
|
||||
<a-col :lg="18" :md="18" :xs="24">
|
||||
<a-card
|
||||
size="small"
|
||||
:bordered="false"
|
||||
@@ -1264,19 +1349,20 @@ onMounted(() => {
|
||||
v-model:expanded-row-keys="arrayState.arrayChildExpandKeys"
|
||||
>
|
||||
<!-- 多列新增操作 -->
|
||||
<template #title v-if="treeState.selectNode.method !== 'get'">
|
||||
<template #title>
|
||||
<a-space :size="16" align="center">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="arrayAdd()"
|
||||
size="small"
|
||||
v-if="treeState.selectNode.method !== 'get'"
|
||||
>
|
||||
<template #icon> <PlusOutlined /> </template>
|
||||
{{ t('common.addText') }}
|
||||
</a-button>
|
||||
<TableColumnsDnd
|
||||
type="ghost"
|
||||
:columns="[...arrayState.columns]"
|
||||
:columns="treeState.selectNode.method === 'get' ? [...arrayState.columns.filter((s:any)=>s.key !== 'index')] : arrayState.columns"
|
||||
v-model:columns-dnd="arrayState.columnsDnd"
|
||||
></TableColumnsDnd>
|
||||
</a-space>
|
||||
|
||||
@@ -11,6 +11,7 @@ import useI18n from '@/hooks/useI18n';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import { FileType } from 'ant-design-vue/lib/upload/interface';
|
||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**查询参数 */
|
||||
@@ -129,7 +130,7 @@ function fnTableSize({ key }: MenuInfo) {
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if(pageNum){
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
listLicense(toRaw(queryParams)).then(res => {
|
||||
@@ -267,7 +268,10 @@ function fnBeforeUploadFile(file: FileType) {
|
||||
const fileName = file.name;
|
||||
const suff = fileName.substring(fileName.lastIndexOf('.'));
|
||||
if (!['.ini'].includes(suff)) {
|
||||
message.error(t('views.configManage.softwareManage.onlyAble',{fileText:'(.ini)'}), 3);
|
||||
message.error(
|
||||
t('views.configManage.softwareManage.onlyAble', { fileText: '(.ini)' }),
|
||||
3
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -287,19 +291,17 @@ function fnUploadFile(up: UploadRequestOption) {
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore()
|
||||
.fnNelist()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.configManage.softwareManage.nullData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
neInfoStore.fnNelist().then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.configManage.softwareManage.nullData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -320,7 +322,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="useNeInfoStore().getNeSelectOtions"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
:placeholder="t('views.configManage.license.neTypePlease')"
|
||||
/>
|
||||
@@ -425,10 +427,7 @@ onMounted(() => {
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
>
|
||||
<a-form name="modalStateFrom" layout="horizontal">
|
||||
<a-form-item
|
||||
:label="t('views.configManage.license.neType')"
|
||||
name="neType"
|
||||
@@ -436,7 +435,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="modalState.from.neType"
|
||||
:options="useNeInfoStore().getNeCascaderOtions"
|
||||
:options="useNeInfoStore().getNeCascaderOptions"
|
||||
:allow-clear="false"
|
||||
:placeholder="t('views.configManage.license.neTypePlease')"
|
||||
/>
|
||||
|
||||
@@ -221,6 +221,7 @@ let modalState: ModalStateType = reactive({
|
||||
pvFlag: '',
|
||||
rmUid: '',
|
||||
vendorName: '',
|
||||
sync: true,
|
||||
},
|
||||
importFrom: {
|
||||
neId: '',
|
||||
@@ -453,26 +454,36 @@ function fnRecordDelete(row: Record<string, any>) {
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.configManage.neManage.delSure', { msg: row.neName }),
|
||||
onOk() {
|
||||
tableState.loading = true;
|
||||
const key = 'delNotice';
|
||||
message.loading({ content: t('common.loading'), key });
|
||||
delNeInfo(row).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.msgSuccess', { msg: t('common.deleteText') }),
|
||||
key,
|
||||
duration: 2,
|
||||
});
|
||||
fnGetList();
|
||||
// 刷新缓存的网元信息
|
||||
useNeInfoStore().fnRefreshNelist();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
key: key,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
delNeInfo(row)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
if (res.data.data && res.data.data.affectedRows) {
|
||||
message.success({
|
||||
content: t('common.msgSuccess', {
|
||||
msg: t('common.deleteText'),
|
||||
}),
|
||||
key,
|
||||
duration: 2,
|
||||
});
|
||||
tableState.loading = false;
|
||||
fnGetList();
|
||||
// 刷新缓存的网元信息
|
||||
useNeInfoStore().fnRefreshNelist();
|
||||
}
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
key: key,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
tableState.loading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -873,7 +884,7 @@ onMounted(() => {
|
||||
<template #icon><UndoOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<a-tooltip placement="left">
|
||||
<template #title>{{ t('common.moreText') }}</template>
|
||||
<a-dropdown
|
||||
placement="bottomRight"
|
||||
@@ -902,7 +913,9 @@ onMounted(() => {
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="reload"
|
||||
v-if="!['OMC', 'PCF', 'IMS', 'MME'].includes(record.neType)"
|
||||
v-if="
|
||||
!['OMC', 'PCF', 'IMS', 'MME'].includes(record.neType)
|
||||
"
|
||||
>
|
||||
<SyncOutlined />
|
||||
{{ t('views.configManage.neManage.reload') }}
|
||||
@@ -922,7 +935,7 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 新增框或修改框 -->
|
||||
<a-modal
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -932,7 +945,12 @@ onMounted(() => {
|
||||
@ok="fnModalOk"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form name="modalStateFrom" layout="horizontal">
|
||||
<a-form
|
||||
name="modalStateFrom"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
@@ -1098,9 +1116,21 @@ onMounted(() => {
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.configManage.neManage.sync')"
|
||||
name="province"
|
||||
>
|
||||
<a-switch
|
||||
v-model:checked="modalState.from.sync"
|
||||
:checked-children="t('views.configManage.neManage.open')"
|
||||
:un-checked-children="t('views.configManage.neManage.close')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</DraggableModal>
|
||||
|
||||
<!-- 导入框 -->
|
||||
<a-modal
|
||||
|
||||
@@ -78,41 +78,38 @@ let tableState: TabeStateType = reactive({
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title:t('views.configManage.softwareManage.neType'),
|
||||
title: t('views.configManage.softwareManage.neType'),
|
||||
dataIndex: 'neType',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.neManage.neId'),
|
||||
dataIndex: 'neId',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.softwareManage.versions'),
|
||||
dataIndex: 'version',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.softwareManage.upVersions'),
|
||||
dataIndex: 'preVersion',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
},
|
||||
{
|
||||
title:t('views.configManage.softwareManage.backVersions'),
|
||||
title: t('views.configManage.softwareManage.backVersions'),
|
||||
dataIndex: 'newVersion',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.softwareManage.status'),
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t('views.configManage.softwareManage.letUpTime'),
|
||||
@@ -122,7 +119,7 @@ let tableColumns: ColumnsType = [
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(opt.value);
|
||||
},
|
||||
width: 2,
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -158,7 +155,7 @@ let tablePagination = reactive({
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if(pageNum){
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
@@ -197,7 +194,8 @@ watch(
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="800px"
|
||||
width="100%"
|
||||
wrap-class-name="full-modal"
|
||||
:title="props.title"
|
||||
:visible="props.visible"
|
||||
:keyboard="false"
|
||||
@@ -206,13 +204,9 @@ watch(
|
||||
:footer="null"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form
|
||||
:model="queryParams"
|
||||
name="queryParams"
|
||||
layout="horizontal"
|
||||
>
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-col :lg="6" :md="6" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.configManage.softwareManage.neType')"
|
||||
name="neType"
|
||||
@@ -225,8 +219,11 @@ watch(
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.configManage.softwareManage.createTime')" name="queryRangePicker">
|
||||
<a-col :lg="6" :md="6" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.configManage.softwareManage.createTime')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
@@ -236,7 +233,7 @@ watch(
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-col :lg="6" :md="6" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
@@ -260,7 +257,7 @@ watch(
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:scroll="{ x: 1200, y: 400 }"
|
||||
:scroll="{ x: true }"
|
||||
:pagination="tablePagination"
|
||||
>
|
||||
</a-table>
|
||||
@@ -272,3 +269,22 @@ watch(
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.full-modal {
|
||||
.ant-modal {
|
||||
max-width: 100%;
|
||||
top: 0;
|
||||
padding-bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.ant-modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh);
|
||||
}
|
||||
.ant-modal-body {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import SoftwareHistory from './components/software-history.vue';
|
||||
|
||||
import { listNeVersion } from '@/api/configManage/softwareManage';
|
||||
import {
|
||||
listNeSoftware,
|
||||
delNeSoftware,
|
||||
@@ -64,8 +64,8 @@ type TabeStateType = {
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
size: 'small',
|
||||
seached: false,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
@@ -154,14 +154,20 @@ type FileStateType = {
|
||||
visible: boolean;
|
||||
/**框类型 */
|
||||
visibleType: string;
|
||||
/**回退框是否显示 */
|
||||
visibleByBack: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**提示内容 */
|
||||
content: string;
|
||||
/**OK按钮是否禁用 */
|
||||
okDisable: boolean;
|
||||
/**网元参数 */
|
||||
neOtions: Record<string, any>[];
|
||||
/**表单数据 */
|
||||
from: Record<string, any>;
|
||||
/**回退表单数据 */
|
||||
backFrom: Record<string, any>;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
@@ -170,12 +176,20 @@ type FileStateType = {
|
||||
let fileModalState: FileStateType = reactive({
|
||||
visible: false,
|
||||
visibleType: 'send',
|
||||
visibleByBack: false,
|
||||
title: '下发激活回退',
|
||||
content: '',
|
||||
okDisable: false,
|
||||
neOtions: [],
|
||||
from: {
|
||||
neId: undefined,
|
||||
},
|
||||
backFrom: {
|
||||
ne: undefined,
|
||||
neType: undefined,
|
||||
neId: undefined,
|
||||
version: '',
|
||||
},
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
@@ -192,6 +206,19 @@ const fileModalStateFrom = Form.useForm(
|
||||
})
|
||||
);
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const fileModalStateBackFrom = Form.useForm(
|
||||
fileModalState.backFrom,
|
||||
reactive({
|
||||
ne: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.configManage.softwareManage.neIdPlease'),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* 文件对话框弹出显示为 下发或激活
|
||||
*/
|
||||
@@ -217,13 +244,7 @@ function fnFileModalVisible(type: string | number, row: Record<string, any>) {
|
||||
fileName: row.fileName,
|
||||
});
|
||||
}
|
||||
if (type === 'back') {
|
||||
fileModalState.title = t('views.configManage.softwareManage.backTitle');
|
||||
fileModalState.content = t(
|
||||
'views.configManage.softwareManage.backContent',
|
||||
{ fileName: row.fileName }
|
||||
);
|
||||
}
|
||||
|
||||
if (!fileModalState.content) {
|
||||
return;
|
||||
}
|
||||
@@ -263,9 +284,6 @@ function fnFileModalOk() {
|
||||
if (type === 'run') {
|
||||
fnType = runNeSoftware(from);
|
||||
}
|
||||
if (type === 'back') {
|
||||
fnType = backNeSoftware(from);
|
||||
}
|
||||
if (fnType === null) {
|
||||
return;
|
||||
}
|
||||
@@ -396,6 +414,7 @@ type ModalStateType = {
|
||||
visibleByEdit: boolean;
|
||||
/**网元版本历史框是否显示 */
|
||||
visibleByHistory: boolean;
|
||||
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**表单数据 */
|
||||
@@ -408,6 +427,7 @@ type ModalStateType = {
|
||||
let modalState: ModalStateType = reactive({
|
||||
visibleByEdit: false,
|
||||
visibleByHistory: false,
|
||||
visibleByBack: false,
|
||||
title: '上传更新',
|
||||
from: {
|
||||
neType: undefined,
|
||||
@@ -512,8 +532,10 @@ function fnModalOk() {
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.visibleByEdit = false;
|
||||
fileModalState.visibleByBack = false;
|
||||
modalState.visibleByHistory = false;
|
||||
modalStateFrom.resetFields();
|
||||
fileModalStateBackFrom.resetFields();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -523,6 +545,92 @@ function fnModalVisibleByHistory() {
|
||||
modalState.visibleByHistory = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框弹出显示为 回退框
|
||||
*/
|
||||
function fnModalVisibleByBack() {
|
||||
fileModalState.visibleByBack = true;
|
||||
//fileModalStateBackFrom.resetFields();
|
||||
fileModalState.title = t('views.configManage.softwareManage.backTitle');
|
||||
fileModalState.content = t('views.configManage.softwareManage.neIdPlease');
|
||||
|
||||
if (!fileModalState.content) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**回退网元类型选择对应修改 */
|
||||
function fnNeChange(_: any, item: any) {
|
||||
fileModalState.backFrom.neType = item[1].neType;
|
||||
fileModalState.backFrom.neId = item[1].neId;
|
||||
let queryData: any = fileModalState.backFrom;
|
||||
queryData.status = 'Active';
|
||||
queryData.pageNum = 1;
|
||||
queryData.pageSize = 20;
|
||||
listNeVersion(toRaw(queryData)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
if (
|
||||
!res.total ||
|
||||
!res.rows[0].preVersion ||
|
||||
res.rows[0].preVersion === '-'
|
||||
) {
|
||||
fileModalState.okDisable = true;
|
||||
fileModalState.content = t(
|
||||
'views.configManage.softwareManage.nullVersion'
|
||||
);
|
||||
tableState.loading = false;
|
||||
return;
|
||||
}
|
||||
fileModalState.content = t(
|
||||
'views.configManage.softwareManage.backContent',
|
||||
{ fileName: res.rows[0].preVersion }
|
||||
);
|
||||
fileModalState.backFrom.version = res.rows[0].preVersion;
|
||||
fileModalState.okDisable = false;
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 回退对话框弹出确认执行函数
|
||||
*/
|
||||
function fnBackModalOk() {
|
||||
fileModalStateBackFrom
|
||||
.validate()
|
||||
.then(e => {
|
||||
const from = toRaw(fileModalState.backFrom);
|
||||
// 发送请求
|
||||
fileModalState.confirmLoading = true;
|
||||
const hide = message.loading({ content: t('common.loading') });
|
||||
backNeSoftware(from)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.msgSuccess', { msg: fileModalState.title }),
|
||||
duration: 3,
|
||||
});
|
||||
fnFileModalCancel();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${fileModalState.title} ${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
fileModalState.visibleByBack = false;
|
||||
fileModalStateBackFrom.resetFields();
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
fileModalState.visibleByBack = false;
|
||||
fileModalState.confirmLoading = false;
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
|
||||
});
|
||||
}
|
||||
|
||||
/**上传前检查或转换压缩 */
|
||||
function fnBeforeUploadFile(file: FileType) {
|
||||
if (modalState.confirmLoading) return false;
|
||||
@@ -537,10 +645,14 @@ function fnBeforeUploadFile(file: FileType) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// 根据给定的软件名取版本号 ims-r2.2312.8_u18.deb
|
||||
const nameArr = fileName.split('.')
|
||||
if(nameArr.length > 3) {
|
||||
modalState.from.version = nameArr[1]
|
||||
// 根据给定的软件名取版本号 ims-r2.2312.x-ub22.deb
|
||||
const matches = fileName.match(/([0-9.]+[0-9x]+)/);
|
||||
if (matches) {
|
||||
modalState.from.version = matches[0];
|
||||
}
|
||||
const neTypeIndex = fileName.indexOf('-');
|
||||
if (neTypeIndex !== -1) {
|
||||
modalState.from.neType = fileName.substring(0, neTypeIndex).toUpperCase();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -653,6 +765,10 @@ onMounted(() => {
|
||||
<template #icon><UploadOutlined /></template>
|
||||
{{ t('common.uploadText') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnModalVisibleByBack()">
|
||||
<template #icon> <UndoOutlined /></template>
|
||||
{{ t('views.configManage.softwareManage.backBtn') }}
|
||||
</a-button>
|
||||
<a-button type="dashed" @click.prevent="fnModalVisibleByHistory()">
|
||||
<template #icon><HistoryOutlined /></template>
|
||||
{{ t('views.configManage.softwareManage.historyBtn') }}
|
||||
@@ -664,11 +780,15 @@ onMounted(() => {
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<template #title>{{
|
||||
tableState.seached
|
||||
? t('common.switch.show')
|
||||
: t('common.switch.hide')
|
||||
}}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
:checked-children="t('common.searchBarText')"
|
||||
:un-checked-children="t('common.searchBarText')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
@@ -741,7 +861,7 @@ onMounted(() => {
|
||||
<template #icon><ThunderboltOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<a-tooltip placement="left">
|
||||
<template #title>{{ t('common.moreText') }}</template>
|
||||
<a-dropdown
|
||||
placement="bottomRight"
|
||||
@@ -762,10 +882,6 @@ onMounted(() => {
|
||||
<DeleteOutlined />
|
||||
{{ t('common.deleteText') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="back">
|
||||
<UndoOutlined />
|
||||
{{ t('views.configManage.softwareManage.backBtn') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
@@ -777,7 +893,7 @@ onMounted(() => {
|
||||
</a-card>
|
||||
|
||||
<!-- 上传框 -->
|
||||
<a-modal
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
@@ -870,7 +986,7 @@ onMounted(() => {
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</DraggableModal>
|
||||
|
||||
<!-- 上传激活历史 -->
|
||||
<SoftwareHistory
|
||||
@@ -879,7 +995,7 @@ onMounted(() => {
|
||||
@cancel="fnModalCancel"
|
||||
/>
|
||||
|
||||
<!-- 文件框 下发激活回退 -->
|
||||
<!-- 文件框 下发激活 -->
|
||||
<a-modal
|
||||
width="600px"
|
||||
:keyboard="false"
|
||||
@@ -910,6 +1026,41 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 回退框 -->
|
||||
<a-modal
|
||||
width="800px"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="fileModalState.visibleByBack"
|
||||
:title="fileModalState.title"
|
||||
:confirm-loading="fileModalState.confirmLoading"
|
||||
@ok="fnBackModalOk"
|
||||
:ok-button-props="{ disabled: fileModalState.okDisable }"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form name="fileModalState" layout="horizontal">
|
||||
<a-form-item name="content">
|
||||
<QuestionCircleOutlined class="file-model__icon" />
|
||||
<span class="file-model__tip">
|
||||
{{ fileModalState.content }}
|
||||
</span>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.configManage.license.neType')"
|
||||
name="ne"
|
||||
v-bind="fileModalStateBackFrom.validateInfos.ne"
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="fileModalState.backFrom.ne"
|
||||
:options="useNeInfoStore().getNeCascaderOptions"
|
||||
:allow-clear="false"
|
||||
@change="fnNeChange"
|
||||
:placeholder="t('views.configManage.softwareManage.neTypePlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -18,11 +18,12 @@ import {
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import saveAs from 'file-saver';
|
||||
import TableColumnsDnd from '@/components/TableColumnsDnd/index.vue';
|
||||
import { writeSheet } from '@/utils/execl-utils';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { readLoalXlsx } from '@/utils/execl-utils';
|
||||
const { getDict } = useDictStore();
|
||||
const { t,currentLocale } = useI18n();
|
||||
const { t, currentLocale } = useI18n();
|
||||
|
||||
/**字典数据 */
|
||||
let dict: {
|
||||
@@ -41,6 +42,9 @@ let dict: {
|
||||
activeAlarmSeverity: [],
|
||||
});
|
||||
|
||||
/**表格字段列排序 */
|
||||
let tableColumnsDnd = ref<ColumnsType>([]);
|
||||
|
||||
/**记录开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
@@ -164,6 +168,7 @@ let tableColumns: ColumnsType = [
|
||||
title: t('views.faultManage.activeAlarm.origLevel'),
|
||||
align: 'center',
|
||||
key: 'origSeverity',
|
||||
dataIndex: 'origSeverity',
|
||||
width: 5,
|
||||
},
|
||||
{
|
||||
@@ -233,9 +238,6 @@ let tableColumns: ColumnsType = [
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
/**帮助文档表格字段列 */
|
||||
let alarmTableColumns: ColumnsType = [
|
||||
{
|
||||
@@ -246,19 +248,19 @@ let alarmTableColumns: ColumnsType = [
|
||||
},
|
||||
{
|
||||
title: t('views.faultManage.activeAlarm.locationInfo'),
|
||||
dataIndex: 'alarmInfo',
|
||||
dataIndex: 'alarmInfo',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
},
|
||||
{
|
||||
title: t('views.faultManage.activeAlarm.addInfo'),
|
||||
dataIndex:'helpInfo',
|
||||
dataIndex: 'helpInfo',
|
||||
align: 'center',
|
||||
width: 8,
|
||||
},
|
||||
{
|
||||
title: t('views.faultManage.activeAlarm.alarmType'),
|
||||
dataIndex: 'alarmType',
|
||||
dataIndex: 'alarmType',
|
||||
align: 'center',
|
||||
width: 5,
|
||||
},
|
||||
@@ -294,7 +296,7 @@ let alarmTableColumns: ColumnsType = [
|
||||
},
|
||||
{
|
||||
title: t('views.faultManage.activeAlarm.objectNf'),
|
||||
dataIndex:'objNf',
|
||||
dataIndex: 'objNf',
|
||||
align: 'center',
|
||||
width: 2,
|
||||
},
|
||||
@@ -416,14 +418,12 @@ function fnModalVisibleByVive(row: Record<string, any>) {
|
||||
modalState.visibleByView = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 告警帮助文档详细信息 */
|
||||
function fnModalVisibleBy(code: string) {
|
||||
modalState.helpShowView = false;
|
||||
const lang=currentLocale.value.split('_')[0];
|
||||
modalState.title=t('views.faultManage.activeAlarm.helpFile');
|
||||
readLoalXlsx(lang,code)
|
||||
const lang = currentLocale.value.split('_')[0];
|
||||
modalState.title = t('views.faultManage.activeAlarm.helpFile');
|
||||
readLoalXlsx(lang, code)
|
||||
.then(res => {
|
||||
alarmTableState.data = res;
|
||||
modalState.helpShowView = true;
|
||||
@@ -438,7 +438,7 @@ function fnModalVisibleBy(code: string) {
|
||||
function fnModalOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const from = toRaw(modalState.from);
|
||||
if (from.ackState) {
|
||||
if (from.ackState === '1') {
|
||||
message.error({
|
||||
content: t('views.faultManage.activeAlarm.ackError'),
|
||||
duration: 3,
|
||||
@@ -631,6 +631,15 @@ function fnExportAll() {
|
||||
onOk() {
|
||||
const key = 'exportAlarm';
|
||||
message.loading({ content: t('common.loading'), key });
|
||||
let sortArr: any = [];
|
||||
tableColumnsDnd.value.forEach((item: any) => {
|
||||
if (item.dataIndex) sortArr.push(item.dataIndex);
|
||||
});
|
||||
|
||||
// 排序字段
|
||||
const sortData = {
|
||||
header: sortArr,
|
||||
};
|
||||
exportAll(queryParams).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
@@ -638,7 +647,7 @@ function fnExportAll() {
|
||||
key,
|
||||
duration: 3,
|
||||
});
|
||||
writeSheet(res.data, 'alarm').then(fileBlob =>
|
||||
writeSheet(res.data, 'alarm', sortData).then(fileBlob =>
|
||||
saveAs(fileBlob, `alarm_${Date.now()}.xlsx`)
|
||||
);
|
||||
} else {
|
||||
@@ -661,7 +670,7 @@ function fnModalCancel() {
|
||||
modalState.visibleByEdit = false;
|
||||
modalState.visibleByView = false;
|
||||
modalState.visibleByShowSet = false;
|
||||
modalState.helpShowView=false;
|
||||
modalState.helpShowView = false;
|
||||
}
|
||||
|
||||
/**查询列表, pageNum初始页数 */
|
||||
@@ -850,7 +859,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnCancelConfirm()"
|
||||
@@ -890,12 +899,12 @@ onMounted(() => {
|
||||
<template #icon> <export-outlined /> </template>
|
||||
{{ t('views.faultManage.activeAlarm.exportAll') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -935,14 +944,18 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
<TableColumnsDnd
|
||||
:columns="tableColumns"
|
||||
v-model:columns-dnd="tableColumnsDnd"
|
||||
></TableColumnsDnd>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:columns="tableColumnsDnd"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
@@ -1006,7 +1019,6 @@ onMounted(() => {
|
||||
</a-table>
|
||||
</a-card>
|
||||
|
||||
|
||||
<!-- 帮助文档 -->
|
||||
<a-modal
|
||||
width="100%"
|
||||
@@ -1027,7 +1039,7 @@ onMounted(() => {
|
||||
:data-source="alarmTableState.data"
|
||||
:size="alarmTableState.size"
|
||||
:pagination="false"
|
||||
:scroll="{ x: 1700, y: 560 }"
|
||||
:scroll="{ x: 1700, y: '82vh' }"
|
||||
>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
@@ -1052,12 +1064,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.alarmId')"
|
||||
name="alarmId"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmId"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmId }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1065,12 +1072,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.alarmSeq')"
|
||||
name="alarmSeq"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmSeq"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmSeq }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1081,12 +1083,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neId')"
|
||||
name="neId"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.neId"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.neId }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1094,12 +1091,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neName')"
|
||||
name="neName"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.neName"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.neName }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1110,12 +1102,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neType')"
|
||||
name="neType"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.neType"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.neType }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1123,12 +1110,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.alarmCode')"
|
||||
name="alarmCode"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmCode"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmCode }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1139,12 +1121,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.alarmTitle')"
|
||||
name="alarmTitle"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmTitle"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmTitle }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1152,85 +1129,37 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.eventTime')"
|
||||
name="eventTime"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.eventTime"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.eventTime }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.alarmTitle')"
|
||||
name="alarmTitle"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmTitle"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.alarmType')"
|
||||
name="alarmType"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.alarmType"
|
||||
style="width: 100%"
|
||||
:options="dict.activeAlarmType"
|
||||
disabled
|
||||
>
|
||||
</a-select>
|
||||
{{ modalState.from.alarmType }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.pvFlag')"
|
||||
name="pvFlag"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.pvFlag"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.objectName')"
|
||||
name="objectName"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.objectName"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.pvFlag }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16"> </a-row>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.locationInfo')"
|
||||
name="locationInfo"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.locationInfo"
|
||||
placeholder="Autosize height with minimum and maximum number of lines"
|
||||
:auto-size="{ minRows: 1, maxRows: 5 }"
|
||||
disabled
|
||||
/>
|
||||
{{ modalState.from.locationInfo }}
|
||||
</a-form-item>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1238,12 +1167,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.province')"
|
||||
name="province"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.province"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.province }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1251,13 +1175,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.origLevel')"
|
||||
name="origSeverity"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.origSeverity"
|
||||
style="width: 100%"
|
||||
:options="dict.activeAlarmSeverity"
|
||||
disabled
|
||||
>
|
||||
</a-select>
|
||||
{{ modalState.from.origSeverity }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1266,33 +1184,20 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.addInfo')"
|
||||
name="addInfo"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.addInfo"
|
||||
:auto-size="{ minRows: 1, maxRows: 5 }"
|
||||
disabled
|
||||
/>
|
||||
{{ modalState.from.addInfo }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.specificProblemId')"
|
||||
name="specificProblemId"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.specificProblemId"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.specificProblemId }}
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.specificProblem')"
|
||||
name="specificProblem"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.specificProblem"
|
||||
:auto-size="{ minRows: 1, maxRows: 5 }"
|
||||
disabled
|
||||
/>
|
||||
{{ modalState.from.specificProblem }}
|
||||
</a-form-item>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1300,13 +1205,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.clearType')"
|
||||
name="clearType"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.clearType"
|
||||
style="width: 100%"
|
||||
:options="dict.activeClearType"
|
||||
disabled
|
||||
>
|
||||
</a-select>
|
||||
{{ modalState.from.clearType }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1314,12 +1213,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.clearTime')"
|
||||
name="clearTime"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.clearTime"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.clearTime }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1330,12 +1224,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.ackUser')"
|
||||
name="ackUser"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.ackUser"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.ackUser }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1343,12 +1232,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.ackState')"
|
||||
name="ackState"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.ackState"
|
||||
style="width: 100%"
|
||||
:options="dict.activeAckState"
|
||||
disabled
|
||||
/>
|
||||
{{ modalState.from.ackState }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1359,12 +1243,15 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.ackTime')"
|
||||
name="ackTime"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.ackTime"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.ackTime }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.objectName')"
|
||||
name="objectName"
|
||||
>
|
||||
{{ modalState.from.objectName }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1573,6 +1460,9 @@ onMounted(() => {
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.full-modal {
|
||||
.ant-modal {
|
||||
max-width: 100%;
|
||||
|
||||
@@ -39,6 +39,9 @@ let dict: {
|
||||
/**记录开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**表格字段列排序 */
|
||||
let tableColumnsDnd = ref<ColumnsType>([]);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**告警设备类型 */
|
||||
@@ -143,7 +146,7 @@ let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('views.faultManage.activeAlarm.origLevel'),
|
||||
align: 'left',
|
||||
dataIndex: 'origLevel',
|
||||
dataIndex: 'origSeverity',
|
||||
key: 'origSeverity',
|
||||
width: 5,
|
||||
},
|
||||
@@ -340,7 +343,7 @@ function fnModalVisibleByVive(row: Record<string, any>) {
|
||||
function fnModalOk() {
|
||||
modalState.confirmLoading = true;
|
||||
const from = toRaw(modalState.from);
|
||||
if (from.ackState) {
|
||||
if (from.ackState === '1') {
|
||||
message.error({
|
||||
content: t('views.faultManage.activeAlarm.ackError'),
|
||||
duration: 3,
|
||||
@@ -431,6 +434,14 @@ function fnExportAll() {
|
||||
onOk() {
|
||||
const key = 'exportAlarmHis';
|
||||
message.loading({ content: t('common.loading'), key });
|
||||
let sortArr: any = [];
|
||||
tableColumnsDnd.value.forEach((item: any) => {
|
||||
if (item.dataIndex) sortArr.push(item.dataIndex);
|
||||
});
|
||||
// 排序字段
|
||||
const sortData = {
|
||||
header: sortArr,
|
||||
};
|
||||
exportAll(queryParams).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
@@ -438,7 +449,7 @@ function fnExportAll() {
|
||||
key,
|
||||
duration: 3,
|
||||
});
|
||||
writeSheet(res.data, 'alarm').then(fileBlob =>
|
||||
writeSheet(res.data, 'alarm', sortData).then(fileBlob =>
|
||||
saveAs(fileBlob, `history-alarm_${Date.now()}.xlsx`)
|
||||
);
|
||||
} else {
|
||||
@@ -707,6 +718,10 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
<TableColumnsDnd
|
||||
:columns="tableColumns"
|
||||
v-model:columns-dnd="tableColumnsDnd"
|
||||
></TableColumnsDnd>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
@@ -714,7 +729,7 @@ onMounted(() => {
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:columns="tableColumnsDnd"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
@@ -785,12 +800,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.alarmId')"
|
||||
name="alarmId"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmId"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmId }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -798,12 +808,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.alarmSeq')"
|
||||
name="alarmSeq"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmSeq"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmSeq }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -814,12 +819,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neId')"
|
||||
name="neId"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.neId"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.neId }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -827,12 +827,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neName')"
|
||||
name="neName"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.neName"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.neName }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -843,12 +838,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.neType')"
|
||||
name="neType"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.neType"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.neType }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -856,12 +846,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.alarmCode')"
|
||||
name="alarmCode"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmCode"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmCode }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -872,12 +857,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.alarmTitle')"
|
||||
name="alarmTitle"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmTitle"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmTitle }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -885,42 +865,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.eventTime')"
|
||||
name="eventTime"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.eventTime"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.alarmTitle')"
|
||||
name="alarmTitle"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.alarmTitle"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.alarmType')"
|
||||
name="alarmType"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.alarmType"
|
||||
style="width: 100%"
|
||||
:options="dict.activeAlarmType"
|
||||
disabled
|
||||
>
|
||||
</a-select>
|
||||
{{ modalState.from.eventTime }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -931,25 +876,16 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.pvFlag')"
|
||||
name="pvFlag"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.pvFlag"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.pvFlag }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.objectName')"
|
||||
name="objectName"
|
||||
:label="t('views.faultManage.activeAlarm.alarmType')"
|
||||
name="alarmType"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.objectName"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.alarmType }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -958,12 +894,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.locationInfo')"
|
||||
name="locationInfo"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.locationInfo"
|
||||
placeholder="Autosize height with minimum and maximum number of lines"
|
||||
:auto-size="{ minRows: 1, maxRows: 5 }"
|
||||
disabled
|
||||
/>
|
||||
{{ modalState.from.locationInfo }}
|
||||
</a-form-item>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -971,12 +902,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.province')"
|
||||
name="province"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.province"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.province }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -984,13 +910,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.origLevel')"
|
||||
name="origSeverity"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.origSeverity"
|
||||
style="width: 100%"
|
||||
:options="dict.activeAlarmSeverity"
|
||||
disabled
|
||||
>
|
||||
</a-select>
|
||||
{{ modalState.from.origSeverity }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -999,33 +919,20 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.addInfo')"
|
||||
name="addInfo"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.addInfo"
|
||||
:auto-size="{ minRows: 1, maxRows: 5 }"
|
||||
disabled
|
||||
/>
|
||||
{{ modalState.from.addInfo }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.specificProblemId')"
|
||||
name="specificProblemId"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.specificProblemId"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.specificProblemId }}
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.specificProblem')"
|
||||
name="specificProblem"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.specificProblem"
|
||||
:auto-size="{ minRows: 1, maxRows: 5 }"
|
||||
disabled
|
||||
/>
|
||||
{{ modalState.from.specificProblem }}
|
||||
</a-form-item>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1033,13 +940,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.clearType')"
|
||||
name="clearType"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.clearType"
|
||||
style="width: 100%"
|
||||
:options="dict.activeClearType"
|
||||
disabled
|
||||
>
|
||||
</a-select>
|
||||
{{ modalState.from.clearType }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1047,12 +948,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.clearTime')"
|
||||
name="clearTime"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.clearTime"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.clearTime }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1063,12 +959,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.ackUser')"
|
||||
name="ackUser"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.ackUser"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.ackUser }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
@@ -1076,12 +967,7 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.ackState')"
|
||||
name="ackState"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="modalState.from.ackState"
|
||||
style="width: 100%"
|
||||
:options="dict.activeAckState"
|
||||
disabled
|
||||
/>
|
||||
{{ modalState.from.ackState }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@@ -1092,12 +978,15 @@ onMounted(() => {
|
||||
:label="t('views.faultManage.activeAlarm.ackTime')"
|
||||
name="ackTime"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.ackTime"
|
||||
disabled
|
||||
allow-clear
|
||||
>
|
||||
</a-input>
|
||||
{{ modalState.from.ackTime }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.faultManage.activeAlarm.objectName')"
|
||||
name="objectName"
|
||||
>
|
||||
{{ modalState.from.objectName }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
@@ -14,6 +14,8 @@ import { PieChart } from 'echarts/charts';
|
||||
import { LabelLayout } from 'echarts/features';
|
||||
import { useRoute } from 'vue-router';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
const { getDict } = useDictStore();
|
||||
const appStore = useAppStore();
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
@@ -28,6 +30,18 @@ echarts.use([
|
||||
LabelLayout,
|
||||
]);
|
||||
|
||||
/**字典数据 */
|
||||
/**用户性别字典 */
|
||||
let indexColor = ref<DictType[]>([
|
||||
{ label: 'normal', value: 'normal', elTagType: '', elTagClass: '#91cc75' },
|
||||
{
|
||||
label: 'abnormal',
|
||||
value: 'abnormal',
|
||||
elTagType: '',
|
||||
elTagClass: '#ee6666',
|
||||
},
|
||||
]);
|
||||
|
||||
/**表格字段列 */
|
||||
//customRender(){} ----单元格处理
|
||||
let tableColumns: ColumnsType = [
|
||||
@@ -56,6 +70,11 @@ let tableColumns: ColumnsType = [
|
||||
dataIndex: 'version',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('views.index.serialNum'),
|
||||
dataIndex: 'serialNum',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('views.index.ipAddress'),
|
||||
dataIndex: 'ipAddress',
|
||||
@@ -92,10 +111,10 @@ let tableState: TabeStateType = reactive({
|
||||
/**表格状态 */
|
||||
let nfInfo: any = reactive({
|
||||
obj: 'OMC',
|
||||
version: '2.2312.8',
|
||||
version: appStore.version,
|
||||
status: t('views.index.normal'),
|
||||
number: '',
|
||||
outTimeDate: '',
|
||||
serialNum: appStore.serialNum,
|
||||
});
|
||||
|
||||
/**表格状态类型 */
|
||||
@@ -149,7 +168,7 @@ function fnGetList(one: boolean) {
|
||||
tableState.loading = false;
|
||||
var rightNum = 0;
|
||||
var errorNum = 0;
|
||||
|
||||
// if (res.length) nfInfo.serialNum = res[0].serialNum;
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
if (res[i].status == '正常' || res[i].status == 'Normal') {
|
||||
rightNum++;
|
||||
@@ -157,9 +176,16 @@ function fnGetList(one: boolean) {
|
||||
errorNum++;
|
||||
}
|
||||
}
|
||||
echarts.init(document.getElementById('echarts-records')).clear();
|
||||
var chartDom = document.getElementById('echarts-records');
|
||||
var myChart = echarts.init(chartDom);
|
||||
|
||||
var chartDom: any = document.getElementById('echarts-records');
|
||||
var existingChart = echarts.getInstanceByDom(chartDom);
|
||||
var myChart: any;
|
||||
if (existingChart) {
|
||||
myChart = existingChart;
|
||||
myChart.clear(); // 清空图表,重新设置数据
|
||||
} else {
|
||||
myChart = echarts.init(chartDom);
|
||||
}
|
||||
|
||||
var option = {
|
||||
title: {
|
||||
@@ -174,7 +200,10 @@ function fnGetList(one: boolean) {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
},
|
||||
color: ['#91cc75', '#ee6666'],
|
||||
color: [
|
||||
'' + indexColor.value[0]['elTagClass'],
|
||||
'' + indexColor.value[1]['elTagClass'],
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: t('views.index.realNeStatus'),
|
||||
@@ -206,125 +235,6 @@ function fnGetList(one: boolean) {
|
||||
});
|
||||
}
|
||||
|
||||
/**點擊網元名 */
|
||||
function init(e: any) {
|
||||
let realData = toRaw(e);
|
||||
var chartDom = document.getElementById('echarts-records');
|
||||
var myChart = echarts.init(chartDom);
|
||||
myChart.clear(); //怕遗留以前得元素
|
||||
|
||||
let cpuUsage = realData.cpuUsage;
|
||||
let memUsage = realData.memUsage;
|
||||
var nfMenUsage =
|
||||
Math.round((memUsage?.nfUsedMem / memUsage?.totalMem) * 10000) / 100.0;
|
||||
let partitionInfo = realData.diskSpace?.partitionInfo[1];
|
||||
var nfMaxDiskSpace =
|
||||
Math.round((partitionInfo?.used / partitionInfo?.total) * 10000) / 100.0;
|
||||
let option = {
|
||||
tooltip: {
|
||||
formatter: '{a} <br/>{b} : {c}%',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Nf Memory usage',
|
||||
center: ['17%', '50%'],
|
||||
radius: '80%',
|
||||
type: 'gauge',
|
||||
progress: {
|
||||
show: true,
|
||||
},
|
||||
pointer: {
|
||||
//仪表盘的指针
|
||||
//这个show属性好像有问题,因为在这次开发中,需要去掉指正,我设置false的时候,还是显示指针,估计是BUG吧,我用的echarts-3.2.3;希望改进。最终,我把width属性设置为0,成功搞定!
|
||||
show: true,
|
||||
//指针长度
|
||||
length: '60%',
|
||||
},
|
||||
title: {
|
||||
offsetCenter: [0, '90%'],
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
formatter: '{value}',
|
||||
textStyle: {
|
||||
fontSize: 18,
|
||||
},
|
||||
offsetCenter: [0, '60%'],
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: nfMenUsage,
|
||||
name: 'MEM',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
center: ['50%', '50%'],
|
||||
name: 'Nf CPU usage',
|
||||
radius: '80%',
|
||||
type: 'gauge',
|
||||
progress: {
|
||||
show: true,
|
||||
},
|
||||
|
||||
title: {
|
||||
offsetCenter: [0, '90%'],
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
formatter: '{value}',
|
||||
textStyle: {
|
||||
fontSize: 18,
|
||||
},
|
||||
offsetCenter: [0, '60%'],
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: cpuUsage?.nfCpuUsage / 100,
|
||||
name: 'CPU',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
center: ['83%', '50%'],
|
||||
name: 'NF maximum disk usage',
|
||||
radius: '80%',
|
||||
type: 'gauge',
|
||||
progress: {
|
||||
show: true,
|
||||
},
|
||||
title: {
|
||||
offsetCenter: [0, '90%'],
|
||||
},
|
||||
detail: {
|
||||
valueAnimation: true,
|
||||
formatter: '{value}',
|
||||
textStyle: {
|
||||
fontSize: 18,
|
||||
},
|
||||
offsetCenter: [0, '60%'],
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: nfMaxDiskSpace,
|
||||
name: 'DiskSpace',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
option && myChart.setOption(option);
|
||||
window.onresize = function () {
|
||||
// echarts 窗口缩放自适应 随着div--echarts-records的大小来适应
|
||||
myChart.resize();
|
||||
};
|
||||
|
||||
nfInfo.obj = realData.name;
|
||||
nfInfo.number = realData.serialNum;
|
||||
nfInfo.outTimeDate = realData.expiryDate;
|
||||
}
|
||||
|
||||
/**抽屉 网元详细信息 */
|
||||
const visible = ref(false);
|
||||
const closeDrawer = () => {
|
||||
@@ -393,6 +303,12 @@ function fnLocale() {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDict('index_status').then(res => {
|
||||
if (res.length > 0) {
|
||||
indexColor.value = res;
|
||||
}
|
||||
});
|
||||
//console.log(indexColor)
|
||||
fnLocale();
|
||||
fnGetList(true);
|
||||
timer = setInterval(() => fnGetList(false), 10000); // 每隔10秒执行一次
|
||||
@@ -463,9 +379,7 @@ onBeforeUnmount(() => {
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'status'">
|
||||
<div v-if="record.status == '正常' || record.status == 'Normal'">
|
||||
<a-tag color="blue" @click="init(record)">{{
|
||||
record.name
|
||||
}}</a-tag>
|
||||
<a-tag color="blue">{{ record.name }}</a-tag>
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-tag color="pink">{{ record.name }}</a-tag>
|
||||
@@ -491,6 +405,7 @@ onBeforeUnmount(() => {
|
||||
nfInfo.obj
|
||||
}}</a-descriptions-item>
|
||||
<template v-if="nfInfo.obj === 'OMC'">
|
||||
|
||||
<a-descriptions-item :label="t('views.index.versionNum')">{{
|
||||
nfInfo.version
|
||||
}}</a-descriptions-item>
|
||||
@@ -500,7 +415,7 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-descriptions-item :label="t('views.index.serialNum')">{{
|
||||
nfInfo.number
|
||||
nfInfo.serialNum
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item :label="t('views.index.expiryDate')">{{
|
||||
nfInfo.outTimeDate
|
||||
|
||||
347
src/views/logManage/neFile/index.vue
Normal file
347
src/views/logManage/neFile/index.vue
Normal file
@@ -0,0 +1,347 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { getNeFile, listNeFiles } from '@/api/tool/neFile';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { Modal, message } from 'ant-design-vue/lib';
|
||||
import saveAs from 'file-saver';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
let neType = ref([]);
|
||||
/**下载触发等待 */
|
||||
let loading = ref(false);
|
||||
/**访问路径 */
|
||||
let nePathArr = ref<string[]>([]);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: '',
|
||||
neId: '',
|
||||
/**读取路径 */
|
||||
path: '',
|
||||
/**前缀过滤 */
|
||||
search: '',
|
||||
/**当前页数 */
|
||||
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();
|
||||
},
|
||||
});
|
||||
|
||||
/**信息文件下载 */
|
||||
function fnDownloadFile(row: Record<string, any>) {
|
||||
if (loading.value) return;
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.logManage.neFile.downTip', { fileName: row.fileName }),
|
||||
onOk() {
|
||||
loading.value = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
getNeFile({
|
||||
neType: queryParams.neType,
|
||||
neId: queryParams.neId,
|
||||
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.neFile.downTipErr'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
loading.value = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**进入目录 */
|
||||
function fnDirCD(dir: string, index?: number) {
|
||||
if (index === undefined) {
|
||||
nePathArr.value.push(dir);
|
||||
queryParams.search = '';
|
||||
fnGetList(1);
|
||||
return;
|
||||
}
|
||||
if (index === 0) {
|
||||
const neType = queryParams.neType;
|
||||
if (neType === 'IMS') {
|
||||
nePathArr.value = ['/var/log/ims'];
|
||||
queryParams.search = '';
|
||||
} else {
|
||||
nePathArr.value = ['/var/log'];
|
||||
queryParams.search = neType.toLowerCase();
|
||||
}
|
||||
fnGetList(1);
|
||||
} else {
|
||||
nePathArr.value = nePathArr.value.slice(0, index + 1);
|
||||
queryParams.search = '';
|
||||
fnGetList(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**网元类型选择对应修改 */
|
||||
function fnNeChange(keys: any, _: any) {
|
||||
// 不是同类型时需要重新加载
|
||||
if (Array.isArray(keys) && queryParams.neType !== keys[0]) {
|
||||
const neType = keys[0];
|
||||
queryParams.neType = neType;
|
||||
queryParams.neId = keys[1];
|
||||
if (neType === 'IMS') {
|
||||
nePathArr.value = ['/var/log/ims'];
|
||||
queryParams.search = '';
|
||||
} else {
|
||||
nePathArr.value = ['/var/log'];
|
||||
queryParams.search = neType.toLowerCase();
|
||||
}
|
||||
fnGetList(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**查询备份信息列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (queryParams.neId === '') {
|
||||
message.warning({
|
||||
content: t('views.logManage.neFile.neTypePlease'),
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
queryParams.path = nePathArr.value.join('/');
|
||||
listNeFiles(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
neInfoStore.fnNelist().then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.logManage.neFile.neType')"
|
||||
name="neType"
|
||||
style="margin-bottom: 0"
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="neType"
|
||||
:options="neInfoStore.getNeCascaderOptions"
|
||||
@change="fnNeChange"
|
||||
:allow-clear="false"
|
||||
:placeholder="t('views.logManage.neFile.neTypePlease')"
|
||||
:disabled="loading || tableState.loading"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="16" :md="18" :xs="24" v-if="nePathArr.length > 0">
|
||||
<a-form-item
|
||||
:label="t('views.logManage.neFile.nePath')"
|
||||
name="configName"
|
||||
style="margin-bottom: 0"
|
||||
>
|
||||
<a-breadcrumb>
|
||||
<a-breadcrumb-item
|
||||
v-for="(path, index) in nePathArr"
|
||||
:key="path"
|
||||
@click="fnDirCD(path, index)"
|
||||
>
|
||||
{{ path }}
|
||||
</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="fileName"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: 800 }"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'fileName'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnDownloadFile(record)"
|
||||
v-if="record.fileType === 'file'"
|
||||
>
|
||||
<template #icon><DownloadOutlined /></template>
|
||||
{{ t('common.downloadText') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnDirCD(record.fileName)"
|
||||
v-if="record.fileType === 'dir'"
|
||||
>
|
||||
<template #icon><FolderOutlined /></template>
|
||||
{{ t('views.logManage.neFile.dirCd') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -10,6 +10,7 @@ import useI18n from '@/hooks/useI18n';
|
||||
import { getMMLByNE, sendMMlByNE } from '@/api/mmlManage/neOperate';
|
||||
import { uploadFileToNE } from '@/api/tool/file';
|
||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
@@ -63,9 +64,30 @@ let state: StateType = reactive({
|
||||
function fnTreeSelect(_: any, info: any) {
|
||||
state.mmlSelect = info.node.dataRef;
|
||||
state.from = {};
|
||||
// 遍历判断是否有初始value
|
||||
if (Array.isArray(state.mmlSelect.param)) {
|
||||
for (const param of state.mmlSelect.param) {
|
||||
if (typeof param.value !== 'undefined' && param.value != '') {
|
||||
const valueType = param.type;
|
||||
if (['enum', 'int'].includes(valueType)) {
|
||||
state.from[param.name] = Number(param.value);
|
||||
} else if (valueType === 'bool') {
|
||||
state.from[param.name] = Boolean(param.value);
|
||||
} else {
|
||||
state.from[param.name] = param.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.autoCompleteValue =
|
||||
`${state.mmlSelect.operation} ${state.mmlSelect.object}`.trim();
|
||||
// state.mmlCmdLog = '';
|
||||
// 回到顶部
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth', // 平滑滚动到顶部,如果不需要平滑效果可以将此行代码删除
|
||||
});
|
||||
}
|
||||
|
||||
/**清空控制台日志 */
|
||||
@@ -185,7 +207,7 @@ function fnUpload(up: UploadRequestOption, name: string) {
|
||||
message.success(t('views.mmlManage.uploadFileOk'), 3);
|
||||
state.from[name] = res.data;
|
||||
} else {
|
||||
message.error(res.msg, 3);
|
||||
message.error(t('views.mmlManage.uploadFileErr'), 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -455,42 +477,47 @@ function fnAutoCompleteChange(value: any, _: any) {
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore()
|
||||
.fnNelist()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length > 0) {
|
||||
// 过滤不可用的网元
|
||||
neCascaderOptions.value = useNeInfoStore().getNeCascaderOtions.filter(
|
||||
(item: any) => {
|
||||
return !['OMC'].includes(item.value);
|
||||
}
|
||||
);
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOptions.value.find(s => s.value === 'AMF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
state.neType = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOptions.value[0].children[0];
|
||||
state.neType = [info.neType, info.neId];
|
||||
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 !['OMC'].includes(item.value);
|
||||
}
|
||||
fnGetList();
|
||||
);
|
||||
if (neCascaderOptions.value.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOptions.value.find(s => s.value === 'AMF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
state.neType = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOptions.value[0].children[0];
|
||||
state.neType = [info.neType, info.neId];
|
||||
}
|
||||
fnGetList();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="6">
|
||||
<a-col :lg="6" :md="6" :xs="24" style="margin-bottom: 24px">
|
||||
<!-- 命令导航 -->
|
||||
<a-card
|
||||
size="small"
|
||||
@@ -518,7 +545,7 @@ onMounted(() => {
|
||||
</a-form>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="18">
|
||||
<a-col :lg="18" :md="18" :xs="24">
|
||||
<!-- 命令参数输入 -->
|
||||
<a-card size="small" :bordered="false">
|
||||
<template #title>
|
||||
@@ -558,7 +585,7 @@ onMounted(() => {
|
||||
</template>
|
||||
|
||||
<a-form
|
||||
layout="vertical"
|
||||
layout="horizontal"
|
||||
autocomplete="off"
|
||||
:validate-on-rule-change="false"
|
||||
:validateTrigger="[]"
|
||||
@@ -573,11 +600,18 @@ onMounted(() => {
|
||||
@select="fnAutoCompleteSelect"
|
||||
@change="fnAutoCompleteChange"
|
||||
>
|
||||
<a-textarea :placeholder="t('common.ipnutPlease')" auto-size />
|
||||
<a-textarea :placeholder="t('common.inputPlease')" auto-size />
|
||||
</a-auto-complete>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<template v-if="state.mmlSelect.operation && state.mmlSelect.param">
|
||||
<template v-if="state.mmlSelect.operation && state.mmlSelect.param">
|
||||
<a-form
|
||||
layout="vertical"
|
||||
autocomplete="off"
|
||||
:validate-on-rule-change="false"
|
||||
:validateTrigger="[]"
|
||||
>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.mmlManage.cmdParamPanel') }}
|
||||
</a-divider>
|
||||
@@ -633,7 +667,7 @@ onMounted(() => {
|
||||
:accept="item.filter"
|
||||
:max-count="1"
|
||||
:show-upload-list="false"
|
||||
:custom-request="v => fnUpload(v, item.name)"
|
||||
:custom-request="(v:any) => fnUpload(v, item.name)"
|
||||
>
|
||||
<a-button
|
||||
type="primary"
|
||||
@@ -653,8 +687,8 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</a-form>
|
||||
</a-form>
|
||||
</template>
|
||||
</a-card>
|
||||
|
||||
<!-- 命令展示 -->
|
||||
|
||||
@@ -60,9 +60,30 @@ let state: StateType = reactive({
|
||||
function fnTreeSelect(_: any, info: any) {
|
||||
state.mmlSelect = info.node.dataRef;
|
||||
state.from = {};
|
||||
// 遍历判断是否有初始value
|
||||
if (Array.isArray(state.mmlSelect.param)) {
|
||||
for (const param of state.mmlSelect.param) {
|
||||
if (typeof param.value !== 'undefined' && param.value != '') {
|
||||
const valueType = param.type;
|
||||
if (['enum', 'int'].includes(valueType)) {
|
||||
state.from[param.name] = Number(param.value);
|
||||
} else if (valueType === 'bool') {
|
||||
state.from[param.name] = Boolean(param.value);
|
||||
} else {
|
||||
state.from[param.name] = param.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.autoCompleteValue =
|
||||
`${state.mmlSelect.operation} ${state.mmlSelect.object}`.trim();
|
||||
// state.mmlCmdLog = '';
|
||||
// 回到顶部
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth', // 平滑滚动到顶部,如果不需要平滑效果可以将此行代码删除
|
||||
});
|
||||
}
|
||||
|
||||
/**清空控制台日志 */
|
||||
@@ -156,8 +177,8 @@ function fnSendMML() {
|
||||
for (let i = 0; i < resultArr.length; i++) {
|
||||
const str = resultArr[i];
|
||||
const logStr = str.replace(/(\r\n|\n)/g, '\n');
|
||||
const cmdStr = cmdArr[i]
|
||||
state.mmlCmdLog += `${cmdStr}\n${logStr}\n`;
|
||||
const cmdStr = cmdArr[i];
|
||||
state.mmlCmdLog += `${cmdStr}\n${logStr}\n`;
|
||||
}
|
||||
} else {
|
||||
state.mmlCmdLog += `${res.msg}\n`;
|
||||
@@ -180,7 +201,7 @@ function fnUpload(up: UploadRequestOption, name: string) {
|
||||
message.success(t('views.mmlManage.uploadFileOk'), 3);
|
||||
state.from[name] = res.data;
|
||||
} else {
|
||||
message.error(res.msg, 3);
|
||||
message.error(t('views.mmlManage.uploadFileErr'), 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -466,7 +487,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="6">
|
||||
<a-col :lg="6" :md="6" :xs="24" style="margin-bottom: 24px">
|
||||
<!-- 命令导航 -->
|
||||
<a-card
|
||||
size="small"
|
||||
@@ -492,7 +513,7 @@ onMounted(() => {
|
||||
</a-form>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="18">
|
||||
<a-col :lg="18" :md="18" :xs="24">
|
||||
<!-- 命令参数输入 -->
|
||||
<a-card size="small" :bordered="false">
|
||||
<template #title>
|
||||
@@ -532,7 +553,7 @@ onMounted(() => {
|
||||
</template>
|
||||
|
||||
<a-form
|
||||
layout="vertical"
|
||||
layout="horizontal"
|
||||
autocomplete="off"
|
||||
:validate-on-rule-change="false"
|
||||
:validateTrigger="[]"
|
||||
@@ -547,11 +568,18 @@ onMounted(() => {
|
||||
@select="fnAutoCompleteSelect"
|
||||
@change="fnAutoCompleteChange"
|
||||
>
|
||||
<a-textarea :placeholder="t('common.ipnutPlease')" auto-size />
|
||||
<a-textarea :placeholder="t('common.inputPlease')" auto-size />
|
||||
</a-auto-complete>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<template v-if="state.mmlSelect.operation && state.mmlSelect.param">
|
||||
<template v-if="state.mmlSelect.operation && state.mmlSelect.param">
|
||||
<a-form
|
||||
layout="vertical"
|
||||
autocomplete="off"
|
||||
:validate-on-rule-change="false"
|
||||
:validateTrigger="[]"
|
||||
>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.mmlManage.cmdParamPanel') }}
|
||||
</a-divider>
|
||||
@@ -607,7 +635,7 @@ onMounted(() => {
|
||||
:accept="item.filter"
|
||||
:max-count="1"
|
||||
:show-upload-list="false"
|
||||
:custom-request="v => fnUpload(v, item.name)"
|
||||
:custom-request="(v:any) => fnUpload(v, item.name)"
|
||||
>
|
||||
<a-button
|
||||
type="primary"
|
||||
@@ -627,8 +655,8 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</a-form>
|
||||
</a-form>
|
||||
</template>
|
||||
</a-card>
|
||||
|
||||
<!-- 命令展示 -->
|
||||
|
||||
@@ -60,9 +60,30 @@ let state: StateType = reactive({
|
||||
function fnTreeSelect(_: any, info: any) {
|
||||
state.mmlSelect = info.node.dataRef;
|
||||
state.from = {};
|
||||
// 遍历判断是否有初始value
|
||||
if (Array.isArray(state.mmlSelect.param)) {
|
||||
for (const param of state.mmlSelect.param) {
|
||||
if (typeof param.value !== 'undefined' && param.value != '') {
|
||||
const valueType = param.type;
|
||||
if (['enum', 'int'].includes(valueType)) {
|
||||
state.from[param.name] = Number(param.value);
|
||||
} else if (valueType === 'bool') {
|
||||
state.from[param.name] = Boolean(param.value);
|
||||
} else {
|
||||
state.from[param.name] = param.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.autoCompleteValue =
|
||||
`${state.mmlSelect.operation} ${state.mmlSelect.object}`.trim();
|
||||
// state.mmlCmdLog = '';
|
||||
// 回到顶部
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth', // 平滑滚动到顶部,如果不需要平滑效果可以将此行代码删除
|
||||
});
|
||||
}
|
||||
|
||||
/**清空控制台日志 */
|
||||
@@ -180,7 +201,7 @@ function fnUpload(up: UploadRequestOption, name: string) {
|
||||
message.success(t('views.mmlManage.uploadFileOk'), 3);
|
||||
state.from[name] = res.data;
|
||||
} else {
|
||||
message.error(res.msg, 3);
|
||||
message.error(t('views.mmlManage.uploadFileErr'), 3);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -446,6 +467,11 @@ onMounted(() => {
|
||||
state.neId = arr[0].value;
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('views.mmlManage.udmOpesrate.noUDM'),
|
||||
duration: 5,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
@@ -466,7 +492,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="6">
|
||||
<a-col :lg="6" :md="6" :xs="24" style="margin-bottom: 24px">
|
||||
<!-- 命令导航 -->
|
||||
<a-card
|
||||
size="small"
|
||||
@@ -492,7 +518,7 @@ onMounted(() => {
|
||||
</a-form>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="18">
|
||||
<a-col :lg="18" :md="18" :xs="24">
|
||||
<!-- 命令参数输入 -->
|
||||
<a-card size="small" :bordered="false">
|
||||
<template #title>
|
||||
@@ -532,7 +558,7 @@ onMounted(() => {
|
||||
</template>
|
||||
|
||||
<a-form
|
||||
layout="vertical"
|
||||
layout="horizontal"
|
||||
autocomplete="off"
|
||||
:validate-on-rule-change="false"
|
||||
:validateTrigger="[]"
|
||||
@@ -547,11 +573,18 @@ onMounted(() => {
|
||||
@select="fnAutoCompleteSelect"
|
||||
@change="fnAutoCompleteChange"
|
||||
>
|
||||
<a-textarea :placeholder="t('common.ipnutPlease')" auto-size />
|
||||
<a-textarea :placeholder="t('common.inputPlease')" auto-size />
|
||||
</a-auto-complete>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<template v-if="state.mmlSelect.operation && state.mmlSelect.param">
|
||||
<template v-if="state.mmlSelect.operation && state.mmlSelect.param">
|
||||
<a-form
|
||||
layout="vertical"
|
||||
autocomplete="off"
|
||||
:validate-on-rule-change="false"
|
||||
:validateTrigger="[]"
|
||||
>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.mmlManage.cmdParamPanel') }}
|
||||
</a-divider>
|
||||
@@ -607,7 +640,7 @@ onMounted(() => {
|
||||
:accept="item.filter"
|
||||
:max-count="1"
|
||||
:show-upload-list="false"
|
||||
:custom-request="v => fnUpload(v, item.name)"
|
||||
:custom-request="(v:any) => fnUpload(v, item.name)"
|
||||
>
|
||||
<a-button
|
||||
type="primary"
|
||||
@@ -627,8 +660,8 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</a-form>
|
||||
</a-form>
|
||||
</template>
|
||||
</a-card>
|
||||
|
||||
<!-- 命令展示 -->
|
||||
|
||||
@@ -645,7 +645,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
@@ -689,12 +689,12 @@ onMounted(() => {
|
||||
<template #icon><SyncOutlined /></template>
|
||||
{{ t('views.monitor.job.resetQueue') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -743,7 +743,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
@@ -866,7 +866,8 @@ onMounted(() => {
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.monitor.job.status')" name="status">
|
||||
{{
|
||||
dict.sysJobStatus.find(s => s.value === modalState.from.status)?.label
|
||||
dict.sysJobStatus.find(s => s.value === modalState.from.status)
|
||||
?.label
|
||||
}}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
@@ -424,7 +424,7 @@ onMounted(() => {
|
||||
v-model:value="queryParams.jobName"
|
||||
:allow-clear="jobId === '0'"
|
||||
:disabled="jobId !== '0'"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -491,7 +491,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button type="default" @click.prevent="fnClose()">
|
||||
<template #icon><CloseOutlined /></template>
|
||||
{{ t('common.close') }}
|
||||
@@ -523,12 +523,12 @@ onMounted(() => {
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -577,7 +577,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
|
||||
1167
src/views/monitor/topology-build/components/GraphEditModal.vue
Normal file
1167
src/views/monitor/topology-build/components/GraphEditModal.vue
Normal file
File diff suppressed because it is too large
Load Diff
187
src/views/monitor/topology-build/hooks/useCombo.ts
Normal file
187
src/views/monitor/topology-build/hooks/useCombo.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
import { message, Form } from 'ant-design-vue/lib';
|
||||
import { reactive, toRaw, watch } from 'vue';
|
||||
import { graphG6, selectSourceTargetOptions } from './useGraph';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
|
||||
/**图分组内置类型 */
|
||||
export const comboTypeOptions = [
|
||||
{
|
||||
value: 'circle',
|
||||
label: '圆形',
|
||||
},
|
||||
{
|
||||
value: 'rect',
|
||||
label: '矩形',
|
||||
},
|
||||
];
|
||||
|
||||
/**图分组标签文本位置 */
|
||||
export const comboPositionOptions = [
|
||||
{
|
||||
value: 'top',
|
||||
label: '上',
|
||||
},
|
||||
{
|
||||
value: 'left',
|
||||
label: '左',
|
||||
},
|
||||
{
|
||||
value: 'right',
|
||||
label: '右',
|
||||
},
|
||||
{
|
||||
value: 'bottom',
|
||||
label: '下',
|
||||
},
|
||||
{
|
||||
value: 'center',
|
||||
label: '居中',
|
||||
},
|
||||
];
|
||||
|
||||
export default function useCombo() {
|
||||
const { t } = useI18n();
|
||||
|
||||
/**图分组信息状态类型 */
|
||||
type ComboStateType = {
|
||||
/**图分组原始数据 */
|
||||
origin: Record<string, any>;
|
||||
/**图分组表单数据 */
|
||||
form: Record<string, any>;
|
||||
};
|
||||
|
||||
/**图分组信息状态 */
|
||||
let comboState: ComboStateType = reactive({
|
||||
origin: {},
|
||||
form: {
|
||||
id: '',
|
||||
type: 'rect',
|
||||
parentId: '',
|
||||
size: [40, 40],
|
||||
padding: [30, 30, 30, 30],
|
||||
style: {
|
||||
radius: 2,
|
||||
fill: '#ffffff',
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
cursor: 'grab',
|
||||
fillOpacity: 0.5,
|
||||
},
|
||||
label: '',
|
||||
labelCfg: {
|
||||
refX: 10,
|
||||
refY: 10,
|
||||
position: 'top',
|
||||
style: {
|
||||
fill: '#000000',
|
||||
fontSize: 12,
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
children: [], // 子元素
|
||||
},
|
||||
});
|
||||
|
||||
/**图分组对话分组内表单属性和校验规则 */
|
||||
const comboStateForm = Form.useForm(
|
||||
comboState.form,
|
||||
reactive({
|
||||
id: [{ required: true, message: '分组唯一标识 ID' }],
|
||||
})
|
||||
);
|
||||
|
||||
/**图分组编辑监听更新视图 */
|
||||
watch(comboState.form, combo => {
|
||||
const info = JSON.parse(JSON.stringify(combo));
|
||||
// 新增不监听变化
|
||||
const comboOriginId = comboState.origin.id;
|
||||
const comboId = info.id;
|
||||
if (comboId && comboId === comboOriginId) {
|
||||
graphG6.value.clearItemStates(comboId, 'selected');
|
||||
const data = graphG6.value.save();
|
||||
const item = data.combos.find((item: any) => item.id === comboId);
|
||||
Object.assign(item, combo);
|
||||
// 无父组id时不要设置,避免导致绘制失败
|
||||
if (!combo.parentId) {
|
||||
Reflect.deleteProperty(item, 'parentId');
|
||||
}
|
||||
graphG6.value.read(data);
|
||||
}
|
||||
});
|
||||
|
||||
/**图分组类型输入限制 */
|
||||
function handleComboTypeChange(type: any) {
|
||||
// 类型尺寸和边距
|
||||
if (type === 'circle') {
|
||||
comboState.form.size = 30;
|
||||
comboState.form.padding = 30;
|
||||
}
|
||||
if (type === 'rect') {
|
||||
comboState.form.size = [30, 20];
|
||||
comboState.form.padding = [10, 20, 10, 20];
|
||||
}
|
||||
}
|
||||
|
||||
/**图分组新增或更新 */
|
||||
function handleOkcombo() {
|
||||
return comboStateForm
|
||||
.validate()
|
||||
.then(e => {
|
||||
const combo = JSON.parse(JSON.stringify(comboState.form));
|
||||
if (!combo.id) {
|
||||
message.warn({
|
||||
content: `分组元素ID错误`,
|
||||
duration: 2,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
const item = graphG6.value.findById(combo.id);
|
||||
if (item) {
|
||||
const data = graphG6.value.save();
|
||||
const item = data.combos.find((item: any) => item.id === combo.id);
|
||||
Object.assign(item, combo);
|
||||
// 无父组id时不要设置,避免导致绘制失败
|
||||
if (!combo.parentId) {
|
||||
Reflect.deleteProperty(item, 'parentId');
|
||||
}
|
||||
graphG6.value.read(data);
|
||||
} else {
|
||||
graphG6.value.createCombo(combo, combo.children);
|
||||
}
|
||||
|
||||
comboStateForm.resetFields();
|
||||
comboState.origin = {};
|
||||
return true;
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(
|
||||
t('common.errorFields', { num: e.errorFields.length }),
|
||||
3
|
||||
);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**图分组取消还原 */
|
||||
function handleCancelcombo() {
|
||||
// 新增无原始数据
|
||||
const origin = JSON.parse(JSON.stringify(comboState.origin));
|
||||
if (origin.id) {
|
||||
const data = graphG6.value.save();
|
||||
const item = data.combos.find((combo: any) => combo.id === origin.id);
|
||||
Object.assign(item, origin);
|
||||
graphG6.value.read(data);
|
||||
}
|
||||
comboStateForm.resetFields();
|
||||
comboState.origin = {};
|
||||
}
|
||||
|
||||
return {
|
||||
comboState,
|
||||
comboStateForm,
|
||||
handleComboTypeChange,
|
||||
handleOkcombo,
|
||||
handleCancelcombo,
|
||||
};
|
||||
}
|
||||
169
src/views/monitor/topology-build/hooks/useEdge.ts
Normal file
169
src/views/monitor/topology-build/hooks/useEdge.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
import { message, Form } from 'ant-design-vue/lib';
|
||||
import { reactive, watch } from 'vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { graphG6 } from './useGraph';
|
||||
|
||||
/**图边内置边类型 */
|
||||
export const edgeTypeOptions = [
|
||||
{
|
||||
value: 'line',
|
||||
label: '直线,连接两个节点的直线',
|
||||
},
|
||||
{
|
||||
value: 'polyline',
|
||||
label: '折线,多段线段构成的折线,连接两个端点',
|
||||
},
|
||||
{
|
||||
value: 'arc',
|
||||
label: '圆弧线,连接两个节点的一段圆弧',
|
||||
},
|
||||
{
|
||||
value: 'quadratic',
|
||||
label: '二阶贝塞尔曲线,只有一个控制点的曲线',
|
||||
},
|
||||
{
|
||||
value: 'cubic',
|
||||
label: '三阶贝塞尔曲线,有两个控制点的曲线',
|
||||
},
|
||||
{
|
||||
value: 'cubic-vertical',
|
||||
label: '垂直方向的三阶贝塞尔曲线',
|
||||
},
|
||||
{
|
||||
value: 'cubic-horizontal',
|
||||
label: '水平方向的三阶贝塞尔曲线',
|
||||
},
|
||||
{
|
||||
value: 'loop',
|
||||
label: '自环',
|
||||
},
|
||||
];
|
||||
|
||||
/**图边标签文本位置 */
|
||||
export const edgePositionOptions = [
|
||||
{
|
||||
value: 'start',
|
||||
label: '开头',
|
||||
},
|
||||
{
|
||||
value: 'middle',
|
||||
label: '中间',
|
||||
},
|
||||
{
|
||||
value: 'end',
|
||||
label: '末尾',
|
||||
},
|
||||
];
|
||||
|
||||
export default function useEdge() {
|
||||
const { t } = useI18n();
|
||||
|
||||
/**图边信息状态类型 */
|
||||
type EdgeStateType = {
|
||||
/**图边原始数据 */
|
||||
origin: Record<string, any>;
|
||||
/**图边表单数据 */
|
||||
form: Record<string, any>;
|
||||
};
|
||||
|
||||
/**图边信息状态 */
|
||||
let edgeState: EdgeStateType = reactive({
|
||||
origin: {},
|
||||
form: {
|
||||
id: '',
|
||||
source: '',
|
||||
target: '',
|
||||
type: 'polyline',
|
||||
style: {
|
||||
offset: 20,
|
||||
radius: 2,
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
cursor: 'pointer',
|
||||
},
|
||||
label: '',
|
||||
labelCfg: {
|
||||
refX: 0,
|
||||
refY: 0,
|
||||
position: 'middle',
|
||||
autoRotate: false,
|
||||
style: {
|
||||
fill: '#ffffff',
|
||||
fontSize: 12,
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**图边对话框内表单属性和校验规则 */
|
||||
const edgeStateForm = Form.useForm(
|
||||
edgeState.form,
|
||||
reactive({
|
||||
id: [{ required: true, message: '边唯一 ID' }],
|
||||
source: [{ required: true, message: '起始点 id' }],
|
||||
target: [{ required: true, message: '结束点 id' }],
|
||||
type: [{ required: true, message: 'line' }],
|
||||
})
|
||||
);
|
||||
|
||||
/**图边编辑监听更新视图 */
|
||||
watch(edgeState.form, edge => {
|
||||
const info = JSON.parse(JSON.stringify(edge));
|
||||
// 新增id是#不监听变化
|
||||
const edgeId = info.id;
|
||||
if (edgeId && edgeId !== '#') {
|
||||
graphG6.value.clearItemStates(edgeId, 'selected');
|
||||
graphG6.value.updateItem(edgeId, info);
|
||||
}
|
||||
});
|
||||
|
||||
/**图边新增或更新 */
|
||||
function handleOkEdge() {
|
||||
return edgeStateForm
|
||||
.validate()
|
||||
.then(e => {
|
||||
const edge = JSON.parse(JSON.stringify(edgeState.form));
|
||||
if (!edge.id) {
|
||||
message.warn({
|
||||
content: `边元素ID错误`,
|
||||
duration: 2,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// 存在更新,新增id是#不监听变化
|
||||
const item = graphG6.value.findById(edge.id);
|
||||
if (item) {
|
||||
graphG6.value.updateItem(item, edge);
|
||||
} else {
|
||||
edge.id = `${edge.source}~${Date.now()}~${edge.target}`;
|
||||
graphG6.value.addItem('edge', edge);
|
||||
}
|
||||
|
||||
edgeStateForm.resetFields();
|
||||
edgeState.origin = {};
|
||||
return true;
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(
|
||||
t('common.errorFields', { num: e.errorFields.length }),
|
||||
3
|
||||
);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**图边取消还原 */
|
||||
function handleCancelEdge() {
|
||||
// 新增无原始数据
|
||||
const origin = JSON.parse(JSON.stringify(edgeState.origin));
|
||||
if (origin.id) {
|
||||
graphG6.value.updateItem(origin.id, origin);
|
||||
}
|
||||
edgeStateForm.resetFields();
|
||||
edgeState.origin = {};
|
||||
}
|
||||
|
||||
return { edgeState, edgeStateForm, handleOkEdge, handleCancelEdge };
|
||||
}
|
||||
581
src/views/monitor/topology-build/hooks/useGraph.ts
Normal file
581
src/views/monitor/topology-build/hooks/useGraph.ts
Normal file
@@ -0,0 +1,581 @@
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import {
|
||||
Graph,
|
||||
GraphData,
|
||||
ICanvas,
|
||||
IShapeBase,
|
||||
Item,
|
||||
Menu,
|
||||
Tooltip,
|
||||
} from '@antv/g6';
|
||||
import { ref } from 'vue';
|
||||
|
||||
/**图模式选择项 */
|
||||
export const graphModeOptions = [
|
||||
{
|
||||
value: 'default',
|
||||
label: '默认',
|
||||
},
|
||||
{
|
||||
value: 'edit',
|
||||
label: '编辑',
|
||||
},
|
||||
];
|
||||
|
||||
/**图实例对象 */
|
||||
export const graphG6 = ref<any>(null);
|
||||
|
||||
/**图事件变更 */
|
||||
export const graphEvent = ref<{
|
||||
type: string;
|
||||
target: HTMLElement | (IShapeBase & ICanvas);
|
||||
item: Item | null;
|
||||
}>();
|
||||
|
||||
/**图元素选择开始结束点 */
|
||||
export const selectSourceTargetOptions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**图元素选择嵌入分组 */
|
||||
export const selectComboOptions = ref<Record<string, any>[]>([]);
|
||||
|
||||
/**图模式选择项 */
|
||||
export const graphMode = ref<string>('default');
|
||||
|
||||
export default function useGraph() {
|
||||
//实例化i18n
|
||||
const { t } = useI18n();
|
||||
|
||||
/**图画布右击菜单 */
|
||||
const graphCanvasMenu = new Menu({
|
||||
offsetX: 6,
|
||||
offseY: 10,
|
||||
itemTypes: ['canvas'],
|
||||
getContent(evt) {
|
||||
console.log(evt);
|
||||
if (!evt) return '无';
|
||||
const edit = graphMode.value === 'edit';
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
"
|
||||
>
|
||||
<h3>画布</h3>
|
||||
<div id="show" style="cursor: pointer; margin-bottom: 2px">
|
||||
显示所有隐藏项
|
||||
</div>
|
||||
<div id="create-edge" style="cursor: pointer; margin-bottom: 2px; display: ${
|
||||
edit ? 'black' : 'none'
|
||||
}">
|
||||
新增边
|
||||
</div>
|
||||
<div id="create-node" style="cursor: pointer; margin-bottom: 2px; display: ${
|
||||
edit ? 'black' : 'none'
|
||||
}">
|
||||
新增节点
|
||||
</div>
|
||||
<div id="create-combo" style="cursor: pointer; margin-bottom: 2px; display: ${
|
||||
edit ? 'black' : 'none'
|
||||
}">
|
||||
新增分组
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'create-edge':
|
||||
case 'create-node':
|
||||
case 'create-combo':
|
||||
graphEvent.value = { type: `canvas-${targetId}`, target, item };
|
||||
break;
|
||||
case 'show':
|
||||
// 显示节点
|
||||
graphG6.value.getNodes().forEach((node: any) => {
|
||||
if (!node.isVisible()) {
|
||||
graphG6.value.showItem(node);
|
||||
graphG6.value.refreshItem(node);
|
||||
}
|
||||
});
|
||||
// 显示边
|
||||
graphG6.value.getEdges().forEach((edge: any) => {
|
||||
if (!edge.isVisible()) {
|
||||
graphG6.value.showItem(edge);
|
||||
graphG6.value.refreshItem(edge);
|
||||
}
|
||||
});
|
||||
// 显示分组
|
||||
graphG6.value.getCombos().forEach((combo: any) => {
|
||||
if (!combo.isVisible()) {
|
||||
graphG6.value.showItem(combo);
|
||||
graphG6.value.updateCombo(combo);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**图分组Combo 右击菜单 */
|
||||
const graphComboMenu = new Menu({
|
||||
offsetX: 6,
|
||||
offseY: 10,
|
||||
itemTypes: ['combo'],
|
||||
getContent(evt) {
|
||||
console.log(evt);
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<h3>分组</h3>
|
||||
<div id="edit" style="cursor: pointer; margin-bottom: 2px">
|
||||
1. 编辑
|
||||
</div>
|
||||
<div id="delete" style="cursor: pointer; margin-bottom: 2px">
|
||||
2. 删除
|
||||
</div>
|
||||
<div id="hide" style="cursor: pointer; margin-bottom: 2px">
|
||||
2. 隐藏
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'edit':
|
||||
graphEvent.value = { type: `combo-${targetId}`, target, item };
|
||||
break;
|
||||
case 'delete':
|
||||
graphG6.value.uncombo(item);
|
||||
graphG6.value.updateCombos();
|
||||
break;
|
||||
case 'hide':
|
||||
graphG6.value.hideItem(item);
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**图节点右击菜单 */
|
||||
const graphNodeMenu = new Menu({
|
||||
offsetX: 6,
|
||||
offseY: 10,
|
||||
itemTypes: ['node'],
|
||||
getContent(evt) {
|
||||
console.log(evt);
|
||||
if (!evt) return '无';
|
||||
const item = evt.item?.getModel();
|
||||
const edit = graphMode.value === 'edit';
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<h3>节点:${item?.label || '无标签'}</h3>
|
||||
<div id="hide" style="cursor: pointer; margin-bottom: 2px">
|
||||
隐藏
|
||||
</div>
|
||||
<div id="edit" style="cursor: pointer; margin-bottom: 2px; display: ${
|
||||
edit ? 'black' : 'none'
|
||||
}">
|
||||
编辑
|
||||
</div>
|
||||
<div id="delete" style="cursor: pointer; margin-bottom: 2px; display: ${
|
||||
edit ? 'black' : 'none'
|
||||
}">
|
||||
删除
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'edit':
|
||||
graphEvent.value = { type: `node-${targetId}`, target, item };
|
||||
break;
|
||||
case 'delete':
|
||||
graphG6.value.removeItem(item);
|
||||
break;
|
||||
case 'hide':
|
||||
graphG6.value.hideItem(item);
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**图节点展示 */
|
||||
const graphNodeTooltip = new Tooltip({
|
||||
offsetX: 10,
|
||||
offsetY: 20,
|
||||
getContent(evt) {
|
||||
console.log(evt);
|
||||
if (!evt) return '无';
|
||||
const item = evt.item?.getModel();
|
||||
if (!item?.label) {
|
||||
return '无标签';
|
||||
}
|
||||
console.log(item);
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<h3>节点: ${item?.label}</h3>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
itemTypes: ['node'],
|
||||
});
|
||||
|
||||
/**图边右击菜单 */
|
||||
const graphEdgeMenu = new Menu({
|
||||
offsetX: 6,
|
||||
offseY: 10,
|
||||
itemTypes: ['edge'],
|
||||
getContent(evt) {
|
||||
console.log(evt);
|
||||
if (!evt) return '无';
|
||||
const item = evt.item?.getModel();
|
||||
const edit = graphMode.value === 'edit';
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<strong>边:${item?.label || '无标签'}</strong>
|
||||
<div id="hide" style="cursor: pointer; margin-bottom: 2px">
|
||||
隐藏
|
||||
</div>
|
||||
<div id="edit" style="cursor: pointer; margin-bottom: 2px; display: ${
|
||||
edit ? 'black' : 'none'
|
||||
}">
|
||||
编辑
|
||||
</div>
|
||||
<div id="delete" style="cursor: pointer; margin-bottom: 2px; display: ${
|
||||
edit ? 'black' : 'none'
|
||||
}">
|
||||
删除
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'edit':
|
||||
graphEvent.value = { type: `edge-${targetId}`, target, item };
|
||||
break;
|
||||
case 'delete':
|
||||
graphG6.value.removeItem(item);
|
||||
break;
|
||||
case 'hide':
|
||||
graphG6.value.hideItem(item);
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**图边展示 */
|
||||
const graphEdgeTooltip = new Tooltip({
|
||||
offsetX: 10,
|
||||
offsetY: 20,
|
||||
getContent(evt) {
|
||||
console.log(evt);
|
||||
if (!evt) return '无';
|
||||
const item = evt.item?.getModel();
|
||||
if (!item?.label) {
|
||||
return '无标签';
|
||||
}
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<h3>边: ${item?.label}</h3>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
itemTypes: ['edge'],
|
||||
});
|
||||
|
||||
/**图绑定事件 */
|
||||
function fnGraphEvent(graph: Graph) {
|
||||
// 调用 graph.add / graph.addItem 方法之后触发
|
||||
graph.on('afteradditem', evt => {
|
||||
fnSelectSourceTargetOptionsData();
|
||||
});
|
||||
|
||||
// 鼠标进入节点事件
|
||||
graph.on('edge:mouseenter', (ev: any) => {
|
||||
// 获得鼠标当前目标边
|
||||
const edge = ev.item;
|
||||
// 该边的起始点
|
||||
const source = edge.getSource();
|
||||
// 该边的结束点
|
||||
const target = edge.getTarget();
|
||||
// 先将边提前,再将端点提前。这样该边两个端点还是在该边上层,较符合常规。
|
||||
// edge.toFront();
|
||||
// source.toFront();
|
||||
// target.toFront();
|
||||
});
|
||||
|
||||
graph.on('edge:mouseleave', (ev: any) => {
|
||||
// 获得图上所有边实例
|
||||
const edges = graph.getEdges();
|
||||
// 遍历边,将所有边的层级放置在后方,以恢复原样
|
||||
// edges.forEach(edge => {
|
||||
// edge.toBack();
|
||||
// });
|
||||
});
|
||||
|
||||
graph.on('node:mouseenter', evt => {
|
||||
// 获得鼠标当前目标节点
|
||||
const node = evt.item;
|
||||
// 获取该节点的所有相关边
|
||||
const edges = node && graph.getEdges();
|
||||
// 遍历相关边,将所有相关边提前,再将相关边的两个端点提前,以保证相关边的端点在边的上方常规效果
|
||||
// edges.forEach((edge: any) => {
|
||||
// edge.toFront();
|
||||
// edge.getSource().toFront();
|
||||
// edge.getTarget().toFront();
|
||||
// });
|
||||
// graphEvent.value = {
|
||||
// type: 'node:mouseenter',
|
||||
// target: evt.target,
|
||||
// item: evt.item,
|
||||
// };
|
||||
});
|
||||
|
||||
graph.on('node:mouseleave', (ev: any) => {
|
||||
// 获得图上所有边实例
|
||||
const edges = graph.getEdges();
|
||||
// 遍历边,将所有边的层级放置在后方,以恢复原样
|
||||
// edges.forEach(edge => {
|
||||
// edge.toBack();
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 图元素选择开始结束点数据获取
|
||||
*/
|
||||
function fnSelectSourceTargetOptionsData() {
|
||||
// 节点
|
||||
selectSourceTargetOptions.value = [];
|
||||
graphG6.value.getNodes().forEach((node: any) => {
|
||||
const info = JSON.parse(JSON.stringify(node.getModel()));
|
||||
selectSourceTargetOptions.value.push({
|
||||
value: info.id,
|
||||
label: info.label,
|
||||
info,
|
||||
});
|
||||
});
|
||||
// 分组
|
||||
selectComboOptions.value = [
|
||||
{
|
||||
value: '',
|
||||
label: '未分配',
|
||||
},
|
||||
];
|
||||
graphG6.value.getCombos().forEach((combo: any) => {
|
||||
const info = JSON.parse(JSON.stringify(combo.getModel()));
|
||||
const comboInfo = {
|
||||
value: info.id,
|
||||
label: info.label,
|
||||
info,
|
||||
};
|
||||
selectSourceTargetOptions.value.push(comboInfo);
|
||||
selectComboOptions.value.push(comboInfo);
|
||||
});
|
||||
}
|
||||
|
||||
/**图数据渲染 */
|
||||
function handleRanderGraph(container: HTMLElement, data: GraphData) {
|
||||
if (!container) return;
|
||||
const { clientHeight, clientWidth } = container;
|
||||
|
||||
const graph = new Graph({
|
||||
container: container,
|
||||
width: clientWidth,
|
||||
height: clientHeight,
|
||||
animate: true,
|
||||
fitCenter: true,
|
||||
modes: {
|
||||
default: [
|
||||
{
|
||||
type: 'click-select',
|
||||
selectEdge: true,
|
||||
},
|
||||
'drag-combo',
|
||||
{
|
||||
type: 'drag-node',
|
||||
onlyChangeComboSize: true,
|
||||
},
|
||||
'drag-canvas',
|
||||
'zoom-canvas',
|
||||
'collapse-expand-combo',
|
||||
],
|
||||
edit: [
|
||||
{
|
||||
type: 'click-select',
|
||||
selectEdge: true,
|
||||
},
|
||||
{
|
||||
type: 'drag-node',
|
||||
shouldEnd: (e: any) => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{ type: 'drag-combo' },
|
||||
'drag-canvas',
|
||||
'zoom-canvas',
|
||||
{ type: 'create-edge', key: 'alt' },
|
||||
],
|
||||
},
|
||||
groupByTypes: false,
|
||||
// layout: {
|
||||
// type: 'dagre',
|
||||
// sortByCombo: false,
|
||||
// ranksep: 10,
|
||||
// nodesep: 10,
|
||||
// },
|
||||
// 全局节点
|
||||
defaultNode: {
|
||||
type: 'rect',
|
||||
size: [80, 40],
|
||||
style: {
|
||||
radius: 4,
|
||||
// fill: '#ffffff',
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
cursor: 'pointer',
|
||||
},
|
||||
labelCfg: {
|
||||
position: 'center',
|
||||
offset: 0,
|
||||
style: {
|
||||
fill: '#000000',
|
||||
fontSize: 12,
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
icon: {
|
||||
show: false,
|
||||
img: '/svg/service.svg',
|
||||
width: 25,
|
||||
height: 25,
|
||||
offset: 20, // triangle 特有
|
||||
},
|
||||
direction: 'up', // triangle 三角形的方向
|
||||
},
|
||||
// 全局边
|
||||
defaultEdge: {
|
||||
type: 'polyline',
|
||||
style: {
|
||||
offset: 20, // 拐弯处距离节点最小距离
|
||||
radius: 2, // 拐弯处的圆角弧度,若不设置则为直角
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
cursor: 'pointer',
|
||||
},
|
||||
labelCfg: {
|
||||
refX: 0,
|
||||
refY: 0,
|
||||
position: 'middle',
|
||||
autoRotate: false,
|
||||
style: {
|
||||
fill: '#ffffff',
|
||||
fontSize: 12,
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
},
|
||||
// 全局分组节点
|
||||
defaultCombo: {
|
||||
type: 'rect', // Combo 类型
|
||||
size: [40, 40],
|
||||
padding: [30, 30, 30, 30],
|
||||
style: {
|
||||
radius: 2,
|
||||
fill: '#ffffff',
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
cursor: 'grab',
|
||||
fillOpacity: 0.5,
|
||||
},
|
||||
labelCfg: {
|
||||
refX: 10,
|
||||
refY: 10,
|
||||
position: 'top',
|
||||
style: {
|
||||
fill: '#000000',
|
||||
fontSize: 12,
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
graphCanvasMenu,
|
||||
graphComboMenu,
|
||||
graphNodeMenu,
|
||||
graphNodeTooltip,
|
||||
graphEdgeMenu,
|
||||
graphEdgeTooltip,
|
||||
],
|
||||
});
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
|
||||
// 图绑定事件
|
||||
fnGraphEvent(graph);
|
||||
|
||||
graphG6.value = graph;
|
||||
|
||||
// 图元素选择开始结束点数据
|
||||
fnSelectSourceTargetOptionsData();
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**图模式改变 default | edit */
|
||||
function handleChangeMode(value: any) {
|
||||
console.log(value, JSON.parse(JSON.stringify(graphG6.value.save())));
|
||||
graphG6.value.setMode(value);
|
||||
graphMode.value = graphG6.value.getCurrentMode();
|
||||
}
|
||||
|
||||
return {
|
||||
handleRanderGraph,
|
||||
handleChangeMode,
|
||||
};
|
||||
}
|
||||
323
src/views/monitor/topology-build/hooks/useNode.ts
Normal file
323
src/views/monitor/topology-build/hooks/useNode.ts
Normal file
@@ -0,0 +1,323 @@
|
||||
import { message, Form } from 'ant-design-vue/lib';
|
||||
import { reactive, watch } from 'vue';
|
||||
import { graphG6 } from './useGraph';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
|
||||
/**图节点内置边类型 */
|
||||
export const nodeTypeOptions = [
|
||||
{
|
||||
value: 'circle',
|
||||
label: '圆形',
|
||||
},
|
||||
{
|
||||
value: 'rect',
|
||||
label: '矩形',
|
||||
},
|
||||
{
|
||||
value: 'ellipse',
|
||||
label: '椭圆',
|
||||
},
|
||||
{
|
||||
value: 'diamond',
|
||||
label: '菱形',
|
||||
},
|
||||
{
|
||||
value: 'triangle',
|
||||
label: '三角形',
|
||||
},
|
||||
{
|
||||
value: 'star',
|
||||
label: '星形',
|
||||
},
|
||||
{
|
||||
value: 'image',
|
||||
label: '图片',
|
||||
},
|
||||
{
|
||||
value: 'donut',
|
||||
label: '面包圈',
|
||||
},
|
||||
];
|
||||
|
||||
/**图节点标签文本位置 */
|
||||
export const nodePositionOptions = [
|
||||
{
|
||||
value: 'top',
|
||||
label: '上',
|
||||
},
|
||||
{
|
||||
value: 'left',
|
||||
label: '左',
|
||||
},
|
||||
{
|
||||
value: 'right',
|
||||
label: '右',
|
||||
},
|
||||
{
|
||||
value: 'bottom',
|
||||
label: '下',
|
||||
},
|
||||
{
|
||||
value: 'center',
|
||||
label: '居中',
|
||||
},
|
||||
];
|
||||
|
||||
/**图节点三角形方向 */
|
||||
export const nodeDirectionOptions = [
|
||||
{ value: 'up', label: '向上' },
|
||||
{ value: 'down', label: '向下' },
|
||||
{ value: 'left', label: '向左' },
|
||||
{ value: 'right', label: '向右' },
|
||||
];
|
||||
|
||||
/**图节点图片裁剪的形状 */
|
||||
export const nodeImageClipCfgOptions = [
|
||||
{ value: 'circle', label: '圆形' },
|
||||
{ value: 'rect', label: '矩形' },
|
||||
{ value: 'ellipse', label: '椭圆' },
|
||||
];
|
||||
|
||||
/**图节点图片来源 */
|
||||
export const nodeImageOptions = [
|
||||
{ value: '/svg/base.svg', label: '基站' },
|
||||
{ value: '/svg/cloud.svg', label: '云' },
|
||||
{ value: '/svg/service.svg', label: '服务器' },
|
||||
{ value: '/svg/service_db.svg', label: '数据服务器' },
|
||||
];
|
||||
|
||||
export default function useNode() {
|
||||
const { t } = useI18n();
|
||||
|
||||
/**图节点信息状态类型 */
|
||||
type NodeStateType = {
|
||||
/**图节点原始数据 */
|
||||
origin: Record<string, any>;
|
||||
/**图节点表单数据 */
|
||||
form: Record<string, any>;
|
||||
};
|
||||
|
||||
/**图节点信息状态 */
|
||||
let nodeState: NodeStateType = reactive({
|
||||
origin: {},
|
||||
form: {
|
||||
id: '',
|
||||
comboId: '',
|
||||
x: 0,
|
||||
y: 0,
|
||||
type: 'rect',
|
||||
size: [80, 40],
|
||||
anchorPoints: false,
|
||||
style: {
|
||||
fill: '#ffffff',
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
},
|
||||
label: '',
|
||||
labelCfg: {
|
||||
position: 'center',
|
||||
offset: 0,
|
||||
style: {
|
||||
fill: '#000000',
|
||||
fontSize: 12,
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**图节点对话框内表单属性和校验规则 */
|
||||
const nodeStateForm = Form.useForm(
|
||||
nodeState.form,
|
||||
reactive({
|
||||
id: [{ required: true, message: '节点唯一 ID' }],
|
||||
type: [{ required: true, message: 'line' }],
|
||||
})
|
||||
);
|
||||
|
||||
/**图节点编辑监听更新视图 */
|
||||
watch(nodeState.form, node => {
|
||||
const info = JSON.parse(JSON.stringify(node));
|
||||
// 新增不监听变化
|
||||
const nodeOriginId = nodeState.origin.id;
|
||||
const nodeId = info.id;
|
||||
if (nodeId && nodeId === nodeOriginId) {
|
||||
// 图片类型需要移除style属性,避免填充
|
||||
if (info.type === 'image') {
|
||||
Reflect.deleteProperty(info, 'style');
|
||||
}
|
||||
graphG6.value.clearItemStates(nodeId, 'selected');
|
||||
graphG6.value.updateItem(nodeId, info);
|
||||
// 三角和图片的样式变更需要重绘才生效
|
||||
if (
|
||||
info.type === 'triangle' ||
|
||||
info.type === 'image' ||
|
||||
info.comboId !== nodeState.origin.comboId
|
||||
) {
|
||||
graphG6.value.read(graphG6.value.save());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**图节点类型输入限制 */
|
||||
function handleNodeTypeChange(type: any) {
|
||||
// 设置图标属性
|
||||
if (['circle', 'ellipse', 'diamond', 'star', 'donut'].includes(type)) {
|
||||
let size: number[] | number = [40, 30];
|
||||
if (['circle', 'star', 'donut'].includes(type)) {
|
||||
size = 60;
|
||||
}
|
||||
const origin = nodeState.origin;
|
||||
if (origin.icon) {
|
||||
nodeState.form = Object.assign(nodeState.form, {
|
||||
size,
|
||||
icon: origin.icon,
|
||||
});
|
||||
} else {
|
||||
nodeState.form = Object.assign(nodeState.form, {
|
||||
size,
|
||||
icon: {
|
||||
show: false,
|
||||
img: '',
|
||||
width: 25,
|
||||
height: 25,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else if (type === 'triangle') {
|
||||
// 三角
|
||||
const origin = nodeState.origin;
|
||||
if (origin.icon) {
|
||||
nodeState.form = Object.assign(nodeState.form, {
|
||||
size: 40,
|
||||
direction: origin.direction || 'up', // triangle 三角形的方向
|
||||
icon: Object.assign({ offset: 20 }, origin.icon),
|
||||
});
|
||||
} else {
|
||||
nodeState.form = Object.assign(nodeState.form, {
|
||||
size: 30,
|
||||
direction: 'up', // triangle 三角形的方向
|
||||
icon: {
|
||||
show: false,
|
||||
img: '/svg/service.svg',
|
||||
width: 25,
|
||||
height: 25,
|
||||
offset: 20, // triangle 特有
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
// 设置图片属性
|
||||
if (type === 'image') {
|
||||
const origin = nodeState.origin;
|
||||
if (origin.img) {
|
||||
nodeState.form = Object.assign(nodeState.form, {
|
||||
size: [30, 30],
|
||||
img: origin.img,
|
||||
clipCfg: origin.clipCfg,
|
||||
});
|
||||
} else {
|
||||
nodeState.form = Object.assign(nodeState.form, {
|
||||
size: [30, 30],
|
||||
img: '/svg/service.svg',
|
||||
clipCfg: {
|
||||
show: false,
|
||||
width: 0,
|
||||
height: 0,
|
||||
type: 'circle',
|
||||
},
|
||||
});
|
||||
}
|
||||
Reflect.deleteProperty(nodeState.form, 'style');
|
||||
} else {
|
||||
// 当切换非图片时补充style属性
|
||||
if (!Reflect.has(nodeState.form, 'style')) {
|
||||
nodeState.form = Object.assign(nodeState.form, {
|
||||
style: {
|
||||
fill: '#ffffff',
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
// 设置矩形大小
|
||||
if (type === 'rect') {
|
||||
nodeState.form = Object.assign(nodeState.form, {
|
||||
size: [80, 40],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**图节点新增或更新 */
|
||||
function handleOkNode() {
|
||||
return nodeStateForm
|
||||
.validate()
|
||||
.then(e => {
|
||||
const node = JSON.parse(JSON.stringify(nodeState.form));
|
||||
if (!node.id) {
|
||||
message.warn({
|
||||
content: `节点元素ID错误`,
|
||||
duration: 2,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// 存在更新,新增不监听变化
|
||||
const item = graphG6.value.findById(node.id);
|
||||
if (item) {
|
||||
graphG6.value.updateItem(item, node);
|
||||
} else {
|
||||
graphG6.value.addItem('node', node);
|
||||
}
|
||||
|
||||
// 三角和图片的样式变更需要重绘才生效
|
||||
if (
|
||||
node.type === 'triangle' ||
|
||||
node.type === 'image' ||
|
||||
node.comboId !== nodeState.origin.comboId
|
||||
) {
|
||||
graphG6.value.read(graphG6.value.save());
|
||||
}
|
||||
|
||||
nodeStateForm.resetFields();
|
||||
nodeState.origin = {};
|
||||
return true;
|
||||
})
|
||||
.catch(e => {
|
||||
message.error(
|
||||
t('common.errorFields', { num: e.errorFields.length }),
|
||||
3
|
||||
);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**图节点取消还原 */
|
||||
function handleCancelNode() {
|
||||
// 新增无原始数据
|
||||
const origin = JSON.parse(JSON.stringify(nodeState.origin));
|
||||
if (origin.id) {
|
||||
graphG6.value.updateItem(origin.id, origin);
|
||||
|
||||
// 三角和图片的样式变更需要重绘才生效
|
||||
if (
|
||||
origin.type === 'triangle' ||
|
||||
origin.type === 'image' ||
|
||||
origin.comboId !== nodeState.form.comboId
|
||||
) {
|
||||
graphG6.value.read(graphG6.value.save());
|
||||
}
|
||||
}
|
||||
nodeStateForm.resetFields();
|
||||
nodeState.origin = {};
|
||||
}
|
||||
|
||||
return {
|
||||
nodeState,
|
||||
nodeStateForm,
|
||||
handleNodeTypeChange,
|
||||
handleOkNode,
|
||||
handleCancelNode,
|
||||
};
|
||||
}
|
||||
2479
src/views/monitor/topology-build/index.vue
Normal file
2479
src/views/monitor/topology-build/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
1755
src/views/monitor/topology/graph.ts
Normal file
1755
src/views/monitor/topology/graph.ts
Normal file
File diff suppressed because it is too large
Load Diff
334
src/views/monitor/topology/index.vue
Normal file
334
src/views/monitor/topology/index.vue
Normal file
@@ -0,0 +1,334 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import ChartGraphG6 from '@/components/ChartGraphG6/index.vue';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { listNe, stateNe } from '@/api/ne/ne';
|
||||
import message from 'ant-design-vue/lib/message';
|
||||
import { randerGroph, switchLayout } from './graph';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
const { t } = useI18n();
|
||||
|
||||
/**图DOM节点实例对象 */
|
||||
const graphG6Dom = ref<HTMLElement | undefined>(undefined);
|
||||
|
||||
/**图实例对象 */
|
||||
const graphG6 = ref<any>(null);
|
||||
|
||||
/**图数据 */
|
||||
const graphG6Data = reactive<Record<string, any>>({
|
||||
nodes: [],
|
||||
edges: [],
|
||||
});
|
||||
|
||||
/**查询全部网元数据列表 */
|
||||
function fnRanderData() {
|
||||
if (!graphG6Dom.value) return;
|
||||
graphG6.value = randerGroph(graphG6Dom.value, graphG6Data);
|
||||
}
|
||||
|
||||
/**查询网元状态 */
|
||||
async function fnGetState() {
|
||||
for (const node of graphG6Data.nodes) {
|
||||
const ne = node.info;
|
||||
if (ne.neType === 'OMC') continue;
|
||||
const result = await stateNe(ne.neType, ne.neId);
|
||||
if (result.code === RESULT_CODE_SUCCESS) {
|
||||
ne.serverState = result.data;
|
||||
ne.serverState.refreshTime = parseDateToStr(
|
||||
ne.serverState.refreshTime,
|
||||
'HH:mm:ss'
|
||||
);
|
||||
}
|
||||
// 修改网元状态颜色
|
||||
const neShape = graphG6.value.findById(ne.neName);
|
||||
graphG6.value.setItemState(
|
||||
neShape,
|
||||
'neState',
|
||||
result.code === RESULT_CODE_SUCCESS
|
||||
);
|
||||
}
|
||||
setTimeout(() => fnGetState(), 30_000);
|
||||
}
|
||||
|
||||
/**查询全部网元数据列表 */
|
||||
function fnGetList(refresh: boolean = false) {
|
||||
listNe({
|
||||
bandStatus: false,
|
||||
})
|
||||
.then(res => {
|
||||
if (
|
||||
res.code === RESULT_CODE_SUCCESS &&
|
||||
Array.isArray(res.data) &&
|
||||
res.data.length > 0
|
||||
) {
|
||||
let rootNode = 'OMC';
|
||||
const nodes = [];
|
||||
const edges = [];
|
||||
for (const item of res.data) {
|
||||
item.serverState = {};
|
||||
const nodeIndex = nodes.findIndex(v => v.id === item.neName);
|
||||
if (nodeIndex === -1) {
|
||||
// 根网管
|
||||
if (item.neType === 'OMC') {
|
||||
rootNode = item.neName;
|
||||
item.serverState = {
|
||||
neId: item.neId,
|
||||
neName: item.neName,
|
||||
neType: item.neType,
|
||||
expire: '-',
|
||||
refreshTime: '-',
|
||||
sn: '-',
|
||||
version: '-',
|
||||
};
|
||||
nodes.push({
|
||||
id: item.neName,
|
||||
label: item.neName,
|
||||
info: item,
|
||||
labelCfg: {
|
||||
position: 'bottom',
|
||||
offset: 8,
|
||||
style: {
|
||||
fill: '#fff',
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
size: 60,
|
||||
icon: {
|
||||
x: -30,
|
||||
y: -30,
|
||||
// 可更换为其他图片地址
|
||||
img: '/svg/service_db.svg',
|
||||
width: 60,
|
||||
height: 60,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
nodes.push({
|
||||
id: item.neName,
|
||||
label: item.neName,
|
||||
info: item,
|
||||
size: 48,
|
||||
icon: {
|
||||
x: -24,
|
||||
y: -24,
|
||||
img: '/svg/service.svg',
|
||||
width: 48,
|
||||
height: 48,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (item.neType !== 'OMC') {
|
||||
const edgeIndex = edges.findIndex(v => v.source === item.neName);
|
||||
if (edgeIndex === -1) {
|
||||
edges.push({
|
||||
source: item.neName,
|
||||
target: rootNode,
|
||||
label: `${item.neType}-${rootNode}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
graphG6Data.nodes = nodes;
|
||||
graphG6Data.edges = edges;
|
||||
console.log(graphG6Data);
|
||||
return true;
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.then(hasNeList => {
|
||||
if (!hasNeList) return;
|
||||
if (refresh) {
|
||||
// graphG6.value.get('canvas').set('localRefresh', true);
|
||||
graphG6.value.destroy();
|
||||
// graphG6.value.clear();
|
||||
}
|
||||
fnRanderData();
|
||||
fnGetState();
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元列表
|
||||
fnGetList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px' }"
|
||||
size="small"
|
||||
>
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title v-if="false">
|
||||
<div class="button-container" style="margin-bottom: -12px">
|
||||
<a-button type="primary">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
{{ t('common.addText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="primary" danger ghost>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.auth.batchDelText') }}
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.loadDataConfirm')"
|
||||
:ok-text="t('common.ok')"
|
||||
:cancel-text="t('common.cancel')"
|
||||
>
|
||||
<a-button type="dashed" danger>
|
||||
<template #icon>
|
||||
<SyncOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.sub.loadData') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button type="dashed">
|
||||
<template #icon>
|
||||
<ImportOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.sub.import') }}
|
||||
</a-button>
|
||||
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.exportConfirm')"
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
>
|
||||
<a-button type="dashed">
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.sub.export') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-button type="default" @click.prevent="switchLayout()">
|
||||
<template #icon><RetweetOutlined /></template>
|
||||
Switch Layout
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<div ref="graphG6Dom" class="chart"></div>
|
||||
|
||||
<template v-if="false">
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 200px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<div><span>状态:</span><span>正常</span></div>
|
||||
<div><span>刷新时间:</span><span>18:37:22</span></div>
|
||||
<div><span>ID:</span><span>neID</span></div>
|
||||
<div><span>名称:</span><span>neName</span></div>
|
||||
<div><span>版本:</span><span>2.2312.8</span></div>
|
||||
<div><span>SN:</span><span>13770707</span></div>
|
||||
<div><span>有效期:</span><span>2024-03-31</span></div>
|
||||
</div>
|
||||
===
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<div id="show" style="cursor: pointer; margin-bottom: 2px">
|
||||
1. 显示所有隐藏项
|
||||
</div>
|
||||
<div id="collapseAll" style="cursor: pointer; margin-bottom: 2px">
|
||||
2. 折叠所有集群
|
||||
</div>
|
||||
</div>
|
||||
===
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<div id="expand" style="cursor: pointer; margin-bottom: 2px">
|
||||
1. 展开集群
|
||||
</div>
|
||||
<div id="hide" style="cursor: pointer; margin-bottom: 2px">
|
||||
2. 隐藏节点
|
||||
</div>
|
||||
</div>
|
||||
===
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 160px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<div id="collapse" style="cursor: pointer; margin-bottom: 2px">
|
||||
1. 折叠集群
|
||||
</div>
|
||||
<div id="hide" style="cursor: pointer; margin-bottom: 2px">
|
||||
2. 隐藏节点
|
||||
</div>
|
||||
<div id="restart" style="cursor: pointer; margin-bottom: 2px">
|
||||
3. 重启
|
||||
</div>
|
||||
</div>
|
||||
===
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100px;
|
||||
background: #e6f7ff;
|
||||
"
|
||||
>
|
||||
<div id="hide" style="cursor: pointer; margin-bottom: 2px">
|
||||
1. 隐藏边
|
||||
</div>
|
||||
</div>
|
||||
<!-- 组件 -->
|
||||
<div class="charts">
|
||||
<ChartGraphG6></ChartGraphG6>
|
||||
</div>
|
||||
</template>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.chart {
|
||||
width: 100%;
|
||||
height: calc(100vh - 300px);
|
||||
background-color: rgb(43, 47, 51);
|
||||
}
|
||||
.charts {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
background-color: rgb(238, 237, 237);
|
||||
margin-top: 32px;
|
||||
}
|
||||
</style>
|
||||
@@ -70,6 +70,8 @@ type TabeStateType = {
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
@@ -79,6 +81,7 @@ let tableState: TabeStateType = reactive({
|
||||
striped: false,
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
@@ -180,6 +183,11 @@ function fnTableChange(pagination: any, filters: any, sorter: any, extra: any) {
|
||||
fnGetList(1);
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**新增框或修改框是否显示 */
|
||||
@@ -482,36 +490,79 @@ function fnModalCancel() {
|
||||
|
||||
/**
|
||||
* UDM鉴权用户删除
|
||||
* @param row 网元编号ID
|
||||
* @param imsi 编号imsi
|
||||
*/
|
||||
function fnRecordDelete(row: Record<string, any>) {
|
||||
function fnRecordDelete(imsi: string) {
|
||||
const neID = queryParams.neId;
|
||||
if (!neID) return;
|
||||
let imsiMsg = imsi;
|
||||
if (imsi === '0') {
|
||||
imsiMsg = `${tableState.selectedRowKeys[0]}... ${t(
|
||||
'views.neUser.auth.numDel'
|
||||
)} ${tableState.selectedRowKeys.length}`;
|
||||
imsi = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.neUser.auth.delSure', { imsi: row.imsi }),
|
||||
content: t('views.neUser.auth.delSure', { imsi: imsiMsg }),
|
||||
onOk() {
|
||||
const key = 'delNotice';
|
||||
message.loading({ content: t('common.loading'), key });
|
||||
const neID = queryParams.neId || '-';
|
||||
delAuth(neID, row).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.msgSuccess', { msg: t('common.deleteText') }),
|
||||
key,
|
||||
duration: 2,
|
||||
});
|
||||
modalState.loadDataLoading = true;
|
||||
const hide = message.loading({ content: t('common.loading') });
|
||||
delAuth(neID, imsi)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
const msgContent = t('common.msgSuccess', {
|
||||
msg: t('common.deleteText'),
|
||||
});
|
||||
message.success({
|
||||
content: `${msgContent} : ${imsiMsg}`,
|
||||
duration: 3,
|
||||
});
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
fnGetList();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
key: key,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
modalState.loadDataLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM鉴权用户导出
|
||||
*/
|
||||
function fnRecordExport(type: string = 'txt') {
|
||||
const selectLen = tableState.selectedRowKeys.length;
|
||||
if (selectLen <= 0) return;
|
||||
const rows: Record<string, any>[] = tableState.data.filter(
|
||||
(row: Record<string, any>) =>
|
||||
tableState.selectedRowKeys.indexOf(row.imsi) >= 0
|
||||
);
|
||||
|
||||
let content = '';
|
||||
if (type == 'txt') {
|
||||
for (const row of rows) {
|
||||
content += `${row.imsi},${row.ki},${row.algoIndex},${row.amf},${row.opc}\r\n`;
|
||||
}
|
||||
}
|
||||
if (type == 'csv') {
|
||||
content = `IMSI,ki,Algo Index,AMF,OPC\r\n`;
|
||||
for (const row of rows) {
|
||||
content += `${row.imsi},${row.ki},${row.algoIndex},${row.amf},${row.opc}\r\n`;
|
||||
}
|
||||
}
|
||||
|
||||
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
|
||||
saveAs(blob, `UDMAuth_${Date.now()}.${type}`);
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList(type: string) {
|
||||
const neID = queryParams.neId;
|
||||
@@ -583,6 +634,10 @@ function fnGetList(pageNum?: number) {
|
||||
}
|
||||
listAuth(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;
|
||||
}
|
||||
@@ -728,7 +783,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
@@ -742,6 +797,18 @@ onMounted(() => {
|
||||
</template>
|
||||
{{ t('views.neUser.auth.batchAddText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.loadDataLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('views.neUser.auth.checkDel') }}
|
||||
</a-button>
|
||||
|
||||
<a-button
|
||||
type="primary"
|
||||
danger
|
||||
@@ -753,6 +820,7 @@ onMounted(() => {
|
||||
</template>
|
||||
{{ t('views.neUser.auth.batchDelText') }}
|
||||
</a-button>
|
||||
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.auth.loadDataConfirm')"
|
||||
:ok-text="t('common.ok')"
|
||||
@@ -778,6 +846,7 @@ onMounted(() => {
|
||||
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.auth.exportConfirm')"
|
||||
placement="topRight"
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
@confirm="fnExportList('txt')"
|
||||
@@ -790,12 +859,32 @@ onMounted(() => {
|
||||
{{ t('views.neUser.auth.export') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.auth.checkExportConfirm')"
|
||||
placement="topRight"
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
@confirm="fnRecordExport('txt')"
|
||||
:show-cancel="false"
|
||||
cancel-text="CSV"
|
||||
@cancel="fnRecordExport('csv')"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
>
|
||||
<a-button
|
||||
type="default"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
>
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('views.neUser.auth.checkExport') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -848,7 +937,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
@@ -864,6 +953,11 @@ onMounted(() => {
|
||||
:scroll="{ y: 'calc(100vh - 480px)' }"
|
||||
@change="fnTableChange"
|
||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'imsi'">
|
||||
@@ -881,7 +975,10 @@ onMounted(() => {
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.deleteText') }}</template>
|
||||
<a-button type="link" @click.prevent="fnRecordDelete(record)">
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.imsi)"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
|
||||
@@ -253,26 +253,11 @@ function fnModalOk() {
|
||||
from.neId = queryParams.neId || '-';
|
||||
from.rfsp = Number(from.rfsp) || 0;
|
||||
|
||||
// 根据类型选择函数
|
||||
let result: any = null;
|
||||
let validateArr = ['imsi', 'msisdn'];
|
||||
if (modalState.isBatch) {
|
||||
validateArr.push('num');
|
||||
if (modalState.type === 'add') {
|
||||
result = batchAddRule(from);
|
||||
}
|
||||
if (modalState.type === 'update') {
|
||||
result = batchUpdateRule(from);
|
||||
}
|
||||
if (modalState.type === 'delete') {
|
||||
result = batchDelRule(from);
|
||||
}
|
||||
} else {
|
||||
if (modalState.type === 'add') {
|
||||
result = addRule(from);
|
||||
}
|
||||
if (modalState.type === 'update') {
|
||||
result = updateRule(from);
|
||||
validateArr = ['num', 'imsi'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,8 +265,29 @@ function fnModalOk() {
|
||||
.validate(validateArr)
|
||||
.then(e => {
|
||||
modalState.confirmLoading = true;
|
||||
|
||||
const hide = message.loading({ content: t('common.loading') });
|
||||
|
||||
// 根据类型选择函数
|
||||
let result: any = null;
|
||||
if (modalState.isBatch) {
|
||||
if (modalState.type === 'add') {
|
||||
result = batchAddRule(from);
|
||||
}
|
||||
if (modalState.type === 'update') {
|
||||
result = batchUpdateRule(from);
|
||||
}
|
||||
if (modalState.type === 'delete') {
|
||||
result = batchDelRule(from);
|
||||
}
|
||||
} else {
|
||||
if (modalState.type === 'add') {
|
||||
result = addRule(from);
|
||||
}
|
||||
if (modalState.type === 'update') {
|
||||
result = updateRule(from);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
.then((res: any) => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
@@ -410,10 +416,7 @@ function fnGetList() {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
tableState.data = res.rows;
|
||||
} else {
|
||||
message.warning({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
tableState.data = [];
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
@@ -472,10 +475,12 @@ function fnModalUploadImportUpload(file: File) {
|
||||
return res;
|
||||
})
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data?.detail) {
|
||||
if (res.code === RESULT_CODE_SUCCESS && res.data?.filePath) {
|
||||
uploadImportState.msg = t('views.neUser.pcf.uploadFileOk');
|
||||
} else if (res.code === RESULT_CODE_SUCCESS && res.data?.detail) {
|
||||
uploadImportState.msg = res.data?.detail;
|
||||
} else {
|
||||
uploadImportState.msg = res.msg;
|
||||
uploadImportState.msg = t('views.neUser.pcf.uploadFileErr');
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -570,7 +575,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
@@ -628,12 +633,12 @@ onMounted(() => {
|
||||
{{ t('views.neUser.pcf.export') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>
|
||||
{{
|
||||
@@ -694,7 +699,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
@@ -776,7 +781,11 @@ onMounted(() => {
|
||||
name="imsi"
|
||||
v-bind="modalStateFrom.validateInfos.imsi"
|
||||
>
|
||||
<a-input v-model:value="modalState.from.imsi" allow-clear>
|
||||
<a-input
|
||||
v-model:value="modalState.from.imsi"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
@@ -824,6 +833,7 @@ onMounted(() => {
|
||||
<a-input
|
||||
v-model:value="modalState.from.imsi"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
:disabled="
|
||||
!modalState.isBatch && modalState.type === 'update'
|
||||
"
|
||||
@@ -851,6 +861,7 @@ onMounted(() => {
|
||||
<a-input
|
||||
v-model:value="modalState.from.msisdn"
|
||||
allow-clear
|
||||
:maxlength="16"
|
||||
:disabled="
|
||||
!modalState.isBatch && modalState.type === 'update'
|
||||
"
|
||||
@@ -863,13 +874,21 @@ onMounted(() => {
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="PCC Rules" name="pccRules">
|
||||
<a-input v-model:value="modalState.from.pccRules" allow-clear>
|
||||
<a-input
|
||||
v-model:value="modalState.from.pccRules"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="SESS Rules" name="sessRules">
|
||||
<a-input v-model:value="modalState.from.sessRules" allow-clear>
|
||||
<a-input
|
||||
v-model:value="modalState.from.sessRules"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -878,13 +897,21 @@ onMounted(() => {
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="QOS Audio" name="qosAudio">
|
||||
<a-input v-model:value="modalState.from.qosAudio" allow-clear>
|
||||
<a-input
|
||||
v-model:value="modalState.from.qosAudio"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="QOS Video" name="qosVideo">
|
||||
<a-input v-model:value="modalState.from.qosVideo" allow-clear>
|
||||
<a-input
|
||||
v-model:value="modalState.from.qosVideo"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -893,13 +920,21 @@ onMounted(() => {
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="HDR Enrich" name="hdrEnrich">
|
||||
<a-input v-model:value="modalState.from.hdrEnrich" allow-clear>
|
||||
<a-input
|
||||
v-model:value="modalState.from.hdrEnrich"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="UE Policy" name="uePolicy">
|
||||
<a-input v-model:value="modalState.from.uePolicy" allow-clear>
|
||||
<a-input
|
||||
v-model:value="modalState.from.uePolicy"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -908,14 +943,23 @@ onMounted(() => {
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="Sar" name="sar">
|
||||
<a-input v-model:value="modalState.from.sar" allow-clear>
|
||||
<a-input
|
||||
v-model:value="modalState.from.sar"
|
||||
allow-clear
|
||||
:maxlength="64"
|
||||
>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="RFSP" name="rfsp">
|
||||
<a-input v-model:value="modalState.from.rfsp" allow-clear>
|
||||
</a-input>
|
||||
<a-input-number
|
||||
v-model:value="modalState.from.rfsp"
|
||||
style="width: 100%"
|
||||
:min="0"
|
||||
:max="255"
|
||||
placeholder="0~255"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
@@ -73,6 +73,8 @@ type TabeStateType = {
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
/**勾选记录 */
|
||||
selectedRowKeys: (string | number)[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
@@ -82,6 +84,7 @@ let tableState: TabeStateType = reactive({
|
||||
striped: false,
|
||||
seached: true,
|
||||
data: [],
|
||||
selectedRowKeys: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
@@ -218,6 +221,11 @@ function fnTableChange(pagination: any, filters: any, sorter: any, extra: any) {
|
||||
fnGetList(1);
|
||||
}
|
||||
|
||||
/**表格多选 */
|
||||
function fnTableSelectedRowKeys(keys: (string | number)[]) {
|
||||
tableState.selectedRowKeys = keys;
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**详情框是否显示 */
|
||||
@@ -454,6 +462,7 @@ const modalStateFrom = Form.useForm(
|
||||
modalState.from,
|
||||
reactive({
|
||||
imsi: [{ required: true, message: 'IMSI' + t('common.unableNull') }],
|
||||
msisdn: [{ required: true, message: 'MSISDN' + t('common.unableNull') }],
|
||||
staticIp: [
|
||||
{ required: true, message: 'static ip' + t('common.unableNull') },
|
||||
],
|
||||
@@ -473,7 +482,7 @@ const modalStateFrom = Form.useForm(
|
||||
function fnModalOk() {
|
||||
const from = Object.assign({}, toRaw(modalState.from));
|
||||
|
||||
let validateNames = ['imsi', 'staticIp'];
|
||||
let validateNames = ['imsi', 'msisdn', 'staticIp'];
|
||||
|
||||
if (from.id === '') {
|
||||
validateNames.push('smData');
|
||||
@@ -573,7 +582,7 @@ function fnBatchModalOk() {
|
||||
modalState.confirmLoading = true;
|
||||
let ardArr = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||
let hplmnArr = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||
let odbArr = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||
let odbArr = [0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
from.ard.forEach((item: any) => {
|
||||
ardArr[item] = 1;
|
||||
@@ -710,37 +719,100 @@ function fnBatchDelModalCancel() {
|
||||
|
||||
/**
|
||||
* UDM签约用户删除
|
||||
* @param imsi 网元编号ID
|
||||
* @param imsi 编号imsi
|
||||
*/
|
||||
function fnRecordDelete(imsi: string) {
|
||||
const neID = queryParams.neId;
|
||||
if (!neID) return;
|
||||
let imsiMsg = imsi;
|
||||
if (imsi === '0') {
|
||||
imsiMsg = `${tableState.selectedRowKeys[0]}... ${t(
|
||||
'views.neUser.sub.numDel'
|
||||
)} ${tableState.selectedRowKeys.length}`;
|
||||
imsi = tableState.selectedRowKeys.join(',');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: t('common.tipTitle'),
|
||||
content: t('views.neUser.auth.delSure', { imsi: imsi }),
|
||||
content: t('views.neUser.auth.delSure', { imsi: imsiMsg }),
|
||||
onOk() {
|
||||
const key = 'delSub';
|
||||
message.loading({ content: t('common.loading'), key });
|
||||
delSub(neID, imsi).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
message.success({
|
||||
content: t('common.msgSuccess', { msg: t('common.deleteText') }),
|
||||
key,
|
||||
duration: 2,
|
||||
});
|
||||
modalState.loadDataLoading = true;
|
||||
const hide = message.loading({ content: t('common.loading') });
|
||||
delSub(neID, imsi)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
const msgContent = t('common.msgSuccess', {
|
||||
msg: t('common.deleteText'),
|
||||
});
|
||||
message.success({
|
||||
content: `${msgContent} : ${imsiMsg}`,
|
||||
duration: 3,
|
||||
});
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
fnGetList();
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
key: key,
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
modalState.loadDataLoading = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* UDM签约用户导出
|
||||
*/
|
||||
function fnRecordExport(type: string = 'txt') {
|
||||
const selectLen = tableState.selectedRowKeys.length;
|
||||
if (selectLen <= 0) return;
|
||||
const rows: Record<string, any>[] = tableState.data.filter(
|
||||
(row: Record<string, any>) =>
|
||||
tableState.selectedRowKeys.indexOf(row.imsi) >= 0
|
||||
);
|
||||
|
||||
let content = '';
|
||||
if (type == 'txt') {
|
||||
for (const row of rows) {
|
||||
debugger;
|
||||
const epsDat = [
|
||||
row.epsFlag,
|
||||
row.epsOdb,
|
||||
row.hplmnOdb,
|
||||
row.ard,
|
||||
row.epstpl,
|
||||
row.contextId,
|
||||
row.apnContext,
|
||||
row.staticIp,
|
||||
].join(',');
|
||||
content += `${row.imsi},${row.msisdn},${row.ambr},${row.nssai},${row.arfb},${row.sar},${row.rat},${row.cn},${row.smfSel},${row.smData},${epsDat}\r\n`;
|
||||
}
|
||||
}
|
||||
if (type == 'csv') {
|
||||
content = `imsi,msisdn,ambr,nssai,arfb,sar,rat,cn,smf_sel,sm_dat,eps_dat\r\n`;
|
||||
for (const row of rows) {
|
||||
const epsDat = [
|
||||
row.epsFlag,
|
||||
row.epsOdb,
|
||||
row.hplmnOdb,
|
||||
row.ard,
|
||||
row.epstpl,
|
||||
row.contextId,
|
||||
row.apnContext,
|
||||
row.staticIp,
|
||||
].join(',');
|
||||
content += `${row.imsi},${row.msisdn},${row.ambr},${row.nssai},${row.arfb},${row.sar},${row.rat},${row.cn},${row.smfSel},${row.smData},${epsDat}\r\n`;
|
||||
}
|
||||
}
|
||||
|
||||
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
|
||||
saveAs(blob, `UDMSub_${Date.now()}.${type}`);
|
||||
}
|
||||
|
||||
/**列表导出 */
|
||||
function fnExportList(type: string) {
|
||||
const neID = queryParams.neId;
|
||||
@@ -812,6 +884,10 @@ function fnGetList(pageNum?: number) {
|
||||
}
|
||||
listSub(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;
|
||||
}
|
||||
@@ -962,7 +1038,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
@@ -976,6 +1052,18 @@ onMounted(() => {
|
||||
</template>
|
||||
{{ t('views.neUser.auth.batchAddText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button
|
||||
type="default"
|
||||
danger
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
:loading="modalState.loadDataLoading"
|
||||
@click.prevent="fnRecordDelete('0')"
|
||||
>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
{{ t('views.neUser.sub.checkDel') }}
|
||||
</a-button>
|
||||
|
||||
<a-button
|
||||
type="primary"
|
||||
danger
|
||||
@@ -987,6 +1075,7 @@ onMounted(() => {
|
||||
</template>
|
||||
{{ t('views.neUser.auth.batchDelText') }}
|
||||
</a-button>
|
||||
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.loadDataConfirm')"
|
||||
:ok-text="t('common.ok')"
|
||||
@@ -1016,6 +1105,7 @@ onMounted(() => {
|
||||
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.exportConfirm')"
|
||||
placement="topRight"
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
@confirm="fnExportList('txt')"
|
||||
@@ -1030,12 +1120,32 @@ onMounted(() => {
|
||||
{{ t('views.neUser.sub.export') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.checkExportConfirm')"
|
||||
placement="topRight"
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
@confirm="fnRecordExport('txt')"
|
||||
:show-cancel="false"
|
||||
cancel-text="CSV"
|
||||
@cancel="fnRecordExport('csv')"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
>
|
||||
<a-button
|
||||
type="default"
|
||||
:disabled="tableState.selectedRowKeys.length <= 0"
|
||||
>
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('views.neUser.sub.checkExport') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -1088,7 +1198,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
@@ -1104,6 +1214,11 @@ onMounted(() => {
|
||||
:scroll="{ y: 'calc(100vh - 480px)' }"
|
||||
@change="fnTableChange"
|
||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
selectedRowKeys: tableState.selectedRowKeys,
|
||||
onChange: fnTableSelectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'imsi'">
|
||||
|
||||
@@ -12,7 +12,7 @@ import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { getGoldTitleByNE, goldData } from '@/api/perfManage/goldTarget';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t, currentLocale } = useI18n();
|
||||
|
||||
/**网元参数 */
|
||||
@@ -83,7 +83,7 @@ function fnTableSize({ key }: MenuInfo) {
|
||||
/**查询参数 */
|
||||
let queryParams: any = reactive({
|
||||
/**卡片切换Flag */
|
||||
cardFlag: 0, //0-显示统计图 1-显示统计表
|
||||
cardFlag: 0, //0-显示统计图 1-显示统计表
|
||||
/**告警设备类型 */
|
||||
neType: '',
|
||||
/**告警网元标识 */
|
||||
@@ -92,8 +92,24 @@ let queryParams: any = reactive({
|
||||
particle: '15',
|
||||
beginTime: '',
|
||||
endTime: '',
|
||||
/**排序字段 */
|
||||
sortField: 'timeGroup',
|
||||
/**排序方式 */
|
||||
sortOrder: 'asc',
|
||||
});
|
||||
|
||||
/**表格分页、排序、筛选变化时触发操作, 排序方式,取值为 ascend descend */
|
||||
function fnTableChange(pagination: any, filters: any, sorter: any, extra: any) {
|
||||
const { columnKey, order } = sorter;
|
||||
if (order) {
|
||||
queryParams.sortField = columnKey;
|
||||
queryParams.sortOrder = order.replace('end', '');
|
||||
} else {
|
||||
queryParams.sortOrder = 'asc';
|
||||
}
|
||||
fnMakeTable(1);
|
||||
}
|
||||
|
||||
/**图表显示数据 */
|
||||
const chartsOption = reactive({
|
||||
/**性能指标 */
|
||||
@@ -195,6 +211,9 @@ function fnDesign() {
|
||||
title: t('views.perfManage.goldTarget.time'),
|
||||
dataIndex: 'timeGroup',
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
key: 'timeGroup',
|
||||
sorter: true,
|
||||
});
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
@@ -204,6 +223,7 @@ function fnDesign() {
|
||||
const neType = queryParams.neType[0];
|
||||
let goldXDate: any = [];
|
||||
let goldYData: any = [];
|
||||
let hideAll: any = {};
|
||||
goldData(queryParams).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
if (res.data.length > 0) {
|
||||
@@ -214,6 +234,7 @@ function fnDesign() {
|
||||
.filter(key => !['timeGroup', 'neName', 'startIndex'].includes(key))
|
||||
.map(key => {
|
||||
const title: any = findTitleByKey(key);
|
||||
hideAll[title] = false;
|
||||
return {
|
||||
name: title,
|
||||
data: res.data.map((item: any) => parseInt(item[key])),
|
||||
@@ -246,29 +267,25 @@ function fnDesign() {
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
right: 10,
|
||||
itemWidth: 8,
|
||||
// orient: 'vertical',
|
||||
// left: 'left',
|
||||
type: 'scroll',
|
||||
orient: 'vertical', // vertical
|
||||
right: 20,
|
||||
//itemWidth: 20,
|
||||
itemGap: 25,
|
||||
textStyle: {
|
||||
color: '#646A73',
|
||||
},
|
||||
icon: 'circle',
|
||||
selected: hideAll,
|
||||
},
|
||||
grid: {
|
||||
left: '10%',
|
||||
right: '5%',
|
||||
right: '30%',
|
||||
bottom: '20%',
|
||||
},
|
||||
yAxis: [
|
||||
{ type: 'value', axisLabel: { fontSize: 10 } },
|
||||
{
|
||||
type: 'value',
|
||||
position: 'right',
|
||||
alignTicks: true,
|
||||
axisLabel: {
|
||||
fontSize: 10,
|
||||
},
|
||||
},
|
||||
],
|
||||
yAxis: [{ type: 'value', splitNumber: 4, axisLabel: { fontSize: 10 } }],
|
||||
};
|
||||
chartsOption.perfChart = option;
|
||||
|
||||
@@ -284,45 +301,50 @@ function fnDesign() {
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore()
|
||||
.fnNelist()
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
|
||||
if (res.data.length > 0) {
|
||||
// 过滤不可用的网元
|
||||
neCascaderOptions.value = useNeInfoStore().getNeCascaderOtions.filter(
|
||||
(item: any) => {
|
||||
return !['OMC'].includes(item.value);
|
||||
}
|
||||
);
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOptions.value.find(s => s.value === 'UPF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
queryParams.neType = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOptions.value[0].children[0];
|
||||
queryParams.neType = [info.neType, info.neId];
|
||||
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 !['OMC'].includes(item.value);
|
||||
}
|
||||
const initTime: Date = new Date();
|
||||
const startTime: Date = new Date(initTime);
|
||||
startTime.setHours(0, 0, 0, 0); // 设置为今天的0点
|
||||
const endTime: Date = new Date(initTime);
|
||||
endTime.setHours(23, 59, 59, 59); // 设置为今天的12点
|
||||
|
||||
queryRangePicker.value = [
|
||||
parseDateToStr(startTime),
|
||||
parseDateToStr(endTime),
|
||||
];
|
||||
fnGetList();
|
||||
);
|
||||
if (neCascaderOptions.value.length === 0) {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
// 默认选择AMF
|
||||
const item = neCascaderOptions.value.find(s => s.value === 'UPF');
|
||||
if (item && item.children) {
|
||||
const info = item.children[0];
|
||||
queryParams.neType = [info.neType, info.neId];
|
||||
} else {
|
||||
const info = neCascaderOptions.value[0].children[0];
|
||||
queryParams.neType = [info.neType, info.neId];
|
||||
}
|
||||
const initTime: Date = new Date();
|
||||
const startTime: Date = new Date(initTime);
|
||||
startTime.setHours(0, 0, 0, 0); // 设置为今天的0点
|
||||
const endTime: Date = new Date(initTime);
|
||||
endTime.setHours(23, 59, 59, 59); // 设置为今天的12点
|
||||
|
||||
queryRangePicker.value = [
|
||||
parseDateToStr(startTime),
|
||||
parseDateToStr(endTime),
|
||||
];
|
||||
fnGetList();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
message.warning({
|
||||
content: t('common.noData'),
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -373,6 +395,7 @@ onMounted(() => {
|
||||
v-model:value="queryParams.particle"
|
||||
:placeholder="t('common.selectPlease')"
|
||||
:options="[
|
||||
{ label: '5M', value: '5' },
|
||||
{ label: '15M', value: '15' },
|
||||
{ label: '30M', value: '30' },
|
||||
{ label: '60M', value: '60' },
|
||||
@@ -462,7 +485,10 @@ onMounted(() => {
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: true }"
|
||||
:scroll="{ x: tableColumnsDnd.length * 200, y: 450 }"
|
||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||
:show-expand-column="false"
|
||||
@change="fnTableChange"
|
||||
>
|
||||
</a-table>
|
||||
</a-card>
|
||||
@@ -477,9 +503,7 @@ onMounted(() => {
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-button type="default" size="small" @click.prevent="fnMakeTable(1)">
|
||||
<template #icon>
|
||||
<ClearOutlined />
|
||||
</template>
|
||||
<template #icon> <bars-outlined /> </template>
|
||||
{{ t('views.perfManage.goldTarget.allData') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
@@ -487,7 +511,7 @@ onMounted(() => {
|
||||
<div class="chart">
|
||||
<ChartLine
|
||||
:option="chartsOption.perfChart"
|
||||
:dataZoom="true"
|
||||
:dataZoom="false"
|
||||
height="400px"
|
||||
></ChartLine>
|
||||
</div>
|
||||
|
||||
334
src/views/perfManage/goldTarget/index1.vue
Normal file
334
src/views/perfManage/goldTarget/index1.vue
Normal file
@@ -0,0 +1,334 @@
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from 'vue-router';
|
||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { Modal } from 'ant-design-vue/lib';
|
||||
import { SizeType } from 'ant-design-vue/lib/config-provider';
|
||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { listgoldData } from '@/api/perfManage/goldTarget';
|
||||
import useNeInfoStore from '@/store/modules/neinfo';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
const { getDict } = useDictStore();
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
|
||||
/**路由标题 */
|
||||
let title = ref<string>((route.meta.title as string) ?? '标题');
|
||||
|
||||
/**记录开始结束时间 */
|
||||
let queryRangePicker = ref<[string, string]>(['', '']);
|
||||
|
||||
/**查询参数 */
|
||||
let queryParams = reactive({
|
||||
/**网元类型 */
|
||||
neType: '',
|
||||
/**记录时间 */
|
||||
beginTime: '',
|
||||
endTime: '',
|
||||
/**排序字段 */
|
||||
sortField: 'value',
|
||||
/**排序方式 */
|
||||
sortOrder: 'asc',
|
||||
/**当前页数 */
|
||||
pageNum: 1,
|
||||
/**每页条数 */
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
/**查询参数重置 */
|
||||
function fnQueryReset() {
|
||||
queryParams = Object.assign(queryParams, {
|
||||
neType: '',
|
||||
beginTime: '',
|
||||
endTime: '',
|
||||
sortField: 'value',
|
||||
sortOrder: 'asc',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
queryRangePicker.value = ['', ''];
|
||||
tablePagination.current = 1;
|
||||
tablePagination.pageSize = 20;
|
||||
fnGetList();
|
||||
}
|
||||
|
||||
/**表格状态类型 */
|
||||
type TabeStateType = {
|
||||
/**加载等待 */
|
||||
loading: boolean;
|
||||
/**紧凑型 */
|
||||
size: SizeType;
|
||||
/**搜索栏 */
|
||||
seached: boolean;
|
||||
/**记录数据 */
|
||||
data: object[];
|
||||
};
|
||||
|
||||
/**表格状态 */
|
||||
let tableState: TabeStateType = reactive({
|
||||
loading: false,
|
||||
size: 'middle',
|
||||
seached: true,
|
||||
data: [],
|
||||
});
|
||||
|
||||
/**表格字段列 */
|
||||
let tableColumns: ColumnsType = [
|
||||
{
|
||||
title: t('views.perfManage.goldTarget.type'),
|
||||
dataIndex: 'neType',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('views.perfManage.goldTarget.enTitle'),
|
||||
dataIndex: 'enTitle',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: t('views.perfManage.goldTarget.value'),
|
||||
dataIndex: 'value',
|
||||
key: 'value',
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: t('views.perfManage.goldTarget.startTime'),
|
||||
dataIndex: 'startTime',
|
||||
key: 'start_time',
|
||||
align: 'center',
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(opt.value);
|
||||
},
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: t('views.perfManage.goldTarget.endTime'),
|
||||
dataIndex: 'endTime',
|
||||
align: 'center',
|
||||
customRender(opt) {
|
||||
if (!opt.value) return '';
|
||||
return parseDateToStr(opt.value);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**表格分页器参数 */
|
||||
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;
|
||||
}
|
||||
|
||||
/**查询黄金指标列表, pageNum初始页数 */
|
||||
function fnGetList(pageNum?: number) {
|
||||
if (tableState.loading) return;
|
||||
tableState.loading = true;
|
||||
if (pageNum) {
|
||||
queryParams.pageNum = pageNum;
|
||||
}
|
||||
if (!queryRangePicker.value) {
|
||||
queryRangePicker.value = ['', ''];
|
||||
}
|
||||
queryParams.beginTime = queryRangePicker.value[0];
|
||||
queryParams.endTime = queryRangePicker.value[1];
|
||||
listgoldData(toRaw(queryParams)).then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.rows)) {
|
||||
tablePagination.total = res.total;
|
||||
tableState.data = res.rows;
|
||||
}
|
||||
tableState.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**表格分页、排序、筛选变化时触发操作, 排序方式,取值为 ascend descend */
|
||||
function fnTableChange(pagination: any, filters: any, sorter: any, extra: any) {
|
||||
console.log(sorter);
|
||||
const { columnKey, order } = sorter;
|
||||
if (order) {
|
||||
queryParams.sortField = columnKey;
|
||||
queryParams.sortOrder = order.replace('end', '');
|
||||
} else {
|
||||
queryParams.sortOrder = 'asc';
|
||||
}
|
||||
fnGetList(1);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore().fnNelist();
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<a-card
|
||||
v-show="tableState.seached"
|
||||
:bordered="false"
|
||||
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||
>
|
||||
<!-- 表格搜索栏 -->
|
||||
<a-form :model="queryParams" name="queryParams" layout="horizontal">
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.perfManage.goldTarget.type')"
|
||||
name="neType"
|
||||
>
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="useNeInfoStore().getNeSelectOtions"
|
||||
allow-clear
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.perfManage.goldTarget.startTime')"
|
||||
name="queryRangePicker"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model:value="queryRangePicker"
|
||||
allow-clear
|
||||
bordered
|
||||
show-time
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
></a-range-picker>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :lg="6" :md="12" :xs="24">
|
||||
<a-form-item>
|
||||
<a-space :size="8">
|
||||
<a-button type="primary" @click.prevent="fnGetList(1)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ t('common.search') }}
|
||||
</a-button>
|
||||
<a-button type="default" @click.prevent="fnQueryReset">
|
||||
<template #icon><ClearOutlined /></template>
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title> </template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
v-model:checked="tableState.seached"
|
||||
:checked-children="t('common.switch.show')"
|
||||
:un-checked-children="t('common.switch.hide')"
|
||||
size="small"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.reloadText') }}</template>
|
||||
<a-button type="text" @click.prevent="fnGetList()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.sizeText') }}</template>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="text">
|
||||
<template #icon><ColumnHeightOutlined /></template>
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu
|
||||
:selected-keys="[tableState.size as string]"
|
||||
@click="fnTableSize"
|
||||
>
|
||||
<a-menu-item key="default">
|
||||
{{ t('common.size.default') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="middle">
|
||||
{{ t('common.size.middle') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="small">
|
||||
{{ t('common.size.small') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
<a-table
|
||||
class="table"
|
||||
row-key="id"
|
||||
:columns="tableColumns"
|
||||
:loading="tableState.loading"
|
||||
:data-source="tableState.data"
|
||||
:size="tableState.size"
|
||||
@change="fnTableChange"
|
||||
:pagination="tablePagination"
|
||||
:scroll="{ x: true }"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'alarmTitle'">
|
||||
<a-tooltip>
|
||||
<template #title>{{ record.operResult }}</template>
|
||||
<div class="alarmTitleText">{{ record.alarmTitle }}</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.table :deep(.ant-pagination) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
.alarmTitleText {
|
||||
max-width: 300px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
taskStop,
|
||||
taskRun,
|
||||
} from '@/api/perfManage/taskManage';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t, currentLocale } = useI18n();
|
||||
|
||||
const generateOptions = (start: any, end: any) => {
|
||||
@@ -378,7 +379,7 @@ function fnSelectPer(s: any, option: any) {
|
||||
/**性能测量数据集选择初始 */
|
||||
function fnSelectPerformanceInit(neType: string) {
|
||||
//console.logg(currentLocale.value); //当前语言
|
||||
const performance = useNeInfoStore().perMeasurementList.filter(
|
||||
const performance = neInfoStore.perMeasurementList.filter(
|
||||
i => i.neType === neType
|
||||
);
|
||||
//进行分组选择
|
||||
@@ -624,7 +625,7 @@ function fnRecordRun(row: Record<string, any>) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活任务
|
||||
* 挂起任务
|
||||
* @param row 网元编号ID
|
||||
*/
|
||||
function fnRecordStop(row: Record<string, any>) {
|
||||
@@ -692,9 +693,9 @@ onMounted(() => {
|
||||
|
||||
Promise.allSettled([
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore().fnNelist(),
|
||||
neInfoStore.fnNelist(),
|
||||
// 获取性能测量集列表
|
||||
useNeInfoStore().fnNeTaskPerformance(),
|
||||
neInfoStore.fnNeTaskPerformance(),
|
||||
]).finally(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
@@ -719,7 +720,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="useNeInfoStore().getNeSelectOtions"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
:placeholder="t('views.traceManage.task.neTypePlease')"
|
||||
/>
|
||||
@@ -887,7 +888,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-cascader
|
||||
:value="modalState.neType"
|
||||
:options="useNeInfoStore().getNeCascaderOtions"
|
||||
:options="neInfoStore.getNeCascaderOptions"
|
||||
disabled
|
||||
/>
|
||||
</a-form-item>
|
||||
@@ -1002,7 +1003,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="modalState.neType"
|
||||
:options="useNeInfoStore().getNeCascaderOtions"
|
||||
:options="neInfoStore.getNeCascaderOptions"
|
||||
@change="fnNeChange"
|
||||
:allow-clear="false"
|
||||
:placeholder="t('views.traceManage.task.neTypePlease')"
|
||||
|
||||
@@ -487,7 +487,7 @@ onMounted(() => {
|
||||
<a-input
|
||||
v-model:value="queryParams.configName"
|
||||
allow-clear
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -499,7 +499,7 @@ onMounted(() => {
|
||||
<a-input
|
||||
v-model:value="queryParams.configKey"
|
||||
allow-clear
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -552,7 +552,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
@@ -588,12 +588,12 @@ onMounted(() => {
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -642,7 +642,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
@@ -839,7 +839,7 @@ onMounted(() => {
|
||||
:auto-size="{ minRows: 4, maxRows: 6 }"
|
||||
:maxlength="450"
|
||||
:show-count="true"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { getLocalColor, changePrimaryColor } from '@/hooks/useTheme';
|
||||
import { reactive, ref, onMounted, toRaw } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import { Form, message, Modal } from 'ant-design-vue/lib';
|
||||
@@ -32,6 +33,18 @@ const dictId = route.params && (route.params.dictId as string);
|
||||
|
||||
const zh = currentLocale.value === 'zh_CN';
|
||||
|
||||
let color = ref<string>(getLocalColor());
|
||||
/**改变主题色 */
|
||||
function fnColorChange(e: Event) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (target.nodeName === 'INPUT') {
|
||||
changePrimaryColor(target.value ?? '#1890ff');
|
||||
} else {
|
||||
changePrimaryColor();
|
||||
}
|
||||
color.value = getLocalColor();
|
||||
}
|
||||
|
||||
/**标签类型数据固定项 */
|
||||
const tagTypeOptions = ref([
|
||||
{ value: '', label: zh ? '普通文本' : 'Plain text' },
|
||||
@@ -289,7 +302,8 @@ function fnModalVisibleByVive(row: Record<string, string>) {
|
||||
* 对话框弹出显示为 新增或者修改
|
||||
* @param dictCode 数据编号id, 不传为新增
|
||||
*/
|
||||
function fnModalVisibleByEdit(dictCode?: string | number) {
|
||||
function fnModalVisibleByEdit(dictCode?: string | number, record?: any) {
|
||||
console.log(record);
|
||||
if (!dictCode) {
|
||||
modalStateFrom.resetFields();
|
||||
modalState.from.dictType = queryParams.dictType;
|
||||
@@ -522,7 +536,7 @@ onMounted(() => {
|
||||
<a-input
|
||||
v-model:value="queryParams.dictLabel"
|
||||
allow-clear
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -561,7 +575,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button type="default" @click.prevent="fnClose()">
|
||||
<template #icon><CloseOutlined /></template>
|
||||
{{ t('common.close') }}
|
||||
@@ -592,12 +606,12 @@ onMounted(() => {
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -646,7 +660,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
@@ -686,7 +700,7 @@ onMounted(() => {
|
||||
<template #title>{{ t('common.editText') }}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnModalVisibleByEdit(record.dictCode)"
|
||||
@click.prevent="fnModalVisibleByEdit(record.dictCode, record)"
|
||||
v-perms:has="['system:dict:edit']"
|
||||
>
|
||||
<template #icon><FormOutlined /></template>
|
||||
@@ -903,8 +917,27 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<!-- 首页状态取色器 -->
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-col
|
||||
:lg="12"
|
||||
:md="12"
|
||||
:xs="24"
|
||||
v-if="modalState.from.dictType === 'index_status'"
|
||||
>
|
||||
<a-form-item
|
||||
:label="t('views.system.dict.colorSelect')"
|
||||
name="tagClass"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.tagClass"
|
||||
type="color"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24" v-else>
|
||||
<a-form-item
|
||||
:label="t('views.system.dictData.tagType')"
|
||||
name="tagType"
|
||||
@@ -926,21 +959,26 @@ onMounted(() => {
|
||||
v-model:value="modalState.from.dictSort"
|
||||
:min="0"
|
||||
:max="65535"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item
|
||||
:label="t('views.system.dictData.tagClass')"
|
||||
name="tagClass"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.tagClass"
|
||||
allow-clear
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
<!-- 非首页状态取色器 -->
|
||||
<a-row :gutter="16" v-if="modalState.from.dictType !== 'index_status'">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
:label="t('views.system.dictData.tagClass')"
|
||||
name="tagClass"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="modalState.from.tagClass"
|
||||
allow-clear
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item :label="t('views.system.dictData.remark')" name="remark">
|
||||
<a-textarea
|
||||
v-model:value="modalState.from.remark"
|
||||
|
||||
@@ -552,7 +552,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
@@ -596,12 +596,12 @@ onMounted(() => {
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -650,7 +650,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
|
||||
@@ -491,7 +491,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
@@ -518,12 +518,12 @@ onMounted(() => {
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -572,7 +572,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
|
||||
@@ -394,7 +394,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button type="default" @click.prevent="fnClose()">
|
||||
<template #icon><CloseOutlined /></template>
|
||||
{{ t('common.cancel') }}
|
||||
@@ -417,12 +417,12 @@ onMounted(() => {
|
||||
<template #icon><UsergroupDeleteOutlined /></template>
|
||||
{{ t('views.system.role.batchCancel') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -471,7 +471,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
@@ -498,7 +498,9 @@ onMounted(() => {
|
||||
<template v-if="column.key === 'userId'">
|
||||
<a-space :size="8" align="center">
|
||||
<a-tooltip>
|
||||
<template #title>{{t('views.system.role.cancelGive')}}</template>
|
||||
<template #title>{{
|
||||
t('views.system.role.cancelGive')
|
||||
}}</template>
|
||||
<a-button
|
||||
type="link"
|
||||
@click.prevent="fnRecordDelete(record.userId)"
|
||||
|
||||
@@ -815,7 +815,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
@@ -842,7 +842,7 @@ onMounted(() => {
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
@@ -1236,7 +1236,10 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.system.role.createTime')" name="createTime">
|
||||
<a-form-item
|
||||
:label="t('views.system.role.createTime')"
|
||||
name="createTime"
|
||||
>
|
||||
<span v-if="+modalState.from.createTime > 0">
|
||||
{{ parseDateToStr(+modalState.from.createTime) }}
|
||||
</span>
|
||||
@@ -1245,12 +1248,18 @@ onMounted(() => {
|
||||
</a-row>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.system.role.roleSort')" name="roleSort">
|
||||
<a-form-item
|
||||
:label="t('views.system.role.roleSort')"
|
||||
name="roleSort"
|
||||
>
|
||||
{{ modalState.from.roleSort }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.system.role.roleStatus')" name="status">
|
||||
<a-form-item
|
||||
:label="t('views.system.role.roleStatus')"
|
||||
name="status"
|
||||
>
|
||||
<DictTag
|
||||
:options="dict.sysNormalDisable"
|
||||
:value="modalState.from.status"
|
||||
@@ -1260,17 +1269,20 @@ onMounted(() => {
|
||||
</a-row>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.system.role.roleName')" name="roleName">
|
||||
<a-form-item
|
||||
:label="t('views.system.role.roleName')"
|
||||
name="roleName"
|
||||
>
|
||||
{{ modalState.from.roleName }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item :label="t('views.system.role.roleKey')" name="roleKey">
|
||||
<a-form-item :label="t('views.system.role.roleKey')" name="roleKey">
|
||||
{{ modalState.from.roleKey }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item :label="t('views.system.role.roleMark')" name="remark">
|
||||
<a-form-item :label="t('views.system.role.roleMark')" name="remark">
|
||||
{{ modalState.from.remark }}
|
||||
</a-form-item>
|
||||
|
||||
@@ -1293,21 +1305,21 @@ onMounted(() => {
|
||||
:checked="modalState.deptTree.expandedKeys.length > 0"
|
||||
@change="(e:any) => fnModalExpandedKeys(e.target.checked, 'dept')"
|
||||
>
|
||||
{{t('views.system.role.openSwitch')}}
|
||||
{{ t('views.system.role.openSwitch') }}
|
||||
</a-checkbox>
|
||||
<a-checkbox
|
||||
id="dept_2"
|
||||
:checked="modalState.from.deptIds.length > 0"
|
||||
@change="(e:any) => fnModalCheckedKeys(e.target.checked, 'dept')"
|
||||
>
|
||||
{{t('views.system.role.selAllSwitch')}}
|
||||
{{ t('views.system.role.selAllSwitch') }}
|
||||
</a-checkbox>
|
||||
<a-checkbox
|
||||
id="dept_1"
|
||||
:checked="modalState.from.deptCheckStrictly === '1'"
|
||||
@change="(e:any) => fnModalCheckStrictly(e.target.checked, 'dept')"
|
||||
>
|
||||
{{t('views.system.role.relationSwitch')}}
|
||||
{{ t('views.system.role.relationSwitch') }}
|
||||
</a-checkbox>
|
||||
</a-space>
|
||||
<a-tree
|
||||
|
||||
@@ -72,7 +72,7 @@ onMounted(() => {
|
||||
v-model:value="state.copyright"
|
||||
allow-clear
|
||||
:maxlength="40"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@ import { onMounted, reactive } from 'vue';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { transferStaticFile } from '@/api/index';
|
||||
import { uploadFileChunk } from '@/api/tool/file';
|
||||
import { transferStaticFile, uploadFileChunk } from '@/api/tool/file';
|
||||
import { FileType } from 'ant-design-vue/lib/upload/interface';
|
||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -124,6 +123,7 @@ onMounted(() => {
|
||||
v-model:value="state.language"
|
||||
style="width: 100px"
|
||||
size="small"
|
||||
v-perms:has="['system:setting:i18n']"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="opt in optionsLocale"
|
||||
@@ -169,6 +169,7 @@ onMounted(() => {
|
||||
v-model:value="state.language"
|
||||
style="width: 100px"
|
||||
size="small"
|
||||
v-perms:has="['system:setting:i18n']"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="opt in optionsLocale"
|
||||
|
||||
@@ -7,10 +7,9 @@ import { onMounted, reactive, watch, computed } from 'vue';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { uploadFile } from '@/api/tool/file';
|
||||
import { transferStaticFile, uploadFile } from '@/api/tool/file';
|
||||
import { changeValue } from '@/api/system/config';
|
||||
import { sessionGet } from '@/utils/cache-session-utils';
|
||||
import { transferStaticFile } from '@/api';
|
||||
import { parseUrlPath } from '@/plugins/file-static-url';
|
||||
const appStore = useAppStore();
|
||||
const { t, currentLocale, optionsLocale } = useI18n();
|
||||
@@ -219,7 +218,7 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-form-item v-perms:has="['system:setting:i18n']">
|
||||
<a-select v-model:value="state.language" style="width: 100px">
|
||||
<a-select-option
|
||||
v-for="opt in optionsLocale"
|
||||
|
||||
@@ -75,7 +75,7 @@ onMounted(() => {
|
||||
v-model:value="state.url"
|
||||
allow-clear
|
||||
:maxlength="255"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ onMounted(() => {
|
||||
v-model:value="state.title"
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
|
||||
|
||||
@@ -38,10 +38,12 @@ const { t } = useI18n();
|
||||
{{ t('views.system.setting.sysOfficialUrl') }}
|
||||
</a-divider>
|
||||
<ChangeOfficialUrl></ChangeOfficialUrl>
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.system.setting.i18n') }}
|
||||
</a-divider>
|
||||
<ChangeI18n></ChangeI18n>
|
||||
<div v-perms:has="['system:setting:i18n']">
|
||||
<a-divider orientation="left">
|
||||
{{ t('views.system.setting.i18n') }}
|
||||
</a-divider>
|
||||
<ChangeI18n></ChangeI18n>
|
||||
</div>
|
||||
</a-card>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
@@ -840,7 +840,7 @@ onMounted(() => {
|
||||
v-model:value="queryParams.userName"
|
||||
allow-clear
|
||||
:maxlength="30"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -853,7 +853,7 @@ onMounted(() => {
|
||||
v-model:value="queryParams.phonenumber"
|
||||
allow-clear
|
||||
:maxlength="11"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
:placeholder="t('common.inputPlease')"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -889,7 +889,7 @@ onMounted(() => {
|
||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.prevent="fnModalVisibleByEdit()"
|
||||
@@ -924,12 +924,12 @@ onMounted(() => {
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
<template #extra>
|
||||
<a-space :size="8" align="center">
|
||||
<div class="button-container">
|
||||
<a-tooltip>
|
||||
<template #title>{{ t('common.searchBarText') }}</template>
|
||||
<a-switch
|
||||
@@ -978,7 +978,7 @@ onMounted(() => {
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表格列表 -->
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
tcpdumpPcapDownload,
|
||||
} from '@/api/traceManage/pcap';
|
||||
import { ref } from 'vue';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
@@ -338,7 +339,7 @@ onUnmounted(() => {
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="modalState.neType"
|
||||
:options="useNeInfoStore().getNeCascaderOtions"
|
||||
:options="neInfoStore.getNeCascaderOptions"
|
||||
@change="fnNeChange"
|
||||
:allow-clear="false"
|
||||
:placeholder="t('views.traceManage.pcap.neTypePlease')"
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from '@/api/traceManage/task';
|
||||
import useDictStore from '@/store/modules/dict';
|
||||
import { regExpIPv4, regExpPort } from '@/utils/regular-utils';
|
||||
const neInfoStore = useNeInfoStore();
|
||||
const { getDict } = useDictStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -382,7 +383,7 @@ function fnSelectInterface(s: any, _: any) {
|
||||
|
||||
/**信令接口选择初始 */
|
||||
function fnSelectInterfaceInit(neType: string) {
|
||||
const interfaces = useNeInfoStore().traceInterfaceList;
|
||||
const interfaces = neInfoStore.traceInterfaceList;
|
||||
modalState.neTypeInterface = interfaces
|
||||
.filter(i => i.neType === neType)
|
||||
.map(i => {
|
||||
@@ -535,9 +536,9 @@ onMounted(() => {
|
||||
});
|
||||
Promise.allSettled([
|
||||
// 获取网元网元列表
|
||||
useNeInfoStore().fnNelist(),
|
||||
neInfoStore.fnNelist(),
|
||||
// 获取跟踪接口列表
|
||||
useNeInfoStore().fnNeTraceInterface(),
|
||||
neInfoStore.fnNeTraceInterface(),
|
||||
]).finally(() => {
|
||||
// 获取列表数据
|
||||
fnGetList();
|
||||
@@ -562,7 +563,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-auto-complete
|
||||
v-model:value="queryParams.neType"
|
||||
:options="useNeInfoStore().getNeSelectOtions"
|
||||
:options="neInfoStore.getNeSelectOtions"
|
||||
allow-clear
|
||||
:placeholder="t('views.traceManage.task.neTypePlease')"
|
||||
/>
|
||||
@@ -748,7 +749,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-cascader
|
||||
:value="modalState.neType"
|
||||
:options="useNeInfoStore().getNeCascaderOtions"
|
||||
:options="neInfoStore.getNeCascaderOptions"
|
||||
disabled
|
||||
/>
|
||||
</a-form-item>
|
||||
@@ -866,7 +867,7 @@ onMounted(() => {
|
||||
>
|
||||
<a-cascader
|
||||
v-model:value="modalState.neType"
|
||||
:options="useNeInfoStore().getNeCascaderOtions"
|
||||
:options="neInfoStore.getNeCascaderOptions"
|
||||
@change="fnNeChange"
|
||||
:allow-clear="false"
|
||||
:placeholder="t('views.traceManage.task.neTypePlease')"
|
||||
|
||||
@@ -21,7 +21,7 @@ export default defineConfig(({ mode }) => {
|
||||
// https://cn.vitejs.dev/config/#server-proxy
|
||||
[env.VITE_API_BASE_URL]: {
|
||||
// target: 'http://192.168.2.166:3030',
|
||||
target: 'http://192.168.2.114:3040',
|
||||
target: 'http://192.168.5.58:3040',
|
||||
changeOrigin: true,
|
||||
rewrite: p => p.replace(env.VITE_API_BASE_URL, ''),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user