Compare commits
349 Commits
Author | SHA1 | Date | |
---|---|---|---|
4a0d65683d | |||
|
a74efe77f0 | ||
|
e1c4cd8a1a | ||
|
3aa3038504 | ||
|
ea84c6ecdd | ||
|
12f0bdf6d2 | ||
|
e699ac3ef3 | ||
|
c8580b9d42 | ||
|
17fdddb17e | ||
|
91d290abf1 | ||
|
a0b9e27e71 | ||
|
e97a677c3b | ||
|
b604fbd59c | ||
|
0cec0db90a | ||
|
3b6da014ed | ||
|
418ee1a269 | ||
|
b374bcddb1 | ||
|
0a96d88efc | ||
|
8cd499c355 | ||
|
77afce4d1d | ||
|
10271fc959 | ||
|
db277254f9 | ||
|
5af0362c0e | ||
|
cc9e593916 | ||
|
f2a59743cb | ||
|
c95ddf4372 | ||
|
4ac1338b85 | ||
|
d41843a10a | ||
|
693e1de289 | ||
|
c06a9d7e85 | ||
|
d94ae6b975 | ||
|
938559a0a9 | ||
|
2349f81149 | ||
|
ff655373ed | ||
|
5d83a368e0 | ||
|
8d926b37cd | ||
|
64569f9b3c | ||
|
9edc6971ca | ||
|
232536ae34 | ||
|
c72b11fd81 | ||
|
c0219744ff | ||
|
322c81fb45 | ||
|
4c807dc273 | ||
|
ff93c4d825 | ||
|
30a36121ad | ||
|
ca296a2a97 | ||
|
c8f62ff5a0 | ||
|
13d9e8615a | ||
|
ef47f4df5e | ||
|
5c8ef2ad03 | ||
|
91f1ad4f46 | ||
|
4394a9814f | ||
|
d032bdf036 | ||
|
266f1ce829 | ||
|
c343e80428 | ||
|
bd84045111 | ||
|
4f1e58aac6 | ||
|
1f6e55a0dc | ||
|
4bf4aa13d7 | ||
|
623f538399 | ||
|
8b7aa520d1 | ||
|
c971f5fdb6 | ||
|
47375663a2 | ||
|
674ffc598f | ||
|
6141e48bc7 | ||
|
37915f60f4 | ||
|
f345c17a1d | ||
|
ea54841d8a | ||
|
ea363b44cd | ||
|
6f4d1f8c05 | ||
|
b90522ec42 | ||
|
6cbbbc2df8 | ||
|
30e5445997 | ||
|
5dc1d2ce35 | ||
|
7aec94a34c | ||
|
463620a75b | ||
|
036fddf8fe | ||
|
49bfd7e346 | ||
|
9edfdfa935 | ||
|
9a5bc59184 | ||
|
7ec224e954 | ||
|
3a387e8cb3 | ||
|
3bdb6304a1 | ||
|
50af8c6c52 | ||
|
3a2324b274 | ||
|
1ae91da1cd | ||
|
1f6955e4a2 | ||
|
9d56dfd106 | ||
|
bb10c84c91 | ||
|
2d68f9631b | ||
|
763a4f059c | ||
|
a534e941ee | ||
|
37fa4b17e4 | ||
|
f769d1148f | ||
|
73791597f1 | ||
|
22def6e5ff | ||
|
cb39384b42 | ||
|
ef8cabe774 | ||
|
d2f0668323 | ||
|
c5f033a598 | ||
|
f126cef711 | ||
|
5f1999adfb | ||
|
c221bd6d56 | ||
|
26b0ba9b3a | ||
|
157398ac9b | ||
|
763136c4e6 | ||
|
a2513a7e55 | ||
|
f6d3ccc7e4 | ||
|
96298d4d60 | ||
|
306d624508 | ||
|
a2bf56da76 | ||
|
c8685a9213 | ||
|
4c384ec372 | ||
|
3305ec024e | ||
|
dc8425559f | ||
|
113e1edb28 | ||
|
da13d24e7f | ||
|
e427cc3748 | ||
|
64c3678d08 | ||
|
e74fce268e | ||
|
37a81de2ce | ||
|
8149d6d6f1 | ||
|
60f97b5ea3 | ||
|
f0d7f13ae9 | ||
|
94adee376c | ||
|
c253ee4461 | ||
|
89dcf0e28d | ||
|
a79f6c71eb | ||
|
58b04e3024 | ||
|
ce8b36179d | ||
|
6070c127fe | ||
|
199c06560e | ||
|
4dd2d5a046 | ||
|
95b6f380b9 | ||
|
6b7411bccd | ||
|
4104017e31 | ||
|
f04d74e660 | ||
|
09e3333a0d | ||
|
73b00b10aa | ||
|
b965bd7c77 | ||
|
db705bf0e3 | ||
|
03b8ebd4f1 | ||
|
ff8a4f1c07 | ||
|
3a8e48b06f | ||
|
b988cf146a | ||
|
96407b6d1c | ||
|
4eb6f82f33 | ||
|
7dcd8cac17 | ||
|
01f2e9cccf | ||
|
060b909a9f | ||
|
5c081c99a8 | ||
|
43dffe1c4b | ||
|
8146ee4f79 | ||
|
9392e28258 | ||
|
3ade4996d3 | ||
|
421fa1e545 | ||
|
e54ba3ba51 | ||
|
7a7d8e18f0 | ||
|
4b891b97f4 | ||
|
3dcc701050 | ||
|
307d2f778a | ||
|
1ac416e7a4 | ||
|
fc619890fe | ||
|
490fdab81d | ||
|
dad0a34339 | ||
|
303876413a | ||
|
b5716e181b | ||
|
450780677e | ||
|
c7d0bbe9bc | ||
|
50558f46c7 | ||
|
2b6ca6e010 | ||
|
be75846529 | ||
|
31682d9f28 | ||
|
1f32be8ce1 | ||
|
0686831059 | ||
|
a1c73423f2 | ||
|
238edf7869 | ||
|
65b70debed | ||
|
7d18f8dca7 | ||
|
b615906e8c | ||
|
d965af29d9 | ||
|
7229abfc62 | ||
|
b54e3a77fc | ||
|
c153582c3a | ||
|
6a80bd0473 | ||
|
30f645bf0a | ||
|
67c8eb8dfb | ||
|
f2e16f8312 | ||
|
dba7d34f1a | ||
|
c0ebe15789 | ||
|
c38fa9d8b3 | ||
|
8f27d88af4 | ||
|
caed6c021d | ||
|
fb8e0df87d | ||
|
1ec8e86ee8 | ||
|
7f292426c8 | ||
|
bad9c90983 | ||
|
f8e6f60e6f | ||
|
cc077e3f21 | ||
|
f63ec5b12c | ||
|
eb07afb452 | ||
|
dee86e132f | ||
|
32cfc5f329 | ||
|
a2c0bceb2d | ||
|
73379f4bd3 | ||
|
d96778aa7a | ||
|
f980c4f557 | ||
|
97fa9307b7 | ||
|
c0d55ccee6 | ||
|
be5408aedc | ||
|
ed3eb1ea9a | ||
|
0f83f9e004 | ||
|
ae23f7de71 | ||
|
e35637524d | ||
|
041052113a | ||
|
e402fc8f6a | ||
|
debdde142e | ||
|
0ab592a01d | ||
|
6f2c573411 | ||
|
b5795f19e0 | ||
|
7d6e9c6161 | ||
|
1535755414 | ||
|
da829d4d54 | ||
|
e388069ff1 | ||
|
3fbc2f20f0 | ||
|
6df6aa6b3a | ||
|
030bea1293 | ||
|
4e72128bbd | ||
|
13e7d78f1b | ||
|
1b0582979f | ||
|
31c520359c | ||
|
cc45d794e9 | ||
|
4915d0c9ce | ||
|
264d1a696c | ||
|
057554d224 | ||
|
007e340ae2 | ||
|
283e576442 | ||
|
91c6290513 | ||
|
9901c2334f | ||
|
e46997271a | ||
|
3036016928 | ||
|
c3d4c7cc12 | ||
|
1ce48a45d0 | ||
|
49d5f6c0ac | ||
|
fa213a9225 | ||
|
3ab1ee41a1 | ||
|
104656affb | ||
|
b2b8eb6c4f | ||
|
ad7a6db096 | ||
|
f81690be14 | ||
|
4293d4e8e0 | ||
|
06f453a686 | ||
|
c881d48145 | ||
|
5d5527f692 | ||
|
2af63042f5 | ||
|
e388576562 | ||
|
6768738344 | ||
|
513debd156 | ||
|
70c6cf571a | ||
|
efd57e13bd | ||
|
b678b64db8 | ||
|
456a8f9aa8 | ||
|
5bb9b1dea2 | ||
|
94a4fb6726 | ||
|
4b53e3c714 | ||
|
c31551eaf7 | ||
|
6925e761dc | ||
|
9ceb537427 | ||
|
268c28c6ac | ||
|
3ea2ce9dae | ||
|
a0fbbf9f69 | ||
|
519db50c87 | ||
|
a0eb49b73b | ||
|
96749d8811 | ||
|
9ea0fdd522 | ||
|
11bc0ba046 | ||
|
68a96b32c2 | ||
|
bba26fcdf1 | ||
|
4db27e9e3c | ||
|
ebbdff239d | ||
|
0c8163e7b5 | ||
|
b35b8892f6 | ||
|
6e76faf9f7 | ||
|
795d6a2199 | ||
|
01b8113a73 | ||
|
52155b6939 | ||
|
7d68bcb16a | ||
|
b0b9dc11b8 | ||
|
72fdc9997c | ||
|
54999a9339 | ||
|
a3f49f67ff | ||
|
9877c7db05 | ||
|
d3e12f5846 | ||
|
b38872c13b | ||
|
8aefbb12e5 | ||
|
9f74f659ad | ||
|
38e85d3dfd | ||
|
87d3fee04e | ||
|
bbee8cc5e1 | ||
|
15c3ae9a16 | ||
|
5082d847bf | ||
|
cde1cc2334 | ||
|
ca7d76b979 | ||
|
32a2c702b5 | ||
|
b2521653c8 | ||
|
8b2a40ef92 | ||
|
4f115f4f58 | ||
|
4d82d8d4f2 | ||
|
fbf4eb56d3 | ||
|
e22b1f4d1f | ||
|
2dd92f7b0c | ||
|
d684043743 | ||
|
5fb9bb0e3c | ||
|
fa4b5e2b7d | ||
|
6983c0feda | ||
|
0a2ecc0bb3 | ||
|
49e810e4ed | ||
|
9a303f7c2c | ||
|
fc770634ee | ||
|
f114be9a98 | ||
|
f0ee9b3080 | ||
|
a737745fd2 | ||
|
b6b1630a91 | ||
|
4656f3147d | ||
|
d14f0a0e8b | ||
|
5a6848b005 | ||
|
8d78f32e72 | ||
|
988eafd521 | ||
|
9d9806beac | ||
|
8e7120b5dd | ||
|
059c905951 | ||
|
c4ed2bde5d | ||
|
bfd937da72 | ||
|
870169a870 | ||
|
6a5bed588f | ||
|
5085de4d6d | ||
|
b130ee33d7 | ||
|
e7c755348b | ||
d04209e756 | |||
61c3c10bd2 | |||
|
d9af13bb46 | ||
|
b6ec60b242 | ||
|
dbde11026c | ||
|
9490392177 | ||
|
53f6d882ab | ||
|
3447055aa5 | ||
|
14bd3b7b65 | ||
|
a3c264312d | ||
|
86cc8754fb |
4
.env.dev-show
Normal file
4
.env.dev-show
Normal file
@ -0,0 +1,4 @@
|
||||
API=test.joylink.club
|
||||
HTTP=https://
|
||||
NS=/ncc
|
||||
WS=wss://
|
4
.env.local
Normal file
4
.env.local
Normal file
@ -0,0 +1,4 @@
|
||||
API=localhost:9081
|
||||
HTTP=http://
|
||||
NS=
|
||||
WS=ws://
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,7 +1,3 @@
|
||||
[submodule "xian-ncc-da-message"]
|
||||
path = xian-ncc-da-message
|
||||
url = https://git.code.tencent.com/xian-ncc-da/xian-ncc-da-message.git
|
||||
[submodule "graphic-pixi"]
|
||||
path = graphic-pixi
|
||||
url = https://git.code.tencent.com/jl-framework/graphic-pixi.git
|
||||
branch = xian-ncc-da
|
||||
|
19
EnvParse.js
Normal file
19
EnvParse.js
Normal file
@ -0,0 +1,19 @@
|
||||
const DotEnv = require('dotenv');
|
||||
|
||||
module.exports = function () {
|
||||
let script = process.env.npm_lifecycle_script;
|
||||
let name = 'dev';
|
||||
if (script) {
|
||||
// quasar启动没有这个
|
||||
script = script.substring(script.indexOf('NODE_ENV=') + 'NODE_ENV='.length);
|
||||
name = script.substring(0, script.indexOf('&'));
|
||||
} else {
|
||||
if (process.env.NODE_ENV == 'production') {
|
||||
name = 'prod';
|
||||
}
|
||||
}
|
||||
console.log(name);
|
||||
name = '.env.' + name;
|
||||
let parsedEnv = DotEnv.config({ path: name }).parsed;
|
||||
return parsedEnv;
|
||||
};
|
@ -1 +1 @@
|
||||
Subproject commit 91eb4a1d0835a8bc007febaf9054291c27d065ff
|
||||
Subproject commit b5ca64750380db0ff8e4e4a56a471363db684e12
|
46
index.html
46
index.html
@ -3,19 +3,43 @@
|
||||
<head>
|
||||
<title><%= productName %></title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="<%= productDescription %>">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="<%= productDescription %>" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta name="msapplication-tap-highlight" content="no" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>"
|
||||
/>
|
||||
|
||||
<link rel="icon" type="image/png" sizes="128x128" href="icons/favicon-128x128.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png">
|
||||
<link rel="icon" type="image/ico" href="favicon.ico">
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="128x128"
|
||||
href="logo/xian_favicon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="96x96"
|
||||
href="logo/xian_favicon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="logo/xian_favicon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href="logo/xian_favicon.png"
|
||||
/>
|
||||
<!-- <link rel="icon" type="image/ico" href="favicon.ico" /> -->
|
||||
<link rel="icon" type="image/png" href="logo/xian_favicon.png" />
|
||||
</head>
|
||||
<body>
|
||||
<body style="overflow: hidden">
|
||||
<!-- quasar:entry-point -->
|
||||
</body>
|
||||
</html>
|
||||
|
17
package.json
17
package.json
@ -9,24 +9,25 @@
|
||||
"lint": "eslint --ext .js,.ts,.vue ./",
|
||||
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
|
||||
"test": "echo \"No test specified\" && exit 0",
|
||||
"dev": "quasar dev",
|
||||
"build": "quasar build",
|
||||
"dev": "set NODE_ENV=dev&&quasar dev",
|
||||
"local": "set NODE_ENV=local&&quasar dev",
|
||||
"build": "set NODE_ENV=dev&&quasar build",
|
||||
"prod": "set NODE_ENV=prod&&quasar build",
|
||||
"dev-show": "set NODE_ENV=dev-show&&quasar build",
|
||||
"protoc": "node scripts/proto.cjs",
|
||||
"sync": "node scripts/sync.cjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pixi/filter-outline": "^5.2.0",
|
||||
"@pixi/graphics-extras": "^7.2.4",
|
||||
"@quasar/extras": "^1.0.0",
|
||||
"@stomp/stompjs": "^7.0.0",
|
||||
"centrifuge": "^4.0.1",
|
||||
"axios": "^1.2.1",
|
||||
"centrifuge": "^4.0.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"google-protobuf": "^3.21.2",
|
||||
"jl-graphic": "git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#v0.1.3",
|
||||
"js-base64": "^3.7.5",
|
||||
"pinia": "^2.0.11",
|
||||
"pixi-viewport": "^5.0.1",
|
||||
"pixi.js": "^7.2.4",
|
||||
"quasar": "^2.6.0",
|
||||
"save-dev": "0.0.1-security",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0"
|
||||
},
|
||||
|
BIN
public/alarmMusic/all-line-blue.mp3
Normal file
BIN
public/alarmMusic/all-line-blue.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/atp-cut.mp3
Normal file
BIN
public/alarmMusic/atp-cut.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/blue.mp3
Normal file
BIN
public/alarmMusic/blue.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/cannot-close.mp3
Normal file
BIN
public/alarmMusic/cannot-close.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/cannot-open.mp3
Normal file
BIN
public/alarmMusic/cannot-open.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/orange-most.mp3
Normal file
BIN
public/alarmMusic/orange-most.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/orange.mp3
Normal file
BIN
public/alarmMusic/orange.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/red-most.mp3
Normal file
BIN
public/alarmMusic/red-most.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/red.mp3
Normal file
BIN
public/alarmMusic/red.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/switch-lost-most.mp3
Normal file
BIN
public/alarmMusic/switch-lost-most.mp3
Normal file
Binary file not shown.
BIN
public/alarmMusic/switch-lost.mp3
Normal file
BIN
public/alarmMusic/switch-lost.mp3
Normal file
Binary file not shown.
BIN
public/logo/NCC.png
Normal file
BIN
public/logo/NCC.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
public/logo/NCC_bai.png
Normal file
BIN
public/logo/NCC_bai.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
public/logo/logoBg.png
Normal file
BIN
public/logo/logoBg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 77 KiB |
BIN
public/logo/xian.jpg
Normal file
BIN
public/logo/xian.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
BIN
public/logo/xian_favicon.png
Normal file
BIN
public/logo/xian_favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
@ -53,10 +53,23 @@ module.exports = configure(function (/* ctx */) {
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
|
||||
build: {
|
||||
target: {
|
||||
browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'],
|
||||
browser: ['es2020'],
|
||||
node: 'node16',
|
||||
},
|
||||
env: require('./EnvParse.js')(),
|
||||
chainWebpack(chain) {
|
||||
chain
|
||||
.plugin('eslint-webpack-plugin')
|
||||
.use(ESLintPlugin, [{ extensions: ['js', 'vue'] }]);
|
||||
|
||||
chain.plugin('define').use(require('webpack/lib/DefinePlugin'), [
|
||||
{
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
|
||||
},
|
||||
},
|
||||
]);
|
||||
},
|
||||
vueRouterMode: 'history', // available values: 'hash', 'history'
|
||||
vueRouterBase: BasePath,
|
||||
// vueDevtools,
|
||||
@ -71,10 +84,16 @@ module.exports = configure(function (/* ctx */) {
|
||||
// ignorePublicFolder: true,
|
||||
// minify: false,
|
||||
// polyfillModulePreload: true,
|
||||
// distDir
|
||||
distDir: 'dist/xianncc',
|
||||
// distDir: `dist/${BasePath}`,
|
||||
|
||||
// extendViteConf (viteConf) {},
|
||||
alias: { 'protobufjs/light': 'protobufjs/dist/light/protobuf.min.js' },
|
||||
|
||||
// extendViteConf(viteConf) {
|
||||
// viteConf.resolve.alias = Object.assign({}, viteConf.resolve.alias, {
|
||||
// 'protobufjs/light': 'protobufjs/dist/light/protobuf.min.js',
|
||||
// });
|
||||
// },
|
||||
// viteVuePluginOptions: {},
|
||||
|
||||
// vitePlugins: [
|
||||
|
@ -1,70 +0,0 @@
|
||||
/**
|
||||
* 同步图形框架文件到 src/jl-graphic/
|
||||
*/
|
||||
const {
|
||||
readdirSync,
|
||||
existsSync,
|
||||
copyFileSync,
|
||||
mkdirSync,
|
||||
rmSync,
|
||||
} = require('fs');
|
||||
const { resolve } = require('path');
|
||||
|
||||
const jlGraphicSrcPath = resolve(__dirname, '../graphic-pixi/src/jlgraphic');
|
||||
const jlGraphicLibPath = resolve(__dirname, '../src/jl-graphic');
|
||||
|
||||
/**
|
||||
* 检查并初始化当前项目引入的jl-graphic库
|
||||
*/
|
||||
function checkAndInitJlGraphicLib() {
|
||||
const exist = existsSync(jlGraphicLibPath);
|
||||
if (exist) {
|
||||
console.log('jl-graphic文件夹已存在,清空');
|
||||
readdirSync(jlGraphicLibPath, {
|
||||
withFileTypes: true,
|
||||
}).forEach((file) => {
|
||||
if (file.isDirectory()) {
|
||||
rmSync(resolve(jlGraphicLibPath, file.name), { recursive: true });
|
||||
} else {
|
||||
rmSync(resolve(jlGraphicLibPath, file.name));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('jl-graphic文件夹不存在,创建');
|
||||
// 文件夹不存在,创建
|
||||
mkdirSync(jlGraphicLibPath);
|
||||
}
|
||||
}
|
||||
|
||||
function copyJlGraphicFiles() {
|
||||
readdirSync(jlGraphicSrcPath, {
|
||||
withFileTypes: true,
|
||||
}).forEach((file) => {
|
||||
recursiveCopyFiles(file);
|
||||
});
|
||||
}
|
||||
|
||||
function recursiveCopyFiles(file, path = []) {
|
||||
if (file.isFile()) {
|
||||
const fileSrcPath = resolve(jlGraphicSrcPath, ...path, file.name);
|
||||
const fileDestPath = resolve(jlGraphicLibPath, ...path, file.name);
|
||||
console.log(`copy file ${fileSrcPath} -> ${fileDestPath}`);
|
||||
copyFileSync(fileSrcPath, fileDestPath);
|
||||
} else if (file.isDirectory()) {
|
||||
const srcDir = resolve(jlGraphicSrcPath, ...path, file.name);
|
||||
const dirPath = resolve(jlGraphicLibPath, ...path, file.name);
|
||||
mkdirSync(dirPath);
|
||||
readdirSync(srcDir, {
|
||||
withFileTypes: true,
|
||||
}).forEach((subFile) => {
|
||||
recursiveCopyFiles(subFile, [...path, file.name]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
checkAndInitJlGraphicLib();
|
||||
copyJlGraphicFiles();
|
||||
}
|
||||
|
||||
main();
|
27
src/api/AlarmThresholdApi.ts
Normal file
27
src/api/AlarmThresholdApi.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
|
||||
const BaseUrl = '/api/config/device';
|
||||
|
||||
export interface ParamsItem {
|
||||
id?: number;
|
||||
lineId: number;
|
||||
configData: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建/修改
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function saveThreshold(data: ParamsItem) {
|
||||
return api.post(`${BaseUrl}/save`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取发布地图详细信息
|
||||
* @param lineId 线路id
|
||||
*/
|
||||
export async function getBaseDataByLineId(lineId: number): Promise<ParamsItem> {
|
||||
const response = await api.get(`${BaseUrl}/initData/${lineId}`);
|
||||
return response.data;
|
||||
}
|
56
src/api/AlarmTipTimeConfig.ts
Normal file
56
src/api/AlarmTipTimeConfig.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto, PageQueryDto } from './ApiCommon';
|
||||
|
||||
const BaseUrl = '/api/alert/tip/time';
|
||||
|
||||
export interface TimeConfigItem {
|
||||
id?: number;
|
||||
timeName: string;
|
||||
startHour: string;
|
||||
endHour: string;
|
||||
timeType: string;
|
||||
publicPeak?: string;
|
||||
}
|
||||
|
||||
export enum TipTimeConfig {
|
||||
假期早高峰 = 'HOLIDAYS_MORN_PEAK',
|
||||
假期晚高峰 = 'HOLIDAYS_EVENING_PEAK',
|
||||
早高峰 = 'MORN_PEAK',
|
||||
晚高峰 = 'EVENING_PEARK',
|
||||
低峰 = 'NORMAL_UNPEARK',
|
||||
}
|
||||
export enum ShowTipTimeConfig {
|
||||
HOLIDAYS_MORN_PEAK = '假期早高峰',
|
||||
HOLIDAYS_EVENING_PEAK = '假期晚高峰',
|
||||
MORN_PEAK = '早高峰',
|
||||
EVENING_PEARK = '晚高峰',
|
||||
NORMAL_UNPEARK = '低峰',
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建/修改时间配置
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export function creatOrEditTimeConfig(data: TimeConfigItem) {
|
||||
return api.post(`${BaseUrl}`, data);
|
||||
}
|
||||
|
||||
class PageQueryParams extends PageQueryDto {
|
||||
timeName?: string;
|
||||
timeType?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取报警提示时间配置列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function alarmTipTimeConfigPageQuery(
|
||||
params: PageQueryParams
|
||||
): Promise<PageDto<TimeConfigItem>> {
|
||||
const response = await api.post(`${BaseUrl}/page`, {
|
||||
params: params,
|
||||
});
|
||||
return response.data;
|
||||
}
|
@ -1,24 +1,68 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto, PageQueryDto } from './ApiCommon';
|
||||
import { AlarmInfo } from './DecisionInfo';
|
||||
|
||||
const alertUriBase = '/api/alert/mock';
|
||||
|
||||
export function mockAlertSet(data: { lineId: number; alertType: string }) {
|
||||
//故障测试
|
||||
export function mockLocalDemoTestSet(
|
||||
alertType: string,
|
||||
data: {
|
||||
lineId: number;
|
||||
deviceInfos: {
|
||||
deviceName: string;
|
||||
deviceType: string;
|
||||
status: string;
|
||||
groupId?: string;
|
||||
}[];
|
||||
}
|
||||
) {
|
||||
return api.post(`${alertUriBase}/localDemoTest/${alertType}`, data);
|
||||
}
|
||||
|
||||
//故障演示
|
||||
export function mockAlertSet(data: {
|
||||
lineId: number;
|
||||
alertType: string;
|
||||
deviceCodes: string[];
|
||||
}) {
|
||||
return api.post(`${alertUriBase}/set`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据设置的故障类型获取需要设置的具体的故障设备
|
||||
* @param id 线路id
|
||||
* @param alertType 故障类型
|
||||
*/
|
||||
export async function getDeviceByAlarmType(
|
||||
id: number,
|
||||
alertType: string
|
||||
): Promise<DeviceConfigItem[]> {
|
||||
const response = await api.post(`${alertUriBase}/find/${id}/${alertType}`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export interface DeviceConfigItem {
|
||||
name: string;
|
||||
code: string;
|
||||
}
|
||||
|
||||
export class PagingQueryParams extends PageQueryDto {
|
||||
alertType?: string;
|
||||
lineId?: number;
|
||||
beginDateTime?: string;
|
||||
endDateTime?: string;
|
||||
alertStatus?: number;
|
||||
}
|
||||
|
||||
interface Item {
|
||||
export interface Item {
|
||||
id: number;
|
||||
alertType: string;
|
||||
timeType: string;
|
||||
locationType: string;
|
||||
drivingInfo: string;
|
||||
submissionInfo: string;
|
||||
alarmStatus: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -29,8 +73,70 @@ interface Item {
|
||||
export async function alarmInfoListQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<Item>> {
|
||||
const response = await api.get('/api/alertRecord/page/detail', {
|
||||
params: params,
|
||||
});
|
||||
const response = await api.post('/api/alertRecord/page/detail', params);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认报警处理
|
||||
* @param id 推送的警告信息的id
|
||||
* @param tipType 故障类型
|
||||
* @param alertLocationId 故障范围对应的列表id
|
||||
*/
|
||||
export function recordConfirmAlarmInfoByTipType(
|
||||
id: number,
|
||||
tipType: string,
|
||||
alertLocationId?: number
|
||||
): Promise<AlarmInfo<Item>> {
|
||||
return api.get(`/api/alertRecord/confirm/${id}/${tipType}`, {
|
||||
params: { alertLocationId: alertLocationId },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误报警处理--误报
|
||||
* @param recordId 推送的警告信息的id
|
||||
*/
|
||||
export function recordFailAlarmInfoById(recordId: number) {
|
||||
return api.post(`/api/alertRecord/fail/${recordId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误报警处理--人工报警和一键确定
|
||||
* @param recordId 推送的警告信息的id
|
||||
*/
|
||||
export function recordManualAlarmInfoById(recordId: number[]) {
|
||||
return api.post('/api/alertRecord/warn', recordId);
|
||||
}
|
||||
|
||||
export interface IReportParams {
|
||||
alertTypes?: string[];
|
||||
beginDateTime?: string;
|
||||
endDateTime?: string;
|
||||
alertStatus?: number;
|
||||
}
|
||||
|
||||
interface IReportRes {
|
||||
alertType: string;
|
||||
counter: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 报警统计
|
||||
* @param lineId 线路id
|
||||
*/
|
||||
export async function recordAlarmReport(
|
||||
lineId: number,
|
||||
data: IReportParams
|
||||
): Promise<IReportRes[]> {
|
||||
const response = await api.post(`/api/alertRecord/report/${lineId}`, data);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* @param linId 线路的id
|
||||
*/
|
||||
export function resetApi(linId: number): Promise<string> {
|
||||
return api.get(`${alertUriBase}/reset/${linId}`);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ export class OrderItemDto {
|
||||
}
|
||||
}
|
||||
|
||||
export interface PageDto<T = unknown> {
|
||||
export interface PageDto<T> {
|
||||
records: T[];
|
||||
/**
|
||||
* 记录总数
|
||||
|
65
src/api/ConfigApi.ts
Normal file
65
src/api/ConfigApi.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto, PageQueryDto } from './ApiCommon';
|
||||
|
||||
export interface IAreaConfigListItem {
|
||||
id: number;
|
||||
lineId: number;
|
||||
areaName: string;
|
||||
deviceType: string;
|
||||
}
|
||||
|
||||
export async function getDeviceAreaList({
|
||||
lineId,
|
||||
deviceType,
|
||||
current,
|
||||
size,
|
||||
areaName,
|
||||
}: {
|
||||
lineId?: string;
|
||||
deviceType?: string;
|
||||
areaName?: string;
|
||||
} & PageQueryDto) {
|
||||
const resp = await api.get<PageDto<IAreaConfigListItem>>(
|
||||
`/api/config/device/area/page/${lineId}`,
|
||||
{ params: { current, size, deviceType, areaName } }
|
||||
);
|
||||
if (resp.status === 200) {
|
||||
return resp.data;
|
||||
} else {
|
||||
throw Error(resp.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteDeviceArea(id: number) {
|
||||
const resp = await api.delete(`/api/config/device/area/${id}`);
|
||||
if (resp.status === 200) {
|
||||
return resp;
|
||||
} else {
|
||||
throw Error(resp.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
export interface IAreaConfigItem {
|
||||
id?: number;
|
||||
lineId: number;
|
||||
areaName: string;
|
||||
deviceType: string;
|
||||
alertTypes: string[];
|
||||
data: number[];
|
||||
}
|
||||
export function deviceRangeSet(data: IAreaConfigItem) {
|
||||
return api.post('/api/config/device/area/save', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取配置信息
|
||||
* @param id 配置列表id
|
||||
*/
|
||||
export function queryDeviceRangeById(
|
||||
id: number
|
||||
): Promise<IAreaConfig<IAreaConfigItem>> {
|
||||
return api.get(`/api/config/device/area/${id}`);
|
||||
}
|
||||
interface IAreaConfig<T = unknown> {
|
||||
data: T;
|
||||
}
|
@ -1,29 +1,36 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto, PageQueryDto } from './ApiCommon';
|
||||
import { TimeConfigItem } from './AlarmTipTimeConfig';
|
||||
|
||||
const DraftUriBase = '/api/alertTip';
|
||||
const AlertTipUriBase = '/api/alertTip';
|
||||
|
||||
export interface createParams {
|
||||
interface AlarmInfoCreateParams {
|
||||
id: number;
|
||||
alertType: string;
|
||||
timeType: string;
|
||||
locationType: string;
|
||||
tipTimeIds: string[];
|
||||
areaConfigId: number;
|
||||
drivingInfo: string;
|
||||
submissionInfo: string;
|
||||
}
|
||||
|
||||
interface Item {
|
||||
export interface AlarmInfoListItem {
|
||||
id: number;
|
||||
alertType: string;
|
||||
timeType: string;
|
||||
locationType: string;
|
||||
timeConfigList: TimeConfigItem[];
|
||||
areaConfigId: number;
|
||||
drivingInfo: string;
|
||||
submissionInfo: string;
|
||||
areaConfigName?: string;
|
||||
}
|
||||
|
||||
export interface AlarmInfo<T = unknown> {
|
||||
data: T;
|
||||
}
|
||||
|
||||
export class PagingQueryParams extends PageQueryDto {
|
||||
alertType?: string;
|
||||
timeType?: string;
|
||||
locationType?: string;
|
||||
areaConfigName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,8 +40,8 @@ export class PagingQueryParams extends PageQueryDto {
|
||||
*/
|
||||
export async function alarmInfoPageQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<Item>> {
|
||||
const response = await api.get(`${DraftUriBase}/page`, {
|
||||
): Promise<PageDto<AlarmInfoListItem>> {
|
||||
const response = await api.get(`${AlertTipUriBase}/page`, {
|
||||
params: params,
|
||||
});
|
||||
return response.data;
|
||||
@ -44,17 +51,29 @@ export async function alarmInfoPageQuery(
|
||||
* 根据id获取决策信息
|
||||
* @param id 草稿id
|
||||
*/
|
||||
export function queryAlarmInfoById(id: number): Promise<AlarmInfo<Item>> {
|
||||
return api.get(`${DraftUriBase}/id/${id}`);
|
||||
export function queryAlarmInfoById(
|
||||
id: number
|
||||
): Promise<AlarmInfo<AlarmInfoListItem>> {
|
||||
return api.get(`${AlertTipUriBase}/id/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建决策信息
|
||||
* 根据报警类型获取决策信息
|
||||
* @param type 草稿type
|
||||
*/
|
||||
export function queryAlarmInfoByType(
|
||||
type: string
|
||||
): Promise<AlarmInfo<AlarmInfoListItem>> {
|
||||
return api.get(`${AlertTipUriBase}/type/${type}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建或编辑决策信息
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function createAlarmInfo(draftData: createParams) {
|
||||
return api.post(`${DraftUriBase}`, draftData);
|
||||
export function createAlarmInfo(draftData: AlarmInfoCreateParams) {
|
||||
return api.post(`${AlertTipUriBase}`, draftData);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,18 +81,26 @@ export function createAlarmInfo(draftData: createParams) {
|
||||
* @param id 草稿id
|
||||
*/
|
||||
export function deleteAlarmInfo(id: number) {
|
||||
return api.delete(`${DraftUriBase}/id/${id}`);
|
||||
return api.delete(`${AlertTipUriBase}/id/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新决策信息
|
||||
* @param data
|
||||
* @returns
|
||||
* 根据故障类型获取对应的范围配置
|
||||
* @param id 线路id
|
||||
* @param tipType 故障类型
|
||||
*/
|
||||
export function updataAlarmInfo(id: number, data: Item) {
|
||||
return api.put(`${DraftUriBase}/id`, data);
|
||||
export async function getDeviceAreaByAlarmType(
|
||||
id: number,
|
||||
alertType: string
|
||||
): Promise<AreaConfigItem[]> {
|
||||
const response = await api.post(
|
||||
`${AlertTipUriBase}/find/type/${id}/${alertType}`,
|
||||
{}
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export interface AlarmInfo<T = unknown> {
|
||||
data: T;
|
||||
export interface AreaConfigItem {
|
||||
id: number;
|
||||
areaName: string;
|
||||
}
|
||||
|
@ -2,39 +2,39 @@ import { api } from 'src/boot/axios';
|
||||
|
||||
const platformUriBase = '/mock/platform/status';
|
||||
const stationUriBase = '/mock/rtu/status';
|
||||
const serverUriBase = '/mock/server/send';
|
||||
|
||||
export function mockPlatformApi(
|
||||
lineId: number,
|
||||
data: {
|
||||
emergstop: boolean;
|
||||
trainberth: boolean;
|
||||
close: boolean;
|
||||
upHold: boolean;
|
||||
downHold: boolean;
|
||||
upOccHold: boolean;
|
||||
downOccHold: boolean;
|
||||
psdOpen: boolean;
|
||||
psdCut: boolean;
|
||||
upSkipstop: boolean;
|
||||
downSkipstop: boolean;
|
||||
upTrainSkipstop: boolean;
|
||||
downTrainSkipstop: boolean;
|
||||
id: string;
|
||||
nextSectionRunTime: 0;
|
||||
nextSectionRunLevel: 0;
|
||||
stopTime: 0;
|
||||
}
|
||||
) {
|
||||
export interface mockPlatformParams {
|
||||
emergstop: boolean;
|
||||
trainberth: boolean;
|
||||
close: boolean;
|
||||
upHold: boolean;
|
||||
downHold: boolean;
|
||||
upOccHold: boolean;
|
||||
downOccHold: boolean;
|
||||
psdOpen: boolean;
|
||||
psdCut: boolean;
|
||||
upSkipstop: boolean;
|
||||
downSkipstop: boolean;
|
||||
upTrainSkipstop: boolean;
|
||||
downTrainSkipstop: boolean;
|
||||
id: string;
|
||||
nextSectionRunTime: number;
|
||||
nextSectionRunLevel: number;
|
||||
stopTime: number;
|
||||
}
|
||||
|
||||
export function mockPlatformApi(lineId: number, data: mockPlatformParams) {
|
||||
return api.post(`${platformUriBase}/${lineId}`, data);
|
||||
}
|
||||
|
||||
export function mockStationApi(
|
||||
lineId: number,
|
||||
data: {
|
||||
ipRtuStusDown: true;
|
||||
ipRtuStusInLocalCtrl: true;
|
||||
ipRtuStusInCentralCtrl: true;
|
||||
ipRtuStusInEmergencyCtrl: true;
|
||||
ipRtuStusDown: boolean;
|
||||
ipRtuStusInLocalCtrl: boolean;
|
||||
ipRtuStusInCentralCtrl: boolean;
|
||||
ipRtuStusInEmergencyCtrl: boolean;
|
||||
id: string;
|
||||
}
|
||||
) {
|
||||
@ -72,3 +72,14 @@ export function mockSignalApi(
|
||||
) {
|
||||
return api.post(`/mock/signal/status/${lineId}`, data);
|
||||
}
|
||||
|
||||
export function mockServerApi(data: {
|
||||
deviceType: string;
|
||||
messageId: string;
|
||||
lineId: number;
|
||||
rtuId: number;
|
||||
deviceName: string;
|
||||
deviceStatus: number;
|
||||
}) {
|
||||
return api.post(serverUriBase, data);
|
||||
}
|
||||
|
@ -44,6 +44,21 @@ export enum DevType {
|
||||
DEVICE_TYPE_GAMA = 'DEVICE_TYPE_GAMA',
|
||||
}
|
||||
|
||||
export const deviceTypeMap = {
|
||||
DEVICE_TYPE_UNKNOW: '未知设备',
|
||||
DEVICE_TYPE_RTU: '集中站',
|
||||
DEVICE_TYPE_STATION: '车站',
|
||||
DEVICE_TYPE_SIGNAL: '信号机',
|
||||
DEVICE_TYPE_SWITCH: '道岔',
|
||||
DEVICE_TYPE_TRACK: '轨道',
|
||||
DEVICE_TYPE_ENTRY: '方向设备',
|
||||
DEVICE_TYPE_PLATFORM: '站台',
|
||||
DEVICE_TYPE_SCADA: '供电区段',
|
||||
DEVICE_TYPE_WATERPROOF_DOOR: '防淹门',
|
||||
DEVICE_TYPE_WORK_AREA: '工作区',
|
||||
DEVICE_TYPE_GAMA: '区域自动驾驶',
|
||||
};
|
||||
|
||||
export function trainMockApi(
|
||||
lineId: number,
|
||||
data: {
|
||||
|
@ -1,7 +1,4 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { ITurnoutState } from 'src/graphics/turnout/Turnout';
|
||||
|
||||
const base = '/mock/train';
|
||||
|
||||
interface State {
|
||||
id: string;
|
||||
@ -37,9 +34,6 @@ interface State {
|
||||
|
||||
export async function setSwitchStatus(lineId: string, state: State) {
|
||||
try {
|
||||
delete state._state;
|
||||
delete state._graphicType;
|
||||
state.speedLimit = 0;
|
||||
return await api.post(`/mock/switch/status/${lineId}`, state);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@ -47,8 +41,6 @@ export async function setSwitchStatus(lineId: string, state: State) {
|
||||
}
|
||||
export async function setTrackStatus(lineId: string, state: State) {
|
||||
try {
|
||||
delete state._state;
|
||||
delete state._graphicType;
|
||||
return await api.post(`/mock/track/status/${lineId}`, state);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
80
src/components/ConnectInfoDialog.vue
Normal file
80
src/components/ConnectInfoDialog.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
ref="dialogRef"
|
||||
@show="onDialogShow"
|
||||
seamless
|
||||
title="与卡斯柯连接状态信息"
|
||||
:width="300"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
v-model:pagination="pagination"
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
@request="onRequest"
|
||||
:rows-per-page-options="[10, 20, 50, 100]"
|
||||
>
|
||||
</q-table>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import DraggableDialog from './common/DraggableDialog.vue';
|
||||
import { QTable } from 'quasar';
|
||||
import { useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { state } from 'src/protos/system_warn_message';
|
||||
|
||||
const lineNetStore = useLineNetStore();
|
||||
const dialogRef = ref<InstanceType<typeof DraggableDialog>>();
|
||||
const tableRef = ref<QTable>();
|
||||
const columns: QTable['columns'] = [
|
||||
{ name: 'lineId', label: '线路ID', field: 'lineId', align: 'center' },
|
||||
{
|
||||
name: 'areaName',
|
||||
label: '实时连接',
|
||||
field: (row) => (row.occRealConned ? '是' : '否'),
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'deviceType',
|
||||
label: '非实时连接',
|
||||
field: (row) => (row.occUnrealConned ? '是' : '否'),
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
const rows = ref<state.WarnMessage[]>([]);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
watch(
|
||||
() => lineNetStore.connectInfo,
|
||||
() => {
|
||||
onDialogShow();
|
||||
}
|
||||
);
|
||||
|
||||
const onRequest: QTable['onRequest'] = async (props) => {
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
pagination.value.page = page;
|
||||
pagination.value.rowsPerPage = rowsPerPage;
|
||||
const datas = lineNetStore.connectInfo?.msgs;
|
||||
if (datas) {
|
||||
rows.value = datas.slice((page - 1) * rowsPerPage, page * rowsPerPage - 1);
|
||||
pagination.value.rowsNumber = datas.length;
|
||||
}
|
||||
};
|
||||
|
||||
const onDialogShow = () => {
|
||||
tableRef.value?.requestServerInteraction();
|
||||
};
|
||||
</script>
|
30
src/components/DrawAppFormUtils.ts
Normal file
30
src/components/DrawAppFormUtils.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { type GraphicDataBase } from 'src/drawApp/graphics/GraphicDataBase';
|
||||
import { IDrawApp, JlGraphic } from 'jl-graphic';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, onUnmounted, reactive } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
export function useFormData<T extends GraphicDataBase>(
|
||||
source: T,
|
||||
app: IDrawApp
|
||||
) {
|
||||
const data = reactive<T>(source);
|
||||
|
||||
onMounted(() => {
|
||||
app.bindFormData(data);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
app.unbindFormData(data);
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const graphic = drawStore.selectedGraphic as JlGraphic;
|
||||
if (graphic) {
|
||||
app.updateGraphicAndRecord(graphic, data);
|
||||
}
|
||||
}
|
||||
|
||||
return { data, onUpdate };
|
||||
}
|
@ -43,16 +43,14 @@ import { reactive } from 'vue';
|
||||
|
||||
const list = reactive([
|
||||
{
|
||||
path: '',
|
||||
label: '系统管理',
|
||||
icon: 'dataset',
|
||||
children: [
|
||||
{
|
||||
path: '/sysManage/user',
|
||||
label: '用户管理',
|
||||
icon: 'manage_accounts',
|
||||
},
|
||||
],
|
||||
path: '/monitor',
|
||||
label: '监控',
|
||||
icon: 'computer',
|
||||
},
|
||||
{
|
||||
path: '/alarmList',
|
||||
label: '报警列表',
|
||||
icon: 'access_alarm',
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
@ -67,24 +65,41 @@ const list = reactive([
|
||||
{
|
||||
path: '/dataManage/publish',
|
||||
label: '发布管理',
|
||||
icon: 'app_registration',
|
||||
icon: 'playlist_add_check',
|
||||
},
|
||||
{
|
||||
path: '/dataManage/lineInfo',
|
||||
label: '线路信息管理',
|
||||
icon: 'app_registration',
|
||||
icon: 'format_list_numbered',
|
||||
},
|
||||
{
|
||||
path: '/dataManage/decisionInfo',
|
||||
label: '决策信息管理',
|
||||
icon: 'app_registration',
|
||||
icon: 'format_align_center',
|
||||
},
|
||||
{
|
||||
path: '/dataManage/thresholdValue',
|
||||
label: '报警故障阈值配置',
|
||||
icon: 'format_indent_increase',
|
||||
},
|
||||
{
|
||||
path: '/dataManage/alarmTipTimeConfig',
|
||||
label: '报警提示时间配置',
|
||||
icon: 'access_time',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/monitor',
|
||||
label: '监控',
|
||||
icon: 'computer',
|
||||
path: '',
|
||||
label: '系统管理',
|
||||
icon: 'dataset',
|
||||
children: [
|
||||
{
|
||||
path: '/sysManage/user',
|
||||
label: '用户管理',
|
||||
icon: 'manage_accounts',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
v-model="showDialog"
|
||||
seamless
|
||||
title="报警"
|
||||
:titleColor="`${bgColor}`"
|
||||
@ -8,6 +9,7 @@
|
||||
:width="dialogWidth"
|
||||
fontColor=""
|
||||
:height="0"
|
||||
bgBorder="solid 2px black"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
@ -17,18 +19,52 @@
|
||||
<q-separator />
|
||||
<div class="alarm-message-detail">
|
||||
<div class="left">
|
||||
<div class="text">时间:{{ alarmInfo.time }}</div>
|
||||
<div class="text">级别:{{ alarmInfo.level }}</div>
|
||||
<div class="text">线路:{{ alarmInfo.lineId }}号线</div>
|
||||
<div class="text">时间:{{ alarmInfo.time }}</div>
|
||||
<div class="text">级别:{{ alarmInfo.level }}</div>
|
||||
<div class="text">线路:{{ alarmInfo.lineId }}号线</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="text">设备:{{ alarmInfo.alertObject }}</div>
|
||||
<div class="text">类型:{{ alarmInfo.alertType }}</div>
|
||||
<div class="text">设备:{{ alarmInfo.alertObject }}</div>
|
||||
<div class="text" v-if="!showFaultType">
|
||||
类型:{{ alarmInfo.alertType }}
|
||||
</div>
|
||||
<div class="text" v-else>类型:{{ faultType }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
<div class="decision-message">
|
||||
<div class="confirm-message" v-if="showConfirmMmessage">
|
||||
<q-card class="box-card">
|
||||
<div class="head">选择故障类型</div>
|
||||
<q-separator />
|
||||
<q-form class="detail" ref="myForm" @submit="confirmAlarm">
|
||||
<q-select
|
||||
style="width: 200px"
|
||||
dense
|
||||
outlined
|
||||
v-model="faultType"
|
||||
:options="faultTypeOptions"
|
||||
label="故障类型"
|
||||
:rules="[(val) => val.length > 0 || '请选择故障类型!']"
|
||||
/>
|
||||
<q-card-actions align="left">
|
||||
<div class="q-gutter-md">
|
||||
<q-btn color="primary" label="确认" type="submit" />
|
||||
<q-btn color="red" label="误报" @click="falseAlarm" />
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="人工接警"
|
||||
@click="manualAlarm"
|
||||
/>
|
||||
</div>
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</div>
|
||||
<div
|
||||
class="decision-message"
|
||||
v-if="!showConfirmMmessage && showDecisionmessage"
|
||||
>
|
||||
<q-card class="box-card">
|
||||
<div class="head">行车方面</div>
|
||||
<q-separator />
|
||||
@ -51,39 +87,30 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { useLineNetStore, AlarmInfo } from 'src/stores/line-net-store';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { QForm, useQuasar } from 'quasar';
|
||||
import { saveAlertTypeData, showAlertTypeData } from './alarmInfoEnum';
|
||||
import {
|
||||
recordConfirmAlarmInfoByTipType,
|
||||
recordFailAlarmInfoById,
|
||||
recordManualAlarmInfoById,
|
||||
} from 'src/api/AlertMock';
|
||||
import { queryAlarmInfoById } from 'src/api/DecisionInfo';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
||||
const props = defineProps<{
|
||||
alarmMeaasge?: AlarmInfo;
|
||||
waitAlarmMeaasge?: AlarmInfo;
|
||||
onHandle: (id: string) => void;
|
||||
}>();
|
||||
|
||||
let bgColor = ref('');
|
||||
const dialogWidth = window.screen.width * 0.5;
|
||||
const lineNetStore = useLineNetStore();
|
||||
|
||||
watch(
|
||||
() => lineNetStore.alarmInfo,
|
||||
(val) => {
|
||||
if (val.length) {
|
||||
search();
|
||||
updata();
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const mapAlarmMessage = new Map([
|
||||
['I', 'I类信息'],
|
||||
['II', 'II类信息'],
|
||||
['III', 'III类信息'],
|
||||
['IV', 'IV类信息'],
|
||||
['0', '未知'],
|
||||
['1', '蓝显'],
|
||||
['2', '列车延误2分钟'],
|
||||
['3', '列车延误10分钟'],
|
||||
['4', '整侧站台门无关闭锁紧信号'],
|
||||
['5', '整侧站台门无法打开'],
|
||||
['6', '整侧站台门无法关闭'],
|
||||
]);
|
||||
const showConfirmMmessage = ref(true);
|
||||
const faultType = ref('');
|
||||
let faultTypeOptions = [];
|
||||
const showFaultType = ref(false);
|
||||
|
||||
const mapColor = new Map([
|
||||
['I', 'rgb(250,61,46)'],
|
||||
@ -100,36 +127,106 @@ const alarmInfo = ref({
|
||||
alertObject: '',
|
||||
alertType: '',
|
||||
locator_device_id: '',
|
||||
alert_location_id: '',
|
||||
});
|
||||
const drivingInfo = ref('');
|
||||
const submissionInfo = ref('');
|
||||
let messageUse: AlarmInfo;
|
||||
const showDialog = ref(true);
|
||||
const showDecisionmessage = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
if (props.alarmMeaasge == undefined && props.waitAlarmMeaasge == undefined) {
|
||||
messageUse = lineNetStore.alarmInfo[0] as AlarmInfo;
|
||||
} else if (props.waitAlarmMeaasge) {
|
||||
messageUse = props.waitAlarmMeaasge as AlarmInfo;
|
||||
} else {
|
||||
messageUse = props.alarmMeaasge as AlarmInfo;
|
||||
if (messageUse.alarmStatus == 1) {
|
||||
showConfirmMmessage.value = false;
|
||||
searchById();
|
||||
} else if (messageUse.alarmStatus == 0) {
|
||||
showConfirmMmessage.value = false;
|
||||
showDecisionmessage.value = false;
|
||||
}
|
||||
}
|
||||
updata();
|
||||
switch (alarmInfo.value.alertType) {
|
||||
case '道岔失表':
|
||||
faultTypeOptions = ['道岔均失表', '道岔定位失表', '道岔反位失表'];
|
||||
break;
|
||||
default:
|
||||
faultTypeOptions = [alarmInfo.value.alertType];
|
||||
faultType.value = alarmInfo.value.alertType;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
function updata() {
|
||||
bgColor.value = mapColor.get(lineNetStore.alarmInfo[0].level) as string;
|
||||
alarmInfo.value.time = lineNetStore.alarmInfo[0].alert_time
|
||||
.substring(0, 19)
|
||||
.replace('T', ' ');
|
||||
alarmInfo.value.level = mapAlarmMessage.get(
|
||||
lineNetStore.alarmInfo[0].level
|
||||
) as string;
|
||||
alarmInfo.value.alertType = mapAlarmMessage.get(
|
||||
lineNetStore.alarmInfo[0].alert_type + ''
|
||||
) as string;
|
||||
alarmInfo.value.alertObject = lineNetStore.alarmInfo[0].alert_object.replace(
|
||||
/\[|]/g,
|
||||
''
|
||||
);
|
||||
alarmInfo.value.lineId = lineNetStore.alarmInfo[0].line_id;
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function confirmAlarm() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
showConfirmMmessage.value = false;
|
||||
showFaultType.value = true;
|
||||
searchByTipType().then(() => {
|
||||
lineNetStore.alarmInfoListTable?.requestServerInteraction();
|
||||
props.onHandle(messageUse.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function search() {
|
||||
function falseAlarm() {
|
||||
showDialog.value = false;
|
||||
recordFailAlarmInfoById(+messageUse.id).then(() => {
|
||||
lineNetStore.alarmInfoListTable?.requestServerInteraction();
|
||||
props.onHandle(messageUse.id);
|
||||
});
|
||||
}
|
||||
|
||||
function manualAlarm() {
|
||||
showDialog.value = false;
|
||||
recordManualAlarmInfoById([+messageUse.id]).then(() => {
|
||||
lineNetStore.alarmInfoListTable?.requestServerInteraction();
|
||||
props.onHandle(messageUse.id);
|
||||
});
|
||||
}
|
||||
|
||||
function updata() {
|
||||
bgColor.value = mapColor.get(messageUse.level) as string;
|
||||
alarmInfo.value.time = messageUse.alert_time
|
||||
.substring(0, 19)
|
||||
.replace('T', ' ');
|
||||
alarmInfo.value.level = (showAlertTypeData as never)[messageUse.level + ''];
|
||||
alarmInfo.value.alertType = (showAlertTypeData as never)[
|
||||
messageUse.alert_type + ''
|
||||
];
|
||||
alarmInfo.value.alertObject = messageUse.alert_object.replace(/\[|]/g, '');
|
||||
alarmInfo.value.lineId = messageUse.line_id;
|
||||
}
|
||||
|
||||
async function searchByTipType() {
|
||||
try {
|
||||
const id = lineNetStore.alarmInfo[0].alert_tip_id;
|
||||
const type = (saveAlertTypeData as never)[faultType.value];
|
||||
const response = await recordConfirmAlarmInfoByTipType(
|
||||
+messageUse.id,
|
||||
type,
|
||||
messageUse.alert_location_id
|
||||
);
|
||||
drivingInfo.value = JSON.parse(response.data.drivingInfo);
|
||||
submissionInfo.value = JSON.parse(response.data.submissionInfo);
|
||||
lineNetStore.treatedAlarm(messageUse);
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '没有此类故障的辅助决策信息',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function searchById() {
|
||||
try {
|
||||
const id = messageUse.alert_tip_id;
|
||||
const response = await queryAlarmInfoById(id);
|
||||
drivingInfo.value = JSON.parse(response.data.drivingInfo);
|
||||
submissionInfo.value = JSON.parse(response.data.submissionInfo);
|
||||
@ -154,11 +251,14 @@ async function search() {
|
||||
}
|
||||
.alarm-message-detail {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
.left,
|
||||
.right {
|
||||
width: 50%;
|
||||
padding: 0 5px;
|
||||
.text {
|
||||
width: 450px;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
@ -166,12 +266,26 @@ async function search() {
|
||||
}
|
||||
}
|
||||
}
|
||||
.confirm-message {
|
||||
margin-top: 10px;
|
||||
.box-card {
|
||||
height: 180px;
|
||||
padding: 0 5px;
|
||||
.head {
|
||||
padding: 5px 5px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.detail {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.decision-message {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 10px 0;
|
||||
margin-top: 10px;
|
||||
.box-card {
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
.head {
|
||||
padding: 5px 5px;
|
||||
|
138
src/components/alarm/alarmInfoEnum.ts
Normal file
138
src/components/alarm/alarmInfoEnum.ts
Normal file
@ -0,0 +1,138 @@
|
||||
export enum showAlertTypeData {
|
||||
'未知故障',
|
||||
'蓝显',
|
||||
'列车延误2分钟',
|
||||
'列车延误10分钟',
|
||||
'整侧站台门无关闭锁紧信号',
|
||||
'整侧站台门无法打开',
|
||||
'整侧站台门无法关闭',
|
||||
'道岔失表',
|
||||
'道岔均失表',
|
||||
'道岔定位失表',
|
||||
'道岔反位失表',
|
||||
'红光带',
|
||||
'橙光带',
|
||||
'计轴红光带',
|
||||
'计轴大面积红光带',
|
||||
'计轴橙光带',
|
||||
'计轴大面积橙光带',
|
||||
'道岔大面积失表',
|
||||
'列车信号故障',
|
||||
'全线蓝显',
|
||||
'联锁区红光带',
|
||||
'联锁区橙光带',
|
||||
'联锁区失表',
|
||||
'一级联锁',
|
||||
I = 'I类信息',
|
||||
II = 'II类信息',
|
||||
III = 'III类信息',
|
||||
IV = 'IV类信息',
|
||||
TRAIN_DELAY_2 = '列车延误2分钟',
|
||||
TRAIN_DELAY_10 = '列车延误10分钟',
|
||||
BLUE_DISPLAY = '蓝显',
|
||||
PLATFORM_DOOR_WITHOUT_LOCKED_SIGNAL = '整侧站台门无关闭锁紧信号',
|
||||
PLATFORM_DOOR_CANNOT_OPEN = '整侧站台门无法打开',
|
||||
PLATFORM_DOOR_CANNOT_CLOSE = '整侧站台门无法关闭',
|
||||
QX = '全线',
|
||||
YHZ_LSQ = '鱼化寨联锁区',
|
||||
HJM_LSQ = '胡家庙联锁区',
|
||||
BCT_LSQ = '北池头联锁区',
|
||||
BSQ_LSQ = '保税区联锁区',
|
||||
SWITCH_LOST = '道岔失表',
|
||||
SWITCH_All_LOST = '道岔均失表',
|
||||
SWITCH_DW_LOST = '道岔定位失表',
|
||||
SWITCH_FW_LOST = '道岔反位失表',
|
||||
AXLE_LED_RED = '计轴红光带',
|
||||
AXLE_LED_RED_MOST = '计轴大面积红光带',
|
||||
AXLE_LED_ORANGE = '计轴橙光带',
|
||||
AXLE_LED_ORANGE_MOST = '计轴大面积橙光带',
|
||||
SWITCH_LOST_MOST = '道岔大面积失表',
|
||||
TRAIN_EB_ATP = '列车信号故障',
|
||||
ALL_LINE_BLUE_DISPLAY = '全线蓝显',
|
||||
AXLE_LED_RED_INTERLOCK_AREA = '联锁区红光带',
|
||||
AXLE_LED_ORANGE_INTERLOCK_AREA = '联锁区橙光带',
|
||||
SWITCH_LOST_INTERLOCK_AREA = '联锁区失表',
|
||||
INTERLOCK_LEVEL_ONE = '一级联锁',
|
||||
}
|
||||
|
||||
export enum saveAlertTypeData {
|
||||
列车延误2分钟 = 'TRAIN_DELAY_2',
|
||||
列车延误10分钟 = 'TRAIN_DELAY_10',
|
||||
蓝显 = 'BLUE_DISPLAY',
|
||||
整侧站台门无关闭锁紧信号 = 'PLATFORM_DOOR_WITHOUT_LOCKED_SIGNAL',
|
||||
整侧站台门无法打开 = 'PLATFORM_DOOR_CANNOT_OPEN',
|
||||
整侧站台门无法关闭 = 'PLATFORM_DOOR_CANNOT_CLOSE',
|
||||
全线 = 'QX',
|
||||
鱼化寨联锁区 = 'YHZ_LSQ',
|
||||
胡家庙联锁区 = 'HJM_LSQ',
|
||||
北池头联锁区 = 'BCT_LSQ',
|
||||
保税区联锁区 = 'BSQ_LSQ',
|
||||
道岔失表 = 'SWITCH_LOST',
|
||||
道岔均失表 = 'SWITCH_All_LOST',
|
||||
道岔定位失表 = 'SWITCH_DW_LOST',
|
||||
道岔反位失表 = 'SWITCH_FW_LOST',
|
||||
计轴红光带 = 'AXLE_LED_RED',
|
||||
计轴大面积红光带 = 'AXLE_LED_RED_MOST',
|
||||
计轴橙光带 = 'AXLE_LED_ORANGE',
|
||||
计轴大面积橙光带 = 'AXLE_LED_ORANGE_MOST',
|
||||
道岔大面积失表 = 'SWITCH_LOST_MOST',
|
||||
列车信号故障 = 'TRAIN_EB_ATP',
|
||||
全线蓝显 = 'ALL_LINE_BLUE_DISPLAY',
|
||||
联锁区红光带 = 'AXLE_LED_RED_INTERLOCK_AREA',
|
||||
联锁区橙光带 = 'AXLE_LED_ORANGE_INTERLOCK_AREA',
|
||||
联锁区失表 = 'SWITCH_LOST_INTERLOCK_AREA',
|
||||
一级联锁 = 'INTERLOCK_LEVEL_ONE',
|
||||
}
|
||||
|
||||
export const GuardConfigTypeData = {
|
||||
switchLostTimes: { label: '道岔失表', unit: '秒', deviceType: '道岔' },
|
||||
switchLostMostNums: {
|
||||
label: '道岔大面积失表',
|
||||
unit: '个',
|
||||
deviceType: '道岔',
|
||||
},
|
||||
redLedMostNums: { label: '大面积红光带', unit: '个', deviceType: '计轴区段' },
|
||||
orangeLedMostNums: {
|
||||
label: '大面积橙光带',
|
||||
unit: '个',
|
||||
deviceType: '计轴区段',
|
||||
},
|
||||
canNotOpenTimes: {
|
||||
label: '站台门无法打开',
|
||||
unit: '秒',
|
||||
deviceType: '屏蔽门',
|
||||
},
|
||||
canNotCloseTimes: {
|
||||
label: '站台门无法关闭',
|
||||
unit: '秒',
|
||||
deviceType: '屏蔽门',
|
||||
},
|
||||
trainAtpCutTimes: {
|
||||
label: '列车制动后导致atp切除的超时时间',
|
||||
unit: '秒',
|
||||
deviceType: '信号',
|
||||
},
|
||||
};
|
||||
|
||||
type findType = string | number;
|
||||
export function isArraysEqual(arr1: findType[], arr2: findType[]) {
|
||||
if (arr1.length !== arr2.length) {
|
||||
return false;
|
||||
}
|
||||
return arr1.sort().join(',') === arr2.sort().join(',');
|
||||
}
|
||||
|
||||
export enum ShowAlertStateData {
|
||||
'未处理' = -1,
|
||||
'误报',
|
||||
'确认',
|
||||
'人工接警',
|
||||
}
|
||||
|
||||
export const alertStatusOptions = [
|
||||
{ label: '全部', value: 999 },
|
||||
{ label: '未处理', value: -1 },
|
||||
{ label: '误报', value: 0 },
|
||||
{ label: '确认', value: 1 },
|
||||
{ label: '人工接警', value: 2 },
|
||||
];
|
@ -1,173 +0,0 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="报警列表"
|
||||
:width="dialogWidth"
|
||||
:height="dialogHeight"
|
||||
>
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
title="报警信息"
|
||||
:style="{ height: dialogHeight + 'px' }"
|
||||
: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-slot:top-left>
|
||||
<q-input
|
||||
dense
|
||||
debounce="1000"
|
||||
v-model.number="filter.lineId"
|
||||
label="线路ID"
|
||||
type="number"
|
||||
/>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
</template>
|
||||
<template v-slot:top-right>
|
||||
<q-input
|
||||
dense
|
||||
debounce="1000"
|
||||
v-model="filter.alertType"
|
||||
label="故障类型"
|
||||
></q-input>
|
||||
<q-btn flat round color="primary" icon="search" />
|
||||
</template>
|
||||
</q-table>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { useQuasar, type QTableColumn } from 'quasar';
|
||||
import { alarmInfoListQuery } from 'src/api/AlertMock';
|
||||
|
||||
const $q = useQuasar();
|
||||
const dialogWidth = window.screen.width * 0.5;
|
||||
const dialogHeight = window.screen.height * 0.5;
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
tableRef.value.requestServerInteraction();
|
||||
});
|
||||
});
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{
|
||||
name: 'id',
|
||||
label: '编号',
|
||||
field: 'id',
|
||||
required: true,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'alertTime',
|
||||
label: '时间',
|
||||
field: 'alertTime',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'lineId',
|
||||
label: '线路',
|
||||
field: 'lineId',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'alertObject',
|
||||
label: '设备',
|
||||
field: 'alertObject',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'level',
|
||||
label: '级别',
|
||||
field: (row) => {
|
||||
if (row.level) {
|
||||
return (showAlertTypeData as never)[row.level + ''];
|
||||
}
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'alertType',
|
||||
label: '故障类型',
|
||||
field: (row) => {
|
||||
if (row.alertType) {
|
||||
return (showAlertTypeData as never)[row.alertType];
|
||||
}
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const tableRef = ref();
|
||||
const rows = reactive([]);
|
||||
const filter = reactive({
|
||||
alertType: '',
|
||||
lineId: '',
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
async function onRequest(props: any) {
|
||||
const { page, rowsPerPage, sortBy, descending } = props.pagination;
|
||||
const filter = props.filter;
|
||||
loading.value = true;
|
||||
try {
|
||||
let response = await alarmInfoListQuery({
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
alertType: (saveAlertTypeData as never)[filter.alertType],
|
||||
lineId: filter.lineId,
|
||||
});
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
enum showAlertTypeData {
|
||||
ALERT_TYPE_UNKNOWN = '未知故障',
|
||||
BLUE_DISPLAY = '蓝显',
|
||||
TRAIN_DELAY_2 = '列车延误2分钟',
|
||||
TRAIN_DELAY_10 = '列车延误10分钟',
|
||||
PLATFORM_DOOR_WITHOUT_LOCKED_SIGNAL = '站台门无关闭且锁紧信号',
|
||||
PLATFORM_DOOR_CANNOT_OPEN = '整侧站台门无法打开',
|
||||
PLATFORM_DOOR_CANNOT_CLOSE = '整侧站台门无法关闭',
|
||||
I = 'I类信息',
|
||||
II = 'II类信息',
|
||||
III = 'III类信息',
|
||||
IV = 'IV类信息',
|
||||
}
|
||||
|
||||
enum saveAlertTypeData {
|
||||
列车延误2分钟 = 'TRAIN_DELAY_2',
|
||||
列车延误10分钟 = 'TRAIN_DELAY_10',
|
||||
蓝显 = 'BLUE_DISPLAY',
|
||||
站台门无关闭且锁紧信号 = 'PLATFORM_DOOR_WITHOUT_LOCKED_SIGNAL',
|
||||
整侧站台门无法打开 = 'PLATFORM_DOOR_CANNOT_OPEN',
|
||||
整侧站台门无法关闭 = 'PLATFORM_DOOR_CANNOT_CLOSE',
|
||||
}
|
||||
</script>
|
363
src/components/alarm/alarmStatistics.vue
Normal file
363
src/components/alarm/alarmStatistics.vue
Normal file
@ -0,0 +1,363 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="报警统计"
|
||||
:width="dialogWidth"
|
||||
:height="dialogHeight"
|
||||
>
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
:style="{ height: dialogHeight + 'px' }"
|
||||
:rows="rows"
|
||||
:columns="columnDefs"
|
||||
row-key="index"
|
||||
v-model:pagination="pagination"
|
||||
:rows-per-page-options="[0]"
|
||||
:loading="loading"
|
||||
:filter="filter"
|
||||
binary-state-sort
|
||||
virtual-scroll
|
||||
>
|
||||
<template v-slot:top>
|
||||
<q-form ref="myForm" @submit="onRequest" style="width: 100%">
|
||||
<div class="q-gutter-md row justify-center items-start">
|
||||
<q-select
|
||||
dense
|
||||
v-model="filter.lineId"
|
||||
:options="optionsLineId"
|
||||
emit-value
|
||||
map-options
|
||||
options-dense
|
||||
label="线路ID"
|
||||
style="width: 100px"
|
||||
/>
|
||||
<q-input
|
||||
dense
|
||||
v-model="filter.beginDateTime"
|
||||
label="开始时间"
|
||||
no-error-icon
|
||||
mask="####-##-## ##:##:##"
|
||||
hint="例如:2023-09-05 16:05:09"
|
||||
lazy-rules
|
||||
:rules="[timeRangeValidation]"
|
||||
:error="errorBeginTime"
|
||||
:error-message="errorMessageBeginTime"
|
||||
>
|
||||
<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.beginDateTime"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
landscape
|
||||
>
|
||||
<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.beginDateTime"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
with-seconds
|
||||
landscape
|
||||
format24h
|
||||
>
|
||||
<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-input
|
||||
dense
|
||||
v-model="filter.endDateTime"
|
||||
label="结束时间"
|
||||
no-error-icon
|
||||
mask="####-##-## ##:##:##"
|
||||
hint="例如:2023-09-05 16:05:09"
|
||||
lazy-rules
|
||||
:rules="[timeRangeValidation]"
|
||||
:error="errorEndTime"
|
||||
:error-message="errorMessageEndTime"
|
||||
>
|
||||
<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.endDateTime"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
landscape
|
||||
>
|
||||
<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.endDateTime"
|
||||
mask="YYYY-MM-DD HH:mm:ss"
|
||||
with-seconds
|
||||
landscape
|
||||
format24h
|
||||
>
|
||||
<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-select
|
||||
dense
|
||||
v-model="filter.alertTypes"
|
||||
:options="typeOptions"
|
||||
multiple
|
||||
emit-value
|
||||
map-options
|
||||
options-dense
|
||||
class="ellipsis"
|
||||
label="类型"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<q-select
|
||||
dense
|
||||
v-model="filter.alertStatus"
|
||||
:options="alertStatusOptions"
|
||||
emit-value
|
||||
map-options
|
||||
options-dense
|
||||
label="处理状态"
|
||||
style="width: 100px"
|
||||
/>
|
||||
<q-btn color="primary" label="查询" type="submit" />
|
||||
</div>
|
||||
</q-form>
|
||||
</template>
|
||||
<template v-slot:body-cell-index="props">
|
||||
<q-td :props="props">
|
||||
<span>{{ props.rowIndex + 1 }}</span>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { useQuasar, type QTableColumn, QForm, date } from 'quasar';
|
||||
import { IReportParams, recordAlarmReport } from 'src/api/AlertMock';
|
||||
import {
|
||||
showAlertTypeData,
|
||||
saveAlertTypeData,
|
||||
alertStatusOptions,
|
||||
} from './alarmInfoEnum';
|
||||
|
||||
defineProps<{
|
||||
optionsLineId: { label: string; value: number }[];
|
||||
}>();
|
||||
|
||||
const $q = useQuasar();
|
||||
const dialogWidth = window.screen.width * 0.6;
|
||||
const dialogHeight = window.screen.height * 0.5;
|
||||
|
||||
const columnDefs: QTableColumn[] = [
|
||||
{
|
||||
name: 'index',
|
||||
label: '编号',
|
||||
field: 'index',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'alertType',
|
||||
label: '故障类型',
|
||||
field: (row) => {
|
||||
if (row.alertType) {
|
||||
return (showAlertTypeData as never)[row.alertType];
|
||||
}
|
||||
},
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'counter',
|
||||
label: '数量',
|
||||
field: 'counter',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
const typeOptions = computed(() => {
|
||||
const list: { label: string; value: string }[] = [];
|
||||
// list.push({ label: '全部', value: '' });
|
||||
for (let i in saveAlertTypeData) {
|
||||
const obj = {
|
||||
label: i,
|
||||
value: saveAlertTypeData[i as keyof typeof saveAlertTypeData],
|
||||
};
|
||||
list.push(obj);
|
||||
}
|
||||
return list;
|
||||
});
|
||||
|
||||
interface Ifilter extends IReportParams {
|
||||
lineId: number;
|
||||
}
|
||||
|
||||
const rows = reactive([]);
|
||||
const filter = reactive<Ifilter>({
|
||||
alertTypes: [],
|
||||
lineId: 3,
|
||||
beginDateTime: '',
|
||||
endDateTime: '',
|
||||
alertStatus: 999,
|
||||
});
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 0,
|
||||
});
|
||||
|
||||
function onRequest() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
loading.value = true;
|
||||
try {
|
||||
const params: IReportParams = {};
|
||||
if (filter.alertTypes?.length) {
|
||||
Object.assign(params, { alertTypes: filter.alertTypes });
|
||||
}
|
||||
if (filter.beginDateTime) {
|
||||
Object.assign(params, { beginDateTime: filter.beginDateTime });
|
||||
}
|
||||
if (filter.endDateTime) {
|
||||
Object.assign(params, { endDateTime: filter.endDateTime });
|
||||
}
|
||||
if (filter.alertStatus != 999) {
|
||||
Object.assign(params, { alertStatus: filter.alertStatus });
|
||||
}
|
||||
const response = await recordAlarmReport(filter.lineId, params);
|
||||
|
||||
pagination.value.rowsNumber = response.length;
|
||||
pagination.value.rowsPerPage = response.length;
|
||||
rows.splice(0, rows.length, ...(response as []));
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取报警统计列表',
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
|
||||
const errorBeginTime = ref(false);
|
||||
const errorEndTime = ref(false);
|
||||
const errorMessageBeginTime = ref('');
|
||||
const errorMessageEndTime = ref('');
|
||||
function timeRangeValidation() {
|
||||
const Reg = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
|
||||
if (filter.beginDateTime) {
|
||||
if (
|
||||
!date.isValid(filter.beginDateTime) ||
|
||||
!Reg.test(filter.beginDateTime)
|
||||
) {
|
||||
errorBeginTime.value = true;
|
||||
errorMessageBeginTime.value = '请输入正确的时间!';
|
||||
return false;
|
||||
} else {
|
||||
filter.beginDateTime = date.formatDate(
|
||||
filter.beginDateTime,
|
||||
'YYYY-MM-DD HH:mm:ss'
|
||||
);
|
||||
}
|
||||
}
|
||||
if (filter.endDateTime) {
|
||||
if (!date.isValid(filter.endDateTime) || !Reg.test(filter.endDateTime)) {
|
||||
errorEndTime.value = true;
|
||||
errorMessageEndTime.value = '请输入正确的时间!';
|
||||
return false;
|
||||
} else {
|
||||
filter.endDateTime = date.formatDate(
|
||||
filter.endDateTime,
|
||||
'YYYY-MM-DD HH:mm:ss'
|
||||
);
|
||||
}
|
||||
}
|
||||
if (
|
||||
filter.beginDateTime &&
|
||||
filter.endDateTime &&
|
||||
new Date(filter.endDateTime).getTime() <
|
||||
new Date(filter.beginDateTime).getTime()
|
||||
) {
|
||||
errorBeginTime.value = true;
|
||||
errorEndTime.value = true;
|
||||
errorMessageBeginTime.value = '开始时间不能大于结束时间!';
|
||||
errorMessageEndTime.value = '结束时间不能小于开始时间!';
|
||||
return false;
|
||||
}
|
||||
errorBeginTime.value = false;
|
||||
errorEndTime.value = false;
|
||||
errorMessageBeginTime.value = '';
|
||||
errorMessageEndTime.value = '';
|
||||
return true;
|
||||
}
|
||||
</script>
|
@ -1,64 +1,202 @@
|
||||
<template>
|
||||
<div>
|
||||
<audio ref="audio">
|
||||
<source src="../../assets/buzzer.mp3" type="audio/mpeg" />
|
||||
<source :src="audioSrc" type="audio/mpeg" />
|
||||
</audio>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { watch, onUnmounted, ref, onMounted } from 'vue';
|
||||
import { useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { watch, onUnmounted, ref, toRaw } from 'vue';
|
||||
import { AlarmInfo, useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { DialogChainObject, useQuasar } from 'quasar';
|
||||
import alarmInfoDialog from 'src/components/alarm/alarmInfoDialog.vue';
|
||||
import { showAlertTypeData } from './alarmInfoEnum';
|
||||
import allLineBlue from '/alarmMusic/all-line-blue.mp3';
|
||||
import atpcut from '/alarmMusic/atp-cut.mp3';
|
||||
import blue from '/alarmMusic/blue.mp3';
|
||||
import cannotClose from '/alarmMusic/cannot-close.mp3';
|
||||
import cannotOpen from '/alarmMusic/cannot-open.mp3';
|
||||
import orangeMost from '/alarmMusic/orange-most.mp3';
|
||||
import orange from '/alarmMusic/orange.mp3';
|
||||
import redMost from '/alarmMusic/red-most.mp3';
|
||||
import red from '/alarmMusic/red.mp3';
|
||||
import switchLostMost from '/alarmMusic/switch-lost-most.mp3';
|
||||
import switchLost from '/alarmMusic/switch-lost.mp3';
|
||||
import buzzer from '/alarmMusic/buzzer.mp3';
|
||||
|
||||
const lineNetStore = useLineNetStore();
|
||||
const audio = ref();
|
||||
const audioSrc = ref('');
|
||||
const $q = useQuasar();
|
||||
const dialogInstance = ref();
|
||||
const playAble = ref(false);
|
||||
const watchInteract = () => {
|
||||
playAble.value = true;
|
||||
document.removeEventListener('click', watchInteract);
|
||||
document.removeEventListener('keydown', watchInteract);
|
||||
};
|
||||
let waitShowDialog: AlarmInfo[] = [];
|
||||
|
||||
watch(
|
||||
() => lineNetStore.alarmInfo,
|
||||
(val) => {
|
||||
if (val.length && audio.value.paused) {
|
||||
playAlarmMusic();
|
||||
if (val.length) {
|
||||
UpdataAlarmInfoList();
|
||||
const hasShow = countHasShowFiveDialog();
|
||||
if (!hasShow) {
|
||||
const alarmType = val[0].alert_type;
|
||||
alarm(alarmType, val[0].id);
|
||||
playAlarmMusic(alarmType);
|
||||
} else {
|
||||
waitShowDialog.push(toRaw(lineNetStore.alarmInfo[0]));
|
||||
}
|
||||
}
|
||||
if (val.length && !lineNetStore.alarmDialog) {
|
||||
alarm();
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
}
|
||||
);
|
||||
|
||||
function playAlarmMusic() {
|
||||
if (playAble.value) {
|
||||
watch(
|
||||
() => lineNetStore.closeAllAlarmInfoDialog,
|
||||
(val) => {
|
||||
if (val) {
|
||||
lineNetStore.closeAllAlarmInfoDialog = false;
|
||||
closeAllDialog();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function playAlarmMusic(type: number) {
|
||||
for (let i = 0; i < dialogInstance.length; i++) {
|
||||
if (dialogInstance[i].show == false) {
|
||||
dialogInstance.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (lineNetStore.playAble && audio.value.paused) {
|
||||
const alarmType = (showAlertTypeData as never)[type + ''];
|
||||
const mapAlarmMusic = new Map([
|
||||
['蓝显', blue],
|
||||
['全线蓝显', allLineBlue],
|
||||
['整侧站台门无法打开', cannotOpen],
|
||||
['整侧站台门无法关闭', cannotClose],
|
||||
['道岔失表', switchLost],
|
||||
['道岔大面积失表', switchLostMost],
|
||||
['计轴红光带', red],
|
||||
['计轴大面积红光带', redMost],
|
||||
['计轴橙光带', orange],
|
||||
['计轴大面积橙光带', orangeMost],
|
||||
['列车信号故障', atpcut],
|
||||
]);
|
||||
const music = mapAlarmMusic.get(alarmType);
|
||||
if (music !== undefined) {
|
||||
audioSrc.value = music;
|
||||
} else {
|
||||
audioSrc.value = buzzer;
|
||||
}
|
||||
audio.value.src = audioSrc.value;
|
||||
audio.value.play();
|
||||
}
|
||||
}
|
||||
|
||||
function alarm() {
|
||||
lineNetStore.alarmDialog = true;
|
||||
dialogInstance.value = $q
|
||||
.dialog({ component: alarmInfoDialog })
|
||||
.onCancel(() => {
|
||||
lineNetStore.alarmDialog = false;
|
||||
});
|
||||
//不关闭弹框,每3分钟播放一次报警音乐
|
||||
function timingPlayAlarmMusic(dialog: DialogChainObject) {
|
||||
const timerIndex = dialogInstance.findIndex((item) => item.dialog == dialog);
|
||||
clearTimeout(dialogInstance[timerIndex].timer);
|
||||
dialogInstance[timerIndex].timer = setTimeout(() => {
|
||||
for (let i = 0; i < dialogInstance.length; i++) {
|
||||
if (
|
||||
dialogInstance[i].show &&
|
||||
!dialogInstance[i].hasHandle &&
|
||||
dialogInstance[i].dialog == dialog
|
||||
) {
|
||||
playAlarmMusic(dialogInstance[i].alarmType);
|
||||
timingPlayAlarmMusic(dialog);
|
||||
}
|
||||
}
|
||||
}, 180000);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('click', watchInteract);
|
||||
document.addEventListener('keydown', watchInteract);
|
||||
});
|
||||
const dialogInstance: {
|
||||
dialog: DialogChainObject;
|
||||
show: boolean;
|
||||
alarmType: number;
|
||||
timer: string | number | NodeJS.Timeout | undefined;
|
||||
id: string;
|
||||
hasHandle: boolean;
|
||||
}[] = [];
|
||||
|
||||
onUnmounted(() => {
|
||||
if (dialogInstance.value && lineNetStore.alarmDialog) {
|
||||
dialogInstance.value.hide();
|
||||
function countHasShowFiveDialog(): boolean {
|
||||
let hasShow = 0;
|
||||
for (let i = 0; i < dialogInstance.length; i++) {
|
||||
if (dialogInstance[i].show) {
|
||||
hasShow++;
|
||||
if (hasShow > 4) break;
|
||||
}
|
||||
}
|
||||
return hasShow > 4 ? true : false;
|
||||
}
|
||||
|
||||
function alarm(alarmType: number, id: string, waitAlarmMeaasge?: AlarmInfo) {
|
||||
const dialogInstanceItem = $q
|
||||
.dialog({
|
||||
component: alarmInfoDialog,
|
||||
componentProps: {
|
||||
waitAlarmMeaasge: waitAlarmMeaasge,
|
||||
onHandle: (id: string) => {
|
||||
for (let i = 0; i < dialogInstance.length; i++) {
|
||||
if (dialogInstance[i].id == id) {
|
||||
dialogInstance[i].hasHandle = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
.onCancel(() => {
|
||||
alarmWaitDialog();
|
||||
const index = dialogInstance.findIndex(
|
||||
(item) => item.dialog == dialogInstanceItem
|
||||
);
|
||||
dialogInstance[index].show = false;
|
||||
});
|
||||
let timer: string | number | NodeJS.Timeout | undefined = undefined;
|
||||
dialogInstance.push({
|
||||
dialog: dialogInstanceItem,
|
||||
show: true,
|
||||
alarmType,
|
||||
timer,
|
||||
hasHandle: false,
|
||||
id,
|
||||
});
|
||||
timingPlayAlarmMusic(dialogInstanceItem);
|
||||
}
|
||||
|
||||
function alarmWaitDialog() {
|
||||
if (countHasShowFiveDialog() && waitShowDialog.length) {
|
||||
alarm(
|
||||
waitShowDialog[0].alert_type,
|
||||
waitShowDialog[0].id,
|
||||
waitShowDialog[0]
|
||||
);
|
||||
playAlarmMusic(waitShowDialog[0].alert_type);
|
||||
waitShowDialog.shift();
|
||||
}
|
||||
}
|
||||
|
||||
function closeAllDialog() {
|
||||
if (dialogInstance.length) {
|
||||
dialogInstance.forEach((item) => {
|
||||
clearTimeout(item.timer);
|
||||
if (item.show) {
|
||||
item.dialog.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
waitShowDialog = [];
|
||||
}
|
||||
|
||||
let timeout: string | number | NodeJS.Timeout | undefined;
|
||||
function UpdataAlarmInfoList() {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
lineNetStore.alarmInfoListTable?.requestServerInteraction();
|
||||
}, 1000);
|
||||
}
|
||||
onUnmounted(() => {
|
||||
clearTimeout(timeout);
|
||||
closeAllDialog();
|
||||
});
|
||||
</script>
|
||||
|
264
src/components/alarm/setAlarmMock.vue
Normal file
264
src/components/alarm/setAlarmMock.vue
Normal file
@ -0,0 +1,264 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
v-model="showsetAlartText"
|
||||
seamless
|
||||
title="设置故障演示"
|
||||
:width="300"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
<q-card class="q-gutter-sm q-px-sm q-mt-sm">
|
||||
<q-form ref="myForm" @submit="onSubmit" @reset="onReset">
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
label="线路ID"
|
||||
v-model.number="setAlartTextData.lineId"
|
||||
type="number"
|
||||
lazy-rules
|
||||
:rules="[(val) => val || '请输入线路ID!']"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
label="故障类型"
|
||||
v-model="setAlartTextData.alertType"
|
||||
:options="optionsAlertType"
|
||||
:rules="[(val) => val.length > 0 || '请选择故障类型!']"
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
<q-item-label> 框选的设备 </q-item-label>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="item in setAlartTextData.deviceCodes"
|
||||
:key="item"
|
||||
square
|
||||
color="primary"
|
||||
text-color="white"
|
||||
removable
|
||||
@remove="removeSelect(item)"
|
||||
>
|
||||
{{ item }}
|
||||
</q-chip>
|
||||
</div>
|
||||
<q-btn
|
||||
v-show="setAlartTextData.deviceCodes.length > 0"
|
||||
style="width: 120px"
|
||||
label="清空框选的设备"
|
||||
color="red"
|
||||
@click="clearSelect"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<div class="q-gutter-sm q-pa-md row justify-center">
|
||||
<q-btn
|
||||
label="提交"
|
||||
type="submit"
|
||||
color="primary"
|
||||
class="q-mr-md"
|
||||
/>
|
||||
<q-btn label="重置" type="reset" color="primary" />
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { JlGraphic } from 'jl-graphic';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { QForm, useQuasar } from 'quasar';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { mockAlertSet } from 'src/api/AlertMock';
|
||||
import { isArraysEqual, saveAlertTypeData } from './alarmInfoEnum';
|
||||
import { Section, SectionType } from 'src/graphics/section/Section';
|
||||
import { LogicSection } from 'src/graphics/logicSection/LogicSection';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
const setAlartTextData = ref<{
|
||||
lineId: string;
|
||||
alertType: string;
|
||||
deviceCodes: string[];
|
||||
}>({
|
||||
lineId: '',
|
||||
alertType: '',
|
||||
deviceCodes: [],
|
||||
});
|
||||
const optionsAlertType = [
|
||||
'蓝显',
|
||||
'全线蓝显',
|
||||
'整侧站台门无法打开',
|
||||
'整侧站台门无法关闭',
|
||||
'道岔失表',
|
||||
'计轴红光带',
|
||||
'计轴大面积红光带',
|
||||
'计轴橙光带',
|
||||
'计轴大面积橙光带',
|
||||
'列车信号故障',
|
||||
];
|
||||
const mapAlertType = new Map([
|
||||
['蓝显', ['station']],
|
||||
['全线蓝显', ['station']],
|
||||
['整侧站台门无法打开', ['Platform']],
|
||||
['整侧站台门无法关闭', ['Platform']],
|
||||
['道岔失表', ['Turnout']],
|
||||
['计轴红光带', ['Section']],
|
||||
['计轴大面积红光带', ['Section']],
|
||||
['计轴橙光带', ['Section']],
|
||||
['计轴大面积橙光带', ['Section']],
|
||||
['列车信号故障', ['LogicSection', 'Turnout']],
|
||||
]);
|
||||
let selectGraphic: JlGraphic[] = [];
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
(val) => {
|
||||
if (val && val.length > 0 && setAlartTextData.value.alertType) {
|
||||
const selectGraphicId = selectGraphic.map((g) => g.id);
|
||||
const appSelectedGraphicsId = lineStore.selectedGraphics?.map(
|
||||
(g) => g.id
|
||||
);
|
||||
if (
|
||||
appSelectedGraphicsId !== undefined &&
|
||||
isArraysEqual(selectGraphicId, appSelectedGraphicsId)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const deviceFilter = lineStore.selectedGraphics?.filter((g) => {
|
||||
let select = false;
|
||||
if (
|
||||
g.type == Station.Type &&
|
||||
(g as Station).datas.concentrationStations &&
|
||||
setAlartTextData.value.alertType == '蓝显'
|
||||
) {
|
||||
select = true;
|
||||
}
|
||||
if (
|
||||
(g.type !== Station.Type &&
|
||||
mapAlertType
|
||||
.get(setAlartTextData.value.alertType)
|
||||
?.includes(g.type)) ||
|
||||
(g.type == Section.Type &&
|
||||
(g as Section).datas.sectionType === SectionType.TurnoutPhysical &&
|
||||
mapAlertType
|
||||
.get(setAlartTextData.value.alertType)
|
||||
?.includes(LogicSection.Type))
|
||||
) {
|
||||
select = true;
|
||||
}
|
||||
return select;
|
||||
}) as JlGraphic[];
|
||||
if (
|
||||
[
|
||||
'道岔失表',
|
||||
'计轴红光带',
|
||||
'计轴橙光带',
|
||||
'列车信号故障',
|
||||
'整侧站台门无法打开',
|
||||
'整侧站台门无法关闭',
|
||||
].includes(setAlartTextData.value.alertType)
|
||||
) {
|
||||
if (deviceFilter[0] !== undefined) {
|
||||
selectGraphic = [deviceFilter[0]];
|
||||
}
|
||||
} else {
|
||||
selectGraphic.push(...deviceFilter);
|
||||
}
|
||||
selectGraphic = Array.from(new Set(selectGraphic));
|
||||
lineStore.getLineApp().updateSelected(...selectGraphic);
|
||||
setAlartTextData.value.deviceCodes = selectGraphic.map((g) => g.code);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
lineStore.getLineApp().emit('options-update', {
|
||||
mouseToolOptions: {
|
||||
boxSelect: true,
|
||||
viewportDrag: true,
|
||||
viewportDragLeft: false,
|
||||
wheelZoom: true,
|
||||
},
|
||||
});
|
||||
clearSelect();
|
||||
onReset();
|
||||
setAlartTextData.value.lineId = lineStore.lineId as unknown as string;
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
const showsetAlartText = ref(true);
|
||||
const $q = useQuasar();
|
||||
|
||||
async function onSubmit() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
try {
|
||||
const params = {
|
||||
lineId: +setAlartTextData.value.lineId,
|
||||
alertType: (saveAlertTypeData as never)[
|
||||
setAlartTextData.value.alertType + ''
|
||||
],
|
||||
deviceCodes: setAlartTextData.value.deviceCodes,
|
||||
};
|
||||
await mockAlertSet(params);
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: '设置故障演示成功',
|
||||
});
|
||||
onReset();
|
||||
} catch (err) {
|
||||
const apiErr = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: apiErr.title,
|
||||
});
|
||||
} finally {
|
||||
showsetAlartText.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeSelect(code: string) {
|
||||
const removeIndex = setAlartTextData.value.deviceCodes.findIndex(
|
||||
(item) => item == code
|
||||
);
|
||||
selectGraphic.splice(removeIndex, 1);
|
||||
setAlartTextData.value.deviceCodes.splice(removeIndex, 1);
|
||||
lineStore.getLineApp().updateSelected(...selectGraphic);
|
||||
}
|
||||
|
||||
function clearSelect() {
|
||||
setAlartTextData.value.deviceCodes = [];
|
||||
selectGraphic = [];
|
||||
lineStore.getLineApp().updateSelected();
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
setAlartTextData.value = {
|
||||
lineId: lineStore.lineId as unknown as string,
|
||||
alertType: '',
|
||||
deviceCodes: [],
|
||||
};
|
||||
selectGraphic = [];
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
lineStore.getLineApp().emit('options-update', {
|
||||
mouseToolOptions: {
|
||||
boxSelect: false,
|
||||
viewportDrag: true,
|
||||
viewportDragLeft: true,
|
||||
wheelZoom: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
</script>
|
408
src/components/alarm/setAlarmText.vue
Normal file
408
src/components/alarm/setAlarmText.vue
Normal file
@ -0,0 +1,408 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
v-model="showsetAlartText"
|
||||
seamless
|
||||
title="设置故障测试"
|
||||
:width="300"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
<q-card class="q-gutter-sm q-px-sm q-mt-sm">
|
||||
<q-form ref="myForm" @submit="onSubmit" @reset="onReset">
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
label="线路ID"
|
||||
v-model.number="setAlartTextData.lineId"
|
||||
type="number"
|
||||
lazy-rules
|
||||
:rules="[(val) => val || '请输入线路ID!']"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
label="故障类型"
|
||||
v-model="setAlartTextData.alertType"
|
||||
:options="optionsAlertType"
|
||||
:rules="[(val) => val.length > 0 || '请选择故障类型!']"
|
||||
@update:model-value="onChooseAlertType"
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-expansion-item
|
||||
bordered
|
||||
expand-separator
|
||||
v-for="(configItem, index) in setAlartTextData.groupList"
|
||||
:key="configItem"
|
||||
v-model="configItem.expanded"
|
||||
:label="configItem.groupName"
|
||||
@click="toggleItem(index)"
|
||||
>
|
||||
<q-card>
|
||||
<q-item no-wrap class="column">
|
||||
<q-input
|
||||
v-if="setAlartTextData.alertType == '列车信号故障'"
|
||||
outlined
|
||||
label="车组号"
|
||||
v-model="configItem.groupId"
|
||||
lazy-rules
|
||||
:rules="[(val) => val.length > 0 || '请输入车组号!']"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
label="故障测试状态"
|
||||
v-model="configItem.status"
|
||||
:options="optionsStatus"
|
||||
:rules="[(val) => val.length > 0 || '请选择故障类型!']"
|
||||
map-options
|
||||
emit-value
|
||||
/>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="(item, selectIndex) in configItem.deviceInfos"
|
||||
:key="item"
|
||||
square
|
||||
color="primary"
|
||||
text-color="white"
|
||||
removable
|
||||
@remove="removeSelect(selectIndex)"
|
||||
clickable
|
||||
@click="clickSelectCenter(selectIndex)"
|
||||
>
|
||||
{{ item.deviceName }}
|
||||
</q-chip>
|
||||
</div>
|
||||
<div>
|
||||
<q-btn
|
||||
v-show="configItem.deviceInfos.length > 0"
|
||||
style="width: 100px"
|
||||
label="清空选择"
|
||||
color="red"
|
||||
class="q-mr-md"
|
||||
@click="clearAllSelect(index)"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="setAlartTextData.alertType == '列车信号故障'"
|
||||
label="删除测试组"
|
||||
color="secondary"
|
||||
@click="deleteSelectConfig(index)"
|
||||
/>
|
||||
</div>
|
||||
</q-item>
|
||||
</q-card>
|
||||
</q-expansion-item>
|
||||
</q-list>
|
||||
<q-btn
|
||||
v-if="setAlartTextData.alertType == '列车信号故障'"
|
||||
class="q-mt-md"
|
||||
label="增加测试组"
|
||||
color="secondary"
|
||||
@click="addSelectConfig"
|
||||
/>
|
||||
<div class="q-gutter-sm q-pa-md row justify-center">
|
||||
<q-btn
|
||||
label="提交"
|
||||
type="submit"
|
||||
color="primary"
|
||||
class="q-mr-md"
|
||||
/>
|
||||
<q-btn label="重置" type="reset" color="primary" />
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { JlGraphic } from 'jl-graphic';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { QForm, useQuasar } from 'quasar';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { mockLocalDemoTestSet } from 'src/api/AlertMock';
|
||||
import { isArraysEqual, saveAlertTypeData } from './alarmInfoEnum';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
const setAlartTextData = ref<{
|
||||
lineId: string;
|
||||
alertType: string;
|
||||
groupList: {
|
||||
groupName: string;
|
||||
groupId?: string;
|
||||
status: string;
|
||||
deviceInfos: {
|
||||
deviceName: string;
|
||||
deviceType: string;
|
||||
}[];
|
||||
expanded: boolean;
|
||||
}[];
|
||||
}>({
|
||||
lineId: '',
|
||||
alertType: '',
|
||||
groupList: [
|
||||
{
|
||||
groupName: '测试组',
|
||||
groupId: '',
|
||||
status: '',
|
||||
deviceInfos: [],
|
||||
expanded: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
const optionsAlertType = [
|
||||
'蓝显',
|
||||
'道岔失表',
|
||||
'计轴红光带',
|
||||
'计轴橙光带',
|
||||
'列车信号故障',
|
||||
];
|
||||
const mapAlertType = new Map([
|
||||
['蓝显', ['station']],
|
||||
['道岔失表', ['Turnout']],
|
||||
['计轴红光带', ['LogicSection', 'Turnout']],
|
||||
['计轴橙光带', ['LogicSection', 'Turnout']],
|
||||
['列车信号故障', ['LogicSection', 'Turnout']],
|
||||
]);
|
||||
enum DeviceType {
|
||||
station = 'DEVICE_TYPE_RTU',
|
||||
Turnout = 'DEVICE_TYPE_SWITCH',
|
||||
LogicSection = 'DEVICE_TYPE_TRACK',
|
||||
}
|
||||
const optionsStatus = [
|
||||
{ label: '正常', value: 'NORMAL' },
|
||||
{ label: '设置', value: 'BEGIN' },
|
||||
{ label: '报警', value: 'ALERT' },
|
||||
];
|
||||
let selectGraphic: JlGraphic[] = [];
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
(val) => {
|
||||
if (
|
||||
val &&
|
||||
val.length > 0 &&
|
||||
setAlartTextData.value.alertType &&
|
||||
clickIndex !== null
|
||||
) {
|
||||
const selectGraphicId = selectGraphic.map((g) => g.id);
|
||||
const appSelectedGraphicsId = lineStore.selectedGraphics?.map(
|
||||
(g) => g.id
|
||||
);
|
||||
if (
|
||||
appSelectedGraphicsId !== undefined &&
|
||||
isArraysEqual(selectGraphicId, appSelectedGraphicsId)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const deviceFilter = lineStore.selectedGraphics?.filter((g) => {
|
||||
let select = false;
|
||||
if (
|
||||
g.type == Station.Type &&
|
||||
(g as Station).datas.concentrationStations &&
|
||||
setAlartTextData.value.alertType == '蓝显'
|
||||
) {
|
||||
select = true;
|
||||
}
|
||||
if (
|
||||
g.type !== Station.Type &&
|
||||
mapAlertType.get(setAlartTextData.value.alertType)?.includes(g.type)
|
||||
) {
|
||||
select = true;
|
||||
}
|
||||
return select;
|
||||
}) as JlGraphic[];
|
||||
if (setAlartTextData.value.alertType !== '列车信号故障') {
|
||||
selectGraphic.push(...deviceFilter);
|
||||
} else if (deviceFilter.length) {
|
||||
selectGraphic = [deviceFilter[0]];
|
||||
}
|
||||
selectGraphic = Array.from(new Set(selectGraphic));
|
||||
lineStore.getLineApp().updateSelected(...selectGraphic);
|
||||
setAlartTextData.value.groupList[clickIndex].deviceInfos = [];
|
||||
selectGraphic.forEach((g) => {
|
||||
setAlartTextData.value.groupList[clickIndex as number].deviceInfos.push(
|
||||
{
|
||||
deviceName: g.code,
|
||||
deviceType: (DeviceType as never)[g.type + ''],
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
lineStore.getLineApp().emit('options-update', {
|
||||
mouseToolOptions: {
|
||||
boxSelect: true,
|
||||
viewportDrag: true,
|
||||
viewportDragLeft: false,
|
||||
wheelZoom: true,
|
||||
},
|
||||
});
|
||||
onReset();
|
||||
setAlartTextData.value.lineId = lineStore.lineId as unknown as string;
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
const showsetAlartText = ref(true);
|
||||
const $q = useQuasar();
|
||||
|
||||
async function onSubmit() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
const deviceInfos = setAlartTextData.value.groupList
|
||||
.map((group) => {
|
||||
const deviceInfo = group.deviceInfos.map((deviceInfo) => {
|
||||
const status = group.status;
|
||||
const groupId = group.groupId || '';
|
||||
return {
|
||||
deviceName: deviceInfo.deviceName,
|
||||
deviceType: deviceInfo.deviceType,
|
||||
status,
|
||||
groupId,
|
||||
};
|
||||
});
|
||||
return deviceInfo;
|
||||
})
|
||||
.flat();
|
||||
try {
|
||||
const params = {
|
||||
lineId: +setAlartTextData.value.lineId,
|
||||
deviceInfos,
|
||||
};
|
||||
const alertType = (saveAlertTypeData as never)[
|
||||
setAlartTextData.value.alertType + ''
|
||||
];
|
||||
await mockLocalDemoTestSet(alertType, params);
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: '设置故障测试成功',
|
||||
});
|
||||
onReset();
|
||||
} catch (err) {
|
||||
const apiErr = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: apiErr.title,
|
||||
});
|
||||
} finally {
|
||||
showsetAlartText.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let clickIndex: null | number = null;
|
||||
function toggleItem(index: number) {
|
||||
const lineApp = lineStore.getLineApp();
|
||||
selectGraphic = [];
|
||||
lineApp.updateSelected();
|
||||
if (setAlartTextData.value.groupList[index].expanded == true) {
|
||||
clickIndex = index;
|
||||
const select: JlGraphic[] = [];
|
||||
setAlartTextData.value.groupList[index].deviceInfos.forEach(
|
||||
(deviceInfo) => {
|
||||
const deviceType = (
|
||||
Object.keys(DeviceType) as Array<keyof typeof DeviceType>
|
||||
).find((key) => DeviceType[key] === deviceInfo.deviceType) as string;
|
||||
const g = lineApp.queryStore.queryByCodeAndType(
|
||||
deviceInfo.deviceName,
|
||||
deviceType
|
||||
) as JlGraphic;
|
||||
select.push(g);
|
||||
}
|
||||
);
|
||||
lineApp.updateSelected(...select);
|
||||
} else {
|
||||
clickIndex = null;
|
||||
}
|
||||
}
|
||||
|
||||
function clickSelectCenter(index: number) {
|
||||
const lineApp = lineStore.getLineApp();
|
||||
const clickTarget = setAlartTextData.value.groupList[clickIndex as number];
|
||||
const deviceType = (
|
||||
Object.keys(DeviceType) as Array<keyof typeof DeviceType>
|
||||
).find(
|
||||
(key) => DeviceType[key] === clickTarget.deviceInfos[index].deviceType
|
||||
) as string;
|
||||
const clickGraphic = lineApp.queryStore.queryByCodeAndType(
|
||||
clickTarget.deviceInfos[index].deviceName,
|
||||
deviceType
|
||||
) as JlGraphic;
|
||||
lineApp.makeGraphicCenterShow(clickGraphic);
|
||||
}
|
||||
|
||||
function removeSelect(removeIndex: number) {
|
||||
const clickTarget = setAlartTextData.value.groupList[clickIndex as number];
|
||||
selectGraphic.splice(removeIndex, 1);
|
||||
clickTarget.deviceInfos.splice(removeIndex, 1);
|
||||
lineStore.getLineApp().updateSelected(...selectGraphic);
|
||||
}
|
||||
|
||||
function clearAllSelect(index: number) {
|
||||
setAlartTextData.value.groupList[index].deviceInfos = [];
|
||||
selectGraphic = [];
|
||||
lineStore.getLineApp().updateSelected();
|
||||
}
|
||||
|
||||
function addSelectConfig() {
|
||||
setAlartTextData.value.groupList.push({
|
||||
groupName: '测试组',
|
||||
groupId: '',
|
||||
status: '',
|
||||
deviceInfos: [],
|
||||
expanded: false,
|
||||
});
|
||||
}
|
||||
|
||||
function deleteSelectConfig(index: number) {
|
||||
setAlartTextData.value.groupList.splice(index, 1);
|
||||
selectGraphic = [];
|
||||
lineStore.getLineApp().updateSelected();
|
||||
}
|
||||
|
||||
function onChooseAlertType() {
|
||||
setAlartTextData.value.groupList = [
|
||||
{
|
||||
groupName: '测试组',
|
||||
groupId: '',
|
||||
status: '',
|
||||
deviceInfos: [],
|
||||
expanded: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
setAlartTextData.value = {
|
||||
lineId: lineStore.lineId as unknown as string,
|
||||
alertType: '',
|
||||
groupList: [
|
||||
{
|
||||
groupName: '测试组',
|
||||
groupId: '',
|
||||
status: '',
|
||||
deviceInfos: [],
|
||||
expanded: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
selectGraphic = [];
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
lineStore.getLineApp().emit('options-update', {
|
||||
mouseToolOptions: {
|
||||
boxSelect: false,
|
||||
viewportDrag: true,
|
||||
viewportDragLeft: true,
|
||||
wheelZoom: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
</script>
|
@ -1,8 +1,60 @@
|
||||
<template>
|
||||
<q-dialog
|
||||
ref="dialogRef"
|
||||
@hide="onHide"
|
||||
v-bind="$attrs"
|
||||
@show="emit('show')"
|
||||
transitionShow="jump-up"
|
||||
transitionHide="jump-down"
|
||||
class="column"
|
||||
>
|
||||
<q-card
|
||||
:style="{
|
||||
transform: `translate3d(${offset.x}px, ${offset.y}px, 1px)`,
|
||||
background: `${props.bgColor}`,
|
||||
border: `${props.bgBorder}`,
|
||||
}"
|
||||
style="max-width: 2000px"
|
||||
>
|
||||
<q-bar
|
||||
ref="headerRef"
|
||||
class="non-selectable q-gutter-l"
|
||||
style="
|
||||
cursor: move;
|
||||
border-top-right-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
"
|
||||
:style="`height: ${props.titleHeight}px;background: ${props.titleColor}`"
|
||||
>
|
||||
<div
|
||||
:style="`height: 100%; line-height: ${props.titleHeight}px; color:${props.fontColor};font-size: ${props.fontSize}px;`"
|
||||
>
|
||||
{{ props.title }}
|
||||
</div>
|
||||
<q-space />
|
||||
<div style="margin-right: 10px"><slot name="titleButton"></slot></div>
|
||||
<q-btn dense flat icon="sym_o_close" v-close-popup></q-btn>
|
||||
</q-bar>
|
||||
<q-scroll-area
|
||||
:style="`width: ${props.width}px; height: ${props.height}px;`"
|
||||
>
|
||||
<slot></slot>
|
||||
</q-scroll-area>
|
||||
<div :style="`width: ${props.width}px`">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QBar, useDialogPluginComponent } from 'quasar';
|
||||
import { ref, onMounted, onUnmounted, reactive, withDefaults } from 'vue';
|
||||
import { ref, onMounted, onUnmounted, reactive } from 'vue';
|
||||
|
||||
const emit = defineEmits([...useDialogPluginComponent.emits]);
|
||||
const emit = defineEmits({
|
||||
...useDialogPluginComponent.emitsObject,
|
||||
show: () => true,
|
||||
});
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@ -14,6 +66,7 @@ const props = withDefaults(
|
||||
width?: number;
|
||||
height?: number;
|
||||
bgColor?: string;
|
||||
bgBorder?: string;
|
||||
}>(),
|
||||
{
|
||||
width: 500,
|
||||
@ -36,6 +89,7 @@ const offset = reactive({
|
||||
});
|
||||
|
||||
const start = { x: 0, y: 0 };
|
||||
const startOffset = { x: 0, y: 0 };
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('mousedown', onMouseDown);
|
||||
@ -46,16 +100,24 @@ onUnmounted(() => {
|
||||
});
|
||||
|
||||
function onMove(e: MouseEvent) {
|
||||
[offset.x, offset.y] = [e.screenX - start.x, e.screenY - start.y];
|
||||
let y = e.clientY > startOffset.y ? e.clientY : startOffset.y;
|
||||
if (y > window.innerHeight - props.titleHeight + startOffset.y) {
|
||||
y = window.innerHeight - props.titleHeight + startOffset.y;
|
||||
}
|
||||
[offset.x, offset.y] = [e.clientX - start.x, y - start.y];
|
||||
}
|
||||
function onMouseUp() {
|
||||
window.removeEventListener('mousemove', onMove);
|
||||
window.removeEventListener('mouseup', onMouseUp);
|
||||
startOffset.x = 0;
|
||||
startOffset.y = 0;
|
||||
}
|
||||
function onMouseDown(e: MouseEvent) {
|
||||
if (headerRef.value?.$el !== e.target) return;
|
||||
start.x = e.screenX - offset.x;
|
||||
start.y = e.screenY - offset.y;
|
||||
if (!e.target || !headerRef.value?.$el.contains(e.target)) return;
|
||||
startOffset.x = e.offsetX;
|
||||
startOffset.y = e.offsetY;
|
||||
start.x = e.clientX - offset.x;
|
||||
start.y = e.clientY - offset.y;
|
||||
window.addEventListener('mousemove', onMove);
|
||||
window.addEventListener('mouseup', onMouseUp);
|
||||
}
|
||||
@ -64,45 +126,3 @@ function onHide() {
|
||||
onDialogHide();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-dialog
|
||||
ref="dialogRef"
|
||||
@hide="onHide"
|
||||
v-bind="$attrs"
|
||||
transitionShow="jump-up"
|
||||
transitionHide="jump-down"
|
||||
class="column"
|
||||
>
|
||||
<q-card
|
||||
:style="{
|
||||
transform: `translate3d(${offset.x}px, ${offset.y}px, 1px)`,
|
||||
background: `${props.bgColor}`,
|
||||
}"
|
||||
style="max-width: 2000px"
|
||||
>
|
||||
<q-bar
|
||||
ref="headerRef"
|
||||
class="non-selectable q-gutter-l"
|
||||
style="cursor: move"
|
||||
:style="`height: ${props.titleHeight}px;background: ${props.titleColor}`"
|
||||
>
|
||||
<div
|
||||
:style="`color:${props.fontColor};font-size: ${props.fontSize}px;`"
|
||||
>
|
||||
{{ props.title }}
|
||||
</div>
|
||||
<q-space />
|
||||
<q-btn dense flat icon="sym_o_close" v-close-popup></q-btn>
|
||||
</q-bar>
|
||||
<q-scroll-area
|
||||
:style="`width: ${props.width}px; height: ${props.height}px;`"
|
||||
>
|
||||
<slot></slot>
|
||||
</q-scroll-area>
|
||||
<div :style="`width: ${props.width}px`">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
@ -19,9 +19,6 @@
|
||||
<template v-if="drawStore.drawGraphicType === Station.Type">
|
||||
<station-template></station-template>
|
||||
</template>
|
||||
<!-- <template v-if="drawStore.drawGraphicType === Train.Type">
|
||||
<train-template></train-template>
|
||||
</template> -->
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
@ -54,9 +51,6 @@
|
||||
<station-line-property
|
||||
v-if="drawStore.selectedGraphicType === StationLine.Type"
|
||||
></station-line-property>
|
||||
<!-- <train-property
|
||||
v-if="drawStore.selectedGraphicType === Train.Type"
|
||||
></train-property> -->
|
||||
<iscs-fan-property
|
||||
v-else-if="drawStore.selectedGraphicType === IscsFan.Type"
|
||||
></iscs-fan-property>
|
||||
@ -87,6 +81,11 @@
|
||||
<LogicSectionProperty
|
||||
v-else-if="drawStore.selectedGraphicType === LogicSection.Type"
|
||||
/>
|
||||
<concentrationDividingLine-property
|
||||
v-else-if="
|
||||
drawStore.selectedGraphicType === ConcentrationDividingLine.Type
|
||||
"
|
||||
/>
|
||||
</q-card-section>
|
||||
</template>
|
||||
</q-card>
|
||||
@ -96,6 +95,8 @@
|
||||
<script setup lang="ts">
|
||||
import LinkTemplate from './templates/LinkTemplate.vue';
|
||||
import RectTemplate from './templates/RectTemplate.vue';
|
||||
import ConcentrationDividingLineProperty from './properties/ConcentrationDividingLineProperty.vue';
|
||||
import { ConcentrationDividingLine } from 'src/graphics/concentrationDividingLine/ConcentrationDividingLine';
|
||||
import PlatformTemplate from './templates/PlatformTemplate.vue';
|
||||
import StationTemplate from './templates/StationTemplate.vue';
|
||||
// import TrainTemplate from './templates/TrainTemplate.vue';
|
||||
|
64
src/components/draw-app/dialogs/SetGaryLineDialog.vue
Normal file
64
src/components/draw-app/dialogs/SetGaryLineDialog.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<q-dialog ref="dialogRef" style="width 800px;">
|
||||
<q-card
|
||||
style="max-width: 900px"
|
||||
:style="{ width: `${80 * props.runLinePoints.length}px` }"
|
||||
>
|
||||
<q-card-section> <div class="text-h6">划定端点</div> </q-card-section>
|
||||
<q-card-section class="q-pt-none">
|
||||
<q-range
|
||||
class="q-mt-xl"
|
||||
v-model="model"
|
||||
color="purple"
|
||||
style="padding: 0px 30px; font-size: 10px"
|
||||
markers
|
||||
:marker-labels="objMarkerLabel"
|
||||
:min="0"
|
||||
:max="props.runLinePoints.length - 1"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn flat label="取消" @click="onDialogCancel" v-close-popup />
|
||||
<q-btn flat label="确认" @click="onDialogOK(model)" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { IPointData } from 'pixi.js';
|
||||
import { useDialogPluginComponent } from 'quasar';
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
runLinePoints: {
|
||||
type: Array<IPointData>,
|
||||
required: true,
|
||||
},
|
||||
garyPointIndexs: {
|
||||
type: Array<number>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const objMarkerLabel = (val: number) =>
|
||||
`P${val}[${props.runLinePoints[val].x},${props.runLinePoints[val].y}]`;
|
||||
const model = ref({
|
||||
min: 0,
|
||||
max: 0,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (props.garyPointIndexs.length) {
|
||||
model.value = {
|
||||
min: props.garyPointIndexs[0],
|
||||
max: props.garyPointIndexs[props.garyPointIndexs.length - 1],
|
||||
};
|
||||
}
|
||||
});
|
||||
defineEmits([...useDialogPluginComponent.emits]);
|
||||
|
||||
const { dialogRef, onDialogOK, onDialogCancel } = useDialogPluginComponent();
|
||||
</script>
|
||||
<style scoped></style>
|
@ -1,12 +1,6 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="axleCountingModel.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input outlined readonly v-model="axleCountingModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
label="计轴名称"
|
||||
@ -16,24 +10,29 @@
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="kilometerSystem.coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="kilometerSystem.kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item no-wrap class="q-gutter-y-sm column">
|
||||
<div>公里标配置</div>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="axleCountingModel.kilometerSystem.coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="axleCountingModel.kilometerSystem.kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
@ -72,17 +71,19 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { AxleCountingData } from 'src/drawApp/graphics/AxleCountingInteraction';
|
||||
import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { computed, onMounted, reactive, watch } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const axleCountingModel = reactive(new AxleCountingData());
|
||||
const kilometerSystem = reactive({ coordinateSystem: '', kilometer: 0 });
|
||||
|
||||
const { data: axleCountingModel, onUpdate } = useFormData(
|
||||
new AxleCountingData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
const CoordinateSystemOptions = [
|
||||
{ label: '车辆段', value: 'DEPOT' },
|
||||
{ label: '停车场', value: 'PARKING_LOT' },
|
||||
@ -90,46 +91,6 @@ const CoordinateSystemOptions = [
|
||||
{ label: '换线', value: 'TRANSFER' },
|
||||
];
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == AxleCounting.Type) {
|
||||
axleCountingModel.copyFrom(val.saveData() as AxleCountingData);
|
||||
if (axleCountingModel.kilometerSystem) {
|
||||
kilometerSystem.coordinateSystem =
|
||||
axleCountingModel.kilometerSystem.coordinateSystem;
|
||||
kilometerSystem.kilometer = axleCountingModel.kilometerSystem.kilometer;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const axleCounting = drawStore.selectedGraphic as AxleCounting;
|
||||
if (axleCounting) {
|
||||
axleCountingModel.copyFrom(axleCounting.saveData());
|
||||
if (axleCountingModel.kilometerSystem) {
|
||||
kilometerSystem.coordinateSystem =
|
||||
axleCountingModel.kilometerSystem.coordinateSystem;
|
||||
kilometerSystem.kilometer = axleCountingModel.kilometerSystem.kilometer;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const axleCounting = drawStore.selectedGraphic as AxleCounting;
|
||||
axleCountingModel.kilometerSystem = {
|
||||
coordinateSystem: kilometerSystem.coordinateSystem,
|
||||
kilometer: kilometerSystem.kilometer,
|
||||
};
|
||||
if (axleCounting) {
|
||||
drawStore
|
||||
.getDrawApp()
|
||||
.updateGraphicAndRecord(axleCounting, axleCountingModel);
|
||||
}
|
||||
}
|
||||
|
||||
const sectionRelations = computed(() => {
|
||||
const axleCounting = drawStore.selectedGraphic as AxleCounting;
|
||||
const sectionRelations =
|
||||
|
@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="concentrationDividingLineModel.id"
|
||||
label="id"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="concentrationDividingLineModel.refLeftStationId"
|
||||
:options="centralizedStations"
|
||||
emitValue
|
||||
mapOptions
|
||||
@update:model-value="onUpdate"
|
||||
label="左边关联的集中站"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="concentrationDividingLineModel.refRightStationId"
|
||||
:options="centralizedStations"
|
||||
emitValue
|
||||
mapOptions
|
||||
@update:model-value="onUpdate"
|
||||
label="右边关联的集中站"
|
||||
/>
|
||||
<q-toggle
|
||||
v-model="
|
||||
concentrationDividingLineModel.isOtherLineConcentrationDividingLine
|
||||
"
|
||||
label="是否与其它线的边界处"
|
||||
emit-value
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item
|
||||
v-for="sectionRelation in sectionRelations"
|
||||
:key="sectionRelation.label"
|
||||
>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
<q-item-label> {{ sectionRelation.label }} </q-item-label>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="(item, index) in sectionRelation.refSectionInfo"
|
||||
:key="index"
|
||||
square
|
||||
color="primary"
|
||||
text-color="white"
|
||||
>
|
||||
{{ item }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { ConcentrationDividingLineData } from 'src/drawApp/graphics/ConcentrationDividingLineInteraction';
|
||||
import { ConcentrationDividingLine } from 'src/graphics/concentrationDividingLine/ConcentrationDividingLine';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const { data: concentrationDividingLineModel, onUpdate } = useFormData(
|
||||
new ConcentrationDividingLineData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
const centralizedStations = ref<{ label: string; value: number }[]>([]);
|
||||
|
||||
const sectionRelations = computed(() => {
|
||||
const refSectionInfo: { label: string; refSectionInfo: string[] }[] = [
|
||||
{ label: '左边关联的设备', refSectionInfo: [] },
|
||||
{ label: '右边关联的设备', refSectionInfo: [] },
|
||||
];
|
||||
enum devicePort {
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
}
|
||||
const concentrationDividingLine =
|
||||
drawStore.selectedGraphic as ConcentrationDividingLine;
|
||||
concentrationDividingLine.datas.nodeConWithSecs.forEach((nodeConWithSec) => {
|
||||
const refleftSection = nodeConWithSec.leftSection?.id
|
||||
? `${
|
||||
drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryById<Section>(nodeConWithSec.leftSection.id).datas
|
||||
.code
|
||||
}(${devicePort[nodeConWithSec.leftSection.devicePort]})`
|
||||
: '边界';
|
||||
refSectionInfo[0].refSectionInfo.push(refleftSection);
|
||||
const refRightSection = nodeConWithSec.rightSection?.id
|
||||
? `${
|
||||
drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryById<Section>(nodeConWithSec.rightSection.id).datas
|
||||
.code
|
||||
}(${devicePort[nodeConWithSec.rightSection.devicePort]})`
|
||||
: '边界';
|
||||
refSectionInfo[1].refSectionInfo.push(refRightSection);
|
||||
});
|
||||
return refSectionInfo;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const stations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Station>(Station.Type);
|
||||
centralizedStations.value = [{ label: '', value: 0 }];
|
||||
stations.forEach((station) => {
|
||||
if (station.datas.concentrationStations || station.datas.depots) {
|
||||
centralizedStations.value.push({
|
||||
label: station.datas.name,
|
||||
value: station.datas.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
@ -59,38 +59,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { LinkData } from 'src/drawApp/graphics/LinkInteraction';
|
||||
import { Link } from 'src/graphics/link/Link';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const linkModel = reactive(new LinkData());
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Link.Type) {
|
||||
// console.log('link变更');
|
||||
linkModel.copyFrom(val.saveData() as LinkData);
|
||||
}
|
||||
}
|
||||
const { data: linkModel, onUpdate } = useFormData(
|
||||
new LinkData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// console.log('link 属性表单 mounted');
|
||||
const link = drawStore.selectedGraphic as Link;
|
||||
if (link) {
|
||||
linkModel.copyFrom(link.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
console.log('link 属性更新');
|
||||
const link = drawStore.selectedGraphic as Link;
|
||||
if (link) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(link, linkModel);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,10 +1,15 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="sectionModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="sectionModel.code"
|
||||
v-model="logicSectionModel.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="logicSectionModel.code"
|
||||
@blur="onUpdate"
|
||||
label="编号"
|
||||
/>
|
||||
@ -12,26 +17,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { LogicSectionData } from 'src/drawApp/graphics/LogicSectionInteraction';
|
||||
import { LogicSection } from 'src/graphics/logicSection/LogicSection';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { shallowRef, watchEffect } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
const sectionModel = shallowRef(new LogicSectionData());
|
||||
|
||||
watchEffect(() => {
|
||||
const section = drawStore.selectedGraphic;
|
||||
if (section && section instanceof LogicSection) {
|
||||
sectionModel.value = section.saveData();
|
||||
}
|
||||
});
|
||||
|
||||
const onUpdate = () => {
|
||||
const section = drawStore.selectedGraphic as LogicSection;
|
||||
if (section) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(section, sectionModel.value);
|
||||
}
|
||||
};
|
||||
const { data: logicSectionModel, onUpdate } = useFormData(
|
||||
new LogicSectionData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
</script>
|
||||
|
@ -52,24 +52,17 @@
|
||||
</q-form>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { PathLineData } from 'src/drawApp/graphics/PathLineInteraction';
|
||||
import { PathLine } from 'src/graphics/pathLine/PathLine';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { reactive, onMounted, watch } from 'vue';
|
||||
import { reactive, onMounted } from 'vue';
|
||||
import { getLineList } from 'src/api/LineInfoApi';
|
||||
const drawStore = useDrawStore();
|
||||
const pathLineModel = reactive(new PathLineData());
|
||||
const lineList: { label: string; value: string }[] = reactive([]);
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == PathLine.Type) {
|
||||
pathLineModel.copyFrom(val.saveData() as PathLineData);
|
||||
}
|
||||
}
|
||||
const { data: pathLineModel, onUpdate } = useFormData(
|
||||
new PathLineData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
const lineList: { label: string; value: string }[] = reactive([]);
|
||||
|
||||
onMounted(() => {
|
||||
getLineList()
|
||||
@ -81,16 +74,5 @@ onMounted(() => {
|
||||
.catch((err) => {
|
||||
console.error('获取线路列表失败:' + err.message);
|
||||
});
|
||||
const pathLine = drawStore.selectedGraphic as PathLine;
|
||||
if (pathLine) {
|
||||
pathLineModel.copyFrom(pathLine.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const pathLine = drawStore.selectedGraphic as PathLine;
|
||||
if (pathLine) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(pathLine, pathLineModel);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="platformModel.id" label="id" hint="" />
|
||||
<q-input outlined readonly v-model="platformModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
label="站台名称"
|
||||
@ -10,26 +10,30 @@
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="hasDoor"
|
||||
:options="optionsDoor"
|
||||
<q-toggle
|
||||
v-model="platformModel.hasdoor"
|
||||
label="是否有屏蔽门"
|
||||
emit-value
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
<q-select
|
||||
v-if="platformModel.hasdoor"
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="direction"
|
||||
v-model="platformModel.direction"
|
||||
:options="optionsDirection"
|
||||
label="方向"
|
||||
map-options
|
||||
emit-value
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="upAndDown"
|
||||
v-model="platformModel.up"
|
||||
:options="optionsUpAndDown"
|
||||
label="上下行"
|
||||
map-options
|
||||
emit-value
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item>
|
||||
@ -42,89 +46,85 @@
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
<q-item-label> 关联的物理区段 </q-item-label>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip square color="primary" text-color="white">
|
||||
{{ sectionName }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="platformModel.centralizedStation"
|
||||
:options="centralizedStations"
|
||||
emitValue
|
||||
mapOptions
|
||||
@update:model-value="onUpdate"
|
||||
label="关联的集中站"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { PlatformData } from 'src/drawApp/graphics/PlatformInteraction';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const platformModel = reactive(new PlatformData());
|
||||
const hasDoor = ref('是');
|
||||
const optionsDoor = ['是', '否'];
|
||||
const direction = ref('向上');
|
||||
const upAndDown = ref('');
|
||||
const optionsDirection = ['向上', '向下'];
|
||||
const optionsUpAndDown = ['上行', '下行'];
|
||||
const stationName = ref('');
|
||||
enum showSelect {
|
||||
是 = 'true',
|
||||
否 = 'false',
|
||||
向上 = 'up',
|
||||
向下 = 'down',
|
||||
}
|
||||
enum showUp {
|
||||
上行 = 'true',
|
||||
下行 = 'false',
|
||||
}
|
||||
enum showSelectData {
|
||||
true = '是',
|
||||
false = '否',
|
||||
up = '向上',
|
||||
down = '向下',
|
||||
}
|
||||
enum showUpData {
|
||||
true = '上行',
|
||||
false = '下行',
|
||||
}
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Platform.Type) {
|
||||
platformModel.copyFrom(val.saveData() as PlatformData);
|
||||
hasDoor.value = (showSelectData as never)[platformModel.hasdoor + ''];
|
||||
direction.value = (showSelectData as never)[platformModel.direction];
|
||||
upAndDown.value = (showUpData as never)[platformModel.up + ''];
|
||||
if (platformModel.refStation) {
|
||||
const refStation = val.queryStore.queryById<Station>(
|
||||
platformModel.refStation
|
||||
) as Station;
|
||||
stationName.value = refStation.datas.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
const { data: platformModel, onUpdate } = useFormData(
|
||||
new PlatformData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
const stationName = computed(() => {
|
||||
const platform = drawStore.selectedGraphic as Platform;
|
||||
if (platformModel.refStation) {
|
||||
const refStation = platform.queryStore.queryById<Station>(
|
||||
platformModel.refStation
|
||||
);
|
||||
return refStation.datas.name;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
const sectionName = computed(() => {
|
||||
const platform = drawStore.selectedGraphic as Platform;
|
||||
if (platformModel.refSectionId) {
|
||||
const refSection = platform.queryStore.queryById<Section>(
|
||||
platformModel.refSectionId
|
||||
);
|
||||
return refSection.datas.code;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
const optionsDirection = [
|
||||
{ label: '向上', value: 'up' },
|
||||
{ label: '向下', value: 'down' },
|
||||
];
|
||||
const optionsUpAndDown = [
|
||||
{ label: '上行', value: true },
|
||||
{ label: '下行', value: false },
|
||||
];
|
||||
const centralizedStations = ref<{ label: string; value: number }[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
const platform = drawStore.selectedGraphic as Platform;
|
||||
if (platform) {
|
||||
platformModel.copyFrom(platform.saveData());
|
||||
hasDoor.value = (showSelectData as never)[platformModel.hasdoor + ''];
|
||||
direction.value = (showSelectData as never)[platformModel.direction];
|
||||
upAndDown.value = (showUpData as never)[platformModel.up + ''];
|
||||
if (platformModel.refStation) {
|
||||
const refStation = platform.queryStore.queryById<Station>(
|
||||
platformModel.refStation
|
||||
) as Station;
|
||||
stationName.value = refStation.datas.name;
|
||||
const stations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Station>(Station.Type);
|
||||
centralizedStations.value = [{ label: '', value: 0 }];
|
||||
stations.forEach((station) => {
|
||||
if (station.datas.concentrationStations || station.datas.depots) {
|
||||
centralizedStations.value.push({
|
||||
label: station.datas.name,
|
||||
value: station.datas.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
platformModel.hasdoor = JSON.parse((showSelect as never)[hasDoor.value]);
|
||||
platformModel.direction = (showSelect as never)[direction.value];
|
||||
platformModel.up = JSON.parse((showUp as never)[upAndDown.value]);
|
||||
const platform = drawStore.selectedGraphic as Platform;
|
||||
if (platform) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(platform, platformModel);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -66,35 +66,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { RectData } from 'src/drawApp/graphics/RectInteraction';
|
||||
import { Rect } from 'src/graphics/rect/Rect';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const rectModel = reactive(new RectData());
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Rect.Type) {
|
||||
rectModel.copyFrom(val.saveData() as RectData);
|
||||
}
|
||||
}
|
||||
const { data: rectModel, onUpdate } = useFormData(
|
||||
new RectData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const Rect = drawStore.selectedGraphic as Rect;
|
||||
if (Rect) {
|
||||
rectModel.copyFrom(Rect.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const Rect = drawStore.selectedGraphic as Rect;
|
||||
if (Rect) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(Rect, rectModel);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -68,6 +68,30 @@
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="runLineModel.lineColor"
|
||||
@blur="onUpdate"
|
||||
label="线路背景色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线路背景色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="runLineModel.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
runLineModel.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<template :key="item" v-for="(item, index) in runLineModel.points">
|
||||
<div style="display: flex; margin-top: 5px">
|
||||
<q-input
|
||||
@ -118,10 +142,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { RunLineData } from 'src/drawApp/graphics/RunLineInteraction';
|
||||
import { RunLine } from 'src/graphics/runLine/RunLine';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch, ref } from 'vue';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
import { Point } from 'pixi.js';
|
||||
import {
|
||||
IStationLineData,
|
||||
@ -130,20 +155,13 @@ import {
|
||||
import { getLineList } from 'src/api/LineInfoApi';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const runLineModel = reactive(new RunLineData());
|
||||
const { data: runLineModel, onUpdate } = useFormData(
|
||||
new RunLineData(),
|
||||
useDrawStore().getDrawApp()
|
||||
);
|
||||
const stationLines: IStationLineData[] = reactive([]);
|
||||
const lineList: { label: string; value: string }[] = reactive([]);
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == RunLine.Type) {
|
||||
runLineModel.copyFrom(val.saveData() as RunLineData);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
getLineList()
|
||||
.then((res) => {
|
||||
@ -154,31 +172,23 @@ onMounted(() => {
|
||||
.catch((err) => {
|
||||
console.error('获取线路列表失败:' + err.message);
|
||||
});
|
||||
const runLine = drawStore.selectedGraphic as RunLine;
|
||||
const stations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType(StationLine.Type) as StationLine[];
|
||||
stations.forEach((item) => stationLines.push(item.datas));
|
||||
if (runLine) {
|
||||
runLineModel.copyFrom(runLine.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const runLine = drawStore.selectedGraphic as RunLine;
|
||||
if (runLine) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(runLine, runLineModel);
|
||||
}
|
||||
}
|
||||
function generatePathLine() {
|
||||
const runLine = drawStore.selectedGraphic as RunLine;
|
||||
if (runLine) {
|
||||
const points = runLineModel.points;
|
||||
const points1: Point[] = [];
|
||||
points.forEach((p) => points1.push(new Point(p.x, p.y)));
|
||||
runLineModel.points.forEach((p) =>
|
||||
points1.push(runLine.localToCanvasPoint(new Point(p.x, p.y)))
|
||||
);
|
||||
runLine.generatePathLine(points1);
|
||||
}
|
||||
}
|
||||
|
||||
function generateContainSta() {
|
||||
const runLine = drawStore.selectedGraphic as RunLine;
|
||||
if (runLine) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="sectionModel.id" label="id" hint="" />
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="sectionModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model="sectionModel.code"
|
||||
@ -9,14 +9,17 @@
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
class="q-mt-lg"
|
||||
v-model="sectionModel.destinationCode"
|
||||
@blur="onUpdate"
|
||||
label="目的地码"
|
||||
/>
|
||||
<q-checkbox
|
||||
v-model="sectionModel.turning"
|
||||
label="是否转换轨"
|
||||
@update:model-value="onUpdate"
|
||||
></q-checkbox>
|
||||
<q-field
|
||||
v-if="!isTurnoutPhysicalSection"
|
||||
class="q-mt-lg"
|
||||
outlined
|
||||
label="关联区段"
|
||||
readonly
|
||||
@ -35,7 +38,6 @@
|
||||
</q-field>
|
||||
<q-field
|
||||
v-if="!isTurnoutPhysicalSection"
|
||||
class="q-mt-lg"
|
||||
outlined
|
||||
label="关联道岔"
|
||||
readonly
|
||||
@ -64,20 +66,33 @@
|
||||
>
|
||||
</template>
|
||||
</q-field>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="sectionModel.centralizedStation"
|
||||
:options="centralizedStations"
|
||||
emitValue
|
||||
mapOptions
|
||||
@update:model-value="onUpdate"
|
||||
label="关联的集中站"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { SectionData } from 'src/drawApp/graphics/SectionInteraction';
|
||||
import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting';
|
||||
import { Section, SectionType } from 'src/graphics/section/Section';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { computed, shallowRef, watchEffect } from 'vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
const sectionModel = shallowRef(new SectionData());
|
||||
const { data: sectionModel, onUpdate } = useFormData(
|
||||
new SectionData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
const sectionRelations = computed(() => {
|
||||
const section = drawStore.selectedGraphic as Section;
|
||||
@ -87,12 +102,15 @@ const sectionRelations = computed(() => {
|
||||
section,
|
||||
Section.Type
|
||||
);
|
||||
return sectionRelations.map(
|
||||
(relation) =>
|
||||
`${relation.getRelationParam(section).param}: ${
|
||||
return sectionRelations.map((relation) => {
|
||||
if (relation.getRelationParam(section).param) {
|
||||
return `${relation.getRelationParam(section).param}: ${
|
||||
relation.getOtherGraphic<Section>(section).datas.code
|
||||
}(${relation.getOtherRelationParam(section).param})`
|
||||
);
|
||||
}(${relation.getOtherRelationParam(section).param})`;
|
||||
} else {
|
||||
return relation.getOtherGraphic<Section>(section).datas.code;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const turnoutRelations = computed(() => {
|
||||
@ -129,17 +147,21 @@ const axleCountingRelations = computed(() => {
|
||||
(relation) => relation.getOtherGraphic<AxleCounting>(section).datas.code
|
||||
);
|
||||
});
|
||||
watchEffect(() => {
|
||||
const section = drawStore.selectedGraphic;
|
||||
if (section && section instanceof Section) {
|
||||
sectionModel.value = section.saveData();
|
||||
}
|
||||
});
|
||||
|
||||
const onUpdate = () => {
|
||||
const section = drawStore.selectedGraphic as Section;
|
||||
if (section) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(section, sectionModel.value);
|
||||
}
|
||||
};
|
||||
const centralizedStations = ref<{ label: string; value: number }[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
const stations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Station>(Station.Type);
|
||||
centralizedStations.value = [{ label: '', value: 0 }];
|
||||
stations.forEach((station) => {
|
||||
if (station.datas.concentrationStations || station.datas.depots) {
|
||||
centralizedStations.value.push({
|
||||
label: station.datas.name,
|
||||
value: station.datas.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
@ -16,13 +16,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { SeparatorData } from 'src/drawApp/graphics/SeparatorInteraction';
|
||||
import { Separator, separatorTypeEnum } from 'src/graphics/separator/Separator';
|
||||
import { separatorTypeEnum } from 'src/graphics/separator/Separator';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const separatorModel = reactive(new SeparatorData());
|
||||
const { data: separatorModel, onUpdate } = useFormData(
|
||||
new SeparatorData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
const typeOptions = [
|
||||
{ label: '区段分隔符', value: separatorTypeEnum.section },
|
||||
@ -30,28 +33,4 @@ const typeOptions = [
|
||||
{ label: '左断路分隔符', value: separatorTypeEnum.endA },
|
||||
{ label: '右断路分隔符', value: separatorTypeEnum.endB },
|
||||
];
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Separator.Type) {
|
||||
separatorModel.copyFrom(val.saveData() as SeparatorData);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const Separator = drawStore.selectedGraphic as Separator;
|
||||
if (Separator) {
|
||||
separatorModel.copyFrom(Separator.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const Separator = drawStore.selectedGraphic as Separator;
|
||||
if (Separator) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(Separator, separatorModel);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="signalModel.id" label="id" hint="" />
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="signalModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="signalModel.code"
|
||||
@ -9,34 +9,106 @@
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="kilometerSystem.coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
v-model="refDevData.deviceType"
|
||||
:options="DeviceTypeOptions"
|
||||
readonly
|
||||
map-options
|
||||
emit-value
|
||||
label="关联设备类型:"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="kilometerSystem.kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
v-model="refDevData.code"
|
||||
:readonly="true"
|
||||
label="关联设备:"
|
||||
></q-input>
|
||||
<q-select
|
||||
outlined
|
||||
v-if="refDevData.deviceType === graphicData.RelatedRef.DeviceType.Turnout"
|
||||
v-model="refDevData.devicePort"
|
||||
:options="DevicePortOptions"
|
||||
:readonly="true"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="关联设备端口:"
|
||||
></q-select>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item no-wrap class="q-gutter-y-sm column">
|
||||
<div>公里标配置</div>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="signalModel.kilometerSystem.coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="signalModel.kilometerSystem.kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="signalModel.centralizedStation"
|
||||
:options="centralizedStations"
|
||||
emitValue
|
||||
mapOptions
|
||||
@update:model-value="onUpdate"
|
||||
label="关联的集中站"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { SignalData } from 'src/drawApp/graphics/SignalInteraction';
|
||||
import { Signal } from 'src/graphics/signal/Signal';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const signalModel = reactive(new SignalData());
|
||||
const kilometerSystem = reactive({ coordinateSystem: '', kilometer: 0 });
|
||||
const { data: signalModel, onUpdate } = useFormData(
|
||||
new SignalData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
const refDevData = computed(() => {
|
||||
return signalModel.refDevice
|
||||
? {
|
||||
...signalModel.refDevice.toObject(),
|
||||
code: drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryById<Section | Turnout>(signalModel.refDevice.id)
|
||||
.datas.code,
|
||||
}
|
||||
: {
|
||||
id: 0,
|
||||
deviceType: graphicData.RelatedRef.DeviceType.Section,
|
||||
devicePort: graphicData.RelatedRef.DevicePort.A,
|
||||
code: '',
|
||||
};
|
||||
});
|
||||
|
||||
const DeviceTypeOptions = [
|
||||
{ label: '区段', value: graphicData.RelatedRef.DeviceType.Section },
|
||||
{ label: '道岔', value: graphicData.RelatedRef.DeviceType.Turnout },
|
||||
];
|
||||
|
||||
const DevicePortOptions = [
|
||||
{ label: 'A端', value: graphicData.RelatedRef.DevicePort.A },
|
||||
{ label: 'B端', value: graphicData.RelatedRef.DevicePort.B },
|
||||
{ label: 'C端', value: graphicData.RelatedRef.DevicePort.C },
|
||||
];
|
||||
|
||||
const CoordinateSystemOptions = [
|
||||
{ label: '车辆段', value: 'DEPOT' },
|
||||
@ -44,42 +116,20 @@ const CoordinateSystemOptions = [
|
||||
{ label: '正线', value: 'MAIN_LINE' },
|
||||
{ label: '换线', value: 'TRANSFER' },
|
||||
];
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Signal.Type) {
|
||||
signalModel.copyFrom(val.saveData() as SignalData);
|
||||
if (signalModel.kilometerSystem) {
|
||||
kilometerSystem.coordinateSystem =
|
||||
signalModel.kilometerSystem.coordinateSystem;
|
||||
kilometerSystem.kilometer = signalModel.kilometerSystem.kilometer;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
const centralizedStations = ref<{ label: string; value: number }[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
const signal = drawStore.selectedGraphic as Signal;
|
||||
if (signal) {
|
||||
signalModel.copyFrom(signal.saveData());
|
||||
if (signalModel.kilometerSystem) {
|
||||
kilometerSystem.coordinateSystem =
|
||||
signalModel.kilometerSystem.coordinateSystem;
|
||||
kilometerSystem.kilometer = signalModel.kilometerSystem.kilometer;
|
||||
const stations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Station>(Station.Type);
|
||||
centralizedStations.value = [{ label: '', value: 0 }];
|
||||
stations.forEach((station) => {
|
||||
if (station.datas.concentrationStations || station.datas.depots) {
|
||||
centralizedStations.value.push({
|
||||
label: station.datas.name,
|
||||
value: station.datas.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const signal = drawStore.selectedGraphic as Signal;
|
||||
signalModel.kilometerSystem = {
|
||||
coordinateSystem: kilometerSystem.coordinateSystem,
|
||||
kilometer: kilometerSystem.kilometer,
|
||||
};
|
||||
if (signal) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(signal, signalModel);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
@ -24,64 +24,42 @@
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="hasTransfer"
|
||||
v-model="stationLineModel.hasTransfer"
|
||||
:options="optionsCircle"
|
||||
label="是否有换乘"
|
||||
map-options
|
||||
emit-value
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="stationLineModel.color"
|
||||
:options="colorOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="站名颜色"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { StationLineData } from 'src/drawApp/graphics/StationLineInteraction';
|
||||
import { StationLine } from 'src/graphics/stationLine/StationLine';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const stationLineModel = reactive(new StationLineData());
|
||||
const hasTransfer = ref('是');
|
||||
const optionsCircle = ['是', '否'];
|
||||
enum showSelect {
|
||||
是 = 'true',
|
||||
否 = 'false',
|
||||
}
|
||||
enum showSelectData {
|
||||
true = '是',
|
||||
false = '否',
|
||||
}
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == StationLine.Type) {
|
||||
stationLineModel.copyFrom(val.saveData() as StationLineData);
|
||||
hasTransfer.value = (showSelectData as never)[
|
||||
stationLineModel.hasTransfer + ''
|
||||
];
|
||||
}
|
||||
}
|
||||
const { data: stationLineModel, onUpdate } = useFormData(
|
||||
new StationLineData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
const optionsCircle = [
|
||||
{ label: '是', value: true },
|
||||
{ label: '否', value: false },
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
const stationLine = drawStore.selectedGraphic as StationLine;
|
||||
if (stationLine) {
|
||||
stationLineModel.copyFrom(stationLine.saveData());
|
||||
hasTransfer.value = (showSelectData as never)[
|
||||
stationLineModel.hasTransfer + ''
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
stationLineModel.hasTransfer = JSON.parse(
|
||||
(showSelect as never)[hasTransfer.value]
|
||||
);
|
||||
const stationLine = drawStore.selectedGraphic as StationLine;
|
||||
if (stationLine) {
|
||||
drawStore
|
||||
.getDrawApp()
|
||||
.updateGraphicAndRecord(stationLine, stationLineModel);
|
||||
}
|
||||
}
|
||||
const colorOptions = [
|
||||
{ label: '橘黄色', value: graphicData.StationLine.stationColor.orange },
|
||||
{ label: '灰色', value: graphicData.StationLine.stationColor.gray },
|
||||
];
|
||||
</script>
|
||||
|
@ -19,61 +19,74 @@
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item no-wrap class="q-gutter-y-sm column">
|
||||
<div>公里标配置</div>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="stationModel.kilometerSystem.coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="stationModel.kilometerSystem.kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-select
|
||||
v-if="stationModel.concentrationStations"
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="kilometerSystem.coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
v-model="stationModel.manageStations"
|
||||
label="集中站管理的车站"
|
||||
multiple
|
||||
:options="optionsStations"
|
||||
map-options
|
||||
emit-value
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="kilometerSystem.kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="hasControl"
|
||||
:options="optionsControl"
|
||||
<q-toggle
|
||||
v-model="stationModel.hasControl"
|
||||
label="是否有控制"
|
||||
emit-value
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="concentrationStations"
|
||||
:options="optionsControl"
|
||||
<q-toggle
|
||||
v-model="stationModel.concentrationStations"
|
||||
label="是否集中站"
|
||||
emit-value
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
<q-toggle
|
||||
v-model="stationModel.depots"
|
||||
label="是否车辆段"
|
||||
emit-value
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { StationData } from 'src/drawApp/graphics/StationInteraction';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { onMounted, watchEffect } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const stationModel = reactive(new StationData());
|
||||
const hasControl = ref('是');
|
||||
const concentrationStations = ref('否');
|
||||
const optionsControl = ['是', '否'];
|
||||
enum showSelect {
|
||||
是 = 'true',
|
||||
否 = 'false',
|
||||
}
|
||||
enum showSelectData {
|
||||
true = '是',
|
||||
false = '否',
|
||||
}
|
||||
const kilometerSystem = reactive({ coordinateSystem: '', kilometer: 0 });
|
||||
const { data: stationModel, onUpdate } = useFormData(
|
||||
new StationData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
let optionsStations: { label: string; value: number }[] = [];
|
||||
|
||||
const CoordinateSystemOptions = [
|
||||
{ label: '车辆段', value: 'DEPOT' },
|
||||
@ -82,55 +95,22 @@ const CoordinateSystemOptions = [
|
||||
{ label: '换线', value: 'TRANSFER' },
|
||||
];
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Station.Type) {
|
||||
stationModel.copyFrom(val.saveData() as StationData);
|
||||
hasControl.value = (showSelectData as never)[
|
||||
stationModel.hasControl + ''
|
||||
];
|
||||
concentrationStations.value = (showSelectData as never)[
|
||||
stationModel.concentrationStations + ''
|
||||
];
|
||||
if (stationModel.kilometerSystem) {
|
||||
kilometerSystem.coordinateSystem =
|
||||
stationModel.kilometerSystem.coordinateSystem;
|
||||
kilometerSystem.kilometer = stationModel.kilometerSystem.kilometer;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const station = drawStore.selectedGraphic as Station;
|
||||
if (station) {
|
||||
stationModel.copyFrom(station.saveData());
|
||||
hasControl.value = (showSelectData as never)[stationModel.hasControl + ''];
|
||||
concentrationStations.value = (showSelectData as never)[
|
||||
stationModel.concentrationStations + ''
|
||||
];
|
||||
if (stationModel.kilometerSystem) {
|
||||
kilometerSystem.coordinateSystem =
|
||||
stationModel.kilometerSystem.coordinateSystem;
|
||||
kilometerSystem.kilometer = stationModel.kilometerSystem.kilometer;
|
||||
}
|
||||
watchEffect(() => {
|
||||
if (
|
||||
stationModel.concentrationStations &&
|
||||
!stationModel.manageStations.includes(stationModel.id)
|
||||
) {
|
||||
stationModel.manageStations.push(stationModel.id);
|
||||
onUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
stationModel.hasControl = JSON.parse((showSelect as never)[hasControl.value]);
|
||||
stationModel.concentrationStations = JSON.parse(
|
||||
(showSelect as never)[concentrationStations.value]
|
||||
);
|
||||
stationModel.kilometerSystem = {
|
||||
coordinateSystem: kilometerSystem.coordinateSystem,
|
||||
kilometer: kilometerSystem.kilometer,
|
||||
};
|
||||
const station = drawStore.selectedGraphic as Station;
|
||||
if (station) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(station, stationModel);
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
optionsStations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Station>(Station.Type)
|
||||
.map((g) => {
|
||||
return { label: g.datas.name, value: g.datas.id };
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
@ -1,84 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="trainModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model="trainModel.code"
|
||||
label="车号"
|
||||
hint=""
|
||||
@blur="onUpdate"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="hasBorder"
|
||||
:options="optionsDoor"
|
||||
label="是否有边框"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="trainDirection"
|
||||
:options="optionsDirection"
|
||||
label="行驶方向"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TrainData } from 'src/drawApp/graphics/TrainInteraction';
|
||||
import { Train } from 'src/graphics/train/Train';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const trainModel = reactive(new TrainData());
|
||||
const hasBorder = ref('是');
|
||||
const optionsDoor = ['是', '否'];
|
||||
const trainDirection = ref('向左');
|
||||
const optionsDirection = ['向左', '向右'];
|
||||
enum showSelect {
|
||||
是 = 'true',
|
||||
否 = 'false',
|
||||
向左 = 'left',
|
||||
向右 = 'right',
|
||||
}
|
||||
enum showSelectData {
|
||||
true = '是',
|
||||
false = '否',
|
||||
left = '向左',
|
||||
right = '向右',
|
||||
}
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Train.Type) {
|
||||
trainModel.copyFrom(val.saveData() as TrainData);
|
||||
hasBorder.value = (showSelectData as never)[trainModel.hasBorder + ''];
|
||||
trainDirection.value = (showSelectData as never)[
|
||||
trainModel.trainDirection
|
||||
];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const train = drawStore.selectedGraphic as Train;
|
||||
if (train) {
|
||||
trainModel.copyFrom(train.saveData());
|
||||
hasBorder.value = (showSelectData as never)[trainModel.hasBorder + ''];
|
||||
trainDirection.value = (showSelectData as never)[trainModel.trainDirection];
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
trainModel.hasBorder = JSON.parse((showSelect as never)[hasBorder.value]);
|
||||
trainModel.trainDirection = (showSelect as never)[trainDirection.value];
|
||||
const train = drawStore.selectedGraphic as Train;
|
||||
if (train) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(train, trainModel);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -36,7 +36,7 @@
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
<q-item-label> 关联的道岔 </q-item-label>
|
||||
<q-item-label> 关联的道岔物理区段 </q-item-label>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="item in relatedTurnout"
|
||||
@ -55,42 +55,20 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { TrainWindowData } from 'src/drawApp/graphics/TrainWindowInteraction';
|
||||
import { LogicSection } from 'src/graphics/logicSection/LogicSection';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { TrainWindow } from 'src/graphics/trainWindow/TrainWindow';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { computed, onMounted, reactive, watch } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const trainWindowModel = reactive(new TrainWindowData());
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == TrainWindow.Type) {
|
||||
trainWindowModel.copyFrom(val.saveData() as TrainWindowData);
|
||||
}
|
||||
}
|
||||
const { data: trainWindowModel, onUpdate } = useFormData(
|
||||
new TrainWindowData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const trainWindow = drawStore.selectedGraphic as TrainWindow;
|
||||
if (trainWindow) {
|
||||
trainWindowModel.copyFrom(trainWindow.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const trainWindow = drawStore.selectedGraphic as TrainWindow;
|
||||
if (trainWindow) {
|
||||
drawStore
|
||||
.getDrawApp()
|
||||
.updateGraphicAndRecord(trainWindow, trainWindowModel);
|
||||
}
|
||||
}
|
||||
|
||||
const relatedLogicSection = computed((): LogicSection[] => {
|
||||
if (
|
||||
drawStore.selectedGraphic &&
|
||||
@ -100,12 +78,14 @@ const relatedLogicSection = computed((): LogicSection[] => {
|
||||
}
|
||||
return [];
|
||||
});
|
||||
const relatedTurnout = computed((): Turnout[] => {
|
||||
const relatedTurnout = computed((): Section[] => {
|
||||
if (
|
||||
drawStore.selectedGraphic &&
|
||||
drawStore.selectedGraphic.type === 'TrainWindow'
|
||||
) {
|
||||
return (drawStore.selectedGraphic as TrainWindow).getRelatedTurnouts();
|
||||
return (
|
||||
drawStore.selectedGraphic as TrainWindow
|
||||
).getRelatedTurnoutsSection();
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
@ -1,48 +1,52 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="turnoutModel.id" label="id" hint="" />
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="turnoutModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model="turnoutModel.code"
|
||||
@blur="onUpdate"
|
||||
label="编号"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="kilometerSystem[0].coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="kilometerSystem[0].kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="kilometerSystem[1].coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系2"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="kilometerSystem[1].kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item no-wrap class="q-gutter-y-sm column">
|
||||
<div>公里标配置</div>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="turnoutModel.kilometerSystem[0].coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="turnoutModel.kilometerSystem[0].kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
</q-item>
|
||||
<q-item no-wrap class="q-gutter-y-sm column">
|
||||
<div>公里标配置</div>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="turnoutModel.kilometerSystem[1].coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系2"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="turnoutModel.kilometerSystem[1].kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-field class="q-mt-lg" outlined label="关联区段" readonly stack-label>
|
||||
<template #control>
|
||||
<q-chip
|
||||
@ -67,28 +71,38 @@
|
||||
>
|
||||
</template>
|
||||
</q-field>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="turnoutModel.centralizedStation"
|
||||
:options="centralizedStations"
|
||||
emitValue
|
||||
mapOptions
|
||||
@update:model-value="onUpdate"
|
||||
label="关联的集中站"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { TurnoutData } from 'src/drawApp/graphics/TurnoutInteraction';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { computed, reactive, shallowRef, watchEffect } from 'vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const { data: turnoutModel, onUpdate } = useFormData(
|
||||
new TurnoutData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
const CoordinateSystemOptions = [
|
||||
{ label: '车辆段', value: 'DEPOT' },
|
||||
{ label: '停车场', value: 'PARKING_LOT' },
|
||||
{ label: '正线', value: 'MAIN_LINE' },
|
||||
{ label: '换线', value: 'TRANSFER' },
|
||||
];
|
||||
const turnoutModel = shallowRef(new TurnoutData());
|
||||
const kilometerSystem = reactive([
|
||||
{ coordinateSystem: '', kilometer: 0 },
|
||||
{ coordinateSystem: '', kilometer: 0 },
|
||||
]);
|
||||
|
||||
const sectionRelations = computed(() => {
|
||||
const turnout = drawStore.selectedGraphic as Turnout;
|
||||
@ -98,12 +112,15 @@ const sectionRelations = computed(() => {
|
||||
turnout,
|
||||
Section.Type
|
||||
);
|
||||
return sectionRelations.map(
|
||||
(relation) =>
|
||||
`${relation.getRelationParam(turnout).param}: ${
|
||||
return sectionRelations.map((relation) => {
|
||||
if (relation.getRelationParam(turnout).param) {
|
||||
return `${relation.getRelationParam(turnout).param}: ${
|
||||
relation.getOtherGraphic<Section>(turnout).datas.code
|
||||
}(${relation.getOtherRelationParam(turnout).param})`
|
||||
);
|
||||
}(${relation.getOtherRelationParam(turnout).param})`;
|
||||
} else {
|
||||
return relation.getOtherGraphic<Section>(turnout).datas.code;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const turnoutRelations = computed(() => {
|
||||
@ -122,28 +139,20 @@ const turnoutRelations = computed(() => {
|
||||
);
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
const turnout = drawStore.selectedGraphic;
|
||||
if (turnout && turnout instanceof Turnout) {
|
||||
turnoutModel.value = turnout.saveData();
|
||||
if (turnoutModel.value.kilometerSystem.length > 0) {
|
||||
kilometerSystem.forEach((ks, i) => {
|
||||
ks.coordinateSystem =
|
||||
turnoutModel.value.kilometerSystem[i].coordinateSystem;
|
||||
ks.kilometer = turnoutModel.value.kilometerSystem[i].kilometer;
|
||||
const centralizedStations = ref<{ label: string; value: number }[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
const stations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Station>(Station.Type);
|
||||
centralizedStations.value = [{ label: '', value: 0 }];
|
||||
stations.forEach((station) => {
|
||||
if (station.datas.concentrationStations || station.datas.depots) {
|
||||
centralizedStations.value.push({
|
||||
label: station.datas.name,
|
||||
value: station.datas.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const onUpdate = () => {
|
||||
const turnout = drawStore.selectedGraphic as Turnout;
|
||||
turnoutModel.value.kilometerSystem = kilometerSystem.map((ks) => ({
|
||||
coordinateSystem: ks.coordinateSystem,
|
||||
kilometer: ks.kilometer,
|
||||
}));
|
||||
if (turnout) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(turnout, turnoutModel.value);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
302
src/components/rangeConfigApp/RangeConfig.vue
Normal file
302
src/components/rangeConfigApp/RangeConfig.vue
Normal file
@ -0,0 +1,302 @@
|
||||
<template>
|
||||
<div v-if="showRangeConfig">
|
||||
<q-card class="q-gutter-sm q-pa-sm">
|
||||
<q-card-section>
|
||||
<div class="text-h6">{{ handleState }}</div>
|
||||
</q-card-section>
|
||||
<q-separator inset></q-separator>
|
||||
<q-form ref="myForm" @submit="onSubmit" @reset="onReset">
|
||||
<q-input
|
||||
outlined
|
||||
label="名称"
|
||||
v-model="rangeConfig.areaName"
|
||||
:rules="[(val) => val.trim() != '' || '名称不能为空']"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="rangeConfig.deviceType"
|
||||
:options="optionsType"
|
||||
label="设备类型"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
:rules="[(val) => val.trim() != '' || '设备类型不能为空']"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="rangeConfig.alertTypes"
|
||||
label="故障类型"
|
||||
multiple
|
||||
:options="optionsAlertType"
|
||||
:rules="[(val) => val.length > 0 || '故障类型不能为空']"
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
<q-item-label> 框选的设备 </q-item-label>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="item in device"
|
||||
:key="item"
|
||||
square
|
||||
color="primary"
|
||||
text-color="white"
|
||||
removable
|
||||
@remove="removeSelect(item)"
|
||||
>
|
||||
{{ item }}
|
||||
</q-chip>
|
||||
</div>
|
||||
<q-btn
|
||||
v-show="device.length > 0"
|
||||
style="width: 120px"
|
||||
label="清空框选的设备"
|
||||
color="red"
|
||||
@click="clearSelect"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<div class="q-gutter-sm q-pa-md row justify-center">
|
||||
<q-btn label="提交" type="submit" color="primary" class="q-mr-md" />
|
||||
<q-btn label="重置" type="reset" color="primary" />
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// import { useLineStore } from 'src/stores/line-store';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { QForm, useQuasar } from 'quasar';
|
||||
import { useRoute } from 'vue-router';
|
||||
import {
|
||||
deviceRangeSet,
|
||||
IAreaConfigItem,
|
||||
queryDeviceRangeById,
|
||||
} from 'src/api/ConfigApi';
|
||||
import { JlGraphic } from 'jl-graphic';
|
||||
import { saveAlertTypeData, showAlertTypeData } from '../alarm/alarmInfoEnum';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { useRangeConfigStore } from 'src/stores/range-config-store';
|
||||
import { getRangeConfigApp } from 'src/drawApp/rangeConfigApp';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
defineExpose({ searchById });
|
||||
|
||||
const route = useRoute();
|
||||
const rangeConfigStore = useRangeConfigStore();
|
||||
const $q = useQuasar();
|
||||
const showRangeConfig = ref(true);
|
||||
const rangeConfig = reactive<{
|
||||
areaName: string;
|
||||
deviceType: `${DeviceType}` | '';
|
||||
device: number[];
|
||||
alertTypes: string[];
|
||||
}>({
|
||||
areaName: '',
|
||||
deviceType: '',
|
||||
device: [],
|
||||
alertTypes: [],
|
||||
});
|
||||
const device = ref<string[]>([]);
|
||||
const handleState = ref('新建范围配置');
|
||||
|
||||
const optionsType = [
|
||||
{ label: '轨道', value: Section.Type },
|
||||
{ label: '道岔', value: Turnout.Type },
|
||||
{ label: '集中站', value: Station.Type },
|
||||
{ label: '站台', value: Platform.Type },
|
||||
];
|
||||
|
||||
const optionsAlertType = [
|
||||
'蓝显',
|
||||
'全线蓝显',
|
||||
'列车延误2分钟',
|
||||
'列车延误10分钟',
|
||||
'整侧站台门无关闭锁紧信号',
|
||||
'整侧站台门无法打开',
|
||||
'整侧站台门无法关闭',
|
||||
'道岔均失表',
|
||||
'道岔定位失表',
|
||||
'道岔反位失表',
|
||||
'计轴红光带',
|
||||
'计轴大面积红光带',
|
||||
'计轴橙光带',
|
||||
'计轴大面积橙光带',
|
||||
'道岔大面积失表',
|
||||
'列车信号故障',
|
||||
'一级联锁',
|
||||
];
|
||||
|
||||
enum DeviceType {
|
||||
station = 'DEVICE_TYPE_RTU',
|
||||
Turnout = 'DEVICE_TYPE_SWITCH',
|
||||
Section = 'DEVICE_TYPE_TRACK',
|
||||
Platform = 'DEVICE_TYPE_PLATFORM',
|
||||
}
|
||||
enum DeviceTypeShow {
|
||||
DEVICE_TYPE_RTU = 'station',
|
||||
DEVICE_TYPE_SWITCH = 'Turnout',
|
||||
DEVICE_TYPE_TRACK = 'Section',
|
||||
DEVICE_TYPE_PLATFORM = 'Platform',
|
||||
}
|
||||
|
||||
watch(
|
||||
() => rangeConfig.alertTypes,
|
||||
(alertTypes) => {
|
||||
if (alertTypes[0] == '一级联锁') {
|
||||
alertTypes.splice(1);
|
||||
}
|
||||
if (
|
||||
alertTypes[0] !== '一级联锁' &&
|
||||
alertTypes.slice(1).includes('一级联锁')
|
||||
) {
|
||||
for (let i = 0; i < alertTypes.length; i++) {
|
||||
if (alertTypes[i] == '一级联锁') {
|
||||
alertTypes.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let selectGraphic: JlGraphic[] = [];
|
||||
watch(
|
||||
() => rangeConfigStore.selectedGraphics,
|
||||
(val) => {
|
||||
if (val && val.length > 0) {
|
||||
const deviceFilter = rangeConfigStore.selectedGraphics?.filter((g) => {
|
||||
let select = false;
|
||||
if (
|
||||
g.type == Station.Type &&
|
||||
rangeConfig.deviceType == Station.Type &&
|
||||
(g as Station).datas.concentrationStations
|
||||
) {
|
||||
select = true;
|
||||
}
|
||||
if (g.type == rangeConfig.deviceType && g.type !== Station.Type) {
|
||||
select = true;
|
||||
}
|
||||
return select;
|
||||
}) as JlGraphic[];
|
||||
selectGraphic.push(...deviceFilter);
|
||||
selectGraphic = Array.from(new Set(selectGraphic));
|
||||
getRangeConfigApp().updateSelected(...selectGraphic);
|
||||
device.value = selectGraphic.map((g) => g.code) as string[];
|
||||
rangeConfig.device = selectGraphic.map((g) => g.id) as number[];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
let editId: number;
|
||||
let handle = ref('');
|
||||
let handleError = ref('');
|
||||
async function onSubmit() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
let validataOfDevice = false;
|
||||
if (rangeConfig.device.length) {
|
||||
validataOfDevice = true;
|
||||
} else {
|
||||
errorNotify('请框选设备', '');
|
||||
}
|
||||
if (res && validataOfDevice) {
|
||||
try {
|
||||
const lineId = +route.params.id as number;
|
||||
const alertTypes = rangeConfig.alertTypes.map(
|
||||
(type) => (saveAlertTypeData as never)[type + '']
|
||||
);
|
||||
const params: IAreaConfigItem = {
|
||||
lineId: lineId,
|
||||
areaName: rangeConfig.areaName,
|
||||
deviceType: (DeviceType as never)[rangeConfig.deviceType + ''],
|
||||
alertTypes: alertTypes,
|
||||
data: rangeConfig.device,
|
||||
};
|
||||
if (handleState.value == '新建范围配置') {
|
||||
handle.value = '创建成功';
|
||||
handleError.value = '创建失败';
|
||||
await deviceRangeSet(params);
|
||||
} else {
|
||||
params.id = editId;
|
||||
handle.value = '更新成功';
|
||||
handleError.value = '更新失败';
|
||||
await deviceRangeSet(params);
|
||||
}
|
||||
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: handle.value,
|
||||
});
|
||||
onReset();
|
||||
showRangeConfig.value = false;
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: (err as { title: '' }).title,
|
||||
});
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
showRangeConfig.value = true;
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function searchById(id: number) {
|
||||
try {
|
||||
handleState.value = '编辑范围配置';
|
||||
clearSelect();
|
||||
editId = id;
|
||||
const response = await queryDeviceRangeById(id);
|
||||
rangeConfig.areaName = response.data.areaName;
|
||||
rangeConfig.deviceType = (DeviceTypeShow as never)[
|
||||
response.data.deviceType + ''
|
||||
];
|
||||
rangeConfig.alertTypes = response.data.alertTypes.map(
|
||||
(type) => (showAlertTypeData as never)[type + '']
|
||||
);
|
||||
const select: JlGraphic[] = [];
|
||||
response.data.data.forEach((id: number) => {
|
||||
const g = getRangeConfigApp().queryStore.queryById(id);
|
||||
select.push(g);
|
||||
device.value.push(g.code);
|
||||
});
|
||||
getRangeConfigApp().updateSelected(...select);
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '没有需要编辑的详细信息',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function removeSelect(code: string) {
|
||||
const removeIndex = device.value.findIndex((item) => item == code);
|
||||
selectGraphic.splice(removeIndex, 1);
|
||||
device.value.splice(removeIndex, 1);
|
||||
rangeConfig.device.splice(removeIndex, 1);
|
||||
getRangeConfigApp().updateSelected(...selectGraphic);
|
||||
}
|
||||
|
||||
function clearSelect() {
|
||||
device.value = [];
|
||||
selectGraphic = [];
|
||||
getRangeConfigApp().updateSelected();
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
handleState.value = '新建范围配置';
|
||||
rangeConfig.areaName = '';
|
||||
rangeConfig.deviceType = '';
|
||||
rangeConfig.alertTypes = [];
|
||||
rangeConfig.device = [];
|
||||
clearSelect();
|
||||
}
|
||||
</script>
|
185
src/components/rangeConfigApp/RangeList.vue
Normal file
185
src/components/rangeConfigApp/RangeList.vue
Normal file
@ -0,0 +1,185 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
IAreaConfigListItem,
|
||||
getDeviceAreaList,
|
||||
deleteDeviceArea,
|
||||
} from 'src/api/ConfigApi';
|
||||
import { ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import DraggableDialog from '../common/DraggableDialog.vue';
|
||||
import { QTable, useQuasar } from 'quasar';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { deviceTypeMap } from 'src/api/TrainApi';
|
||||
|
||||
const $q = useQuasar();
|
||||
const lineId = useRoute().params.id as string;
|
||||
const tableRef = ref<QTable>();
|
||||
const columns: QTable['columns'] = [
|
||||
{ name: 'id', label: 'ID', field: 'id', align: 'center' },
|
||||
{ name: 'lineId', label: '线路ID', field: 'lineId', align: 'center' },
|
||||
{
|
||||
name: 'areaName',
|
||||
label: '名称',
|
||||
field: 'areaName',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'deviceType',
|
||||
label: '设备类型',
|
||||
field: (row) => deviceTypeMap[row.deviceType as keyof typeof deviceTypeMap],
|
||||
align: 'center',
|
||||
},
|
||||
{ name: 'operations', label: '操作', field: 'operations', align: 'center' },
|
||||
];
|
||||
const rows = ref<IAreaConfigListItem[]>([]);
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 1,
|
||||
rowsPerPage: 10,
|
||||
rowsNumber: 10,
|
||||
});
|
||||
|
||||
const searchAreaName = ref('');
|
||||
watch(
|
||||
() => searchAreaName.value,
|
||||
() => {
|
||||
tableRef.value?.requestServerInteraction();
|
||||
}
|
||||
);
|
||||
|
||||
const onRequest: QTable['onRequest'] = async (props) => {
|
||||
const { page, rowsPerPage } = props.pagination;
|
||||
loading.value = true;
|
||||
try {
|
||||
const resp = await getDeviceAreaList({
|
||||
lineId,
|
||||
current: page,
|
||||
size: rowsPerPage,
|
||||
areaName: searchAreaName.value,
|
||||
});
|
||||
pagination.value.page = resp.current;
|
||||
pagination.value.rowsNumber = resp.total;
|
||||
pagination.value.rowsPerPage = resp.size;
|
||||
rows.value = resp.records;
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: '无法获取范围列表',
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const onDialogShow = () => {
|
||||
tableRef.value?.requestServerInteraction();
|
||||
};
|
||||
|
||||
const dialogRef = ref<InstanceType<typeof DraggableDialog>>();
|
||||
const props = defineProps<{
|
||||
onEditClick: (row: IAreaConfigListItem) => void;
|
||||
}>();
|
||||
function onEdit(row: IAreaConfigListItem) {
|
||||
props.onEditClick(row);
|
||||
}
|
||||
function deleteData(row: IAreaConfigListItem) {
|
||||
$q.dialog({ message: `确定删除 "${row.areaName}" 吗?`, cancel: true }).onOk(
|
||||
async () => {
|
||||
try {
|
||||
await deleteDeviceArea(row.id);
|
||||
} catch (err) {
|
||||
errorNotify('删除失败:', err);
|
||||
} finally {
|
||||
tableRef.value?.requestServerInteraction();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<draggable-dialog
|
||||
ref="dialogRef"
|
||||
@show="onDialogShow"
|
||||
title="范围列表"
|
||||
:width="800"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<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]"
|
||||
>
|
||||
<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:body-cell-operations="props">
|
||||
<q-td :props="props">
|
||||
<div class="q-gutter-sm row justify-center">
|
||||
<q-btn color="primary" label="编辑" @click="onEdit(props.row)" />
|
||||
<q-btn color="red" label="删除" @click="deleteData(props.row)" />
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
</template>
|
||||
<template v-slot:titleButton>
|
||||
<q-btn square color="purple" style="margin-right: 10px" icon="search">
|
||||
<q-popup-edit
|
||||
ref="popupEdit"
|
||||
v-model="searchAreaName"
|
||||
:cover="false"
|
||||
:offset="[0, 10]"
|
||||
v-slot="scope"
|
||||
>
|
||||
<q-input
|
||||
color="accent"
|
||||
v-model="scope.value"
|
||||
label="区域名称"
|
||||
dense
|
||||
autofocus
|
||||
@keyup.enter="scope.set"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="search" color="accent" />
|
||||
</template>
|
||||
</q-input>
|
||||
</q-popup-edit>
|
||||
</q-btn>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.custom-column {
|
||||
max-width: 250px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.message-tip {
|
||||
width: 300px;
|
||||
overflow: auto;
|
||||
line-height: 22px;
|
||||
white-space: pre-wrap;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
33
src/components/state-app/StateProperties.vue
Normal file
33
src/components/state-app/StateProperties.vue
Normal file
@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<!-- 画布或图形对象属性 -->
|
||||
<div v-if="lineStore.selectedGraphics !== null">
|
||||
<q-card flat>
|
||||
<q-card-section>
|
||||
<div class="text-h6">
|
||||
{{ lineStore.selectedGraphicType + ' 状态属性' }}
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator inset></q-separator>
|
||||
<template v-if="lineStore.selectedGraphics.length === 1">
|
||||
<q-card-section>
|
||||
<platform-property
|
||||
v-if="lineStore.selectedGraphicType === Platform.Type"
|
||||
></platform-property>
|
||||
<station-property
|
||||
v-if="lineStore.selectedGraphicType === Station.Type"
|
||||
></station-property>
|
||||
</q-card-section>
|
||||
</template>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import PlatformProperty from './deviceStates/PlatformProperty.vue';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import StationProperty from './deviceStates/StationProperty.vue';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
</script>
|
247
src/components/state-app/deviceStates/PlatformProperty.vue
Normal file
247
src/components/state-app/deviceStates/PlatformProperty.vue
Normal file
@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="lineStore.selectedGraphic.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="站台名称"
|
||||
readonly
|
||||
@blur="onUpdate"
|
||||
v-model="lineStore.selectedGraphic.datas.code"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="psdOpen"
|
||||
:options="optionsChoose"
|
||||
label="屏蔽门打开"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="psdCut"
|
||||
:options="optionsChoose"
|
||||
label="屏蔽门切除"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="emergstop"
|
||||
:options="optionsChoose"
|
||||
label="是否紧急关闭"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="trainberth"
|
||||
:options="optionsChoose"
|
||||
label="是否在站台停站"
|
||||
/>
|
||||
<q-select
|
||||
v-if="lineStore.selectedGraphic.datas.up"
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="upHold"
|
||||
:options="optionsChoose"
|
||||
label="是否上行车站扣车"
|
||||
/>
|
||||
<q-select
|
||||
v-if="lineStore.selectedGraphic.datas.up"
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="upOccHold"
|
||||
:options="optionsChoose"
|
||||
label="是否上行中心扣车"
|
||||
/>
|
||||
<q-select
|
||||
v-if="!lineStore.selectedGraphic.datas.up"
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="downHold"
|
||||
:options="optionsChoose"
|
||||
label="是否下行车站扣车"
|
||||
/>
|
||||
<q-select
|
||||
v-if="!lineStore.selectedGraphic.datas.up"
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="downOccHold"
|
||||
:options="optionsChoose"
|
||||
label="是否下行中心扣车"
|
||||
/>
|
||||
<q-select
|
||||
v-if="lineStore.selectedGraphic.datas.up"
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="upSkipstop"
|
||||
:options="optionsChoose"
|
||||
label="是否上行跳停"
|
||||
/>
|
||||
<q-select
|
||||
v-if="!lineStore.selectedGraphic.datas.up"
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="downSkipstop"
|
||||
:options="optionsChoose"
|
||||
label="是否下行跳停"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="人工设置区间运行等级"
|
||||
type="textarea"
|
||||
@blur="onUpdate"
|
||||
v-model="platformModel.nextSectionRunTime"
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="人工设置停站时间"
|
||||
type="textarea"
|
||||
@blur="onUpdate"
|
||||
v-model="platformModel.stopTime"
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PlatformState } from 'src/drawApp/graphics/PlatformInteraction';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { mockPlatformApi, mockPlatformParams } from 'src/api/PlatformApi';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
const platformModel = reactive(new PlatformState());
|
||||
const optionsChoose = ['是', '否'];
|
||||
|
||||
const psdOpen = ref('');
|
||||
const psdCut = ref('');
|
||||
const emergstop = ref('');
|
||||
const trainberth = ref('');
|
||||
const upHold = ref('');
|
||||
const upOccHold = ref('');
|
||||
const upSkipstop = ref('');
|
||||
const downHold = ref('');
|
||||
const downOccHold = ref('');
|
||||
const downSkipstop = ref('');
|
||||
|
||||
enum showSelect {
|
||||
是 = 'true',
|
||||
否 = 'false',
|
||||
}
|
||||
enum showSelectData {
|
||||
true = '是',
|
||||
false = '否',
|
||||
}
|
||||
|
||||
lineStore.$subscribe;
|
||||
watch(
|
||||
() => lineStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Platform.Type) {
|
||||
platformModel.copyFrom((val as Platform).states as PlatformState);
|
||||
psdOpen.value = (showSelectData as never)[platformModel.psdOpen + ''];
|
||||
psdCut.value = (showSelectData as never)[platformModel.psdCut + ''];
|
||||
emergstop.value = (showSelectData as never)[platformModel.emergstop + ''];
|
||||
trainberth.value = (showSelectData as never)[
|
||||
platformModel.trainberth + ''
|
||||
];
|
||||
upHold.value = (showSelectData as never)[platformModel.upHold + ''];
|
||||
upOccHold.value = (showSelectData as never)[platformModel.upOccHold + ''];
|
||||
upSkipstop.value = (showSelectData as never)[
|
||||
platformModel.upSkipstop + ''
|
||||
];
|
||||
downHold.value = (showSelectData as never)[platformModel.downHold + ''];
|
||||
downOccHold.value = (showSelectData as never)[
|
||||
platformModel.downOccHold + ''
|
||||
];
|
||||
downSkipstop.value = (showSelectData as never)[
|
||||
platformModel.downSkipstop + ''
|
||||
];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const platform = lineStore.selectedGraphic as Platform;
|
||||
if (platform) {
|
||||
platformModel.copyFrom((platform as Platform).states as PlatformState);
|
||||
psdOpen.value = (showSelectData as never)[platformModel.psdOpen + ''];
|
||||
psdCut.value = (showSelectData as never)[platformModel.psdCut + ''];
|
||||
emergstop.value = (showSelectData as never)[platformModel.emergstop + ''];
|
||||
trainberth.value = (showSelectData as never)[platformModel.trainberth + ''];
|
||||
upHold.value = (showSelectData as never)[platformModel.upHold + ''];
|
||||
upOccHold.value = (showSelectData as never)[platformModel.upOccHold + ''];
|
||||
upSkipstop.value = (showSelectData as never)[platformModel.upSkipstop + ''];
|
||||
downHold.value = (showSelectData as never)[platformModel.downHold + ''];
|
||||
downOccHold.value = (showSelectData as never)[
|
||||
platformModel.downOccHold + ''
|
||||
];
|
||||
downSkipstop.value = (showSelectData as never)[
|
||||
platformModel.upSkipstop + ''
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const platform = lineStore.selectedGraphic as Platform;
|
||||
platformModel.psdOpen = JSON.parse((showSelect as never)[psdOpen.value]);
|
||||
platformModel.psdCut = JSON.parse((showSelect as never)[psdCut.value]);
|
||||
platformModel.emergstop = JSON.parse((showSelect as never)[emergstop.value]);
|
||||
platformModel.trainberth = JSON.parse(
|
||||
(showSelect as never)[trainberth.value]
|
||||
);
|
||||
platformModel.upHold = JSON.parse((showSelect as never)[upHold.value]);
|
||||
platformModel.upOccHold = JSON.parse((showSelect as never)[upOccHold.value]);
|
||||
platformModel.upSkipstop = JSON.parse(
|
||||
(showSelect as never)[upSkipstop.value]
|
||||
);
|
||||
platformModel.downHold = JSON.parse((showSelect as never)[downHold.value]);
|
||||
platformModel.downOccHold = JSON.parse(
|
||||
(showSelect as never)[downOccHold.value]
|
||||
);
|
||||
platformModel.downSkipstop = JSON.parse(
|
||||
(showSelect as never)[downSkipstop.value]
|
||||
);
|
||||
const data: { [key: string]: boolean | number | string } = {
|
||||
emergstop: false,
|
||||
trainberth: false,
|
||||
close: false,
|
||||
upHold: false,
|
||||
upOccHold: false,
|
||||
downOccHold: false,
|
||||
psdOpen: false,
|
||||
psdCut: false,
|
||||
upSkipstop: false,
|
||||
downSkipstop: false,
|
||||
upTrainSkipstop: false,
|
||||
downTrainSkipstop: false,
|
||||
downHold: false,
|
||||
id: platform.id,
|
||||
nextSectionRunTime: 0,
|
||||
nextSectionRunLevel: 0,
|
||||
stopTime: 0,
|
||||
};
|
||||
type keyData = 'emergstop' | 'trainberth';
|
||||
Object.keys(data).forEach((i) => {
|
||||
data[i] = platformModel[i as keyData] || data[i];
|
||||
});
|
||||
if (platform) {
|
||||
mockPlatformApi(3, data as unknown as mockPlatformParams)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, '---err---');
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
103
src/components/state-app/deviceStates/StationProperty.vue
Normal file
103
src/components/state-app/deviceStates/StationProperty.vue
Normal file
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="lineStore.selectedGraphic.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="车站名称"
|
||||
readonly
|
||||
@blur="onUpdate"
|
||||
v-model="lineStore.selectedGraphic.datas.name"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="controlChange"
|
||||
:options="optionsChoose"
|
||||
label="车站控制模式转换"
|
||||
/>
|
||||
<q-checkbox
|
||||
v-model="stationModel.ipRtuStusDown"
|
||||
label="是否通信中断"
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
<q-checkbox
|
||||
v-model="stationModel.ipRtuStusInLocalCtrl"
|
||||
label="是否站控"
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { StationState } from 'src/drawApp/graphics/StationInteraction';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { mockStationApi } from 'src/api/PlatformApi';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
const stationModel = reactive(new StationState());
|
||||
const optionsChoose = ['中控', '站控且允许转到中控', '站控且不允许转到中控'];
|
||||
|
||||
const controlChange = ref('');
|
||||
|
||||
lineStore.$subscribe;
|
||||
watch(
|
||||
() => lineStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Station.Type) {
|
||||
stationModel.copyFrom((val as Station).states as StationState);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const station = lineStore.selectedGraphic as Station;
|
||||
if (station) {
|
||||
stationModel.copyFrom((station as Station).states as StationState);
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const station = lineStore.selectedGraphic as Station;
|
||||
const data = {
|
||||
ipRtuStusDown: false,
|
||||
ipRtuStusInLocalCtrl: false,
|
||||
ipRtuStusInCentralCtrl: false,
|
||||
ipRtuStusInEmergencyCtrl: false,
|
||||
id: station.id,
|
||||
};
|
||||
const lineId = lineStore.lineId as number;
|
||||
data.ipRtuStusDown = stationModel.ipRtuStusDown;
|
||||
data.ipRtuStusInLocalCtrl = stationModel.ipRtuStusInLocalCtrl;
|
||||
if (station) {
|
||||
switch (controlChange.value) {
|
||||
case '中控':
|
||||
data.ipRtuStusInLocalCtrl = false;
|
||||
data.ipRtuStusDown = false;
|
||||
break;
|
||||
case '站控且允许转到中控':
|
||||
data.ipRtuStusInLocalCtrl = true;
|
||||
data.ipRtuStusDown = false;
|
||||
break;
|
||||
case '站控且不允许转到中控':
|
||||
data.ipRtuStusInLocalCtrl = true;
|
||||
data.ipRtuStusDown = true;
|
||||
break;
|
||||
}
|
||||
mockStationApi(lineId, data)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, '---err---');
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
31
src/components/webSocketConnect.ts
Normal file
31
src/components/webSocketConnect.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { HandleMessage, StompMessagingClient } from 'jl-graphic';
|
||||
import { getJwtToken } from 'src/configs/TokenManage';
|
||||
import { getWebsocketUrl } from 'src/configs/UrlManage';
|
||||
|
||||
export function webSocketConnect(destination: string, handler: HandleMessage) {
|
||||
const socket = new StompMessagingClient({
|
||||
wsUrl: `${getWebsocketUrl()}`,
|
||||
token: getJwtToken() as string,
|
||||
protocol: 'protobuf',
|
||||
connectTimeout: 30 * 1000,
|
||||
heartbeat: 60,
|
||||
retryPeriod: 2 * 1000,
|
||||
retryTimes: 100,
|
||||
});
|
||||
socket.on('connected', () => {
|
||||
socket?.subscribe(destination, handler);
|
||||
});
|
||||
socket.on('disconnected', () => {
|
||||
console.log('disconnected');
|
||||
});
|
||||
return socket;
|
||||
}
|
||||
|
||||
export function closeWebSocketConnect(
|
||||
socket: StompMessagingClient | null,
|
||||
destination: string
|
||||
) {
|
||||
socket?.unsubscribe0(destination);
|
||||
socket?.close();
|
||||
socket = null;
|
||||
}
|
@ -1,15 +1,23 @@
|
||||
function getHost(): string {
|
||||
// return '192.168.3.7:9081';
|
||||
// return '192.168.3.47:9081';
|
||||
// return '192.168.3.37:9081';
|
||||
// return '192.168.3.15:9081';
|
||||
return '192.168.3.233:9081';
|
||||
const base_api = process.env.API;
|
||||
// console.log(process.env);
|
||||
// console.log(' load env :' + process.env.NODE_ENV);
|
||||
return base_api + '';
|
||||
}
|
||||
|
||||
export function getHttpBase() {
|
||||
return `http://${getHost()}`;
|
||||
return process.env.HTTP + `${getHost()}` + process.env.NS;
|
||||
}
|
||||
|
||||
export function getWebsocketUrl() {
|
||||
return `ws://${getHost()}/ws-default`;
|
||||
return process.env.WS + `${getHost()}`+ process.env.NS+'/ws-default';
|
||||
}
|
||||
|
||||
export function getShowSetAlarmTextButton() {
|
||||
let show = false;
|
||||
const host = window.location.hostname;
|
||||
if (process.env.NODE_ENV == 'development' || host == '192.168.3.233') {
|
||||
show = true;
|
||||
}
|
||||
return show;
|
||||
}
|
||||
|
@ -1 +1,4 @@
|
||||
// app global css in SCSS form
|
||||
.my-notif-class {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
@ -33,6 +33,9 @@ export class AxleCountingData
|
||||
this.data.code = v;
|
||||
}
|
||||
get kilometerSystem(): KilometerSystem {
|
||||
if (!this.data.kilometerSystem) {
|
||||
this.data.kilometerSystem = new graphicData.KilometerSystem();
|
||||
}
|
||||
return this.data.kilometerSystem;
|
||||
}
|
||||
set kilometerSystem(v: KilometerSystem) {
|
||||
|
77
src/drawApp/graphics/ConcentrationDividingLineInteraction.ts
Normal file
77
src/drawApp/graphics/ConcentrationDividingLineInteraction.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import {
|
||||
IConcentrationDividingLineData,
|
||||
ConcentrationDividingLine,
|
||||
} from 'src/graphics/concentrationDividingLine/ConcentrationDividingLine';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { IPointData } from 'pixi.js';
|
||||
|
||||
export class ConcentrationDividingLineData
|
||||
extends GraphicDataBase
|
||||
implements IConcentrationDividingLineData
|
||||
{
|
||||
constructor(data?: graphicData.ConcentrationDividingLine) {
|
||||
let concentrationDividingLine;
|
||||
if (!data) {
|
||||
concentrationDividingLine = new graphicData.ConcentrationDividingLine({
|
||||
common: GraphicDataBase.defaultCommonInfo(
|
||||
ConcentrationDividingLine.Type
|
||||
),
|
||||
});
|
||||
} else {
|
||||
concentrationDividingLine = data;
|
||||
}
|
||||
super(concentrationDividingLine);
|
||||
}
|
||||
public get data(): graphicData.ConcentrationDividingLine {
|
||||
return this.getData<graphicData.ConcentrationDividingLine>();
|
||||
}
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get points(): IPointData[] {
|
||||
return this.data.points;
|
||||
}
|
||||
set points(points: IPointData[]) {
|
||||
this.data.points = points.map(
|
||||
(p) => new graphicData.Point({ x: p.x, y: p.y })
|
||||
);
|
||||
}
|
||||
get refLeftStationId(): number {
|
||||
return this.data.refLeftStationId;
|
||||
}
|
||||
set refLeftStationId(v: number) {
|
||||
this.data.refLeftStationId = v;
|
||||
}
|
||||
get refRightStationId(): number {
|
||||
return this.data.refRightStationId;
|
||||
}
|
||||
set refRightStationId(v: number) {
|
||||
this.data.refRightStationId = v;
|
||||
}
|
||||
get nodeConWithSecs(): graphicData.NodeConWithSec[] {
|
||||
return this.data.nodeConWithSecs;
|
||||
}
|
||||
set nodeConWithSecs(nodes: graphicData.NodeConWithSec[]) {
|
||||
this.data.nodeConWithSecs = nodes;
|
||||
}
|
||||
get isOtherLineConcentrationDividingLine(): boolean {
|
||||
return this.data.isOtherLineConcentrationDividingLine;
|
||||
}
|
||||
set isOtherLineConcentrationDividingLine(v: boolean) {
|
||||
this.data.isOtherLineConcentrationDividingLine = v;
|
||||
}
|
||||
clone(): ConcentrationDividingLineData {
|
||||
return new ConcentrationDividingLineData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: ConcentrationDividingLineData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: ConcentrationDividingLineData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
@ -6,14 +6,13 @@ import {
|
||||
GraphicTransform,
|
||||
IChildTransform,
|
||||
IGraphicTransform,
|
||||
} from 'src/jl-graphic';
|
||||
} from 'jl-graphic';
|
||||
// import { toStorageTransform } from '..';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { IPointData, Point } from 'pixi.js';
|
||||
import { state } from 'src/protos/device_status';
|
||||
|
||||
export interface ICommonInfo {
|
||||
id: string;
|
||||
id: number;
|
||||
graphicType: string;
|
||||
transform: IGraphicTransform;
|
||||
childTransforms: IChildTransform[];
|
||||
@ -60,7 +59,7 @@ export abstract class GraphicDataBase implements GraphicData {
|
||||
|
||||
static defaultCommonInfo(graphicType: string): graphicData.CommonInfo {
|
||||
return new graphicData.CommonInfo({
|
||||
id: '',
|
||||
id: 0,
|
||||
graphicType: graphicType,
|
||||
transform: new graphicData.Transform({
|
||||
position: new graphicData.Point({ x: 0, y: 0 }),
|
||||
@ -76,10 +75,10 @@ export abstract class GraphicDataBase implements GraphicData {
|
||||
return this._data as D;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
get id(): number {
|
||||
return this._data.common.id;
|
||||
}
|
||||
set id(v: string) {
|
||||
set id(v: number) {
|
||||
this._data.common.id = v;
|
||||
}
|
||||
get graphicType(): string {
|
||||
|
@ -3,20 +3,18 @@ import { IPointData, DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import { ILinkData, Link } from 'src/graphics/link/Link';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
import {
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
} from 'src/jl-graphic';
|
||||
import {
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
addWayPoint,
|
||||
clearWayPoint,
|
||||
getWaypointRangeIndex,
|
||||
PolylineEditPlugin,
|
||||
removeLineWayPoint,
|
||||
} from 'src/jl-graphic/plugins/GraphicEditPlugin';
|
||||
} from 'jl-graphic';
|
||||
|
||||
export class LinkData extends GraphicDataBase implements ILinkData {
|
||||
constructor(data?: graphicData.Link) {
|
||||
@ -119,12 +117,12 @@ const EpEditMenu: ContextMenu = ContextMenu.init({
|
||||
|
||||
export class DrawLinkPlugin extends GraphicInteractionPlugin<Link> {
|
||||
static Name = 'link_draw_right_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(DrawLinkPlugin.Name, app);
|
||||
app.registerMenu(LinkEditMenu);
|
||||
app.registerMenu(EpEditMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new DrawLinkPlugin(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Link[] | undefined {
|
||||
|
@ -10,15 +10,16 @@ import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { DisplayObject, FederatedMouseEvent, IPointData } from 'pixi.js';
|
||||
import { state } from 'src/protos/device_status';
|
||||
import {
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
} from 'src/jl-graphic';
|
||||
MenuItemOptions,
|
||||
ContextMenu,
|
||||
} from 'jl-graphic';
|
||||
import { LogicSectionGraphicHitArea } from 'src/graphics/logicSection/LogicSectionDrawAssistant';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { setTrackStatus } from 'src/api/TurnoutApi';
|
||||
import { successNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
let menuItemHandler: (propName: keyof ILogicSectionState) => void;
|
||||
|
||||
@ -54,6 +55,10 @@ const blocked: MenuItemOptions = {
|
||||
name: '轨道区段封锁 - blocked',
|
||||
handler: () => menuItemHandler('blocked'),
|
||||
};
|
||||
const speedLimit: MenuItemOptions = {
|
||||
name: '限速 - speedLimit',
|
||||
handler: () => menuItemHandler('speedLimit'),
|
||||
};
|
||||
|
||||
const LogicSectionMenu = ContextMenu.init({
|
||||
name: 'LogicSection菜单',
|
||||
@ -68,6 +73,7 @@ const LogicSectionMenu = ContextMenu.init({
|
||||
atcInvalid,
|
||||
overlap,
|
||||
blocked,
|
||||
speedLimit,
|
||||
],
|
||||
},
|
||||
],
|
||||
@ -75,25 +81,32 @@ const LogicSectionMenu = ContextMenu.init({
|
||||
|
||||
export class LogicSectionOperationPlugin extends GraphicInteractionPlugin<LogicSection> {
|
||||
static Name = 'logic_section_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(LogicSectionOperationPlugin.Name, app);
|
||||
app.registerMenu(LogicSectionMenu);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): LogicSection[] | undefined {
|
||||
return grahpics.filter((g): g is LogicSection => g instanceof LogicSection);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new LogicSectionOperationPlugin(app);
|
||||
}
|
||||
bind(g: LogicSection): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.lineGraphic.hitArea = new LogicSectionGraphicHitArea(g);
|
||||
g.on('_leftclick', this.onLeftClick, this);
|
||||
g.on('rightclick', this.onContextMenu, this);
|
||||
}
|
||||
unbind(g: LogicSection): void {
|
||||
g.off('_leftclick', this.onLeftClick, this);
|
||||
g.off('rightclick', this.onContextMenu);
|
||||
}
|
||||
onLeftClick(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const section = target.getGraphic() as LogicSection;
|
||||
this.app.updateSelected(section);
|
||||
}
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const section = target.getGraphic() as LogicSection;
|
||||
@ -141,10 +154,16 @@ export class LogicSectionOperationPlugin extends GraphicInteractionPlugin<LogicS
|
||||
menuItemHandler = (propName) => {
|
||||
const lineId = useLineStore().lineId?.toString();
|
||||
if (!lineId) return;
|
||||
console.log({ ...section.states });
|
||||
let val: boolean | number;
|
||||
if (propName !== 'speedLimit') {
|
||||
val = !section.states[propName];
|
||||
} else {
|
||||
val = section.states[propName] > 0 ? 0 : 20;
|
||||
successNotify(`限速设为${val}`);
|
||||
}
|
||||
setTrackStatus(lineId, {
|
||||
...state,
|
||||
[propName]: !section.states[propName],
|
||||
[propName]: val,
|
||||
});
|
||||
};
|
||||
LogicSectionMenu.open(e.global);
|
||||
@ -295,6 +314,14 @@ export class LogicSectionState
|
||||
public set limitType(value: LimitType) {
|
||||
this.states.limitType = value;
|
||||
}
|
||||
|
||||
// 集中站站号
|
||||
public get rtuId(): number {
|
||||
return this.states.rtuId;
|
||||
}
|
||||
public set rtuId(value: number) {
|
||||
this.states.rtuId = value;
|
||||
}
|
||||
clone(): LogicSectionState {
|
||||
return new LogicSectionState(this.states.cloneMessage());
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ import {
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { state } from 'src/protos/device_status';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import {
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
} from 'src/jl-graphic';
|
||||
MenuItemOptions,
|
||||
ContextMenu,
|
||||
} from 'jl-graphic';
|
||||
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import { mockPlatformApi } from 'src/api/PlatformApi';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
@ -59,12 +59,24 @@ export class PlatformData extends GraphicDataBase implements IPlatformData {
|
||||
set up(v: boolean) {
|
||||
this.data.up = v;
|
||||
}
|
||||
get refStation(): string {
|
||||
get refStation(): number {
|
||||
return this.data.refStation;
|
||||
}
|
||||
set refStation(v: string) {
|
||||
set refStation(v: number) {
|
||||
this.data.refStation = v;
|
||||
}
|
||||
get refSectionId(): number {
|
||||
return this.data.refSectionId;
|
||||
}
|
||||
set refSectionId(v: number) {
|
||||
this.data.refSectionId = v;
|
||||
}
|
||||
get centralizedStation(): number {
|
||||
return this.data.centralizedStationId;
|
||||
}
|
||||
set centralizedStation(v: number) {
|
||||
this.data.centralizedStationId = v;
|
||||
}
|
||||
|
||||
clone(): PlatformData {
|
||||
return new PlatformData(this.data.cloneMessage());
|
||||
@ -188,6 +200,13 @@ export class PlatformState extends GraphicStateBase implements IPlatformState {
|
||||
set stopTime(v: number) {
|
||||
this.states.stopTime = v;
|
||||
}
|
||||
// 集中站站号
|
||||
get rtuId(): number {
|
||||
return this.states.rtuId;
|
||||
}
|
||||
set rtuId(value: number) {
|
||||
this.states.rtuId = value;
|
||||
}
|
||||
get states(): state.Platform {
|
||||
return this.getState<state.Platform>();
|
||||
}
|
||||
@ -202,86 +221,26 @@ export class PlatformState extends GraphicStateBase implements IPlatformState {
|
||||
}
|
||||
}
|
||||
|
||||
const holdConfig: MenuItemOptions = {
|
||||
name: '扣车',
|
||||
};
|
||||
const removeHoldrConfig: MenuItemOptions = {
|
||||
name: '取消扣车',
|
||||
};
|
||||
const batchHoldConfig: MenuItemOptions = {
|
||||
name: '批量扣车',
|
||||
};
|
||||
const removeBatchHoldConfig: MenuItemOptions = {
|
||||
name: '批量取消扣车',
|
||||
};
|
||||
const earlyDepartureConfig: MenuItemOptions = {
|
||||
name: '提前发车',
|
||||
};
|
||||
const skipStopConfig: MenuItemOptions = {
|
||||
name: '设置跳停',
|
||||
};
|
||||
const removeSkipStopConfig: MenuItemOptions = {
|
||||
name: '取消跳停',
|
||||
};
|
||||
const dockTimeConfig: MenuItemOptions = {
|
||||
name: '设置停站时间',
|
||||
};
|
||||
const operatingLevelConfig: MenuItemOptions = {
|
||||
name: '设置运行等级',
|
||||
};
|
||||
const numberOfRegionalTrainsConfig: MenuItemOptions = {
|
||||
name: '区间列车数量限制',
|
||||
};
|
||||
const removeNumberOfRegionalTrainsConfig: MenuItemOptions = {
|
||||
name: '取消区间列车数量限制',
|
||||
};
|
||||
const platformMessadeConfig: MenuItemOptions = {
|
||||
name: '站台详细信息',
|
||||
const resetConfig: MenuItemOptions = {
|
||||
name: '重置状态',
|
||||
};
|
||||
|
||||
const PlatformOperateMenu: ContextMenu = ContextMenu.init({
|
||||
name: '站台操作菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [
|
||||
holdConfig,
|
||||
removeHoldrConfig,
|
||||
skipStopConfig,
|
||||
removeSkipStopConfig,
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const dispatchPlatformOperateMenu: ContextMenu = ContextMenu.init({
|
||||
name: '调度仿真站台操作菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [
|
||||
holdConfig,
|
||||
removeHoldrConfig,
|
||||
batchHoldConfig,
|
||||
removeBatchHoldConfig,
|
||||
earlyDepartureConfig,
|
||||
skipStopConfig,
|
||||
removeSkipStopConfig,
|
||||
dockTimeConfig,
|
||||
operatingLevelConfig,
|
||||
numberOfRegionalTrainsConfig,
|
||||
removeNumberOfRegionalTrainsConfig,
|
||||
platformMessadeConfig,
|
||||
],
|
||||
items: [resetConfig],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export class PlatformOperateInteraction extends GraphicInteractionPlugin<Platform> {
|
||||
static Name = 'platform_operate_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(PlatformOperateInteraction.Name, app);
|
||||
app.registerMenu(PlatformOperateMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new PlatformOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Platform[] | undefined {
|
||||
@ -327,70 +286,8 @@ export class PlatformOperateInteraction extends GraphicInteractionPlugin<Platfor
|
||||
nextSectionRunLevel: 0,
|
||||
stopTime: 0,
|
||||
};
|
||||
holdConfig.handler = () => {
|
||||
resetConfig.handler = () => {
|
||||
const dataCopy = JSON.parse(JSON.stringify(data));
|
||||
if (platform.datas.direction == 'down') {
|
||||
//dataCopy.upHold = true; //上行方向车站扣车
|
||||
dataCopy.trainberth = true; //列车停站
|
||||
dataCopy.emergstop = true; //紧急关闭
|
||||
dataCopy.upOccHold = true; //上行方向中心扣车
|
||||
dataCopy.psdOpen = true;
|
||||
dataCopy.nextSectionRunLevel = 2;
|
||||
dataCopy.nextSectionRunTime = 10;
|
||||
dataCopy.stopTime = 5;
|
||||
} else {
|
||||
dataCopy.downHold = true; //下行方向车站扣车
|
||||
dataCopy.downOccHold = true; //下行方向中心扣车
|
||||
dataCopy.psdCut = true;
|
||||
}
|
||||
mockPlatformApi(lineId, dataCopy)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, '---err---');
|
||||
});
|
||||
};
|
||||
removeHoldrConfig.handler = () => {
|
||||
const dataCopy = JSON.parse(JSON.stringify(data));
|
||||
if (platform.datas.direction == 'down') {
|
||||
dataCopy.upHold = false;
|
||||
} else {
|
||||
dataCopy.downHold = false;
|
||||
}
|
||||
mockPlatformApi(lineId, dataCopy)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, '---err---');
|
||||
});
|
||||
};
|
||||
skipStopConfig.handler = () => {
|
||||
const dataCopy = JSON.parse(JSON.stringify(data));
|
||||
if (platform.datas.direction == 'down') {
|
||||
dataCopy.upSkipstop = true; //上行方向跳停
|
||||
} else {
|
||||
dataCopy.downSkipstop = true; //下行方向跳停
|
||||
dataCopy.nextSectionRunLevel = 2;
|
||||
dataCopy.nextSectionRunTime = 10;
|
||||
dataCopy.stopTime = 5;
|
||||
}
|
||||
mockPlatformApi(lineId, dataCopy)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, '---err---');
|
||||
});
|
||||
};
|
||||
removeSkipStopConfig.handler = () => {
|
||||
const dataCopy = JSON.parse(JSON.stringify(data));
|
||||
if (platform.datas.direction == 'down') {
|
||||
dataCopy.upSkipstop = false;
|
||||
} else {
|
||||
dataCopy.downSkipstop = false;
|
||||
}
|
||||
mockPlatformApi(lineId, dataCopy)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
|
@ -4,7 +4,7 @@ import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import { DisplayObject, FederatedMouseEvent, IPointData } from 'pixi.js';
|
||||
import {
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
} from 'src/jl-graphic';
|
||||
@ -128,12 +128,12 @@ const EpEditMenu: ContextMenu = ContextMenu.init({
|
||||
|
||||
export class DrawPolygonPlugin extends GraphicInteractionPlugin<Polygon> {
|
||||
static Name = 'polygon_draw_right_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(DrawPolygonPlugin.Name, app);
|
||||
app.registerMenu(PolygonEditMenu);
|
||||
app.registerMenu(EpEditMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new DrawPolygonPlugin(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Polygon[] | undefined {
|
||||
|
@ -8,22 +8,21 @@ import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import {
|
||||
GraphicInteractionPlugin,
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
JlGraphic,
|
||||
} from 'src/jl-graphic';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
import { FederatedMouseEvent, DisplayObject, IPointData } from 'pixi.js';
|
||||
import {
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
addWayPoint,
|
||||
clearWayPoint,
|
||||
getWaypointRangeIndex,
|
||||
PolylineEditPlugin,
|
||||
removeLineWayPoint,
|
||||
} from 'src/jl-graphic/plugins/GraphicEditPlugin';
|
||||
} from 'jl-graphic';
|
||||
import { FederatedMouseEvent, DisplayObject, IPointData } from 'pixi.js';
|
||||
import { RunLineGraphicHitArea } from 'src/graphics/runLine/RunLineDrawAssistant';
|
||||
import { Dialog } from 'quasar';
|
||||
import SetDashLineDialog from '../../components/draw-app/dialogs/SetDashLineDialog.vue';
|
||||
import SetGaryLineDialog from '../../components/draw-app/dialogs/SetGaryLineDialog.vue';
|
||||
|
||||
export class RunLineData extends GraphicDataBase implements IRunLineData {
|
||||
constructor(data?: graphicData.RunLine) {
|
||||
@ -72,10 +71,10 @@ export class RunLineData extends GraphicDataBase implements IRunLineData {
|
||||
set containSta(v: string[]) {
|
||||
this.data.containSta = v;
|
||||
}
|
||||
get linkPathLines(): string[] {
|
||||
get linkPathLines(): number[] {
|
||||
return this.data.linkPathLines;
|
||||
}
|
||||
set linkPathLines(v: string[]) {
|
||||
set linkPathLines(v: number[]) {
|
||||
this.data.linkPathLines = v;
|
||||
}
|
||||
get lineId(): string {
|
||||
@ -90,6 +89,18 @@ export class RunLineData extends GraphicDataBase implements IRunLineData {
|
||||
set dashPointIndexs(v: number[]) {
|
||||
this.data.dashPointIndexs = v;
|
||||
}
|
||||
get grayPointIndexs(): number[] {
|
||||
return this.data.grayPointIndexs;
|
||||
}
|
||||
set grayPointIndexs(v: number[]) {
|
||||
this.data.grayPointIndexs = v;
|
||||
}
|
||||
get lineColor(): string {
|
||||
return this.data.lineColor;
|
||||
}
|
||||
set lineColor(v: string) {
|
||||
this.data.lineColor = v;
|
||||
}
|
||||
clone(): RunLineData {
|
||||
return new RunLineData(this.data.cloneMessage());
|
||||
}
|
||||
@ -113,12 +124,20 @@ export const clearWaypointsConfig: MenuItemOptions = {
|
||||
export const setDashLineConfig: MenuItemOptions = {
|
||||
name: '设置虚线段',
|
||||
};
|
||||
export const setGrayLineConfig: MenuItemOptions = {
|
||||
name: '设置灰线段',
|
||||
};
|
||||
|
||||
const RunLineEditMenu: ContextMenu = ContextMenu.init({
|
||||
name: '运行线编辑菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [addWaypointConfig, clearWaypointsConfig, setDashLineConfig],
|
||||
items: [
|
||||
addWaypointConfig,
|
||||
clearWaypointsConfig,
|
||||
setDashLineConfig,
|
||||
setGrayLineConfig,
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -133,12 +152,12 @@ const EpEditMenu: ContextMenu = ContextMenu.init({
|
||||
|
||||
export class DrawRunLinePlugin extends GraphicInteractionPlugin<RunLine> {
|
||||
static Name = 'runline_draw_right_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(DrawRunLinePlugin.Name, app);
|
||||
app.registerMenu(RunLineEditMenu);
|
||||
app.registerMenu(EpEditMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new DrawRunLinePlugin(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): RunLine[] | undefined {
|
||||
@ -195,7 +214,7 @@ export class DrawRunLinePlugin extends GraphicInteractionPlugin<RunLine> {
|
||||
};
|
||||
setDashLineConfig.handler = () => {
|
||||
Dialog.create({
|
||||
title: '创建列车',
|
||||
title: '设置虚线段',
|
||||
message: '',
|
||||
component: SetDashLineDialog,
|
||||
componentProps: {
|
||||
@ -215,17 +234,40 @@ export class DrawRunLinePlugin extends GraphicInteractionPlugin<RunLine> {
|
||||
runLine.doRepaint();
|
||||
});
|
||||
};
|
||||
setGrayLineConfig.handler = () => {
|
||||
console.log(runLine.datas, '11111');
|
||||
Dialog.create({
|
||||
title: '设置灰线段',
|
||||
message: '',
|
||||
component: SetGaryLineDialog,
|
||||
componentProps: {
|
||||
runLinePoints: runLine.datas.points,
|
||||
garyPointIndexs: runLine.datas.grayPointIndexs,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk((data: { min: number; max: number }) => {
|
||||
const indexList = [];
|
||||
if (data.min !== data.max) {
|
||||
for (let i = data.min; i <= data.max; i++) {
|
||||
indexList.push(i);
|
||||
}
|
||||
}
|
||||
runLine.datas.grayPointIndexs = indexList;
|
||||
runLine.doRepaint();
|
||||
});
|
||||
};
|
||||
RunLineEditMenu.open(e.global);
|
||||
}
|
||||
}
|
||||
|
||||
export class RunLineOperateInteraction extends GraphicInteractionPlugin<RunLine> {
|
||||
static Name = 'runLine_operate_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(RunLineOperateInteraction.Name, app);
|
||||
app.registerMenu(EpEditMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new RunLineOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): RunLine[] | undefined {
|
||||
|
@ -2,7 +2,9 @@ import * as pb_1 from 'google-protobuf';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import { ISectionData, Section } from 'src/graphics/section/Section';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { IPointData } from 'pixi.js';
|
||||
import { DisplayObject, FederatedMouseEvent, IPointData } from 'pixi.js';
|
||||
import { GraphicInteractionPlugin, IGraphicApp, JlGraphic } from 'jl-graphic';
|
||||
import { SectionGraphicHitArea } from 'src/graphics/section/SectionDrawAssistant';
|
||||
|
||||
export class SectionData extends GraphicDataBase implements ISectionData {
|
||||
constructor(data?: graphicData.Section) {
|
||||
@ -51,16 +53,16 @@ export class SectionData extends GraphicDataBase implements ISectionData {
|
||||
set sectionType(type: graphicData.Section.SectionType) {
|
||||
this.data.sectionType = type;
|
||||
}
|
||||
get axleCountings(): string[] {
|
||||
return this.data.axleCountings;
|
||||
get axleCountings(): number[] {
|
||||
return this.data.axleCountings.map((a) => Number(a));
|
||||
}
|
||||
set axleCountings(axleCountings: string[]) {
|
||||
this.data.axleCountings = axleCountings;
|
||||
set axleCountings(axleCountings: number[]) {
|
||||
this.data.axleCountings = axleCountings.map((a) => a.toString());
|
||||
}
|
||||
get children(): string[] {
|
||||
get children(): number[] {
|
||||
return this.data.children;
|
||||
}
|
||||
set children(children: string[]) {
|
||||
set children(children: number[]) {
|
||||
this.data.children = children;
|
||||
}
|
||||
get destinationCode(): string {
|
||||
@ -69,6 +71,18 @@ export class SectionData extends GraphicDataBase implements ISectionData {
|
||||
set destinationCode(destinationCode: string) {
|
||||
this.data.destinationCode = destinationCode;
|
||||
}
|
||||
get turning(): boolean {
|
||||
return this.data.turning;
|
||||
}
|
||||
set turning(v: boolean) {
|
||||
this.data.turning = v;
|
||||
}
|
||||
get centralizedStation(): number {
|
||||
return this.data.centralizedStationId;
|
||||
}
|
||||
set centralizedStation(v: number) {
|
||||
this.data.centralizedStationId = v;
|
||||
}
|
||||
clone(): SectionData {
|
||||
return new SectionData(this.data.cloneMessage());
|
||||
}
|
||||
@ -79,3 +93,30 @@ export class SectionData extends GraphicDataBase implements ISectionData {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class sectionOperationPlugin extends GraphicInteractionPlugin<Section> {
|
||||
static Name = 'logic_section_menu';
|
||||
constructor(app: IGraphicApp) {
|
||||
super(sectionOperationPlugin.Name, app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Section[] | undefined {
|
||||
return grahpics.filter((g): g is Section => g instanceof Section);
|
||||
}
|
||||
static init(app: IGraphicApp) {
|
||||
return new sectionOperationPlugin(app);
|
||||
}
|
||||
bind(g: Section): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.lineGraphic.hitArea = new SectionGraphicHitArea(g);
|
||||
g.on('_leftclick', this.onLeftClick, this);
|
||||
}
|
||||
unbind(g: Section): void {
|
||||
g.off('_leftclick', this.onLeftClick, this);
|
||||
}
|
||||
onLeftClick(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const section = target.getGraphic() as Section;
|
||||
this.app.updateSelected(section);
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,16 @@ import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import {
|
||||
GraphicInteractionPlugin,
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
JlGraphic,
|
||||
} from 'src/jl-graphic';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
} from 'jl-graphic';
|
||||
import { FederatedMouseEvent, DisplayObject } from 'pixi.js';
|
||||
import { state } from 'src/protos/device_status';
|
||||
import { mockSignalApi } from 'src/api/PlatformApi';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { SignalGraphicHitArea } from 'src/graphics/signal/SignalDrawAssistant';
|
||||
|
||||
export class SignalData extends GraphicDataBase implements ISignalData {
|
||||
constructor(data?: graphicData.Signal) {
|
||||
@ -46,12 +47,27 @@ export class SignalData extends GraphicDataBase implements ISignalData {
|
||||
set mirror(v: boolean) {
|
||||
this.data.mirror = v;
|
||||
}
|
||||
get refDevice(): graphicData.RelatedRef {
|
||||
return this.data.refDevice;
|
||||
}
|
||||
set refDevice(v: graphicData.RelatedRef) {
|
||||
this.data.refDevice = v;
|
||||
}
|
||||
get kilometerSystem(): KilometerSystem {
|
||||
if (!this.data.kilometerSystem) {
|
||||
this.data.kilometerSystem = new graphicData.KilometerSystem();
|
||||
}
|
||||
return this.data.kilometerSystem;
|
||||
}
|
||||
set kilometerSystem(v: KilometerSystem) {
|
||||
this.data.kilometerSystem = new graphicData.KilometerSystem(v);
|
||||
}
|
||||
get centralizedStation(): number {
|
||||
return this.data.centralizedStationId;
|
||||
}
|
||||
set centralizedStation(v: number) {
|
||||
this.data.centralizedStationId = v;
|
||||
}
|
||||
clone(): SignalData {
|
||||
return new SignalData(this.data.cloneMessage());
|
||||
}
|
||||
@ -215,6 +231,13 @@ export class SignalState extends GraphicStateBase implements ISignalState {
|
||||
set lampFailure(v: boolean) {
|
||||
this.states.lampFailure = v;
|
||||
}
|
||||
// 集中站站号
|
||||
get rtuId(): number {
|
||||
return this.states.rtuId;
|
||||
}
|
||||
set rtuId(value: number) {
|
||||
this.states.rtuId = value;
|
||||
}
|
||||
get states(): state.Signal {
|
||||
return this.getState<state.Signal>();
|
||||
}
|
||||
@ -275,11 +298,11 @@ const SignalOperateMenu: ContextMenu = ContextMenu.init({
|
||||
});
|
||||
export class DrawSignalInteraction extends GraphicInteractionPlugin<Signal> {
|
||||
static Name = 'signal_draw_right_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(DrawSignalInteraction.Name, app);
|
||||
app.registerMenu(SignalEditMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new DrawSignalInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Signal[] | undefined {
|
||||
@ -308,11 +331,11 @@ export class DrawSignalInteraction extends GraphicInteractionPlugin<Signal> {
|
||||
|
||||
export class SignalOperateInteraction extends GraphicInteractionPlugin<Signal> {
|
||||
static Name = 'signal_operate_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(SignalOperateInteraction.Name, app);
|
||||
app.registerMenu(SignalOperateMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new SignalOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Signal[] | undefined {
|
||||
@ -324,6 +347,7 @@ export class SignalOperateInteraction extends GraphicInteractionPlugin<Signal> {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.selectable = true;
|
||||
g.lampMainBody.hitArea = new SignalGraphicHitArea(g);
|
||||
g.on('_rightclick', this.onContextMenu, this);
|
||||
}
|
||||
|
||||
|
@ -7,17 +7,17 @@ import {
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { state } from 'src/protos/device_status';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import {
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
} from 'src/jl-graphic';
|
||||
MenuItemOptions,
|
||||
ContextMenu,
|
||||
} from 'jl-graphic';
|
||||
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import { KilometerSystem } from 'src/graphics/signal/Signal';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { mockStationApi } from 'src/api/PlatformApi';
|
||||
import { mockServerApi, mockStationApi } from 'src/api/PlatformApi';
|
||||
|
||||
export class StationData extends GraphicDataBase implements IStationData {
|
||||
constructor(data?: graphicData.Station) {
|
||||
@ -42,6 +42,9 @@ export class StationData extends GraphicDataBase implements IStationData {
|
||||
this.data.code = v;
|
||||
}
|
||||
get kilometerSystem(): KilometerSystem {
|
||||
if (!this.data.kilometerSystem) {
|
||||
this.data.kilometerSystem = new graphicData.KilometerSystem();
|
||||
}
|
||||
return this.data.kilometerSystem;
|
||||
}
|
||||
set kilometerSystem(v: KilometerSystem) {
|
||||
@ -65,6 +68,18 @@ export class StationData extends GraphicDataBase implements IStationData {
|
||||
set name(v: string) {
|
||||
this.data.name = v;
|
||||
}
|
||||
get manageStations(): number[] {
|
||||
return this.data.manageStations;
|
||||
}
|
||||
set manageStations(v: number[]) {
|
||||
this.data.manageStations = v;
|
||||
}
|
||||
get depots(): boolean {
|
||||
return this.data.depots;
|
||||
}
|
||||
set depots(v: boolean) {
|
||||
this.data.depots = v;
|
||||
}
|
||||
clone(): StationData {
|
||||
return new StationData(this.data.cloneMessage());
|
||||
}
|
||||
@ -88,7 +103,11 @@ export class StationState extends GraphicStateBase implements IStationState {
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.states.id;
|
||||
if (this.states.id.length === 1) {
|
||||
return '0' + this.states.id;
|
||||
} else {
|
||||
return this.states.id;
|
||||
}
|
||||
}
|
||||
get ipRtuStusDown(): boolean {
|
||||
return this.states.ipRtuStusDown;
|
||||
@ -117,6 +136,13 @@ export class StationState extends GraphicStateBase implements IStationState {
|
||||
get states(): state.Rtu {
|
||||
return this.getState<state.Rtu>();
|
||||
}
|
||||
// 集中站站号
|
||||
get rtuId(): number {
|
||||
return this.states.rtuId;
|
||||
}
|
||||
set rtuId(value: number) {
|
||||
this.states.rtuId = value;
|
||||
}
|
||||
clone(): StationState {
|
||||
return new StationState(this.states.cloneMessage());
|
||||
}
|
||||
@ -128,32 +154,32 @@ export class StationState extends GraphicStateBase implements IStationState {
|
||||
}
|
||||
}
|
||||
|
||||
const powerUnlockConfig: MenuItemOptions = {
|
||||
name: '上电解锁',
|
||||
const resetConfig: MenuItemOptions = {
|
||||
name: '重置状态',
|
||||
};
|
||||
const buleShow: MenuItemOptions = {
|
||||
name: '蓝显',
|
||||
};
|
||||
const cancelBuleShow: MenuItemOptions = {
|
||||
name: '取消蓝显',
|
||||
};
|
||||
|
||||
const chainConfig: MenuItemOptions = {
|
||||
name: '全站设置连锁自动触发',
|
||||
};
|
||||
const removeChainConfig: MenuItemOptions = {
|
||||
name: '全站取消连锁自动触发',
|
||||
};
|
||||
const StationOperateMenu: ContextMenu = ContextMenu.init({
|
||||
name: '车站操作菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [powerUnlockConfig, chainConfig, removeChainConfig],
|
||||
items: [resetConfig, buleShow, cancelBuleShow],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export class StationOperateInteraction extends GraphicInteractionPlugin<Station> {
|
||||
static Name = 'station_operate_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(StationOperateInteraction.Name, app);
|
||||
app.registerMenu(StationOperateMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new StationOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Station[] | undefined {
|
||||
@ -187,34 +213,30 @@ export class StationOperateInteraction extends GraphicInteractionPlugin<Station>
|
||||
ipRtuStusInEmergencyCtrl: false,
|
||||
id: station.id,
|
||||
};
|
||||
powerUnlockConfig.handler = () => {
|
||||
/* station.states.ipRtuStusInLocalCtrl = true;
|
||||
station.doRepaint(); */
|
||||
const dataCopy = JSON.parse(JSON.stringify(data));
|
||||
dataCopy.ipRtuStusInLocalCtrl = true;
|
||||
mockStationApi(lineId, dataCopy)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, '---err---');
|
||||
});
|
||||
buleShow.handler = () => {
|
||||
const data = {
|
||||
deviceType: 'DEVICE_TYPE_RTU',
|
||||
messageId: 'DEVICE_STATUS_CHANGE',
|
||||
lineId: 3,
|
||||
rtuId: station.states.rtuId,
|
||||
deviceName: station.states.rtuId + '',
|
||||
deviceStatus: 32768,
|
||||
};
|
||||
mockServerApi(data);
|
||||
};
|
||||
chainConfig.handler = () => {
|
||||
const dataCopy = JSON.parse(JSON.stringify(data));
|
||||
dataCopy.ipRtuStusInLocalCtrl = true;
|
||||
dataCopy.ipRtuStusDown = true;
|
||||
mockStationApi(lineId, dataCopy)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, '---err---');
|
||||
});
|
||||
cancelBuleShow.handler = () => {
|
||||
const data = {
|
||||
deviceType: 'DEVICE_TYPE_RTU',
|
||||
messageId: 'DEVICE_STATUS_CHANGE',
|
||||
lineId: 3,
|
||||
rtuId: station.states.rtuId,
|
||||
deviceName: station.states.rtuId + '',
|
||||
deviceStatus: 1,
|
||||
};
|
||||
mockServerApi(data);
|
||||
};
|
||||
removeChainConfig.handler = () => {
|
||||
resetConfig.handler = () => {
|
||||
const dataCopy = JSON.parse(JSON.stringify(data));
|
||||
dataCopy.ipRtuStusInLocalCtrl = false;
|
||||
mockStationApi(lineId, dataCopy)
|
||||
.then((res) => {
|
||||
console.log(res, '---res--');
|
||||
|
@ -43,6 +43,12 @@ export class StationLineData
|
||||
set hideName(v: boolean) {
|
||||
this.data.hideName = v;
|
||||
}
|
||||
get color(): graphicData.StationLine.stationColor {
|
||||
return this.data.codeColor;
|
||||
}
|
||||
set color(v: graphicData.StationLine.stationColor) {
|
||||
this.data.codeColor = v;
|
||||
}
|
||||
clone(): StationLineData {
|
||||
return new StationLineData(this.data.cloneMessage());
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { state } from 'src/protos/device_status';
|
||||
import { train } from 'src/protos/train';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import {
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
VectorText,
|
||||
} from 'src/jl-graphic';
|
||||
MenuItemOptions,
|
||||
ContextMenu,
|
||||
} from 'jl-graphic';
|
||||
import {
|
||||
Color,
|
||||
Container,
|
||||
@ -69,6 +69,11 @@ export class TrainState extends GraphicStateBase implements ITrainState {
|
||||
get code(): string {
|
||||
return this.states.groupId;
|
||||
}
|
||||
get remove(): boolean {
|
||||
const rtuIdArr = [81, 82];
|
||||
const hasRtuId = rtuIdArr.includes(this.states.rtuId);
|
||||
return hasRtuId;
|
||||
}
|
||||
|
||||
get states(): train.TrainInfo {
|
||||
return this.getState<train.TrainInfo>();
|
||||
@ -194,12 +199,12 @@ export class TrainState extends GraphicStateBase implements ITrainState {
|
||||
set rate(v: number) {
|
||||
this.states.rate = v;
|
||||
}
|
||||
get remove(): train.TrainRemove {
|
||||
return this.states.remove;
|
||||
}
|
||||
set remove(v: train.TrainRemove) {
|
||||
this.states.remove = new train.TrainRemove(v);
|
||||
}
|
||||
// get remove(): train.TrainRemove {
|
||||
// return this.states.remove;
|
||||
// }
|
||||
// set remove(v: train.TrainRemove) {
|
||||
// this.states.remove = new train.TrainRemove(v);
|
||||
// }
|
||||
get block(): train.TrainBlock {
|
||||
return this.states.block;
|
||||
}
|
||||
@ -269,13 +274,12 @@ const TrainOperateMenu: ContextMenu = ContextMenu.init({
|
||||
export class TrainOperateInteraction extends GraphicInteractionPlugin<Train> {
|
||||
static Name = 'train_operate_menu';
|
||||
hoverLaber: TrainHoverLabel;
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(TrainOperateInteraction.Name, app);
|
||||
this.hoverLaber = new TrainHoverLabel();
|
||||
app.canvas.addChild(this.hoverLaber);
|
||||
app.registerMenu(TrainOperateMenu);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new TrainOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Train[] | undefined {
|
||||
@ -290,7 +294,7 @@ export class TrainOperateInteraction extends GraphicInteractionPlugin<Train> {
|
||||
this.onMouseHover(g);
|
||||
};
|
||||
g.trainbody.onmouseout = () => {
|
||||
this.onMouseOut();
|
||||
this.onMouseOut(g);
|
||||
};
|
||||
}
|
||||
|
||||
@ -304,13 +308,15 @@ export class TrainOperateInteraction extends GraphicInteractionPlugin<Train> {
|
||||
|
||||
onMouseHover(g: Train): void {
|
||||
if (!this.hoverLaber.isShow) {
|
||||
g.addChild(this.hoverLaber);
|
||||
this.hoverLaber.doRepaint(g.states);
|
||||
const bodyWh = g.trainbody.localBoundsToCanvasPoints();
|
||||
this.hoverLaber.position.set(bodyWh[2].x, bodyWh[2].y);
|
||||
const bodyWh = g.trainbody.getBodyWH();
|
||||
this.hoverLaber.position.set(bodyWh.width / 2, bodyWh.height / 2);
|
||||
}
|
||||
}
|
||||
onMouseOut(): void {
|
||||
onMouseOut(g: Train): void {
|
||||
if (this.hoverLaber.isShow) {
|
||||
g.removeChild(this.hoverLaber);
|
||||
this.hoverLaber.clear();
|
||||
}
|
||||
}
|
||||
@ -430,6 +436,7 @@ const labelConsts = {
|
||||
codeFontSize: 12,
|
||||
};
|
||||
class TrainHoverLabel extends Container {
|
||||
static Type = 'TrainHoverLabel';
|
||||
boxRact: Graphics = new Graphics();
|
||||
sText: VectorText = new VectorText('');
|
||||
isShow: boolean;
|
||||
@ -446,7 +453,12 @@ class TrainHoverLabel extends Container {
|
||||
fill: labelConsts.textColor,
|
||||
fontSize: labelConsts.codeFontSize,
|
||||
};
|
||||
const text = `列车类型:计划车\n来 源:人工标记\n车 组 号:${states.groupId}\n表 号:${states.trainId}\n车 次 号:${states.globalId}`;
|
||||
const codeA = states.groupId;
|
||||
// const firstChar = codeA.substring(0, 1); // 获取首字符
|
||||
// if (+firstChar == states.lineId) {
|
||||
// codeA = codeA.substring(1); // 删除首字符是线路号的字符
|
||||
// }
|
||||
const text = `列车类型:计划车\n来 源:人工标记\n车 组 号:${codeA}\n表 号:${states.trainId}\n车 次 号:${states.globalId}\n线 路 号:${states.lineId}`;
|
||||
this.sText.text = text;
|
||||
this.sText.style = style;
|
||||
const { width: codeWidth, height: codeHeight } =
|
||||
|
@ -31,10 +31,10 @@ export class TrainWindowData
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get refDeviceId(): string[] {
|
||||
get refDeviceId(): number[] {
|
||||
return this.data.refDeviceId;
|
||||
}
|
||||
set refDeviceId(v: string[]) {
|
||||
set refDeviceId(v: number[]) {
|
||||
this.data.refDeviceId = v;
|
||||
}
|
||||
clone(): TrainWindowData {
|
||||
|
@ -10,18 +10,19 @@ import { DisplayObject, FederatedMouseEvent, IPointData } from 'pixi.js';
|
||||
import { KilometerSystem } from 'src/graphics/signal/Signal';
|
||||
import { state } from 'src/protos/device_status';
|
||||
import {
|
||||
GraphicApp,
|
||||
IGraphicApp,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
} from 'src/jl-graphic';
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
} from 'jl-graphic';
|
||||
import {
|
||||
ForkHitArea,
|
||||
TurnoutSectionHitArea,
|
||||
} from 'src/graphics/turnout/TurnoutDrawAssistant';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
import { setSwitchStatus } from 'src/api/TurnoutApi';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { successNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
let menuItemHandler: (propName: keyof ITurnoutState) => void;
|
||||
|
||||
@ -102,7 +103,10 @@ const ipSingleSwitchStusLostIndication: MenuItemOptions = {
|
||||
name: '道岔失表示-ipSingleSwitchStusLostIndication',
|
||||
handler: () => menuItemHandler('ipSingleSwitchStusLostIndication'),
|
||||
};
|
||||
|
||||
const speedLimit: MenuItemOptions = {
|
||||
name: '限速 - speedLimit',
|
||||
handler: () => menuItemHandler('speedLimit'),
|
||||
};
|
||||
const TurnoutOperateMenu = ContextMenu.init({
|
||||
name: 'Turnout操作菜单',
|
||||
groups: [
|
||||
@ -127,6 +131,7 @@ const TurnoutOperateMenu = ContextMenu.init({
|
||||
ipSingleSwitchStusTsrBmReverse,
|
||||
ipSingleSwitchStusBlocked2,
|
||||
ipSingleSwitchStusLostIndication,
|
||||
speedLimit,
|
||||
],
|
||||
},
|
||||
],
|
||||
@ -134,14 +139,14 @@ const TurnoutOperateMenu = ContextMenu.init({
|
||||
|
||||
export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
|
||||
static Name = 'turnout_operate_menu';
|
||||
constructor(app: GraphicApp) {
|
||||
constructor(app: IGraphicApp) {
|
||||
super(TurnoutOperationPlugin.Name, app);
|
||||
app.registerMenu(TurnoutOperateMenu);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Turnout[] | undefined {
|
||||
return grahpics.filter((g): g is Turnout => g instanceof Turnout);
|
||||
}
|
||||
static init(app: GraphicApp) {
|
||||
static init(app: IGraphicApp) {
|
||||
return new TurnoutOperationPlugin(app);
|
||||
}
|
||||
bind(g: Turnout): void {
|
||||
@ -153,6 +158,7 @@ export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
|
||||
sectionGraphic.cursor = 'pointer';
|
||||
sectionGraphic.hitArea = new TurnoutSectionHitArea(sectionGraphic);
|
||||
});
|
||||
g.on('_leftclick', this.onLeftClick, this);
|
||||
g.on('rightclick', this.onContextMenu, this);
|
||||
}
|
||||
unbind(g: Turnout): void {
|
||||
@ -160,8 +166,14 @@ export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
|
||||
g.graphics.sections.forEach((sectionGraphic) => {
|
||||
sectionGraphic.eventMode = 'none';
|
||||
});
|
||||
g.off('_leftclick', this.onLeftClick, this);
|
||||
g.on('rightclick', this.onContextMenu, this);
|
||||
}
|
||||
onLeftClick(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const section = target.getGraphic() as Turnout;
|
||||
this.app.updateSelected(section);
|
||||
}
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const turnout = target.getGraphic() as Turnout;
|
||||
@ -193,6 +205,7 @@ export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
|
||||
ipSingleSwitchStusBlocked2: turnout.states.ipSingleSwitchStusBlocked2, // 道岔封锁
|
||||
ipSingleSwitchStusLostIndication:
|
||||
turnout.states.ipSingleSwitchStusLostIndication, // 道岔失表示
|
||||
speedLimit: turnout.states.speedLimit,
|
||||
};
|
||||
(Object.keys(state) as unknown as (keyof ITurnoutState)[]).forEach(
|
||||
(key: keyof ITurnoutState) => {
|
||||
@ -220,10 +233,17 @@ export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
|
||||
menuItemHandler = (propName) => {
|
||||
const lineId = useLineStore().lineId?.toString();
|
||||
if (!lineId) return;
|
||||
let val: boolean | number;
|
||||
if (propName !== 'speedLimit') {
|
||||
val = !turnout.states[propName];
|
||||
} else {
|
||||
val = turnout.states[propName] > 0 ? 0 : 20;
|
||||
successNotify(`限速设为${val}`);
|
||||
}
|
||||
setSwitchStatus(lineId, {
|
||||
...state,
|
||||
id: turnout.datas.code,
|
||||
[propName]: !turnout.states[propName],
|
||||
[propName]: val,
|
||||
});
|
||||
};
|
||||
TurnoutOperateMenu.open(e.global);
|
||||
@ -301,13 +321,24 @@ export class TurnoutData extends GraphicDataBase implements ITurnoutData {
|
||||
this.data.pcRef = ref;
|
||||
}
|
||||
get kilometerSystem(): KilometerSystem[] {
|
||||
return this.data.kilometerSystem;
|
||||
return this.data.kilometerSystem.length > 0
|
||||
? this.data.kilometerSystem
|
||||
: (this.data.kilometerSystem = [
|
||||
new graphicData.KilometerSystem(),
|
||||
new graphicData.KilometerSystem(),
|
||||
]);
|
||||
}
|
||||
set kilometerSystem(value: KilometerSystem[]) {
|
||||
this.data.kilometerSystem = value.map(
|
||||
(v) => new graphicData.KilometerSystem(v)
|
||||
);
|
||||
}
|
||||
get centralizedStation(): number {
|
||||
return this.data.centralizedStationId;
|
||||
}
|
||||
set centralizedStation(v: number) {
|
||||
this.data.centralizedStationId = v;
|
||||
}
|
||||
clone(): TurnoutData {
|
||||
return new TurnoutData(this.data.cloneMessage());
|
||||
}
|
||||
@ -446,8 +477,25 @@ export class TurnoutStates extends GraphicStateBase implements ITurnoutState {
|
||||
public set ipSingleSwitchStusLostIndication(value: boolean) {
|
||||
this.states.ipSingleSwitchStusLostIndication = value;
|
||||
}
|
||||
id?: string;
|
||||
speedLimit?: number;
|
||||
public get id(): string {
|
||||
return this.states.id;
|
||||
}
|
||||
public set id(value: string) {
|
||||
this.states.id = value;
|
||||
}
|
||||
// 集中站站号
|
||||
public get rtuId(): number {
|
||||
return this.states.rtuId;
|
||||
}
|
||||
public set rtuId(value: number) {
|
||||
this.states.rtuId = value;
|
||||
}
|
||||
get speedLimit(): number {
|
||||
return this.states.speedLimit;
|
||||
}
|
||||
set speedLimit(val: number) {
|
||||
this.states.speedLimit = val;
|
||||
}
|
||||
get states(): state.Switch {
|
||||
return this.getState<state.Switch>();
|
||||
}
|
||||
|
@ -7,13 +7,14 @@ import { Signal, SignalTemplate } from 'src/graphics/signal/Signal';
|
||||
import { SignalDraw } from 'src/graphics/signal/SignalDrawAssistant';
|
||||
import {
|
||||
CombinationKey,
|
||||
GraphicApp,
|
||||
GraphicData,
|
||||
JlDrawApp,
|
||||
IDrawApp,
|
||||
KeyListener,
|
||||
} from 'src/jl-graphic';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
newDrawApp,
|
||||
IGraphicStorage,
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
} from 'jl-graphic';
|
||||
import { IscsFanData } from './graphics/IscsFanInteraction';
|
||||
import { LinkData } from './graphics/LinkInteraction';
|
||||
import { TrainData, TrainState } from './graphics/TrainInteraction';
|
||||
@ -23,6 +24,12 @@ import {
|
||||
SignalState,
|
||||
} from './graphics/SignalInteraction';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import {
|
||||
ConcentrationDividingLine,
|
||||
ConcentrationDividingLineTemplate,
|
||||
} from 'src/graphics/concentrationDividingLine/ConcentrationDividingLine';
|
||||
import { ConcentrationDividingLineData } from './graphics/ConcentrationDividingLineInteraction';
|
||||
import { ConcentrationDividingLineDraw } from 'src/graphics/concentrationDividingLine/ConcentrationDividingLineDrawAssistant';
|
||||
import { Rect, RectTemplate } from 'src/graphics/rect/Rect';
|
||||
import { RectDraw } from 'src/graphics/rect/RectDrawAssistant';
|
||||
import { RectData } from './graphics/RectInteraction';
|
||||
@ -120,7 +127,7 @@ import { FederatedMouseEvent } from 'pixi.js';
|
||||
// });
|
||||
// }
|
||||
|
||||
function constructMenu(app: JlDrawApp): (e: FederatedMouseEvent) => void {
|
||||
function constructMenu(app: IDrawApp): (e: FederatedMouseEvent) => void {
|
||||
const UndoOptions: MenuItemOptions = {
|
||||
name: '撤销',
|
||||
};
|
||||
@ -203,9 +210,9 @@ function constructMenu(app: JlDrawApp): (e: FederatedMouseEvent) => void {
|
||||
};
|
||||
return handleRightClick;
|
||||
}
|
||||
let drawApp: JlDrawApp | null = null;
|
||||
let drawApp: IDrawApp | null = null;
|
||||
|
||||
export function getDrawApp(): JlDrawApp | null {
|
||||
export function getDrawApp(): IDrawApp | null {
|
||||
return drawApp;
|
||||
}
|
||||
|
||||
@ -216,35 +223,18 @@ export function destroyDrawApp(): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function initDrawApp(dom: HTMLElement): JlDrawApp {
|
||||
drawApp = new JlDrawApp(dom);
|
||||
export function initDrawApp(): IDrawApp {
|
||||
drawApp = newDrawApp({
|
||||
dataLoader: loadDrawDatas,
|
||||
});
|
||||
const app = drawApp;
|
||||
//根据草稿图类型加载绘图工具
|
||||
let drawAssistants: (
|
||||
| PlatformDraw
|
||||
| StationDraw
|
||||
| SignalDraw
|
||||
| TurnoutDraw
|
||||
| RunLineDraw
|
||||
| SectionDraw
|
||||
| LogicSectionDraw
|
||||
| StationLineDraw
|
||||
| RectDraw
|
||||
| TrainLineDraw
|
||||
| PathLineDraw
|
||||
| TrainWindowDraw
|
||||
| TrainDraw
|
||||
| OneClickGenerateDraw
|
||||
| AxleCountingDraw
|
||||
| SeparatorDraw
|
||||
)[] = [];
|
||||
const draftType = useDrawStore().$state.draftType;
|
||||
if (draftType === 'Line') {
|
||||
drawAssistants = [
|
||||
new PlatformDraw(
|
||||
app,
|
||||
new PlatformTemplate(new PlatformData(), new PlatformState())
|
||||
),
|
||||
new PlatformDraw(
|
||||
app,
|
||||
new PlatformTemplate(new PlatformData(), new PlatformState())
|
||||
),
|
||||
new StationDraw(
|
||||
app,
|
||||
new StationTemplate(new StationData(), new StationState())
|
||||
@ -273,11 +263,15 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
|
||||
new AxleCountingTemplate(new AxleCountingData())
|
||||
),
|
||||
new SeparatorDraw(app, new SeparatorTemplate(new SeparatorData())),
|
||||
];
|
||||
new ConcentrationDividingLineDraw(
|
||||
app,
|
||||
new ConcentrationDividingLineTemplate(
|
||||
new ConcentrationDividingLineData()
|
||||
)
|
||||
);
|
||||
DrawSignalInteraction.init(app);
|
||||
} else {
|
||||
drawAssistants = [
|
||||
new StationLineDraw(app, new StationLineTemplate(new StationLineData())),
|
||||
new StationLineDraw(app, new StationLineTemplate(new StationLineData())),
|
||||
new RectDraw(app, new RectTemplate(new RectData())),
|
||||
new RunLineDraw(app, new RunLineTemplate(new RunLineData())),
|
||||
new TrainLineDraw(
|
||||
@ -285,14 +279,11 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
|
||||
new ItrainLineTemplate(new TrainLineData(), new TrainLineState())
|
||||
),
|
||||
new PathLineDraw(app, new PathLineTemplate(new PathLineData())),
|
||||
];
|
||||
DrawRunLinePlugin.init(app);
|
||||
DrawRunLinePlugin.init(app);
|
||||
}
|
||||
|
||||
app.setOptions({ drawAssistants: drawAssistants });
|
||||
const handleRIghtClick = constructMenu(app);
|
||||
app.canvas.on('_rightclick', (e) => {
|
||||
if (app._drawing) return;
|
||||
if (app.drawing) return;
|
||||
handleRIghtClick(e);
|
||||
});
|
||||
app.addKeyboardListener(
|
||||
@ -308,7 +299,7 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
|
||||
return drawApp;
|
||||
}
|
||||
|
||||
export function saveDrawToServer(app: JlDrawApp) {
|
||||
export function saveDrawToServer(app: IDrawApp) {
|
||||
const base64 = saveDrawDatas(app);
|
||||
const drawStore = useDrawStore();
|
||||
const id = drawStore.draftId;
|
||||
@ -325,7 +316,7 @@ export function saveDrawToServer(app: JlDrawApp) {
|
||||
}
|
||||
|
||||
// const StorageKey = 'graphic-storage';
|
||||
export function saveDrawDatas(app: JlDrawApp) {
|
||||
export function saveDrawDatas(app: IDrawApp) {
|
||||
const storage = new graphicData.RtssGraphicStorage();
|
||||
const canvasData = app.canvas.saveData();
|
||||
storage.canvas = new graphicData.Canvas({
|
||||
@ -385,22 +376,105 @@ export function saveDrawDatas(app: JlDrawApp) {
|
||||
} else if (LogicSection.Type === g.type) {
|
||||
const logicSectionData = (g as LogicSection).saveData();
|
||||
storage.logicSections.push((logicSectionData as LogicSectionData).data);
|
||||
} else if (g instanceof ConcentrationDividingLine) {
|
||||
const concentrationDividingLineData = g.saveData();
|
||||
storage.concentrationDividingLines.push(
|
||||
(concentrationDividingLineData as ConcentrationDividingLineData).data
|
||||
);
|
||||
}
|
||||
});
|
||||
// storage.Platforms.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// item.nrefStation = +item.refStation;
|
||||
// item.nrefSectionId = +item.refSectionId;
|
||||
// });
|
||||
// storage.axleCountings.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// item.axleCountingRef = item.axleCountingRef.map((child) => {
|
||||
// child.nid = +child.id;
|
||||
// return child;
|
||||
// });
|
||||
// });
|
||||
// storage.iscsFans.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.links.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.logicSections.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.pathLines.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.polygons.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.rects.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.runLines.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// item.nlinkPathLines = item.linkPathLines.map((child) => +child);
|
||||
// });
|
||||
// storage.section.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// if (item.paRef) {
|
||||
// item.paRef.nid = +item.paRef.id;
|
||||
// }
|
||||
// if (item.pbRef) {
|
||||
// item.pbRef.nid = +item.pbRef.id;
|
||||
// }
|
||||
// item.nchildren = item.children.map((child) => +child);
|
||||
// });
|
||||
// storage.separators.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.signals.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.stationLines.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.stations.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.train.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.trainLines.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// });
|
||||
// storage.trainWindows.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// item.nrefDeviceId = item.refDeviceId.map((child) => +child);
|
||||
// });
|
||||
// storage.turnouts.forEach((item) => {
|
||||
// item.common.nid = +item.common.id;
|
||||
// if (item.paRef) {
|
||||
// item.paRef.nid = +item.paRef.id;
|
||||
// }
|
||||
// if (item.pbRef) {
|
||||
// item.pbRef.nid = +item.pbRef.id;
|
||||
// }
|
||||
// if (item.pcRef) {
|
||||
// item.pcRef.nid = +item.pcRef.id;
|
||||
// }
|
||||
// });
|
||||
const base64 = fromUint8Array(storage.serialize());
|
||||
console.log('保存数据', storage);
|
||||
// localStorage.setItem(StorageKey, base64);
|
||||
return base64;
|
||||
}
|
||||
|
||||
export async function loadDrawDatas(app: GraphicApp) {
|
||||
export async function loadDrawDatas(): Promise<IGraphicStorage> {
|
||||
// localStorage.removeItem(StorageKey);
|
||||
// const base64 = localStorage.getItem(StorageKey);
|
||||
// console.log('加载数据', base64);
|
||||
const drawStore = useDrawStore();
|
||||
const id = drawStore.draftId;
|
||||
if (!id) {
|
||||
return;
|
||||
throw new Error('获取数据异常:未获取到草稿地图ID');
|
||||
}
|
||||
const { proto: base64 } = await getDraft(id);
|
||||
if (base64) {
|
||||
@ -408,7 +482,6 @@ export async function loadDrawDatas(app: GraphicApp) {
|
||||
toUint8Array(base64)
|
||||
);
|
||||
console.log('加载数据', storage);
|
||||
app.updateCanvas(storage.canvas);
|
||||
const datas: GraphicData[] = [];
|
||||
storage.links.forEach((link) => {
|
||||
datas.push(new LinkData(link));
|
||||
@ -461,8 +534,15 @@ export async function loadDrawDatas(app: GraphicApp) {
|
||||
storage.trainWindows.forEach((trainWindow) => {
|
||||
datas.push(new TrainWindowData(trainWindow));
|
||||
});
|
||||
app.loadGraphic(datas);
|
||||
} else {
|
||||
app.loadGraphic([]);
|
||||
storage.concentrationDividingLines.forEach((concentrationDividingLine) => {
|
||||
datas.push(new ConcentrationDividingLineData(concentrationDividingLine));
|
||||
});
|
||||
return Promise.resolve({
|
||||
canvasProperty: storage.canvas,
|
||||
datas: datas,
|
||||
});
|
||||
}
|
||||
return Promise.resolve({
|
||||
datas: [],
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,11 @@
|
||||
import { GraphicApp, GraphicData, GraphicState } from 'src/jl-graphic';
|
||||
import {
|
||||
ClientEngine,
|
||||
GraphicData,
|
||||
GraphicState,
|
||||
IGraphicApp,
|
||||
IGraphicStorage,
|
||||
newGraphicApp,
|
||||
} from 'jl-graphic';
|
||||
import {
|
||||
TrainData,
|
||||
TrainOperateInteraction,
|
||||
@ -29,7 +36,10 @@ import {
|
||||
TurnoutStates,
|
||||
} from './graphics/TurnoutInteraction';
|
||||
import { Turnout, TurnoutTemplate } from 'src/graphics/turnout/Turnout';
|
||||
import { SectionData } from './graphics/SectionInteraction';
|
||||
import {
|
||||
SectionData,
|
||||
sectionOperationPlugin,
|
||||
} from './graphics/SectionInteraction';
|
||||
import { SectionTemplate } from 'src/graphics/section/Section';
|
||||
import { getPublishMapInfoByLineId } from 'src/api/PublishApi';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
@ -50,11 +60,7 @@ import {
|
||||
import { TrainWindowData } from './graphics/TrainWindowInteraction';
|
||||
import { SeparatorTemplate } from 'src/graphics/separator/Separator';
|
||||
import { SeparatorData } from './graphics/SeparatorInteraction';
|
||||
|
||||
let lineApp: GraphicApp | null = null;
|
||||
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
|
||||
import { ContextMenu, MenuItemOptions } from 'jl-graphic';
|
||||
import {
|
||||
LogicSection,
|
||||
LogicSectionTemplate,
|
||||
@ -64,21 +70,13 @@ import {
|
||||
LogicSectionOperationPlugin,
|
||||
LogicSectionState,
|
||||
} from './graphics/LogicSectionInteraction';
|
||||
import { alert } from 'src/protos/alertInfo';
|
||||
import { Notify, QNotifyUpdateOptions } from 'quasar';
|
||||
import { useLineNetStore } from 'src/stores/line-net-store';
|
||||
import { QNotifyUpdateOptions, Notify } from 'quasar';
|
||||
import { alert } from 'src/protos/alertInfo';
|
||||
|
||||
// const QuickJumpMenu = new ContextMenu({
|
||||
// name: '快捷跳转',
|
||||
// groups: [
|
||||
// {
|
||||
// items: [],
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// let QuickJumpMenu: ContextMenu = new ContextMenu();
|
||||
let lineApp: IGraphicApp | null = null;
|
||||
|
||||
export function getLineApp(): GraphicApp | null {
|
||||
export function getLineApp() {
|
||||
return lineApp;
|
||||
}
|
||||
|
||||
@ -89,8 +87,27 @@ export function destroyLineApp(): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function initLineApp(dom: HTMLElement): GraphicApp {
|
||||
lineApp = new GraphicApp(dom);
|
||||
export function initLineApp(): IGraphicApp {
|
||||
if (lineApp) return lineApp;
|
||||
|
||||
lineApp = newGraphicApp({
|
||||
interactiveGraphicTypeIncludes: [
|
||||
Signal.Type,
|
||||
Platform.Type,
|
||||
Station.Type,
|
||||
Train.Type,
|
||||
LogicSection.Type,
|
||||
Turnout.Type,
|
||||
],
|
||||
mouseToolOptions: {
|
||||
boxSelect: false,
|
||||
viewportDrag: true,
|
||||
viewportDragLeft: true,
|
||||
wheelZoom: true,
|
||||
},
|
||||
dataLoader: loadLineDatas,
|
||||
});
|
||||
|
||||
const graphicTemplate = [
|
||||
new TrainTemplate(new TrainData(), new TrainState()),
|
||||
new SignalTemplate(new SignalData(), new SignalState()),
|
||||
@ -104,67 +121,100 @@ export function initLineApp(dom: HTMLElement): GraphicApp {
|
||||
new TrainWindowTemplate(new TrainWindowData()),
|
||||
];
|
||||
lineApp.registerGraphicTemplates(...graphicTemplate);
|
||||
lineApp.setOptions({
|
||||
mouseToolOptions: {
|
||||
boxSelect: false,
|
||||
viewportDrag: true,
|
||||
wheelZoom: true,
|
||||
},
|
||||
interactiveTypeOptions: {
|
||||
interactiveGraphicTypeIncludes: [
|
||||
Signal.Type,
|
||||
Platform.Type,
|
||||
Station.Type,
|
||||
Train.Type,
|
||||
LogicSection.Type,
|
||||
Turnout.Type,
|
||||
],
|
||||
},
|
||||
});
|
||||
SignalOperateInteraction.init(lineApp);
|
||||
PlatformOperateInteraction.init(lineApp);
|
||||
StationOperateInteraction.init(lineApp);
|
||||
TrainOperateInteraction.init(lineApp);
|
||||
TurnoutOperationPlugin.init(lineApp);
|
||||
LogicSectionOperationPlugin.init(lineApp);
|
||||
sectionOperationPlugin.init(lineApp);
|
||||
|
||||
lineApp.enableWsMassaging({
|
||||
engine: ClientEngine.Stomp,
|
||||
wsUrl: getWebsocketUrl(),
|
||||
token: getJwtToken() as string,
|
||||
});
|
||||
|
||||
let msgNotify: null | ((props?: QNotifyUpdateOptions | undefined) => void) =
|
||||
null;
|
||||
lineApp.on('websocket-connect-state-change', (connected) => {
|
||||
if (!connected && !msgNotify) {
|
||||
msgNotify = Notify.create({
|
||||
type: 'negative',
|
||||
timeout: 0,
|
||||
position: 'top-right',
|
||||
message: '与WebSocket服务连接断开!',
|
||||
classes: 'my-notif-class',
|
||||
});
|
||||
} else if (msgNotify && connected) {
|
||||
msgNotify();
|
||||
msgNotify = null;
|
||||
}
|
||||
});
|
||||
|
||||
lineApp.reload().then(() => {
|
||||
if (!lineApp) return;
|
||||
const quickJumpMenu = new ContextMenu({
|
||||
name: '快捷跳转',
|
||||
groups: [
|
||||
{
|
||||
items: lineApp.queryStore
|
||||
.queryByType<Station>(Station.Type)
|
||||
.map<MenuItemOptions>((station) => ({
|
||||
name: station.datas.name ?? '',
|
||||
handler: () => {
|
||||
lineApp?.makeGraphicCenterShow(station);
|
||||
},
|
||||
})),
|
||||
},
|
||||
],
|
||||
});
|
||||
lineApp.registerMenu(quickJumpMenu);
|
||||
lineApp.canvas.on('_rightclick', (e) => {
|
||||
quickJumpMenu.open(e.global);
|
||||
});
|
||||
|
||||
const axleCountings = lineApp.queryStore.queryByType<AxleCounting>(
|
||||
AxleCounting.Type
|
||||
);
|
||||
axleCountings.forEach((axleCounting) => {
|
||||
axleCounting.visible = false;
|
||||
});
|
||||
const trainWindows = lineApp.queryStore.queryByType<TrainWindow>(
|
||||
TrainWindow.Type
|
||||
);
|
||||
trainWindows.forEach((trainWindow) => {
|
||||
trainWindow.visible = false;
|
||||
});
|
||||
handleSubscribe(lineApp);
|
||||
});
|
||||
|
||||
return lineApp;
|
||||
}
|
||||
|
||||
export async function loadLineDatas(app: GraphicApp) {
|
||||
export async function loadLineDatas(): Promise<IGraphicStorage> {
|
||||
const lineStore = useLineStore();
|
||||
const lineId = lineStore.lineId;
|
||||
if (!lineId) {
|
||||
return;
|
||||
throw Error('请先选择线路');
|
||||
}
|
||||
const { proto: base64, name: lineName } = await getPublishMapInfoByLineId(
|
||||
lineId,
|
||||
'line'
|
||||
);
|
||||
lineStore.setLineName(lineName);
|
||||
const datas: GraphicData[] = [];
|
||||
if (base64) {
|
||||
const storage = graphicData.RtssGraphicStorage.deserialize(
|
||||
toUint8Array(base64)
|
||||
);
|
||||
console.log('加载数据', storage);
|
||||
app.updateCanvas(storage.canvas);
|
||||
const datas: GraphicData[] = [];
|
||||
storage.Platforms.forEach((platform) => {
|
||||
const g = new PlatformData(platform);
|
||||
datas.push(g);
|
||||
});
|
||||
const quickJumpMenuItem: MenuItemOptions[] = [];
|
||||
storage.stations.forEach((station) => {
|
||||
datas.push(new StationData(station));
|
||||
const item: MenuItemOptions = {
|
||||
name: station.name,
|
||||
handler: () => {
|
||||
const g = app.queryStore.queryById(station.common.id);
|
||||
if (g) {
|
||||
app.makeGraphicCenterShow(g);
|
||||
}
|
||||
},
|
||||
};
|
||||
quickJumpMenuItem.push(item);
|
||||
});
|
||||
storage.train.forEach((train) => {
|
||||
datas.push(new TrainData(train));
|
||||
@ -190,96 +240,75 @@ export async function loadLineDatas(app: GraphicApp) {
|
||||
storage.trainWindows.forEach((trainWindow) => {
|
||||
datas.push(new TrainWindowData(trainWindow));
|
||||
});
|
||||
await app.loadGraphic(datas);
|
||||
|
||||
//隐藏计轴--和车次窗
|
||||
const axleCountings = app.queryStore.queryByType<AxleCounting>(
|
||||
AxleCounting.Type
|
||||
);
|
||||
axleCountings.forEach((axleCounting) => {
|
||||
axleCounting.visible = false;
|
||||
});
|
||||
const trainWindows = app.queryStore.queryByType<TrainWindow>(
|
||||
TrainWindow.Type
|
||||
);
|
||||
trainWindows.forEach((trainWindow) => {
|
||||
trainWindow.visible = false;
|
||||
});
|
||||
const QuickJumpMenu = new ContextMenu({
|
||||
name: '快捷跳转',
|
||||
groups: [
|
||||
{
|
||||
items: quickJumpMenuItem,
|
||||
},
|
||||
],
|
||||
});
|
||||
app.registerMenu(QuickJumpMenu);
|
||||
app.canvas.on('_rightclick', (e) => {
|
||||
QuickJumpMenu.open(e.global);
|
||||
});
|
||||
|
||||
app.enableWsMassaging({
|
||||
wsUrl: `${getWebsocketUrl()}`,
|
||||
token: getJwtToken() as string,
|
||||
});
|
||||
app.subscribe({
|
||||
destination: `/queue/line/${lineId}/device`,
|
||||
messageConverter: (message: Uint8Array) => {
|
||||
const states: GraphicState[] = [];
|
||||
const storage = state.WsLineMessage.deserialize(message);
|
||||
storage.signal.forEach((item) => {
|
||||
states.push(new SignalState(item));
|
||||
});
|
||||
storage.platform.forEach((item) => {
|
||||
states.push(new PlatformState(item));
|
||||
});
|
||||
storage.rtu.forEach((item) => {
|
||||
states.push(new StationState(item));
|
||||
});
|
||||
storage.switch.forEach((item) => {
|
||||
states.push(new TurnoutStates(item));
|
||||
});
|
||||
storage.track.forEach((item) => {
|
||||
states.push(new LogicSectionState(item));
|
||||
});
|
||||
return states;
|
||||
},
|
||||
});
|
||||
app.subscribe({
|
||||
destination: `/queue/line/${lineId}/train`,
|
||||
messageConverter: (message: Uint8Array) => {
|
||||
const states: GraphicState[] = [];
|
||||
const trainStorage = state.WsLineTrainMessage.deserialize(message);
|
||||
trainStorage.trainInfo.forEach((item) => {
|
||||
states.push(new TrainState(item));
|
||||
});
|
||||
return states;
|
||||
},
|
||||
});
|
||||
let msgNotify: null | ((props?: QNotifyUpdateOptions | undefined) => void) =
|
||||
null;
|
||||
app.on('websocket-connect-state-change', (connected) => {
|
||||
if (!connected && !msgNotify) {
|
||||
msgNotify = Notify.create({
|
||||
type: 'negative',
|
||||
timeout: 0,
|
||||
position: 'top-right',
|
||||
message: '通信链接已断开!',
|
||||
});
|
||||
} else if (msgNotify && connected) {
|
||||
msgNotify();
|
||||
msgNotify = null;
|
||||
}
|
||||
});
|
||||
const lineNetStore = useLineNetStore();
|
||||
app.subscribe({
|
||||
destination: '/queue/xian/ncc/alert',
|
||||
messageHandle: (message: Uint8Array) => {
|
||||
const storage = alert.NccAlertInfoMessage.deserialize(message);
|
||||
lineNetStore.setAlarmInfo(storage.messages as []);
|
||||
},
|
||||
return Promise.resolve({
|
||||
canvasProperty: storage.canvas,
|
||||
datas: datas,
|
||||
});
|
||||
} else {
|
||||
app.loadGraphic([]);
|
||||
return Promise.resolve({
|
||||
datas: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleSubscribe(lineApp: IGraphicApp) {
|
||||
const lineStore = useLineStore();
|
||||
const lineId = lineStore.lineId;
|
||||
lineApp.subscribe({
|
||||
destination: `/queue/line/${lineId}/device`,
|
||||
messageConverter: (message: Uint8Array) => {
|
||||
const states: GraphicState[] = [];
|
||||
const storage = state.WsLineMessage.deserialize(message);
|
||||
storage.signal.forEach((item) => {
|
||||
if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) {
|
||||
states.push(new SignalState(item));
|
||||
}
|
||||
});
|
||||
storage.platform.forEach((item) => {
|
||||
if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) {
|
||||
states.push(new PlatformState(item));
|
||||
}
|
||||
});
|
||||
storage.rtu.forEach((item) => {
|
||||
if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) {
|
||||
states.push(new StationState(item));
|
||||
}
|
||||
});
|
||||
storage.switch.forEach((item) => {
|
||||
if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) {
|
||||
states.push(new TurnoutStates(item));
|
||||
}
|
||||
});
|
||||
storage.track.forEach((item) => {
|
||||
if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) {
|
||||
states.push(new LogicSectionState(item));
|
||||
}
|
||||
});
|
||||
return states;
|
||||
},
|
||||
});
|
||||
lineApp.subscribe({
|
||||
destination: `/queue/line/${lineId}/train`,
|
||||
createOnNotFound: { graphicTypes: [Train.Type] },
|
||||
messageConverter: (message: Uint8Array) => {
|
||||
const states: GraphicState[] = [];
|
||||
const trainStorage = state.WsLineTrainMessage.deserialize(message);
|
||||
// console.log(trainStorage, '222');
|
||||
trainStorage.trainInfo.forEach((item) => {
|
||||
// if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) {
|
||||
if (item.rtuId) {
|
||||
states.push(new TrainState(item));
|
||||
}
|
||||
});
|
||||
return states;
|
||||
},
|
||||
});
|
||||
const lineNetStore = useLineNetStore();
|
||||
lineApp.subscribe({
|
||||
destination: '/queue/xian/ncc/alert',
|
||||
messageHandle: (message: Uint8Array) => {
|
||||
const storage = alert.NccAlertInfoMessage.deserialize(message);
|
||||
lineNetStore.setAlarmInfo(storage.messages as []);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,10 @@
|
||||
import { GraphicApp, GraphicData, GraphicState } from 'src/jl-graphic';
|
||||
import {
|
||||
IGraphicApp,
|
||||
GraphicData,
|
||||
GraphicState,
|
||||
newGraphicApp,
|
||||
IGraphicStorage,
|
||||
} from 'jl-graphic';
|
||||
import { getPublishLineNet } from 'src/api/PublishApi';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { state } from 'src/protos/ws_message';
|
||||
@ -28,11 +34,11 @@ import { toUint8Array } from 'js-base64';
|
||||
import { getWebsocketUrl } from 'src/configs/UrlManage';
|
||||
import { getJwtToken } from 'src/configs/TokenManage';
|
||||
import { alert } from 'src/protos/alertInfo';
|
||||
import { QNotifyUpdateOptions, Notify } from 'quasar';
|
||||
import { Notify } from 'quasar';
|
||||
|
||||
let lineNetApp: GraphicApp | null = null;
|
||||
let lineNetApp: IGraphicApp | null = null;
|
||||
|
||||
export function getLineNetApp(): GraphicApp | null {
|
||||
export function getLineNetApp(): IGraphicApp | null {
|
||||
return lineNetApp;
|
||||
}
|
||||
|
||||
@ -43,8 +49,21 @@ export function destroyLineNetApp(): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function initLineNetApp(dom: HTMLElement): GraphicApp {
|
||||
lineNetApp = new GraphicApp(dom);
|
||||
export function initLineNetApp(): IGraphicApp {
|
||||
lineNetApp = newGraphicApp({
|
||||
interactiveGraphicTypeIncludes: [
|
||||
RunLine.Type,
|
||||
StationLine.Type,
|
||||
TrainLine.Type,
|
||||
],
|
||||
mouseToolOptions: {
|
||||
boxSelect: false,
|
||||
viewportDrag: true,
|
||||
viewportDragLeft: true,
|
||||
wheelZoom: true,
|
||||
},
|
||||
dataLoader: loadLineNetDatas,
|
||||
});
|
||||
const graphicTemplate = [
|
||||
new RunLineTemplate(new RunLineData()),
|
||||
new PathLineTemplate(new PathLineData()),
|
||||
@ -52,36 +71,47 @@ export function initLineNetApp(dom: HTMLElement): GraphicApp {
|
||||
new ItrainLineTemplate(new TrainLineData(), new TrainLineState()),
|
||||
new RectTemplate(new RectData()),
|
||||
];
|
||||
lineNetApp.registerGraphicTemplates(...graphicTemplate);
|
||||
lineNetApp.setOptions({
|
||||
mouseToolOptions: {
|
||||
boxSelect: false,
|
||||
viewportDrag: true,
|
||||
wheelZoom: true,
|
||||
},
|
||||
interactiveTypeOptions: {
|
||||
interactiveGraphicTypeIncludes: [
|
||||
RunLine.Type,
|
||||
StationLine.Type,
|
||||
TrainLine.Type,
|
||||
],
|
||||
},
|
||||
lineNetApp.reload().then(() => {
|
||||
if (!lineNetApp) return;
|
||||
const pathLineList = lineNetApp.queryStore.queryByType(PathLine.Type);
|
||||
pathLineList.forEach((pathLine) => {
|
||||
pathLine.visible = false;
|
||||
});
|
||||
handleSubscribe(lineNetApp);
|
||||
});
|
||||
|
||||
lineNetApp.registerGraphicTemplates(...graphicTemplate);
|
||||
|
||||
RunLineOperateInteraction.init(lineNetApp);
|
||||
|
||||
let msgNotify: ReturnType<Notify['create']> | null = null;
|
||||
lineNetApp.on('websocket-connect-state-change', (connected) => {
|
||||
if (!connected && !msgNotify) {
|
||||
msgNotify = Notify.create({
|
||||
type: 'negative',
|
||||
timeout: 0,
|
||||
position: 'top-right',
|
||||
message: '与WebSocket服务连接断开!',
|
||||
classes: 'my-notif-class',
|
||||
});
|
||||
} else if (msgNotify && connected) {
|
||||
msgNotify();
|
||||
msgNotify = null;
|
||||
}
|
||||
});
|
||||
return lineNetApp;
|
||||
}
|
||||
|
||||
export async function loadLineNetDatas(app: GraphicApp) {
|
||||
export async function loadLineNetDatas(): Promise<IGraphicStorage> {
|
||||
const lineNetStore = useLineNetStore();
|
||||
const { proto: base64, name: lineNetName } = await getPublishLineNet();
|
||||
lineNetStore.setLineNetName(lineNetName);
|
||||
const datas: GraphicData[] = [];
|
||||
if (base64) {
|
||||
const storage = graphicData.RtssGraphicStorage.deserialize(
|
||||
toUint8Array(base64)
|
||||
);
|
||||
console.log('加载数据', storage);
|
||||
app.updateCanvas(storage.canvas);
|
||||
const datas: GraphicData[] = [];
|
||||
storage.runLines.forEach((runLine) => {
|
||||
const g = new RunLineData(runLine);
|
||||
datas.push(g);
|
||||
@ -102,49 +132,40 @@ export async function loadLineNetDatas(app: GraphicApp) {
|
||||
const g = new RectData(rect);
|
||||
datas.push(g);
|
||||
});
|
||||
await app.loadGraphic(datas);
|
||||
const pathLineList = app.queryStore.queryByType(PathLine.Type);
|
||||
pathLineList.forEach((pathLine) => {
|
||||
pathLine.visible = false;
|
||||
});
|
||||
app.enableWsMassaging({
|
||||
wsUrl: `${getWebsocketUrl()}`,
|
||||
token: getJwtToken() as string,
|
||||
});
|
||||
app.subscribe({
|
||||
destination: '/queue/lineNet',
|
||||
messageConverter: (message: Uint8Array) => {
|
||||
const storage = state.WsLineNetMessage.deserialize(message);
|
||||
const states: GraphicState[] = [];
|
||||
storage.offset.forEach((item) => {
|
||||
states.push(new TrainLineState(item));
|
||||
});
|
||||
return states;
|
||||
},
|
||||
});
|
||||
app.subscribe({
|
||||
destination: '/queue/xian/ncc/alert',
|
||||
messageHandle: (message: Uint8Array) => {
|
||||
const storage = alert.NccAlertInfoMessage.deserialize(message);
|
||||
lineNetStore.setAlarmInfo(storage.messages as []);
|
||||
},
|
||||
});
|
||||
let msgNotify: null | ((props?: QNotifyUpdateOptions | undefined) => void) =
|
||||
null;
|
||||
app.on('websocket-connect-state-change', (connected) => {
|
||||
if (!connected && !msgNotify) {
|
||||
msgNotify = Notify.create({
|
||||
type: 'negative',
|
||||
timeout: 0,
|
||||
position: 'top-right',
|
||||
message: '通信链接已断开!',
|
||||
});
|
||||
} else if (msgNotify && connected) {
|
||||
msgNotify();
|
||||
msgNotify = null;
|
||||
}
|
||||
return Promise.resolve({
|
||||
canvasProperty: storage.canvas,
|
||||
datas: datas,
|
||||
});
|
||||
} else {
|
||||
app.loadGraphic([]);
|
||||
return Promise.resolve({
|
||||
datas: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleSubscribe(lineNetApp: IGraphicApp) {
|
||||
const lineNetStore = useLineNetStore();
|
||||
lineNetApp.enableWsMassaging({
|
||||
wsUrl: `${getWebsocketUrl()}`,
|
||||
token: getJwtToken() as string,
|
||||
});
|
||||
lineNetApp.subscribe({
|
||||
destination: '/queue/lineNet',
|
||||
createOnNotFound: { graphicTypes: [TrainLine.Type] },
|
||||
messageConverter: (message: Uint8Array) => {
|
||||
const storage = state.WsLineNetMessage.deserialize(message);
|
||||
const states: GraphicState[] = [];
|
||||
storage.offset.forEach((item) => {
|
||||
states.push(new TrainLineState(item));
|
||||
});
|
||||
return states;
|
||||
},
|
||||
});
|
||||
lineNetApp.subscribe({
|
||||
destination: '/queue/xian/ncc/alert',
|
||||
messageHandle: (message: Uint8Array) => {
|
||||
const storage = alert.NccAlertInfoMessage.deserialize(message);
|
||||
lineNetStore.setAlarmInfo(storage.messages as []);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
210
src/drawApp/rangeConfigApp.ts
Normal file
210
src/drawApp/rangeConfigApp.ts
Normal file
@ -0,0 +1,210 @@
|
||||
import {
|
||||
LogicSection,
|
||||
LogicSectionTemplate,
|
||||
} from 'src/graphics/logicSection/LogicSection';
|
||||
import { Platform, PlatformTemplate } from 'src/graphics/platform/Platform';
|
||||
import { SectionTemplate } from 'src/graphics/section/Section';
|
||||
import { Signal, SignalTemplate } from 'src/graphics/signal/Signal';
|
||||
import { Station, StationTemplate } from 'src/graphics/station/Station';
|
||||
import { Turnout, TurnoutTemplate } from 'src/graphics/turnout/Turnout';
|
||||
import {
|
||||
IGraphicApp,
|
||||
GraphicData,
|
||||
newGraphicApp,
|
||||
MenuItemOptions,
|
||||
ContextMenu,
|
||||
IGraphicStorage,
|
||||
} from 'jl-graphic';
|
||||
import {
|
||||
LogicSectionData,
|
||||
LogicSectionState,
|
||||
} from './graphics/LogicSectionInteraction';
|
||||
import { SeparatorTemplate } from 'src/graphics/separator/Separator';
|
||||
import { AxleCountingTemplate } from 'src/graphics/axleCounting/AxleCounting';
|
||||
import { SignalData, SignalState } from './graphics/SignalInteraction';
|
||||
import { PlatformData, PlatformState } from './graphics/PlatformInteraction';
|
||||
import { StationData, StationState } from './graphics/StationInteraction';
|
||||
import { TurnoutData, TurnoutStates } from './graphics/TurnoutInteraction';
|
||||
import { SectionData } from './graphics/SectionInteraction';
|
||||
import { SeparatorData } from './graphics/SeparatorInteraction';
|
||||
import { AxleCountingData } from './graphics/AxleCountingInteraction';
|
||||
import { getPublishMapInfoByLineId } from 'src/api/PublishApi';
|
||||
import { useRangeConfigStore } from 'src/stores/range-config-store';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { toUint8Array } from 'js-base64';
|
||||
|
||||
let rangeConfigApp: IGraphicApp;
|
||||
|
||||
export function getRangeConfigApp() {
|
||||
return rangeConfigApp;
|
||||
}
|
||||
|
||||
export function initRangeConfigApp(lineId: number) {
|
||||
rangeConfigApp = newGraphicApp({
|
||||
mouseToolOptions: {
|
||||
boxSelect: true,
|
||||
viewportDrag: true,
|
||||
wheelZoom: true,
|
||||
},
|
||||
interactiveGraphicTypeIncludes: [
|
||||
Signal.Type,
|
||||
Platform.Type,
|
||||
Station.Type,
|
||||
LogicSection.Type,
|
||||
Turnout.Type,
|
||||
],
|
||||
dataLoader: () => loadRangeConfigDatas(lineId),
|
||||
});
|
||||
const graphicTemplate = [
|
||||
new SignalTemplate(new SignalData(), new SignalState()),
|
||||
new PlatformTemplate(new PlatformData(), new PlatformState()),
|
||||
new StationTemplate(new StationData(), new StationState()),
|
||||
new TurnoutTemplate(new TurnoutData(), new TurnoutStates()),
|
||||
new SectionTemplate(new SectionData()),
|
||||
new LogicSectionTemplate(new LogicSectionData(), new LogicSectionState()),
|
||||
new SeparatorTemplate(new SeparatorData()),
|
||||
new AxleCountingTemplate(new AxleCountingData()),
|
||||
];
|
||||
rangeConfigApp.registerGraphicTemplates(...graphicTemplate);
|
||||
|
||||
rangeConfigApp.reload().then(() => {
|
||||
const QuickJumpMenu = new ContextMenu({
|
||||
name: '快捷跳转',
|
||||
groups: [
|
||||
{
|
||||
items: rangeConfigApp.queryStore
|
||||
.queryByType<Station>(Station.Type)
|
||||
.map<MenuItemOptions>((station) => ({
|
||||
name: station.datas.name ?? '',
|
||||
handler: () => {
|
||||
rangeConfigApp?.makeGraphicCenterShow(station);
|
||||
},
|
||||
})),
|
||||
},
|
||||
],
|
||||
});
|
||||
rangeConfigApp.registerMenu(QuickJumpMenu);
|
||||
rangeConfigApp.canvas.on('_rightclick', (e) => {
|
||||
QuickJumpMenu.open(e.global);
|
||||
});
|
||||
});
|
||||
|
||||
return rangeConfigApp;
|
||||
}
|
||||
|
||||
export async function loadRangeConfigDatas(
|
||||
lineId: number
|
||||
): Promise<IGraphicStorage> {
|
||||
if (!lineId) throw Error('请先选择线路');
|
||||
const store = useRangeConfigStore();
|
||||
|
||||
const { proto: base64, name: lineName } = await getPublishMapInfoByLineId(
|
||||
lineId,
|
||||
'line'
|
||||
);
|
||||
store.setLineName(lineName);
|
||||
const datas: GraphicData[] = [];
|
||||
if (base64) {
|
||||
const storage = graphicData.RtssGraphicStorage.deserialize(
|
||||
toUint8Array(base64)
|
||||
);
|
||||
console.log('加载数据', storage);
|
||||
storage.Platforms.forEach((platform) => {
|
||||
datas.push(new PlatformData(platform));
|
||||
});
|
||||
storage.stations.forEach((station) => {
|
||||
datas.push(new StationData(station));
|
||||
});
|
||||
storage.turnouts.forEach((turnout) => {
|
||||
datas.push(new TurnoutData(turnout));
|
||||
});
|
||||
storage.section.forEach((section) => {
|
||||
datas.push(new SectionData(section));
|
||||
});
|
||||
storage.logicSections.forEach((section) => {
|
||||
datas.push(new LogicSectionData(section));
|
||||
});
|
||||
storage.separators.forEach((separator) => {
|
||||
datas.push(new SeparatorData(separator));
|
||||
});
|
||||
storage.axleCountings.forEach((axleCounting) => {
|
||||
datas.push(new AxleCountingData(axleCounting));
|
||||
});
|
||||
return Promise.resolve({
|
||||
canvasProperty: storage.canvas,
|
||||
datas: datas,
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve({
|
||||
datas: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadLineDatas(app: IGraphicApp) {
|
||||
const store = useRangeConfigStore();
|
||||
const lineId = store.lineId;
|
||||
if (!lineId) return;
|
||||
|
||||
const { proto: base64, name: lineName } = await getPublishMapInfoByLineId(
|
||||
lineId,
|
||||
'line'
|
||||
);
|
||||
store.setLineName(lineName);
|
||||
if (base64) {
|
||||
const storage = graphicData.RtssGraphicStorage.deserialize(
|
||||
toUint8Array(base64)
|
||||
);
|
||||
const datas: GraphicData[] = [];
|
||||
storage.Platforms.forEach((platform) => {
|
||||
const g = new PlatformData(platform);
|
||||
datas.push(g);
|
||||
});
|
||||
const quickJumpMenuItem: MenuItemOptions[] = [];
|
||||
storage.stations.forEach((station) => {
|
||||
datas.push(new StationData(station));
|
||||
const item: MenuItemOptions = {
|
||||
name: station.name,
|
||||
handler: () => {
|
||||
const g = app.queryStore.queryById(station.common.id);
|
||||
if (g) {
|
||||
app.makeGraphicCenterShow(g);
|
||||
}
|
||||
},
|
||||
};
|
||||
quickJumpMenuItem.push(item);
|
||||
});
|
||||
storage.turnouts.forEach((turnout) => {
|
||||
datas.push(new TurnoutData(turnout));
|
||||
});
|
||||
storage.section.forEach((section) => {
|
||||
datas.push(new SectionData(section));
|
||||
});
|
||||
storage.logicSections.forEach((section) => {
|
||||
datas.push(new LogicSectionData(section));
|
||||
});
|
||||
storage.separators.forEach((separator) => {
|
||||
datas.push(new SeparatorData(separator));
|
||||
});
|
||||
storage.axleCountings.forEach((axleCounting) => {
|
||||
datas.push(new AxleCountingData(axleCounting));
|
||||
});
|
||||
const QuickJumpMenu = new ContextMenu({
|
||||
name: '快捷跳转',
|
||||
groups: [
|
||||
{
|
||||
items: quickJumpMenuItem,
|
||||
},
|
||||
],
|
||||
});
|
||||
app.registerMenu(QuickJumpMenu);
|
||||
app.canvas.on('_rightclick', (e) => {
|
||||
QuickJumpMenu.open(e.global);
|
||||
});
|
||||
}
|
||||
}
|
||||
export function destroyRangeConfigApp(): void {
|
||||
if (rangeConfigApp) {
|
||||
rangeConfigApp.destroy();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { Graphics } from 'pixi.js';
|
||||
import { calculateMirrorPoint } from 'src/jl-graphic';
|
||||
import { calculateMirrorPoint } from 'jl-graphic';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { Turnout, TurnoutPort } from './turnout/Turnout';
|
||||
import { Section, SectionPort } from './section/Section';
|
||||
@ -77,7 +77,7 @@ export function drawArrow(
|
||||
|
||||
export function createRelatedRefProto(
|
||||
type: string,
|
||||
id: string,
|
||||
id: number,
|
||||
port?: TurnoutPort | SectionPort
|
||||
) {
|
||||
const typeMap = new Map([
|
||||
@ -111,6 +111,6 @@ export function protoPort2Data(port: graphicData.RelatedRef.DevicePort) {
|
||||
|
||||
export interface IRelatedRefData {
|
||||
deviceType: graphicData.RelatedRef.DeviceType; //关联的设备类型
|
||||
id: string; //关联的设备ID
|
||||
id: number; //关联的设备ID
|
||||
devicePort: graphicData.RelatedRef.DevicePort; //关联的设备端口
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
JlGraphic,
|
||||
JlGraphicTemplate,
|
||||
VectorText,
|
||||
} from 'src/jl-graphic';
|
||||
} from 'jl-graphic';
|
||||
import { IRelatedRefData, protoPort2Data } from '../CommonGraphics';
|
||||
import { KilometerSystem } from '../signal/Signal';
|
||||
|
||||
|
@ -5,10 +5,10 @@ import {
|
||||
GraphicDrawAssistant,
|
||||
GraphicIdGenerator,
|
||||
GraphicInteractionPlugin,
|
||||
JlDrawApp,
|
||||
IDrawApp,
|
||||
JlGraphic,
|
||||
distance2,
|
||||
} from 'src/jl-graphic';
|
||||
} from 'jl-graphic';
|
||||
|
||||
import {
|
||||
IAxleCountingData,
|
||||
@ -16,7 +16,7 @@ import {
|
||||
AxleCountingTemplate,
|
||||
AxleCountingConsts,
|
||||
} from './AxleCounting';
|
||||
import { Section, SectionPort, SectionType } from '../section/Section';
|
||||
import { Section, SectionPort } from '../section/Section';
|
||||
import { Turnout, TurnoutPort } from '../turnout/Turnout';
|
||||
import { IRelatedRefData, createRelatedRefProto } from '../CommonGraphics';
|
||||
import { Signal } from '../signal/Signal';
|
||||
@ -42,8 +42,8 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
|
||||
IAxleCountingData
|
||||
> {
|
||||
codeGraph: AxleCounting;
|
||||
constructor(app: JlDrawApp, template: AxleCountingTemplate) {
|
||||
super(app, template, 'sym_o_circle', '不展示');
|
||||
constructor(app: IDrawApp, template: AxleCountingTemplate) {
|
||||
super(app, template, 'sym_o_circle', '计轴');
|
||||
this.codeGraph = this.graphicTemplate.new();
|
||||
this.container.addChild(this.codeGraph);
|
||||
AxleCountingInteraction.init(app);
|
||||
@ -198,12 +198,6 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
|
||||
if (axleCountingPs.y > height.y) {
|
||||
direction = -1;
|
||||
}
|
||||
if (
|
||||
section.datas.sectionType === SectionType.Logic ||
|
||||
section.datas.children.includes(refDevice.id)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (refDevice.type == Section.Type || refDevice.type == Turnout.Type)
|
||||
this.draw(
|
||||
axleCountingPs,
|
||||
@ -352,10 +346,10 @@ function buildAbsorbablePositions(
|
||||
|
||||
export class AxleCountingInteraction extends GraphicInteractionPlugin<AxleCounting> {
|
||||
static Name = 'AxleCounting_transform';
|
||||
constructor(app: JlDrawApp) {
|
||||
constructor(app: IDrawApp) {
|
||||
super(AxleCountingInteraction.Name, app);
|
||||
}
|
||||
static init(app: JlDrawApp) {
|
||||
static init(app: IDrawApp) {
|
||||
return new AxleCountingInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): AxleCounting[] | undefined {
|
||||
|
@ -0,0 +1,224 @@
|
||||
import { IPointData } from 'pixi.js';
|
||||
import {
|
||||
GraphicData,
|
||||
JlGraphic,
|
||||
JlGraphicTemplate,
|
||||
calculateDistanceFromPointToLine,
|
||||
getRectangleCenter,
|
||||
ILineGraphic,
|
||||
} from 'jl-graphic';
|
||||
import { SectionGraphic } from './SectionGraphic';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { Section, SectionType } from '../section/Section';
|
||||
import { arePolylinesIntersect } from './ConcentrationDividingLineUtils';
|
||||
import { createRelatedRefProto } from '../CommonGraphics';
|
||||
import { Turnout,TurnoutPort } from '../turnout/Turnout';
|
||||
|
||||
export interface IConcentrationDividingLineData extends GraphicData {
|
||||
get code(): string; // 编号
|
||||
set code(v: string);
|
||||
get points(): IPointData[]; // 线坐标点
|
||||
set points(points: IPointData[]);
|
||||
get refLeftStationId(): number; //左边关联的集中站id
|
||||
set refLeftStationId(v: number);
|
||||
get refRightStationId(): number; //右边关联的集中站id
|
||||
set refRightStationId(v: number);
|
||||
get nodeConWithSecs(): graphicData.NodeConWithSec[]; // 集中区分割线与区段的交点
|
||||
set nodeConWithSecs(nodes: graphicData.NodeConWithSec[]);
|
||||
get isOtherLineConcentrationDividingLine(): boolean; //集中区分割线绘制在其它线的边界处
|
||||
set isOtherLineConcentrationDividingLine(v: boolean);
|
||||
clone(): IConcentrationDividingLineData;
|
||||
copyFrom(data: IConcentrationDividingLineData): void;
|
||||
eq(other: IConcentrationDividingLineData): boolean;
|
||||
}
|
||||
|
||||
export const ConcentrationDividingLineConsts = {
|
||||
lineColor: '#f00',
|
||||
lineWidth: 2,
|
||||
};
|
||||
|
||||
enum devicePort {
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
}
|
||||
|
||||
export class ConcentrationDividingLine
|
||||
extends JlGraphic
|
||||
implements ILineGraphic
|
||||
{
|
||||
static Type = 'ConcentrationDividingLine';
|
||||
lineGraphic: SectionGraphic;
|
||||
|
||||
constructor() {
|
||||
super(ConcentrationDividingLine.Type);
|
||||
this.lineGraphic = new SectionGraphic();
|
||||
this.transformSave = true;
|
||||
this.addChild(this.lineGraphic);
|
||||
}
|
||||
|
||||
get datas(): IConcentrationDividingLineData {
|
||||
return this.getDatas<IConcentrationDividingLineData>();
|
||||
}
|
||||
|
||||
get linePoints(): IPointData[] {
|
||||
return this.datas.points;
|
||||
}
|
||||
set linePoints(points: IPointData[]) {
|
||||
const old = this.datas.clone();
|
||||
old.points = points;
|
||||
this.updateData(old);
|
||||
}
|
||||
|
||||
doRepaint() {
|
||||
if (this.datas.points.length < 2) {
|
||||
throw new Error('Link坐标数据异常');
|
||||
}
|
||||
this.lineGraphic.clear();
|
||||
this.lineGraphic.points = this.datas.points;
|
||||
this.lineGraphic.lineStyle(
|
||||
ConcentrationDividingLineConsts.lineWidth,
|
||||
ConcentrationDividingLineConsts.lineColor
|
||||
);
|
||||
this.lineGraphic.paint();
|
||||
}
|
||||
buildRelation() {
|
||||
const nodeConWithSecs: graphicData.NodeConWithSec[] = [];
|
||||
const sections = this.queryStore
|
||||
.queryByType<Section>(Section.Type)
|
||||
.filter((g) => g.datas.sectionType == SectionType.Physical);
|
||||
const hasNodeSection = new Map<number, string>();
|
||||
sections.forEach((section) => {
|
||||
const changeSectionData = section.datas.points.map((point) =>
|
||||
section.localToCanvasPoint(point)
|
||||
);
|
||||
const changeConcentrationDividingLineData = this.datas.points.map(
|
||||
(point) => this.localToCanvasPoint(point)
|
||||
);
|
||||
const hasNode = arePolylinesIntersect(
|
||||
changeSectionData,
|
||||
changeConcentrationDividingLineData
|
||||
);
|
||||
if (hasNode) {
|
||||
const minA = calculateDistanceFromPointToLine(
|
||||
hasNode.segment2[0],
|
||||
hasNode.segment2[1],
|
||||
section.localToCanvasPoint(section.getStartPoint())
|
||||
);
|
||||
const minB = calculateDistanceFromPointToLine(
|
||||
hasNode.segment2[0],
|
||||
hasNode.segment2[1],
|
||||
section.localToCanvasPoint(section.getEndPoint())
|
||||
);
|
||||
const relationParam = minA > minB ? TurnoutPort.B : TurnoutPort.A;
|
||||
const portRefOtherDevice =
|
||||
relationParam == 'A' ? section.datas.paRef : section.datas.pbRef;
|
||||
if (
|
||||
portRefOtherDevice?.id &&
|
||||
!hasNodeSection.get(section.id) &&
|
||||
!hasNodeSection.get(portRefOtherDevice.id)
|
||||
) {
|
||||
const refDevice = this.queryStore.queryById<Turnout | Section>(
|
||||
portRefOtherDevice?.id
|
||||
);
|
||||
const [leftDevice, rightDevice] =
|
||||
refDevice.localToCanvasPoint(
|
||||
getRectangleCenter(refDevice.getLocalBounds())
|
||||
).x <
|
||||
section.localToCanvasPoint(
|
||||
getRectangleCenter(section.getLocalBounds())
|
||||
).x
|
||||
? [
|
||||
{
|
||||
device: refDevice,
|
||||
port: devicePort[
|
||||
portRefOtherDevice.devicePort
|
||||
] as TurnoutPort,
|
||||
},
|
||||
{ device: section, port: relationParam },
|
||||
]
|
||||
: [
|
||||
{ device: section, port: relationParam },
|
||||
{
|
||||
device: refDevice,
|
||||
port: devicePort[
|
||||
portRefOtherDevice.devicePort
|
||||
] as TurnoutPort,
|
||||
},
|
||||
];
|
||||
hasNodeSection.set(leftDevice.device.id, '1');
|
||||
hasNodeSection.set(rightDevice.device.id, '1');
|
||||
nodeConWithSecs.push(
|
||||
new graphicData.NodeConWithSec({
|
||||
leftSection: createRelatedRefProto(
|
||||
leftDevice.device.type,
|
||||
leftDevice.device.id,
|
||||
leftDevice.port
|
||||
),
|
||||
rightSection: createRelatedRefProto(
|
||||
rightDevice.device.type,
|
||||
rightDevice.device.id,
|
||||
rightDevice.port
|
||||
),
|
||||
})
|
||||
);
|
||||
} else if (!hasNodeSection.get(section.id) && !portRefOtherDevice?.id) {
|
||||
const [leftSectionId, rightSectionId] =
|
||||
relationParam === 'A'
|
||||
? [undefined, section.id]
|
||||
: [section.id, undefined];
|
||||
hasNodeSection.set(section.id, '1');
|
||||
if (leftSectionId == undefined) {
|
||||
nodeConWithSecs.push(
|
||||
new graphicData.NodeConWithSec({
|
||||
leftSection: undefined,
|
||||
rightSection: createRelatedRefProto(
|
||||
Section.Type,
|
||||
rightSectionId,
|
||||
TurnoutPort.A
|
||||
),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
nodeConWithSecs.push(
|
||||
new graphicData.NodeConWithSec({
|
||||
leftSection: createRelatedRefProto(
|
||||
Section.Type,
|
||||
leftSectionId,
|
||||
TurnoutPort.B
|
||||
),
|
||||
rightSection: undefined,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
nodeConWithSecs.sort((a, b) => {
|
||||
const sectionAId = a.leftSection ? a.leftSection.id : a.rightSection.id;
|
||||
const sectionA = this.queryStore.queryById<Section | Turnout>(sectionAId);
|
||||
const sectionBId = b.leftSection ? b.leftSection.id : b.rightSection.id;
|
||||
const sectionB = this.queryStore.queryById<Section | Turnout>(sectionBId);
|
||||
return (
|
||||
sectionA.localToCanvasPoint(
|
||||
getRectangleCenter(sectionA.getLocalBounds())
|
||||
).y -
|
||||
sectionB.localToCanvasPoint(
|
||||
getRectangleCenter(sectionB.getLocalBounds())
|
||||
).y
|
||||
);
|
||||
});
|
||||
this.datas.nodeConWithSecs = nodeConWithSecs;
|
||||
}
|
||||
}
|
||||
|
||||
export class ConcentrationDividingLineTemplate extends JlGraphicTemplate<ConcentrationDividingLine> {
|
||||
constructor(dataTemplate: IConcentrationDividingLineData) {
|
||||
super(ConcentrationDividingLine.Type, { dataTemplate });
|
||||
}
|
||||
new() {
|
||||
const g = new ConcentrationDividingLine();
|
||||
g.loadData(this.datas);
|
||||
return g;
|
||||
}
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
import {
|
||||
IGraphicApp,
|
||||
GraphicDrawAssistant,
|
||||
GraphicInteractionPlugin,
|
||||
IDrawApp,
|
||||
JlGraphic,
|
||||
linePoint,
|
||||
PolylineEditPlugin,
|
||||
addWayPoint,
|
||||
clearWayPoint,
|
||||
MenuItemOptions,
|
||||
ContextMenu
|
||||
} from 'jl-graphic';
|
||||
import {
|
||||
IConcentrationDividingLineData,
|
||||
ConcentrationDividingLine,
|
||||
ConcentrationDividingLineConsts,
|
||||
ConcentrationDividingLineTemplate,
|
||||
} from './ConcentrationDividingLine';
|
||||
import {
|
||||
DisplayObject,
|
||||
FederatedMouseEvent,
|
||||
Graphics,
|
||||
IHitArea,
|
||||
Point,
|
||||
} from 'pixi.js';
|
||||
import { getWayLineIndex } from '../polygon/PolygonUtils';
|
||||
|
||||
export class ConcentrationDividingLineDraw extends GraphicDrawAssistant<
|
||||
ConcentrationDividingLineTemplate,
|
||||
IConcentrationDividingLineData
|
||||
> {
|
||||
points: Point[] = [];
|
||||
graphic = new Graphics();
|
||||
|
||||
constructor(app: IDrawApp, template: ConcentrationDividingLineTemplate) {
|
||||
super(app, template, 'sym_o_timeline', '集中区分割线');
|
||||
this.container.addChild(this.graphic);
|
||||
|
||||
ConcentrationDividingLinePointEditPlugin.init(app, this);
|
||||
}
|
||||
|
||||
bind(): void {
|
||||
super.bind();
|
||||
}
|
||||
unbind(): void {
|
||||
super.unbind();
|
||||
}
|
||||
|
||||
onLeftDown(e: FederatedMouseEvent): void {
|
||||
const { x, y } = this.toCanvasCoordinates(e.global);
|
||||
const p = new Point(x, y);
|
||||
this.points.push(p);
|
||||
}
|
||||
|
||||
onRightClick(): void {
|
||||
if (this.points.length < 2) {
|
||||
this.finish();
|
||||
return;
|
||||
}
|
||||
this.createAndStore(true);
|
||||
}
|
||||
|
||||
onEsc(): void {
|
||||
if (this.points.length < 2) {
|
||||
this.finish();
|
||||
return;
|
||||
}
|
||||
this.createAndStore(true);
|
||||
}
|
||||
|
||||
redraw(p: Point): void {
|
||||
if (this.points.length < 1) return;
|
||||
this.graphic.clear();
|
||||
this.graphic.lineStyle(
|
||||
ConcentrationDividingLineConsts.lineWidth,
|
||||
ConcentrationDividingLineConsts.lineColor
|
||||
);
|
||||
|
||||
const ps = [...this.points];
|
||||
ps.push(p);
|
||||
ps.forEach((p, i) => {
|
||||
if (i !== 0) {
|
||||
this.graphic.lineTo(p.x, p.y);
|
||||
} else {
|
||||
this.graphic.moveTo(p.x, p.y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
prepareData(data: IConcentrationDividingLineData): boolean {
|
||||
if (this.points.length < 2) {
|
||||
console.log('ConcentrationDividingLine绘制因点不够取消绘制');
|
||||
return false;
|
||||
}
|
||||
data.points = this.points;
|
||||
return true;
|
||||
}
|
||||
|
||||
clearCache(): void {
|
||||
this.points = [];
|
||||
this.graphic.clear();
|
||||
}
|
||||
}
|
||||
|
||||
export class ConcentrationDividingLineGraphicHitArea implements IHitArea {
|
||||
concentrationDividingLine: ConcentrationDividingLine;
|
||||
constructor(concentrationDividingLine: ConcentrationDividingLine) {
|
||||
this.concentrationDividingLine = concentrationDividingLine;
|
||||
}
|
||||
contains(x: number, y: number): boolean {
|
||||
for (
|
||||
let i = 1;
|
||||
i < this.concentrationDividingLine.datas.points.length;
|
||||
i++
|
||||
) {
|
||||
const p1 = this.concentrationDividingLine.datas.points[i - 1];
|
||||
const p2 = this.concentrationDividingLine.datas.points[i];
|
||||
if (
|
||||
linePoint(p1, p2, { x, y }, ConcentrationDividingLineConsts.lineWidth)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const addWaypointConfig: MenuItemOptions = {
|
||||
name: '添加路径点',
|
||||
};
|
||||
const clearWaypointsConfig: MenuItemOptions = {
|
||||
name: '清除所有路径点',
|
||||
};
|
||||
const ConcentrationDividingLineEditMenu: ContextMenu = ContextMenu.init({
|
||||
name: '集中区分割线编辑菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [addWaypointConfig, clearWaypointsConfig],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export class ConcentrationDividingLinePointEditPlugin extends GraphicInteractionPlugin<ConcentrationDividingLine> {
|
||||
static Name = 'ConcentrationDividingLinePointDrag';
|
||||
drawAssistant: ConcentrationDividingLineDraw;
|
||||
|
||||
constructor(app: IGraphicApp, da: ConcentrationDividingLineDraw) {
|
||||
super(ConcentrationDividingLinePointEditPlugin.Name, app);
|
||||
this.drawAssistant = da;
|
||||
app.registerMenu(ConcentrationDividingLineEditMenu);
|
||||
}
|
||||
static init(app: IGraphicApp, da: ConcentrationDividingLineDraw) {
|
||||
return new ConcentrationDividingLinePointEditPlugin(app, da);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): ConcentrationDividingLine[] | undefined {
|
||||
return grahpics.filter(
|
||||
(g) => g.type == ConcentrationDividingLine.Type
|
||||
) as ConcentrationDividingLine[];
|
||||
}
|
||||
bind(g: ConcentrationDividingLine): void {
|
||||
g.lineGraphic.eventMode = 'static';
|
||||
g.lineGraphic.cursor = 'pointer';
|
||||
g.lineGraphic.hitArea = new ConcentrationDividingLineGraphicHitArea(g);
|
||||
g.transformSave = true;
|
||||
g.on('selected', this.onSelected, this);
|
||||
g.on('unselected', this.onUnselected, this);
|
||||
g.on('_rightclick', this.onContextMenu, this);
|
||||
}
|
||||
unbind(g: ConcentrationDividingLine): void {
|
||||
g.off('selected', this.onSelected, this);
|
||||
g.off('unselected', this.onUnselected, this);
|
||||
g.off('_rightclick', this.onContextMenu, this);
|
||||
}
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const concentrationDividingLine =
|
||||
target.getGraphic() as ConcentrationDividingLine;
|
||||
this.app.updateSelected(concentrationDividingLine);
|
||||
const p = concentrationDividingLine.screenToLocalPoint(e.global);
|
||||
addWaypointConfig.handler = () => {
|
||||
const linePoints = concentrationDividingLine.linePoints;
|
||||
const { start, end } = getWayLineIndex(linePoints, p);
|
||||
addWayPoint(concentrationDividingLine, false, start, end, p);
|
||||
};
|
||||
clearWaypointsConfig.handler = () => {
|
||||
clearWayPoint(concentrationDividingLine, false);
|
||||
};
|
||||
ConcentrationDividingLineEditMenu.open(e.global);
|
||||
}
|
||||
onSelected(g: DisplayObject): void {
|
||||
const concentrationDividingLine = g as ConcentrationDividingLine;
|
||||
let lep = concentrationDividingLine.getAssistantAppend<PolylineEditPlugin>(
|
||||
PolylineEditPlugin.Name
|
||||
);
|
||||
if (!lep) {
|
||||
lep = new PolylineEditPlugin(concentrationDividingLine);
|
||||
concentrationDividingLine.addAssistantAppend(lep);
|
||||
}
|
||||
lep.showAll();
|
||||
}
|
||||
onUnselected(g: DisplayObject): void {
|
||||
const concentrationDividingLine = g as ConcentrationDividingLine;
|
||||
const lep =
|
||||
concentrationDividingLine.getAssistantAppend<PolylineEditPlugin>(
|
||||
PolylineEditPlugin.Name
|
||||
);
|
||||
if (lep) {
|
||||
lep.hideAll();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
import { IPointData } from 'pixi.js';
|
||||
import { Section } from '../section/Section';
|
||||
import { Turnout } from '../turnout/Turnout';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { IDrawApp, JlGraphic } from 'jl-graphic';
|
||||
import { GraphicDataBase } from 'src/drawApp/graphics/GraphicDataBase';
|
||||
import { TurnoutData } from 'src/drawApp/graphics/TurnoutInteraction';
|
||||
import { SectionData } from 'src/drawApp/graphics/SectionInteraction';
|
||||
import { SignalData } from 'src/drawApp/graphics/SignalInteraction';
|
||||
import { Signal } from '../signal/Signal';
|
||||
import { Platform } from '../platform/Platform';
|
||||
import { PlatformData } from 'src/drawApp/graphics/PlatformInteraction';
|
||||
|
||||
//判断线段与线段有木有交点
|
||||
export function isSegmentsIntersect(
|
||||
segment1: IPointData[],
|
||||
segment2: IPointData[]
|
||||
) {
|
||||
const [p1, p2] = segment1;
|
||||
const [p3, p4] = segment2;
|
||||
// 判断包围盒是否相交
|
||||
if (
|
||||
Math.max(p1.x, p2.x) < Math.min(p3.x, p4.x) ||
|
||||
Math.min(p1.x, p2.x) > Math.max(p3.x, p4.x) ||
|
||||
Math.max(p1.y, p2.y) < Math.min(p3.y, p4.y) ||
|
||||
Math.min(p1.y, p2.y) > Math.max(p3.y, p4.y)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
// 计算向量叉积
|
||||
const cross1 = crossProduct(p3, p1, p4);
|
||||
const cross2 = crossProduct(p3, p2, p4);
|
||||
const cross3 = crossProduct(p1, p3, p2);
|
||||
const cross4 = crossProduct(p1, p4, p2);
|
||||
if (cross1 * cross2 < 0 && cross3 * cross4 < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function crossProduct(p1: IPointData, p2: IPointData, p3: IPointData) {
|
||||
return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
|
||||
}
|
||||
|
||||
export function getSegmentsFromPolyline(polyline: IPointData[]) {
|
||||
const segments = [];
|
||||
|
||||
for (let i = 0; i < polyline.length - 1; i++) {
|
||||
const segment = [polyline[i], polyline[i + 1]];
|
||||
segments.push(segment);
|
||||
}
|
||||
|
||||
return segments;
|
||||
}
|
||||
|
||||
//判断折线与折线有木有交点
|
||||
export function arePolylinesIntersect(
|
||||
polyline1: IPointData[],
|
||||
polyline2: IPointData[]
|
||||
) {
|
||||
const segments1 = getSegmentsFromPolyline(polyline1);
|
||||
const segments2 = getSegmentsFromPolyline(polyline2);
|
||||
|
||||
for (const segment1 of segments1) {
|
||||
for (const segment2 of segments2) {
|
||||
if (isSegmentsIntersect(segment1, segment2)) {
|
||||
return { hasnode: true, segment1, segment2 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取指定区间内的物理区段和道岔
|
||||
export function findContainDevice(
|
||||
refDevice: Section | Turnout,
|
||||
refDevicePort: graphicData.RelatedRef.DevicePort,
|
||||
containDeviceIds: number[],
|
||||
drawApp: IDrawApp
|
||||
) {
|
||||
const devicePort = graphicData.RelatedRef.DevicePort;
|
||||
containDeviceIds.push(refDevice.id);
|
||||
switch (true) {
|
||||
case refDevice instanceof Section:
|
||||
const sectionPaorbRef =
|
||||
refDevicePort == devicePort.B
|
||||
? refDevice.datas.paRef
|
||||
: refDevice.datas.pbRef;
|
||||
if (sectionPaorbRef && !containDeviceIds.includes(sectionPaorbRef.id)) {
|
||||
const pbRefDevice = drawApp.queryStore.queryById<Section | Turnout>(
|
||||
sectionPaorbRef.id
|
||||
);
|
||||
findContainDevice(
|
||||
pbRefDevice,
|
||||
sectionPaorbRef.devicePort,
|
||||
containDeviceIds,
|
||||
drawApp
|
||||
);
|
||||
}
|
||||
break;
|
||||
//道岔需要分路--实际的走向
|
||||
case refDevice instanceof Turnout:
|
||||
const otherPorts = [devicePort.A, devicePort.B, devicePort.C].filter(
|
||||
(port) => port !== refDevicePort
|
||||
);
|
||||
otherPorts.forEach((port) => {
|
||||
switch (port) {
|
||||
case devicePort.A:
|
||||
const turnoutPaRef = refDevice.datas.paRef;
|
||||
if (turnoutPaRef && !containDeviceIds.includes(turnoutPaRef.id)) {
|
||||
const paRefDevice = drawApp.queryStore.queryById<
|
||||
Section | Turnout
|
||||
>(turnoutPaRef.id);
|
||||
findContainDevice(
|
||||
paRefDevice,
|
||||
turnoutPaRef.devicePort,
|
||||
containDeviceIds,
|
||||
drawApp
|
||||
);
|
||||
}
|
||||
break;
|
||||
case devicePort.B:
|
||||
const turnoutPbRef = refDevice.datas.pbRef;
|
||||
if (turnoutPbRef && !containDeviceIds.includes(turnoutPbRef.id)) {
|
||||
const pbRefDevice = drawApp.queryStore.queryById<
|
||||
Section | Turnout
|
||||
>(turnoutPbRef.id);
|
||||
findContainDevice(
|
||||
pbRefDevice,
|
||||
turnoutPbRef.devicePort,
|
||||
containDeviceIds,
|
||||
drawApp
|
||||
);
|
||||
}
|
||||
break;
|
||||
case devicePort.C:
|
||||
const turnoutPcRef = (refDevice as Turnout).datas.pcRef;
|
||||
if (turnoutPcRef && !containDeviceIds.includes(turnoutPcRef.id)) {
|
||||
const pcRefDevice = drawApp.queryStore.queryById<
|
||||
Section | Turnout
|
||||
>(turnoutPcRef.id);
|
||||
findContainDevice(
|
||||
pcRefDevice,
|
||||
turnoutPcRef.devicePort,
|
||||
containDeviceIds,
|
||||
drawApp
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function handleCentralizedStationsData(
|
||||
devices: JlGraphic[],
|
||||
centralizedStation: number
|
||||
) {
|
||||
interface GraphicData {
|
||||
centralizedStation: number;
|
||||
}
|
||||
const dataMap = new Map<string, GraphicDataBase>([
|
||||
[Turnout.Type, new TurnoutData()],
|
||||
[Section.Type, new SectionData()],
|
||||
[Signal.Type, new SignalData()],
|
||||
[Platform.Type, new PlatformData()],
|
||||
]);
|
||||
devices.forEach((device) => {
|
||||
const data = dataMap.get(device.type);
|
||||
if (data) {
|
||||
data.copyFrom(device.saveData());
|
||||
const dataCopy = data as GraphicDataBase & GraphicData;
|
||||
dataCopy.centralizedStation = centralizedStation;
|
||||
device.updateData(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//找到公共的元素
|
||||
type findType = string | number;
|
||||
export function findCommonElements(arrays: findType[][]) {
|
||||
if (arrays.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const commonElements: findType[] = [];
|
||||
arrays[0].forEach((element) => {
|
||||
if (arrays.every((arr) => arr.includes(element))) {
|
||||
commonElements.push(element);
|
||||
}
|
||||
});
|
||||
return commonElements;
|
||||
}
|
57
src/graphics/concentrationDividingLine/SectionGraphic.ts
Normal file
57
src/graphics/concentrationDividingLine/SectionGraphic.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { Graphics, IPointData } from 'pixi.js';
|
||||
import { assertBezierPoints, convertToBezierParams } from 'jl-graphic';
|
||||
|
||||
export enum DevicePort {
|
||||
A = 'A',
|
||||
B = 'B',
|
||||
C = 'C',
|
||||
}
|
||||
|
||||
export class SectionGraphic extends Graphics {
|
||||
static Type = 'SectionGraphic';
|
||||
private _points: IPointData[] = [];
|
||||
public get points(): IPointData[] {
|
||||
return this._points;
|
||||
}
|
||||
public set points(value: IPointData[]) {
|
||||
if (!this.isCurve) {
|
||||
if (value.length < 2) {
|
||||
throw Error('Polyline must have at least 2 points');
|
||||
}
|
||||
} else {
|
||||
assertBezierPoints(value);
|
||||
}
|
||||
this._points = value;
|
||||
}
|
||||
|
||||
private _segmentsCount = 10;
|
||||
public get segmentsCount(): number {
|
||||
return this._segmentsCount;
|
||||
}
|
||||
public set segmentsCount(value: number) {
|
||||
if (value < 1) {
|
||||
throw Error('segmentsCount must be at least 1');
|
||||
}
|
||||
this._segmentsCount = value;
|
||||
}
|
||||
|
||||
isCurve = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
paint() {
|
||||
if (this.isCurve) {
|
||||
const bps = convertToBezierParams(this.points);
|
||||
bps.forEach((bp) => {
|
||||
this.drawBezierCurve(bp.p1, bp.p2, bp.cp1, bp.cp2, this.segmentsCount);
|
||||
});
|
||||
} else {
|
||||
this.moveTo(this.points[0].x, this.points[0].y);
|
||||
for (let i = 1; i < this.points.length; i++) {
|
||||
this.lineTo(this.points[i].x, this.points[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user