Compare commits

...

125 Commits

Author SHA1 Message Date
joylink_fanyuhong
dd6fd1ed80 Merge remote-tracking branch 'origin/develop' into local-test
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m53s
2024-11-20 17:22:47 +08:00
joylink_fanyuhong
dd7cb75ceb Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-11-20 16:03:28 +08:00
joylink_fanyuhong
6252bf426c 故障时间展示调整 2024-11-20 16:03:25 +08:00
joylink_zhaoerwei
342aff6ebd 去掉手机列 2024-11-20 13:37:49 +08:00
joylink_fanyuhong
ca8a2fb279 报错调整 2024-11-20 10:53:36 +08:00
joylink_fanyuhong
718835302e 提示按钮调整 2024-11-20 10:42:51 +08:00
joylink_zhaoerwei
59ffd45dfb btn提示 2024-11-20 10:32:18 +08:00
joylink_fanyuhong
2070142e56 故障统计调整 2024-11-20 10:27:36 +08:00
joylink_fanyuhong
48c9adc9dc Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-11-20 10:17:35 +08:00
joylink_fanyuhong
d02295b206 跳转ats判断逻辑调整 2024-11-20 10:17:32 +08:00
joylink_zhaoerwei
5c9f6c4a43 双button bug
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m54s
2024-11-20 10:00:20 +08:00
joylink_zhaoerwei
a2b80e131f Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m48s
commit d142917797
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Wed Nov 20 09:53:19 2024 +0800

    微调

commit c514486354
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Wed Nov 20 09:49:50 2024 +0800

    语音报警btn加提示
2024-11-20 09:54:47 +08:00
joylink_zhaoerwei
d142917797 微调 2024-11-20 09:53:19 +08:00
joylink_zhaoerwei
c514486354 语音报警btn加提示 2024-11-20 09:49:50 +08:00
joylink_fanyuhong
eafdc7b870 Merge remote-tracking branch 'origin/develop' into local-test
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m52s
2024-11-20 09:21:14 +08:00
joylink_fanyuhong
9a6d4efedb merge
Some checks failed
local-test分支构建发布 / Docker-Build (push) Failing after 56s
2024-11-20 09:19:18 +08:00
joylink_fanyuhong
e6f6ac2b7e 账号格式校验调整 2024-11-20 09:15:10 +08:00
joylink_fanyuhong
da04217a08 登录页注释注册按钮 2024-11-20 09:10:25 +08:00
joylink_fanyuhong
de64a23eb8 故障提示超宽调整 2024-11-20 09:08:19 +08:00
joylink_fanyuhong
2e19a66a6b Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-11-19 14:05:54 +08:00
joylink_fanyuhong
fac62de1ae 等待时间调整 2024-11-19 14:05:48 +08:00
joylink_zhaoerwei
bfebe3e28d 列车报点 2024-11-19 10:50:42 +08:00
joylink_fanyuhong
e2faeb2d05 根据状态判断是否显示故障时间 2024-11-18 17:29:46 +08:00
joylink_fanyuhong
109a19527d protoc 2024-11-18 17:12:23 +08:00
joylink_fanyuhong
09b6dcbb19 Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-11-18 16:59:55 +08:00
joylink_fanyuhong
539e8b7d01 代码调整 2024-11-18 16:59:39 +08:00
joylink_zhaoerwei
1cd4cb815c 告警弹框 2024-11-18 15:50:46 +08:00
joylink_zhaoerwei
a37e33d7d8 故障类型查询调整 2024-11-18 15:05:46 +08:00
joylink_zhaoerwei
f7634d7672 同步proto 2024-11-18 09:47:55 +08:00
joylink_zhaoerwei
550bd752f8 ncc应急处置 2024-11-15 16:47:08 +08:00
joylink_zhaoerwei
67bfc01f6e toolTip调整 2024-11-15 13:32:13 +08:00
joylink_zhaoerwei
35f41df852 微调 2024-11-15 11:29:34 +08:00
joylink_zhaoerwei
6888e20634 微调 2024-11-15 11:09:15 +08:00
joylink_fanyuhong
4a3c2fafbf 代码提交 2024-11-15 10:11:12 +08:00
joylink_zhaoerwei
2aad7d4139 流程表调整 2024-11-15 09:18:14 +08:00
joylink_fanyuhong
02e49ec6fa 报警调整 2024-11-15 09:08:22 +08:00
joylink_fanyuhong
2b3673485c Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-11-15 09:03:41 +08:00
joylink_fanyuhong
0c1471f651 报警记录调整 2024-11-15 09:03:37 +08:00
joylink_zhaoerwei
f699666f96 Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m53s
commit e932e7d0ae
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Thu Nov 14 18:14:13 2024 +0800

    增加是否播报语音

commit 05896cb241
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Thu Nov 14 17:51:50 2024 +0800

    添加应急处置流程表

commit debaf97510
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Thu Nov 14 15:59:51 2024 +0800

    菜单调整

commit 99b7cba025
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Thu Nov 14 14:50:39 2024 +0800

    卡斯柯=》同方

commit 41e59960ee
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Thu Nov 14 14:46:13 2024 +0800

    公里表显示调整

commit 0da7654efa
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Thu Nov 14 11:14:19 2024 +0800

    增加5个故障
2024-11-14 18:15:56 +08:00
joylink_zhaoerwei
e932e7d0ae 增加是否播报语音 2024-11-14 18:14:13 +08:00
joylink_zhaoerwei
05896cb241 添加应急处置流程表 2024-11-14 17:51:50 +08:00
joylink_fanyuhong
debaf97510 菜单调整 2024-11-14 15:59:51 +08:00
joylink_fanyuhong
99b7cba025 卡斯柯=》同方 2024-11-14 14:50:39 +08:00
joylink_fanyuhong
41e59960ee 公里表显示调整 2024-11-14 14:46:13 +08:00
joylink_zhaoerwei
0da7654efa 增加5个故障 2024-11-14 11:14:19 +08:00
joylink_fanyuhong
5269e91153 Merge remote-tracking branch 'origin/develop' into local-test
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m49s
# Conflicts:
#	src/components/dialog/FaultQueryDialog.vue
2024-11-13 10:09:51 +08:00
joylink_zhaoerwei
de94896fd7 切换路由自动关闭弹框 2024-11-13 10:05:24 +08:00
joylink_zhaoerwei
4d65590ad1 Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m49s
commit 1333a0ec6f
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Wed Nov 13 09:33:09 2024 +0800

    查询无数据调整
2024-11-13 09:34:33 +08:00
joylink_fanyuhong
84fac01c7a Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-11-13 09:34:00 +08:00
joylink_fanyuhong
b26d213a0e 链接提示调整 2024-11-13 09:33:57 +08:00
joylink_zhaoerwei
1333a0ec6f 查询无数据调整 2024-11-13 09:33:09 +08:00
joylink_fanyuhong
1f8b5552c7 Merge remote-tracking branch 'origin/develop' into local-test
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m50s
# Conflicts:
#	src/drawApp/lineNetApp.ts
2024-11-12 18:02:55 +08:00
joylink_zhaoerwei
52fbdba1af 故障查询调整 2024-11-12 17:28:58 +08:00
joylink_zhaoerwei
9ac2c2dc59 故障查询调整 2024-11-12 16:44:22 +08:00
joylink_fanyuhong
cfcf0e06d1 添加链接提示 2024-11-12 15:18:07 +08:00
joylink_zhaoerwei
158aed62e6 Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m53s
commit 33292ca9b8
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Tue Nov 12 09:17:32 2024 +0800

    订阅处理

commit cdcad825f7
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Tue Nov 12 09:13:54 2024 +0800

    取消订阅调整

commit 44f7389132
Merge: 425d8e9 a2ae992
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Mon Nov 11 18:18:43 2024 +0800

    Merge remote-tracking branch 'origin/develop' into develop

commit 425d8e986b
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Mon Nov 11 18:16:10 2024 +0800

    处理订阅

commit a2ae99209f
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Nov 11 17:48:52 2024 +0800

    订阅调整
2024-11-12 09:49:53 +08:00
joylink_fanyuhong
33292ca9b8 订阅处理 2024-11-12 09:17:32 +08:00
joylink_fanyuhong
cdcad825f7 取消订阅调整 2024-11-12 09:13:54 +08:00
joylink_fanyuhong
44f7389132 Merge remote-tracking branch 'origin/develop' into develop 2024-11-11 18:18:43 +08:00
joylink_fanyuhong
425d8e986b 处理订阅 2024-11-11 18:18:29 +08:00
joylink_zhaoerwei
40e11e0d67 Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m51s
commit a2ae99209f
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Nov 11 17:48:52 2024 +0800

    订阅调整
2024-11-11 17:49:53 +08:00
joylink_zhaoerwei
a2ae99209f 订阅调整 2024-11-11 17:48:52 +08:00
joylink_fanyuhong
bdaa3507e9 merge
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m57s
2024-11-11 09:17:57 +08:00
joylink_zhaoerwei
2f815a0707 微调 2024-11-08 18:02:40 +08:00
joylink_zhaoerwei
f10e55ce0d 故障查询调整 2024-11-08 17:59:50 +08:00
joylink_zhaoerwei
7971887d2c 故障查询相关调整 2024-11-08 17:47:19 +08:00
joylink_zhaoerwei
4adeedb4d5 音频根据线路播放 2024-11-08 15:57:53 +08:00
joylink_zhaoerwei
a57d89a7f3 故障指导与退出服务 2024-11-08 15:06:07 +08:00
joylink_fanyuhong
50b80fef68 Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-11-08 13:55:25 +08:00
joylink_fanyuhong
b00010901a 保留app 2024-11-08 13:55:21 +08:00
joylink_zhaoerwei
7cd0df6b1b 故障查询过滤 2024-11-08 10:45:03 +08:00
joylink_zhaoerwei
0ecd9aac7c 增加故障查询 2024-11-08 10:19:57 +08:00
joylink_zhaoerwei
fbb08bb9e3 代码备用 2024-11-07 17:28:33 +08:00
joylink_zhaoerwei
f8e36732d8 增加道岔挤岔 2024-11-05 10:45:15 +08:00
joylink_zhaoerwei
a04ca22f4f Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m55s
commit ae81b3f4f8
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Nov 4 10:49:37 2024 +0800

    新建决策信息调整

commit 586e920216
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Fri Nov 1 11:23:40 2024 +0800

    应急触发

commit 25b89e8d34
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Fri Nov 1 09:46:21 2024 +0800

    增加设备类型

commit 3fc1f4deb7
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Fri Nov 1 09:25:39 2024 +0800

    故障测试加应急触发

commit d75c48a011
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Thu Oct 31 17:27:00 2024 +0800

    应急触发

commit 26f8581f55
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Thu Oct 31 16:20:21 2024 +0800

    增加应急触发

commit f0495153e6
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Wed Oct 30 13:45:15 2024 +0800

    计轴配置
2024-11-05 09:07:59 +08:00
joylink_zhaoerwei
ae81b3f4f8 新建决策信息调整 2024-11-04 10:49:37 +08:00
joylink_zhaoerwei
586e920216 应急触发 2024-11-01 11:23:40 +08:00
joylink_zhaoerwei
25b89e8d34 增加设备类型 2024-11-01 09:46:21 +08:00
joylink_zhaoerwei
3fc1f4deb7 故障测试加应急触发 2024-11-01 09:25:39 +08:00
joylink_zhaoerwei
d75c48a011 应急触发 2024-10-31 17:27:00 +08:00
joylink_zhaoerwei
5181c897e7 Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 2m2s
commit 26f8581f55
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Thu Oct 31 16:20:21 2024 +0800

    增加应急触发

commit f0495153e6
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Wed Oct 30 13:45:15 2024 +0800

    计轴配置
2024-10-31 16:21:49 +08:00
joylink_zhaoerwei
26f8581f55 增加应急触发 2024-10-31 16:20:21 +08:00
joylink_zhaoerwei
425da8f1af Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m55s
commit f0495153e6
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Wed Oct 30 13:45:15 2024 +0800

    计轴配置
2024-10-30 13:48:30 +08:00
joylink_zhaoerwei
f0495153e6 计轴配置 2024-10-30 13:45:15 +08:00
joylink_fanyuhong
328e70e188 Merge remote-tracking branch 'origin/develop' into local-test
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 2m2s
2024-10-30 13:27:41 +08:00
joylink_zhaoerwei
fb6c01dbfd 生成计轴配置 2024-10-30 11:45:19 +08:00
joylink_fanyuhong
9c7af7e256 页面查询按钮添加函数 2024-10-25 16:31:05 +08:00
joylink_fanyuhong
670e9c14db 添加查询按钮 2024-10-25 14:48:46 +08:00
joylink_fanyuhong
ca75a70a0f 登录记录&操作记录入参提交 2024-10-25 10:57:33 +08:00
joylink_fanyuhong
5d6283daa6 登录记录&操作记录入参提交
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m54s
2024-10-25 10:44:35 +08:00
joylink_zhaoerwei
37835ed2d6 报警记录增加查询 2024-10-24 15:33:14 +08:00
joylink_zhaoerwei
a486e97e5a 微调 2024-10-24 15:13:57 +08:00
joylink_zhaoerwei
c06c626d52 决策信息查询修改 2024-10-24 15:11:25 +08:00
joylink_fanyuhong
40d57a3fc8 Merge remote-tracking branch 'origin/develop' into local-test
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 1m55s
# Conflicts:
#	src/components/SysMenu.vue
#	src/layouts/MainLayout.vue
#	src/pages/RoleManage.vue
#	src/pages/UserLogin.vue
#	src/router/routes.ts
2024-10-23 15:23:23 +08:00
joylink_zhaoerwei
c5cee6ee5c 调整编辑角色 2024-10-23 14:44:03 +08:00
joylink_zhaoerwei
3ecc0558b1 报警弹框操作增加禁用逻辑和禁选逻辑 2024-10-22 16:11:24 +08:00
joylink_zhaoerwei
330f7cc809 订阅路径修改 2024-10-22 11:30:53 +08:00
joylink_zhaoerwei
2a7cf2e186 添加角色配置 2024-10-22 10:32:37 +08:00
joylink_zhaoerwei
c4ee11a520 Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 2m1s
commit fb18c04248
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Oct 21 17:18:51 2024 +0800

    权限角色调整

commit b6d345426f
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Oct 21 16:37:58 2024 +0800

    弹框不弹--改路由

commit b8d08b40bb
Merge: 2676d4d 5044db8
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Mon Oct 21 14:56:07 2024 +0800

    Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop

commit 2676d4d1d8
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Mon Oct 21 14:56:05 2024 +0800

    登录流程调整

commit 5044db830b
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Oct 21 11:19:08 2024 +0800

    修改报警接口

commit 31ae2f378d
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Mon Oct 21 10:57:15 2024 +0800

    记录调整添加接口入参

commit c7d5464276
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Mon Oct 21 10:24:35 2024 +0800

    刷新token调整

commit c77612e4dc
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Mon Oct 21 10:20:43 2024 +0800

    代码调整

commit 199e775f81
Merge: e90c255 00da310
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Fri Oct 18 17:19:42 2024 +0800

    Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop

commit e90c25523e
Author: joylink_fanyuhong <18706759286@163.com>
Date:   Fri Oct 18 17:19:40 2024 +0800

    接口调整暂时提交

commit 00da31059b
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Fri Oct 18 17:04:11 2024 +0800

    决策信息暂提

commit 012340628a
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Thu Oct 17 09:33:01 2024 +0800

    移动报警列表+去掉接口管理
2024-10-21 17:20:24 +08:00
joylink_zhaoerwei
fb18c04248 权限角色调整 2024-10-21 17:18:51 +08:00
joylink_zhaoerwei
b6d345426f 弹框不弹--改路由 2024-10-21 16:37:58 +08:00
joylink_fanyuhong
b8d08b40bb Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-10-21 14:56:07 +08:00
joylink_fanyuhong
2676d4d1d8 登录流程调整 2024-10-21 14:56:05 +08:00
joylink_zhaoerwei
5044db830b 修改报警接口 2024-10-21 11:19:08 +08:00
joylink_fanyuhong
31ae2f378d 记录调整添加接口入参 2024-10-21 10:57:15 +08:00
joylink_fanyuhong
c7d5464276 刷新token调整 2024-10-21 10:24:35 +08:00
joylink_fanyuhong
c77612e4dc 代码调整 2024-10-21 10:20:43 +08:00
joylink_fanyuhong
199e775f81 Merge branch 'develop' of https://gitea.joylink.club/joylink/xian-ncc-da-client into develop 2024-10-18 17:19:42 +08:00
joylink_fanyuhong
e90c25523e 接口调整暂时提交 2024-10-18 17:19:40 +08:00
joylink_zhaoerwei
00da31059b 决策信息暂提 2024-10-18 17:04:11 +08:00
joylink_zhaoerwei
012340628a 移动报警列表+去掉接口管理 2024-10-17 09:33:01 +08:00
8efecc78d7 Merge pull request '修改cicd设置node环境更新使用版本' (#1) from develop into local-test
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 2m47s
Reviewed-on: #1
2024-09-24 09:22:57 +08:00
soul-walker
a3a5a18fc4 修改cicd设置node环境更新使用版本 2024-09-24 09:18:34 +08:00
joylink_fanyuhong
a828c47e49 Merge remote-tracking branch 'origin/develop' into local-test
Some checks failed
local-test分支构建发布 / Docker-Build (push) Failing after 7m1s
2024-09-23 13:55:28 +08:00
joylink_fanyuhong
7b06dee5be 构建关联关系调整 2024-09-23 13:55:11 +08:00
joylink_fanyuhong
aaf8b932a5 区段放开目的地吗位置偏移 2024-09-23 09:12:28 +08:00
joylink_fanyuhong
49b94329f7 三个记录页面雏形(待接口完善) 2024-09-09 10:01:20 +08:00
joylink_fanyuhong
181a3dae51 合并代码
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 2m20s
2024-09-06 15:06:06 +08:00
joylink_zhaoerwei
acaf3d1f11 权限调整+绘制吸附同步 2024-09-06 14:39:48 +08:00
joylink_zhaoerwei
076b366137 Squashed commit of the following:
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 2m36s
commit 6296877798
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Fri Sep 6 11:08:37 2024 +0800

    权限代码备用

commit be4df53219
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Jul 15 16:10:30 2024 +0800

    同步北京部分计轴

commit 20d39f9f4a
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Jul 15 15:41:09 2024 +0800

    同步区段复制控制-A键直接复制到端点

commit d345a1dc87
Author: joylink_zhaoerwei <Bob_Engineer@163.com>
Date:   Mon Jul 15 15:17:30 2024 +0800

    前端框架版本升级+同步北京区段道岔移动时端点吸附
2024-09-06 11:11:04 +08:00
joylink_zhaoerwei
6296877798 权限代码备用 2024-09-06 11:08:37 +08:00
joylink_zhaoerwei
be4df53219 同步北京部分计轴 2024-07-15 16:10:30 +08:00
joylink_zhaoerwei
20d39f9f4a 同步区段复制控制-A键直接复制到端点 2024-07-15 15:41:09 +08:00
joylink_zhaoerwei
d345a1dc87 前端框架版本升级+同步北京区段道岔移动时端点吸附 2024-07-15 15:17:30 +08:00
45b34cb3b9 submodule url更新
All checks were successful
local-test分支构建发布 / Docker-Build (push) Successful in 2m18s
依赖的graphic-pixi git路径更新
添加local-test构建发布工作流
2024-03-28 10:57:47 +08:00
93 changed files with 5594 additions and 553 deletions

View File

@ -1,4 +1,4 @@
API=192.168.3.233:9081 API=192.168.33.233:9081
HTTP=http:// HTTP=http://
NS= NS=
WS=ws:// WS=ws://

View File

@ -0,0 +1,53 @@
name: local-test分支构建发布
run-name: ${{ gitea.actor }} is testing out Gitea Actions
on:
push:
branches:
- local-test
jobs:
Docker-Build:
runs-on: joylink-local233
steps:
- name: 检出代码
uses: https://gitea.joylink.club/actions/checkout@v4
with:
submodules: recursive
- name: 设置node环境
uses: https://gitea.joylink.club/actions/local-setup-node@v0.1.2
with:
version: 'v18.19.1'
cache: 'yarn'
cache-dependency-path: 'yarn.lock'
- name: 安装yarn,并run build
run: |
node -v
npm -v
npm config set registry https://registry.npmmirror.com
npm install --global yarn
yarn config set registry https://registry.npmmirror.com
yarn
yarn run build
tar czvf ./dist-test.tar.gz ./dist
- name: 打包发送到服务器
uses: https://gitea.joylink.club/appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.LOCAL_233_SSH_HOST }}
username: ${{ secrets.LOCAL_233_SSH_USER }}
password: ${{ secrets.LOCAL_233_SSH_PASSWORD }}
port: ${{ secrets.LOCAL_233_SSH_PORT }}
source: ./dist-test.tar.gz
target: /home/minio/oss/xian-ncc-da-client
overwrite: true
- name: SSH连接服务器并解压发布
uses: https://gitea.joylink.club/appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.LOCAL_233_SSH_HOST }}
port: ${{ secrets.LOCAL_233_SSH_PORT }}
username: ${{ secrets.LOCAL_233_SSH_USER }}
password: ${{ secrets.LOCAL_233_SSH_PASSWORD }}
script: |
cd /home/minio/oss/xian-ncc-da-client
rm -rf /usr/local/joylink/client/xianncc
mkdir -p /usr/local/joylink/client
tar xz --strip 2 -C /usr/local/joylink/client -f dist-test.tar.gz

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "xian-ncc-da-message"] [submodule "xian-ncc-da-message"]
path = xian-ncc-da-message path = xian-ncc-da-message
url = https://git.code.tencent.com/xian-ncc-da/xian-ncc-da-message.git url = https://gitea.joylink.club/joylink/xian-ncc-da-message.git

@ -1 +0,0 @@
Subproject commit b5ca64750380db0ff8e4e4a56a471363db684e12

View File

@ -23,7 +23,7 @@
"centrifuge": "^4.0.1", "centrifuge": "^4.0.1",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"google-protobuf": "^3.21.2", "google-protobuf": "^3.21.2",
"jl-graphic": "git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#v0.1.3", "jl-graphic": "git+https://gitea.joylink.club/joylink/graphic-pixi.git#v0.1.15",
"js-base64": "^3.7.5", "js-base64": "^3.7.5",
"pinia": "^2.0.11", "pinia": "^2.0.11",
"quasar": "^2.6.0", "quasar": "^2.6.0",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/alarmMusic/4/red.mp3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -63,6 +63,8 @@ export interface Item {
drivingInfo: string; drivingInfo: string;
submissionInfo: string; submissionInfo: string;
alarmStatus: number; alarmStatus: number;
lineId: number;
lineType: string;
} }
/** /**
@ -73,7 +75,7 @@ export interface Item {
export async function alarmInfoListQuery( export async function alarmInfoListQuery(
params: PagingQueryParams params: PagingQueryParams
): Promise<PageDto<Item>> { ): Promise<PageDto<Item>> {
const response = await api.post('/api/alertRecord/page/detail', params); const response = await api.get('/api/alertRecord/page/detail', { params });
return response.data; return response.data;
} }

164
src/api/AuthApi.ts Normal file
View File

@ -0,0 +1,164 @@
import { api } from 'src/boot/axios';
import { PageDto, PageQueryDto } from './ApiCommon';
const AuthBase = '/api/role';
export interface Role {
id: number;
name: string;
}
export class PagingQueryParams extends PageQueryDto {
name?: string;
}
export interface createRoleParams {
name: string;
resList: number[];
}
export interface editRoleParams extends createRoleParams {
id: number;
}
export interface RoleInfo {
id: number;
name: string;
resList: number[];
roleConfigStr: string;
}
/**
*
* @param params
* @returns
*/
export async function pageQueryRole(
params: PagingQueryParams
): Promise<PageDto<Role>> {
const response = await api.get(`${AuthBase}/role/page`, {
params: params,
});
return response.data;
}
/**
*
* @param data
* @returns
*/
export function createRole(data: createRoleParams) {
return api.post(`${AuthBase}/role/saveOrUpdate`, data);
}
/**
*
* @param id id
*/
export function deleteRole(id: number) {
return api.delete(`${AuthBase}/role/${id}`);
}
/**
*
* @param id id
* @param data
*/
export function saveRoleData(data: editRoleParams) {
return api.post(`${AuthBase}/role/saveOrUpdate`, data);
}
/**
*
* @param id id
* @returns
*/
export async function getRoleInfo(id: number): Promise<RoleInfo> {
const response = await api.get(`${AuthBase}/role/${id}`);
return response.data;
}
/**
*
* @param id id
* @param data
*/
export function roleConfig(id: number, data: string) {
return api.post(`${AuthBase}/config/${id}`, data, {
headers: {
'Content-Type': 'text/plain',
},
});
}
interface LinkRole {
id: number;
roleList: number[];
}
/**
*
* @param params
* @returns
*/
export async function userLinkRole(params: LinkRole): Promise<string> {
const response = await api.post('api/user/edit', params);
return response.data.token;
}
export interface PathItem {
id: number;
method: string;
name: string;
path: string;
}
/**
*
* @param params
* @returns
*/
export async function pageQueryPath(
params: PagingQueryParams
): Promise<PageDto<PathItem>> {
const response = await api.get(`${AuthBase}/res/page`, {
params: params,
});
return response.data;
}
/**
*
* @param data
* @returns
*/
export function createPath(data: Omit<PathItem, 'id'>) {
return api.post(`${AuthBase}/res/saveOrUpdate`, data);
}
/**
*
* @param id id
*/
export function deletePath(id: number) {
return api.delete(`${AuthBase}/res/${id}`);
}
/**
*
* @param id id
* @param data
*/
export function savePathData(data: PathItem) {
return api.post(`${AuthBase}/res/saveOrUpdate`, data);
}
/**
*
* @param id id
* @returns
*/
export async function getPathInfo(id: number): Promise<PathItem> {
const response = await api.get(`${AuthBase}/res/${id}`);
return response.data;
}

View File

@ -6,6 +6,8 @@ const AlertTipUriBase = '/api/alertTip';
interface AlarmInfoCreateParams { interface AlarmInfoCreateParams {
id: number; id: number;
lineId: number;
lineType: string;
alertType: string; alertType: string;
tipTimeIds: string[]; tipTimeIds: string[];
areaConfigId: number; areaConfigId: number;
@ -15,6 +17,8 @@ interface AlarmInfoCreateParams {
export interface AlarmInfoListItem { export interface AlarmInfoListItem {
id: number; id: number;
lineId: number;
lineType: string;
alertType: string; alertType: string;
timeConfigList: TimeConfigItem[]; timeConfigList: TimeConfigItem[];
areaConfigId: number; areaConfigId: number;

40
src/api/LogApi.ts Normal file
View File

@ -0,0 +1,40 @@
import { api } from 'src/boot/axios';
import { PageDto, PageQueryDto } from './ApiCommon';
const LogUriBase = '/api/log';
export interface Record {
id: number;
faceName: string;
eventType: string;
subEventType: string;
uri: string;
method: string;
parameters: string;
requestSuccess: boolean;
userName: string;
fromUserId: number;
mobile: string;
createDateTime: string;
}
export class PagingQueryParams extends PageQueryDto {
logType?: string;
name?: string;
beginDate?: string;
endDate?: string;
}
/**
*
* @param params
* @returns
*/
export async function pageQuery(
params: PagingQueryParams
): Promise<PageDto<Record>> {
const response = await api.get(`${LogUriBase}/paging`, {
params: params,
});
return response.data;
}

View File

@ -10,12 +10,13 @@ interface RegisterInfo {
password: string; password: string;
} }
interface User { export interface User {
id: string; id: string;
name: string; name: string;
mobile: string; mobile: string;
password: string; password: string;
registerTime: string; registerTime: string;
roleList: { roleId: number; roleName: string }[];
} }
const PasswordSult = '4a6d74126bfd06d69406fcccb7e7d5d9'; // 密码加盐 const PasswordSult = '4a6d74126bfd06d69406fcccb7e7d5d9'; // 密码加盐
@ -71,3 +72,46 @@ export async function pageQuery(
}); });
return response.data; return response.data;
} }
/**
*
*/
export async function logout(): Promise<string> {
const response = await api.post(`${UserUriBase}/logout`);
return response.data;
}
interface tokenInfo {
token: string;
remainingSecond: number;
}
/**
* token
*/
export async function refreshToken(): Promise<tokenInfo> {
const response = await api.post(`${UserUriBase}/refresh/token`);
return response.data;
}
export interface role {
id: number;
name: string;
roleConfig: {
lineId: number;
lineType: string;
}[];
}
interface userInfo {
remainingSecond: number;
roles: role[];
defaultRole: string;
}
/**
*
*/
export async function getUserInfo(): Promise<userInfo> {
const response = await api.post(`${UserUriBase}/info`);
return response.data;
}

94
src/api/faultQuery.ts Normal file
View File

@ -0,0 +1,94 @@
import { api } from 'src/boot/axios';
import { PageDto, PageQueryDto } from './ApiCommon';
const faultQueryUriBase = '/api/fault/query';
export interface FaultQueryListItem {
id?: number;
lineId: number;
faultType: string;
faultNameShower: string;
faultDriverShower: string;
resultMsg: string;
}
export interface FaultQueryInfo<T = unknown> {
data: T;
}
export class PagingQueryParams extends PageQueryDto {
lineId?: string;
faultType?: string;
faultName?: string;
}
/**
*
* @param params
* @returns
*/
export async function faultQueryPageQuery(
params: PagingQueryParams
): Promise<PageDto<FaultQueryListItem>> {
const response = await api.get(`${faultQueryUriBase}/page`, {
params: params,
});
return response.data;
}
/**
*
* @param params
* @returns
*/
export function createFaultQuery(faultData: FaultQueryListItem) {
return api.post(`${faultQueryUriBase}`, faultData);
}
/**
*
* @param id 稿id
*/
export function deleteFaultQueryById(id: number) {
return api.delete(`${faultQueryUriBase}/${id}`);
}
/**
* id获取故障查询
* @param id 稿id
*/
export function faultQueryById(
id: number
): Promise<FaultQueryInfo<FaultQueryListItem>> {
return api.get(`${faultQueryUriBase}/${id}`);
}
export interface FaultTypeItem {
fts: { faultType: string; typeName: string }[];
lineId: number;
}
/**
*
*/
export async function faultQueryType(): Promise<Array<FaultTypeItem>> {
const response = await api.get(`${faultQueryUriBase}/type`);
return response.data;
}
export interface NccFaultQueryListItem {
nccTypeName: string;
nccData: { action: string; datas: string[] }[];
}
/**
* ncc故障查询
* @param params
* @returns
*/
export async function nccFaultQueryPageQuery(): Promise<
NccFaultQueryListItem[]
> {
const response = await api.post(`${faultQueryUriBase}/ncc`);
return response.data;
}

View File

@ -0,0 +1,6 @@
export enum MethodType {
POST = 'POST',
PUT = 'PUT',
DELETE = 'DELETE',
GET = 'GET',
}

View File

@ -3,7 +3,7 @@
ref="dialogRef" ref="dialogRef"
@show="onDialogShow" @show="onDialogShow"
seamless seamless
title="与卡斯柯连接状态信息" title="与同方连接状态信息"
:width="300" :width="300"
:height="0" :height="0"
> >

View File

@ -1,7 +1,7 @@
<template> <template>
<q-list bordered separator> <q-list bordered separator>
<div v-for="(menu, ii) in list" :key="ii"> <div v-for="(menu, ii) in list" :key="ii">
<div v-if="menu.children"> <div v-if="menu.children && menu.show">
<q-expansion-item :icon="menu.icon" :label="menu.label"> <q-expansion-item :icon="menu.icon" :label="menu.label">
<q-card> <q-card>
<q-list bordered separator> <q-list bordered separator>
@ -24,7 +24,7 @@
</q-card> </q-card>
</q-expansion-item> </q-expansion-item>
</div> </div>
<div v-else> <div v-else-if="menu.show">
<q-item clickable :to="menu.path" exact> <q-item clickable :to="menu.path" exact>
<q-item-section avatar> <q-item-section avatar>
<q-icon :name="menu.icon"></q-icon> <q-icon :name="menu.icon"></q-icon>
@ -39,20 +39,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getMonitorPath } from 'src/router/routes';
import { useUserStore } from 'src/stores/user-store';
import { reactive } from 'vue'; import { reactive } from 'vue';
const userStore = useUserStore();
const list = reactive([ const list = reactive([
{ {
path: '/monitor', show: userStore.defaultRole == 'ADMIN',
label: '监控',
icon: 'computer',
},
{
path: '/alarmList',
label: '报警列表',
icon: 'access_alarm',
},
{
path: '', path: '',
label: '数据管理', label: '数据管理',
icon: 'list_alt', icon: 'list_alt',
@ -73,9 +67,9 @@ const list = reactive([
icon: 'format_list_numbered', icon: 'format_list_numbered',
}, },
{ {
path: '/dataManage/decisionInfo', path: '/dataManage/faultQuery',
label: '决策信息管理', label: '故障查询管理',
icon: 'format_align_center', icon: 'disabled_by_default',
}, },
{ {
path: '/dataManage/thresholdValue', path: '/dataManage/thresholdValue',
@ -90,6 +84,7 @@ const list = reactive([
], ],
}, },
{ {
show: true,
path: '', path: '',
label: '系统管理', label: '系统管理',
icon: 'dataset', icon: 'dataset',
@ -99,6 +94,57 @@ const list = reactive([
label: '用户管理', label: '用户管理',
icon: 'manage_accounts', icon: 'manage_accounts',
}, },
{
show: userStore.defaultRole == 'ADMIN',
path: '/sysManage/role',
label: '权限管理',
icon: 'nature_people',
},
{
path: '/sysManage/loginRecord',
label: '登录记录',
icon: 'description',
},
{
path: '/sysManage/operateRecord',
label: '操作记录',
icon: 'receipt',
},
{
path: '/sysManage/alarmRecord',
label: '报警记录',
icon: 'alarm_on',
},
],
},
{
show: true,
path: getMonitorPath(userStore.roles).monitorPath,
label: '监控管理',
icon: 'computer',
},
{
show: true,
path: '/alarmInfo/list',
label: '报警管理',
icon: 'alarm_on',
},
{
show: true,
path: '',
label: '辅助决策',
icon: 'developer_board',
children: [
{
path: '/dataManage/decisionInfo',
label: '辅助决策方案管理查询',
icon: 'format_align_center',
},
{
path: '/dataManage/emergencyResponse',
label: '应急处置流程表',
icon: 'call_merge',
},
], ],
}, },
]); ]);

View File

@ -49,11 +49,22 @@
/> />
<q-card-actions align="left"> <q-card-actions align="left">
<div class="q-gutter-md"> <div class="q-gutter-md">
<q-btn color="primary" label="确认" type="submit" /> <q-btn
<q-btn color="red" label="误报" @click="falseAlarm" /> color="primary"
label="确认"
:disable="operateDisabled"
type="submit"
/>
<q-btn
color="red"
label="误报"
:disable="operateDisabled"
@click="falseAlarm"
/>
<q-btn <q-btn
color="primary" color="primary"
label="人工接警" label="人工接警"
:disable="operateDisabled"
@click="manualAlarm" @click="manualAlarm"
/> />
</div> </div>
@ -88,7 +99,7 @@
<script setup lang="ts"> <script setup lang="ts">
import DraggableDialog from '../common/DraggableDialog.vue'; import DraggableDialog from '../common/DraggableDialog.vue';
import { useLineNetStore, AlarmInfo } from 'src/stores/line-net-store'; import { useLineNetStore, AlarmInfo } from 'src/stores/line-net-store';
import { onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { QForm, useQuasar } from 'quasar'; import { QForm, useQuasar } from 'quasar';
import { saveAlertTypeData, showAlertTypeData } from './alarmInfoEnum'; import { saveAlertTypeData, showAlertTypeData } from './alarmInfoEnum';
import { import {
@ -97,6 +108,8 @@ import {
recordManualAlarmInfoById, recordManualAlarmInfoById,
} from 'src/api/AlertMock'; } from 'src/api/AlertMock';
import { queryAlarmInfoById } from 'src/api/DecisionInfo'; import { queryAlarmInfoById } from 'src/api/DecisionInfo';
import { useUserStore } from 'src/stores/user-store';
import { getMonitorPath } from 'src/router/routes';
const props = defineProps<{ const props = defineProps<{
alarmMeaasge?: AlarmInfo; alarmMeaasge?: AlarmInfo;
@ -124,6 +137,7 @@ const alarmInfo = ref({
level: '', level: '',
time: '', time: '',
lineId: '', lineId: '',
lineType: '',
alertObject: '', alertObject: '',
alertType: '', alertType: '',
locator_device_id: '', locator_device_id: '',
@ -203,6 +217,7 @@ function updata() {
]; ];
alarmInfo.value.alertObject = messageUse.alert_object.replace(/\[|]/g, ''); alarmInfo.value.alertObject = messageUse.alert_object.replace(/\[|]/g, '');
alarmInfo.value.lineId = messageUse.line_id; alarmInfo.value.lineId = messageUse.line_id;
alarmInfo.value.lineType = messageUse.line_type;
} }
async function searchByTipType() { async function searchByTipType() {
@ -237,6 +252,15 @@ async function searchById() {
}); });
} }
} }
const userStore = useUserStore();
const operateDisabled = computed(() => {
const config = getMonitorPath(userStore.roles);
const disabled =
config.lineType == alarmInfo.value.lineType &&
config.lineIds.includes(+alarmInfo.value.lineId);
return !disabled;
});
</script> </script>
<style lang='scss' scoped> <style lang='scss' scoped>

View File

@ -23,6 +23,14 @@ export enum showAlertTypeData {
'联锁区橙光带', '联锁区橙光带',
'联锁区失表', '联锁区失表',
'一级联锁', '一级联锁',
'应急触发',
'道岔挤岔',
'zc联锁故障',
'列车定位丢失',
'列车完整性',
'列车故障救援',
'ats卡滞',
'列车报点',
I = 'I类信息', I = 'I类信息',
II = 'II类信息', II = 'II类信息',
III = 'III类信息', III = 'III类信息',
@ -53,6 +61,14 @@ export enum showAlertTypeData {
AXLE_LED_ORANGE_INTERLOCK_AREA = '联锁区橙光带', AXLE_LED_ORANGE_INTERLOCK_AREA = '联锁区橙光带',
SWITCH_LOST_INTERLOCK_AREA = '联锁区失表', SWITCH_LOST_INTERLOCK_AREA = '联锁区失表',
INTERLOCK_LEVEL_ONE = '一级联锁', INTERLOCK_LEVEL_ONE = '一级联锁',
PLATFORM_EMERG_STOP = '应急触发',
SWITCH_JAMMED = '道岔挤岔',
INTERLOCKED_ZC_FAULT = 'zc联锁故障',
TRAIN_LOST_LOCATION = '列车定位丢失',
TRAIN_INTEGRITY_ALARM = '列车完整性',
TRAIN_FAULT_HELP = '列车故障救援',
INTERLOCKED_ATS_STUCK = 'ats卡滞',
TRAIN_RECORD = '列车报点',
} }
export enum saveAlertTypeData { export enum saveAlertTypeData {
@ -82,6 +98,14 @@ export enum saveAlertTypeData {
= 'AXLE_LED_ORANGE_INTERLOCK_AREA', = 'AXLE_LED_ORANGE_INTERLOCK_AREA',
= 'SWITCH_LOST_INTERLOCK_AREA', = 'SWITCH_LOST_INTERLOCK_AREA',
= 'INTERLOCK_LEVEL_ONE', = 'INTERLOCK_LEVEL_ONE',
= 'PLATFORM_EMERG_STOP',
= 'SWITCH_JAMMED',
zc联锁故障 = 'INTERLOCKED_ZC_FAULT',
= 'TRAIN_LOST_LOCATION',
= 'TRAIN_INTEGRITY_ALARM',
= 'TRAIN_FAULT_HELP',
ats卡滞 = 'INTERLOCKED_ATS_STUCK',
= 'TRAIN_RECORD',
} }
export const GuardConfigTypeData = { export const GuardConfigTypeData = {

View File

@ -12,17 +12,33 @@ import { AlarmInfo, useLineNetStore } from 'src/stores/line-net-store';
import { DialogChainObject, useQuasar } from 'quasar'; import { DialogChainObject, useQuasar } from 'quasar';
import alarmInfoDialog from 'src/components/alarm/alarmInfoDialog.vue'; import alarmInfoDialog from 'src/components/alarm/alarmInfoDialog.vue';
import { showAlertTypeData } from './alarmInfoEnum'; import { showAlertTypeData } from './alarmInfoEnum';
import allLineBlue from '/alarmMusic/all-line-blue.mp3'; import allLineBlue3 from '/alarmMusic/3/all-line-blue.mp3';
import atpcut from '/alarmMusic/atp-cut.mp3'; import atpcut3 from '/alarmMusic/3/atp-cut.mp3';
import blue from '/alarmMusic/blue.mp3'; import blue3 from '/alarmMusic/3/blue.mp3';
import cannotClose from '/alarmMusic/cannot-close.mp3'; import cannotClose3 from '/alarmMusic/3/cannot-close.mp3';
import cannotOpen from '/alarmMusic/cannot-open.mp3'; import cannotOpen3 from '/alarmMusic/3/cannot-open.mp3';
import orangeMost from '/alarmMusic/orange-most.mp3'; import orangeMost3 from '/alarmMusic/3/orange-most.mp3';
import orange from '/alarmMusic/orange.mp3'; import orange3 from '/alarmMusic/3/orange.mp3';
import redMost from '/alarmMusic/red-most.mp3'; import redMost3 from '/alarmMusic/3/red-most.mp3';
import red from '/alarmMusic/red.mp3'; import red3 from '/alarmMusic/3/red.mp3';
import switchLostMost from '/alarmMusic/switch-lost-most.mp3'; import switchLostMost3 from '/alarmMusic/3/switch-lost-most.mp3';
import switchLost from '/alarmMusic/switch-lost.mp3'; import switchLost3 from '/alarmMusic/3/switch-lost.mp3';
import switchJammed3 from '/alarmMusic/3/switch_jammed.mp3';
import platformEmergStop3 from '/alarmMusic/3/platform_emerg_stop.mp3';
//4线
import allLineBlue4 from '/alarmMusic/4/all-line-blue.mp3';
import atpcut4 from '/alarmMusic/4/atp-cut.mp3';
import blue4 from '/alarmMusic/4/blue.mp3';
import cannotClose4 from '/alarmMusic/4/cannot-close.mp3';
import cannotOpen4 from '/alarmMusic/4/cannot-open.mp3';
import orangeMost4 from '/alarmMusic/4/orange-most.mp3';
import orange4 from '/alarmMusic/4/orange.mp3';
import redMost4 from '/alarmMusic/4/red-most.mp3';
import red4 from '/alarmMusic/4/red.mp3';
import switchLostMost4 from '/alarmMusic/4/switch-lost-most.mp3';
import switchLost4 from '/alarmMusic/4/switch-lost.mp3';
import switchJammed4 from '/alarmMusic/4/switch_jammed.mp3';
import platformEmergStop4 from '/alarmMusic/4/platform_emerg_stop.mp3';
import buzzer from '/alarmMusic/buzzer.mp3'; import buzzer from '/alarmMusic/buzzer.mp3';
const lineNetStore = useLineNetStore(); const lineNetStore = useLineNetStore();
@ -39,8 +55,8 @@ watch(
const hasShow = countHasShowFiveDialog(); const hasShow = countHasShowFiveDialog();
if (!hasShow) { if (!hasShow) {
const alarmType = val[0].alert_type; const alarmType = val[0].alert_type;
alarm(alarmType, val[0].id); alarm(alarmType, val[0].id, +val[0].line_id);
playAlarmMusic(alarmType); playAlarmMusic(alarmType, +val[0].line_id);
} else { } else {
waitShowDialog.push(toRaw(lineNetStore.alarmInfo[0])); waitShowDialog.push(toRaw(lineNetStore.alarmInfo[0]));
} }
@ -58,28 +74,53 @@ watch(
} }
); );
function playAlarmMusic(type: number) { function playAlarmMusic(type: number, lineId: number) {
for (let i = 0; i < dialogInstance.length; i++) { for (let i = 0; i < dialogInstance.length; i++) {
if (dialogInstance[i].show == false) { if (dialogInstance[i].show == false) {
dialogInstance.splice(i, 1); dialogInstance.splice(i, 1);
i--; i--;
} }
} }
if (!lineNetStore.handlePlayAble) return;
if (lineNetStore.playAble && audio.value.paused) { if (lineNetStore.playAble && audio.value.paused) {
const alarmType = (showAlertTypeData as never)[type + '']; const alarmType = (showAlertTypeData as never)[type + ''];
const mapAlarmMusic = new Map([ let mapAlarmMusic = new Map();
['蓝显', blue], switch (lineId) {
['全线蓝显', allLineBlue], case 3:
['整侧站台门无法打开', cannotOpen], mapAlarmMusic = new Map([
['整侧站台门无法关闭', cannotClose], ['蓝显', blue3],
['道岔失表', switchLost], ['全线蓝显', allLineBlue3],
['道岔大面积失表', switchLostMost], ['整侧站台门无法打开', cannotOpen3],
['计轴红光带', red], ['整侧站台门无法关闭', cannotClose3],
['计轴大面积红光带', redMost], ['道岔失表', switchLost3],
['计轴橙光带', orange], ['道岔大面积失表', switchLostMost3],
['计轴大面积橙光带', orangeMost], ['计轴红光带', red3],
['列车信号故障', atpcut], ['计轴大面积红光带', redMost3],
['计轴橙光带', orange3],
['计轴大面积橙光带', orangeMost3],
['列车信号故障', atpcut3],
['应急触发', platformEmergStop3],
['道岔挤岔', switchJammed3],
]); ]);
break;
case 4:
mapAlarmMusic = new Map([
['蓝显', blue4],
['全线蓝显', allLineBlue4],
['整侧站台门无法打开', cannotOpen4],
['整侧站台门无法关闭', cannotClose4],
['道岔失表', switchLost4],
['道岔大面积失表', switchLostMost4],
['计轴红光带', red4],
['计轴大面积红光带', redMost4],
['计轴橙光带', orange4],
['计轴大面积橙光带', orangeMost4],
['列车信号故障', atpcut4],
['应急触发', platformEmergStop4],
['道岔挤岔', switchJammed4],
]);
break;
}
const music = mapAlarmMusic.get(alarmType); const music = mapAlarmMusic.get(alarmType);
if (music !== undefined) { if (music !== undefined) {
audioSrc.value = music; audioSrc.value = music;
@ -102,7 +143,7 @@ function timingPlayAlarmMusic(dialog: DialogChainObject) {
!dialogInstance[i].hasHandle && !dialogInstance[i].hasHandle &&
dialogInstance[i].dialog == dialog dialogInstance[i].dialog == dialog
) { ) {
playAlarmMusic(dialogInstance[i].alarmType); playAlarmMusic(dialogInstance[i].alarmType, dialogInstance[i].lineId);
timingPlayAlarmMusic(dialog); timingPlayAlarmMusic(dialog);
} }
} }
@ -116,6 +157,7 @@ const dialogInstance: {
timer: string | number | NodeJS.Timeout | undefined; timer: string | number | NodeJS.Timeout | undefined;
id: string; id: string;
hasHandle: boolean; hasHandle: boolean;
lineId: number;
}[] = []; }[] = [];
function countHasShowFiveDialog(): boolean { function countHasShowFiveDialog(): boolean {
@ -129,7 +171,12 @@ function countHasShowFiveDialog(): boolean {
return hasShow > 4 ? true : false; return hasShow > 4 ? true : false;
} }
function alarm(alarmType: number, id: string, waitAlarmMeaasge?: AlarmInfo) { function alarm(
alarmType: number,
id: string,
lineId: number,
waitAlarmMeaasge?: AlarmInfo
) {
const dialogInstanceItem = $q const dialogInstanceItem = $q
.dialog({ .dialog({
component: alarmInfoDialog, component: alarmInfoDialog,
@ -160,6 +207,7 @@ function alarm(alarmType: number, id: string, waitAlarmMeaasge?: AlarmInfo) {
timer, timer,
hasHandle: false, hasHandle: false,
id, id,
lineId,
}); });
timingPlayAlarmMusic(dialogInstanceItem); timingPlayAlarmMusic(dialogInstanceItem);
} }
@ -169,9 +217,10 @@ function alarmWaitDialog() {
alarm( alarm(
waitShowDialog[0].alert_type, waitShowDialog[0].alert_type,
waitShowDialog[0].id, waitShowDialog[0].id,
+waitShowDialog[0].line_id,
waitShowDialog[0] waitShowDialog[0]
); );
playAlarmMusic(waitShowDialog[0].alert_type); playAlarmMusic(waitShowDialog[0].alert_type, +waitShowDialog[0].line_id);
waitShowDialog.shift(); waitShowDialog.shift();
} }
} }

View File

@ -103,6 +103,8 @@ const optionsAlertType = [
'计轴橙光带', '计轴橙光带',
'计轴大面积橙光带', '计轴大面积橙光带',
'列车信号故障', '列车信号故障',
'应急触发',
'道岔挤岔',
]; ];
const mapAlertType = new Map([ const mapAlertType = new Map([
['蓝显', ['station']], ['蓝显', ['station']],
@ -115,6 +117,8 @@ const mapAlertType = new Map([
['计轴橙光带', ['Section']], ['计轴橙光带', ['Section']],
['计轴大面积橙光带', ['Section']], ['计轴大面积橙光带', ['Section']],
['列车信号故障', ['LogicSection', 'Turnout']], ['列车信号故障', ['LogicSection', 'Turnout']],
['应急触发', ['Platform']],
['道岔挤岔', ['Turnout']],
]); ]);
let selectGraphic: JlGraphic[] = []; let selectGraphic: JlGraphic[] = [];

View File

@ -40,7 +40,9 @@
<q-card> <q-card>
<q-item no-wrap class="column"> <q-item no-wrap class="column">
<q-input <q-input
v-if="setAlartTextData.alertType == '列车信号故障'" v-if="
needShowTrainGroup.includes(setAlartTextData.alertType)
"
outlined outlined
label="车组号" label="车组号"
v-model="configItem.groupId" v-model="configItem.groupId"
@ -81,7 +83,11 @@
@click="clearAllSelect(index)" @click="clearAllSelect(index)"
/> />
<q-btn <q-btn
v-if="setAlartTextData.alertType == '列车信号故障'" v-if="
needShowTrainGroup.includes(
setAlartTextData.alertType
)
"
label="删除测试组" label="删除测试组"
color="secondary" color="secondary"
@click="deleteSelectConfig(index)" @click="deleteSelectConfig(index)"
@ -92,7 +98,7 @@
</q-expansion-item> </q-expansion-item>
</q-list> </q-list>
<q-btn <q-btn
v-if="setAlartTextData.alertType == '列车信号故障'" v-if="needShowTrainGroup.includes(setAlartTextData.alertType)"
class="q-mt-md" class="q-mt-md"
label="增加测试组" label="增加测试组"
color="secondary" color="secondary"
@ -116,7 +122,7 @@
<script setup lang="ts"> <script setup lang="ts">
import DraggableDialog from '../common/DraggableDialog.vue'; import DraggableDialog from '../common/DraggableDialog.vue';
import { onMounted, onUnmounted, ref, watch } from 'vue'; import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import { JlGraphic } from 'jl-graphic'; import { JlGraphic } from 'jl-graphic';
import { Station } from 'src/graphics/station/Station'; import { Station } from 'src/graphics/station/Station';
import { useLineStore } from 'src/stores/line-store'; import { useLineStore } from 'src/stores/line-store';
@ -124,6 +130,8 @@ import { QForm, useQuasar } from 'quasar';
import { ApiError } from 'src/boot/axios'; import { ApiError } from 'src/boot/axios';
import { mockLocalDemoTestSet } from 'src/api/AlertMock'; import { mockLocalDemoTestSet } from 'src/api/AlertMock';
import { isArraysEqual, saveAlertTypeData } from './alarmInfoEnum'; import { isArraysEqual, saveAlertTypeData } from './alarmInfoEnum';
import { Section } from 'src/graphics/section/Section';
import { Platform } from 'src/graphics/platform/Platform';
const lineStore = useLineStore(); const lineStore = useLineStore();
const setAlartTextData = ref<{ const setAlartTextData = ref<{
@ -152,12 +160,17 @@ const setAlartTextData = ref<{
}, },
], ],
}); });
const needShowTrainGroup = ['列车信号故障', '列车报点'];
const optionsAlertType = [ const optionsAlertType = [
'蓝显', '蓝显',
'道岔失表', '道岔失表',
'计轴红光带', '计轴红光带',
'计轴橙光带', '计轴橙光带',
'列车信号故障', '列车信号故障',
'应急触发',
'道岔挤岔',
'列车完整性',
'列车报点',
]; ];
const mapAlertType = new Map([ const mapAlertType = new Map([
['蓝显', ['station']], ['蓝显', ['station']],
@ -165,17 +178,33 @@ const mapAlertType = new Map([
['计轴红光带', ['LogicSection', 'Turnout']], ['计轴红光带', ['LogicSection', 'Turnout']],
['计轴橙光带', ['LogicSection', 'Turnout']], ['计轴橙光带', ['LogicSection', 'Turnout']],
['列车信号故障', ['LogicSection', 'Turnout']], ['列车信号故障', ['LogicSection', 'Turnout']],
['应急触发', ['Platform']],
['道岔挤岔', ['Turnout']],
['列车完整性', ['LogicSection']],
['列车报点', ['Section']],
]); ]);
enum DeviceType { enum DeviceType {
station = 'DEVICE_TYPE_RTU', station = 'DEVICE_TYPE_RTU',
Turnout = 'DEVICE_TYPE_SWITCH', Turnout = 'DEVICE_TYPE_SWITCH',
LogicSection = 'DEVICE_TYPE_TRACK', LogicSection = 'DEVICE_TYPE_TRACK',
Platform = 'DEVICE_TYPE_PLATFORM',
Section = 'DEVICE_TYPE_SECTION',
} }
const optionsStatus = [ const optionsStatus = computed(() => {
if (setAlartTextData.value.alertType !== '列车报点') {
return [
{ label: '正常', value: 'NORMAL' }, { label: '正常', value: 'NORMAL' },
{ label: '设置', value: 'BEGIN' }, { label: '设置', value: 'BEGIN' },
{ label: '报警', value: 'ALERT' }, { label: '报警', value: 'ALERT' },
]; ];
} else {
return [
{ label: '到站', value: 'NORMAL' },
{ label: '离站', value: 'BEGIN' },
];
}
});
let allplatformRefSection: number[] = [];
let selectGraphic: JlGraphic[] = []; let selectGraphic: JlGraphic[] = [];
watch( watch(
@ -205,16 +234,22 @@ watch(
setAlartTextData.value.alertType == '蓝显' setAlartTextData.value.alertType == '蓝显'
) { ) {
select = true; select = true;
} } else if (
if ( g.type == Section.Type &&
setAlartTextData.value.alertType == '列车报点' &&
allplatformRefSection.includes(g.id)
) {
select = true;
} else if (
g.type !== Station.Type && g.type !== Station.Type &&
g.type !== Section.Type &&
mapAlertType.get(setAlartTextData.value.alertType)?.includes(g.type) mapAlertType.get(setAlartTextData.value.alertType)?.includes(g.type)
) { ) {
select = true; select = true;
} }
return select; return select;
}) as JlGraphic[]; }) as JlGraphic[];
if (setAlartTextData.value.alertType !== '列车信号故障') { if (!needShowTrainGroup.includes(setAlartTextData.value.alertType)) {
selectGraphic.push(...deviceFilter); selectGraphic.push(...deviceFilter);
} else if (deviceFilter.length) { } else if (deviceFilter.length) {
selectGraphic = [deviceFilter[0]]; selectGraphic = [deviceFilter[0]];
@ -235,6 +270,12 @@ watch(
); );
onMounted(() => { onMounted(() => {
const platforms = lineStore
.getLineApp()
.queryStore.queryByType<Platform>(Platform.Type);
platforms.forEach((platform) =>
allplatformRefSection.push(platform.datas.refSectionId)
);
lineStore.getLineApp().emit('options-update', { lineStore.getLineApp().emit('options-update', {
mouseToolOptions: { mouseToolOptions: {
boxSelect: true, boxSelect: true,

View File

@ -0,0 +1,186 @@
<template>
<q-list bordered separator class="rounded-borders">
<q-expansion-item
bordered
expand-separator
v-for="(configItem, index) in selectConfig"
:key="configItem"
v-model="configItem.expanded"
:label="configItem.code"
@click="toggleItem(index)"
>
<q-card>
<q-item no-wrap class="q-gutter-y-sm column">
<q-input
v-if="props.ableAdd"
outlined
v-model="configItem.code"
label="配置项类型"
lazy-rules
/>
<div class="q-gutter-sm row">
<q-chip
v-for="(item, selectIndex) in configItem.refDevicesCode"
:key="item"
square
color="primary"
text-color="white"
removable
@remove="removeSelect(selectIndex)"
clickable
@click="clickSelectCenter(selectIndex)"
>
{{ item }}
</q-chip>
</div>
<div>
<q-btn
v-show="configItem.refDevicesCode.length > 0"
style="width: 100px"
label="清空选择"
color="red"
class="q-mr-md"
@click="clearAllSelect(index)"
/>
<q-btn
v-if="props.ableAdd"
label="删除配置项"
color="secondary"
@click="deleteSelectConfig(index)"
/>
</div>
</q-item>
</q-card>
</q-expansion-item>
</q-list>
<q-btn
v-if="props.ableAdd"
class="q-mt-md"
label="增加配置项"
color="secondary"
@click="addSelectConfig"
/>
</template>
<script setup lang="ts">
import { inject, ref, watch } from 'vue';
import { IDrawApp, JlGraphic } from 'jl-graphic';
const props = withDefaults(
defineProps<{
drawStore: {
selectedGraphics: JlGraphic[];
getDrawApp(): IDrawApp;
};
ableAdd?: boolean;
}>(),
{ ableAdd: false }
);
const selectConfig = ref<
{
code: string;
refDevices: number[];
refDevicesCode: string[];
expanded: boolean;
}[]
>([
{
code: '配置项模版',
refDevices: [],
refDevicesCode: [],
expanded: false,
},
]);
let selectGraphic: JlGraphic[] = [];
defineExpose({
selectConfig,
selectGraphic,
});
interface GraphicData {
datas: { code: string };
}
const filterSelect = inject('filter') as (g: JlGraphic) => boolean;
watch(
() => props.drawStore.selectedGraphics,
(val) => {
if (val && val.length > 0 && clickIndex !== null) {
const selectFilter = props.drawStore.selectedGraphics?.filter(
filterSelect
) as JlGraphic[];
selectGraphic.push(...selectFilter);
selectGraphic = Array.from(new Set(selectGraphic));
props.drawStore.getDrawApp().updateSelected(...selectGraphic);
selectConfig.value[clickIndex].refDevicesCode = selectGraphic.map((g) =>
(g as JlGraphic & GraphicData).datas.code == ''
? g.id + ''
: (g as JlGraphic & GraphicData).datas.code
);
selectConfig.value[clickIndex].refDevices = selectGraphic.map(
(g) => g.id
) as number[];
}
}
);
let clickIndex: null | number = null;
function toggleItem(index: number) {
const drawApp = props.drawStore.getDrawApp();
selectGraphic = [];
drawApp.updateSelected();
if (selectConfig.value[index].expanded == true) {
clickIndex = index;
const select: JlGraphic[] = [];
selectConfig.value[index].refDevices.forEach((id: number) => {
const g = drawApp.queryStore.queryById(id);
select.push(g);
});
drawApp.updateSelected(...select);
} else {
clickIndex = null;
}
}
function removeSelect(removeIndex: number) {
const clickTarget = selectConfig.value[clickIndex as number];
selectGraphic.splice(removeIndex, 1);
clickTarget.refDevicesCode.splice(removeIndex, 1);
clickTarget.refDevices.splice(removeIndex, 1);
props.drawStore.getDrawApp().updateSelected(...selectGraphic);
}
function clickSelectCenter(index: number) {
const drawApp = props.drawStore.getDrawApp();
const clickTarget = selectConfig.value[clickIndex as number];
const clickGraphic = drawApp.queryStore.queryById(
clickTarget.refDevices[index]
);
drawApp.makeGraphicCenterShow(clickGraphic);
}
function clearAllSelect(index: number) {
selectConfig.value[index].refDevices = [];
selectConfig.value[index].refDevicesCode = [];
selectGraphic = [];
props.drawStore.getDrawApp().updateSelected();
}
function addSelectConfig() {
selectConfig.value.push({
code: '配置项模版',
refDevices: [],
refDevicesCode: [],
expanded: false,
});
}
function deleteSelectConfig(index: number) {
selectConfig.value.splice(index, 1);
selectGraphic = [];
props.drawStore.getDrawApp().updateSelected();
}
</script>

View File

@ -0,0 +1,357 @@
<template>
<draggable-dialog
seamless
ref="dialogRef"
@show="onDialogShow"
title="故障查询"
:width="990"
:height="600"
>
<div class="dialogContainer">
<q-table
ref="tableRef"
row-key="id"
v-model:pagination="pagination"
:loading="loading"
:rows="rows"
:columns="columns"
@request="onRequest"
:rows-per-page-options="[10, 20, 50, 100]"
style="width: 500px; height: 600px"
>
<template v-slot:body="props">
<q-tr
:props="props"
:class="{ changeBackground: props.row.id === clickRowInfo.id }"
@click="handleRowClick(props.row)"
>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
class="custom-column"
>
{{ col.value }}
<q-tooltip
anchor="bottom middle"
v-if="props.value && props.value.length > 20"
>
<div class="message-tip">
{{ col.value }}
</div>
</q-tooltip>
</q-td>
</q-tr>
</template>
</q-table>
<q-scroll-area style="width: 490px; height: 580px">
<div class="detaiRow">
<div class="text">
<span class="textHead">故障类型</span> {{
clickRowInfo.faultType
}}
</div>
<div class="text">
<span class="textHead"> {{ showTitle.faultNameShower }}</span
>{{ clickRowInfo.faultNameShower }}
</div>
<q-card class="box-card">
<div class="head">{{ showTitle.faultDriverShower }}</div>
<q-separator />
<div>
<div class="detail">{{ clickRowInfo.faultDriverShower }}</div>
</div>
</q-card>
<q-card class="box-card">
<div class="head">{{ showTitle.resultMsg }}</div>
<q-separator />
<div>
<div class="detail">{{ clickRowInfo.resultMsg }}</div>
</div>
</q-card>
</div>
</q-scroll-area>
</div>
<template v-slot:titleButton>
<q-btn
square
color="purple"
style="margin-right: 10px"
icon="search"
@click="reset"
>
<q-popup-edit
ref="popupEdit"
v-model="noUse"
:cover="false"
:offset="[0, 10]"
>
<q-select
dense
label="故障类型"
v-model="filter.faultType"
emit-value
map-options
:options="searchOptionsFaultType"
style="min-width: 130px"
/>
<q-input
dense
label="故障现象(故障名称)"
v-model="filter.faultName"
lazy-rules
/>
<div class="button-container">
<q-btn
color="primary"
label="查询"
type="submit"
style="margin-top: 10px"
@click="searchTable"
/>
</div>
</q-popup-edit>
</q-btn>
</template>
</draggable-dialog>
</template>
<script setup lang="ts">
import { reactive, ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import DraggableDialog from '../common/DraggableDialog.vue';
import { QTable, useQuasar } from 'quasar';
import {
FaultQueryListItem,
faultQueryPageQuery,
faultQueryType,
FaultTypeItem,
} from 'src/api/faultQuery';
const $q = useQuasar();
const lineId = useRoute().params.lineId as string;
const tableRef = ref<QTable>();
const columns = computed(() => [
{
name: 'id',
label: '编号',
field: 'id',
required: true,
align: 'center',
},
{
name: 'faultType',
label: '故障类型',
field: (row: FaultQueryListItem) => {
if (row.faultType) {
return getFaultTypeName(row);
}
},
align: 'center',
},
{
name: 'faultNameShower',
label: '消息名称(故障现象)',
field: 'faultNameShower',
required: true,
align: 'center',
},
]);
const rows = reactive([]);
const loading = ref(false);
const pagination = ref({
sortBy: 'desc',
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 10,
});
const filter = reactive({
faultType: '',
faultName: '',
});
const onRequest: QTable['onRequest'] = async (props) => {
const { page, rowsPerPage } = props.pagination;
loading.value = true;
try {
const params = {
current: page,
size: rowsPerPage,
lineId,
};
if (filter.faultType !== '') {
Object.assign(params, {
faultType: filter.faultType,
});
}
if (filter.faultName !== '') {
Object.assign(params, {
faultName: filter.faultName,
});
}
let resp = await faultQueryPageQuery(params);
pagination.value.page = resp.current;
pagination.value.rowsNumber = resp.total;
pagination.value.rowsPerPage = resp.size;
rows.splice(0, rows.length, ...(resp.records as []));
if (rows.length) {
handleRowClick(rows[0]);
} else {
clickRowInfo.faultType = '';
clickRowInfo.faultNameShower = '';
clickRowInfo.faultDriverShower = '';
clickRowInfo.resultMsg = '';
}
} catch (err) {
$q.notify({
type: 'negative',
message: '无法获取范围列表',
});
} finally {
loading.value = false;
}
};
const clickRowInfo = reactive({
id: 0,
faultType: '',
faultNameShower: '',
faultDriverShower: '',
resultMsg: '',
});
const showTitle = reactive({
faultNameShower: '',
faultDriverShower: '',
resultMsg: '',
});
function handleRowClick(row: FaultQueryListItem) {
if (row.faultType.includes('FAULT_EMERGENCY_GUIDE')) {
showTitle.faultNameShower = '故障现象';
showTitle.faultDriverShower = '司机处理结果';
showTitle.resultMsg = '行调提醒司机关键点';
} else {
showTitle.faultNameShower = '故障名称';
showTitle.faultDriverShower = '故障现象';
showTitle.resultMsg = '退出服务地点';
}
clickRowInfo.id = row?.id as number;
clickRowInfo.faultType = getFaultTypeName(row) as string;
clickRowInfo.faultNameShower = row.faultNameShower;
clickRowInfo.faultDriverShower = row.faultDriverShower;
clickRowInfo.resultMsg = row.resultMsg;
}
async function queryAllFaultType() {
try {
allOptionsFaultType = await faultQueryType();
handleSelectFaultType();
} catch (err) {
$q.notify({
type: 'negative',
message: '无法获取指定线路的故障类型配置',
});
}
}
let allOptionsFaultType: FaultTypeItem[] = [];
function getFaultTypeName(row: FaultQueryListItem) {
for (let i = 0; i < allOptionsFaultType.length; i++) {
if (allOptionsFaultType[i].lineId == row.lineId) {
const fts = allOptionsFaultType[i].fts;
for (let j = 0; i < fts.length; j++) {
if (fts[j].faultType == row.faultType) {
return fts[j].typeName;
}
}
}
}
}
const searchOptionsFaultType = ref([{ label: '全部', value: '' }]);
function handleSelectFaultType() {
allOptionsFaultType.forEach((faultTypeOption) => {
faultTypeOption.fts.forEach((fault) =>
searchOptionsFaultType.value.push({
label: fault.typeName,
value: fault.faultType,
})
);
});
}
function searchTable() {
tableRef.value?.requestServerInteraction();
}
const noUse = ref('');
function reset() {
filter.faultType = '';
filter.faultName = '';
}
const onDialogShow = () => {
queryAllFaultType();
setTimeout(() => {
tableRef.value?.requestServerInteraction();
}, 1000);
};
</script>
<style lang='scss' scoped>
.changeBackground {
background-color: #31ccec;
}
.custom-column {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.message-tip {
width: 300px;
overflow: auto;
line-height: 22px;
white-space: pre-wrap;
font-size: 14px;
}
.button-container {
display: flex;
justify-content: center;
margin-top: 10px;
}
.dialogContainer {
display: flex;
.detaiRow {
margin: 10px 0 0 20px;
.text {
width: 450px;
word-wrap: break-word;
margin-bottom: 10px;
font-size: 18px;
.textHead {
font-weight: 600;
}
}
.box-card {
width: 450px;
height: 235px;
margin-bottom: 10px;
padding: 0 5px;
.head {
padding: 5px 5px;
font-size: 20px;
font-weight: 600;
}
.detail {
margin-bottom: 10px;
padding: 5px 5px;
line-height: 28px;
white-space: pre-wrap;
font-size: 20px;
}
}
}
}
</style>

View File

@ -0,0 +1,183 @@
<template>
<q-card class="q-gutter-sm q-pa-sm">
<q-card-section>
<div class="text-h6">一键生成计轴配置</div>
</q-card-section>
<q-form ref="myForm">
<selectConfig-utils ref="selectConfigUtils" :drawStore="drawStore" />
<div class="q-mt-md q-gutter-md">
<q-btn label="确认修改" color="primary" @click="onSubmit" />
<q-btn label="返回" color="red" @click="goBack" />
<q-btn label="生成计轴" color="primary" @click="generateAxleCounting" />
</div>
<div class="q-mt-md q-gutter-md">
<q-btn
label="检查计轴"
color="primary"
@click="showErrorAxleCounting"
/>
<q-btn
v-if="showCheck"
label="上一个"
color="primary"
@click="clickSelectCenter(-1)"
/>
<q-btn
v-if="showCheck"
label="下一个"
color="primary"
@click="clickSelectCenter(1)"
/>
</div>
</q-form>
</q-card>
</template>
<script setup lang="ts">
import { onMounted, ref, provide } from 'vue';
import { QForm, useQuasar } from 'quasar';
import { JlGraphic } from 'jl-graphic';
import { useDrawStore } from 'src/stores/draw-store';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { Turnout } from 'src/graphics/turnout/Turnout';
import {
loadGenerateAxleCountingConfig,
setGenerateAxleCountingConfig,
} from 'src/drawApp';
import SelectConfigUtils from 'src/components/common/SelectConfigUtils.vue';
import { OneClickGenerate } from 'src/graphics/trainWindow/oneClickDrawAssistant';
import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting';
//使
const filterSelect = (g: JlGraphic) => g instanceof Turnout;
const selectConfigUtils = ref<InstanceType<typeof SelectConfigUtils> | null>(
null
);
provide('filter', filterSelect);
const emit = defineEmits(['close']);
const drawStore = useDrawStore();
const $q = useQuasar();
onMounted(() => {
selectConfigUtils.value.selectConfig = [
{
code: 'bb连接的道岔',
refDevices: [],
refDevicesCode: [],
expanded: false,
},
{
code: '不生成计轴的道岔组',
refDevices: [],
refDevicesCode: [],
expanded: false,
},
];
const generateAxleCountingConfig = loadGenerateAxleCountingConfig();
if (generateAxleCountingConfig !== undefined) {
selectConfigUtils.value.selectConfig.forEach(
(generate: {
code: string;
refDevices: number[];
refDevicesCode: string[];
}) => {
if (generate.code == 'bb连接的道岔') {
generate.refDevices = generateAxleCountingConfig.bbConnect;
generateAxleCountingConfig.bbConnect.forEach((id) => {
const g = drawStore.getDrawApp().queryStore.queryById(id);
generate.refDevicesCode.push(g.code);
});
} else if (generate.code == '不生成计轴的道岔组') {
generate.refDevices = generateAxleCountingConfig.noGenerateGroup;
generateAxleCountingConfig.noGenerateGroup.forEach((id) => {
const g = drawStore.getDrawApp().queryStore.queryById(id);
generate.refDevicesCode.push(g.code);
});
}
}
);
}
});
const myForm = ref<QForm | null>(null);
async function onSubmit() {
myForm.value?.validate().then(async (res) => {
if (res) {
try {
const generateAxleCountingConfig =
new graphicData.GenerateAxleCountingConfig();
selectConfigUtils.value.selectConfig.forEach(
(generate: { code: string; refDevices: number[] }) => {
if (generate.code == 'bb连接的道岔') {
generateAxleCountingConfig.bbConnect = generate.refDevices;
} else if (generate.code == '不生成计轴的道岔组') {
generateAxleCountingConfig.noGenerateGroup = generate.refDevices;
}
}
);
setGenerateAxleCountingConfig(generateAxleCountingConfig);
$q.notify({
type: 'positive',
message: '更新成功',
});
} catch (err) {
$q.notify({
type: 'negative',
message: '更新失败',
});
}
}
});
}
function goBack() {
emit('close');
}
function generateAxleCounting() {
drawStore.oneClickType = 'AxleCounting';
drawStore.getDrawApp().interactionPlugin(OneClickGenerate.Type).resume();
}
const selectConfig = ref<
{
axleCountingId: number;
axleCountingCode: string;
}[]
>([]);
function showErrorAxleCounting() {
showCheck.value = true;
const axleCountings = drawStore
.getDrawApp()
.queryStore.queryByType<AxleCounting>(AxleCounting.Type);
const erroeAxleCountings = axleCountings
.filter((g) => g.datas.axleCountingRef.length < 2)
.sort((a, b) => a.position.x - b.position.x);
erroeAxleCountings.forEach((axleCounting) => {
selectConfig.value.push({
axleCountingId: axleCounting.id,
axleCountingCode: axleCounting.datas.code,
});
});
}
const currentIndex = ref(-1);
const showCheck = ref(false);
function clickSelectCenter(add: number) {
if (
currentIndex.value + add < 0 ||
currentIndex.value + add >= selectConfig.value.length
)
return;
currentIndex.value = currentIndex.value + add;
const target = drawStore
.getDrawApp()
.queryStore.queryById(
selectConfig.value[currentIndex.value].axleCountingId
);
drawStore.getDrawApp().makeGraphicCenterShow(target);
drawStore.getDrawApp().updateSelected(target);
}
</script>

View File

@ -130,6 +130,8 @@ const optionsAlertType = [
'道岔大面积失表', '道岔大面积失表',
'列车信号故障', '列车信号故障',
'一级联锁', '一级联锁',
'应急触发',
'道岔挤岔',
]; ];
enum DeviceType { enum DeviceType {

View File

@ -16,7 +16,7 @@ export function getWebsocketUrl() {
export function getShowSetAlarmTextButton() { export function getShowSetAlarmTextButton() {
let show = false; let show = false;
const host = window.location.hostname; const host = window.location.hostname;
if (process.env.NODE_ENV == 'development' || host == '192.168.3.233') { if (process.env.NODE_ENV == 'development' || host == '192.168.33.233') {
show = true; show = true;
} }
return show; return show;

View File

@ -207,6 +207,12 @@ export class PlatformState extends GraphicStateBase implements IPlatformState {
set rtuId(value: number) { set rtuId(value: number) {
this.states.rtuId = value; this.states.rtuId = value;
} }
get bizWaitTimeSec(): number {
return this.states.bizWaitTimeSec;
}
set bizWaitTimeSec(value: number) {
this.states.bizWaitTimeSec = value;
}
get states(): state.Platform { get states(): state.Platform {
return this.getState<state.Platform>(); return this.getState<state.Platform>();
} }

View File

@ -23,6 +23,7 @@ import { RunLineGraphicHitArea } from 'src/graphics/runLine/RunLineDrawAssistant
import { Dialog } from 'quasar'; import { Dialog } from 'quasar';
import SetDashLineDialog from '../../components/draw-app/dialogs/SetDashLineDialog.vue'; import SetDashLineDialog from '../../components/draw-app/dialogs/SetDashLineDialog.vue';
import SetGaryLineDialog from '../../components/draw-app/dialogs/SetGaryLineDialog.vue'; import SetGaryLineDialog from '../../components/draw-app/dialogs/SetGaryLineDialog.vue';
import { useLineNetStore } from 'src/stores/line-net-store';
export class RunLineData extends GraphicDataBase implements IRunLineData { export class RunLineData extends GraphicDataBase implements IRunLineData {
constructor(data?: graphicData.RunLine) { constructor(data?: graphicData.RunLine) {
@ -235,7 +236,6 @@ export class DrawRunLinePlugin extends GraphicInteractionPlugin<RunLine> {
}); });
}; };
setGrayLineConfig.handler = () => { setGrayLineConfig.handler = () => {
console.log(runLine.datas, '11111');
Dialog.create({ Dialog.create({
title: '设置灰线段', title: '设置灰线段',
message: '', message: '',
@ -280,10 +280,22 @@ export class RunLineOperateInteraction extends GraphicInteractionPlugin<RunLine>
g.cursor = 'pointer'; g.cursor = 'pointer';
g.lineBody.hitArea = new RunLineGraphicHitArea(g); g.lineBody.hitArea = new RunLineGraphicHitArea(g);
g.selectable = true; g.selectable = true;
g.on('_leftclick', this.leftClick, this);
} }
unbind(g: RunLine): void { unbind(g: RunLine): void {
g.selectable = false; g.selectable = false;
g.eventMode = 'none'; g.eventMode = 'none';
g.off('_leftclick', this.leftClick, this);
}
leftClick(e: FederatedMouseEvent) {
const target = e.target as DisplayObject;
const runLine = target.getGraphic() as RunLine;
const lineId = runLine.datas.lineId;
if (lineId) {
useLineNetStore().jumpLineCount++;
useLineNetStore().jumpLineId = lineId;
}
} }
} }

View File

@ -14,6 +14,9 @@ import {
IGraphicStorage, IGraphicStorage,
ContextMenu, ContextMenu,
MenuItemOptions, MenuItemOptions,
calculateDistanceFromPointToLine,
distance2,
getRectangleCenter,
} from 'jl-graphic'; } from 'jl-graphic';
import { IscsFanData } from './graphics/IscsFanInteraction'; import { IscsFanData } from './graphics/IscsFanInteraction';
import { LinkData } from './graphics/LinkInteraction'; import { LinkData } from './graphics/LinkInteraction';
@ -286,6 +289,9 @@ export function initDrawApp(): IDrawApp {
if (app.drawing) return; if (app.drawing) return;
handleRIghtClick(e); handleRIghtClick(e);
}); });
app.on('destroy', () => {
generateAxleCountingConfig = new graphicData.GenerateAxleCountingConfig();
});
app.addKeyboardListener( app.addKeyboardListener(
new KeyListener({ new KeyListener({
value: 'KeyS', value: 'KeyS',
@ -296,6 +302,99 @@ export function initDrawApp(): IDrawApp {
}, },
}) })
); );
// KeyA 用于区段复制--控制生成的区段位置
const graphicCopyPlugin = app.app.graphicCopyPlugin;
const copySectionListener = new KeyListener({
value: 'KeyA',
global: true,
onPress: () => {
graphicCopyPlugin.updateMoveLimit('sectionPointLimit');
},
});
graphicCopyPlugin.addGraphicControlers([
{
controlerList: [copySectionListener],
check: () => {
if (
graphicCopyPlugin.copys.length == 1 &&
graphicCopyPlugin.copys[0].type == Section.Type
)
return true;
return false;
},
moveLimitOption: {
moveLimitName: 'sectionPointLimit',
moveLimit: (e) => {
const mousePos = app.toCanvasCoordinates(e.global);
const selectSection = app.selectedGraphics[0] as Section;
let selectSectionLeft = selectSection.localToCanvasPoint(
selectSection.getStartPoint()
);
let selectSectionRight = selectSection.localToCanvasPoint(
selectSection.getEndPoint()
);
[selectSectionLeft, selectSectionRight] =
selectSectionLeft.x < selectSectionRight.x
? [selectSectionLeft, selectSectionRight]
: [selectSectionRight, selectSectionLeft];
//要移动到目标位的区段
const sections = app.queryStore.queryByType<Section>(Section.Type);
const minDistanceSection = sections.reduce((prev, cur) => {
const prevDistance = calculateDistanceFromPointToLine(
prev.localToCanvasPoint(prev.getStartPoint()),
prev.localToCanvasPoint(prev.getEndPoint()),
mousePos
);
const curDistance = calculateDistanceFromPointToLine(
cur.localToCanvasPoint(cur.getStartPoint()),
cur.localToCanvasPoint(cur.getEndPoint()),
mousePos
);
return prevDistance > curDistance ||
(prevDistance == curDistance &&
distance2(
prev.localToCanvasPoint(prev.getStartPoint()),
mousePos
) >
distance2(
cur.localToCanvasPoint(cur.getStartPoint()),
mousePos
))
? cur
: prev;
});
const minDistanceRefSectionsPos =
minDistanceSection.localToCanvasPoint(
getRectangleCenter(
minDistanceSection.lineGraphic.getLocalBounds()
)
);
let minDistanceSectionLeft = minDistanceSection.localToCanvasPoint(
minDistanceSection.getStartPoint()
);
let minDistanceSectionRight = minDistanceSection.localToCanvasPoint(
minDistanceSection.getEndPoint()
);
[minDistanceSectionLeft, minDistanceSectionRight] =
minDistanceSectionLeft.x < minDistanceSectionRight.x
? [minDistanceSectionLeft, minDistanceSectionRight]
: [minDistanceSectionRight, minDistanceSectionLeft];
if (mousePos.x > minDistanceRefSectionsPos.x) {
graphicCopyPlugin.container.position.x =
minDistanceSectionRight.x - selectSectionLeft.x;
graphicCopyPlugin.container.position.y =
minDistanceSectionRight.y - selectSectionLeft.y;
} else {
graphicCopyPlugin.container.position.x =
minDistanceSectionLeft.x - selectSectionRight.x;
graphicCopyPlugin.container.position.y =
minDistanceSectionLeft.y - selectSectionRight.y;
}
},
},
},
]);
return drawApp; return drawApp;
} }
@ -461,6 +560,7 @@ export function saveDrawDatas(app: IDrawApp) {
// item.pcRef.nid = +item.pcRef.id; // item.pcRef.nid = +item.pcRef.id;
// } // }
// }); // });
storage.generateAxleCountingConfig = generateAxleCountingConfig;
const base64 = fromUint8Array(storage.serialize()); const base64 = fromUint8Array(storage.serialize());
console.log('保存数据', storage); console.log('保存数据', storage);
// localStorage.setItem(StorageKey, base64); // localStorage.setItem(StorageKey, base64);
@ -483,6 +583,7 @@ export async function loadDrawDatas(): Promise<IGraphicStorage> {
); );
console.log('加载数据', storage); console.log('加载数据', storage);
const datas: GraphicData[] = []; const datas: GraphicData[] = [];
generateAxleCountingConfig = storage.generateAxleCountingConfig;
storage.links.forEach((link) => { storage.links.forEach((link) => {
datas.push(new LinkData(link)); datas.push(new LinkData(link));
}); });
@ -546,3 +647,15 @@ export async function loadDrawDatas(): Promise<IGraphicStorage> {
datas: [], datas: [],
}); });
} }
//一键生成计轴配置
let generateAxleCountingConfig = new graphicData.GenerateAxleCountingConfig();
export function loadGenerateAxleCountingConfig() {
return generateAxleCountingConfig;
}
export function setGenerateAxleCountingConfig(
newScreenDoorConfig: graphicData.GenerateAxleCountingConfig
) {
generateAxleCountingConfig = newScreenDoorConfig;
}

View File

@ -73,23 +73,32 @@ import {
import { Notify, QNotifyUpdateOptions } from 'quasar'; import { Notify, QNotifyUpdateOptions } from 'quasar';
import { useLineNetStore } from 'src/stores/line-net-store'; import { useLineNetStore } from 'src/stores/line-net-store';
import { alert } from 'src/protos/alertInfo'; import { alert } from 'src/protos/alertInfo';
import { useUserStore } from 'src/stores/user-store';
import { getMonitorPath } from 'src/router/routes';
let lineApp: IGraphicApp | null = null; let lineApp: IGraphicApp | null = null;
const lineAppMap = new Map<number, IGraphicApp>();
export function getLineApp() { export function getLineApp() {
return lineApp; return lineApp;
} }
export function destroyLineApp(): void { export function destroyLineApp(): void {
if (lineApp) { for (const key of lineAppMap.keys()) {
lineApp.destroy(); const app = lineAppMap.get(key);
lineApp = null; if (app) {
app.destroy();
} }
}
lineApp = null;
} }
export function initLineApp(): IGraphicApp { export function initLineApp(lineId: number): IGraphicApp {
if (lineApp) return lineApp; lineApp = lineAppMap.get(lineId) || null;
if (lineApp) {
handleSubscribe(lineApp);
return lineApp;
}
lineApp = newGraphicApp({ lineApp = newGraphicApp({
interactiveGraphicTypeIncludes: [ interactiveGraphicTypeIncludes: [
Signal.Type, Signal.Type,
@ -107,6 +116,7 @@ export function initLineApp(): IGraphicApp {
}, },
dataLoader: loadLineDatas, dataLoader: loadLineDatas,
}); });
lineAppMap.set(lineId, lineApp);
const graphicTemplate = [ const graphicTemplate = [
new TrainTemplate(new TrainData(), new TrainState()), new TrainTemplate(new TrainData(), new TrainState()),
@ -251,6 +261,18 @@ export async function loadLineDatas(): Promise<IGraphicStorage> {
} }
} }
export function cancelSubscribe(lineApp: IGraphicApp) {
const lineStore = useLineStore();
const lineId = lineStore.lineId;
if (lineId) {
lineApp.unsubscribe(`/queue/line/${lineId}/device`);
lineApp.unsubscribe(`/queue/line/${lineId}/train`);
monitorDestinations.forEach((destination) => {
lineApp.unsubscribe(destination);
});
}
}
let monitorDestinations: string[] = [];
function handleSubscribe(lineApp: IGraphicApp) { function handleSubscribe(lineApp: IGraphicApp) {
const lineStore = useLineStore(); const lineStore = useLineStore();
const lineId = lineStore.lineId; const lineId = lineStore.lineId;
@ -304,11 +326,15 @@ function handleSubscribe(lineApp: IGraphicApp) {
}, },
}); });
const lineNetStore = useLineNetStore(); const lineNetStore = useLineNetStore();
const userStore = useUserStore();
monitorDestinations = getMonitorPath(userStore.roles).destinations;
monitorDestinations.forEach((destination) => {
lineApp.subscribe({ lineApp.subscribe({
destination: '/queue/xian/ncc/alert', destination,
messageHandle: (message: Uint8Array) => { messageHandle: (message: Uint8Array) => {
const storage = alert.NccAlertInfoMessage.deserialize(message); const storage = alert.NccAlertInfoMessage.deserialize(message);
lineNetStore.setAlarmInfo(storage.messages as []); lineNetStore.setAlarmInfo(storage.messages as []);
}, },
}); });
});
} }

View File

@ -35,6 +35,8 @@ import { getWebsocketUrl } from 'src/configs/UrlManage';
import { getJwtToken } from 'src/configs/TokenManage'; import { getJwtToken } from 'src/configs/TokenManage';
import { alert } from 'src/protos/alertInfo'; import { alert } from 'src/protos/alertInfo';
import { Notify } from 'quasar'; import { Notify } from 'quasar';
import { useUserStore } from 'src/stores/user-store';
import { getMonitorPath } from 'src/router/routes';
let lineNetApp: IGraphicApp | null = null; let lineNetApp: IGraphicApp | null = null;
@ -50,6 +52,10 @@ export function destroyLineNetApp(): void {
} }
export function initLineNetApp(): IGraphicApp { export function initLineNetApp(): IGraphicApp {
if (lineNetApp) {
handleSubscribe(lineNetApp);
return lineNetApp;
}
lineNetApp = newGraphicApp({ lineNetApp = newGraphicApp({
interactiveGraphicTypeIncludes: [ interactiveGraphicTypeIncludes: [
RunLine.Type, RunLine.Type,
@ -143,6 +149,14 @@ export async function loadLineNetDatas(): Promise<IGraphicStorage> {
} }
} }
export function cancelSubscribe(lineNetApp: IGraphicApp) {
lineNetApp.unsubscribe('/queue/lineNet');
monitorDestinations.forEach((destination) => {
lineNetApp.unsubscribe(destination);
});
}
let monitorDestinations: string[] = [];
function handleSubscribe(lineNetApp: IGraphicApp) { function handleSubscribe(lineNetApp: IGraphicApp) {
const lineNetStore = useLineNetStore(); const lineNetStore = useLineNetStore();
lineNetApp.enableWsMassaging({ lineNetApp.enableWsMassaging({
@ -161,11 +175,15 @@ function handleSubscribe(lineNetApp: IGraphicApp) {
return states; return states;
}, },
}); });
const userStore = useUserStore();
monitorDestinations = getMonitorPath(userStore.roles).destinations;
monitorDestinations.forEach((destination) => {
lineNetApp.subscribe({ lineNetApp.subscribe({
destination: '/queue/xian/ncc/alert', destination,
messageHandle: (message: Uint8Array) => { messageHandle: (message: Uint8Array) => {
const storage = alert.NccAlertInfoMessage.deserialize(message); const storage = alert.NccAlertInfoMessage.deserialize(message);
lineNetStore.setAlarmInfo(storage.messages as []); lineNetStore.setAlarmInfo(storage.messages as []);
}, },
}); });
});
} }

View File

@ -14,12 +14,13 @@ import {
IAxleCountingData, IAxleCountingData,
AxleCounting, AxleCounting,
AxleCountingTemplate, AxleCountingTemplate,
AxleCountingConsts,
} from './AxleCounting'; } from './AxleCounting';
import { Section, SectionPort } from '../section/Section'; import { Section, SectionPort } from '../section/Section';
import { Turnout, TurnoutPort } from '../turnout/Turnout'; import { Turnout, TurnoutPort } from '../turnout/Turnout';
import { IRelatedRefData, createRelatedRefProto } from '../CommonGraphics'; import { IRelatedRefData, createRelatedRefProto } from '../CommonGraphics';
import { Signal } from '../signal/Signal'; import { Signal } from '../signal/Signal';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { loadGenerateAxleCountingConfig } from 'src/drawApp';
export interface IAxleCountingDrawOptions { export interface IAxleCountingDrawOptions {
newData: () => IAxleCountingData; newData: () => IAxleCountingData;
@ -80,12 +81,39 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
refGraphic: Section | Turnout, refGraphic: Section | Turnout,
refPort: TurnoutPort | SectionPort refPort: TurnoutPort | SectionPort
) { ) {
const generateAxleCountingConfig = loadGenerateAxleCountingConfig();
if (generateAxleCountingConfig?.noGenerateGroup !== undefined) {
const noGenerateGroup = generateAxleCountingConfig.noGenerateGroup;
for (let i = 0; i < noGenerateGroup.length; i++) {
if (
noGenerateGroup[i] == graphic.id &&
((i % 2 == 0 && refGraphic.id == noGenerateGroup[i + 1]) ||
(i % 2 == 1 && refGraphic.id == noGenerateGroup[i - 1]))
) {
map.set(`${graphic.id}-${port}`, 1);
map.set(`${refGraphic.id}-${refPort}`, 1);
return;
}
}
}
if ( if (
graphic.type == 'Turnout' && graphic.type == 'Turnout' &&
reftype == 'Turnout' && reftype == 'Turnout' &&
port == TurnoutPort.B && port == TurnoutPort.B &&
refPort == TurnoutPort.B refPort == TurnoutPort.B
) { ) {
//查看生成计轴bb配置
let hasBB = false;
if (generateAxleCountingConfig !== undefined) {
const bbConnect = generateAxleCountingConfig.bbConnect;
if (
bbConnect.includes(graphic.id) ||
bbConnect.includes(refGraphic.id)
) {
hasBB = true;
}
}
//bb连接处有信号机需要生成
const points = (graphic as Turnout).getPortPoints(); const points = (graphic as Turnout).getPortPoints();
const portPs = graphic.localToCanvasPoints(points[1][0])[0]; const portPs = graphic.localToCanvasPoints(points[1][0])[0];
let hasSingle = false; let hasSingle = false;
@ -95,7 +123,7 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
hasSingle = true; hasSingle = true;
} }
}); });
if (!hasSingle) { if (!hasSingle && !hasBB) {
map.set(`${graphic.id}-${port}`, 1); map.set(`${graphic.id}-${port}`, 1);
map.set(`${refGraphic.id}-${refPort}`, 1); map.set(`${refGraphic.id}-${refPort}`, 1);
return; return;
@ -112,14 +140,7 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
const refData2 = createRelatedRefProto(graphic.type, graphic.id, port); const refData2 = createRelatedRefProto(graphic.type, graphic.id, port);
const axleCounting = new AxleCounting(direction); const axleCounting = new AxleCounting(direction);
axleCounting.loadData(this.graphicTemplate.datas); axleCounting.loadData(this.graphicTemplate.datas);
if (graphic.type == 'Turnout') {
axleCounting.position.set(ps.x, ps.y); axleCounting.position.set(ps.x, ps.y);
} else {
axleCounting.position.set(
ps.x,
ps.y - AxleCountingConsts.offsetSection * direction
);
}
axleCounting.id = GraphicIdGenerator.next(); axleCounting.id = GraphicIdGenerator.next();
axleCounting.datas.axleCountingRef = [refData2, refData1]; axleCounting.datas.axleCountingRef = [refData2, refData1];
axleCounting.datas.code = `${graphic.datas.code}-${port}+${refGraphic.datas.code}-${refPort}`; axleCounting.datas.code = `${graphic.datas.code}-${port}+${refGraphic.datas.code}-${refPort}`;
@ -139,14 +160,7 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
const refData = createRelatedRefProto(graphic.type, graphic.id, port); const refData = createRelatedRefProto(graphic.type, graphic.id, port);
const axleCounting = new AxleCounting(direction); const axleCounting = new AxleCounting(direction);
axleCounting.loadData(this.graphicTemplate.datas); axleCounting.loadData(this.graphicTemplate.datas);
if (graphic.type == 'Turnout') {
axleCounting.position.set(ps.x, ps.y); axleCounting.position.set(ps.x, ps.y);
} else {
axleCounting.position.set(
ps.x,
ps.y - AxleCountingConsts.offsetSection * direction
);
}
axleCounting.id = GraphicIdGenerator.next(); axleCounting.id = GraphicIdGenerator.next();
axleCounting.datas.axleCountingRef = [refData]; axleCounting.datas.axleCountingRef = [refData];
axleCounting.datas.code = `${graphic.datas.code}-${port}`; axleCounting.datas.code = `${graphic.datas.code}-${port}`;
@ -156,9 +170,28 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
} }
oneGenerates(height: Point) { oneGenerates(height: Point) {
const map = new Map(); const map = new Map();
const axleCountings = this.app.queryStore.queryByType<AxleCounting>( const needDelete: AxleCounting[] = [];
AxleCounting.Type const axleCountings = this.app.queryStore
.queryByType<AxleCounting>(AxleCounting.Type)
.filter((axleCounting) => {
if (axleCounting.datas.axleCountingRef.length == 1) {
const refInfo = axleCounting.datas.axleCountingRef[0];
if (refInfo.deviceType == graphicData.RelatedRef.DeviceType.Section) {
const refSection = this.app.queryStore.queryById<Section>(
refInfo.id
); );
if (
refSection.datas.paRef != undefined &&
refSection.datas.pbRef != undefined
) {
needDelete.push(axleCounting);
return false;
}
}
}
return true;
});
this.app.deleteGraphics(...needDelete);
const axleCountingRefs: IRelatedRefData[] = []; const axleCountingRefs: IRelatedRefData[] = [];
axleCountings.forEach((axleCounting) => { axleCountings.forEach((axleCounting) => {
axleCountingRefs.push(...axleCounting.datas.axleCountingRef); axleCountingRefs.push(...axleCounting.datas.axleCountingRef);

View File

@ -11,6 +11,7 @@ import {
} from 'jl-graphic'; } from 'jl-graphic';
import { Station } from '../station/Station'; import { Station } from '../station/Station';
import { Section } from '../section/Section'; import { Section } from '../section/Section';
import { useLineStore } from 'src/stores/line-store';
export interface IPlatformData extends GraphicData { export interface IPlatformData extends GraphicData {
get code(): string; // 编号 get code(): string; // 编号
@ -66,6 +67,8 @@ export interface IPlatformState extends GraphicState {
set stopTime(v: number); set stopTime(v: number);
get rtuId(): number; // 集中站站号 get rtuId(): number; // 集中站站号
set rtuId(v: number); set rtuId(v: number);
get bizWaitTimeSec(): number; //乘客等待秒数
set bizWaitTimeSec(v: number);
} }
//站台颜色 //站台颜色
@ -189,6 +192,8 @@ class codeGraph extends Container {
runLevel: VectorText = new VectorText(''); //运行等级 runLevel: VectorText = new VectorText(''); //运行等级
runTime: VectorText = new VectorText(''); //运行时间 runTime: VectorText = new VectorText(''); //运行时间
stopTime: VectorText = new VectorText(''); //停站时间 stopTime: VectorText = new VectorText(''); //停站时间
waitSec: VectorText = new VectorText(); //VectorText
circle: Graphics = new Graphics(); circle: Graphics = new Graphics();
constructor() { constructor() {
super(); super();
@ -197,12 +202,14 @@ class codeGraph extends Container {
this.addChild(this.circle); this.addChild(this.circle);
this.addChild(this.stopTime); this.addChild(this.stopTime);
this.addChild(this.runTime); this.addChild(this.runTime);
this.addChild(this.waitSec);
this.character.setVectorFontSize(platformConsts.besideFontSize); this.character.setVectorFontSize(platformConsts.besideFontSize);
this.runLevel.setVectorFontSize(platformConsts.besideFontSize); this.runLevel.setVectorFontSize(platformConsts.besideFontSize);
this.stopTime.setVectorFontSize(platformConsts.besideFontSize); this.stopTime.setVectorFontSize(platformConsts.besideFontSize);
this.runTime.setVectorFontSize(platformConsts.besideFontSize); this.runTime.setVectorFontSize(platformConsts.besideFontSize);
this.waitSec.setVectorFontSize(platformConsts.besideFontSize);
} }
draw(): void { draw(datas: IPlatformData): void {
//扣车 //扣车
const character = this.character; const character = this.character;
character.text = 'H'; character.text = 'H';
@ -254,11 +261,25 @@ class codeGraph extends Container {
platformConsts.besideSpacing platformConsts.besideSpacing
); );
stopTime.style.fill = PlatformColorEnum.whiteNumbers; stopTime.style.fill = PlatformColorEnum.whiteNumbers;
//乘客等待时间
const waitSec = this.waitSec;
waitSec.anchor.set(0.5);
let yPos = platformConsts.height / 2 + platformConsts.doorPlatformSpacing;
if (datas.direction == 'down') {
yPos = -platformConsts.height / 2 - platformConsts.doorPlatformSpacing;
}
waitSec.position.set(0, yPos);
waitSec.style.fill = PlatformColorEnum.whiteNumbers;
character.visible = false; character.visible = false;
circle.visible = false; circle.visible = false;
runLevel.visible = false; runLevel.visible = false;
stopTime.visible = false; stopTime.visible = false;
runTime.visible = false; runTime.visible = false;
waitSec.visible = false;
} }
clear(): void { clear(): void {
this.character.destroy(); this.character.destroy();
@ -309,6 +330,23 @@ class codeGraph extends Container {
this.stopTime.visible = true; this.stopTime.visible = true;
this.stopTime.text = stateData.stopTime; this.stopTime.text = stateData.stopTime;
} }
if (useLineStore().faultStatistics) {
const minutes = Math.floor(stateData.bizWaitTimeSec / 60);
const seconds = stateData.bizWaitTimeSec % 60;
let minutesString = '' + minutes;
let secondsString = '' + seconds;
if (minutes < 10) {
minutesString = `0${minutes}`;
}
if (seconds < 10) {
secondsString = `0${seconds}`;
}
this.waitSec.visible = true;
this.waitSec.text = `${minutesString}:${secondsString}`;
} else {
this.waitSec.visible = false;
}
} }
} }
//子元素--站台旁菱形图标 //子元素--站台旁菱形图标
@ -388,7 +426,7 @@ export class Platform extends JlGraphic {
} }
this.platformGraphic.draw(this.states); this.platformGraphic.draw(this.states);
this.besideGraphic.draw(); this.besideGraphic.draw();
this.codeGraph.draw(); this.codeGraph.draw(this.datas);
this.doorGraphic.position.set( this.doorGraphic.position.set(
0, 0,

View File

@ -8,7 +8,6 @@ import {
distance2, distance2,
splitLineEvenly, splitLineEvenly,
ILineGraphic, ILineGraphic,
epsilon,
Vector2, Vector2,
} from 'jl-graphic'; } from 'jl-graphic';
import { import {
@ -29,6 +28,8 @@ export enum SectionPort {
B = 'B', B = 'B',
} }
const sectionEpsilon = 0.1;
export interface ISectionData extends GraphicData { export interface ISectionData extends GraphicData {
get code(): string; // 编号 get code(): string; // 编号
set code(v: string); set code(v: string);
@ -148,17 +149,17 @@ export class Section extends JlGraphic implements ILineGraphic {
const destinationCodePosition = this.datas.childTransforms?.find( const destinationCodePosition = this.datas.childTransforms?.find(
(t) => t.name === this.destinationCodeGraphic.name (t) => t.name === this.destinationCodeGraphic.name
)?.transform.position; )?.transform.position;
// if (destinationCodePosition) { if (destinationCodePosition) {
// this.destinationCodeGraphic.position.set( this.destinationCodeGraphic.position.set(
// destinationCodePosition.x, destinationCodePosition.x,
// destinationCodePosition.y destinationCodePosition.y
// ); );
// } else { } else {
this.destinationCodeGraphic.position.set( this.destinationCodeGraphic.position.set(
this.datas.points[0].x, this.datas.points[0].x,
this.datas.points[0].y - 20 this.datas.points[0].y - 20
); );
// } }
} }
} }
@ -244,7 +245,7 @@ export class Section extends JlGraphic implements ILineGraphic {
distance2( distance2(
this.localToCanvasPoint(this.getStartPoint()), this.localToCanvasPoint(this.getStartPoint()),
section.localToCanvasPoint(section.getStartPoint()) section.localToCanvasPoint(section.getStartPoint())
) <= epsilon ) <= sectionEpsilon
) { ) {
param = [SectionPort.A, SectionPort.A]; param = [SectionPort.A, SectionPort.A];
} }
@ -252,7 +253,7 @@ export class Section extends JlGraphic implements ILineGraphic {
distance2( distance2(
this.localToCanvasPoint(this.getEndPoint()), this.localToCanvasPoint(this.getEndPoint()),
section.localToCanvasPoint(section.getStartPoint()) section.localToCanvasPoint(section.getStartPoint())
) <= epsilon ) <= sectionEpsilon
) { ) {
param = [SectionPort.B, SectionPort.A]; param = [SectionPort.B, SectionPort.A];
} }
@ -260,7 +261,7 @@ export class Section extends JlGraphic implements ILineGraphic {
distance2( distance2(
this.localToCanvasPoint(this.getStartPoint()), this.localToCanvasPoint(this.getStartPoint()),
section.localToCanvasPoint(section.getEndPoint()) section.localToCanvasPoint(section.getEndPoint())
) <= epsilon ) <= sectionEpsilon
) { ) {
param = [SectionPort.A, SectionPort.B]; param = [SectionPort.A, SectionPort.B];
} }
@ -268,7 +269,7 @@ export class Section extends JlGraphic implements ILineGraphic {
distance2( distance2(
this.localToCanvasPoint(this.getEndPoint()), this.localToCanvasPoint(this.getEndPoint()),
section.localToCanvasPoint(section.getEndPoint()) section.localToCanvasPoint(section.getEndPoint())
) <= epsilon ) <= sectionEpsilon
) { ) {
param = [SectionPort.B, SectionPort.B]; param = [SectionPort.B, SectionPort.B];
} }

View File

@ -49,6 +49,7 @@ import { AxleCounting } from '../axleCounting/AxleCounting';
import { LogicSectionData } from 'src/drawApp/graphics/LogicSectionInteraction'; import { LogicSectionData } from 'src/drawApp/graphics/LogicSectionInteraction';
import { LogicSectionDraw } from '../logicSection/LogicSectionDrawAssistant'; import { LogicSectionDraw } from '../logicSection/LogicSectionDrawAssistant';
import { LogicSection } from '../logicSection/LogicSection'; import { LogicSection } from '../logicSection/LogicSection';
import { buildDragMoveAbsorbablePositions } from '../turnout/TurnoutDrawAssistant';
export class SectionDraw extends GraphicDrawAssistant< export class SectionDraw extends GraphicDrawAssistant<
SectionTemplate, SectionTemplate,
@ -443,11 +444,13 @@ export class SectionPointEditPlugin extends GraphicInteractionPlugin<Section> {
g.on('selected', this.onSelected, this); g.on('selected', this.onSelected, this);
g.on('unselected', this.onUnselected, this); g.on('unselected', this.onUnselected, this);
g.on('_rightclick', this.onContextMenu, this); g.on('_rightclick', this.onContextMenu, this);
g.on('transformstart', this.onDragMove, this);
} }
unbind(g: Section): void { unbind(g: Section): void {
g.off('selected', this.onSelected, this); g.off('selected', this.onSelected, this);
g.off('unselected', this.onUnselected, this); g.off('unselected', this.onUnselected, this);
g.off('_rightclick', this.onContextMenu, this); g.off('_rightclick', this.onContextMenu, this);
g.off('transformstart', this.onDragMove, this);
} }
onContextMenu(e: FederatedMouseEvent) { onContextMenu(e: FederatedMouseEvent) {
@ -585,4 +588,10 @@ export class SectionPointEditPlugin extends GraphicInteractionPlugin<Section> {
section.draggable = false; section.draggable = false;
} }
} }
onDragMove(e: GraphicTransformEvent) {
const section = e.target as Section;
this.app.setOptions({
absorbablePositions: buildDragMoveAbsorbablePositions(section),
});
}
} }

View File

@ -195,6 +195,7 @@ export class Station extends JlGraphic {
codeGraph.anchor.set(0.5); codeGraph.anchor.set(0.5);
const kilometerCode = this.datas.kilometerSystem?.kilometer || 12345678; const kilometerCode = this.datas.kilometerSystem?.kilometer || 12345678;
if (Math.floor(kilometerCode * 1000).toString().length > 3) { if (Math.floor(kilometerCode * 1000).toString().length > 3) {
if (Number(kilometerCode) > 0) {
const kiloBit = Math.floor(Number(kilometerCode) / 1000000).toString(); const kiloBit = Math.floor(Number(kilometerCode) / 1000000).toString();
kilometerGraph.text = kilometerGraph.text =
'K' + 'K' +
@ -203,6 +204,17 @@ export class Station extends JlGraphic {
( (
Number(kilometerCode.toString().substring(kiloBit.length)) / 1000 Number(kilometerCode.toString().substring(kiloBit.length)) / 1000
).toFixed(3); ).toFixed(3);
} else {
const fuKilometerCode = Number(kilometerCode) * -1;
const kiloBit = Math.floor(fuKilometerCode / 1000000).toString();
kilometerGraph.text =
'K-' +
kiloBit +
'-' +
(
Number(kilometerCode.toString().substring(kiloBit.length)) / 1000
).toFixed(3);
}
} else { } else {
kilometerGraph.text = (kilometerCode * 1000).toFixed(3); kilometerGraph.text = (kilometerCode * 1000).toFixed(3);
} }

View File

@ -10,7 +10,6 @@ import {
angleOfIncludedAngle, angleOfIncludedAngle,
distance2, distance2,
getParallelOfPolyline, getParallelOfPolyline,
epsilon,
Vector2, Vector2,
} from 'jl-graphic'; } from 'jl-graphic';
import { Section, SectionPort, SectionType } from '../section/Section'; import { Section, SectionPort, SectionType } from '../section/Section';
@ -22,6 +21,7 @@ import {
import { KilometerSystem } from '../signal/Signal'; import { KilometerSystem } from '../signal/Signal';
import { Station } from '../station/Station'; import { Station } from '../station/Station';
const turnoutEpsilon = 0.1;
export interface ITurnoutData extends GraphicData { export interface ITurnoutData extends GraphicData {
get code(): string; get code(): string;
set code(code: string); set code(code: string);
@ -541,22 +541,20 @@ export class Turnout extends JlGraphic {
buildRelation(): void { buildRelation(): void {
this.relationManage.deleteRelationOfGraphic(this); this.relationManage.deleteRelationOfGraphic(this);
/** 道岔和区段 */ /** 道岔和区段 */
this.queryStore.queryByType<Section>(Section.Type) this.queryStore.queryByType<Section>(Section.Type).forEach((section) => {
.forEach((section) => {
if (section.datas.sectionType === SectionType.TurnoutPhysical) { if (section.datas.sectionType === SectionType.TurnoutPhysical) {
if (section.datas.children.includes(this.datas.id)) { if (section.datas.children.includes(this.datas.id)) {
this.relationManage.addRelation(this, section) this.relationManage.addRelation(this, section);
} }
return return;
} }
this.getPortPoints().forEach((port, i) => { this.getPortPoints().forEach((port, i) => {
if ( if (
distance2( distance2(
section.localToCanvasPoint(section.getStartPoint()), section.localToCanvasPoint(section.getStartPoint()),
this.localToCanvasPoint(port[port.length - 1]) this.localToCanvasPoint(port[port.length - 1])
) <= epsilon ) <= turnoutEpsilon
) { ) {
this.relationManage.addRelation( this.relationManage.addRelation(
new GraphicRelationParam( new GraphicRelationParam(
@ -570,7 +568,7 @@ export class Turnout extends JlGraphic {
distance2( distance2(
section.localToCanvasPoint(section.getEndPoint()), section.localToCanvasPoint(section.getEndPoint()),
this.localToCanvasPoint(port[port.length - 1]) this.localToCanvasPoint(port[port.length - 1])
) <= epsilon ) <= turnoutEpsilon
) { ) {
this.relationManage.addRelation( this.relationManage.addRelation(
new GraphicRelationParam( new GraphicRelationParam(
@ -594,7 +592,7 @@ export class Turnout extends JlGraphic {
distance2( distance2(
this.localToCanvasPoint(thisPort[thisPort.length - 1]), this.localToCanvasPoint(thisPort[thisPort.length - 1]),
turnout.localToCanvasPoint(otherPort[otherPort.length - 1]) turnout.localToCanvasPoint(otherPort[otherPort.length - 1])
) <= epsilon ) <= turnoutEpsilon
) { ) {
const angle = angleOfIncludedAngle( const angle = angleOfIncludedAngle(
this.localToCanvasPoint(thisPort[thisPort.length - 1]) /* 交点 */, this.localToCanvasPoint(thisPort[thisPort.length - 1]) /* 交点 */,
@ -668,9 +666,13 @@ export class Turnout extends JlGraphic {
const pcRelation = this.relationManage const pcRelation = this.relationManage
.getRelationsOfGraphic(this) .getRelationsOfGraphic(this)
.find( .find(
(relation) => relation.getRelationParam(this).param === TurnoutPort.C (relation) =>
&& (!(relation.getOtherGraphic(this) instanceof Section relation.getRelationParam(this).param === TurnoutPort.C &&
&& relation.getOtherGraphic<Section>(this).datas.sectionType !== SectionType.TurnoutPhysical)) !(
relation.getOtherGraphic(this) instanceof Section &&
relation.getOtherGraphic<Section>(this).datas.sectionType !==
SectionType.TurnoutPhysical
)
); );
const pcDevice = pcRelation?.getOtherGraphic<Section | Turnout>(this); const pcDevice = pcRelation?.getOtherGraphic<Section | Turnout>(this);
if (pcDevice) { if (pcDevice) {

View File

@ -17,6 +17,7 @@ import {
AbsorbableLine, AbsorbableLine,
ContextMenu, ContextMenu,
MenuItemOptions, MenuItemOptions,
distance,
} from 'jl-graphic'; } from 'jl-graphic';
import { import {
ITurnoutData, ITurnoutData,
@ -178,6 +179,130 @@ function buildAbsorbablePositions(turnout: Turnout): AbsorbablePosition[] {
return aps; return aps;
} }
type dragType = Turnout | Section;
class DragMoveAbsorbablePoint extends AbsorbablePoint {
moveTarget:
| {
position: IPointData;
portPos: IPointData[];
}
| undefined;
constructor(point: IPointData, absorbRange = 15) {
super(point, absorbRange);
}
tryAbsorb(...dragTargets: dragType[]): void {
const dragTarget = dragTargets[0];
if (dragTarget instanceof Turnout) {
if (this.moveTarget == undefined) {
const {
pointA: [A],
pointB: [B],
pointC: [C],
} = dragTarget.datas;
this.moveTarget = {
position: dragTarget
.getGraphicApp()
.toCanvasCoordinates(dragTarget.getGlobalPosition()),
portPos: [
dragTarget.localToCanvasPoint(A),
dragTarget.localToCanvasPoint(B),
dragTarget.localToCanvasPoint(C),
],
};
}
const {
pointA: [A],
pointB: [B],
pointC: [C],
} = dragTarget.datas;
[A, B, C].forEach((p, i) => {
const changePos = dragTarget.localToCanvasPoint(p);
if (
distance(this._point.x, this._point.y, changePos.x, changePos.y) <
this.absorbRange &&
this.moveTarget
) {
dragTarget.updatePositionByCanvasPosition(
new Point(
this.moveTarget.position.x +
this._point.x -
this.moveTarget.portPos[i].x,
this.moveTarget.position.y +
this._point.y -
this.moveTarget.portPos[i].y
)
);
}
});
} else {
if (this.moveTarget == undefined) {
this.moveTarget = {
position: dragTarget
.getGraphicApp()
.toCanvasCoordinates(dragTarget.getGlobalPosition()),
portPos: [
dragTarget.localToCanvasPoint(dragTarget.getStartPoint()),
dragTarget.localToCanvasPoint(dragTarget.getEndPoint()),
],
};
}
dragTarget
.localToCanvasPoints(...dragTarget.datas.points)
.forEach((p, i) => {
if (
distance(this._point.x, this._point.y, p.x, p.y) <
this.absorbRange &&
this.moveTarget
) {
dragTarget.updatePositionByCanvasPosition(
new Point(
this.moveTarget.position.x +
this._point.x -
this.moveTarget.portPos[i].x,
this.moveTarget.position.y +
this._point.y -
this.moveTarget.portPos[i].y
)
);
}
});
}
}
}
export function buildDragMoveAbsorbablePositions(
target: dragType
): AbsorbablePosition[] {
const aps: AbsorbablePosition[] = [];
const sections = target.queryStore.queryByType<Section>(Section.Type);
sections.forEach((section) => {
if (section.id !== target.id) {
section.localToCanvasPoints(...section.datas.points).forEach((p) => {
aps.push(new DragMoveAbsorbablePoint(p)); //区段端点
});
}
});
const turnouts = target.queryStore.queryByType<Turnout>(Turnout.Type);
turnouts.forEach((otherTurnout) => {
if (otherTurnout.id !== target.id) {
const {
pointA: [A],
pointB: [B],
pointC: [C],
} = otherTurnout.datas;
[A, B, C].forEach((p) => {
aps.push(
new DragMoveAbsorbablePoint(otherTurnout.localToCanvasPoint(p)) //道岔端点
);
});
}
});
return aps;
}
function onEditPointCreate(turnout: Turnout, dp: DraggablePoint) { function onEditPointCreate(turnout: Turnout, dp: DraggablePoint) {
dp.on('transformstart', (e: GraphicTransformEvent) => { dp.on('transformstart', (e: GraphicTransformEvent) => {
if (e.isShift()) { if (e.isShift()) {
@ -290,6 +415,7 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
g.transformSave = true; g.transformSave = true;
g.on('selected', this.onSelected, this); g.on('selected', this.onSelected, this);
g.on('unselected', this.onUnSelected, this); g.on('unselected', this.onUnSelected, this);
g.on('transformstart', this.onDragMove, this);
} }
unbind(g: Turnout): void { unbind(g: Turnout): void {
@ -298,6 +424,7 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
g.graphics.sections.forEach((sectionGraphic) => { g.graphics.sections.forEach((sectionGraphic) => {
sectionGraphic.off('rightclick'); sectionGraphic.off('rightclick');
}); });
g.off('transformstart', this.onDragMove, this);
} }
onSelected(g: DisplayObject) { onSelected(g: DisplayObject) {
@ -309,6 +436,9 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
tep = new TurnoutEditPlugin(turnout, { onEditPointCreate }); tep = new TurnoutEditPlugin(turnout, { onEditPointCreate });
turnout.addAssistantAppend(tep); turnout.addAssistantAppend(tep);
} }
tep.editPoints = [[], [], []];
tep.removeChildren();
tep.initEditPoints();
// tep.reset(); // tep.reset();
tep.showAll(); tep.showAll();
tep.setRelatedDrag(); tep.setRelatedDrag();
@ -327,6 +457,13 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
filter(...grahpics: JlGraphic[]): Turnout[] | undefined { filter(...grahpics: JlGraphic[]): Turnout[] | undefined {
return grahpics.filter((g) => g.type == Turnout.Type) as Turnout[]; return grahpics.filter((g) => g.type == Turnout.Type) as Turnout[];
} }
onDragMove(e: GraphicTransformEvent) {
const turnout = e.target as Turnout;
this.app.setOptions({
absorbablePositions: buildDragMoveAbsorbablePositions(turnout),
});
}
} }
type onTurnoutEditPointCreate = (turnout: Turnout, dp: DraggablePoint) => void; type onTurnoutEditPointCreate = (turnout: Turnout, dp: DraggablePoint) => void;
@ -441,7 +578,7 @@ export class TurnoutEditPlugin extends GraphicEditPlugin<Turnout> {
Array.from(cpMap.entries()).forEach(([cpDatas, dataPoints], i) => { Array.from(cpMap.entries()).forEach(([cpDatas, dataPoints], i) => {
cpDatas.forEach((cpData, j) => { cpDatas.forEach((cpData, j) => {
const dp = new DraggablePoint(cpData); const dp = new DraggablePoint(cpData);
dp.on('transforming', (e: GraphicTransformEvent) => { dp.on('transforming', () => {
const localPoint = this.graphic.canvasToLocalPoint(dp.position); const localPoint = this.graphic.canvasToLocalPoint(dp.position);
dataPoints[j].x = localPoint.x; dataPoints[j].x = localPoint.x;
dataPoints[j].y = localPoint.y; dataPoints[j].y = localPoint.y;

View File

@ -122,8 +122,11 @@
<q-drawer show-if-above bordered v-model="rightDrawerOpen" side="right"> <q-drawer show-if-above bordered v-model="rightDrawerOpen" side="right">
<q-resize-observer @resize="onRightResize" /> <q-resize-observer @resize="onRightResize" />
<!-- drawer content --> <axleCounting-config
<draw-properties></draw-properties> v-if="showGenerateAxleCountingConfig"
@close="closeGenerateAxleCountingConfig"
/>
<draw-properties v-else></draw-properties>
</q-drawer> </q-drawer>
<q-page-container> <q-page-container>
@ -189,6 +192,7 @@ import {
findContainDevice, findContainDevice,
handleCentralizedStationsData, handleCentralizedStationsData,
} from 'src/graphics/concentrationDividingLine/ConcentrationDividingLineUtils'; } from 'src/graphics/concentrationDividingLine/ConcentrationDividingLineUtils';
import AxleCountingConfig from 'src/components/draw-app/properties/AxleCountingConfig.vue';
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
@ -358,10 +362,14 @@ function oneClickSeparator() {
.getDrawAssistant(Separator.Type) as SeparatorDraw; .getDrawAssistant(Separator.Type) as SeparatorDraw;
separatorDraw.oneGenerates(); separatorDraw.oneGenerates();
} }
const showGenerateAxleCountingConfig = ref(false);
const closeGenerateAxleCountingConfig = () => {
showGenerateAxleCountingConfig.value = false;
};
function oneClickAxleCounting() { function oneClickAxleCounting() {
// //
drawStore.oneClickType = 'AxleCounting'; showGenerateAxleCountingConfig.value = true;
drawStore.getDrawApp().interactionPlugin(OneClickGenerate.Type).resume();
} }
function oneClickTurnoutSection() { function oneClickTurnoutSection() {

View File

@ -15,7 +15,13 @@
<img :src="NCC" style="width: 80px" /> <img :src="NCC" style="width: 80px" />
</div> </div>
<q-toolbar-title> 西安NCC调度辅助决策系统 </q-toolbar-title> <q-toolbar-title> 西安NCC调度辅助决策系统 </q-toolbar-title>
<!-- <q-btn
v-show="route.path.includes('line/monitor')"
color="info"
label="故障查询"
class="q-mr-sm"
@click="openFaultQueryDialog()"
/> -->
<q-btn <q-btn
v-show="route.path.includes('line/monitor')" v-show="route.path.includes('line/monitor')"
color="info" color="info"
@ -40,11 +46,45 @@
<div class="q-gutter-sm row items-center no-wrap"> <div class="q-gutter-sm row items-center no-wrap">
<q-btn <q-btn
v-show="route.path.includes('line/monitor/')" v-show="showBackMonitor"
color="info" color="info"
label="返回" label="返回"
@click="backConfirm" @click="backConfirm"
/> />
<q-btn
round
dense
flat
:color="lineStore.faultStatistics ? 'white' : 'red'"
:icon="lineStore.faultStatistics ? 'grid_on' : 'grid_off'"
@click="
() => {
lineStore.faultStatistics = !lineStore.faultStatistics;
}
"
>
<q-tooltip style="font-size: 14px">
{{
lineStore.faultStatistics
? '关闭故障信息统计'
: '开启故障信息统计'
}}
</q-tooltip>
</q-btn>
<q-btn
round
dense
flat
:color="lineNetStore.handlePlayAble ? 'white' : 'red'"
:icon="lineNetStore.handlePlayAble ? 'alarm_on' : 'alarm_off'"
@click="changeCanPlayAlarmMusic"
>
<q-tooltip style="font-size: 14px">
{{
lineNetStore.handlePlayAble ? '关闭语音报警' : '开启语音报警'
}}
</q-tooltip>
</q-btn>
<q-btn <q-btn
round round
dense dense
@ -54,6 +94,9 @@
@click="$q.fullscreen.toggle()" @click="$q.fullscreen.toggle()"
v-if="$q.screen.gt.sm" v-if="$q.screen.gt.sm"
> >
<q-tooltip style="font-size: 14px">
{{ $q.fullscreen.isActive ? '关闭全屏' : '开启全屏' }}
</q-tooltip>
</q-btn> </q-btn>
<q-btn <q-btn
flat flat
@ -62,7 +105,9 @@
icon="connected_tv" icon="connected_tv"
:color="lineNetStore.connectButtonColor" :color="lineNetStore.connectButtonColor"
@click="openConnectInfoDialog" @click="openConnectInfoDialog"
/> >
<q-tooltip style="font-size: 14px">与同方连接状态</q-tooltip>
</q-btn>
<q-btn-dropdown <q-btn-dropdown
flat flat
stretch stretch
@ -98,11 +143,11 @@
</q-scroll-area> </q-scroll-area>
</q-page-container> </q-page-container>
</q-layout> </q-layout>
<commonAlarm v-if="route.path.includes('alarmList')" /> <commonAlarm v-if="route.path.includes('alarmInfo')" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted } from 'vue'; import { ref, reactive, onMounted, onUnmounted, computed, watch } from 'vue';
import SysMenu from 'src/components/SysMenu.vue'; import SysMenu from 'src/components/SysMenu.vue';
import { useRouter, useRoute } from 'vue-router'; import { useRouter, useRoute } from 'vue-router';
import { Dialog, DialogChainObject, useQuasar } from 'quasar'; import { Dialog, DialogChainObject, useQuasar } from 'quasar';
@ -124,12 +169,28 @@ import {
webSocketConnect, webSocketConnect,
closeWebSocketConnect, closeWebSocketConnect,
} from 'src/components/webSocketConnect'; } from 'src/components/webSocketConnect';
import { logout } from 'src/api/UserApi';
import { ApiError } from 'src/boot/axios';
import { useUserStore } from 'src/stores/user-store';
import { getMonitorPath } from 'src/router/routes';
import FaultQueryDialog from 'src/components/dialog/FaultQueryDialog.vue';
const leftDrawerOpen = ref(false); const leftDrawerOpen = ref(false);
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
const lineStore = useLineStore(); const lineStore = useLineStore();
const lineNetStore = useLineNetStore(); const lineNetStore = useLineNetStore();
watch(
() => route.path,
() => {
if (!route.path.includes('line/monitor') && faultQueryDialogInstance) {
faultQueryDialogInstance.hide();
faultQueryDialogInstance = null;
}
}
);
function toggleLeftDrawer() { function toggleLeftDrawer() {
leftDrawerOpen.value = !leftDrawerOpen.value; leftDrawerOpen.value = !leftDrawerOpen.value;
onResize(); onResize();
@ -153,6 +214,14 @@ function onLeftResize(size: { width: number; height: number }) {
leftDrawerSize.height = size.height; leftDrawerSize.height = size.height;
} }
const showBackMonitor = computed(() => {
const userStore = useUserStore();
const isShow =
route.path.includes('line/monitor/') &&
getMonitorPath(userStore.roles).lineType == 'NCC';
return isShow;
});
const watchInteract = () => { const watchInteract = () => {
lineNetStore.playAble = true; lineNetStore.playAble = true;
document.removeEventListener('click', watchInteract); document.removeEventListener('click', watchInteract);
@ -168,6 +237,14 @@ onMounted(() => {
socket = webSocketConnect(destination, handler); socket = webSocketConnect(destination, handler);
}); });
let faultQueryDialogInstance: DialogChainObject | null = null;
function openFaultQueryDialog() {
if (faultQueryDialogInstance) return;
faultQueryDialogInstance = $q.dialog({
component: FaultQueryDialog,
});
}
// //
const $q = useQuasar(); const $q = useQuasar();
function openSetAlarmMockDialog() { function openSetAlarmMockDialog() {
@ -210,9 +287,18 @@ function logOut() {
message: '确认是否登出?', message: '确认是否登出?',
cancel: true, cancel: true,
persistent: true, persistent: true,
}).onOk(() => { }).onOk(async () => {
try {
await logout();
clearJwtToken(); clearJwtToken();
router.push({ name: 'login' }); router.push({ name: 'login' });
} catch (err) {
const apiErr = err as ApiError;
$q.notify({
type: 'negative',
message: apiErr.title,
});
}
}); });
} }
@ -241,4 +327,8 @@ function resetFn() {
}); });
}); });
} }
function changeCanPlayAlarmMusic() {
lineNetStore.handlePlayAble = !lineNetStore.handlePlayAble;
}
</script> </script>

View File

@ -44,6 +44,13 @@
lazy-rules lazy-rules
:rules="[(val) => val >= 0 || '请选择线路ID']" :rules="[(val) => val >= 0 || '请选择线路ID']"
/> />
<q-select
dense
label="线路类型"
v-model="filter.lineType"
:options="searchOptionsLineType"
style="width: 100px"
/>
<q-input <q-input
dense dense
v-model="filter.beginDateTime" v-model="filter.beginDateTime"
@ -237,6 +244,8 @@ import {
webSocketConnect, webSocketConnect,
closeWebSocketConnect, closeWebSocketConnect,
} from 'src/components/webSocketConnect'; } from 'src/components/webSocketConnect';
import { getMonitorPath } from 'src/router/routes';
import { useUserStore } from 'src/stores/user-store';
const $q = useQuasar(); const $q = useQuasar();
const lineNetStore = useLineNetStore(); const lineNetStore = useLineNetStore();
@ -246,6 +255,7 @@ const props = withDefaults(
}>(), }>(),
{ sizeHeight: 500 } { sizeHeight: 500 }
); );
const userStore = useUserStore();
const tableHeight = computed(() => { const tableHeight = computed(() => {
return props.sizeHeight - 32; return props.sizeHeight - 32;
@ -271,6 +281,13 @@ const columnDefs: QTableColumn[] = [
field: 'lineId', field: 'lineId',
align: 'center', align: 'center',
}, },
{
name: 'lineType',
label: '线路类型',
field: 'lineType',
required: true,
align: 'center',
},
{ {
name: 'alertObject', name: 'alertObject',
label: '设备', label: '设备',
@ -334,7 +351,11 @@ async function onRequest(props: any) {
lineId: filter.value.lineId, lineId: filter.value.lineId,
}); });
} }
if (filter.value.lineType !== '全部') {
Object.assign(params, {
lineType: filter.value.lineType,
});
}
if (filter.value.alertType !== '全部') { if (filter.value.alertType !== '全部') {
Object.assign(params, { Object.assign(params, {
alertType: (saveAlertTypeData as never)[filter.value.alertType], alertType: (saveAlertTypeData as never)[filter.value.alertType],
@ -369,10 +390,16 @@ async function onRequest(props: any) {
onMounted(() => { onMounted(() => {
queryLineInfo(); queryLineInfo();
destinations = getMonitorPath(userStore.roles).destinations;
setTimeout(() => { setTimeout(() => {
tableRef.value.requestServerInteraction(); tableRef.value.requestServerInteraction();
lineNetStore.alarmInfoListTable = tableRef.value; lineNetStore.alarmInfoListTable = tableRef.value;
socket = webSocketConnect(destination, handler); destinations.forEach((destination) => {
allSocketsAndDestinations.push({
socket: webSocketConnect(destination, handler),
destination,
});
});
}); });
}); });
@ -386,8 +413,12 @@ watch(
); );
function updateSelect() { function updateSelect() {
const config = getMonitorPath(userStore.roles);
for (let i = 0; i < selected.value.length; i++) { for (let i = 0; i < selected.value.length; i++) {
if (selected.value[i].alarmStatus !== -1) { const canSelect =
config.lineType == selected.value[i].lineType &&
config.lineIds.includes(+selected.value[i].lineId);
if (selected.value[i].alarmStatus !== -1 || !canSelect) {
selected.value.splice(i, 1); selected.value.splice(i, 1);
i--; i--;
} }
@ -419,6 +450,7 @@ function batchHandle() {
const filter = ref({ const filter = ref({
alertType: '全部', alertType: '全部',
lineId: 0, lineId: 0,
lineType: '全部',
beginDateTime: '', beginDateTime: '',
endDateTime: '', endDateTime: '',
alertStatus: 999, alertStatus: 999,
@ -427,6 +459,7 @@ const filter = ref({
const optionsLineId = ref<{ label: string; value: number }[]>([ const optionsLineId = ref<{ label: string; value: number }[]>([
{ label: '全部', value: 0 }, { label: '全部', value: 0 },
]); ]);
const searchOptionsLineType = ['全部', 'NCC', 'OCC'];
async function queryLineInfo() { async function queryLineInfo() {
try { try {
let response = await pageQuery({ let response = await pageQuery({
@ -465,6 +498,8 @@ const optionsAlertType = [
'列车信号故障', '列车信号故障',
'联锁区红光带', '联锁区红光带',
'联锁区橙光带', '联锁区橙光带',
'应急触发',
'道岔挤岔',
]; ];
// //
@ -532,6 +567,7 @@ function openAlarmDialog(row: any) {
row.alert_time = row.alertTime; row.alert_time = row.alertTime;
row.alert_type = row.alertType; row.alert_type = row.alertType;
row.line_id = row.lineId; row.line_id = row.lineId;
row.line_type = row.lineType;
row.alert_object = row.alertObject; row.alert_object = row.alertObject;
row.alert_tip_id = row.alertTipId; row.alert_tip_id = row.alertTipId;
row.alert_location_id = row.alertLocationId; row.alert_location_id = row.alertLocationId;
@ -551,15 +587,20 @@ function openAlarmDialog(row: any) {
}); });
} }
let socket: StompMessagingClient | null = null; let allSocketsAndDestinations: {
const destination = '/queue/xian/ncc/alert'; socket: StompMessagingClient;
destination: string;
}[] = [];
let destinations: string[] = [];
function handler(message: Uint8Array) { function handler(message: Uint8Array) {
const storage = alert.NccAlertInfoMessage.deserialize(message); const storage = alert.NccAlertInfoMessage.deserialize(message);
lineNetStore.setAlarmInfo(storage.messages as []); lineNetStore.setAlarmInfo(storage.messages as []);
} }
onUnmounted(() => { onUnmounted(() => {
closeWebSocketConnect(socket, destination); allSocketsAndDestinations.forEach((info) => {
closeWebSocketConnect(info.socket, info.destination);
});
}); });
// //

294
src/pages/AlarmRecord.vue Normal file
View File

@ -0,0 +1,294 @@
<template>
<div class="q-pa-md">
<q-table
ref="tableRef"
title="报警记录"
:style="{ height: tableHeight + 'px' }"
class="my-sticky-virtscroll-table"
:rows="rows"
:columns="columnDefs"
row-key="id"
v-model:pagination="pagination"
:rows-per-page-options="[10, 20, 50, 100]"
:loading="loading"
binary-state-sort
@request="onRequest"
>
<template v-slot:top-right>
<q-input
dense
class="q-mr-md"
debounce="1000"
v-model="filter.name"
label="操作人"
></q-input>
<q-input
v-model="filter.beginDate"
label="开始时间"
debounce="1000"
class="q-mr-md"
dense
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="filter.beginDate" mask="YYYY-MM-DD HH:mm:ss">
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append>
<q-icon name="access_time" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-time
v-model="filter.beginDate"
mask="YYYY-MM-DD HH:mm:ss"
format24h
with-seconds
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="Close" color="primary" flat />
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-input
v-model="filter.endDate"
label="截止时间"
debounce="1000"
class="q-mr-md"
dense
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="filter.endDate" mask="YYYY-MM-DD HH:mm:ss">
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append>
<q-icon name="access_time" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-time
v-model="filter.endDate"
mask="YYYY-MM-DD HH:mm:ss"
format24h
with-seconds
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
</template>
<!-- <template v-slot:body-cell-subEventType="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip outline size="sm" color="primary">
{{ getSubEventType(props.row.subEventType) }}
</q-chip>
</div>
</q-td>
</template> -->
<template v-slot:body-cell-requestSuccess="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip outline size="sm" color="primary">
{{ props.row.requestSuccess === 1 ? '连接' : '断开' }}
</q-chip>
</div>
</q-td>
</template>
<!-- <template v-slot:top-right>
<q-input
dense
debounce="1000"
v-model="filter.name"
label="用户名"
></q-input>
<q-btn flat round color="primary" icon="search" />
</template> -->
<!-- <template v-slot:body-cell-roles="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip
outline
size="sm"
color="primary"
v-for="(item, index) in props.row.roleList"
:key="index"
>
{{ item.roleName }}
</q-chip>
</div>
</q-td>
</template> -->
<!-- <template v-slot:body-cell-operations="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-btn
color="primary"
label="编辑角色"
:disable="operateDisabled"
@click="edieUserData(props.row)"
/>
</div>
</q-td>
</template> -->
</q-table>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue';
import { type QTableColumn } from 'quasar';
import { pageQuery, Record } from '../api/LogApi';
import { errorNotify } from '../utils/CommonNotify';
// const $q = useQuasar(); useQuasar
const props = withDefaults(
defineProps<{
sizeHeight: number;
}>(),
{ sizeHeight: 500 }
);
const tableHeight = computed(() => {
return props.sizeHeight - 32;
});
onMounted(() => {
tableRef.value.requestServerInteraction();
});
const columnDefs: QTableColumn[] = [
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
{
name: 'lineId',
label: '线路ID',
field: 'lineId',
align: 'center',
},
{
name: 'faceName',
label: '接口名称',
field: 'faceName',
align: 'center',
},
{
name: 'userName',
label: '操作人员',
field: 'userName',
align: 'center',
},
{
name: 'createDateTime',
label: '记录时间',
field: 'createDateTime',
align: 'center',
},
{
name: 'requestSuccess',
label: '连接断开',
field: 'requestSuccess',
align: 'center',
},
];
const tableRef = ref();
const rows = reactive([]);
const filter = reactive({
name: '',
beginDate: '',
endDate: '',
});
const loading = ref(false);
const pagination = ref({
sortBy: 'desc',
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 10,
});
// eslint-disable-next-line
async function onRequest(props: any) {
const { page, rowsPerPage, sortBy, descending } = props.pagination;
loading.value = true;
try {
let response = await pageQuery({
current: page,
size: rowsPerPage,
logType: 'WARN',
name: filter.name,
beginDate: filter.beginDate,
endDate: filter.endDate,
});
pagination.value.rowsNumber = response.total;
pagination.value.page = page;
pagination.value.rowsPerPage = rowsPerPage;
pagination.value.sortBy = sortBy;
pagination.value.descending = descending;
rows.splice(0, rows.length, ...(response.records as []));
} catch (error: any) {
errorNotify('获取数据失败', error);
} finally {
loading.value = false;
}
}
function getSubEventType(type: string) {
switch (type) {
case 'LOGIN':
return '登录';
case 'LOGOUT':
return '登出';
case 'QUERY':
return '查询';
case 'SAVE_OR_UPDATE':
return '保存';
case 'DELETE':
return '删除';
case 'WARN':
return '报警';
default:
return '';
}
}
function searchQuery() {
tableRef.value.requestServerInteraction();
}
</script>

View File

@ -0,0 +1,372 @@
<template>
<div class="q-pa-md">
<q-table
ref="tableRef"
title="权限接口列表"
:style="{ height: tableHeight + 'px' }"
class="my-sticky-virtscroll-table"
:rows="rows"
:columns="columnDefs"
row-key="id"
v-model:pagination="pagination"
:rows-per-page-options="[10, 20, 50, 100]"
:loading="loading"
:filter="filter"
:selection="isRole ? 'multiple' : 'none'"
v-model:selected="selected"
@update:selected="tableSelected"
:selected-rows-label="getSelectedString"
binary-state-sort
@request="onRequest"
>
<template v-slot:top-right>
<q-input
dense
debounce="1000"
v-model="filter.name"
label="名称"
></q-input>
<q-btn flat round color="primary" icon="search" />
<q-btn
v-if="!isRole"
color="primary"
label="新建"
@click="editFormShow = true"
/>
</template>
<template v-slot:header-selection="scope">
<q-checkbox v-model="scope.selected" />
</template>
<template v-slot:body-selection="scope">
<q-checkbox v-model="scope.selected" />
</template>
<template v-slot:body-cell-operations="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-btn
color="primary"
label="编辑"
@click="edieAuthData(props.row)"
/>
<q-btn
color="red"
:disable="operateDisabled"
label="删除"
@click="deleteAuthData(props.row)"
/>
</div>
</q-td>
</template>
</q-table>
<q-dialog
v-model="editFormShow"
persistent
transition-show="scale"
transition-hide="scale"
>
<q-card style="width: 300px">
<q-card-section>
<q-form
ref="myForm"
@submit="edieAuthPath"
@reset="onReset"
class="q-gutter-md"
>
<div class="text-h6">{{ pathInfo.id ? '修改' : '新建' }}</div>
<q-input outlined label="名称" v-model="pathInfo.name" />
<q-input outlined label="接口" v-model="pathInfo.path" />
<q-select
outlined
v-model="pathInfo.methodList"
:options="options"
multiple
map-options
emit-value
label="方法"
lazy-rules
:rules="[(val) => val.length > 0 || '请选择方法!']"
></q-select>
<q-card-actions align="right">
<q-btn color="primary" label="保存" type="submit" />
<q-btn label="取消" type="reset" v-close-popup />
</q-card-actions>
</q-form>
</q-card-section>
</q-card>
</q-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed, watch } from 'vue';
import { useQuasar, type QTableColumn, QForm } from 'quasar';
import {
createPath,
deletePath,
pageQueryPath,
PathItem,
savePathData,
} from '../api/AuthApi';
import { successNotify } from '../utils/CommonNotify';
import { ApiError } from 'src/boot/axios';
import { MethodType } from 'src/components/AuthData';
import { useRoute } from 'vue-router';
const $q = useQuasar();
interface SelectItem {
id: number;
}
const props = withDefaults(
defineProps<{
sizeHeight: number;
selects?: PathItem[];
}>(),
{ sizeHeight: 500, selects: () => [] }
);
const tableHeight = computed(() => {
return props.sizeHeight - 32;
});
onMounted(() => {
tableRef.value.requestServerInteraction();
selected.value = props.selects;
});
const columnDefs: QTableColumn[] = [
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
{
name: 'name',
label: '权限接口名称',
field: 'name',
required: true,
align: 'center',
},
{
name: 'path',
label: '接口路径',
field: 'path',
required: true,
align: 'center',
},
{
name: 'method',
label: '方法',
field: (row) => {
return getMethodName(row.method);
},
align: 'center',
},
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
];
const operateDisabled = ref(false);
const tableRef = ref();
const rows = reactive([]);
const filter = reactive({
name: '',
});
const loading = ref(false);
const pagination = ref({
sortBy: 'desc',
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 10,
});
// eslint-disable-next-line
async function onRequest(props: any) {
const { page, rowsPerPage, sortBy, descending } = props.pagination;
const filter = props.filter;
loading.value = true;
try {
let response = await pageQueryPath({
name: filter.name,
current: page,
size: rowsPerPage,
});
pagination.value.rowsNumber = response.total;
pagination.value.page = page;
pagination.value.rowsPerPage = rowsPerPage;
pagination.value.sortBy = sortBy;
pagination.value.descending = descending;
rows.splice(0, rows.length, ...(response.records as []));
} catch (err) {
const error = err as ApiError;
$q.notify({
type: 'negative',
message: error.title,
});
} finally {
loading.value = false;
}
}
const editFormShow = ref(false);
interface PathInfo extends Omit<PathItem, 'id' | 'method'> {
id: string;
methodList: MethodType[];
}
const pathInfo = reactive<PathInfo>({
id: '',
methodList: [],
name: '',
path: '',
});
const options = computed(() => {
const list: { label: string; value: string }[] = [];
for (let item in MethodType) {
const obj = {
label: item,
value: MethodType[item as MethodType],
};
list.push(obj);
}
return list;
});
//
function edieAuthData(row: PathItem) {
pathInfo.id = row.id + '';
pathInfo.name = row.name;
pathInfo.path = row.path;
let list: MethodType[] = [];
if (row.method == '*') {
list = options.value.map((item) => item.value as MethodType);
} else {
list = row.method.split(',') as MethodType[];
}
pathInfo.methodList = list;
editFormShow.value = true;
}
const myForm = ref<QForm | null>(null);
//
async function edieAuthPath() {
myForm.value?.validate().then(async (res) => {
if (res) {
operateDisabled.value = true;
try {
let method = pathInfo.methodList.join(',');
const everyM = options.value.every((item) => {
return pathInfo.methodList.includes(item.value as MethodType);
});
if (everyM) {
method = '*';
}
const params = {
name: pathInfo.name,
path: pathInfo.path,
method: method,
};
if (pathInfo.id) {
const cloneParams = Object.assign(params, { id: +pathInfo.id });
await savePathData(cloneParams);
} else {
await createPath(params);
}
onReset();
tableRef.value.requestServerInteraction(); //
editFormShow.value = false;
successNotify('保存成功!');
} catch (err) {
const error = err as ApiError;
$q.notify({
type: 'negative',
message: error.title,
});
} finally {
operateDisabled.value = false;
}
}
});
}
function deleteAuthData(row: PathItem) {
operateDisabled.value = true;
$q.dialog({
title: '确认',
message: `确认删除权限接口 "${row.name}" 吗?`,
cancel: true,
})
.onOk(async () => {
try {
await deletePath(row.id);
tableRef.value.requestServerInteraction(); //
} catch (err) {
const error = err as ApiError;
$q.notify({
type: 'negative',
message: error.title,
});
}
})
.onDismiss(() => {
operateDisabled.value = false;
});
}
function onReset() {
pathInfo.id = '';
pathInfo.name = '';
pathInfo.methodList = [];
pathInfo.path = '';
myForm.value?.resetValidation();
}
function getMethodName(val: string) {
let name = val;
if (val == '*') {
const list = options.value.map((item) => item.value);
name = list.join(',');
}
return name;
}
const route = useRoute();
const isRole = computed(() => {
//
return route.path.includes('/sysManage/role');
});
const selected = ref<SelectItem[]>([]);
function getSelectedString() {
const nameArr = selected.value.map((item) => {
return item.id;
});
const name = nameArr.join('');
return `已选ID${name}`;
}
if (isRole.value) {
const index = columnDefs.findIndex((item) => {
return item.name == 'operations';
});
if (index >= 0) {
columnDefs.splice(index, 1);
}
}
const emit = defineEmits(['selectsed']);
function tableSelected() {
emit('selectsed', selected.value);
}
watch(
() => props.selects,
(val) => {
selected.value = val.map((item) => {
return { id: item.id };
});
}
);
</script>

View File

@ -27,13 +27,48 @@
</q-td> </q-td>
</template> </template>
<template v-slot:top-right> <template v-slot:top-right>
<q-btn <q-form ref="myForm" @submit="searchDecisionInfo" style="width: 100%">
class="q-mr-md" <div class="q-gutter-md q-mt-none row justify-center items-start">
color="primary" <q-select
label="查询" dense
@click="openSearchDialog" v-model="filter.lineId"
:options="searchOptionsLineId"
emit-value
map-options
options-dense
label="线路ID"
style="width: 75px"
no-error-icon
lazy-rules
:rules="[(val) => val >= 0 || '请选择线路ID']"
/> />
<q-btn color="primary" label="新建" @click="createFormShow = true" /> <q-select
dense
label="线路类型"
v-model="filter.lineType"
:options="searchOptionsLineType"
style="width: 100px"
/>
<q-select
dense
label="故障类型"
v-model="filter.alertType"
:options="searchOptionsAlertType"
style="width: 130px"
/>
<q-input
dense
v-model="filter.areaConfigName"
label="区域名称"
></q-input>
<q-btn color="primary" label="查询" type="submit" />
<q-btn
color="primary"
label="新建"
@click="createFormShow = true"
/>
</div>
</q-form>
</template> </template>
<template v-slot:body-cell-operations="props"> <template v-slot:body-cell-operations="props">
@ -73,6 +108,23 @@
<div class="text-h6"> <div class="text-h6">
{{ creatForm.id ? '编辑决策信息' : '新建决策信息' }} {{ creatForm.id ? '编辑决策信息' : '新建决策信息' }}
</div> </div>
<q-select
outlined
label="线路ID"
v-model="creatForm.lineId"
:options="optionsLineId"
emit-value
map-options
options-dense
lazy-rules
:rules="[(val) => val > 0 || '请选择线路ID']"
/>
<q-select
outlined
label="线路类型"
v-model="creatForm.lineType"
:options="optionsLineType"
/>
<q-select <q-select
outlined outlined
label="故障类型" label="故障类型"
@ -111,44 +163,12 @@
</q-card-section> </q-card-section>
<q-card-actions align="right"> <q-card-actions align="right">
<q-btn color="primary" label="创建" type="submit" /> <q-btn color="primary" label="确定" type="submit" />
<q-btn label="取消" type="reset" v-close-popup /> <q-btn label="取消" type="reset" v-close-popup />
</q-card-actions> </q-card-actions>
</q-form> </q-form>
</q-card> </q-card>
</q-dialog> </q-dialog>
<q-dialog
v-model="searchDialog"
persistent
transition-show="scale"
transition-hide="scale"
>
<q-card style="width: 300px">
<q-card-section>
<div class="text-h6">查询决策信息</div>
</q-card-section>
<q-card-section>
<q-select
outlined
label="故障类型"
v-model="filter.alertType"
:options="optionsAlertType"
class="q-mb-md"
/>
<q-input
outlined
v-model="filter.areaConfigName"
label="区域名称"
></q-input>
</q-card-section>
<q-card-actions align="right">
<q-btn color="primary" label="确定" @click="searchDecisionInfo()" />
<q-btn label="取消" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
</div> </div>
</template> </template>
@ -169,6 +189,7 @@ import {
} from 'src/components/alarm/alarmInfoEnum'; } from 'src/components/alarm/alarmInfoEnum';
import { ApiError } from 'src/boot/axios'; import { ApiError } from 'src/boot/axios';
import { ShowTipTimeConfig, TipTimeConfig } from 'src/api/AlarmTipTimeConfig'; import { ShowTipTimeConfig, TipTimeConfig } from 'src/api/AlarmTipTimeConfig';
import { pageQuery } from 'src/api/LineInfoApi';
const $q = useQuasar(); const $q = useQuasar();
@ -191,6 +212,20 @@ const columnDefs: QTableColumn[] = [
required: true, required: true,
align: 'center', align: 'center',
}, },
{
name: 'lineId',
label: '线路',
field: 'lineId',
required: true,
align: 'center',
},
{
name: 'lineType',
label: '线路类型',
field: 'lineType',
required: true,
align: 'center',
},
{ {
name: 'alertType', name: 'alertType',
label: '故障类型', label: '故障类型',
@ -255,16 +290,42 @@ const pagination = ref({
rowsNumber: 10, rowsNumber: 10,
}); });
const filter = ref({
alertType: '全部',
areaConfigName: '',
lineId: 0,
lineType: '全部',
});
const onRequest: QTable['onRequest'] = async (props) => { const onRequest: QTable['onRequest'] = async (props) => {
const { page, rowsPerPage, sortBy, descending } = props.pagination; const { page, rowsPerPage, sortBy, descending } = props.pagination;
loading.value = true; loading.value = true;
try { try {
let response = await alarmInfoPageQuery({ const params = {
current: page, current: page,
size: rowsPerPage, size: rowsPerPage,
};
if (filter.value.lineId !== 0) {
Object.assign(params, {
lineId: filter.value.lineId,
});
}
if (filter.value.lineType !== '全部') {
Object.assign(params, {
lineType: filter.value.lineType,
});
}
if (filter.value.alertType !== '全部') {
Object.assign(params, {
alertType: (saveAlertTypeData as never)[filter.value.alertType], alertType: (saveAlertTypeData as never)[filter.value.alertType],
});
}
if (filter.value.areaConfigName) {
Object.assign(params, {
areaConfigName: filter.value.areaConfigName, areaConfigName: filter.value.areaConfigName,
}); });
}
let response = await alarmInfoPageQuery(params);
const pageData = response; const pageData = response;
pagination.value.rowsNumber = pageData.total; pagination.value.rowsNumber = pageData.total;
pagination.value.page = page; pagination.value.page = page;
@ -283,22 +344,13 @@ const onRequest: QTable['onRequest'] = async (props) => {
}; };
onMounted(() => { onMounted(() => {
queryLineInfo();
setTimeout(() => { setTimeout(() => {
tableRef.value.requestServerInteraction(); tableRef.value.requestServerInteraction();
}); });
}); });
const searchDialog = ref(false);
const filter = ref({
alertType: '',
areaConfigName: '',
});
function openSearchDialog() {
filter.value = { alertType: '', areaConfigName: '' };
searchDialog.value = true;
}
function searchDecisionInfo() { function searchDecisionInfo() {
searchDialog.value = false;
tableRef.value.requestServerInteraction(); tableRef.value.requestServerInteraction();
} }
@ -306,6 +358,8 @@ const createFormShow = ref(false);
const myForm = ref<QForm | null>(null); const myForm = ref<QForm | null>(null);
const creatForm = reactive({ const creatForm = reactive({
id: '', id: '',
lineId: '',
lineType: 'NCC',
alertType: '', alertType: '',
tipTimeIds: [], tipTimeIds: [],
areaConfigId: '', areaConfigId: '',
@ -313,6 +367,30 @@ const creatForm = reactive({
submissionInfo: '', submissionInfo: '',
}); });
const optionsLineId = ref<{ label: string; value: number }[]>([]);
const searchOptionsLineId = ref<{ label: string; value: number }[]>([
{ label: '全部', value: 0 },
]);
async function queryLineInfo() {
try {
let response = await pageQuery({
current: 1,
size: 50,
});
response.records.forEach((info) => {
optionsLineId.value.push({ label: info.name, value: info.lineId });
searchOptionsLineId.value.push({ label: info.name, value: info.lineId });
});
} catch (err) {
const error = err as ApiError;
$q.notify({
type: 'negative',
message: error.title,
});
}
}
const optionsLineType = ['NCC', 'OCC'];
const searchOptionsLineType = ['全部', ...optionsLineType];
const optionsAlertType = [ const optionsAlertType = [
'蓝显', '蓝显',
'全线蓝显', '全线蓝显',
@ -333,13 +411,24 @@ const optionsAlertType = [
'联锁区红光带', '联锁区红光带',
'联锁区橙光带', '联锁区橙光带',
'联锁区失表', '联锁区失表',
'应急触发',
'道岔挤岔',
'zc联锁故障',
'列车定位丢失',
'列车完整性',
'列车故障救援',
'ats卡滞',
]; ];
const searchOptionsAlertType = ['全部', ...optionsAlertType];
let optionsLocationType = ref<string[]>([]); let optionsLocationType = ref<string[]>([]);
let optionsLocationList: AreaConfigItem[] = []; let optionsLocationList: AreaConfigItem[] = [];
async function searchLocationType() { async function searchLocationType() {
try { try {
const alertType = (saveAlertTypeData as never)[creatForm.alertType]; const alertType = (saveAlertTypeData as never)[creatForm.alertType];
optionsLocationList = await getDeviceAreaByAlarmType(3, alertType); optionsLocationList = await getDeviceAreaByAlarmType(
+creatForm.lineId,
alertType
);
optionsLocationType.value = optionsLocationList.map( optionsLocationType.value = optionsLocationList.map(
(item) => item.areaName (item) => item.areaName
); );
@ -372,6 +461,8 @@ function onCreate() {
}); });
const params = { const params = {
id: +creatForm.id, id: +creatForm.id,
lineId: +creatForm.lineId,
lineType: creatForm.lineType,
alertType: (saveAlertTypeData as never)[creatForm.alertType], alertType: (saveAlertTypeData as never)[creatForm.alertType],
tipTimeIds: tipTimeIds, tipTimeIds: tipTimeIds,
areaConfigId: areaConfigId as number, areaConfigId: areaConfigId as number,
@ -403,6 +494,8 @@ function onCreate() {
function editData(row: AlarmInfoListItem) { function editData(row: AlarmInfoListItem) {
creatForm.id = row.id + ''; creatForm.id = row.id + '';
creatForm.lineId = row.lineId + '';
creatForm.lineType = row.lineType;
creatForm.alertType = (showAlertTypeData as never)[row.alertType + '']; creatForm.alertType = (showAlertTypeData as never)[row.alertType + ''];
creatForm.tipTimeIds = row.timeConfigList?.map( creatForm.tipTimeIds = row.timeConfigList?.map(
(timeConfig) => (ShowTipTimeConfig as never)[timeConfig.timeType + ''] (timeConfig) => (ShowTipTimeConfig as never)[timeConfig.timeType + '']
@ -440,6 +533,8 @@ async function deleteData(row: AlarmInfoListItem) {
function onReset() { function onReset() {
creatForm.id = ''; creatForm.id = '';
creatForm.lineId = '';
creatForm.lineType = 'NCC';
creatForm.alertType = ''; creatForm.alertType = '';
creatForm.tipTimeIds = []; creatForm.tipTimeIds = [];
creatForm.areaConfigId = ''; creatForm.areaConfigId = '';

View File

@ -21,7 +21,7 @@
v-model="filter.name" v-model="filter.name"
label="名称" label="名称"
></q-input> ></q-input>
<q-btn flat round color="primary" icon="search" /> <q-btn flat round color="primary" icon="search" @click="searchQuery" />
<q-btn color="primary" label="新建" @click="createFormShow = true" /> <q-btn color="primary" label="新建" @click="createFormShow = true" />
</template> </template>
@ -362,4 +362,7 @@ async function deleteData(row: any) {
operateDisabled.value = false; operateDisabled.value = false;
}); });
} }
function searchQuery() {
tableRef.value.requestServerInteraction();
}
</script> </script>

View File

@ -0,0 +1,533 @@
<template>
<q-tabs
v-model="tab"
dense
active-color="primary"
indicator-color="primary"
align="justify"
narrow-indicator
>
<q-tab
v-for="(item, index) in tabList"
:key="index"
:name="item.value"
:label="item.label"
/>
</q-tabs>
<q-separator />
<q-tab-panel name="info">
<div class="occContainer" v-if="roleType == 'OCC'">
<q-table
ref="tableRef"
row-key="id"
v-model:pagination="pagination"
:loading="loading"
:rows="rows"
:columns="columns"
@request="onRequest"
:rows-per-page-options="[10, 20, 50, 100]"
:filter="filter"
class="left"
>
<template v-slot:top-right>
<q-form ref="myForm" style="width: 100%">
<div class="q-gutter-md q-mt-none row justify-center items-start">
<q-select
dense
label="故障类型"
v-model="filter.faultType"
emit-value
map-options
:options="searchOptionsFaultType"
style="min-width: 130px"
/>
<q-input
dense
:label="inputSearchName"
v-model="filter.faultName"
lazy-rules
/>
<q-btn
flat
round
color="primary"
icon="search"
@click="searchTable"
/>
</div>
</q-form>
</template>
<template v-slot:body="props">
<q-tr
:props="props"
:class="{ changeBackground: props.row.id === clickRowInfo.id }"
@click="handleRowClick(props.row)"
>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
class="custom-column"
@mouseover="onMouseOver"
@mouseleave="showTooltip = false"
>
{{ col.value }}
<q-tooltip v-if="showTooltip" anchor="bottom middle">
<div class="message-tip">
{{ col.value }}
</div>
</q-tooltip>
</q-td>
</q-tr>
</template>
</q-table>
<q-scroll-area class="right">
<div class="detaiRow">
<div class="text">
<span class="textHead">故障类型</span> {{
clickRowInfo.faultType
}}
</div>
<div class="text">
<span class="textHead"> {{ showTitle.faultNameShower }}</span
>{{ clickRowInfo.faultNameShower }}
</div>
<q-card class="box-card">
<div class="head">{{ showTitle.faultDriverShower }}</div>
<q-separator />
<div>
<div class="detail">{{ clickRowInfo.faultDriverShower }}</div>
</div>
</q-card>
<q-card class="box-card">
<div class="head">{{ showTitle.resultMsg }}</div>
<q-separator />
<div>
<div class="detail">{{ clickRowInfo.resultMsg }}</div>
</div>
</q-card>
</div>
</q-scroll-area>
</div>
<div v-else class="nccContainer">
<q-btn-toggle
v-model="selectMenuName"
toggle-color="primary"
:options="menuOption"
@update:model-value="selectedMenu"
class="q-btn-toggle"
/>
<q-card
class="box-card"
v-for="nccData in showNccData"
:key="nccData.action"
>
<div class="head">{{ nccData.action }}</div>
<q-separator />
<div class="detail">
<div v-for="data in nccData.datas" :key="data">{{ data }}</div>
</div>
</q-card>
</div>
</q-tab-panel>
</template>
<script setup lang="ts">
import { reactive, ref, computed, onMounted, watch } from 'vue';
import { QTable, useQuasar } from 'quasar';
import {
FaultQueryListItem,
faultQueryPageQuery,
faultQueryType,
FaultTypeItem,
NccFaultQueryListItem,
nccFaultQueryPageQuery,
} from 'src/api/faultQuery';
import { getMonitorPath } from 'src/router/routes';
import { useUserStore } from 'src/stores/user-store';
const props = withDefaults(
defineProps<{
sizeHeight: number;
sizeWidth: number;
}>(),
{ sizeHeight: 500, sizeWidth: 500 }
);
const $q = useQuasar();
const tab = ref('GUIDE');
const tableTitle = reactive({
faultNameShower: '故障现象',
faultDriverShower: '司机处理结果',
});
const inputSearchName = ref('故障现象');
watch(tab, (tabVal) => {
if (tabVal == 'GUIDE') {
inputSearchName.value = '故障现象';
tableTitle.faultNameShower = '故障现象';
tableTitle.faultDriverShower = '司机处理结果';
} else {
inputSearchName.value = '故障名称';
tableTitle.faultNameShower = '故障名称';
tableTitle.faultDriverShower = '故障现象';
}
handleSelectFaultType();
});
const tabList = ref();
const tableRef = ref<QTable>();
const columns = computed(() => [
{
name: 'id',
label: '编号',
field: 'id',
required: true,
align: 'center',
},
{
name: 'lineId',
label: '线路',
field: 'lineId',
required: true,
align: 'center',
},
{
name: 'faultType',
label: '故障类型',
field: (row: FaultQueryListItem) => {
if (row.faultType) {
return getFaultTypeName(row);
}
},
align: 'center',
},
{
name: 'faultNameShower',
label: tableTitle.faultNameShower,
field: 'faultNameShower',
required: true,
align: 'center',
},
{
name: 'faultDriverShower',
label: tableTitle.faultDriverShower,
field: 'faultDriverShower',
required: true,
align: 'center',
},
]);
const rows = reactive([]);
const loading = ref(false);
const pagination = ref({
sortBy: 'desc',
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 10,
});
const filter = reactive({
lineId: 0,
faultType: '',
faultName: '',
});
const onRequest: QTable['onRequest'] = async (props) => {
const { page, rowsPerPage } = props.pagination;
loading.value = true;
try {
const params = {
current: page,
size: rowsPerPage,
};
if (filter.lineId !== 0) {
Object.assign(params, {
lineId: filter.lineId,
});
}
if (filter.faultType !== '') {
Object.assign(params, {
faultType: filter.faultType,
});
}
if (filter.faultName !== '') {
Object.assign(params, {
faultName: filter.faultName,
});
}
let resp = await faultQueryPageQuery(params);
pagination.value.page = resp.current;
pagination.value.rowsNumber = resp.total;
pagination.value.rowsPerPage = resp.size;
rows.splice(0, rows.length, ...(resp.records as []));
if (rows.length) {
handleRowClick(rows[0]);
} else {
clickRowInfo.faultType = '';
clickRowInfo.faultNameShower = '';
clickRowInfo.faultDriverShower = '';
clickRowInfo.resultMsg = '';
}
} catch (err) {
$q.notify({
type: 'negative',
message: '无法获取范围列表',
});
} finally {
loading.value = false;
}
};
const clickRowInfo = reactive({
id: 0,
faultType: '',
faultNameShower: '',
faultDriverShower: '',
resultMsg: '',
});
const showTitle = reactive({
faultNameShower: '',
faultDriverShower: '',
resultMsg: '',
});
function handleRowClick(row: FaultQueryListItem) {
if (row.faultType.includes('FAULT_EMERGENCY_GUIDE')) {
showTitle.faultNameShower = '故障现象';
showTitle.faultDriverShower = '司机处理结果';
showTitle.resultMsg = '行调提醒司机关键点';
} else {
showTitle.faultNameShower = '故障名称';
showTitle.faultDriverShower = '故障现象';
showTitle.resultMsg = '退出服务地点';
}
clickRowInfo.id = row?.id as number;
clickRowInfo.faultType = getFaultTypeName(row) as string;
clickRowInfo.faultNameShower = row.faultNameShower;
clickRowInfo.faultDriverShower = row.faultDriverShower;
clickRowInfo.resultMsg = row.resultMsg;
}
async function queryAllFaultType() {
try {
allOptionsFaultType = await faultQueryType();
handleSelectFaultType();
} catch (err) {
$q.notify({
type: 'negative',
message: '无法获取指定线路的故障类型配置',
});
}
}
let allOptionsFaultType: FaultTypeItem[] = [];
function getFaultTypeName(row: FaultQueryListItem) {
for (let i = 0; i < allOptionsFaultType.length; i++) {
if (allOptionsFaultType[i].lineId == row.lineId) {
const fts = allOptionsFaultType[i].fts;
for (let j = 0; i < fts.length; j++) {
if (fts[j].faultType == row.faultType) {
return fts[j].typeName;
}
}
}
}
}
const searchOptionsFaultType = ref([{ label: '全部', value: '' }]);
function handleSelectFaultType() {
let allType = '';
searchOptionsFaultType.value = [{ label: '全部', value: '' }];
for (let i = 0; i < allOptionsFaultType.length; i++) {
if (allOptionsFaultType[i].lineId == filter.lineId) {
allOptionsFaultType[i].fts.forEach((item) => {
if (
(tab.value == 'GUIDE' &&
item.faultType.includes('FAULT_EMERGENCY_GUIDE')) ||
(tab.value == 'SERVICE' &&
item.faultType.includes('FAULT_EXIT_SERVICE'))
) {
searchOptionsFaultType.value.push({
label: item.typeName,
value: item.faultType,
});
if (allType == '') {
allType = item.faultType;
} else {
allType = allType + ',' + item.faultType;
}
}
});
break;
}
}
filter.faultType = allType;
searchOptionsFaultType.value[0].value = allType;
}
function searchTable() {
tableRef.value?.requestServerInteraction();
}
//ncc
const nccDatas = ref<NccFaultQueryListItem[]>();
const selectMenuName = ref('');
const menuOption = ref<
{
label: string;
value: string;
}[]
>([]);
const showNccData = ref<{ action: string; datas: string[] }[]>();
function selectedMenu(name: string) {
showNccData.value = nccDatas.value?.find(
(nccData) => nccData.nccTypeName == name
)?.nccData;
}
async function nccFaultQueryPageQueryFn() {
try {
nccDatas.value = await nccFaultQueryPageQuery();
nccDatas.value.forEach((nccDta) =>
menuOption.value.push({
label: nccDta.nccTypeName,
value: nccDta.nccTypeName,
})
);
selectMenuName.value = nccDatas.value[0].nccTypeName;
showNccData.value = nccDatas.value[0].nccData;
} catch (err) {
$q.notify({
type: 'negative',
message: '无法获取ncc故障查询',
});
}
}
const showTooltip = ref(false);
function onMouseOver(e: MouseEvent) {
const target = e.target as HTMLElement;
if (target.scrollWidth > target.clientWidth) {
showTooltip.value = true;
}
}
const userStore = useUserStore();
const roleType = ref('');
onMounted(() => {
const config = getMonitorPath(userStore.roles);
if (config.lineType == 'NCC') {
roleType.value = 'NCC';
tabList.value = [
{
label: 'ncc应急处置流程',
value: 'NCC',
},
];
tab.value = 'NCC';
nccFaultQueryPageQueryFn();
} else {
roleType.value = 'OCC';
tabList.value = [
{
label: '故障指导',
value: 'GUIDE',
},
{
label: '退出服务',
value: 'SERVICE',
},
];
filter.lineId = config.lineIds[0];
queryAllFaultType();
}
});
</script>
<style lang='scss' scoped>
.changeBackground {
background-color: #31ccec;
}
.custom-column {
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.message-tip {
width: 300px;
overflow: auto;
line-height: 22px;
white-space: pre-wrap;
font-size: 14px;
}
.button-container {
display: flex;
justify-content: center;
margin-top: 10px;
}
.occContainer {
display: flex;
height: calc(100vh - 120px);
.left {
width: 67%;
}
.right {
flex: 1;
height: 100%;
.detaiRow {
margin: 10px 0 0 20px;
.text {
width: 450px;
word-wrap: break-word;
margin-bottom: 10px;
font-size: 18px;
.textHead {
font-weight: 600;
}
}
.box-card {
width: 98%;
height: calc(50vh - 115px);
margin-bottom: 10px;
padding: 0 5px;
.head {
padding: 5px 5px;
font-size: 20px;
font-weight: 600;
}
.detail {
margin-bottom: 10px;
padding: 5px 5px;
line-height: 28px;
white-space: pre-wrap;
font-size: 20px;
}
}
}
}
}
.nccContainer {
.q-btn-toggle {
margin-bottom: 15px;
}
.box-card {
width: 98%;
min-height: 150px;
margin-bottom: 15px;
padding: 0 5px;
.head {
padding: 5px 5px;
font-size: 20px;
font-weight: 600;
}
.detail {
margin-bottom: 10px;
padding: 5px 5px;
line-height: 28px;
white-space: pre-wrap;
font-size: 20px;
}
}
}
</style>

View File

@ -0,0 +1,501 @@
<template>
<div class="q-pa-md">
<q-table
ref="tableRef"
title="故障查询"
:style="{ height: tableHeight + 'px' }"
:rows="rows"
:columns="columnDefs"
row-key="id"
v-model:pagination="pagination"
:rows-per-page-options="[10, 20, 50, 100]"
:loading="loading"
binary-state-sort
@request="onRequest"
>
<template v-slot:body-cell="props">
<q-td :props="props" class="custom-column">
{{ props.value }}
<q-tooltip
anchor="bottom middle"
v-if="props.value && props.value.length > 20"
>
<div class="message-tip">
{{ props.value }}
</div>
</q-tooltip>
</q-td>
</template>
<template v-slot:top-right>
<q-form ref="myForm" @submit="searchDecisionInfo" style="width: 100%">
<div class="q-gutter-md q-mt-none row justify-center items-start">
<q-select
dense
v-model="filter.lineId"
:options="searchOptionsLineId"
emit-value
map-options
options-dense
label="线路ID"
style="width: 75px"
no-error-icon
lazy-rules
@update:model-value="handleSelectSearchLineId"
:rules="[(val) => val >= 0 || '请选择线路ID']"
/>
<q-select
dense
label="故障类型"
v-model="filter.faultType"
emit-value
map-options
:options="searchOptionsFaultType"
style="min-width: 130px"
/>
<q-btn color="primary" label="查询" type="submit" />
<q-btn
color="primary"
label="新建"
@click="createFormShow = true"
/>
</div>
</q-form>
</template>
<template v-slot:body-cell-operations="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-btn
color="primary"
:disable="operateDisabled"
label="编辑"
@click="editData(props.row)"
/>
<q-btn
color="red"
:disable="operateDisabled"
label="删除"
@click="deleteData(props.row)"
/>
</div>
</q-td>
</template>
</q-table>
<q-dialog
v-model="createFormShow"
persistent
transition-show="scale"
transition-hide="scale"
>
<q-card style="width: 500px">
<q-form
ref="myForm"
@submit="onCreate"
@reset="onReset"
class="q-gutter-md"
>
<q-card-section class="q-gutter-sm">
<div class="text-h6">
{{ creatForm.id ? '编辑故障查询' : '新建故障查询' }}
</div>
<q-select
outlined
label="线路ID"
v-model="creatForm.lineId"
:options="optionsLineId"
emit-value
map-options
lazy-rules
@update:model-value="handleSelectLineId"
:rules="[(val) => val > 0 || '请选择线路ID']"
/>
<q-select
outlined
label="故障类型"
v-model="creatForm.faultType"
:options="optionsFaultType"
emit-value
map-options
:rules="[(val) => val.length > 0 || '请选择故障类型!']"
/>
<q-input
outlined
label="消息名称(故障现象)"
v-model="creatForm.faultNameShower"
lazy-rules
:rules="[(val) => val.length > 0 || '请输入消息名称!']"
/>
<q-input
outlined
type="textarea"
label="司机处理结果(服务故障现象)"
v-model="creatForm.faultDriverShower"
lazy-rules
:rules="[(val) => val.length > 0 || '请输入司机处理结果!']"
/>
<q-input
outlined
type="textarea"
label="司机关键点(退出服务地点)"
v-model="creatForm.resultMsg"
lazy-rules
:rules="[(val) => val.length > 0 || '请输入司机关键点!']"
/>
</q-card-section>
<q-card-actions align="right">
<q-btn color="primary" label="确定" type="submit" />
<q-btn label="取消" type="reset" v-close-popup />
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue';
import { useQuasar, type QTableColumn, QForm, QTable } from 'quasar';
import {
faultQueryPageQuery,
deleteFaultQueryById,
createFaultQuery,
FaultQueryListItem,
faultQueryType,
FaultTypeItem,
} from '../api/faultQuery';
import { ApiError } from 'src/boot/axios';
import { pageQuery } from 'src/api/LineInfoApi';
const $q = useQuasar();
const props = withDefaults(
defineProps<{
sizeHeight: number;
}>(),
{ sizeHeight: 500 }
);
const tableHeight = computed(() => {
return props.sizeHeight - 32;
});
const columnDefs: QTableColumn[] = [
{
name: 'id',
label: '编号',
field: 'id',
required: true,
align: 'center',
},
{
name: 'lineId',
label: '线路',
field: 'lineId',
required: true,
align: 'center',
},
{
name: 'faultType',
label: '故障类型',
field: (row) => {
if (row.faultType) {
return getFaultTypeName(row);
}
},
align: 'center',
},
{
name: 'faultNameShower',
label: '消息名称(故障现象)',
field: 'faultNameShower',
required: true,
align: 'center',
},
{
name: 'faultDriverShower',
label: '司机处理结果(服务故障现象)',
field: 'faultDriverShower',
required: true,
align: 'center',
},
{
name: 'resultMsg',
label: '司机关键点(退出服务地点)',
field: 'resultMsg',
required: true,
align: 'center',
},
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
];
const operateDisabled = ref(false);
const tableRef = ref();
const rows = reactive([]);
const loading = ref(false);
const pagination = ref({
sortBy: 'desc',
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 10,
});
const filter = ref({
faultType: '',
lineId: 0,
});
const onRequest: QTable['onRequest'] = async (props) => {
const { page, rowsPerPage, sortBy, descending } = props.pagination;
loading.value = true;
try {
const params = {
current: page,
size: rowsPerPage,
};
if (filter.value.lineId !== 0) {
Object.assign(params, {
lineId: filter.value.lineId,
});
}
if (filter.value.faultType!=='') {
Object.assign(params, {
faultType: filter.value.faultType,
});
}
let response = await faultQueryPageQuery(params);
const pageData = response;
pagination.value.rowsNumber = pageData.total;
pagination.value.page = page;
pagination.value.rowsPerPage = rowsPerPage;
pagination.value.sortBy = sortBy;
pagination.value.descending = descending;
rows.splice(0, rows.length, ...(pageData.records as []));
} catch (err) {
$q.notify({
type: 'negative',
message: '无法获取故障查询列表',
});
} finally {
loading.value = false;
}
};
onMounted(() => {
queryLineInfo();
queryAllFaultType();
setTimeout(() => {
tableRef.value.requestServerInteraction();
});
});
function searchDecisionInfo() {
tableRef.value.requestServerInteraction();
}
const createFormShow = ref(false);
const myForm = ref<QForm | null>(null);
const creatForm = reactive({
id: '',
lineId: '',
faultType: '',
faultNameShower: '',
faultDriverShower: '',
resultMsg: '',
});
const optionsLineId = ref<{ label: string; value: number }[]>([]);
const searchOptionsLineId = ref<{ label: string; value: number }[]>([
{ label: '全部', value: 0 },
]);
async function queryLineInfo() {
try {
let response = await pageQuery({
current: 1,
size: 50,
});
response.records.forEach((info) => {
optionsLineId.value.push({ label: info.name, value: info.lineId });
searchOptionsLineId.value.push({ label: info.name, value: info.lineId });
});
} catch (err) {
const error = err as ApiError;
$q.notify({
type: 'negative',
message: error.title,
});
}
}
let allOptionsFaultType: FaultTypeItem[] = [];
let optionsFaultType = ref<{ label: string; value: string }[]>([]);
async function queryAllFaultType() {
try {
allOptionsFaultType = await faultQueryType();
handleSelectAllFaultType();
} catch (err) {
$q.notify({
type: 'negative',
message: '无法获取指定线路的故障类型配置',
});
}
}
function getFaultTypeName(row: FaultQueryListItem) {
for (let i = 0; i < allOptionsFaultType.length; i++) {
if (allOptionsFaultType[i].lineId == row.lineId) {
const fts = allOptionsFaultType[i].fts;
for (let j = 0; i < fts.length; j++) {
if (fts[j].faultType == row.faultType) {
return fts[j].typeName;
}
}
}
}
}
function handleSelectLineId() {
optionsFaultType.value = [];
creatForm.faultType = '';
for (let i = 0; i < allOptionsFaultType.length; i++) {
if (allOptionsFaultType[i].lineId == +creatForm.lineId) {
allOptionsFaultType[i].fts.forEach((item) => {
optionsFaultType.value.push({
label: item.typeName,
value: item.faultType,
});
});
break;
}
}
}
const searchOptionsFaultType = ref<{ label: string; value: string }[]>([
{ label: '全部', value: '' },
]);
function handleSelectSearchLineId() {
filter.value.faultType = '';
searchOptionsFaultType.value = [{ label: '全部', value: '' }];
if (filter.value.lineId == 0) {
handleSelectAllFaultType();
}
for (let i = 0; i < allOptionsFaultType.length; i++) {
if (allOptionsFaultType[i].lineId == filter.value.lineId) {
allOptionsFaultType[i].fts.forEach((item) => {
searchOptionsFaultType.value.push({
label: item.typeName,
value: item.faultType,
});
});
break;
}
}
}
function handleSelectAllFaultType() {
allOptionsFaultType.forEach((faultTypeOption) => {
faultTypeOption.fts.forEach((fault) =>
searchOptionsFaultType.value.push({
label: fault.typeName,
value: fault.faultType,
})
);
});
}
function onCreate() {
myForm.value?.validate().then(async (res) => {
if (res) {
operateDisabled.value = true;
try {
const params = {
lineId: +creatForm.lineId,
faultType: creatForm.faultType,
faultNameShower: creatForm.faultNameShower,
faultDriverShower: creatForm.faultDriverShower,
resultMsg: creatForm.resultMsg,
};
if (creatForm.id !== '') {
Object.assign(params, {
id: +creatForm.id,
});
}
await createFaultQuery(params);
onReset();
createFormShow.value = false;
tableRef.value.requestServerInteraction(); //
} catch (err) {
const apiErr = err as ApiError;
$q.notify({
type: 'negative',
message: apiErr.title,
});
} finally {
operateDisabled.value = false;
}
}
});
}
function editData(row: FaultQueryListItem) {
creatForm.id = row.id + '';
creatForm.lineId = row.lineId + '';
creatForm.faultType = row.faultType;
creatForm.faultNameShower = row.faultNameShower;
creatForm.faultDriverShower = row.faultDriverShower;
creatForm.resultMsg = row.resultMsg;
createFormShow.value = true;
}
async function deleteData(row: FaultQueryListItem) {
operateDisabled.value = true;
$q.dialog({
title: '确认',
message: `确认删除编号是"${row.id}"的决策信息吗?`,
cancel: true,
})
.onOk(async () => {
try {
await deleteFaultQueryById(row.id as number);
tableRef.value.requestServerInteraction(); //
} catch (err) {
$q.notify({
type: 'negative',
message: '无法删除决策信息',
});
}
})
.onDismiss(() => {
operateDisabled.value = false;
});
}
function onReset() {
creatForm.id = '';
creatForm.lineId = '';
creatForm.faultType = '';
creatForm.faultNameShower = '';
creatForm.faultDriverShower = '';
creatForm.resultMsg = '';
myForm.value?.resetValidation();
}
</script>
<style scoped>
.custom-column {
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.message-tip {
width: 300px;
max-height: 250px;
overflow: auto;
line-height: 22px;
white-space: pre-wrap;
font-size: 14px;
}
</style>

View File

@ -21,7 +21,7 @@
v-model="filter.name" v-model="filter.name"
label="名称" label="名称"
></q-input> ></q-input>
<q-btn flat round color="primary" icon="search" /> <q-btn flat round color="primary" icon="search" @click="searchQuery" />
<q-btn color="primary" label="新建" @click="createFormShow = true" /> <q-btn color="primary" label="新建" @click="createFormShow = true" />
</template> </template>
@ -267,4 +267,7 @@ function editData(row: any) {
editInfo.config = row.config || ''; editInfo.config = row.config || '';
createFormShow.value = true; createFormShow.value = true;
} }
function searchQuery() {
tableRef.value.requestServerInteraction();
}
</script> </script>

View File

@ -3,14 +3,97 @@
<q-page-container style="padding: 0; overflow: hidden"> <q-page-container style="padding: 0; overflow: hidden">
<div id="line-app-container"></div> <div id="line-app-container"></div>
</q-page-container> </q-page-container>
<div
v-if="faultInfo"
style="
position: absolute;
right: 0;
top: 10px;
background: white;
width: 400px;
"
>
<div style="width: 100%; text-align: right" class="bg-primary q-pa-ms">
<q-icon
name="add_circle"
size="md"
v-if="faultInfoMin"
style="cursor: pointer"
@click="() => (faultInfoMin = false)"
/>
<q-icon
name="remove_circle"
size="md"
v-if="!faultInfoMin"
style="cursor: pointer"
@click="() => (faultInfoMin = true)"
/>
<q-icon
name="cancel"
size="md"
style="cursor: pointer"
@click="() => (faultInfo = false)"
/>
</div>
<div
v-if="!faultInfoMin"
class="q-pa-ms"
style="
background: white;
max-width: 400px;
height: 268px;
overflow-y: scroll;
"
>
<template v-for="(item, index) in timeInfoLabel" :key="index">
<div
class="row justify-between q-ma-sm bg-blue text-white"
style="border-radius: 5px; padding: 5px"
>
<div
style="
max-width: 250px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
>
{{ item.split('--')[0] }}
<q-tooltip>{{ item.split('--')[0] }}</q-tooltip>
</div>
<div>
<span>{{ item.split('--')[1] }}</span>
<q-icon
name="cancel"
size="xs"
style="cursor: pointer; margin-left: 10px"
@click="handleRemoveInfo(index)"
/>
</div>
</div>
<!-- <q-chip
removable
@remove="handleRemoveInfo(index)"
color="primary"
text-color="white"
square
:label="item"
>
<q-tooltip v-if="item.length > 34"> {{ item }} </q-tooltip>
</q-chip> -->
</template>
</div>
</div>
</q-page> </q-page>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, watch, onUnmounted } from 'vue'; import { onMounted, onUnmounted, watch, ref, reactive } from 'vue';
import { useLineStore } from 'src/stores/line-store'; import { useLineStore } from 'src/stores/line-store';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useLineNetStore } from 'src/stores/line-net-store'; import { AlarmInfo, useLineNetStore } from 'src/stores/line-net-store';
import { showAlertTypeData } from 'src/components/alarm/alarmInfoEnum';
import { Platform } from 'src/graphics/platform/Platform';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@ -22,6 +105,11 @@ const props = withDefaults(
const route = useRoute(); const route = useRoute();
const lineStore = useLineStore(); const lineStore = useLineStore();
const lineNetStore = useLineNetStore(); const lineNetStore = useLineNetStore();
const faultInfo = ref(false);
const faultInfoMin = ref(false);
const alarmInfoList: AlarmInfo[] = reactive([]);
let timeInterval = null;
let timeInfoLabel: string[] = reactive([]);
watch( watch(
() => props.sizeHeight, () => props.sizeHeight,
@ -36,13 +124,72 @@ watch(
} }
); );
watch(
() => faultInfo.value,
() => {
if (!faultInfo.value) {
alarmInfoList.splice(0, 1);
timeInfoLabel.splice(0);
timeInterval = null;
} else {
timeInterval = setInterval(() => {
const now = Date.now();
// const labels: string[] = [];
timeInfoLabel.splice(0);
alarmInfoList.forEach((info) => {
const date = info.alert_time.substring(0, 19).replace('T', ' ');
let infoTime = new Date(date).getTime();
console.log(date, new Date(date), infoTime, now, 'now');
const distance = formatTime((now - infoTime) / 1000);
const label = handleShowLabel(info);
timeInfoLabel.push(label + '--' + distance);
});
}, 1000);
}
}
);
watch( watch(
() => lineNetStore.alarmInfo, () => lineNetStore.alarmInfo,
(val) => { (val) => {
if (val.length) { if (val.length) {
centerFaultDevice(); centerFaultDevice();
const lineState = lineNetStore.connectInfo?.msgs.find(
(msg) => msg.lineId == lineId
);
// console.log(lineState, 'line');
if (lineState?.atsWarnShowCounter) {
val.forEach((info) => {
alarmInfoList.push(info);
});
faultInfo.value = true;
} }
} }
}
);
watch(
() => lineNetStore.connectInfo,
(val) => {
if (val?.msgs) {
const lineState = val.msgs.find((msg) => msg.lineId == lineId);
if (!lineState?.atsWarnShowCounter) {
faultInfo.value = false;
}
}
}
);
watch(
() => lineStore.faultStatistics,
() => {
const platfroms = lineStore
.getLineApp()
.queryStore.queryByType<Platform>(Platform.Type);
platfroms.forEach((platfrom) => {
platfrom.changeState();
});
}
); );
const lineId = Number(route.params.lineId); const lineId = Number(route.params.lineId);
@ -80,7 +227,41 @@ function centerFaultDevice() {
} }
} }
function handleShowLabel(alarmInfo: AlarmInfo) {
const type = (showAlertTypeData as never)[alarmInfo.alert_type + ''];
const device = alarmInfo.alert_object.replace(/\[|]/g, '');
return device + '[' + type + ']';
}
function handleRemoveInfo(index: number) {
alarmInfoList.splice(index, 1);
timeInfoLabel.splice(index, 1);
if (!alarmInfoList.length) {
faultInfo.value = false;
}
console.log(alarmInfoList, faultInfo.value);
}
function formatTime(seconds: number) {
//
seconds = Math.floor(seconds);
//
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = (seconds % 3600) % 60;
console.log(hours, minutes, secs, seconds, 'sec');
//
const hours1 = String(hours).padStart(2, '0');
const minutes1 = String(minutes).padStart(2, '0');
const secs1 = String(secs).padStart(2, '0');
//
return `${hours1}:${minutes1}:${secs1}`;
}
onUnmounted(() => { onUnmounted(() => {
lineStore.destroy(); lineStore.cancelSubscribe();
timeInterval = null;
}); });
</script> </script>

292
src/pages/LoginRecord.vue Normal file
View File

@ -0,0 +1,292 @@
<template>
<div class="q-pa-md">
<q-table
ref="tableRef"
title="登录记录"
:style="{ height: tableHeight + 'px' }"
class="my-sticky-virtscroll-table"
:rows="rows"
:columns="columnDefs"
row-key="id"
v-model:pagination="pagination"
:rows-per-page-options="[10, 20, 50, 100]"
:loading="loading"
binary-state-sort
@request="onRequest"
>
<template v-slot:top-right>
<q-input
dense
class="q-mr-md"
debounce="1000"
v-model="filter.name"
label="操作人"
></q-input>
<q-input
v-model="filter.beginDate"
label="开始时间"
debounce="1000"
class="q-mr-md"
dense
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="filter.beginDate" mask="YYYY-MM-DD HH:mm:ss">
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append>
<q-icon name="access_time" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-time
v-model="filter.beginDate"
mask="YYYY-MM-DD HH:mm:ss"
format24h
with-seconds
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="Close" color="primary" flat />
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-input
v-model="filter.endDate"
label="截止时间"
debounce="1000"
class="q-mr-md"
dense
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="filter.endDate" mask="YYYY-MM-DD HH:mm:ss">
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append>
<q-icon name="access_time" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-time
v-model="filter.endDate"
mask="YYYY-MM-DD HH:mm:ss"
format24h
with-seconds
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
</template>
<template v-slot:body-cell-subEventType="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip outline size="sm" color="primary">
{{ getSubEventType(props.row.subEventType) }}
</q-chip>
</div>
</q-td>
</template>
<template v-slot:body-cell-requestSuccess="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip outline size="sm" color="primary">
{{ props.row.requestSuccess === 1 ? '成功' : '失败' }}
</q-chip>
</div>
</q-td>
</template>
<!-- <template v-slot:top-right>
<q-input
dense
debounce="1000"
v-model="filter.name"
label="用户名"
></q-input>
<q-btn flat round color="primary" icon="search" />
</template> -->
<!-- <template v-slot:body-cell-roles="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip
outline
size="sm"
color="primary"
v-for="(item, index) in props.row.roleList"
:key="index"
>
{{ item.roleName }}
</q-chip>
</div>
</q-td>
</template> -->
<!-- <template v-slot:body-cell-operations="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-btn
color="primary"
label="编辑角色"
:disable="operateDisabled"
@click="edieUserData(props.row)"
/>
</div>
</q-td>
</template> -->
</q-table>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue';
import { type QTableColumn } from 'quasar';
import { pageQuery, Record } from '../api/LogApi';
import { errorNotify } from '../utils/CommonNotify';
// const $q = useQuasar(); useQuasar
const props = withDefaults(
defineProps<{
sizeHeight: number;
}>(),
{ sizeHeight: 500 }
);
const tableHeight = computed(() => {
return props.sizeHeight - 32;
});
onMounted(() => {
tableRef.value.requestServerInteraction();
});
const columnDefs: QTableColumn[] = [
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
{
name: 'subEventType',
label: '操作',
field: 'subEventType',
align: 'center',
},
{
name: 'faceName',
label: '接口名称',
field: 'faceName',
align: 'center',
},
{
name: 'userName',
label: '操作人员',
field: 'userName',
align: 'center',
},
{
name: 'createDateTime',
label: '记录时间',
field: 'createDateTime',
align: 'center',
},
{
name: 'requestSuccess',
label: '请求成功',
field: 'requestSuccess',
align: 'center',
},
];
const tableRef = ref();
const rows = reactive([]);
const filter = reactive({
name: '',
beginDate: '',
endDate: '',
});
const loading = ref(false);
const pagination = ref({
sortBy: 'desc',
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 10,
});
// eslint-disable-next-line
async function onRequest(props: any) {
const { page, rowsPerPage, sortBy, descending } = props.pagination;
loading.value = true;
try {
let response = await pageQuery({
current: page,
size: rowsPerPage,
logType: 'LOGIN',
name: filter.name,
beginDate: filter.beginDate,
endDate: filter.endDate,
});
pagination.value.rowsNumber = response.total;
pagination.value.page = page;
pagination.value.rowsPerPage = rowsPerPage;
pagination.value.sortBy = sortBy;
pagination.value.descending = descending;
rows.splice(0, rows.length, ...(response.records as []));
} catch (error: any) {
errorNotify('获取数据失败', error);
} finally {
loading.value = false;
}
}
function getSubEventType(type: string) {
switch (type) {
case 'LOGIN':
return '登录';
case 'LOGOUT':
return '登出';
case 'QUERY':
return '查询';
case 'SAVE_OR_UPDATE':
return '保存';
case 'DELETE':
return '删除';
default:
return '';
}
}
function searchQuery() {
tableRef.value.requestServerInteraction();
}
</script>

View File

@ -7,9 +7,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, watch, onUnmounted } from 'vue'; import { onMounted, onUnmounted, watch } from 'vue';
import { useLineNetStore } from 'src/stores/line-net-store'; import { useLineNetStore } from 'src/stores/line-net-store';
import { RunLine } from 'src/graphics/runLine/RunLine';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
const props = withDefaults( const props = withDefaults(
@ -35,13 +34,10 @@ watch(
} }
); );
watch( watch(
() => lineNetStore.selectedGraphic, () => lineNetStore.jumpLineCount,
(val) => { (val) => {
if (val && lineNetStore.selectedGraphicType == RunLine.Type) { if (val) {
const lineId = (val as RunLine)?.datas.lineId; router.replace(`/line/monitor/${lineNetStore.jumpLineId}`);
if (lineId) {
router.replace(`/line/monitor/${lineId}`);
}
} }
} }
); );
@ -74,6 +70,6 @@ onMounted(() => {
}); });
onUnmounted(() => { onUnmounted(() => {
lineNetStore.destroy(); lineNetStore.cancelSubscribe();
}); });
</script> </script>

292
src/pages/OperateRecord.vue Normal file
View File

@ -0,0 +1,292 @@
<template>
<div class="q-pa-md">
<q-table
ref="tableRef"
title="操作记录"
:style="{ height: tableHeight + 'px' }"
class="my-sticky-virtscroll-table"
:rows="rows"
:columns="columnDefs"
row-key="id"
v-model:pagination="pagination"
:rows-per-page-options="[10, 20, 50, 100]"
:loading="loading"
binary-state-sort
@request="onRequest"
>
<template v-slot:top-right>
<q-input
dense
class="q-mr-md"
debounce="1000"
v-model="filter.name"
label="操作人"
></q-input>
<q-input
v-model="filter.beginDate"
label="开始时间"
debounce="1000"
class="q-mr-md"
dense
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="filter.beginDate" mask="YYYY-MM-DD HH:mm:ss">
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append>
<q-icon name="access_time" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-time
v-model="filter.beginDate"
mask="YYYY-MM-DD HH:mm:ss"
format24h
with-seconds
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="Close" color="primary" flat />
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-input
v-model="filter.endDate"
label="截止时间"
debounce="1000"
class="q-mr-md"
dense
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-date v-model="filter.endDate" mask="YYYY-MM-DD HH:mm:ss">
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append>
<q-icon name="access_time" class="cursor-pointer">
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
>
<q-time
v-model="filter.endDate"
mask="YYYY-MM-DD HH:mm:ss"
format24h
with-seconds
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="关闭" color="primary" flat />
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-btn flat round color="primary" icon="search" @click="searchQuery" />
</template>
<template v-slot:body-cell-subEventType="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip outline size="sm" color="primary">
{{ getSubEventType(props.row.subEventType) }}
</q-chip>
</div>
</q-td>
</template>
<template v-slot:body-cell-requestSuccess="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip outline size="sm" color="primary">
{{ props.row.requestSuccess === 1 ? '成功' : '失败' }}
</q-chip>
</div>
</q-td>
</template>
<!-- <template v-slot:top-right>
<q-input
dense
debounce="1000"
v-model="filter.name"
label="用户名"
></q-input>
<q-btn flat round color="primary" icon="search" />
</template> -->
<!-- <template v-slot:body-cell-roles="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip
outline
size="sm"
color="primary"
v-for="(item, index) in props.row.roleList"
:key="index"
>
{{ item.roleName }}
</q-chip>
</div>
</q-td>
</template> -->
<!-- <template v-slot:body-cell-operations="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-btn
color="primary"
label="编辑角色"
:disable="operateDisabled"
@click="edieUserData(props.row)"
/>
</div>
</q-td>
</template> -->
</q-table>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue';
import { type QTableColumn } from 'quasar';
import { pageQuery, Record } from '../api/LogApi';
import { errorNotify } from '../utils/CommonNotify';
// const $q = useQuasar();
const props = withDefaults(
defineProps<{
sizeHeight: number;
}>(),
{ sizeHeight: 500 }
);
const tableHeight = computed(() => {
return props.sizeHeight - 32;
});
onMounted(() => {
tableRef.value.requestServerInteraction();
});
const columnDefs: QTableColumn[] = [
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
{
name: 'subEventType',
label: '操作',
field: 'subEventType',
align: 'center',
},
{
name: 'faceName',
label: '接口名称',
field: 'faceName',
align: 'center',
},
{
name: 'userName',
label: '操作人员',
field: 'userName',
align: 'center',
},
{
name: 'createDateTime',
label: '记录时间',
field: 'createDateTime',
align: 'center',
},
{
name: 'requestSuccess',
label: '请求成功',
field: 'requestSuccess',
align: 'center',
},
];
const tableRef = ref();
const rows = reactive([]);
const filter = reactive({
name: '',
beginDate: '',
endDate: '',
});
const loading = ref(false);
const pagination = ref({
sortBy: 'desc',
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 10,
});
// eslint-disable-next-line
async function onRequest(props: any) {
const { page, rowsPerPage, sortBy, descending } = props.pagination;
loading.value = true;
try {
let response = await pageQuery({
current: page,
size: rowsPerPage,
logType: 'OPERATE',
name: filter.name,
beginDate: filter.beginDate,
endDate: filter.endDate,
});
pagination.value.rowsNumber = response.total;
pagination.value.page = page;
pagination.value.rowsPerPage = rowsPerPage;
pagination.value.sortBy = sortBy;
pagination.value.descending = descending;
rows.splice(0, rows.length, ...(response.records as []));
} catch (error: any) {
errorNotify('获取数据失败', error);
} finally {
loading.value = false;
}
}
function searchQuery() {
tableRef.value.requestServerInteraction();
}
function getSubEventType(type: string) {
switch (type) {
case 'LOGIN':
return '登录';
case 'LOGOUT':
return '登出';
case 'QUERY':
return '查询';
case 'SAVE_OR_UPDATE':
return '保存';
case 'DELETE':
return '删除';
default:
return '';
}
}
</script>

View File

@ -21,7 +21,7 @@
v-model="filter.name" v-model="filter.name"
label="名称" label="名称"
></q-input> ></q-input>
<q-btn flat round color="primary" icon="search" /> <q-btn flat round color="primary" icon="search" @click="searchQuery" />
</template> </template>
<template v-slot:body-cell-operations="props"> <template v-slot:body-cell-operations="props">
@ -183,4 +183,7 @@ async function deleteData(row: any) {
operateDisabled.value = false; operateDisabled.value = false;
}); });
} }
function searchQuery() {
tableRef.value.requestServerInteraction();
}
</script> </script>

208
src/pages/RoleManage.vue Normal file
View File

@ -0,0 +1,208 @@
<template>
<div class="q-pa-md">
<q-table
ref="tableRef"
title="角色列表"
:style="{ height: tableHeight + 'px' }"
class="my-sticky-virtscroll-table"
:rows="rows"
:columns="columnDefs"
row-key="id"
v-model:pagination="pagination"
:rows-per-page-options="[10, 20, 50, 100]"
:loading="loading"
:filter="filter"
binary-state-sort
@request="onRequest"
>
<template
v-if="userStore.defaultRole == 'ADMIN'"
v-slot:body-cell-operations="props"
>
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-btn
:disable="operateDisabled"
color="primary"
label="配置"
@click="edieRoleData(props.row)"
/>
</div>
</q-td>
</template>
</q-table>
<q-dialog
v-model="editFormShow"
persistent
transition-show="scale"
transition-hide="scale"
>
</q-dialog>
<q-dialog
v-model="editFormShow"
persistent
transition-show="scale"
transition-hide="scale"
>
<q-card style="width: 300px">
<q-card-section>
<q-form
ref="myForm"
@submit="roleConfigFn"
@reset="onReset"
class="q-gutter-md"
>
<div class="text-h6">配置角色信息</div>
<q-input outlined disable label="角色" v-model="roleInfo.name" />
<q-input outlined label="配置" v-model="roleInfo.config" />
<q-card-actions align="right">
<q-btn color="primary" label="保存" type="submit" />
<q-btn label="取消" type="reset" v-close-popup />
</q-card-actions>
</q-form>
</q-card-section>
</q-card>
</q-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue';
import { useQuasar, type QTableColumn, QForm } from 'quasar';
import { pageQueryRole, roleConfig, RoleInfo } from 'src/api/AuthApi';
import { ApiError } from 'src/boot/axios';
import { successNotify } from 'src/utils/CommonNotify';
import { useUserStore } from 'src/stores/user-store';
const $q = useQuasar();
const props = withDefaults(
defineProps<{
sizeHeight: number;
}>(),
{ sizeHeight: 500 }
);
const tableHeight = computed(() => {
return props.sizeHeight - 32;
});
const userStore = useUserStore();
onMounted(() => {
if (userStore.defaultRole == 'ADMIN') {
columnDefs.push({
name: 'operations',
label: '操作',
field: 'operations',
align: 'center',
});
}
tableRef.value.requestServerInteraction();
});
const columnDefs: QTableColumn[] = [
{ name: 'id', label: '角色ID', field: 'id', align: 'center' },
{
name: 'name',
label: '角色名称',
field: 'name',
required: true,
align: 'center',
},
];
const tableRef = ref();
const rows = reactive([]);
const filter = reactive({
name: '',
});
const loading = ref(false);
const pagination = ref({
sortBy: 'desc',
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 10,
});
// eslint-disable-next-line
async function onRequest(props: any) {
const { page, rowsPerPage, sortBy, descending } = props.pagination;
const filter = props.filter;
loading.value = true;
try {
let response = await pageQueryRole({
name: filter.name,
current: page,
size: rowsPerPage,
});
pagination.value.rowsNumber = response.total;
pagination.value.page = page;
pagination.value.rowsPerPage = rowsPerPage;
pagination.value.sortBy = sortBy;
pagination.value.descending = descending;
rows.splice(0, rows.length, ...(response.records as []));
} catch (err) {
const error = err as ApiError;
$q.notify({
type: 'negative',
message: error.title,
});
} finally {
loading.value = false;
}
}
//
interface RoleItemInfo extends Omit<RoleInfo, 'id'> {
id: string;
editPaths: { id: number }[];
roleConfigStr: string;
}
const roleInfo = reactive<RoleItemInfo>({
id: '',
editPaths: [],
name: '',
resList: [],
roleConfigStr: '',
});
function edieRoleData(row: RoleInfo) {
roleInfo.id = row.id + '';
roleInfo.name = row.name;
roleInfo.roleConfigStr=row.roleConfigStr
editFormShow.value = true;
}
const operateDisabled = ref(false);
const myForm = ref<QForm | null>(null);
const editFormShow = ref(false);
function roleConfigFn() {
myForm.value?.validate().then(async (res) => {
if (res) {
operateDisabled.value = true;
try {
await roleConfig(+roleInfo.id, roleInfo.roleConfigStr);
editFormShow.value = false;
successNotify('修改成功');
} catch (err) {
const error = err as ApiError;
$q.notify({
type: 'negative',
message: error.title,
});
} finally {
operateDisabled.value = false;
}
}
});
}
function onReset() {
roleInfo.id = '';
roleInfo.name = '';
roleInfo.roleConfigStr = '';
myForm.value?.resetValidation();
}
</script>

View File

@ -24,8 +24,7 @@
label="账号" label="账号"
lazy-rules lazy-rules
type="tel" type="tel"
mask="###########" :rules="[(val) => val.length || '请输入账号!']"
:rules="[(val) => val.length == 11 || '请输入正确手机格式!']"
/> />
<q-input <q-input
@ -36,9 +35,9 @@
lazy-rules lazy-rules
/> />
<div class="text-right"> <!-- <div class="text-right">
<q-btn flat label="注册" to="/register" color="primary" /> <q-btn flat label="注册" to="/register" color="primary" />
</div> </div> -->
<div class="text-center"> <div class="text-center">
<q-btn label="登录" type="submit" color="primary" /> <q-btn label="登录" type="submit" color="primary" />
@ -55,13 +54,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import { ApiError } from 'src/boot/axios'; import { ApiError } from 'src/boot/axios';
import { login } from 'src/api/UserApi'; import { getUserInfo, login } from 'src/api/UserApi';
import { clearJwtToken, saveJwtToken } from 'src/configs/TokenManage'; import { clearJwtToken, saveJwtToken } from 'src/configs/TokenManage';
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useUserStore } from 'src/stores/user-store';
import { handleRefreshToken } from 'src/utils/refreshToken';
import { getMonitorPath } from 'src/router/routes';
const $q = useQuasar(); const $q = useQuasar();
const router = useRouter(); const router = useRouter();
const userStore = useUserStore();
const loginInfo = reactive({ const loginInfo = reactive({
account: '', account: '',
@ -74,7 +77,15 @@ async function doLogin() {
clearJwtToken(); clearJwtToken();
const token = await login(loginInfo); const token = await login(loginInfo);
saveJwtToken(token); saveJwtToken(token);
router.push({ name: 'home' }); const userInfo = await getUserInfo();
userStore.roles = userInfo.roles;
userStore.defaultRole = userInfo.defaultRole;
userStore.remainingSecond = userInfo.remainingSecond;
setTimeout(
() => handleRefreshToken(),
userInfo.remainingSecond * 1000 - 10000
);
router.replace(getMonitorPath(userInfo.roles).monitorPath);
} catch (err) { } catch (err) {
visible.value = false; visible.value = false;
const apiErr = err as ApiError; const apiErr = err as ApiError;

View File

@ -22,18 +22,89 @@
v-model="filter.name" v-model="filter.name"
label="用户名" label="用户名"
></q-input> ></q-input>
<q-btn flat round color="primary" icon="search" /> <q-btn flat round color="primary" icon="search" @click="searchQuery" />
</template>
<template v-slot:body-cell-roles="props">
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-chip
outline
size="sm"
color="primary"
v-for="(item, index) in props.row.roleList"
:key="index"
>
{{ item.roleName }}
</q-chip>
</div>
</q-td>
</template>
<template
v-if="userStore.defaultRole == 'ADMIN'"
v-slot:body-cell-operations="props"
>
<q-td :props="props">
<div class="q-gutter-sm row justify-center">
<q-btn
color="primary"
label="编辑角色"
:disable="operateDisabled"
@click="edieUserData(props.row)"
/>
</div>
</q-td>
</template> </template>
</q-table> </q-table>
<q-dialog
v-model="editFormShow"
persistent
transition-show="scale"
transition-hide="scale"
>
<q-card style="width: 300px">
<q-card-section>
<q-form
ref="myForm"
@submit="edieUserRole"
@reset="onReset"
class="q-gutter-md"
>
<div class="text-h6">修改用户角色</div>
<q-input outlined disable label="用户名" v-model="userInfo.name" />
<q-select
outlined
v-model="userInfo.Rids"
:options="options"
multiple
map-options
emit-value
label="用户角色"
lazy-rules
:rules="[(val) => val.length > 0 || '请选择角色!']"
></q-select>
<q-card-actions align="right">
<q-btn color="primary" label="保存" type="submit" />
<q-btn label="取消" type="reset" v-close-popup />
</q-card-actions>
</q-form>
</q-card-section>
</q-card>
</q-dialog>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'; import { ref, reactive, onMounted, computed } from 'vue';
import { type QTableColumn } from 'quasar'; import { QForm, useQuasar, type QTableColumn } from 'quasar';
import { pageQuery } from '../api/UserApi'; import { pageQuery, User } from '../api/UserApi';
import { errorNotify } from '../utils/CommonNotify'; import { errorNotify, successNotify } from '../utils/CommonNotify';
import { ApiError } from 'src/boot/axios';
import { pageQueryRole, userLinkRole } from 'src/api/AuthApi';
import { useUserStore } from 'src/stores/user-store';
const $q = useQuasar();
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
sizeHeight: number; sizeHeight: number;
@ -43,9 +114,19 @@ const props = withDefaults(
const tableHeight = computed(() => { const tableHeight = computed(() => {
return props.sizeHeight - 32; return props.sizeHeight - 32;
}); });
const userStore = useUserStore();
onMounted(() => { onMounted(() => {
if (userStore.defaultRole == 'ADMIN') {
columnDefs.push({
name: 'operations',
label: '操作',
field: 'operations',
align: 'center',
});
}
tableRef.value.requestServerInteraction(); tableRef.value.requestServerInteraction();
getAllRole();
}); });
const columnDefs: QTableColumn[] = [ const columnDefs: QTableColumn[] = [
@ -58,15 +139,16 @@ const columnDefs: QTableColumn[] = [
}, },
{ name: 'id', label: '用户ID', field: 'id', align: 'center' }, { name: 'id', label: '用户ID', field: 'id', align: 'center' },
{ {
name: 'registerTime', name: 'roles',
label: '创建时间', label: '角色',
field: 'registerTime', field: 'roles',
required: true,
align: 'center', align: 'center',
}, },
{ {
name: 'mobile', name: 'registerTime',
label: '手机号', label: '创建时间',
field: 'mobile', field: 'registerTime',
align: 'center', align: 'center',
}, },
]; ];
@ -85,6 +167,7 @@ const pagination = ref({
rowsNumber: 10, rowsNumber: 10,
}); });
// eslint-disable-next-line
async function onRequest(props: any) { async function onRequest(props: any) {
const { page, rowsPerPage, sortBy, descending } = props.pagination; const { page, rowsPerPage, sortBy, descending } = props.pagination;
const filter = props.filter; const filter = props.filter;
@ -109,4 +192,98 @@ async function onRequest(props: any) {
loading.value = false; loading.value = false;
} }
} }
const editFormShow = ref(false);
interface UserInfo extends Omit<User, 'password'> {
Rids: number[];
}
const userInfo = reactive<UserInfo>({
id: '',
name: '',
mobile: '',
registerTime: '',
roleList: [],
Rids: [],
});
const options: { label: string; value: number }[] = [];
function getAllRole() {
pageQueryRole({
current: 1,
size: 999,
})
.then((res) => {
res.records.forEach((item) => {
const obj = {
label: item.name,
value: item.id,
};
options.push(obj);
});
})
.catch((err) => {
console.log(err);
});
}
//
function edieUserData(row: User) {
userInfo.id = row.id;
userInfo.name = row.name;
userInfo.registerTime = row.registerTime;
if (row?.roleList) {
userInfo.roleList = row.roleList;
userInfo.Rids = row.roleList.map((item) => {
return item.roleId;
});
} else {
userInfo.roleList = [];
userInfo.Rids = [];
}
editFormShow.value = true;
}
const myForm = ref<QForm | null>(null);
//
const operateDisabled = ref(false);
function edieUserRole() {
myForm.value?.validate().then(async (res) => {
if (res) {
operateDisabled.value = true;
try {
await userLinkRole({
id: +userInfo.id,
roleList: userInfo.Rids,
});
tableRef.value.requestServerInteraction(); //
editFormShow.value = false;
successNotify('修改成功');
} catch (err) {
const error = err as ApiError;
$q.notify({
type: 'negative',
message: error.title,
});
} finally {
operateDisabled.value = false;
}
}
});
}
function onReset() {
userInfo.id = '';
userInfo.name = '';
userInfo.mobile = '';
userInfo.registerTime = '';
userInfo.roleList = [];
userInfo.Rids = [];
myForm.value?.resetValidation();
}
function searchQuery() {
tableRef.value.requestServerInteraction();
}
</script> </script>

View File

@ -35,7 +35,15 @@ export namespace alert {
AXLE_LED_RED_INTERLOCK_AREA = 20, AXLE_LED_RED_INTERLOCK_AREA = 20,
AXLE_LED_ORANGE_INTERLOCK_AREA = 21, AXLE_LED_ORANGE_INTERLOCK_AREA = 21,
SWITCH_LOST_INTERLOCK_AREA = 22, SWITCH_LOST_INTERLOCK_AREA = 22,
INTERLOCK_LEVEL_ONE = 23 INTERLOCK_LEVEL_ONE = 23,
PLATFORM_EMERG_STOP = 24,
SWITCH_JAMMED = 25,
INTERLOCKED_ZC_FAULT = 26,
TRAIN_LOST_LOCATION = 27,
TRAIN_INTEGRITY_ALARM = 28,
TRAIN_FAULT_HELP = 29,
INTERLOCKED_ATS_STUCK = 30,
TRAIN_RECORD = 31
} }
export enum TipTimeConfig { export enum TipTimeConfig {
HOLIDAYS_MORN_PEAK = 0, HOLIDAYS_MORN_PEAK = 0,

View File

@ -87,6 +87,7 @@ export namespace alert {
locator_device_id?: string; locator_device_id?: string;
alert_location_id?: number; alert_location_id?: number;
mock?: boolean; mock?: boolean;
line_type?: string;
}) { }) {
super(); super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
@ -121,6 +122,9 @@ export namespace alert {
if ("mock" in data && data.mock != undefined) { if ("mock" in data && data.mock != undefined) {
this.mock = data.mock; this.mock = data.mock;
} }
if ("line_type" in data && data.line_type != undefined) {
this.line_type = data.line_type;
}
} }
} }
get id() { get id() {
@ -183,6 +187,12 @@ export namespace alert {
set mock(value: boolean) { set mock(value: boolean) {
pb_1.Message.setField(this, 10, value); pb_1.Message.setField(this, 10, value);
} }
get line_type() {
return pb_1.Message.getFieldWithDefault(this, 11, "") as string;
}
set line_type(value: string) {
pb_1.Message.setField(this, 11, value);
}
static fromObject(data: { static fromObject(data: {
id?: string; id?: string;
level?: string; level?: string;
@ -194,6 +204,7 @@ export namespace alert {
locator_device_id?: string; locator_device_id?: string;
alert_location_id?: number; alert_location_id?: number;
mock?: boolean; mock?: boolean;
line_type?: string;
}): Message { }): Message {
const message = new Message({}); const message = new Message({});
if (data.id != null) { if (data.id != null) {
@ -226,6 +237,9 @@ export namespace alert {
if (data.mock != null) { if (data.mock != null) {
message.mock = data.mock; message.mock = data.mock;
} }
if (data.line_type != null) {
message.line_type = data.line_type;
}
return message; return message;
} }
toObject() { toObject() {
@ -240,6 +254,7 @@ export namespace alert {
locator_device_id?: string; locator_device_id?: string;
alert_location_id?: number; alert_location_id?: number;
mock?: boolean; mock?: boolean;
line_type?: string;
} = {}; } = {};
if (this.id != null) { if (this.id != null) {
data.id = this.id; data.id = this.id;
@ -271,6 +286,9 @@ export namespace alert {
if (this.mock != null) { if (this.mock != null) {
data.mock = this.mock; data.mock = this.mock;
} }
if (this.line_type != null) {
data.line_type = this.line_type;
}
return data; return data;
} }
serialize(): Uint8Array; serialize(): Uint8Array;
@ -297,6 +315,8 @@ export namespace alert {
writer.writeInt64(9, this.alert_location_id); writer.writeInt64(9, this.alert_location_id);
if (this.mock != false) if (this.mock != false)
writer.writeBool(10, this.mock); writer.writeBool(10, this.mock);
if (this.line_type.length)
writer.writeString(11, this.line_type);
if (!w) if (!w)
return writer.getResultBuffer(); return writer.getResultBuffer();
} }
@ -336,6 +356,9 @@ export namespace alert {
case 10: case 10:
message.mock = reader.readBool(); message.mock = reader.readBool();
break; break;
case 11:
message.line_type = reader.readString();
break;
default: reader.skipField(); default: reader.skipField();
} }
} }

View File

@ -3191,6 +3191,9 @@ export namespace state {
timestamp?: number; timestamp?: number;
lineId?: number; lineId?: number;
receiveTime?: number; receiveTime?: number;
bizWaitTimerGoing?: boolean;
bizWaitStartTimeSec?: number;
bizWaitTimeSec?: number;
}) { }) {
super(); super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
@ -3258,6 +3261,15 @@ export namespace state {
if ("receiveTime" in data && data.receiveTime != undefined) { if ("receiveTime" in data && data.receiveTime != undefined) {
this.receiveTime = data.receiveTime; this.receiveTime = data.receiveTime;
} }
if ("bizWaitTimerGoing" in data && data.bizWaitTimerGoing != undefined) {
this.bizWaitTimerGoing = data.bizWaitTimerGoing;
}
if ("bizWaitStartTimeSec" in data && data.bizWaitStartTimeSec != undefined) {
this.bizWaitStartTimeSec = data.bizWaitStartTimeSec;
}
if ("bizWaitTimeSec" in data && data.bizWaitTimeSec != undefined) {
this.bizWaitTimeSec = data.bizWaitTimeSec;
}
} }
} }
get emergstop() { get emergstop() {
@ -3386,6 +3398,24 @@ export namespace state {
set receiveTime(value: number) { set receiveTime(value: number) {
pb_1.Message.setField(this, 21, value); pb_1.Message.setField(this, 21, value);
} }
get bizWaitTimerGoing() {
return pb_1.Message.getFieldWithDefault(this, 22, false) as boolean;
}
set bizWaitTimerGoing(value: boolean) {
pb_1.Message.setField(this, 22, value);
}
get bizWaitStartTimeSec() {
return pb_1.Message.getFieldWithDefault(this, 23, 0) as number;
}
set bizWaitStartTimeSec(value: number) {
pb_1.Message.setField(this, 23, value);
}
get bizWaitTimeSec() {
return pb_1.Message.getFieldWithDefault(this, 24, 0) as number;
}
set bizWaitTimeSec(value: number) {
pb_1.Message.setField(this, 24, value);
}
static fromObject(data: { static fromObject(data: {
emergstop?: boolean; emergstop?: boolean;
trainberth?: boolean; trainberth?: boolean;
@ -3408,6 +3438,9 @@ export namespace state {
timestamp?: number; timestamp?: number;
lineId?: number; lineId?: number;
receiveTime?: number; receiveTime?: number;
bizWaitTimerGoing?: boolean;
bizWaitStartTimeSec?: number;
bizWaitTimeSec?: number;
}): Platform { }): Platform {
const message = new Platform({}); const message = new Platform({});
if (data.emergstop != null) { if (data.emergstop != null) {
@ -3473,6 +3506,15 @@ export namespace state {
if (data.receiveTime != null) { if (data.receiveTime != null) {
message.receiveTime = data.receiveTime; message.receiveTime = data.receiveTime;
} }
if (data.bizWaitTimerGoing != null) {
message.bizWaitTimerGoing = data.bizWaitTimerGoing;
}
if (data.bizWaitStartTimeSec != null) {
message.bizWaitStartTimeSec = data.bizWaitStartTimeSec;
}
if (data.bizWaitTimeSec != null) {
message.bizWaitTimeSec = data.bizWaitTimeSec;
}
return message; return message;
} }
toObject() { toObject() {
@ -3498,6 +3540,9 @@ export namespace state {
timestamp?: number; timestamp?: number;
lineId?: number; lineId?: number;
receiveTime?: number; receiveTime?: number;
bizWaitTimerGoing?: boolean;
bizWaitStartTimeSec?: number;
bizWaitTimeSec?: number;
} = {}; } = {};
if (this.emergstop != null) { if (this.emergstop != null) {
data.emergstop = this.emergstop; data.emergstop = this.emergstop;
@ -3562,6 +3607,15 @@ export namespace state {
if (this.receiveTime != null) { if (this.receiveTime != null) {
data.receiveTime = this.receiveTime; data.receiveTime = this.receiveTime;
} }
if (this.bizWaitTimerGoing != null) {
data.bizWaitTimerGoing = this.bizWaitTimerGoing;
}
if (this.bizWaitStartTimeSec != null) {
data.bizWaitStartTimeSec = this.bizWaitStartTimeSec;
}
if (this.bizWaitTimeSec != null) {
data.bizWaitTimeSec = this.bizWaitTimeSec;
}
return data; return data;
} }
serialize(): Uint8Array; serialize(): Uint8Array;
@ -3610,6 +3664,12 @@ export namespace state {
writer.writeInt32(20, this.lineId); writer.writeInt32(20, this.lineId);
if (this.receiveTime != 0) if (this.receiveTime != 0)
writer.writeInt64(21, this.receiveTime); writer.writeInt64(21, this.receiveTime);
if (this.bizWaitTimerGoing != false)
writer.writeBool(22, this.bizWaitTimerGoing);
if (this.bizWaitStartTimeSec != 0)
writer.writeInt64(23, this.bizWaitStartTimeSec);
if (this.bizWaitTimeSec != 0)
writer.writeInt64(24, this.bizWaitTimeSec);
if (!w) if (!w)
return writer.getResultBuffer(); return writer.getResultBuffer();
} }
@ -3682,6 +3742,15 @@ export namespace state {
case 21: case 21:
message.receiveTime = reader.readInt64(); message.receiveTime = reader.readInt64();
break; break;
case 22:
message.bizWaitTimerGoing = reader.readBool();
break;
case 23:
message.bizWaitStartTimeSec = reader.readInt64();
break;
case 24:
message.bizWaitTimeSec = reader.readInt64();
break;
default: reader.skipField(); default: reader.skipField();
} }
} }

View File

@ -28,6 +28,7 @@ export namespace graphicData {
separators?: Separator[]; separators?: Separator[];
logicSections?: LogicSection[]; logicSections?: LogicSection[];
concentrationDividingLines?: ConcentrationDividingLine[]; concentrationDividingLines?: ConcentrationDividingLine[];
generateAxleCountingConfig?: GenerateAxleCountingConfig;
}) { }) {
super(); super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], this.#one_of_decls); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], this.#one_of_decls);
@ -92,6 +93,9 @@ export namespace graphicData {
if ("concentrationDividingLines" in data && data.concentrationDividingLines != undefined) { if ("concentrationDividingLines" in data && data.concentrationDividingLines != undefined) {
this.concentrationDividingLines = data.concentrationDividingLines; this.concentrationDividingLines = data.concentrationDividingLines;
} }
if ("generateAxleCountingConfig" in data && data.generateAxleCountingConfig != undefined) {
this.generateAxleCountingConfig = data.generateAxleCountingConfig;
}
} }
} }
get canvas() { get canvas() {
@ -217,6 +221,15 @@ export namespace graphicData {
set concentrationDividingLines(value: ConcentrationDividingLine[]) { set concentrationDividingLines(value: ConcentrationDividingLine[]) {
pb_1.Message.setRepeatedWrapperField(this, 20, value); pb_1.Message.setRepeatedWrapperField(this, 20, value);
} }
get generateAxleCountingConfig() {
return pb_1.Message.getWrapperField(this, GenerateAxleCountingConfig, 21) as GenerateAxleCountingConfig;
}
set generateAxleCountingConfig(value: GenerateAxleCountingConfig) {
pb_1.Message.setWrapperField(this, 21, value);
}
get has_generateAxleCountingConfig() {
return pb_1.Message.getField(this, 21) != null;
}
static fromObject(data: { static fromObject(data: {
canvas?: ReturnType<typeof Canvas.prototype.toObject>; canvas?: ReturnType<typeof Canvas.prototype.toObject>;
links?: ReturnType<typeof Link.prototype.toObject>[]; links?: ReturnType<typeof Link.prototype.toObject>[];
@ -238,6 +251,7 @@ export namespace graphicData {
separators?: ReturnType<typeof Separator.prototype.toObject>[]; separators?: ReturnType<typeof Separator.prototype.toObject>[];
logicSections?: ReturnType<typeof LogicSection.prototype.toObject>[]; logicSections?: ReturnType<typeof LogicSection.prototype.toObject>[];
concentrationDividingLines?: ReturnType<typeof ConcentrationDividingLine.prototype.toObject>[]; concentrationDividingLines?: ReturnType<typeof ConcentrationDividingLine.prototype.toObject>[];
generateAxleCountingConfig?: ReturnType<typeof GenerateAxleCountingConfig.prototype.toObject>;
}): RtssGraphicStorage { }): RtssGraphicStorage {
const message = new RtssGraphicStorage({}); const message = new RtssGraphicStorage({});
if (data.canvas != null) { if (data.canvas != null) {
@ -300,6 +314,9 @@ export namespace graphicData {
if (data.concentrationDividingLines != null) { if (data.concentrationDividingLines != null) {
message.concentrationDividingLines = data.concentrationDividingLines.map(item => ConcentrationDividingLine.fromObject(item)); message.concentrationDividingLines = data.concentrationDividingLines.map(item => ConcentrationDividingLine.fromObject(item));
} }
if (data.generateAxleCountingConfig != null) {
message.generateAxleCountingConfig = GenerateAxleCountingConfig.fromObject(data.generateAxleCountingConfig);
}
return message; return message;
} }
toObject() { toObject() {
@ -324,6 +341,7 @@ export namespace graphicData {
separators?: ReturnType<typeof Separator.prototype.toObject>[]; separators?: ReturnType<typeof Separator.prototype.toObject>[];
logicSections?: ReturnType<typeof LogicSection.prototype.toObject>[]; logicSections?: ReturnType<typeof LogicSection.prototype.toObject>[];
concentrationDividingLines?: ReturnType<typeof ConcentrationDividingLine.prototype.toObject>[]; concentrationDividingLines?: ReturnType<typeof ConcentrationDividingLine.prototype.toObject>[];
generateAxleCountingConfig?: ReturnType<typeof GenerateAxleCountingConfig.prototype.toObject>;
} = {}; } = {};
if (this.canvas != null) { if (this.canvas != null) {
data.canvas = this.canvas.toObject(); data.canvas = this.canvas.toObject();
@ -385,6 +403,9 @@ export namespace graphicData {
if (this.concentrationDividingLines != null) { if (this.concentrationDividingLines != null) {
data.concentrationDividingLines = this.concentrationDividingLines.map((item: ConcentrationDividingLine) => item.toObject()); data.concentrationDividingLines = this.concentrationDividingLines.map((item: ConcentrationDividingLine) => item.toObject());
} }
if (this.generateAxleCountingConfig != null) {
data.generateAxleCountingConfig = this.generateAxleCountingConfig.toObject();
}
return data; return data;
} }
serialize(): Uint8Array; serialize(): Uint8Array;
@ -431,6 +452,8 @@ export namespace graphicData {
writer.writeRepeatedMessage(19, this.logicSections, (item: LogicSection) => item.serialize(writer)); writer.writeRepeatedMessage(19, this.logicSections, (item: LogicSection) => item.serialize(writer));
if (this.concentrationDividingLines.length) if (this.concentrationDividingLines.length)
writer.writeRepeatedMessage(20, this.concentrationDividingLines, (item: ConcentrationDividingLine) => item.serialize(writer)); writer.writeRepeatedMessage(20, this.concentrationDividingLines, (item: ConcentrationDividingLine) => item.serialize(writer));
if (this.has_generateAxleCountingConfig)
writer.writeMessage(21, this.generateAxleCountingConfig, () => this.generateAxleCountingConfig.serialize(writer));
if (!w) if (!w)
return writer.getResultBuffer(); return writer.getResultBuffer();
} }
@ -500,6 +523,9 @@ export namespace graphicData {
case 20: case 20:
reader.readMessage(message.concentrationDividingLines, () => pb_1.Message.addToRepeatedWrapperField(message, 20, ConcentrationDividingLine.deserialize(reader), ConcentrationDividingLine)); reader.readMessage(message.concentrationDividingLines, () => pb_1.Message.addToRepeatedWrapperField(message, 20, ConcentrationDividingLine.deserialize(reader), ConcentrationDividingLine));
break; break;
case 21:
reader.readMessage(message.generateAxleCountingConfig, () => message.generateAxleCountingConfig = GenerateAxleCountingConfig.deserialize(reader));
break;
default: reader.skipField(); default: reader.skipField();
} }
} }
@ -5241,4 +5267,94 @@ export namespace graphicData {
return Separator.deserialize(bytes); return Separator.deserialize(bytes);
} }
} }
export class GenerateAxleCountingConfig extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {
bbConnect?: number[];
noGenerateGroup?: number[];
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [1, 2], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") {
if ("bbConnect" in data && data.bbConnect != undefined) {
this.bbConnect = data.bbConnect;
}
if ("noGenerateGroup" in data && data.noGenerateGroup != undefined) {
this.noGenerateGroup = data.noGenerateGroup;
}
}
}
get bbConnect() {
return pb_1.Message.getFieldWithDefault(this, 1, []) as number[];
}
set bbConnect(value: number[]) {
pb_1.Message.setField(this, 1, value);
}
get noGenerateGroup() {
return pb_1.Message.getFieldWithDefault(this, 2, []) as number[];
}
set noGenerateGroup(value: number[]) {
pb_1.Message.setField(this, 2, value);
}
static fromObject(data: {
bbConnect?: number[];
noGenerateGroup?: number[];
}): GenerateAxleCountingConfig {
const message = new GenerateAxleCountingConfig({});
if (data.bbConnect != null) {
message.bbConnect = data.bbConnect;
}
if (data.noGenerateGroup != null) {
message.noGenerateGroup = data.noGenerateGroup;
}
return message;
}
toObject() {
const data: {
bbConnect?: number[];
noGenerateGroup?: number[];
} = {};
if (this.bbConnect != null) {
data.bbConnect = this.bbConnect;
}
if (this.noGenerateGroup != null) {
data.noGenerateGroup = this.noGenerateGroup;
}
return data;
}
serialize(): Uint8Array;
serialize(w: pb_1.BinaryWriter): void;
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
const writer = w || new pb_1.BinaryWriter();
if (this.bbConnect.length)
writer.writePackedUint32(1, this.bbConnect);
if (this.noGenerateGroup.length)
writer.writePackedUint32(2, this.noGenerateGroup);
if (!w)
return writer.getResultBuffer();
}
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): GenerateAxleCountingConfig {
const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new GenerateAxleCountingConfig();
while (reader.nextField()) {
if (reader.isEndGroup())
break;
switch (reader.getFieldNumber()) {
case 1:
message.bbConnect = reader.readPackedUint32();
break;
case 2:
message.noGenerateGroup = reader.readPackedUint32();
break;
default: reader.skipField();
}
}
return message;
}
serializeBinary(): Uint8Array {
return this.serialize();
}
static deserializeBinary(bytes: Uint8Array): GenerateAxleCountingConfig {
return GenerateAxleCountingConfig.deserialize(bytes);
}
}
} }

View File

@ -78,6 +78,7 @@ export namespace state {
lineId?: number; lineId?: number;
occRealConned?: boolean; occRealConned?: boolean;
occUnrealConned?: boolean; occUnrealConned?: boolean;
atsWarnShowCounter?: boolean;
}) { }) {
super(); super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
@ -91,6 +92,9 @@ export namespace state {
if ("occUnrealConned" in data && data.occUnrealConned != undefined) { if ("occUnrealConned" in data && data.occUnrealConned != undefined) {
this.occUnrealConned = data.occUnrealConned; this.occUnrealConned = data.occUnrealConned;
} }
if ("atsWarnShowCounter" in data && data.atsWarnShowCounter != undefined) {
this.atsWarnShowCounter = data.atsWarnShowCounter;
}
} }
} }
get lineId() { get lineId() {
@ -111,10 +115,17 @@ export namespace state {
set occUnrealConned(value: boolean) { set occUnrealConned(value: boolean) {
pb_1.Message.setField(this, 3, value); pb_1.Message.setField(this, 3, value);
} }
get atsWarnShowCounter() {
return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean;
}
set atsWarnShowCounter(value: boolean) {
pb_1.Message.setField(this, 4, value);
}
static fromObject(data: { static fromObject(data: {
lineId?: number; lineId?: number;
occRealConned?: boolean; occRealConned?: boolean;
occUnrealConned?: boolean; occUnrealConned?: boolean;
atsWarnShowCounter?: boolean;
}): WarnMessage { }): WarnMessage {
const message = new WarnMessage({}); const message = new WarnMessage({});
if (data.lineId != null) { if (data.lineId != null) {
@ -126,6 +137,9 @@ export namespace state {
if (data.occUnrealConned != null) { if (data.occUnrealConned != null) {
message.occUnrealConned = data.occUnrealConned; message.occUnrealConned = data.occUnrealConned;
} }
if (data.atsWarnShowCounter != null) {
message.atsWarnShowCounter = data.atsWarnShowCounter;
}
return message; return message;
} }
toObject() { toObject() {
@ -133,6 +147,7 @@ export namespace state {
lineId?: number; lineId?: number;
occRealConned?: boolean; occRealConned?: boolean;
occUnrealConned?: boolean; occUnrealConned?: boolean;
atsWarnShowCounter?: boolean;
} = {}; } = {};
if (this.lineId != null) { if (this.lineId != null) {
data.lineId = this.lineId; data.lineId = this.lineId;
@ -143,6 +158,9 @@ export namespace state {
if (this.occUnrealConned != null) { if (this.occUnrealConned != null) {
data.occUnrealConned = this.occUnrealConned; data.occUnrealConned = this.occUnrealConned;
} }
if (this.atsWarnShowCounter != null) {
data.atsWarnShowCounter = this.atsWarnShowCounter;
}
return data; return data;
} }
serialize(): Uint8Array; serialize(): Uint8Array;
@ -155,6 +173,8 @@ export namespace state {
writer.writeBool(2, this.occRealConned); writer.writeBool(2, this.occRealConned);
if (this.occUnrealConned != false) if (this.occUnrealConned != false)
writer.writeBool(3, this.occUnrealConned); writer.writeBool(3, this.occUnrealConned);
if (this.atsWarnShowCounter != false)
writer.writeBool(4, this.atsWarnShowCounter);
if (!w) if (!w)
return writer.getResultBuffer(); return writer.getResultBuffer();
} }
@ -173,6 +193,9 @@ export namespace state {
case 3: case 3:
message.occUnrealConned = reader.readBool(); message.occUnrealConned = reader.readBool();
break; break;
case 4:
message.atsWarnShowCounter = reader.readBool();
break;
default: reader.skipField(); default: reader.skipField();
} }
} }

View File

@ -8,6 +8,9 @@ import {
import routes from './routes'; import routes from './routes';
import { getJwtToken } from 'src/configs/TokenManage'; import { getJwtToken } from 'src/configs/TokenManage';
import { getUserInfo } from 'src/api/UserApi';
import { useUserStore } from 'src/stores/user-store';
import { handleRefreshToken } from 'src/utils/refreshToken';
/* /*
* If not building with SSR mode, you can * If not building with SSR mode, you can
@ -42,7 +45,24 @@ export default route(function (/* { store, ssrContext } */) {
if (!getJwtToken()) { if (!getJwtToken()) {
next({ path: '/login' }); next({ path: '/login' });
} else { } else {
try {
const userStore = useUserStore();
if (!userStore.remainingSecond) {
const userInfo = await getUserInfo();
userStore.defaultRole = userInfo.defaultRole;
userStore.roles = userInfo.roles;
userStore.remainingSecond = userInfo.remainingSecond;
setTimeout(
() => handleRefreshToken(),
userInfo.remainingSecond * 1000 - 10000
);
}
next(); next();
} catch (e) {
console.error('获取用户信息出错:', e);
next({ path: '/login' });
}
} }
} }
}); });

View File

@ -1,10 +1,11 @@
import { RouteRecordRaw } from 'vue-router'; import { RouteRecordRaw } from 'vue-router';
import { role } from 'src/api/UserApi';
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] = [
{ {
path: '/', path: '/',
name: 'home', name: 'home',
redirect: '/monitor', redirect: '/login',
// component: () => import('layouts/MainLayout.vue'), // component: () => import('layouts/MainLayout.vue'),
// children: [{ path: '', component: () => import('pages/IndexPage.vue') }], // children: [{ path: '', component: () => import('pages/IndexPage.vue') }],
}, },
@ -45,6 +46,16 @@ const routes: RouteRecordRaw[] = [
name: 'decisionInfo', name: 'decisionInfo',
component: () => import('pages/DecisionInfoManage.vue'), component: () => import('pages/DecisionInfoManage.vue'),
}, },
{
path: 'faultQuery',
name: 'faultQuery',
component: () => import('pages/FaultQueryManage.vue'),
},
{
path: 'emergencyResponse',
name: 'emergencyResponse',
component: () => import('pages/EmergencyResponseManage.vue'),
},
{ {
path: 'thresholdValue', path: 'thresholdValue',
name: 'thresholdValue', name: 'thresholdValue',
@ -70,6 +81,61 @@ const routes: RouteRecordRaw[] = [
}, },
component: () => import('pages/UserManage.vue'), component: () => import('pages/UserManage.vue'),
}, },
{
path: 'role',
name: 'role',
meta: {
description: '权限管理',
},
component: () => import('pages/RoleManage.vue'),
},
{
path: 'authPath',
name: 'authPath',
meta: {
description: '权限接口管理',
},
component: () => import('pages/AuthPathManage.vue'),
},
{
path: 'loginRecord',
name: 'loginRecord',
meta: {
description: '登录记录',
},
component: () => import('pages/LoginRecord.vue'),
},
{
path: 'operateRecord',
name: 'operateRecord',
meta: {
description: '操作记录',
},
component: () => import('pages/OperateRecord.vue'),
},
{
path: 'alarmRecord',
name: 'alarmRecord',
meta: {
description: '报警记录',
},
component: () => import('pages/AlarmRecord.vue'),
},
],
},
{
path: '/alarmInfo',
name: 'alarmInfo',
component: () => import('layouts/MainLayout.vue'),
children: [
{
path: 'list',
name: 'list',
meta: {
description: '报警信息',
},
component: () => import('pages/AlarmInfoList.vue'),
},
], ],
}, },
{ {
@ -117,17 +183,6 @@ const routes: RouteRecordRaw[] = [
}, },
], ],
}, },
{
path: '/alarmList',
component: () => import('layouts/MainLayout.vue'),
children: [
{
path: '',
name: 'alarmList',
component: () => import('src/pages/AlarmInfoList.vue'),
},
],
},
// Always leave this as last one, // Always leave this as last one,
// but you can also remove it // but you can also remove it
@ -138,3 +193,45 @@ const routes: RouteRecordRaw[] = [
]; ];
export default routes; export default routes;
export function getMonitorPath(roles: role[]) {
const configInfo: {
monitorPath: string;
lineIds: number[];
lineType: string;
destinations: string[];
} = {
monitorPath: '',
lineIds: [],
lineType: '',
destinations: [],
};
let allOCCLineIds: number[] = [];
for (let i = 0; i < roles.length; i++) {
const roleConfig = roles[i].roleConfig;
for (let j = 0; j < roleConfig.length; j++) {
if (roleConfig[j].lineType == 'NCC') {
configInfo.monitorPath = '/monitor';
configInfo.lineIds = roleConfig.map((config) => {
configInfo.destinations.push(
`/queue/xian/NCC/${config.lineId}/alert`
);
return config.lineId;
});
configInfo.lineType = 'NCC';
return configInfo;
} else {
allOCCLineIds.push(roleConfig[j].lineId);
}
}
}
allOCCLineIds = [...new Set(allOCCLineIds)];
const minId = Math.min(...allOCCLineIds);
configInfo.monitorPath = `/line/monitor/${minId}`;
configInfo.lineIds = allOCCLineIds;
configInfo.lineType = 'OCC';
allOCCLineIds.forEach((lineId) => {
configInfo.destinations.push(`/queue/xian/OCC/${lineId}/alert`);
});
return configInfo;
}

View File

@ -4,9 +4,10 @@ import {
initLineNetApp, initLineNetApp,
getLineNetApp, getLineNetApp,
destroyLineNetApp, destroyLineNetApp,
cancelSubscribe,
} from 'src/drawApp/lineNetApp'; } from 'src/drawApp/lineNetApp';
import { markRaw } from 'vue'; import { markRaw } from 'vue';
import { QTable } from 'quasar'; import { Notify, QNotifyUpdateOptions, QTable } from 'quasar';
import { state } from 'src/protos/system_warn_message'; import { state } from 'src/protos/system_warn_message';
export interface AlarmInfo { export interface AlarmInfo {
id: string; id: string;
@ -14,12 +15,17 @@ export interface AlarmInfo {
alert_time: string; alert_time: string;
alert_tip_id: number; alert_tip_id: number;
line_id: string; line_id: string;
line_type: string;
alert_object: string; alert_object: string;
alert_type: number; alert_type: number;
locator_device_id: string; locator_device_id: string;
alert_location_id: number; alert_location_id: number;
alarmStatus?: number; alarmStatus?: number;
} }
let msgNotify: null | ((props?: QNotifyUpdateOptions | undefined) => void) =
null;
let tip = '';
export const useLineNetStore = defineStore('lineNet', { export const useLineNetStore = defineStore('lineNet', {
state: () => ({ state: () => ({
selectedGraphics: null as JlGraphic[] | null, selectedGraphics: null as JlGraphic[] | null,
@ -27,10 +33,13 @@ export const useLineNetStore = defineStore('lineNet', {
alarmInfo: [] as AlarmInfo[], //报警信息 alarmInfo: [] as AlarmInfo[], //报警信息
untreatedMap: new Map(), // 未处理的报警 untreatedMap: new Map(), // 未处理的报警
alarmInfoListTable: undefined as QTable | undefined, alarmInfoListTable: undefined as QTable | undefined,
playAble: false, //是否允许播放音乐 playAble: false, //是否允许播放音乐(与页面交互之后为true)
handlePlayAble: true, //默认交互之后可播放音乐
closeAllAlarmInfoDialog: false, closeAllAlarmInfoDialog: false,
connectButtonColor: 'green', connectButtonColor: 'green',
connectInfo: null as state.WarnLineMessage | null, connectInfo: null as state.WarnLineMessage | null,
jumpLineCount: 0,
jumpLineId: '',
}), }),
getters: { getters: {
untreatedNum: (state) => { untreatedNum: (state) => {
@ -71,6 +80,10 @@ export const useLineNetStore = defineStore('lineNet', {
this.selectedGraphics = []; this.selectedGraphics = [];
return app; return app;
}, },
cancelSubscribe() {
const app = this.getLineNetApp();
cancelSubscribe(app);
},
destroy() { destroy() {
this.selectedGraphics = null; this.selectedGraphics = null;
destroyLineNetApp(); destroyLineNetApp();
@ -85,6 +98,45 @@ export const useLineNetStore = defineStore('lineNet', {
}); });
}, },
setConnectInfo(data: state.WarnLineMessage) { setConnectInfo(data: state.WarnLineMessage) {
let newTip = '';
data.msgs.forEach((item: state.WarnMessage) => {
if (!item.occRealConned) {
newTip =
newTip + `<div>${item.lineId}号线路与同方的实时连接已断开;</div>`;
}
if (!item.occUnrealConned) {
newTip =
newTip + `<div>${item.lineId}号线路与同方的非实时连接已断开</div>`;
}
});
if (newTip && (newTip !== tip || !msgNotify)) {
if (msgNotify) {
msgNotify();
}
tip = newTip;
msgNotify = Notify.create({
type: 'negative',
timeout: 0,
position: 'top',
html: true,
message: tip,
actions: [
{
icon: 'close',
color: 'white',
handler: () => {
if (msgNotify) {
msgNotify();
}
},
},
],
});
} else if (!newTip) {
if (msgNotify) {
msgNotify();
}
}
this.connectInfo = data; this.connectInfo = data;
const allConnectAmount = data.msgs.reduce((pre, cur) => { const allConnectAmount = data.msgs.reduce((pre, cur) => {
let addValue = 0; let addValue = 0;

View File

@ -1,6 +1,11 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { IJlCanvas, JlGraphic, IGraphicApp } from 'jl-graphic'; import { IJlCanvas, JlGraphic, IGraphicApp } from 'jl-graphic';
import { initLineApp, getLineApp, destroyLineApp } from 'src/drawApp/lineApp'; import {
initLineApp,
getLineApp,
destroyLineApp,
cancelSubscribe,
} from 'src/drawApp/lineApp';
import { markRaw } from 'vue'; import { markRaw } from 'vue';
export const useLineStore = defineStore('line', { export const useLineStore = defineStore('line', {
@ -8,6 +13,7 @@ export const useLineStore = defineStore('line', {
selectedGraphics: null as JlGraphic[] | null, selectedGraphics: null as JlGraphic[] | null,
lineId: null as number | null, lineId: null as number | null,
lineName: null as string | null, lineName: null as string | null,
faultStatistics: false,
}), }),
getters: { getters: {
selectedGraphicType: (state) => { selectedGraphicType: (state) => {
@ -39,7 +45,7 @@ export const useLineStore = defineStore('line', {
}, },
initLineApp(lineId: number) { initLineApp(lineId: number) {
this.setLineId(lineId); this.setLineId(lineId);
const app = initLineApp(); const app = initLineApp(lineId);
app.on('graphicselected', (graphics) => { app.on('graphicselected', (graphics) => {
this.selectedGraphics = markRaw(graphics); this.selectedGraphics = markRaw(graphics);
}); });
@ -50,6 +56,10 @@ export const useLineStore = defineStore('line', {
this.selectedGraphics = null; this.selectedGraphics = null;
destroyLineApp(); destroyLineApp();
}, },
cancelSubscribe() {
const app = this.getLineApp();
cancelSubscribe(app);
},
setLineId(id: number | null) { setLineId(id: number | null) {
this.lineId = id; this.lineId = id;
}, },

19
src/stores/user-store.ts Normal file
View File

@ -0,0 +1,19 @@
import { defineStore } from 'pinia';
import { role } from 'src/api/UserApi';
export const useUserStore = defineStore('user', {
state: () => ({
remainingSecond: 0,
roles: [] as role[],
defaultRole: '',
}),
getters: {},
actions: {
// setRemainingSecond(remainingSecond: number) {
// this.remainingSecond = remainingSecond;
// },
// setDefaultRole(defaultRole: string) {
// this.defaultRole = defaultRole;
// },
},
});

18
src/utils/refreshToken.ts Normal file
View File

@ -0,0 +1,18 @@
import { saveJwtToken } from 'src/configs/TokenManage';
import { refreshToken } from 'src/api/UserApi';
import { useUserStore } from 'src/stores/user-store';
export async function handleRefreshToken() {
try {
const userStore = useUserStore();
const tokenInfo = await refreshToken();
saveJwtToken(tokenInfo.token);
userStore.remainingSecond = tokenInfo.remainingSecond;
setTimeout(
() => handleRefreshToken(),
tokenInfo.remainingSecond * 1000 - 10000
);
} catch (e) {
console.error('刷新 token 出错:', e);
}
}

@ -1 +1 @@
Subproject commit c20feed4b6ae3bdd02cb21b4cc5af03c55be869b Subproject commit 7aef4b876fae6622d93a21c99fe293df7bf7d572

261
yarn.lock
View File

@ -326,18 +326,6 @@
eventemitter3 "^4.0.0" eventemitter3 "^4.0.0"
url "^0.11.0" url "^0.11.0"
"@pkgr/utils@^2.4.2":
version "2.4.2"
resolved "https://registry.npmmirror.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc"
integrity sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==
dependencies:
cross-spawn "^7.0.3"
fast-glob "^3.3.0"
is-glob "^4.0.3"
open "^9.1.0"
picocolors "^1.0.0"
tslib "^2.6.0"
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2" version "1.1.2"
resolved "https://registry.npmmirror.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" resolved "https://registry.npmmirror.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
@ -448,13 +436,6 @@
resolved "https://registry.npmmirror.com/@quasar/vite-plugin/-/vite-plugin-1.6.0.tgz#3b8f82656b14782fafe66b30dfac0775b87ab9dd" resolved "https://registry.npmmirror.com/@quasar/vite-plugin/-/vite-plugin-1.6.0.tgz#3b8f82656b14782fafe66b30dfac0775b87ab9dd"
integrity sha512-LmbV76G1CwWZbrEQhqyZpkRQTJyO3xpW55aXY1zWN+JhyUeG77CcMCEWteBVnJ6I6ehUPFDC9ONd2+WlwH6rNQ== integrity sha512-LmbV76G1CwWZbrEQhqyZpkRQTJyO3xpW55aXY1zWN+JhyUeG77CcMCEWteBVnJ6I6ehUPFDC9ONd2+WlwH6rNQ==
"@rollup/plugin-alias@^5.1.0":
version "5.1.0"
resolved "https://registry.npmmirror.com/@rollup/plugin-alias/-/plugin-alias-5.1.0.tgz#99a94accc4ff9a3483be5baeedd5d7da3b597e93"
integrity sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ==
dependencies:
slash "^4.0.0"
"@rollup/pluginutils@^4.1.2": "@rollup/pluginutils@^4.1.2":
version "4.2.1" version "4.2.1"
resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
@ -1006,11 +987,6 @@ base64-js@^1.3.1:
resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
big-integer@^1.6.44:
version "1.6.52"
resolved "https://registry.npmmirror.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85"
integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==
binary-extensions@^2.0.0: binary-extensions@^2.0.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
@ -1057,13 +1033,6 @@ boolbase@^1.0.0:
resolved "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" resolved "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
bplist-parser@^0.2.0:
version "0.2.0"
resolved "https://registry.npmmirror.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e"
integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==
dependencies:
big-integer "^1.6.44"
brace-expansion@^1.1.7: brace-expansion@^1.1.7:
version "1.1.11" version "1.1.11"
resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@ -1122,13 +1091,6 @@ buffer@^6.0.3:
base64-js "^1.3.1" base64-js "^1.3.1"
ieee754 "^1.2.1" ieee754 "^1.2.1"
bundle-name@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a"
integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==
dependencies:
run-applescript "^5.0.0"
bytes@3.0.0: bytes@3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmmirror.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" resolved "https://registry.npmmirror.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
@ -1406,24 +1368,6 @@ deep-is@^0.1.3:
resolved "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" resolved "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
default-browser-id@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c"
integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==
dependencies:
bplist-parser "^0.2.0"
untildify "^4.0.0"
default-browser@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da"
integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==
dependencies:
bundle-name "^3.0.0"
default-browser-id "^3.0.0"
execa "^7.1.1"
titleize "^3.0.0"
defaults@^1.0.3: defaults@^1.0.3:
version "1.0.4" version "1.0.4"
resolved "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" resolved "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
@ -1445,11 +1389,6 @@ define-lazy-prop@^2.0.0:
resolved "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" resolved "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
define-lazy-prop@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f"
integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==
delayed-stream@~1.0.0: delayed-stream@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@ -1808,19 +1747,6 @@ eslint-config-prettier@^8.1.0:
resolved "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" resolved "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11"
integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==
eslint-config-prettier@^9.1.0:
version "9.1.0"
resolved "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f"
integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
eslint-plugin-prettier@^5.0.1:
version "5.0.1"
resolved "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz#a3b399f04378f79f066379f544e42d6b73f11515"
integrity sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==
dependencies:
prettier-linter-helpers "^1.0.0"
synckit "^0.8.5"
eslint-plugin-vue@^9.0.0: eslint-plugin-vue@^9.0.0:
version "9.19.2" version "9.19.2"
resolved "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.19.2.tgz#7ab83a001a1ac8bccae013c5b9cb5d2c644fb376" resolved "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.19.2.tgz#7ab83a001a1ac8bccae013c5b9cb5d2c644fb376"
@ -1855,7 +1781,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint@^8.10.0, eslint@^8.55.0: eslint@^8.10.0:
version "8.55.0" version "8.55.0"
resolved "https://registry.npmmirror.com/eslint/-/eslint-8.55.0.tgz#078cb7b847d66f2c254ea1794fa395bf8e7e03f8" resolved "https://registry.npmmirror.com/eslint/-/eslint-8.55.0.tgz#078cb7b847d66f2c254ea1794fa395bf8e7e03f8"
integrity sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA== integrity sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==
@ -1962,36 +1888,6 @@ events@^3.3.0:
resolved "https://registry.npmmirror.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" resolved "https://registry.npmmirror.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
execa@^5.0.0:
version "5.1.1"
resolved "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
dependencies:
cross-spawn "^7.0.3"
get-stream "^6.0.0"
human-signals "^2.1.0"
is-stream "^2.0.0"
merge-stream "^2.0.0"
npm-run-path "^4.0.1"
onetime "^5.1.2"
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
execa@^7.1.1:
version "7.2.0"
resolved "https://registry.npmmirror.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9"
integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==
dependencies:
cross-spawn "^7.0.3"
get-stream "^6.0.1"
human-signals "^4.3.0"
is-stream "^3.0.0"
merge-stream "^2.0.0"
npm-run-path "^5.1.0"
onetime "^6.0.0"
signal-exit "^3.0.7"
strip-final-newline "^3.0.0"
express@^4.17.3: express@^4.17.3:
version "4.18.2" version "4.18.2"
resolved "https://registry.npmmirror.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" resolved "https://registry.npmmirror.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
@ -2043,11 +1939,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-diff@^1.1.2:
version "1.3.0"
resolved "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
fast-glob@3.2.12: fast-glob@3.2.12:
version "3.2.12" version "3.2.12"
resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
@ -2059,7 +1950,7 @@ fast-glob@3.2.12:
merge2 "^1.3.0" merge2 "^1.3.0"
micromatch "^4.0.4" micromatch "^4.0.4"
fast-glob@^3.2.9, fast-glob@^3.3.0: fast-glob@^3.2.9:
version "3.3.2" version "3.3.2"
resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
@ -2229,11 +2120,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@
has-symbols "^1.0.3" has-symbols "^1.0.3"
hasown "^2.0.0" hasown "^2.0.0"
get-stream@^6.0.0, get-stream@^6.0.1:
version "6.0.1"
resolved "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
glob-parent@^5.1.2, glob-parent@~5.1.2: glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2" version "5.1.2"
resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
@ -2378,16 +2264,6 @@ http-errors@2.0.0:
statuses "2.0.1" statuses "2.0.1"
toidentifier "1.0.1" toidentifier "1.0.1"
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
human-signals@^4.3.0:
version "4.3.1"
resolved "https://registry.npmmirror.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2"
integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==
iconv-lite@0.4.24, iconv-lite@^0.4.24: iconv-lite@0.4.24, iconv-lite@^0.4.24:
version "0.4.24" version "0.4.24"
resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@ -2481,11 +2357,6 @@ is-docker@^2.0.0, is-docker@^2.1.1:
resolved "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" resolved "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
is-docker@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200"
integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==
is-extglob@^2.1.1: is-extglob@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
@ -2503,13 +2374,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies: dependencies:
is-extglob "^2.1.1" is-extglob "^2.1.1"
is-inside-container@^1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4"
integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==
dependencies:
is-docker "^3.0.0"
is-interactive@^1.0.0: is-interactive@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" resolved "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
@ -2537,16 +2401,6 @@ is-plain-object@^2.0.4:
dependencies: dependencies:
isobject "^3.0.1" isobject "^3.0.1"
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
is-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
is-unicode-supported@^0.1.0: is-unicode-supported@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" resolved "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
@ -2584,17 +2438,13 @@ isobject@^3.0.1:
resolved "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" resolved "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
"jl-graphic@git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#v0.1.0": "jl-graphic@git+https://gitea.joylink.club/joylink/graphic-pixi.git#v0.1.15":
version "0.0.1" version "0.1.14"
resolved "git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#95de26aad236a7ed2bed23bf82d1c28cbcc7bc73" resolved "git+https://gitea.joylink.club/joylink/graphic-pixi.git#8b0ad14f7324a5eaba58239645a1fa0452e87ab4"
dependencies: dependencies:
"@pixi/graphics-extras" "^7.3.2" "@pixi/graphics-extras" "^7.3.2"
"@pixi/utils" "^7.3.2" "@pixi/utils" "^7.3.2"
"@rollup/plugin-alias" "^5.1.0"
"@stomp/stompjs" "^7.0.0" "@stomp/stompjs" "^7.0.0"
eslint "^8.55.0"
eslint-config-prettier "^9.1.0"
eslint-plugin-prettier "^5.0.1"
mqtt "^5.2.1" mqtt "^5.2.1"
pixi-viewport "^5.0.1" pixi-viewport "^5.0.1"
pixi.js "^7.3.2" pixi.js "^7.3.2"
@ -2771,11 +2621,6 @@ merge-descriptors@1.0.1:
resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
merge-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
merge2@^1.3.0, merge2@^1.4.1: merge2@^1.3.0, merge2@^1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" resolved "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
@ -2816,11 +2661,6 @@ mimic-fn@^2.1.0:
resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mimic-fn@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2" version "3.1.2"
resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@ -2934,20 +2774,6 @@ normalize-range@^0.1.2:
resolved "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" resolved "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
npm-run-path@^4.0.1:
version "4.0.1"
resolved "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
dependencies:
path-key "^3.0.0"
npm-run-path@^5.1.0:
version "5.1.0"
resolved "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00"
integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==
dependencies:
path-key "^4.0.0"
nth-check@^2.1.1: nth-check@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" resolved "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
@ -2987,20 +2813,13 @@ once@^1.3.0, once@^1.4.0:
dependencies: dependencies:
wrappy "1" wrappy "1"
onetime@^5.1.0, onetime@^5.1.2: onetime@^5.1.0:
version "5.1.2" version "5.1.2"
resolved "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" resolved "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
dependencies: dependencies:
mimic-fn "^2.1.0" mimic-fn "^2.1.0"
onetime@^6.0.0:
version "6.0.0"
resolved "https://registry.npmmirror.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
dependencies:
mimic-fn "^4.0.0"
open@^8.4.0: open@^8.4.0:
version "8.4.2" version "8.4.2"
resolved "https://registry.npmmirror.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" resolved "https://registry.npmmirror.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
@ -3010,16 +2829,6 @@ open@^8.4.0:
is-docker "^2.1.1" is-docker "^2.1.1"
is-wsl "^2.2.0" is-wsl "^2.2.0"
open@^9.1.0:
version "9.1.0"
resolved "https://registry.npmmirror.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6"
integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==
dependencies:
default-browser "^4.0.0"
define-lazy-prop "^3.0.0"
is-inside-container "^1.0.0"
is-wsl "^2.2.0"
optionator@^0.9.3: optionator@^0.9.3:
version "0.9.3" version "0.9.3"
resolved "https://registry.npmmirror.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" resolved "https://registry.npmmirror.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
@ -3095,16 +2904,11 @@ path-is-absolute@^1.0.0:
resolved "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" resolved "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
path-key@^3.0.0, path-key@^3.1.0: path-key@^3.1.0:
version "3.1.1" version "3.1.1"
resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
path-key@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
path-parse@^1.0.7: path-parse@^1.0.7:
version "1.0.7" version "1.0.7"
resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
@ -3206,13 +3010,6 @@ prelude-ls@^1.2.1:
resolved "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" resolved "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
prettier-linter-helpers@^1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
dependencies:
fast-diff "^1.1.2"
prettier@^2.5.1: prettier@^2.5.1:
version "2.8.8" version "2.8.8"
resolved "https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" resolved "https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
@ -3453,13 +3250,6 @@ rollup-plugin-visualizer@^5.5.4:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
run-applescript@^5.0.0:
version "5.0.0"
resolved "https://registry.npmmirror.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c"
integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==
dependencies:
execa "^5.0.0"
run-async@^2.4.0: run-async@^2.4.0:
version "2.4.1" version "2.4.1"
resolved "https://registry.npmmirror.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" resolved "https://registry.npmmirror.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
@ -3599,7 +3389,7 @@ side-channel@^1.0.4:
get-intrinsic "^1.0.2" get-intrinsic "^1.0.2"
object-inspect "^1.9.0" object-inspect "^1.9.0"
signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: signal-exit@^3.0.2:
version "3.0.7" version "3.0.7"
resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
@ -3609,11 +3399,6 @@ slash@^3.0.0:
resolved "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" resolved "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
slash@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7"
integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
slice-ansi@^4.0.0: slice-ansi@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" resolved "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
@ -3683,16 +3468,6 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
dependencies: dependencies:
ansi-regex "^5.0.1" ansi-regex "^5.0.1"
strip-final-newline@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
strip-final-newline@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
strip-json-comments@^3.1.1: strip-json-comments@^3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
@ -3710,14 +3485,6 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
synckit@^0.8.5:
version "0.8.6"
resolved "https://registry.npmmirror.com/synckit/-/synckit-0.8.6.tgz#b69b7fbce3917c2673cbdc0d87fb324db4a5b409"
integrity sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA==
dependencies:
"@pkgr/utils" "^2.4.2"
tslib "^2.6.2"
table@^6.8.0: table@^6.8.0:
version "6.8.1" version "6.8.1"
resolved "https://registry.npmmirror.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" resolved "https://registry.npmmirror.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf"
@ -3750,11 +3517,6 @@ through@^2.3.6:
resolved "https://registry.npmmirror.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.npmmirror.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
titleize@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53"
integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==
tmp@^0.0.33: tmp@^0.0.33:
version "0.0.33" version "0.0.33"
resolved "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" resolved "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@ -3784,7 +3546,7 @@ tslib@^1.8.1:
resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.1.0, tslib@^2.6.0, tslib@^2.6.2: tslib@^2.1.0, tslib@^2.6.2:
version "2.6.2" version "2.6.2"
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" resolved "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
@ -3851,11 +3613,6 @@ unpipe@1.0.0, unpipe@~1.0.0:
resolved "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" resolved "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
untildify@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
update-browserslist-db@^1.0.13: update-browserslist-db@^1.0.13:
version "1.0.13" version "1.0.13"
resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"