Compare commits
200 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d843e81fd4 | ||
|
82fabffdb8 | ||
|
ec135451d4 | ||
|
22d3a1794a | ||
|
9261a95f78 | ||
|
eee398eaa1 | ||
|
1fa571f777 | ||
|
309931be31 | ||
|
b6c031d7b9 | ||
|
875a566b38 | ||
2fb6f91372 | |||
|
ef0637003a | ||
|
53f1be79e9 | ||
|
c640f3f85a | ||
|
efb8140a29 | ||
|
dd5f77d6f1 | ||
|
4314e0db79 | ||
|
db7911985a | ||
|
268a964ef0 | ||
|
fe789210dc | ||
|
3a7662d308 | ||
|
f566a47718 | ||
|
faee59bd55 | ||
|
db3d424e53 | ||
|
52a7e89283 | ||
|
a13833d8b8 | ||
|
0b97ef6253 | ||
|
936ace948d | ||
|
935e12f264 | ||
|
8540e68711 | ||
|
7cc534028b | ||
|
f9782c1227 | ||
|
e5745dfc9f | ||
|
8cd833b466 | ||
|
870c790c93 | ||
|
2e07f7413b | ||
|
75b8f03e30 | ||
|
c3309c9266 | ||
|
086c5628ba | ||
|
d0121191f8 | ||
|
de11916836 | ||
|
8e16683b53 | ||
|
b58591efeb | ||
|
9681bd2b7b | ||
|
aa156e400c | ||
|
2b0f794fd1 | ||
|
b63df4acf4 | ||
|
04c02e2a40 | ||
df8eb7ad54 | |||
|
b90c3e3bda | ||
|
4200403e9a | ||
8e6b0f6b77 | |||
|
aaf1c5df40 | ||
|
863d52bf56 | ||
|
de876c4807 | ||
06efef16c7 | |||
|
93e1f7992c | ||
|
c019c19a33 | ||
eeb9eef77c | |||
|
98a128a4dd | ||
8b173bfc2b | |||
b4b3012432 | |||
|
9558bea3a5 | ||
|
9458eca656 | ||
|
9612b27c76 | ||
|
63924eaaef | ||
949b173603 | |||
|
fd2e8bd975 | ||
|
88d3f22a8e | ||
|
8839b38911 | ||
|
a9e4416b0e | ||
|
c487a649d4 | ||
|
9531f7bfa3 | ||
|
2aebcf31b5 | ||
|
a5c1277f23 | ||
|
b71680772d | ||
|
05a29ea5a8 | ||
|
6ddc51ecd7 | ||
|
e6b0557b1b | ||
|
be5499e4ca | ||
|
77982dacd2 | ||
|
87d617c3e6 | ||
|
f95e12cf3e | ||
|
7b680de6de | ||
|
f6057003a6 | ||
|
e92f5600ee | ||
|
0814ad6cac | ||
|
9da46fce2d | ||
|
6e556db5b0 | ||
|
a04acb38fa | ||
|
5e3d7c3aea | ||
|
b63c87335f | ||
|
d5f4efe6e6 | ||
|
cb78231722 | ||
|
a709c1f395 | ||
|
e2db43b689 | ||
|
99374d8f49 | ||
|
49b9c83949 | ||
|
a487159ac0 | ||
|
0b3b8013ba | ||
|
da6d8a2caf | ||
|
c603b3ac55 | ||
|
ed834b114a | ||
|
cde11aa2bb | ||
|
fc8ddeecb7 | ||
|
c64045452e | ||
|
b9c20b93fd | ||
|
ed298762cc | ||
|
3ae615df66 | ||
|
8364677185 | ||
|
c168d7b0cc | ||
|
834ba6931e | ||
|
e92fd12c31 | ||
|
b15b78d735 | ||
|
0f7dba3642 | ||
|
3bdff0950c | ||
|
8b50e89bf9 | ||
|
9ebe9b40e2 | ||
|
522d5ac4f0 | ||
|
da60b95807 | ||
|
7f598e209c | ||
|
f7d95ed2c7 | ||
|
5c78c1daca | ||
|
d7cb1bb50a | ||
|
f9e06c5f09 | ||
|
2a217ed2f3 | ||
|
9597f302f3 | ||
|
8c22629234 | ||
|
fcf9ea7983 | ||
|
5c05f5d595 | ||
|
4290e66fe3 | ||
|
e566724f8a | ||
|
288784c4bf | ||
|
67956745e5 | ||
|
076b500db5 | ||
|
f83a11125b | ||
|
f1aaafeb67 | ||
|
e0586c5738 | ||
|
9379ebfcc6 | ||
|
e9ddf033a3 | ||
|
fe46019070 | ||
|
095c38f76a | ||
|
26e68ae3a5 | ||
|
ea52fbf206 | ||
|
3e0752e352 | ||
|
0f1c65c6e6 | ||
|
b46f8c71e4 | ||
|
bc295e6977 | ||
|
394e6cf5ee | ||
|
c29cb2411f | ||
|
75b5e81ad4 | ||
|
3823eea337 | ||
|
50a940c245 | ||
|
d781b6afd2 | ||
|
88a0cd9ec4 | ||
|
c76caa6b58 | ||
|
0f0d925488 | ||
|
71612e4613 | ||
|
94fe367687 | ||
|
6a183f2347 | ||
|
c762a5df55 | ||
|
9cc9c96671 | ||
|
4bff283635 | ||
|
bebd538f01 | ||
|
571b460780 | ||
|
79f3b05f39 | ||
|
ae2e524059 | ||
|
58bbdeefda | ||
|
422eab1811 | ||
|
9b6adf3f76 | ||
|
1adb5c4647 | ||
|
cdfaf6f3eb | ||
|
3a9d7c5f7d | ||
|
0767750d2c | ||
|
73300543e1 | ||
|
e822b6118a | ||
|
8e2d111570 | ||
|
b197c697f3 | ||
|
aff04379d7 | ||
|
9b2acf4659 | ||
|
29583d4940 | ||
|
c90a49e076 | ||
|
9eca541c1f | ||
|
ade8346d3b | ||
|
0b0d6303cd | ||
|
b08be32d1e | ||
|
1a3dd02c94 | ||
|
6dad42231d | ||
|
fcc864241b | ||
|
4794c99fbf | ||
|
178c5758f2 | ||
|
a9df480265 | ||
|
85e4f2da85 | ||
|
8fd0277338 | ||
|
81e5c23093 | ||
|
fc23bb11d5 | ||
|
347dec93d0 | ||
|
ed5463a370 | ||
|
0f3b59254f | ||
|
f813cea9e9 |
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,3 +1,3 @@
|
||||
[submodule "bj-rtss-message"]
|
||||
path = bj-rtss-message
|
||||
url = ../bj-rtss-message.git
|
||||
[submodule "rts-sim-testing-message"]
|
||||
path = rts-sim-testing-message
|
||||
url = http://120.46.212.6:3000/joylink/rts-sim-testing-message.git
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 999608fa88a430cba9bef8915f76993a0e4c6d8e
|
10502
package-lock.json
generated
10502
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -22,12 +22,13 @@
|
||||
"default-passive-events": "^2.0.0",
|
||||
"echarts": "^5.4.3",
|
||||
"google-protobuf": "^3.21.2",
|
||||
"jl-graphic": "git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#v0.1.3",
|
||||
"jl-graphic": "git+http://120.46.212.6:3000/joylink/graphic-pixi.git#v0.1.11",
|
||||
"js-base64": "^3.7.5",
|
||||
"pinia": "^2.0.11",
|
||||
"quasar": "^2.6.0",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0"
|
||||
"vue-router": "^4.0.0",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@quasar/app-vite": "^1.0.0",
|
||||
@ -45,7 +46,7 @@
|
||||
"typescript": "^4.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18 || ^16 || ^14.19",
|
||||
"node": "^20 || ^18 || ^16 || ^14.19",
|
||||
"npm": ">= 6.13.4",
|
||||
"yarn": ">= 1.21.1"
|
||||
}
|
||||
|
@ -32,6 +32,11 @@
|
||||
<path d="M14.4091 23V11.3636H18.3409C19.2538 11.3636 20 11.5284 20.5795 11.858C21.1629 12.1837 21.5947 12.625 21.875 13.1818C22.1553 13.7386 22.2955 14.3598 22.2955 15.0455C22.2955 15.7311 22.1553 16.3542 21.875 16.9148C21.5985 17.4754 21.1705 17.9223 20.5909 18.2557C20.0114 18.5852 19.2689 18.75 18.3636 18.75H15.5455V17.5H18.3182C18.9432 17.5 19.4451 17.392 19.8239 17.1761C20.2027 16.9602 20.4773 16.6686 20.6477 16.3011C20.822 15.9299 20.9091 15.5114 20.9091 15.0455C20.9091 14.5795 20.822 14.1629 20.6477 13.7955C20.4773 13.428 20.2008 13.1402 19.8182 12.9318C19.4356 12.7197 18.928 12.6136 18.2955 12.6136H15.8182V23H14.4091Z" fill="white"/>
|
||||
<line y1="32" x2="35" y2="32" stroke="white" stroke-width="4"/>
|
||||
</symbol>
|
||||
<symbol id="icon-garage-door-box" viewBox="0 0 35 34" fill="none">
|
||||
<rect x="1" y="1" width="33" height="32" stroke="white" stroke-width="2"/>
|
||||
<path d="M17.1932 14C17.0838 13.6652 16.9396 13.3653 16.7607 13.1001C16.585 12.8317 16.3745 12.603 16.1293 12.4141C15.8873 12.2251 15.6122 12.081 15.304 11.9815C14.9957 11.8821 14.6577 11.8324 14.2898 11.8324C13.6866 11.8324 13.138 11.9882 12.6442 12.2997C12.1503 12.6113 11.7576 13.0703 11.4659 13.6768C11.1742 14.2834 11.0284 15.0275 11.0284 15.9091C11.0284 16.7907 11.1759 17.5348 11.4709 18.1413C11.7659 18.7479 12.1652 19.2069 12.669 19.5185C13.1728 19.83 13.7396 19.9858 14.3693 19.9858C14.9527 19.9858 15.4664 19.8615 15.9105 19.6129C16.358 19.361 16.706 19.0064 16.9545 18.549C17.2064 18.0883 17.3324 17.5464 17.3324 16.9233L17.7102 17.0028H14.6477V15.9091H18.5256V17.0028C18.5256 17.8414 18.3466 18.5705 17.9886 19.1903C17.634 19.8101 17.1435 20.2907 16.517 20.6321C15.8939 20.9702 15.178 21.1392 14.3693 21.1392C13.4678 21.1392 12.6757 20.9271 11.9929 20.5028C11.3134 20.0786 10.7831 19.4754 10.402 18.6932C10.0241 17.911 9.83523 16.983 9.83523 15.9091C9.83523 15.1037 9.94295 14.3795 10.1584 13.7365C10.3771 13.0902 10.6854 12.54 11.0831 12.0859C11.4808 11.6319 11.9515 11.2839 12.495 11.0419C13.0386 10.8 13.6368 10.679 14.2898 10.679C14.8267 10.679 15.3272 10.7602 15.7912 10.9226C16.2585 11.0817 16.6745 11.3087 17.0391 11.6037C17.407 11.8954 17.7135 12.245 17.9588 12.6527C18.2041 13.0571 18.3731 13.5062 18.4659 14H17.1932Z" fill="white"/>
|
||||
<line y1="32" x2="35" y2="32" stroke="white" stroke-width="4"/>
|
||||
</symbol>
|
||||
<symbol id="icon-esb-button" viewBox="0 0 35 34" fill="none">
|
||||
<rect x="1" y="1" width="33" height="32" stroke="white" stroke-width="2"/>
|
||||
<line y1="32" x2="35" y2="32" stroke="white" stroke-width="4"/>
|
||||
@ -75,4 +80,10 @@
|
||||
<path d="M20 27H39" stroke="#FFFFFF"/>
|
||||
<path d="M29 27V43" stroke="#FFFFFF"/>
|
||||
</symbol>
|
||||
<symbol id="icon-car-washing" viewBox="0 0 150 150" fill="none">
|
||||
<rect x="45" y="3" width="60" height="144" fill="#FFFFFF" stroke="#FFFFFF"/>
|
||||
</symbol>
|
||||
<symbol id="icon-flood-gate" viewBox="0 0 129 139" fill="none">
|
||||
<path fill-rule="evenodd" stroke="rgba(255, 255, 255, 1)" stroke-width="5" d="M0 1.5L61.5 1.5M61.5 1.5L123 1.5M61.5 1.5L61.5 137.5L0 137.5L123 137.5"/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 13 KiB |
1
rts-sim-testing-message
Submodule
1
rts-sim-testing-message
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit a1534096aa1ed2566b93ffe7bfde76750de10a60
|
@ -7,7 +7,7 @@ const os = require('os');
|
||||
|
||||
const { exec } = require('child_process');
|
||||
|
||||
const messageDir = resolve(__dirname, '../bj-rtss-message');
|
||||
const messageDir = resolve(__dirname, '../rts-sim-testing-message');
|
||||
const protoDir = resolve(messageDir, 'protos');
|
||||
const destDir = resolve(__dirname, '../src/protos');
|
||||
|
||||
|
@ -118,7 +118,8 @@ export async function getPublishMapInfoByLineId(
|
||||
export function saveToDraft(
|
||||
id: number,
|
||||
data: {
|
||||
name: string;
|
||||
draftName: string;
|
||||
category: string;
|
||||
}
|
||||
) {
|
||||
return api.post(`${PublishUriBase}/saveAsDrafting/${id}`, data);
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { request } from 'src/protos/request';
|
||||
import { TrainConfigData } from './TrainModelApi';
|
||||
|
||||
const UriBase = '/api/v1/simulation';
|
||||
|
||||
@ -20,6 +22,16 @@ export async function destroySimulation(data: { simulationId: string }) {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export interface TrainEnd {
|
||||
radarCheckSpeedDiff: number;
|
||||
radarCheckTime: number;
|
||||
radarEnable: boolean;
|
||||
speedSensorEnableA: boolean;
|
||||
speedSensorEnableB: boolean;
|
||||
accOutSpeed: number;
|
||||
radarOutSpeed: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加列车
|
||||
* @param simulationId 仿真id
|
||||
@ -29,36 +41,43 @@ export async function destroySimulation(data: { simulationId: string }) {
|
||||
* @param devicePort 道岔的端口
|
||||
* @param headOffset 偏移量(区段从A端为偏移原点,道岔从岔芯为偏移原点)
|
||||
* @param trainLength 列车总长
|
||||
* @param trainId 列车编号
|
||||
* @param trainSpeed 列车初始速度
|
||||
*/
|
||||
export async function addTrain(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
up: boolean;
|
||||
id: number;
|
||||
trainId: number;
|
||||
trainSpeed: number;
|
||||
devicePort?: string;
|
||||
headOffset: number;
|
||||
trainLength?: number;
|
||||
configTrain: TrainConfigData;
|
||||
trainEndsA: TrainEnd;
|
||||
trainEndsB: TrainEnd;
|
||||
}) {
|
||||
const response = await api.post(`${UriBase}/train/add`, data);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加列车
|
||||
* 修改列车
|
||||
* @param id 列车的id
|
||||
* @param simulationId 仿真id
|
||||
* @param trainLength 列车总长
|
||||
* @param wheelDiameter 列车轮径
|
||||
*/
|
||||
export async function updateTrain(data: {
|
||||
id: string;
|
||||
simulationId: string;
|
||||
trainLength?: number;
|
||||
wheelDiameter?: number;
|
||||
}) {
|
||||
const response = await api.post(`${UriBase}/train/update`, data);
|
||||
return response.data;
|
||||
}
|
||||
// export async function updateTrain(data: {
|
||||
// id: string;
|
||||
// simulationId: string;
|
||||
// trainLength?: number;
|
||||
// wheelDiameter?: number;
|
||||
// }) {
|
||||
// const response = await api.post(`${UriBase}/train/update`, data);
|
||||
// return response.data;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 移除列车
|
||||
@ -74,22 +93,48 @@ export async function removeTrain(data: {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有列车
|
||||
*/
|
||||
export async function removeAllTrain(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
}) {
|
||||
const response = await api.post(`${UriBase}/train/remove/all`, data);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function setAxleSectionState(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
id: number;
|
||||
operation: number;
|
||||
deviceId: number;
|
||||
operation: request.Section.Operation;
|
||||
param?: {
|
||||
mockDrst: boolean;
|
||||
mockPdrst: boolean;
|
||||
};
|
||||
}) {
|
||||
return await api.post(`${UriBase}/axleSection/operation`, data);
|
||||
}
|
||||
|
||||
export async function setSignalState(data: {
|
||||
// {
|
||||
// simulationId: string;
|
||||
// mapId: number;
|
||||
// id: number;
|
||||
// operation: number;
|
||||
// aspect: number;
|
||||
// }
|
||||
export interface SignalOperationReq {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
id: number;
|
||||
operation: number;
|
||||
aspect: number;
|
||||
}) {
|
||||
deviceId: number;
|
||||
operation: request.Signal.Operation;
|
||||
param: {
|
||||
force: request.Signal.Force;
|
||||
dsList: request.Signal.DS[];
|
||||
};
|
||||
}
|
||||
export async function setSignalState(data: SignalOperationReq) {
|
||||
return await api.post(`${UriBase}/signal/operation`, data);
|
||||
}
|
||||
|
||||
@ -98,6 +143,7 @@ export interface SetSwitchParams {
|
||||
mapId: number;
|
||||
deviceId: number;
|
||||
operation: number;
|
||||
param: { forcePosition: number };
|
||||
}
|
||||
|
||||
export async function setSwitchPosition(data: SetSwitchParams) {
|
||||
@ -109,7 +155,7 @@ export interface IbpButtonOperationParams {
|
||||
down: boolean;
|
||||
mapId: number;
|
||||
simulationId: string;
|
||||
stationId: number;
|
||||
ibpId: number;
|
||||
}
|
||||
export async function ibpButtonOperation(params: IbpButtonOperationParams) {
|
||||
return await api.post(`${UriBase}/ibp/btn/operation`, params);
|
||||
@ -129,7 +175,7 @@ export async function esbButtonOperation(params: EsbButtonOperationParams) {
|
||||
export interface IbpKeyOperationParams {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
stationId: number;
|
||||
ibpId: number;
|
||||
gear: number;
|
||||
keyId: number;
|
||||
}
|
||||
@ -192,10 +238,10 @@ export async function getSimulationChannelName(): Promise<string> {
|
||||
* @returns
|
||||
*/
|
||||
export async function setRelayState(data: {
|
||||
id: number;
|
||||
mapId: number;
|
||||
simulationId: string;
|
||||
td: boolean;
|
||||
mapId: number;
|
||||
deviceId: number;
|
||||
operation: request.Relay.Operation;
|
||||
}) {
|
||||
return await api.post(`${UriBase}/relay/operation`, data);
|
||||
}
|
||||
@ -224,7 +270,7 @@ export async function getMapKilometerRange(
|
||||
export async function pslOperate(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
gateBoxId: number;
|
||||
pslId: number;
|
||||
buttonCode: string;
|
||||
down: boolean;
|
||||
}) {
|
||||
@ -237,9 +283,150 @@ export async function screenDoorOperate(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
deviceId: number;
|
||||
operation: number;
|
||||
asdCodes?: number[];
|
||||
group?: number;
|
||||
operation: request.Psd.Operation;
|
||||
param: {
|
||||
asdCodes: number[];
|
||||
force: request.Psd.Force;
|
||||
fault: request.Psd.Fault;
|
||||
};
|
||||
}) {
|
||||
return await api.post(`${UriBase}/psd/operation`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 应答器修改报文
|
||||
*/
|
||||
export async function updateMessageTransponder(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
fixedTelegram: string;
|
||||
fixedUserTelegram: string;
|
||||
variableTelegram: string;
|
||||
variableUserTelegram: string;
|
||||
baliseId: number;
|
||||
}) {
|
||||
return await api.put(`${UriBase}/balise/telegram/modify`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置应答器报文
|
||||
*/
|
||||
export async function resetMessageTransponder(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
baliseId: number;
|
||||
}) {
|
||||
return await api.put(`${UriBase}/balise/telegram/reset`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改应答器位置
|
||||
*/
|
||||
export async function updatePositionTransponder(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
baliseId: number;
|
||||
km: {
|
||||
coordinateSystem: string;
|
||||
kilometer: number;
|
||||
direction: number;
|
||||
};
|
||||
}) {
|
||||
return await api.put(`${UriBase}/balise/position/modify`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置应答器位置
|
||||
*/
|
||||
export async function resetPositionTransponder(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
baliseId: number;
|
||||
}) {
|
||||
return await api.put(`${UriBase}/balise/position/reset`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化所有应答器状态
|
||||
*/
|
||||
export async function initTranspondersState(simulationId: string) {
|
||||
return await api.put(`${UriBase}/balise/reset?simulationId=${simulationId}`);
|
||||
}
|
||||
|
||||
export interface TrainConfig {
|
||||
trainId: number;
|
||||
length: number;
|
||||
simulationId: string;
|
||||
wheelDiameter: number;
|
||||
configData: {
|
||||
davisParamA: number;
|
||||
davisParamB: number;
|
||||
davisParamC: number;
|
||||
curveResistanceParamR1: number;
|
||||
curveResistanceParamR2: number;
|
||||
curveResistanceParamR3: number;
|
||||
curveResistanceParamR4: number;
|
||||
jump: boolean;
|
||||
revolvingMassParam: number;
|
||||
slide: number;
|
||||
slipA: number;
|
||||
slipR: number;
|
||||
slipD: number;
|
||||
stopSign: number;
|
||||
idlingA: number;
|
||||
idlingR: number;
|
||||
idlingD: number;
|
||||
};
|
||||
trainEndsA: {
|
||||
radarCheckSpeedDiff: number;
|
||||
radarCheckTime: number;
|
||||
radarEnable: boolean;
|
||||
speedSensorEnableA: boolean;
|
||||
speedSensorEnableB: boolean;
|
||||
accOutSpeed: number;
|
||||
radarOutSpeed: number;
|
||||
};
|
||||
trainEndsB: {
|
||||
radarCheckSpeedDiff: number;
|
||||
radarCheckTime: number;
|
||||
radarEnable: boolean;
|
||||
speedSensorEnableA: boolean;
|
||||
speedSensorEnableB: boolean;
|
||||
accOutSpeed: number;
|
||||
radarOutSpeed: number;
|
||||
};
|
||||
}
|
||||
/** 列车参数修改 */
|
||||
export async function updateTrainConfig(data: TrainConfig) {
|
||||
return await api.post(`${UriBase}/train/config`, data);
|
||||
}
|
||||
|
||||
/** 应答器停止发送报文 */
|
||||
export async function stopTransponderTelegram(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
baliseId: number;
|
||||
}) {
|
||||
return await api.put(`${UriBase}/balise/telegram/stop`, data);
|
||||
}
|
||||
/** 应答器取消停止发送报文 */
|
||||
export async function sendTransponderTelegram(data: {
|
||||
simulationId: string;
|
||||
mapId: number;
|
||||
baliseId: number;
|
||||
}) {
|
||||
return await api.put(`${UriBase}/balise/telegram/send`, data);
|
||||
}
|
||||
|
||||
/** 获取列车可以连接平台列表 */
|
||||
export async function getCanLinkPlatForm(id: string) {
|
||||
return await api.get(`${UriBase}/train/conn/type/${id}`);
|
||||
}
|
||||
/** 修改列车连接 */
|
||||
export async function updateTrainConn(data: {
|
||||
id: string;
|
||||
simulationId: string;
|
||||
connType: number;
|
||||
}) {
|
||||
return await api.post(`${UriBase}/train/conn`, data);
|
||||
}
|
||||
|
@ -27,15 +27,37 @@ export async function pageQuery(
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export interface TrainConfigData {
|
||||
davisParamA: number;
|
||||
davisParamB: number;
|
||||
davisParamC: number;
|
||||
curveResistanceParamR1: number;
|
||||
curveResistanceParamR2: number;
|
||||
curveResistanceParamR3: number;
|
||||
curveResistanceParamR4: number;
|
||||
jump: boolean;
|
||||
revolvingMassParam: number;
|
||||
slide: number;
|
||||
slipA: number;
|
||||
slipR: number;
|
||||
slipD: number;
|
||||
stopSign: number;
|
||||
idlingA: number;
|
||||
idlingR: number;
|
||||
idlingD: number;
|
||||
}
|
||||
|
||||
export interface TrainCreateParams {
|
||||
carriage_length: number;
|
||||
description: string;
|
||||
max_diameter: number;
|
||||
min_diameter: number;
|
||||
// max_diameter: number;
|
||||
// min_diameter: number;
|
||||
name: string;
|
||||
total_length: number;
|
||||
train_model: number;
|
||||
train_sets: string;
|
||||
trainConfigData?: TrainConfigData;
|
||||
trainControlMapId: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,4 +12,4 @@
|
||||
<path fill="#00B4FF"
|
||||
d="M.5 251.9c29.6-.5 59.2-.8 88.8-1l88.7-.3 88.7.3 44.4.4 44.4.6-44.4.6-44.4.4-88.7.3-88.7-.3a7981 7981 0 01-88.8-1z" />
|
||||
<path fill="none" d="M-565.2 324H-252v15.8h-313.2z" />
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
@ -67,6 +67,9 @@ export class ApiError {
|
||||
// for each client)
|
||||
const api = axios.create({ baseURL: getHttpBase() });
|
||||
let isOpenDialog = false; // 认证弹窗是否打开
|
||||
|
||||
const CancelToken = axios.CancelToken;
|
||||
const source = CancelToken.source();
|
||||
export default boot(({ app, router }) => {
|
||||
// for use inside Vue files (Options API) through this.$axios and this.$api
|
||||
|
||||
@ -74,6 +77,10 @@ export default boot(({ app, router }) => {
|
||||
api.interceptors.request.use(
|
||||
(config) => {
|
||||
config.headers.Authorization = getJwtToken();
|
||||
config.cancelToken = source.token;
|
||||
if (isOpenDialog) {
|
||||
source.cancel();
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(err: AxiosError) => {
|
||||
|
@ -3,6 +3,7 @@
|
||||
ref="dialogRef"
|
||||
@hide="onHide"
|
||||
v-bind="$attrs"
|
||||
@show="emit('show')"
|
||||
transitionShow="jump-up"
|
||||
transitionHide="jump-down"
|
||||
class="column"
|
||||
@ -11,17 +12,22 @@
|
||||
: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"
|
||||
style="
|
||||
cursor: move;
|
||||
border-top-right-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
"
|
||||
:style="`height: ${props.titleHeight}px;background: ${props.titleColor}`"
|
||||
>
|
||||
<div
|
||||
:style="`color:${props.fontColor};font-size: ${props.fontSize}px;`"
|
||||
:style="`height: 100%; line-height: ${props.titleHeight}px; color:${props.fontColor};font-size: ${props.fontSize}px;`"
|
||||
>
|
||||
{{ props.title }}
|
||||
</div>
|
||||
@ -45,7 +51,10 @@
|
||||
import { QBar, useDialogPluginComponent } from 'quasar';
|
||||
import { ref, onMounted, onUnmounted, reactive } from 'vue';
|
||||
|
||||
const emit = defineEmits([...useDialogPluginComponent.emits]);
|
||||
const emit = defineEmits({
|
||||
...useDialogPluginComponent.emitsObject,
|
||||
show: () => true,
|
||||
});
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@ -57,10 +66,11 @@ const props = withDefaults(
|
||||
width?: number;
|
||||
height?: number;
|
||||
bgColor?: string;
|
||||
bgBorder?: string;
|
||||
}>(),
|
||||
{
|
||||
width: 500,
|
||||
height: 600,
|
||||
height: 800,
|
||||
titleColor: 'rgb(25,118,210)',
|
||||
titleHeight: 36,
|
||||
fontSize: 20,
|
||||
@ -68,7 +78,8 @@ const props = withDefaults(
|
||||
}
|
||||
);
|
||||
|
||||
const { dialogRef, onDialogHide } = useDialogPluginComponent();
|
||||
const { dialogRef, onDialogHide /* , onDialogCancel, onDialogOK */ } =
|
||||
useDialogPluginComponent();
|
||||
|
||||
const headerRef = ref<InstanceType<typeof QBar> | null>(null);
|
||||
|
||||
@ -78,6 +89,7 @@ const offset = reactive({
|
||||
});
|
||||
|
||||
const start = { x: 0, y: 0 };
|
||||
const startOffset = { x: 0, y: 0 };
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('mousedown', onMouseDown);
|
||||
@ -88,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);
|
||||
}
|
||||
|
@ -39,12 +39,17 @@
|
||||
<platform-property
|
||||
v-if="drawStore.selectedGraphicType === Platform.Type"
|
||||
></platform-property>
|
||||
<ibpBox-property
|
||||
v-if="drawStore.selectedGraphicType === IbpBox.Type"
|
||||
></ibpBox-property>
|
||||
<pslBox-property
|
||||
v-if="drawStore.selectedGraphicType === PslBox.Type"
|
||||
></pslBox-property>
|
||||
<screenDoor-property
|
||||
v-if="drawStore.selectedGraphicType === ScreenDoor.Type"
|
||||
></screenDoor-property>
|
||||
<station-property
|
||||
v-if="drawStore.selectedGraphicType === Station.Type"
|
||||
:ibpNameList="ibpNameList"
|
||||
></station-property>
|
||||
<!-- <train-property
|
||||
v-if="drawStore.selectedGraphicType === Train.Type"
|
||||
@ -90,7 +95,6 @@
|
||||
></spks-switch-property>
|
||||
<gated-box-property
|
||||
v-else-if="drawStore.selectedGraphicType === GatedBox.Type"
|
||||
:pslNameList="pslNameList"
|
||||
></gated-box-property>
|
||||
<esb-button-property
|
||||
v-else-if="drawStore.selectedGraphicType === EsbButton.Type"
|
||||
@ -135,6 +139,18 @@
|
||||
drawStore.selectedGraphicType === ConcentrationDividingLine.Type
|
||||
"
|
||||
/>
|
||||
<flood-gate-property
|
||||
v-else-if="drawStore.selectedGraphicType === FloodGate.Type"
|
||||
/>
|
||||
<car-washing-property
|
||||
v-else-if="drawStore.selectedGraphicType === CarWashing.Type"
|
||||
></car-washing-property>
|
||||
<garage-door-property
|
||||
v-else-if="drawStore.selectedGraphicType === GarageDoor.Type"
|
||||
></garage-door-property>
|
||||
<garage-door-box-property
|
||||
v-else-if="drawStore.selectedGraphicType === GarageDoorBox.Type"
|
||||
></garage-door-box-property>
|
||||
</q-card-section>
|
||||
</template>
|
||||
<template v-else-if="drawStore.selectedGraphics.length > 1">
|
||||
@ -152,6 +168,10 @@ import PolygonProperty from './properties/PolygonProperty.vue';
|
||||
import { Polygon } from 'src/graphics/polygon/Polygon';
|
||||
import PlatformProperty from './properties/PlatformProperty.vue';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import IbpBoxProperty from './properties/IbpBoxProperty.vue';
|
||||
import { IbpBox } from 'src/graphics/ibpBox/IbpBox';
|
||||
import PslBoxProperty from './properties/PslBoxProperty.vue';
|
||||
import { PslBox } from 'src/graphics/pslBox/PslBox';
|
||||
import ScreenDoorProperty from './properties/ScreenDoorProperty.vue';
|
||||
import { ScreenDoor } from 'src/graphics/screenDoor/ScreenDoor';
|
||||
import StationProperty from './properties/StationProperty.vue';
|
||||
@ -196,7 +216,6 @@ import CurvatureKiloMarkerProperty from './properties/CurvatureKiloMarkerPropert
|
||||
import { SlopeKiloMarker } from 'src/graphics/slopeKiloMarker/SlopeKiloMarker';
|
||||
import { Slope } from 'src/graphics/slope/Slope';
|
||||
import SlopeProperty from './properties/SlopeProperty.vue';
|
||||
import { Link } from 'src/graphics/link/Link';
|
||||
// import LinkProperty from './properties/LinkProperty.vue';
|
||||
import { Curvature } from 'src/graphics/curvature/Curvature';
|
||||
import CurvatureProperty from './properties/CurvatureProperty.vue';
|
||||
@ -208,35 +227,16 @@ import { TrackSection } from 'src/graphics/trackSection/TrackSection';
|
||||
import TrackLogicSectionProperty from './properties/TrackLogicSectionProperty.vue';
|
||||
import { TrackLogicSection } from 'src/graphics/trackLogicSection/TrackLogicSection';
|
||||
import MultipleSelectProperty from './properties/multipleSelectProperty.vue';
|
||||
import { onMounted } from 'vue';
|
||||
import { getPublishList } from 'src/api/PublishApi';
|
||||
import { PictureType } from 'src/protos/picture';
|
||||
import { DepartureTimer } from 'src/graphics/departureTimer/DepartureTimer';
|
||||
import DepartureTimerProperty from './properties/DepartureTimerProperty.vue';
|
||||
import FloodGateProperty from './properties/FloodGateProperty.vue';
|
||||
import { FloodGate } from 'src/graphics/floodGate/FloodGate';
|
||||
import GarageDoorProperty from './properties/GarageDoorProperty.vue';
|
||||
import { GarageDoor } from 'src/graphics/garageDoor/GarageDoor';
|
||||
import CarWashingProperty from './properties/CarWashingProperty.vue';
|
||||
import { CarWashing } from 'src/graphics/carWashing/CarWashing';
|
||||
import GarageDoorBoxProperty from './properties/GarageDoorBoxProperty.vue';
|
||||
import { GarageDoorBox } from 'src/graphics/garageDoorBox/GarageDoorBox';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const ibpNameList: string[] = [];
|
||||
const pslNameList: string[] = [];
|
||||
onMounted(() => {
|
||||
getPublishList({
|
||||
type: PictureType.IBP,
|
||||
category: drawStore.categoryType,
|
||||
}).then((ibpMapList) => {
|
||||
if (ibpMapList && ibpMapList.length) {
|
||||
ibpMapList.forEach((item) => {
|
||||
ibpNameList.push(item.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
getPublishList({
|
||||
type: PictureType.Psl,
|
||||
category: drawStore.categoryType,
|
||||
}).then((pslMapList) => {
|
||||
if (pslMapList && pslMapList.length) {
|
||||
pslMapList.forEach((item) => {
|
||||
pslNameList.push(item.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
49
src/components/draw-app/TccDrawProperties.vue
Normal file
49
src/components/draw-app/TccDrawProperties.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<!-- 画布或图形对象属性 -->
|
||||
<div v-if="tccDrawStore.selectedGraphics !== null">
|
||||
<q-card flat>
|
||||
<q-card-section>
|
||||
<div class="text-h6">
|
||||
{{ tccDrawStore.selectedObjName + ' 属性' }}
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator inset></q-separator>
|
||||
<template v-if="tccDrawStore.selectedGraphics.length === 0">
|
||||
<q-card-section>
|
||||
<canvas-tcc-property></canvas-tcc-property>
|
||||
</q-card-section>
|
||||
</template>
|
||||
<template v-else-if="tccDrawStore.selectedGraphics.length === 1">
|
||||
<q-card-section>
|
||||
<tcc-button-property
|
||||
v-if="tccDrawStore.selectedGraphicType === TccButton.Type"
|
||||
/>
|
||||
<tcc-text-property
|
||||
v-if="tccDrawStore.selectedGraphicType === TextContent.Type"
|
||||
/>
|
||||
<tcc-key-property
|
||||
v-else-if="tccDrawStore.selectedGraphicType === TccKey.Type"
|
||||
/>
|
||||
<tcc-handle-property
|
||||
v-else-if="tccDrawStore.selectedGraphicType === TccHandle.Type"
|
||||
/>
|
||||
</q-card-section>
|
||||
</template>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTccDrawStore } from 'src/stores/tcc-draw-store';
|
||||
import CanvasTccProperty from './properties/CanvasTccProperty.vue';
|
||||
import { TccButton } from 'src/graphics/tccButton/TccButton';
|
||||
import TccButtonProperty from './properties/TccButtonProperty.vue';
|
||||
import { TextContent } from 'src/graphics/textContent/TextContent';
|
||||
import TccTextProperty from './properties/TccTextProperty.vue';
|
||||
import { TccKey } from 'src/graphics/tccKey/TccKey';
|
||||
import TccKeyProperty from './properties/TccKeyProperty.vue';
|
||||
import { TccHandle } from 'src/graphics/tccHandle/TccHandle';
|
||||
import TccHandleProperty from './properties/TccHandleProperty.vue';
|
||||
|
||||
const tccDrawStore = useTccDrawStore();
|
||||
</script>
|
@ -1,12 +1,16 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<q-dialog ref="dialogRef">
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="添加列车"
|
||||
v-model="showAddTrainOperation"
|
||||
:width="300"
|
||||
:height="525"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<div class="text-h6">添加列车</div>
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
readonly
|
||||
:label="props.dev.type"
|
||||
@ -14,7 +18,21 @@
|
||||
/>
|
||||
<q-input
|
||||
type="number"
|
||||
dense
|
||||
outlined
|
||||
label="列车编号"
|
||||
v-model.number="trainId"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-input
|
||||
type="number"
|
||||
outlined
|
||||
label="列车初始速度(km/h)"
|
||||
:min="0"
|
||||
v-model.number="trainSpeed"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-input
|
||||
type="number"
|
||||
outlined
|
||||
:label="`列车偏移(mm)【长度${props.kmLength}mm】`"
|
||||
:max="kmLength"
|
||||
@ -26,7 +44,6 @@
|
||||
<q-select
|
||||
v-model="dir"
|
||||
label="运行方向"
|
||||
dense
|
||||
outlined
|
||||
:options="dirOptions"
|
||||
emitValue
|
||||
@ -37,7 +54,6 @@
|
||||
<q-select
|
||||
v-model="trainConfig"
|
||||
label="列车配置"
|
||||
dense
|
||||
outlined
|
||||
:options="trainConfigOption"
|
||||
:option-label="
|
||||
@ -55,39 +71,43 @@
|
||||
</q-select>
|
||||
<q-input
|
||||
type="number"
|
||||
dense
|
||||
outlined
|
||||
:label="`列车轮径(mm)【${
|
||||
trainConfig ? trainConfig.min_diameter : ''
|
||||
}-${trainConfig ? trainConfig.max_diameter : ''}mm】`"
|
||||
:max="trainConfig?.max_diameter"
|
||||
:min="trainConfig?.min_diameter"
|
||||
:label="`列车轮径(mm)【750-840mm】`"
|
||||
:max="840"
|
||||
:min="750"
|
||||
v-model.number="wheelDiameter"
|
||||
lazy-rules
|
||||
:rules="wheelDiameterRules"
|
||||
/>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn flat label="取消" @click="onDialogCancel" v-close-popup />
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showAddTrainOperation = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" :disable="!trainConfig" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm, useDialogPluginComponent } from 'quasar';
|
||||
import { TrainConfigItem } from 'src/api/TrainModelApi';
|
||||
import { QForm } from 'quasar';
|
||||
import { TrainConfigData, TrainConfigItem } from 'src/api/TrainModelApi';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, ref, onUnmounted } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { addTrain } from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
const props = defineProps({
|
||||
dev: {
|
||||
type: [Section, Turnout],
|
||||
type: Section,
|
||||
required: true,
|
||||
},
|
||||
kmLength: {
|
||||
@ -108,10 +128,10 @@ const dirOptions = [
|
||||
{ label: '上行', value: 1 },
|
||||
{ label: '下行', value: 0 },
|
||||
];
|
||||
const trainSpeed = ref(0);
|
||||
const trainId = ref(1);
|
||||
|
||||
defineEmits([...useDialogPluginComponent.emits]);
|
||||
|
||||
const { dialogRef, onDialogOK, onDialogCancel } = useDialogPluginComponent();
|
||||
const showAddTrainOperation = ref(true);
|
||||
|
||||
const offsetRules = [
|
||||
(val: string) => (val !== null && val !== '') || '偏移量不能为空!',
|
||||
@ -128,12 +148,45 @@ const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
onDialogOK({
|
||||
dir: dir.value,
|
||||
offset: offset.value,
|
||||
trainLength: trainConfig.value?.total_length,
|
||||
if (!trainConfig.value) {
|
||||
return;
|
||||
}
|
||||
const lineStore = useLineStore();
|
||||
const params = {
|
||||
simulationId: lineStore.simulationId || '',
|
||||
mapId: lineStore.mapId || 0,
|
||||
up: !!dir.value,
|
||||
id: props.dev.datas.id,
|
||||
headOffset: offset.value,
|
||||
trainId: trainId.value,
|
||||
trainSpeed: trainSpeed.value,
|
||||
wheelDiameter: wheelDiameter.value,
|
||||
trainLength: trainConfig.value.total_length,
|
||||
configTrain: trainConfig.value.trainConfigData as TrainConfigData,
|
||||
trainControlMapId: trainConfig.value.trainControlMapId,
|
||||
trainEndsA: {
|
||||
radarCheckSpeedDiff: 0,
|
||||
radarCheckTime: 0,
|
||||
radarEnable: true,
|
||||
speedSensorEnableA: true,
|
||||
speedSensorEnableB: true,
|
||||
accOutSpeed: 0,
|
||||
radarOutSpeed: 0,
|
||||
},
|
||||
trainEndsB: {
|
||||
radarCheckSpeedDiff: 0,
|
||||
radarCheckTime: 0,
|
||||
radarEnable: true,
|
||||
speedSensorEnableA: true,
|
||||
speedSensorEnableB: true,
|
||||
accOutSpeed: 0,
|
||||
radarOutSpeed: 0,
|
||||
},
|
||||
};
|
||||
addTrain(params).catch((err) => {
|
||||
errorNotify(`添加列车失败!: ${err.title}`, err);
|
||||
});
|
||||
showAddTrainOperation.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -141,13 +194,7 @@ function onCreate() {
|
||||
const wheelDiameter = ref(800);
|
||||
const wheelDiameterRules = [
|
||||
(val: string) => (val !== null && val !== '') || '列车轮径不能为空!',
|
||||
(val: number) =>
|
||||
(trainConfig.value &&
|
||||
val >= trainConfig.value.min_diameter &&
|
||||
val <= trainConfig.value.max_diameter) ||
|
||||
`列车轮径在${trainConfig.value ? trainConfig.value.min_diameter : ''}到${
|
||||
trainConfig.value ? trainConfig.value.max_diameter : ''
|
||||
}mm之间!`,
|
||||
(val: number) => (val >= 750 && val <= 840) || '列车轮径在750到840mm之间!',
|
||||
];
|
||||
|
||||
const trainConfigOption = computed(() => {
|
||||
@ -158,15 +205,17 @@ const trainConfig = ref<TrainConfigItem | null>({
|
||||
id: 0,
|
||||
carriage_length: 0,
|
||||
description: '',
|
||||
max_diameter: 0,
|
||||
min_diameter: 0,
|
||||
name: '',
|
||||
total_length: 0,
|
||||
train_model: 0,
|
||||
train_sets: '',
|
||||
trainControlMapId: 0,
|
||||
});
|
||||
function setConfigVal(val: TrainConfigItem | null) {
|
||||
trainConfig.value = val || null;
|
||||
}
|
||||
onUnmounted(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
</script>
|
||||
<style scoped></style>
|
||||
|
251
src/components/draw-app/dialogs/CiCjQdListStateDialog.vue
Normal file
251
src/components/draw-app/dialogs/CiCjQdListStateDialog.vue
Normal file
@ -0,0 +1,251 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="驱采状态"
|
||||
:width="dialogWidth"
|
||||
:height="500"
|
||||
>
|
||||
<q-tabs
|
||||
v-model="tab"
|
||||
dense
|
||||
active-color="primary"
|
||||
indicator-color="primary"
|
||||
align="justify"
|
||||
narrow-indicator
|
||||
>
|
||||
<q-tab
|
||||
v-for="(item, index) in tabList"
|
||||
:key="index"
|
||||
:name="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</q-tabs>
|
||||
<q-separator />
|
||||
<q-tab-panels v-model="tab" animated keep-alive>
|
||||
<template v-for="tabInfo in tabList" :key="tabInfo.label">
|
||||
<q-tab-panel :name="tabInfo.value">
|
||||
<div
|
||||
class="row no-wrap"
|
||||
v-for="row in showSetCellMessage.rows"
|
||||
:key="row"
|
||||
>
|
||||
<div
|
||||
class="ceil"
|
||||
:class="{
|
||||
CellGreen:
|
||||
row > 1 &&
|
||||
col > 1 &&
|
||||
tabInfo.ListMap.get(`${row - 1}-${col - 1}`),
|
||||
changeCellSize: col == 1,
|
||||
CellRed:
|
||||
row > 1 &&
|
||||
col > 1 &&
|
||||
tabInfo.ListMap.get(`${row - 1}-${col - 1}`) &&
|
||||
tabInfo.stateMap.get(`${row - 1}-${col - 1}`),
|
||||
}"
|
||||
v-for="col in showSetCellMessage.cols"
|
||||
:key="col"
|
||||
@click="handleCellClick(row, col)"
|
||||
>
|
||||
<span v-if="row == 1 && col == 1"> 位置</span>
|
||||
<span v-else-if="row == 1 || col == 1">
|
||||
{{ row == 1 ? col - 1 : row - 1 }}</span
|
||||
>
|
||||
<div
|
||||
v-else
|
||||
@mouseover="onMouseOver"
|
||||
@mouseleave="showTooltip = false"
|
||||
>
|
||||
{{ tabInfo.ListMap.get(`${row - 1}-${col - 1}`) }}
|
||||
<q-tooltip
|
||||
anchor="bottom middle"
|
||||
self="bottom middle"
|
||||
v-if="showTooltip"
|
||||
>
|
||||
{{ tabInfo.ListMap.get(`${row - 1}-${col - 1}`) }}
|
||||
</q-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-tab-panel>
|
||||
</template>
|
||||
</q-tab-panels>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { relayCabinetGraphicData } from 'src/protos/relayCabinetLayoutGraphics';
|
||||
import { refRelaysListMap, sceneCiCjQdListMap } from 'src/drawApp/relayScene';
|
||||
import { Relay } from 'src/graphics/relay/Relay';
|
||||
import { JlGraphic } from 'jl-graphic';
|
||||
import { useTestManageStore } from 'src/stores/testManage-store';
|
||||
|
||||
const testManageStore = useTestManageStore();
|
||||
const lineStore = useLineStore();
|
||||
const tab = ref('CiCj');
|
||||
const tabList = ref([
|
||||
{
|
||||
label: '采集状态',
|
||||
value: 'CiCj',
|
||||
ListMap: new Map<string, string>(),
|
||||
stateMap: new Map<string, boolean>(),
|
||||
},
|
||||
{
|
||||
label: '驱动状态',
|
||||
value: 'CiQd',
|
||||
ListMap: new Map<string, string>(),
|
||||
stateMap: new Map<string, boolean>(),
|
||||
},
|
||||
]);
|
||||
const setCellMessage = ref<{ rows: number; cols: number }>({
|
||||
rows: 32,
|
||||
cols: 8,
|
||||
});
|
||||
const showSetCellMessage = computed(() => {
|
||||
return {
|
||||
rows: setCellMessage.value.rows + 1,
|
||||
cols: setCellMessage.value.cols + 1,
|
||||
};
|
||||
});
|
||||
|
||||
let ciCjList = sceneCiCjQdListMap.get(
|
||||
`${lineStore.sceneName}+ciCjList`
|
||||
) as relayCabinetGraphicData.CiCj;
|
||||
let ciQdList = sceneCiCjQdListMap.get(
|
||||
`${lineStore.sceneName}+ciQdList`
|
||||
) as relayCabinetGraphicData.CiQd;
|
||||
|
||||
const dialogWidth = computed(() => {
|
||||
return setCellMessage.value.cols * 134 + 85;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => testManageStore.stationQc,
|
||||
(val) => {
|
||||
if (val) {
|
||||
val.cjStates.forEach((state) => {
|
||||
tabList.value[0].stateMap.set(
|
||||
`${state.row + 1}-${state.col + 1}`,
|
||||
state.on
|
||||
);
|
||||
});
|
||||
val.qdStates.forEach((state) => {
|
||||
tabList.value[1].stateMap.set(
|
||||
`${state.row + 1}-${state.col + 1}`,
|
||||
state.on
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
setCellMessage.value.rows = ciCjList.dsCount;
|
||||
setCellMessage.value.cols = ciCjList.cjList.length;
|
||||
tabList.value[0].ListMap = updateCiCjListMap();
|
||||
tabList.value[1].ListMap = updateCiQdListMap();
|
||||
});
|
||||
|
||||
function updateCiCjListMap() {
|
||||
const showCiCjListMap = new Map<string, string>();
|
||||
ciCjList?.cjList.forEach((cjDataSet, i) => {
|
||||
cjDataSet.bitList.forEach((cjData, j) => {
|
||||
const ref = cjData.refRelays.map((refRelay) => {
|
||||
const refDeviceData = refRelaysListMap.get(refRelay.relayId);
|
||||
const relay = lineStore
|
||||
.getLineApp()
|
||||
.getScene(lineStore.sceneName)
|
||||
.queryStore.queryById<Relay>(refRelay.relayId);
|
||||
const pos =
|
||||
refRelay.position == relayCabinetGraphicData.CjDataItem.PostionType.Q
|
||||
? 'Q'
|
||||
: 'H';
|
||||
if (refDeviceData?.device) {
|
||||
return `${refDeviceData.device}_${refDeviceData?.combinationtype}_${relay.datas.code}_${pos}`;
|
||||
} else {
|
||||
return `${refDeviceData?.combinationtype}_${relay.datas.code}_${pos}`;
|
||||
}
|
||||
});
|
||||
showCiCjListMap.set(`${j + 1}-${i + 1}`, ref.join('/'));
|
||||
});
|
||||
});
|
||||
return showCiCjListMap;
|
||||
}
|
||||
|
||||
function updateCiQdListMap() {
|
||||
const showCiQdListMap = new Map<string, string>();
|
||||
ciQdList?.qdList.forEach((cjDataSet, i) => {
|
||||
cjDataSet.bitList.forEach((cjData, j) => {
|
||||
const ref = cjData.refRelays.map((refRelay) => {
|
||||
const refDeviceData = refRelaysListMap.get(refRelay);
|
||||
const relay = lineStore
|
||||
.getLineApp()
|
||||
.getScene(lineStore.sceneName)
|
||||
.queryStore.queryById<Relay>(refRelay);
|
||||
if (refDeviceData?.device) {
|
||||
return `${refDeviceData.device}_${refDeviceData.combinationtype}_${relay.datas.code}`;
|
||||
} else {
|
||||
return `${refDeviceData?.combinationtype}_${relay.datas.code}`;
|
||||
}
|
||||
});
|
||||
showCiQdListMap.set(`${j + 1}-${i + 1}`, ref.join('/'));
|
||||
});
|
||||
});
|
||||
return showCiQdListMap;
|
||||
}
|
||||
|
||||
function handleCellClick(row: number, col: number) {
|
||||
if (row == 1 || col == 1) return;
|
||||
const app = lineStore.getLineApp().getScene(lineStore.sceneName);
|
||||
app.updateSelected();
|
||||
const select: JlGraphic[] = [];
|
||||
if (tab.value == 'CiCj') {
|
||||
ciCjList.cjList[col - 2].bitList[row - 2].refRelays.forEach((relay) => {
|
||||
const g = app.queryStore.queryById(relay.relayId) as Relay;
|
||||
select.push(g);
|
||||
});
|
||||
} else {
|
||||
ciQdList.qdList[col - 2].bitList[row - 2].refRelays.forEach((relayId) => {
|
||||
const g = app.queryStore.queryById(relayId) as Relay;
|
||||
select.push(g);
|
||||
});
|
||||
}
|
||||
app.updateSelected(...select);
|
||||
app.makeGraphicCenterShow(...select);
|
||||
}
|
||||
|
||||
const showTooltip = ref(false);
|
||||
function onMouseOver(e: MouseEvent) {
|
||||
if ((e.target as HTMLElement).clientHeight > 30) {
|
||||
showTooltip.value = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ceil {
|
||||
width: 120px;
|
||||
height: 30px;
|
||||
border: solid 1px red;
|
||||
margin: 7px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
}
|
||||
.changeCellSize {
|
||||
width: 40px;
|
||||
}
|
||||
.CellGreen {
|
||||
border: solid 1px green;
|
||||
background-color: green;
|
||||
}
|
||||
.CellRed {
|
||||
border: solid 1px red;
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
@ -66,6 +66,8 @@ const deviceTypeMap = {
|
||||
8: '信号机故障报警仪',
|
||||
9: '断路器',
|
||||
10: '电源屏',
|
||||
11: '车库门',
|
||||
12: '洗车机',
|
||||
};
|
||||
const columns: QTable['columns'] = [
|
||||
{
|
||||
|
167
src/components/draw-app/dialogs/DeviceSearchDialog.vue
Normal file
167
src/components/draw-app/dialogs/DeviceSearchDialog.vue
Normal file
@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<DraggableDialog seamless :height="73" title="设备检索">
|
||||
<q-card class="q-pa-sm">
|
||||
<q-select
|
||||
filled
|
||||
v-model="deviceId"
|
||||
label="设备检索"
|
||||
use-input
|
||||
hide-selected
|
||||
fill-input
|
||||
input-debounce="0"
|
||||
:options="serachDeviceList"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@filter="filterFn"
|
||||
@update:model-value="onJump"
|
||||
style="width: 450px"
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey"> 无匹配数据 </q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</q-card>
|
||||
</DraggableDialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { IDrawApp, IGraphicApp } from 'jl-graphic';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { Transponder } from 'src/graphics/transponder/Transponder';
|
||||
import { Signal } from 'src/graphics/signal/Signal';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { ScreenDoor } from 'src/graphics/screenDoor/ScreenDoor';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { SpksSwitch } from 'src/graphics/spksSwitch/SpksSwitch';
|
||||
import { GatedBox } from 'src/graphics/gatedBox/GatedBox';
|
||||
import { EsbButton } from 'src/graphics/esbButton/EsbButton';
|
||||
|
||||
interface ItemData {
|
||||
label: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
showDialog: boolean;
|
||||
app: IDrawApp | IGraphicApp;
|
||||
}>();
|
||||
|
||||
const deviceList = ref<ItemData[]>([]);
|
||||
const deviceId = ref(0);
|
||||
const serachDeviceList = ref<ItemData[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
if (props.showDialog) {
|
||||
// const graphicsList = props.app.queryStore.getAllGraphics();
|
||||
const list: ItemData[] = [];
|
||||
const qs = props.app.queryStore;
|
||||
const sections = qs.queryByType<Section>(Section.Type);
|
||||
sections.forEach((item) => {
|
||||
let station = null;
|
||||
if (item.datas.centralizedStations[0]) {
|
||||
station = qs.queryById(item.datas.centralizedStations[0]);
|
||||
}
|
||||
list.push({
|
||||
label: '区段' + item.code + (station ? '【' + station.code + '】' : ''),
|
||||
value: item.id,
|
||||
});
|
||||
});
|
||||
const transponders = qs.queryByType<Transponder>(Transponder.Type);
|
||||
transponders.forEach((item) => {
|
||||
let station = null;
|
||||
if (item.datas.centralizedStations[0]) {
|
||||
station = qs.queryById(item.datas.centralizedStations[0]);
|
||||
}
|
||||
list.push({
|
||||
label:
|
||||
'应答器' + item.code + (station ? '【' + station.code + '】' : ''),
|
||||
value: item.id,
|
||||
});
|
||||
});
|
||||
const signals = qs.queryByType<Signal>(Signal.Type);
|
||||
signals.forEach((item) => {
|
||||
let station = null;
|
||||
if (item.datas.centralizedStations[0]) {
|
||||
station = qs.queryById(item.datas.centralizedStations[0]);
|
||||
}
|
||||
list.push({
|
||||
label:
|
||||
'信号机' + item.code + (station ? '【' + station.code + '】' : ''),
|
||||
value: item.id,
|
||||
});
|
||||
});
|
||||
const turnouts = qs.queryByType<Turnout>(Turnout.Type);
|
||||
turnouts.forEach((item) => {
|
||||
let station = null;
|
||||
if (item.datas.centralizedStations[0]) {
|
||||
station = qs.queryById(item.datas.centralizedStations[0]);
|
||||
}
|
||||
list.push({
|
||||
label: '道岔' + item.code + (station ? '【' + station.code + '】' : ''),
|
||||
value: item.id,
|
||||
});
|
||||
});
|
||||
// const axleCountings = props.app.queryStore.queryByType<AxleCounting>(
|
||||
// AxleCounting.Type
|
||||
// );
|
||||
// axleCountings.forEach((item) => {
|
||||
// list.push({ label: '区段检测点' + item.code, value: item.id });
|
||||
// });
|
||||
const stations = qs.queryByType<Station>(Station.Type);
|
||||
stations.forEach((item) => {
|
||||
list.push({ label: '车站' + item.code, value: item.id });
|
||||
});
|
||||
const platforms = qs.queryByType<Platform>(Platform.Type);
|
||||
platforms.forEach((item) => {
|
||||
list.push({ label: item.code, value: item.id });
|
||||
});
|
||||
const screenDoors = qs.queryByType<ScreenDoor>(ScreenDoor.Type);
|
||||
screenDoors.forEach((item) => {
|
||||
list.push({ label: '屏蔽门' + item.code, value: item.id });
|
||||
});
|
||||
const gatedBoxs = qs.queryByType<GatedBox>(GatedBox.Type);
|
||||
gatedBoxs.forEach((item) => {
|
||||
list.push({ label: '门控箱' + item.code, value: item.id });
|
||||
});
|
||||
const esbButtons = qs.queryByType<EsbButton>(EsbButton.Type);
|
||||
esbButtons.forEach((item) => {
|
||||
list.push({ label: '紧急关闭' + item.code, value: item.id });
|
||||
});
|
||||
const spksSwitchs = qs.queryByType<SpksSwitch>(SpksSwitch.Type);
|
||||
spksSwitchs.forEach((item) => {
|
||||
list.push({ label: 'SPKS开关' + item.code, value: item.id });
|
||||
});
|
||||
deviceList.value = list;
|
||||
serachDeviceList.value = list;
|
||||
}
|
||||
});
|
||||
|
||||
function filterFn(val: string, update: any) {
|
||||
update(() => {
|
||||
serachDeviceList.value = deviceList.value.filter((v) =>
|
||||
v.label.includes(val)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function onJump(id: number) {
|
||||
const device = props.app.queryStore.queryById(id);
|
||||
props.app.makeGraphicCenterShow(device);
|
||||
props.app.updateSelected(device);
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.text {
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
padding: 5px;
|
||||
}
|
||||
.text:hover {
|
||||
color: #09f;
|
||||
}
|
||||
</style>
|
143
src/components/draw-app/dialogs/LoadTransponderData.vue
Normal file
143
src/components/draw-app/dialogs/LoadTransponderData.vue
Normal file
@ -0,0 +1,143 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="导入应答器报文数据"
|
||||
v-model="showLoadTransData"
|
||||
:width="300"
|
||||
:height="249"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<q-select
|
||||
v-model="stationId"
|
||||
label="应答器所属车站"
|
||||
outlined
|
||||
:options="stationOptions"
|
||||
emitValue
|
||||
:rules="[(val) => !!val || '应答器所属车站不能为空!']"
|
||||
mapOptions
|
||||
hint=""
|
||||
>
|
||||
</q-select>
|
||||
<q-file
|
||||
outlined
|
||||
accept=".xlsx,.xls"
|
||||
label="应答器报文数据文件"
|
||||
v-model="file"
|
||||
:rules="[(val) => !!val || '导入文件不能为空']"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="attach_file" />
|
||||
</template>
|
||||
</q-file>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showLoadTransData = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { successNotify } from 'src/utils/CommonNotify';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import * as XLSX from 'xlsx';
|
||||
import { Transponder } from 'src/graphics/transponder/Transponder';
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
const stationId = ref<number>();
|
||||
const stationOptions = ref<{ label: string; value: number }[]>([]);
|
||||
const file = ref<File | null>(null);
|
||||
|
||||
const showLoadTransData = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
const stations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Station>(Station.Type);
|
||||
const list: { label: string; value: number }[] = [];
|
||||
stations.forEach((sta) => {
|
||||
list.push({ label: sta.datas.stationName, value: sta.datas.id });
|
||||
});
|
||||
stationOptions.value = list;
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
const station = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryById<Station>(stationId.value as number);
|
||||
const stationNameAcronym = station.datas.stationNameAcronym;
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e: any) {
|
||||
const data = new Uint8Array(e.target.result);
|
||||
const workbook = XLSX.read(data, { type: 'array' });
|
||||
const sheet = workbook.Sheets['应答器报文清单'];
|
||||
const dataList = XLSX.utils.sheet_to_json(sheet) as {
|
||||
[propname: string]: string;
|
||||
}[];
|
||||
const index = dataList.findIndex((data) =>
|
||||
Object.values(data).includes('应答器编号')
|
||||
);
|
||||
const title = dataList[index];
|
||||
const titleKeys = Object.keys(title);
|
||||
const codeIndex = titleKeys.findIndex(
|
||||
(key) => title[key] === '应答器名称'
|
||||
);
|
||||
const userMessageIndex = titleKeys.findIndex(
|
||||
(key) => title[key] === '用户报文(830bits)'
|
||||
);
|
||||
const messageIndex = titleKeys.findIndex(
|
||||
(key) => title[key] === '报文(1023bits)'
|
||||
);
|
||||
dataList.forEach((data, i) => {
|
||||
if (i > index) {
|
||||
const tranCode =
|
||||
data[titleKeys[codeIndex]].split('_')[0] +
|
||||
'_' +
|
||||
stationNameAcronym;
|
||||
const transpnder = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByCodeAndType<Transponder>(
|
||||
tranCode,
|
||||
Transponder.Type
|
||||
);
|
||||
if (transpnder) {
|
||||
const datas = transpnder.datas.clone();
|
||||
datas.fixedTelegram = data[titleKeys[messageIndex]].replaceAll(
|
||||
' ',
|
||||
''
|
||||
);
|
||||
datas.fixedUserTelegram = data[
|
||||
titleKeys[userMessageIndex]
|
||||
].replaceAll(' ', '');
|
||||
transpnder.updateData(datas);
|
||||
}
|
||||
}
|
||||
});
|
||||
showLoadTransData.value = false;
|
||||
successNotify('导入应答器报文成功!');
|
||||
};
|
||||
if (file.value) {
|
||||
reader.readAsArrayBuffer(file.value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
124
src/components/draw-app/dialogs/MoveTransponder.vue
Normal file
124
src/components/draw-app/dialogs/MoveTransponder.vue
Normal file
@ -0,0 +1,124 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="移动应答器位置"
|
||||
v-model="showMoveTransponder"
|
||||
:width="300"
|
||||
:height="345"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
readonly
|
||||
label="应答器"
|
||||
v-model="props.code"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="props.coordinateSystem"
|
||||
readonly
|
||||
label="坐标系"
|
||||
></q-input>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="km"
|
||||
type="number"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="props.direction"
|
||||
:options="directionOptions"
|
||||
readonly
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
label="方向"
|
||||
></q-select>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showMoveTransponder = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { updatePositionTransponder } from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
const props = defineProps({
|
||||
code: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
coordinateSystem: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
kilometer: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
direction: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const km = ref(0);
|
||||
onMounted(() => {
|
||||
km.value = props.kilometer;
|
||||
});
|
||||
|
||||
const showMoveTransponder = ref(true);
|
||||
|
||||
const directionOptions = [
|
||||
{ label: '左行', value: 0 },
|
||||
{ label: '右行', value: 1 },
|
||||
];
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
updatePositionTransponder({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: props.id,
|
||||
km: {
|
||||
coordinateSystem: props.coordinateSystem,
|
||||
kilometer: km.value,
|
||||
direction: props.direction,
|
||||
},
|
||||
}).catch((e) => errorNotify('移动应答器失败:' + e.title, e));
|
||||
showMoveTransponder.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
onUnmounted(() => {
|
||||
useLineStore().deviceOpreratDialogInstance = null;
|
||||
});
|
||||
</script>
|
||||
<style scoped></style>
|
179
src/components/draw-app/dialogs/ScreenDoorOperation.vue
Normal file
179
src/components/draw-app/dialogs/ScreenDoorOperation.vue
Normal file
@ -0,0 +1,179 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
v-model="showSectionOperation"
|
||||
seamless
|
||||
title="屏蔽门设置参数"
|
||||
:width="380"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
readonly
|
||||
label="名称"
|
||||
v-model="props.code"
|
||||
/>
|
||||
<div
|
||||
class="q-gutter-sm"
|
||||
style="border: 1px solid #ccc; border-radius: 3px"
|
||||
>
|
||||
<div>屏蔽门强制:</div>
|
||||
<q-radio
|
||||
v-for="option in screenDoorForceOption"
|
||||
:key="option.value"
|
||||
v-model="screenDoorForce"
|
||||
:val="option.value"
|
||||
:label="option.label"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="q-gutter-sm"
|
||||
style="border: 1px solid #ccc; border-radius: 3px"
|
||||
>
|
||||
<div>设置故障:</div>
|
||||
<q-radio
|
||||
v-for="option in screenDoorFaultOption"
|
||||
:key="option.value"
|
||||
v-model="screenDoorFault"
|
||||
:val="option.value"
|
||||
:label="option.label"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="q-gutter-sm"
|
||||
style="border: 1px solid #ccc; border-radius: 3px"
|
||||
>
|
||||
<div>选择子门:</div>
|
||||
<template :key="item" v-for="item in asdOptions">
|
||||
<q-checkbox
|
||||
v-model="asdCodes"
|
||||
:val="item"
|
||||
:label="item < 10 ? '0' + item : item + ''"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showTurnoutOperation = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { screenDoorOperate } from 'src/api/Simulation';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { request } from 'src/protos/request';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
sonDoorAmount: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
asdCodesProp: {
|
||||
type: Array<number>,
|
||||
required: true,
|
||||
},
|
||||
screenDoorForceProp: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
screenDoorFaultProp: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const lineStore = useLineStore();
|
||||
const showSectionOperation = ref(true);
|
||||
const screenDoorForce = ref<request.Psd.Force>(0);
|
||||
const screenDoorForceOption = [
|
||||
{
|
||||
label: '无强制',
|
||||
value: request.Psd.Force.F_NONE,
|
||||
},
|
||||
{
|
||||
label: '强制开门',
|
||||
value: request.Psd.Force.F_ASD_KM,
|
||||
},
|
||||
{
|
||||
label: '强制关门',
|
||||
value: request.Psd.Force.F_ASD_GM,
|
||||
},
|
||||
];
|
||||
const screenDoorFault = ref<request.Psd.Fault>(0);
|
||||
const screenDoorFaultOption = [
|
||||
{
|
||||
label: '无故障',
|
||||
value: request.Psd.Fault.FA_NONE,
|
||||
},
|
||||
{
|
||||
label: '设置故障物',
|
||||
value: request.Psd.Fault.FA_Obstacle,
|
||||
},
|
||||
];
|
||||
const asdCodes = ref<number[]>([]);
|
||||
const asdOptions = ref<number[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
for (let i = 1; i <= props.sonDoorAmount; i++) {
|
||||
asdOptions.value.push(i);
|
||||
}
|
||||
asdCodes.value = props.asdCodesProp;
|
||||
screenDoorForce.value = props.screenDoorForceProp;
|
||||
screenDoorFault.value = props.screenDoorFaultProp;
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
const obj = {
|
||||
simulationId: lineStore?.simulationId || '',
|
||||
mapId: lineStore.mapId as number,
|
||||
deviceId: props.id,
|
||||
operation: request.Psd.Operation.SetParams,
|
||||
param: {
|
||||
asdCodes: asdCodes.value,
|
||||
force: screenDoorForce.value,
|
||||
fault: screenDoorFault.value,
|
||||
},
|
||||
};
|
||||
screenDoorOperate(obj).catch((e) =>
|
||||
errorNotify('屏蔽门操作失败:' + e.title, e)
|
||||
);
|
||||
showSectionOperation.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
</script>
|
||||
<style scoped></style>
|
108
src/components/draw-app/dialogs/SectionOperation.vue
Normal file
108
src/components/draw-app/dialogs/SectionOperation.vue
Normal file
@ -0,0 +1,108 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
v-model="showSectionOperation"
|
||||
seamless
|
||||
title="区段设置参数"
|
||||
:width="380"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
readonly
|
||||
label="名称"
|
||||
v-model="props.code"
|
||||
/>
|
||||
<div
|
||||
class="q-gutter-sm"
|
||||
style="border: 1px solid #ccc; border-radius: 3px"
|
||||
>
|
||||
<div>模拟CI复位/预复位:</div>
|
||||
<q-toggle v-model="mockDrst" label="是否复位" />
|
||||
<q-toggle v-model="mockPdrst" label="是否预复位" />
|
||||
</div>
|
||||
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showTurnoutOperation = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { setAxleSectionState } from 'src/api/Simulation';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { request } from 'src/protos/request';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
axleDrst: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
axlePdrst: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const lineStore = useLineStore();
|
||||
const mockDrst = ref(false);
|
||||
const mockPdrst = ref(false);
|
||||
const showSectionOperation = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
mockDrst.value = props.axleDrst;
|
||||
mockPdrst.value = props.axlePdrst;
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
const obj = {
|
||||
simulationId: lineStore?.simulationId || '',
|
||||
mapId: lineStore.mapId as number,
|
||||
deviceId: props.id,
|
||||
operation: request.Section.Operation.SetParams,
|
||||
param: {
|
||||
mockDrst: mockDrst.value,
|
||||
mockPdrst: mockPdrst.value,
|
||||
},
|
||||
};
|
||||
setAxleSectionState(obj).catch((e) =>
|
||||
errorNotify('区段操作失败:' + e.title, e)
|
||||
);
|
||||
showSectionOperation.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
</script>
|
97
src/components/draw-app/dialogs/SetTrainLink.vue
Normal file
97
src/components/draw-app/dialogs/SetTrainLink.vue
Normal file
@ -0,0 +1,97 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="列车连接"
|
||||
v-model="showLoadTransData"
|
||||
:width="300"
|
||||
:height="175"
|
||||
>
|
||||
<q-card style="width: 300px">
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<q-select
|
||||
v-model="connType"
|
||||
label="连接平台"
|
||||
outlined
|
||||
:options="connectOptions"
|
||||
emitValue
|
||||
:rules="[(val) => !!val || '连接平台不能为空!']"
|
||||
mapOptions
|
||||
hint=""
|
||||
>
|
||||
</q-select>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showLoadTransData = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { getCanLinkPlatForm, updateTrainConn } from 'src/api/Simulation';
|
||||
import { successNotify, errorNotify } from 'src/utils/CommonNotify';
|
||||
const props = defineProps({
|
||||
simulationId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
trainId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const connType = ref<number>(0);
|
||||
const connectOptions = ref<{ label: string; value: number }[]>([]);
|
||||
|
||||
const showLoadTransData = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
connectOptions.value = [];
|
||||
getCanLinkPlatForm(props.simulationId)
|
||||
.then((resp) => {
|
||||
const list: { label: string; value: number }[] = [];
|
||||
resp.data.forEach((element: { connType: number }) => {
|
||||
if (element.connType === 1) {
|
||||
list.push({ label: '半实物', value: 1 });
|
||||
} else if (element.connType === 2) {
|
||||
list.push({ label: 'PC仿真', value: 2 });
|
||||
}
|
||||
});
|
||||
connectOptions.value = list;
|
||||
})
|
||||
.catch((e) => {
|
||||
errorNotify('获取列车可连接第三方平台失败!', e);
|
||||
});
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
updateTrainConn({
|
||||
id: props.trainId + '',
|
||||
simulationId: props.simulationId,
|
||||
connType: connType.value,
|
||||
})
|
||||
.then(() => {
|
||||
successNotify('列车连接成功!');
|
||||
showLoadTransData.value = false;
|
||||
})
|
||||
.catch((e) => {
|
||||
errorNotify('列车连接失败', e);
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
598
src/components/draw-app/dialogs/SetTrainParam.vue
Normal file
598
src/components/draw-app/dialogs/SetTrainParam.vue
Normal file
@ -0,0 +1,598 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="列车设置"
|
||||
v-model="showTrainParamOperation"
|
||||
:width="1000"
|
||||
:height="722"
|
||||
>
|
||||
<q-card style="width: 1000px; height: auto">
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="float-text">1端</div>
|
||||
<div class="stroke-box">
|
||||
<div class="float-text">雷达</div>
|
||||
<div class="stroke-box">
|
||||
<div class="row">
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-xm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsA.radarCheckSpeedDiff"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsA.radarCheckSpeedDiff = 0)"
|
||||
label="雷达测速差值(m/s)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-sm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsA.radarCheckTime"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsA.radarCheckTime = 0)"
|
||||
label="雷达检测时间(秒)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-xm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsA.radarOutSpeed"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsA.radarOutSpeed = 0)"
|
||||
label="雷达速度输出(m/s)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.trainEndsA.radarEnable"
|
||||
label="雷达是否有效"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="float-text">速传</div>
|
||||
<div class="stroke-box">
|
||||
<div class="row">
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.trainEndsA.speedSensorEnableA"
|
||||
label="速传1是否有效"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.trainEndsA.speedSensorEnableB"
|
||||
label="速传2是否有效"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-xm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsA.accOutSpeed"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsA.accOutSpeed = 0)"
|
||||
label="速传速度输出(m/s)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="float-text">加速度计</div>
|
||||
<div class="stroke-box" style="margin-bottom: 10px">
|
||||
<div class="row">
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-sm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsA.accCheckSpeedDiff"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsA.accCheckSpeedDiff = 0)"
|
||||
label="加速度测速差值(米/秒)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-sm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsA.accCheckTime"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsA.accCheckTime = 0)"
|
||||
label="加速度持续时间(秒)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.trainEndsA.accEnable"
|
||||
label="加速度计是否有效"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="float-text">2端</div>
|
||||
<div class="stroke-box">
|
||||
<div class="float-text">雷达</div>
|
||||
<div class="stroke-box">
|
||||
<div class="row">
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-xm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsB.radarCheckSpeedDiff"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsB.radarCheckSpeedDiff = 0)"
|
||||
label="雷达测速差值(m/s)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-sm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsB.radarCheckTime"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsB.radarCheckTime = 0)"
|
||||
label="雷达检测时间(秒)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-xm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsB.radarOutSpeed"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsB.radarOutSpeed = 0)"
|
||||
label="雷达速度输出(m/s)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.trainEndsB.radarEnable"
|
||||
label="雷达是否有效"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="float-text">速传</div>
|
||||
<div class="stroke-box">
|
||||
<div class="row">
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.trainEndsB.speedSensorEnableA"
|
||||
label="速传1是否有效"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.trainEndsB.speedSensorEnableB"
|
||||
label="速传2是否有效"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-xm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsB.accOutSpeed"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsB.accOutSpeed = 0)"
|
||||
label="速传速度输出(m/s)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="float-text">加速度计</div>
|
||||
<div class="stroke-box" style="margin-bottom: 10px">
|
||||
<div class="row">
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-sm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsB.accCheckSpeedDiff"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsB.accCheckSpeedDiff = 0)"
|
||||
label="加速度测速差值(米/秒)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-input
|
||||
class="q-input-sm"
|
||||
outlined
|
||||
v-model.number="model.trainEndsB.accCheckTime"
|
||||
clearable
|
||||
@clear="() => (model.trainEndsB.accCheckTime = 0)"
|
||||
label="加速度持续时间(秒)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.trainEndsB.accEnable"
|
||||
label="加速度计是否有效"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="float-text">基本参数</div>
|
||||
<div class="stroke-box">
|
||||
<div class="row">
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
class="q-input--sm"
|
||||
v-model.number="model.length"
|
||||
label="列车长度(mm)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
class="q-input--sm"
|
||||
v-model.number="model.wheelDiameter"
|
||||
:label="`列车轮径(mm)【750-840mm】`"
|
||||
:max="840"
|
||||
:min="750"
|
||||
:rules="wheelDiameterRules"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
class="q-input--sm"
|
||||
v-model.number="model.configData.davisParamA"
|
||||
label="基本阻力参数A"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.davisParamB"
|
||||
label="基本阻力参数B"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.davisParamC"
|
||||
label="基本阻力参数C"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.curveResistanceParamR1"
|
||||
label="曲线阻力参数R1"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.curveResistanceParamR2"
|
||||
label="曲线阻力参数R2"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.curveResistanceParamR3"
|
||||
label="曲线阻力参数R3"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.curveResistanceParamR4"
|
||||
label="曲线阻力参数R4"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.revolvingMassParam"
|
||||
label="旋转质量参数"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="float-text">故障</div>
|
||||
<div class="stroke-box">
|
||||
<div class="row">
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.slide"
|
||||
clearable
|
||||
@clear="() => (model.configData.slide = 0)"
|
||||
label="前溜/后溜(m/s)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.slipA"
|
||||
clearable
|
||||
@clear="() => (model.configData.slipA = 0)"
|
||||
label="打滑加速度(m/s²)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.slipR"
|
||||
clearable
|
||||
@clear="() => (model.configData.slipR = 0)"
|
||||
label="打滑冲击率(m/s³)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.slipD"
|
||||
clearable
|
||||
@clear="() => (model.configData.slipD = 0)"
|
||||
label="打滑持续时间(ms)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.stopSign"
|
||||
:default-value="0"
|
||||
clearable
|
||||
@clear="() => (model.configData.stopSign = 0)"
|
||||
label="过标/欠标(mm)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.idlingA"
|
||||
clearable
|
||||
@clear="() => (model.configData.idlingA = 0)"
|
||||
label="空转加速度(m/s²)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.idlingR"
|
||||
clearable
|
||||
@clear="() => (model.configData.idlingR = 0)"
|
||||
label="空转冲击率(m/s³)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="model.configData.idlingD"
|
||||
clearable
|
||||
@clear="() => (model.configData.idlingD = 0)"
|
||||
label="空转持续时间(ms)"
|
||||
hint=""
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3 q-px-sm">
|
||||
<q-checkbox
|
||||
style="font-size: 12px"
|
||||
v-model="model.configData.jump"
|
||||
label="是否跳跃"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showTrainParamOperation = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { Train } from 'src/graphics/train/Train';
|
||||
import { ref, onMounted, reactive, onUnmounted } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { updateTrainConfig } from 'src/api/Simulation';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
const props = defineProps({
|
||||
train: {
|
||||
type: Train,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const model = reactive({
|
||||
trainId: 0,
|
||||
simulationId: '',
|
||||
trainEndsA: {
|
||||
radarCheckSpeedDiff: 0,
|
||||
radarCheckTime: 0,
|
||||
radarEnable: true,
|
||||
speedSensorEnableA: true,
|
||||
speedSensorEnableB: true,
|
||||
accEnable: true,
|
||||
accCheckSpeedDiff: 0,
|
||||
accCheckTime: 0,
|
||||
accOutSpeed: 0,
|
||||
radarOutSpeed: 0,
|
||||
},
|
||||
trainEndsB: {
|
||||
radarCheckSpeedDiff: 0,
|
||||
radarCheckTime: 0,
|
||||
radarEnable: true,
|
||||
speedSensorEnableA: true,
|
||||
speedSensorEnableB: true,
|
||||
accEnable: true,
|
||||
accCheckSpeedDiff: 0,
|
||||
accCheckTime: 0,
|
||||
accOutSpeed: 0,
|
||||
radarOutSpeed: 0,
|
||||
},
|
||||
configData: {
|
||||
davisParamA: 0,
|
||||
davisParamB: 0,
|
||||
davisParamC: 0,
|
||||
curveResistanceParamR1: 0,
|
||||
curveResistanceParamR2: 0,
|
||||
curveResistanceParamR3: 0,
|
||||
curveResistanceParamR4: 0,
|
||||
jump: false,
|
||||
revolvingMassParam: 0,
|
||||
slide: 0,
|
||||
slipA: 0,
|
||||
slipR: 0,
|
||||
slipD: 0,
|
||||
stopSign: 0,
|
||||
idlingA: 0,
|
||||
idlingR: 0,
|
||||
idlingD: 0,
|
||||
},
|
||||
length: 0,
|
||||
wheelDiameter: 0,
|
||||
});
|
||||
onMounted(() => {
|
||||
initModel();
|
||||
});
|
||||
|
||||
const wheelDiameterRules = [
|
||||
(val: string) => (val !== null && val !== '') || '列车轮径不能为空!',
|
||||
(val: number) => (val >= 750 && val <= 840) || '列车轮径在750到840mm之间!',
|
||||
];
|
||||
|
||||
const showTrainParamOperation = ref(true);
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function initModel() {
|
||||
const trainState = props.train.states;
|
||||
model.trainEndsA = {
|
||||
radarCheckSpeedDiff: trainState.aRadarCheckSpeedDiff,
|
||||
radarCheckTime: trainState.aRadarCheckTime,
|
||||
radarEnable: trainState.aRadarEnable,
|
||||
speedSensorEnableA: trainState.aSpeedSensorEnableA,
|
||||
speedSensorEnableB: trainState.aSpeedSensorEnableB,
|
||||
accEnable: trainState.aAccEnable,
|
||||
accCheckSpeedDiff: trainState.aAccCheckSpeedDiff,
|
||||
accCheckTime: trainState.aAccCheckTime,
|
||||
accOutSpeed: trainState.aAccOutSpeed,
|
||||
radarOutSpeed: trainState.aRadarOutSpeed,
|
||||
};
|
||||
model.trainEndsB = {
|
||||
radarCheckSpeedDiff: trainState.bRadarCheckSpeedDiff,
|
||||
radarCheckTime: trainState.bRadarCheckTime,
|
||||
radarEnable: trainState.bRadarEnable,
|
||||
speedSensorEnableA: trainState.bSpeedSensorEnableA,
|
||||
speedSensorEnableB: trainState.bSpeedSensorEnableB,
|
||||
accEnable: trainState.bAccEnable,
|
||||
accCheckSpeedDiff: trainState.bAccCheckSpeedDiff,
|
||||
accCheckTime: trainState.bAccCheckTime,
|
||||
accOutSpeed: trainState.bAccOutSpeed,
|
||||
radarOutSpeed: trainState.bRadarOutSpeed,
|
||||
};
|
||||
model.configData = {
|
||||
davisParamA: trainState.davisParamA,
|
||||
davisParamB: trainState.davisParamB,
|
||||
davisParamC: trainState.davisParamC,
|
||||
curveResistanceParamR1: trainState.curveResistanceParamR1,
|
||||
curveResistanceParamR2: trainState.curveResistanceParamR2,
|
||||
curveResistanceParamR3: trainState.curveResistanceParamR3,
|
||||
curveResistanceParamR4: trainState.curveResistanceParamR4,
|
||||
jump: trainState.jump,
|
||||
revolvingMassParam: trainState.revolvingMassParam,
|
||||
slide: trainState.slide,
|
||||
slipA: trainState.slipA,
|
||||
slipR: trainState.slipR,
|
||||
slipD: trainState.slipD,
|
||||
stopSign: trainState.stopSign,
|
||||
idlingA: trainState.idlingA,
|
||||
idlingR: trainState.idlingR,
|
||||
idlingD: trainState.idlingD,
|
||||
};
|
||||
model.length = trainState.trainLength;
|
||||
model.wheelDiameter = trainState.wheelDiameter;
|
||||
}
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
model.simulationId = useLineStore().simulationId || '';
|
||||
model.trainId = +props.train.states.id;
|
||||
updateTrainConfig(model).catch((err) => {
|
||||
errorNotify('列车参数失败!', err);
|
||||
});
|
||||
showTrainParamOperation.value = false;
|
||||
useLineStore().deviceOpreratDialogInstance = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
onUnmounted(() => {
|
||||
useLineStore().deviceOpreratDialogInstance = null;
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.stroke-box {
|
||||
margin: 10px 10px 0;
|
||||
border: 1px solid #ccc;
|
||||
padding: 15px 5px 0;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.float-text {
|
||||
background: #fff;
|
||||
position: relative;
|
||||
float: left;
|
||||
left: 20px;
|
||||
}
|
||||
</style>
|
262
src/components/draw-app/dialogs/SignalOperation.vue
Normal file
262
src/components/draw-app/dialogs/SignalOperation.vue
Normal file
@ -0,0 +1,262 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="信号机设置参数"
|
||||
v-model="showSignalOperation"
|
||||
:width="width"
|
||||
:height="330"
|
||||
>
|
||||
<q-card class="q-m-a-sm">
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
readonly
|
||||
label="信号机名称"
|
||||
v-model="props.code"
|
||||
/>
|
||||
<div
|
||||
class="q-gutter-sm"
|
||||
style="border: 1px solid #ccc; border-radius: 3px"
|
||||
>
|
||||
<div>信号机强制:</div>
|
||||
<q-radio
|
||||
v-for="option in signalForceOptions"
|
||||
:key="option.value"
|
||||
v-model="signalForce"
|
||||
:val="option.value"
|
||||
:label="option.label"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="q-gutter-sm"
|
||||
style="border: 1px solid #ccc; border-radius: 3px"
|
||||
>
|
||||
<div>信号机断丝:</div>
|
||||
<q-checkbox
|
||||
v-for="option in signalDsOptions"
|
||||
:key="option.value"
|
||||
v-model="signalDs"
|
||||
:val="option.value"
|
||||
:label="option.label"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showSignalOperation = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { request } from 'src/protos/request';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { onMounted, ref, computed, onUnmounted } from 'vue';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { setSignalState } from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
mt: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
param: {
|
||||
type: request.SignalParam,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const width = computed(() => {
|
||||
if (signalForceOptions.value.length === 6) {
|
||||
return 530;
|
||||
} else if (signalForceOptions.value.length === 5) {
|
||||
return 450;
|
||||
} else {
|
||||
return 400;
|
||||
}
|
||||
});
|
||||
|
||||
const signalForce = ref<request.Signal.Force>(0);
|
||||
const signalDs = ref<request.Signal.DS[]>([]);
|
||||
|
||||
interface SignalDsItem {
|
||||
label: string;
|
||||
value: request.Signal.DS;
|
||||
}
|
||||
const signalDsOptions = ref<SignalDsItem[]>([]);
|
||||
const hDs = {
|
||||
label: '红灯断丝',
|
||||
value: request.Signal.DS.DS_H,
|
||||
};
|
||||
const uDs = {
|
||||
label: '黄灯断丝',
|
||||
value: request.Signal.DS.DS_U,
|
||||
};
|
||||
const lDs = {
|
||||
label: '绿灯断丝',
|
||||
value: request.Signal.DS.DS_L,
|
||||
};
|
||||
const aDs = {
|
||||
label: '蓝灯断丝',
|
||||
value: request.Signal.DS.DS_A,
|
||||
};
|
||||
const bDs = {
|
||||
label: '白灯断丝',
|
||||
value: request.Signal.DS.DS_B,
|
||||
};
|
||||
|
||||
interface SignalForceItem {
|
||||
label: string;
|
||||
value: request.Signal.Force;
|
||||
}
|
||||
const signalForceOptions = ref<SignalForceItem[]>([]);
|
||||
const noForce = {
|
||||
label: '无强制',
|
||||
value: request.Signal.Force.SF_NONE,
|
||||
};
|
||||
const mieDeng = {
|
||||
label: '灭灯',
|
||||
value: request.Signal.Force.SF_M,
|
||||
};
|
||||
const hongDeng = {
|
||||
label: '红灯',
|
||||
value: request.Signal.Force.SF_H,
|
||||
};
|
||||
const huangDeng = {
|
||||
label: '黄灯',
|
||||
value: request.Signal.Force.SF_U,
|
||||
};
|
||||
const lvDeng = {
|
||||
label: '绿灯',
|
||||
value: request.Signal.Force.SF_L,
|
||||
};
|
||||
const huanghongDeng = {
|
||||
label: '黄红灯',
|
||||
value: request.Signal.Force.SF_HU,
|
||||
};
|
||||
const lanDeng = {
|
||||
label: '蓝灯',
|
||||
value: request.Signal.Force.SF_A,
|
||||
};
|
||||
const baiDeng = {
|
||||
label: '白灯',
|
||||
value: request.Signal.Force.SF_B,
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
signalDs.value = props.param.dsList;
|
||||
signalForce.value = props.param.force;
|
||||
switch (props.mt) {
|
||||
case graphicData.Signal.Model.HL:
|
||||
signalDsOptions.value = [hDs, lDs];
|
||||
signalForceOptions.value = [noForce, mieDeng, hongDeng, lvDeng];
|
||||
break;
|
||||
case graphicData.Signal.Model.AB:
|
||||
signalDsOptions.value = [aDs, bDs];
|
||||
signalForceOptions.value = [noForce, mieDeng, lanDeng, baiDeng];
|
||||
break;
|
||||
case graphicData.Signal.Model.HBU_DU:
|
||||
signalDsOptions.value = [hDs, bDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
baiDeng,
|
||||
huangDeng,
|
||||
];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_FU:
|
||||
signalDsOptions.value = [hDs, lDs];
|
||||
signalForceOptions.value = [noForce, mieDeng, hongDeng, lvDeng];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_DU_YY:
|
||||
signalDsOptions.value = [hDs, lDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
lvDeng,
|
||||
huangDeng,
|
||||
huanghongDeng,
|
||||
];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_YY:
|
||||
signalDsOptions.value = [hDs, lDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
lvDeng,
|
||||
huanghongDeng,
|
||||
];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_FL_DU_YY:
|
||||
signalDsOptions.value = [hDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
huangDeng,
|
||||
huanghongDeng,
|
||||
];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_DU:
|
||||
signalDsOptions.value = [hDs, lDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
lvDeng,
|
||||
huangDeng,
|
||||
];
|
||||
break;
|
||||
}
|
||||
});
|
||||
const showSignalOperation = ref(true);
|
||||
const lineStore = useLineStore();
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
const obj = {
|
||||
simulationId: lineStore.simulationId || '',
|
||||
mapId: lineStore.mapId as number,
|
||||
deviceId: props.id,
|
||||
operation: request.Points.Operation.SetParams,
|
||||
param: { force: signalForce.value, dsList: signalDs.value },
|
||||
};
|
||||
setSignalState(obj).catch((e) =>
|
||||
errorNotify('信号机操作失败:' + e.title, e)
|
||||
);
|
||||
showSignalOperation.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
</script>
|
||||
<style scoped></style>
|
89
src/components/draw-app/dialogs/TrainSearchDialog.vue
Normal file
89
src/components/draw-app/dialogs/TrainSearchDialog.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<DraggableDialog seamless :height="73" title="列车检索">
|
||||
<q-card class="q-pa-sm">
|
||||
<q-select
|
||||
filled
|
||||
v-model="deviceId"
|
||||
label="列车检索"
|
||||
use-input
|
||||
hide-selected
|
||||
fill-input
|
||||
input-debounce="0"
|
||||
:options="serachTrainList"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@filter="filterFn"
|
||||
@update:model-value="onJump"
|
||||
style="width: 450px"
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey"> 无匹配数据 </q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</q-card>
|
||||
</DraggableDialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { IDrawApp, IGraphicApp } from 'jl-graphic';
|
||||
import { Train } from 'src/graphics/train/Train';
|
||||
|
||||
interface ItemData {
|
||||
label: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
showDialog: boolean;
|
||||
app: IDrawApp | IGraphicApp;
|
||||
}>();
|
||||
|
||||
const deviceList = ref<ItemData[]>([]);
|
||||
const deviceId = ref(0);
|
||||
const serachTrainList = ref<ItemData[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
if (props.showDialog) {
|
||||
const list: ItemData[] = [];
|
||||
const qs = props.app.queryStore;
|
||||
const trains = qs.queryByType<Train>(Train.Type);
|
||||
trains.forEach((item) => {
|
||||
list.push({
|
||||
label: '列车' + item.states.id,
|
||||
value: item.id,
|
||||
});
|
||||
});
|
||||
|
||||
deviceList.value = list;
|
||||
serachTrainList.value = list;
|
||||
}
|
||||
});
|
||||
|
||||
function filterFn(val: string, update: any) {
|
||||
update(() => {
|
||||
serachTrainList.value = deviceList.value.filter((v) =>
|
||||
v.label.includes(val)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function onJump(id: number) {
|
||||
const device = props.app.queryStore.queryById(id);
|
||||
props.app.makeGraphicCenterShow(device);
|
||||
props.app.updateSelected(device);
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.text {
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
padding: 5px;
|
||||
}
|
||||
.text:hover {
|
||||
color: #09f;
|
||||
}
|
||||
</style>
|
123
src/components/draw-app/dialogs/TurnoutOperation.vue
Normal file
123
src/components/draw-app/dialogs/TurnoutOperation.vue
Normal file
@ -0,0 +1,123 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
v-model="showTurnoutOperation"
|
||||
seamless
|
||||
title="道岔设置参数"
|
||||
:width="380"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
readonly
|
||||
label="名称"
|
||||
v-model="props.code"
|
||||
/>
|
||||
<div
|
||||
class="q-gutter-sm"
|
||||
style="border: 1px solid #ccc; border-radius: 3px"
|
||||
>
|
||||
<div>道岔强制:</div>
|
||||
<q-radio
|
||||
v-for="option in turnoutForceOption"
|
||||
:key="option.value"
|
||||
v-model="turnoutForce"
|
||||
:val="option.value"
|
||||
:label="option.label"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showTurnoutOperation = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { SetSwitchParams, setSwitchPosition } from 'src/api/Simulation';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { request } from 'src/protos/request';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
force: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const lineStore = useLineStore();
|
||||
const showTurnoutOperation = ref(true);
|
||||
const turnoutForce = ref<request.Points.Force>(0);
|
||||
const turnoutForceOption = [
|
||||
{
|
||||
label: '无强制',
|
||||
value: request.Points.Force.FP_NONE,
|
||||
},
|
||||
{
|
||||
label: '定位',
|
||||
value: request.Points.Force.FP_DW,
|
||||
},
|
||||
{
|
||||
label: '反位',
|
||||
value: request.Points.Force.FP_FW,
|
||||
},
|
||||
{
|
||||
label: '失表',
|
||||
value: request.Points.Force.FP_SB,
|
||||
},
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
turnoutForce.value = props.force;
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
const obj: SetSwitchParams = {
|
||||
simulationId: lineStore?.simulationId || '',
|
||||
mapId: lineStore.mapId as number,
|
||||
deviceId: props.id,
|
||||
operation: request.Points.Operation.SetParams,
|
||||
param: { forcePosition: turnoutForce.value },
|
||||
};
|
||||
setSwitchPosition(obj).catch((e) =>
|
||||
errorNotify('道岔操作失败:' + e.title, e)
|
||||
);
|
||||
showTurnoutOperation.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
</script>
|
||||
<style scoped></style>
|
220
src/components/draw-app/dialogs/UpdateMessageTransponder.vue
Normal file
220
src/components/draw-app/dialogs/UpdateMessageTransponder.vue
Normal file
@ -0,0 +1,220 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<template>
|
||||
<draggable-dialog
|
||||
seamless
|
||||
title="修改应答器报文"
|
||||
v-model="showUpdateMessage"
|
||||
:width="400"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<q-card style="width: 400px">
|
||||
<q-card-section>
|
||||
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
readonly
|
||||
label="应答器"
|
||||
v-model="props.code"
|
||||
/>
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
label="固定用户报文"
|
||||
autogrow
|
||||
counter
|
||||
:rules="[
|
||||
(val) => {
|
||||
return validateUserMessage(val);
|
||||
},
|
||||
]"
|
||||
v-model="fixedUserTelegramData"
|
||||
/>
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
label="固定报文"
|
||||
autogrow
|
||||
counter
|
||||
:rules="[
|
||||
(val) => {
|
||||
return validateMessage(val);
|
||||
},
|
||||
]"
|
||||
v-model="fixedTelegramData"
|
||||
/>
|
||||
<q-input
|
||||
v-if="
|
||||
props.type === TransponderTypeEnum.VB ||
|
||||
props.type === TransponderTypeEnum.IB
|
||||
"
|
||||
dense
|
||||
outlined
|
||||
label="可变用户报文"
|
||||
autogrow
|
||||
counter
|
||||
:rules="[
|
||||
(val) => {
|
||||
return validateVMessage(val);
|
||||
},
|
||||
]"
|
||||
v-model="variableUserTelegramData"
|
||||
/>
|
||||
<q-input
|
||||
v-if="
|
||||
props.type === TransponderTypeEnum.VB ||
|
||||
props.type === TransponderTypeEnum.IB
|
||||
"
|
||||
dense
|
||||
outlined
|
||||
label="可变报文"
|
||||
autogrow
|
||||
counter
|
||||
:rules="[
|
||||
(val) => {
|
||||
return validateVMessage(val);
|
||||
},
|
||||
]"
|
||||
v-model="variableTelegramData"
|
||||
/>
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn
|
||||
flat
|
||||
label="取消"
|
||||
@click="showUpdateMessage = false"
|
||||
v-close-popup
|
||||
/>
|
||||
<q-btn flat label="确认" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QForm } from 'quasar';
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { updateMessageTransponder } from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { TransponderTypeEnum } from 'src/graphics/transponder/Transponder';
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
fixedTelegram: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
fixedUserTelegram: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
variableTelegram: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
variableUserTelegram: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const showUpdateMessage = ref(true);
|
||||
const fixedTelegramData = ref('');
|
||||
const fixedUserTelegramData = ref('');
|
||||
const variableTelegramData = ref('');
|
||||
const variableUserTelegramData = ref('');
|
||||
onMounted(() => {
|
||||
fixedTelegramData.value = props.fixedTelegram;
|
||||
fixedUserTelegramData.value = props.fixedUserTelegram;
|
||||
variableTelegramData.value = props.variableTelegram;
|
||||
variableUserTelegramData.value = props.variableUserTelegram;
|
||||
});
|
||||
|
||||
const myForm = ref<QForm | null>(null);
|
||||
function onCreate() {
|
||||
myForm.value?.validate().then(async (res) => {
|
||||
if (res) {
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
updateMessageTransponder({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: props.id,
|
||||
fixedTelegram: fixedTelegramData.value,
|
||||
fixedUserTelegram: fixedUserTelegramData.value,
|
||||
variableTelegram: variableTelegramData.value,
|
||||
variableUserTelegram: variableUserTelegramData.value,
|
||||
}).catch((e) => errorNotify('修改应答器报文失败:' + e.title, e));
|
||||
showUpdateMessage.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
useLineStore().deviceOpreratDialogInstance = null;
|
||||
});
|
||||
|
||||
function validateUserMessage(val: string) {
|
||||
if (val.length !== 208) {
|
||||
return '报文长度应为208个字符!';
|
||||
}
|
||||
return validateBMessage(val);
|
||||
}
|
||||
function validateMessage(val: string) {
|
||||
if (val.length !== 256) {
|
||||
return '报文长度应为256个字符!';
|
||||
}
|
||||
return validateBMessage(val);
|
||||
}
|
||||
function validateVMessage(val: string) {
|
||||
if (!val) {
|
||||
return '请填写报文内容!';
|
||||
}
|
||||
if (val.length % 2 === 1) {
|
||||
return '请填写报文内容数据长度应为偶数!';
|
||||
}
|
||||
return validateBMessage(val);
|
||||
}
|
||||
function validateBMessage(val: string) {
|
||||
const list = [
|
||||
'0',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
];
|
||||
const falg = val.split('').some((elem) => !list.includes(elem));
|
||||
if (falg) {
|
||||
return '报文格式错误:字符应为【0-F】的十六进制数';
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
@ -43,30 +43,77 @@
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-toggle
|
||||
v-model="canvas.gridBackground.hasGrid"
|
||||
label="是否有网格背景"
|
||||
emit-value
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
type="number"
|
||||
v-if="canvas.gridBackground.hasGrid"
|
||||
v-model.number="canvas.gridBackground.space"
|
||||
@blur="onUpdate"
|
||||
label="网格间距"
|
||||
lazy-rules
|
||||
:rules="[(val) => val >= 0 || '画布高必须大于0']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-if="canvas.gridBackground.hasGrid"
|
||||
v-model="canvas.gridBackground.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
|
||||
:model-value="canvas.gridBackground.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
canvas.gridBackground.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useIBPDrawStore } from 'src/stores/ibp-draw-store';
|
||||
import { onMounted, onUnmounted, reactive } from 'vue';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
const ibpDrawStore = useIBPDrawStore();
|
||||
|
||||
const canvas = reactive({
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
backgroundColor: '#ffffff',
|
||||
backgroundColor: '#706e6e',
|
||||
gridBackground: {
|
||||
hasGrid: false,
|
||||
lineColor: '#c2aeae',
|
||||
space: 50,
|
||||
},
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// console.log('画布属性表单mounted');
|
||||
const jc = ibpDrawStore.getJlCanvas();
|
||||
canvas.width = jc.properties.width;
|
||||
canvas.height = jc.properties.height;
|
||||
canvas.backgroundColor = jc.properties.backgroundColor;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// console.log('画布属性表单unmounted');
|
||||
setTimeout(() => {
|
||||
const jc = ibpDrawStore.getJlCanvas();
|
||||
canvas.width = jc.properties.width;
|
||||
canvas.height = jc.properties.height;
|
||||
canvas.backgroundColor = jc.properties.backgroundColor;
|
||||
if (jc.properties.gridBackground) {
|
||||
canvas.gridBackground = jc.properties.gridBackground;
|
||||
}
|
||||
onUpdate();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
|
80
src/components/draw-app/properties/CanvasTccProperty.vue
Normal file
80
src/components/draw-app/properties/CanvasTccProperty.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="canvas.width"
|
||||
@blur="onUpdate"
|
||||
label="画布宽 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '画布宽必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
type="number"
|
||||
v-model.number="canvas.height"
|
||||
@blur="onUpdate"
|
||||
label="画布高 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => val > 0 || '画布高必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
v-model="canvas.backgroundColor"
|
||||
@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
|
||||
:model-value="canvas.backgroundColor"
|
||||
@change="
|
||||
(val) => {
|
||||
canvas.backgroundColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTccDrawStore } from 'src/stores/tcc-draw-store';
|
||||
import { onMounted, onUnmounted, reactive } from 'vue';
|
||||
const tccDrawStore = useTccDrawStore();
|
||||
|
||||
const canvas = reactive({
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
backgroundColor: '#ffffff',
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// console.log('画布属性表单mounted');
|
||||
const jc = tccDrawStore.getJlCanvas();
|
||||
canvas.width = jc.properties.width;
|
||||
canvas.height = jc.properties.height;
|
||||
canvas.backgroundColor = jc.properties.backgroundColor;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// console.log('画布属性表单unmounted');
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
// console.log('画布属性更新');
|
||||
const app = tccDrawStore.getDrawApp();
|
||||
app.updateCanvasAndRecord({
|
||||
...canvas,
|
||||
viewportTransform: app.canvas.properties.viewportTransform,
|
||||
});
|
||||
}
|
||||
</script>
|
100
src/components/draw-app/properties/CarWashingProperty.vue
Normal file
100
src/components/draw-app/properties/CarWashingProperty.vue
Normal file
@ -0,0 +1,100 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="carWashingModel.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
class="q-mt-sm"
|
||||
v-model="carWashingModel.code"
|
||||
@blur="onUpdate"
|
||||
label="名称"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="carWashingModel.linkSection"
|
||||
:options="sectionList"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="关联区段"
|
||||
></q-select>
|
||||
<q-field class="q-mt-lg" outlined label="所属集中站" stack-label>
|
||||
<template #control>
|
||||
<q-chip
|
||||
color="primary"
|
||||
text-color="white"
|
||||
v-for="(id, index) in carWashingModel.centralizedStations"
|
||||
:key="index"
|
||||
removable
|
||||
@remove="removeStation(index)"
|
||||
square
|
||||
>{{ getName(id) }}</q-chip
|
||||
>
|
||||
<q-btn round color="primary" size="xs" icon="add" @click="addStation" />
|
||||
</template>
|
||||
</q-field>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { CarWashingData } from 'src/drawApp/graphics/CarWashingInteraction';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import AddCentralizedStationDialog from '../dialogs/AddCentralizedStationDialog.vue';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const sectionList: { label: string; value: number }[] = reactive([]);
|
||||
|
||||
const { data: carWashingModel, onUpdate } = useFormData(
|
||||
new CarWashingData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const sections = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Section>(Section.Type);
|
||||
sections.forEach((p) => {
|
||||
sectionList.push({
|
||||
value: p.id,
|
||||
label: `${p.datas.code}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
function removeStation(index: number) {
|
||||
carWashingModel.centralizedStations.splice(index, 1);
|
||||
onUpdate();
|
||||
}
|
||||
const $q = useQuasar();
|
||||
function addStation() {
|
||||
$q.dialog({
|
||||
title: '',
|
||||
message: '',
|
||||
component: AddCentralizedStationDialog,
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk((data: number) => {
|
||||
carWashingModel.centralizedStations.push(data);
|
||||
onUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
function getName(id: number) {
|
||||
try {
|
||||
const station = drawStore.getDrawApp().queryStore.queryById<Station>(id);
|
||||
return station.datas.code;
|
||||
} catch (error) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
</script>
|
95
src/components/draw-app/properties/FloodGateProperty.vue
Normal file
95
src/components/draw-app/properties/FloodGateProperty.vue
Normal file
@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="floodGateModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
class="q-mt-sm"
|
||||
v-model="floodGateModel.code"
|
||||
@blur="onUpdate"
|
||||
label="名称"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="floodGateModel.linkSection"
|
||||
:options="sectionList"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="关联区段"
|
||||
></q-select>
|
||||
<q-field class="q-mt-lg" outlined label="所属集中站" stack-label>
|
||||
<template #control>
|
||||
<q-chip
|
||||
color="primary"
|
||||
text-color="white"
|
||||
v-for="(id, index) in floodGateModel.centralizedStations"
|
||||
:key="index"
|
||||
removable
|
||||
@remove="removeStation(index)"
|
||||
square
|
||||
>{{ getName(id) }}</q-chip
|
||||
>
|
||||
<q-btn round color="primary" size="xs" icon="add" @click="addStation" />
|
||||
</template>
|
||||
</q-field>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { FloodGateData } from 'src/drawApp/graphics/FloodGateInteraction';
|
||||
import AddCentralizedStationDialog from '../dialogs/AddCentralizedStationDialog.vue';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const sectionList: { label: string; value: number }[] = reactive([]);
|
||||
|
||||
const { data: floodGateModel, onUpdate } = useFormData(
|
||||
new FloodGateData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const sections = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Section>(Section.Type);
|
||||
sections.forEach((p) => {
|
||||
sectionList.push({
|
||||
value: p.id,
|
||||
label: `${p.datas.code}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function removeStation(index: number) {
|
||||
floodGateModel.centralizedStations.splice(index, 1);
|
||||
onUpdate();
|
||||
}
|
||||
const $q = useQuasar();
|
||||
function addStation() {
|
||||
$q.dialog({
|
||||
title: '',
|
||||
message: '',
|
||||
component: AddCentralizedStationDialog,
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk((data: number) => {
|
||||
floodGateModel.centralizedStations.push(data);
|
||||
onUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
function getName(id: number) {
|
||||
try {
|
||||
const station = drawStore.getDrawApp().queryStore.queryById<Station>(id);
|
||||
return station.datas.code;
|
||||
} catch (error) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
</script>
|
78
src/components/draw-app/properties/GarageDoorBoxProperty.vue
Normal file
78
src/components/draw-app/properties/GarageDoorBoxProperty.vue
Normal file
@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="garageDoorBoxModel.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
class="q-mt-sm"
|
||||
v-model="garageDoorBoxModel.code"
|
||||
@blur="onUpdate"
|
||||
label="编号"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
class="q-mt-sm"
|
||||
style="margin-top: 10px"
|
||||
v-model="garageDoorBoxModel.refGarageDoorId"
|
||||
:options="garageDoorList"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="关联屏蔽门"
|
||||
></q-select>
|
||||
<q-select
|
||||
outlined
|
||||
class="q-mt-sm"
|
||||
@blur="onUpdate"
|
||||
v-model="garageDoorBoxModel.refPslMapCode"
|
||||
:options="pslNameList"
|
||||
label="关联PSL地图"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { GarageDoorBoxData } from 'src/drawApp/graphics/GarageDoorBoxInteraction';
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { getPublishList } from 'src/api/PublishApi';
|
||||
import { PictureType } from 'src/protos/picture';
|
||||
import { GarageDoor } from 'src/graphics/garageDoor/GarageDoor';
|
||||
|
||||
const { data: garageDoorBoxModel, onUpdate } = useFormData(
|
||||
new GarageDoorBoxData(),
|
||||
useDrawStore().getDrawApp()
|
||||
);
|
||||
|
||||
const garageDoorList: { label: string; value: number }[] = reactive([]);
|
||||
const pslNameList = ref<string[]>([]);
|
||||
onMounted(() => {
|
||||
const list2: string[] = [];
|
||||
getPublishList({
|
||||
type: PictureType.Psl,
|
||||
category: useDrawStore().categoryType,
|
||||
}).then((pslMapList) => {
|
||||
if (pslMapList && pslMapList.length) {
|
||||
pslMapList.forEach((item) => {
|
||||
list2.push(item.name);
|
||||
});
|
||||
}
|
||||
pslNameList.value = list2;
|
||||
});
|
||||
const garageDoors = useDrawStore()
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<GarageDoor>(GarageDoor.Type);
|
||||
garageDoors.forEach((p) => {
|
||||
garageDoorList.push({
|
||||
value: p.id,
|
||||
label: `${p.datas.code}[${p.datas.id}]`,
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
101
src/components/draw-app/properties/GarageDoorProperty.vue
Normal file
101
src/components/draw-app/properties/GarageDoorProperty.vue
Normal file
@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="garageDoorModel.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
class="q-mt-sm"
|
||||
v-model="garageDoorModel.code"
|
||||
@blur="onUpdate"
|
||||
label="名称"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="garageDoorModel.linkSection"
|
||||
:options="sectionList"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="关联区段"
|
||||
></q-select>
|
||||
<q-field class="q-mt-lg" outlined label="所属集中站" stack-label>
|
||||
<template #control>
|
||||
<q-chip
|
||||
color="primary"
|
||||
text-color="white"
|
||||
v-for="(id, index) in garageDoorModel.centralizedStations"
|
||||
:key="index"
|
||||
removable
|
||||
@remove="removeStation(index)"
|
||||
square
|
||||
>{{ getName(id) }}</q-chip
|
||||
>
|
||||
<q-btn round color="primary" size="xs" icon="add" @click="addStation" />
|
||||
</template>
|
||||
</q-field>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
import { GarageDoorData } from 'src/drawApp/graphics/GarageDoorInteraction';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import AddCentralizedStationDialog from '../dialogs/AddCentralizedStationDialog.vue';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const sectionList: { label: string; value: number }[] = reactive([]);
|
||||
|
||||
const { data: garageDoorModel, onUpdate } = useFormData(
|
||||
new GarageDoorData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const sections = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Section>(Section.Type);
|
||||
sections.forEach((p) => {
|
||||
sectionList.push({
|
||||
value: p.id,
|
||||
label: `${p.datas.code}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
const $q = useQuasar();
|
||||
function removeStation(index: number) {
|
||||
garageDoorModel.centralizedStations.splice(index, 1);
|
||||
onUpdate();
|
||||
}
|
||||
|
||||
function addStation() {
|
||||
$q.dialog({
|
||||
title: '',
|
||||
message: '',
|
||||
component: AddCentralizedStationDialog,
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk((data: number) => {
|
||||
garageDoorModel.centralizedStations.push(data);
|
||||
onUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
function getName(id: number) {
|
||||
try {
|
||||
const station = drawStore.getDrawApp().queryStore.queryById<Station>(id);
|
||||
return station.datas.code;
|
||||
} catch (error) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
</script>
|
@ -24,7 +24,7 @@
|
||||
class="q-mt-sm"
|
||||
@blur="onUpdate"
|
||||
v-model="gatedBoxModel.refGatedBoxMapCode"
|
||||
:options="props.pslNameList"
|
||||
:options="pslNameList"
|
||||
label="关联PSL地图"
|
||||
/>
|
||||
</q-form>
|
||||
@ -34,24 +34,31 @@
|
||||
import { GatedBoxData } from 'src/drawApp/graphics/GatedBoxInteraction';
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, defineProps } from 'vue';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ScreenDoor } from 'src/graphics/screenDoor/ScreenDoor';
|
||||
import { getPublishList } from 'src/api/PublishApi';
|
||||
import { PictureType } from 'src/protos/picture';
|
||||
|
||||
const { data: gatedBoxModel, onUpdate } = useFormData(
|
||||
new GatedBoxData(),
|
||||
useDrawStore().getDrawApp()
|
||||
);
|
||||
|
||||
const props = defineProps({
|
||||
pslNameList: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const screenDoorList: { label: string; value: number }[] = reactive([]);
|
||||
|
||||
const pslNameList = ref<string[]>([]);
|
||||
onMounted(() => {
|
||||
const list2: string[] = [];
|
||||
getPublishList({
|
||||
type: PictureType.Psl,
|
||||
category: useDrawStore().categoryType,
|
||||
}).then((pslMapList) => {
|
||||
if (pslMapList && pslMapList.length) {
|
||||
pslMapList.forEach((item) => {
|
||||
list2.push(item.name);
|
||||
});
|
||||
}
|
||||
pslNameList.value = list2;
|
||||
});
|
||||
const screenDoors = useDrawStore()
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<ScreenDoor>(ScreenDoor.Type);
|
||||
|
72
src/components/draw-app/properties/IbpBoxProperty.vue
Normal file
72
src/components/draw-app/properties/IbpBoxProperty.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="IbpBoxModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="IbpBoxModel.code"
|
||||
@blur="onUpdate"
|
||||
label="编号"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="IbpBoxModel.refStationId"
|
||||
:options="stationList"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="关联车站"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
class="q-mt-md"
|
||||
@blur="onUpdate"
|
||||
v-model="IbpBoxModel.refIbpMapCode"
|
||||
:options="ibpNameList"
|
||||
label="关联IBP地图"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getPublishList } from 'src/api/PublishApi';
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { IbpBoxData } from 'src/drawApp/graphics/IbpBoxInteraction';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { PictureType } from 'src/protos/picture';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const { data: IbpBoxModel, onUpdate } = useFormData(
|
||||
new IbpBoxData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
const stationList: { label: string; value: number }[] = reactive([]);
|
||||
const ibpNameList = ref<string[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
const list1: string[] = [];
|
||||
getPublishList({
|
||||
type: PictureType.IBP,
|
||||
category: drawStore.categoryType,
|
||||
}).then((ibpMapList) => {
|
||||
if (ibpMapList && ibpMapList.length) {
|
||||
ibpMapList.forEach((item) => {
|
||||
list1.push(item.name);
|
||||
});
|
||||
ibpNameList.value = list1;
|
||||
}
|
||||
});
|
||||
const stations = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Station>(Station.Type);
|
||||
stations.forEach((p) => {
|
||||
stationList.push({
|
||||
value: p.id,
|
||||
label: `${p.datas.code}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
72
src/components/draw-app/properties/PslBoxProperty.vue
Normal file
72
src/components/draw-app/properties/PslBoxProperty.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="IbpBoxModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="IbpBoxModel.code"
|
||||
@blur="onUpdate"
|
||||
label="编号"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="IbpBoxModel.refPlatformId"
|
||||
:options="stationList"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="关联站台"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
class="q-mt-md"
|
||||
@blur="onUpdate"
|
||||
v-model="IbpBoxModel.refPslMapCode"
|
||||
:options="pslNameList"
|
||||
label="关联PSL地图"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getPublishList } from 'src/api/PublishApi';
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { PslBoxData } from 'src/drawApp/graphics/PslBoxInteraction';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { PictureType } from 'src/protos/picture';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const { data: IbpBoxModel, onUpdate } = useFormData(
|
||||
new PslBoxData(),
|
||||
drawStore.getDrawApp()
|
||||
);
|
||||
const stationList: { label: string; value: number }[] = reactive([]);
|
||||
const pslNameList = ref<string[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
const list2: string[] = [];
|
||||
getPublishList({
|
||||
type: PictureType.Psl,
|
||||
category: useDrawStore().categoryType,
|
||||
}).then((pslMapList) => {
|
||||
if (pslMapList && pslMapList.length) {
|
||||
pslMapList.forEach((item) => {
|
||||
list2.push(item.name);
|
||||
});
|
||||
}
|
||||
pslNameList.value = list2;
|
||||
});
|
||||
const platforms = drawStore
|
||||
.getDrawApp()
|
||||
.queryStore.queryByType<Platform>(Platform.Type);
|
||||
platforms.forEach((p) => {
|
||||
stationList.push({
|
||||
value: p.id,
|
||||
label: `${p.datas.code}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
@ -86,6 +86,8 @@ const optionsType = [
|
||||
},
|
||||
{ label: '断路器', value: graphicData.RelatedRef.DeviceType.Breakers },
|
||||
{ label: '电源屏', value: graphicData.RelatedRef.DeviceType.PowerScreen },
|
||||
{ label: '车库门', value: graphicData.RelatedRef.DeviceType.GarageDoor },
|
||||
{ label: '洗车机', value: graphicData.RelatedRef.DeviceType.CarWashing },
|
||||
];
|
||||
|
||||
const noShowType = [
|
||||
|
@ -32,14 +32,9 @@ const upDownOptions = [
|
||||
];
|
||||
|
||||
function setSignalDirection(signal: Signal, v1: { x: number; y: number }) {
|
||||
const p1 = signal.lampMainBody.getPositionOnCanvas();
|
||||
const p2 = signal.lampMainBody.localToCanvasPoint(
|
||||
new Point(
|
||||
signal.lampMainBody.lamps[0].radiusX,
|
||||
signal.lampMainBody.lamps[0].radiusY
|
||||
)
|
||||
);
|
||||
const v2 = { x: p1.x - p2.x, y: p1.y - p2.y };
|
||||
const b1 = signal.lampMainBody.lampPost.getBounds();
|
||||
const b2 = signal.lampMainBody.lamps.getBounds();
|
||||
const v2 = { x: b1.x - b2.x, y: b1.y - b2.y };
|
||||
const dotProduct = v1.x * v2.x + v1.y * v2.y;
|
||||
let length1 = Math.sqrt(v1.x * v1.x + v1.y * v1.y);
|
||||
let length2 = Math.sqrt(v2.x * v2.x + v2.y * v2.y);
|
||||
|
@ -19,6 +19,15 @@
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="车站名拼音简写"
|
||||
type="textarea"
|
||||
@blur="onUpdate"
|
||||
v-model="stationModel.stationNameAcronym"
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item no-wrap class="q-gutter-y-sm column">
|
||||
<template v-if="stationModel.kilometerSystem">
|
||||
@ -74,14 +83,6 @@
|
||||
emit-value
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
class="q-mt-md"
|
||||
@blur="onUpdate"
|
||||
v-model="stationModel.refIbpMapCode"
|
||||
:options="props.ibpNameList"
|
||||
label="关联IBP地图"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
@ -90,17 +91,9 @@ 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 { defineProps, onMounted, watchEffect } from 'vue';
|
||||
import { onMounted, watchEffect } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
const props = defineProps({
|
||||
ibpNameList: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { data: stationModel, onUpdate } = useFormData(
|
||||
new StationData(),
|
||||
drawStore.getDrawApp()
|
||||
@ -110,7 +103,6 @@ const directionOptions = [
|
||||
{ label: '左行', value: 0 },
|
||||
{ label: '右行', value: 1 },
|
||||
];
|
||||
|
||||
let optionsStations: { label: string; value: number }[] = [];
|
||||
|
||||
watchEffect(() => {
|
||||
|
28
src/components/draw-app/properties/TccButtonProperty.vue
Normal file
28
src/components/draw-app/properties/TccButtonProperty.vue
Normal file
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="tccButtonModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model="tccButtonModel.code"
|
||||
@blur="onUpdate"
|
||||
label="紧急制动按钮"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-checkbox
|
||||
v-model="tccButtonModel.isSelfReset"
|
||||
label="是否自复位"
|
||||
@update:model-value="onUpdate"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TccButtonData } from 'src/drawApp/graphics/TccButtonInteraction';
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { useTccDrawStore } from 'src/stores/tcc-draw-store';
|
||||
|
||||
const { data: tccButtonModel, onUpdate } = useFormData(
|
||||
new TccButtonData(),
|
||||
useTccDrawStore().getDrawApp()
|
||||
);
|
||||
</script>
|
24
src/components/draw-app/properties/TccHandleProperty.vue
Normal file
24
src/components/draw-app/properties/TccHandleProperty.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="tccHandleModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model="tccHandleModel.code"
|
||||
@blur="onUpdate"
|
||||
label="Tcc手柄"
|
||||
lazy-rules
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TccHandleData } from 'src/drawApp/graphics/TccHandleInteraction';
|
||||
import { useTccDrawStore } from 'src/stores/tcc-draw-store';
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
|
||||
const tccDrawStore = useTccDrawStore();
|
||||
const { data: tccHandleModel, onUpdate } = useFormData(
|
||||
new TccHandleData(),
|
||||
tccDrawStore.getDrawApp()
|
||||
);
|
||||
</script>
|
44
src/components/draw-app/properties/TccKeyProperty.vue
Normal file
44
src/components/draw-app/properties/TccKeyProperty.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="tccKeyModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model="tccKeyModel.code"
|
||||
@blur="onUpdate"
|
||||
label="Tcc钥匙"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
v-model="tccKeyModel.type"
|
||||
:options="optionsKeyType"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="Tcc钥匙类型"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TccKeyData } from 'src/drawApp/graphics/TccKeyInteraction';
|
||||
import { useTccDrawStore } from 'src/stores/tcc-draw-store';
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
import { tccGraphicData } from 'src/protos/tccGraphics';
|
||||
|
||||
const tccDrawStore = useTccDrawStore();
|
||||
const { data: tccKeyModel, onUpdate } = useFormData(
|
||||
new TccKeyData(),
|
||||
tccDrawStore.getDrawApp()
|
||||
);
|
||||
const optionsKeyType = [
|
||||
{
|
||||
label: '司控器激活端',
|
||||
value: tccGraphicData.TccKey.TccKeyType.driverControllerActivationClint,
|
||||
},
|
||||
{
|
||||
label: '前后方向控制',
|
||||
value: tccGraphicData.TccKey.TccKeyType.frontAndRearDirectionalControl,
|
||||
},
|
||||
];
|
||||
</script>
|
50
src/components/draw-app/properties/TccTextProperty.vue
Normal file
50
src/components/draw-app/properties/TccTextProperty.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="textContentModel.id" label="id" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model="textContentModel.content"
|
||||
@update:model-value="onUpdate"
|
||||
label="TCC文字内容"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="textContentModel.color"
|
||||
@blur="onUpdate"
|
||||
label="TCC文字颜色"
|
||||
lazy-rules
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
@update:model-value="onUpdate"
|
||||
v-model="textContentModel.color"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
v-model.number="textContentModel.fontSize"
|
||||
type="number"
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
label="TCC文字大小"
|
||||
lazy-rules
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TccTextData } from 'src/drawApp/graphics/TccTextContentInteraction';
|
||||
import { useTccDrawStore } from 'src/stores/tcc-draw-store';
|
||||
import { useFormData } from 'src/components/DrawAppFormUtils';
|
||||
|
||||
const tccDrawStore = useTccDrawStore();
|
||||
const { data: textContentModel, onUpdate } = useFormData(
|
||||
new TccTextData(),
|
||||
tccDrawStore.getDrawApp()
|
||||
);
|
||||
</script>
|
@ -50,6 +50,22 @@
|
||||
@update:model-value="onUpdate"
|
||||
label="应答器类型"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
class="q-mt-md"
|
||||
readonly
|
||||
autogrow
|
||||
v-model="transponderModel.fixedUserTelegram"
|
||||
label="固定用户报文"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
class="q-mt-md"
|
||||
readonly
|
||||
autogrow
|
||||
v-model="transponderModel.fixedTelegram"
|
||||
label="固定报文"
|
||||
/>
|
||||
<q-field class="q-mt-md" outlined label="关联区段" readonly stack-label>
|
||||
<template #control>
|
||||
<q-chip
|
||||
|
@ -25,6 +25,9 @@
|
||||
<spks-switch-state
|
||||
v-else-if="lineStore.selectedGraphicType === SpksSwitch.Type"
|
||||
/>
|
||||
<transponder-state
|
||||
v-else-if="lineStore.selectedGraphicType === Transponder.Type"
|
||||
></transponder-state>
|
||||
</div>
|
||||
</q-scroll-area>
|
||||
</template>
|
||||
@ -51,6 +54,8 @@ import ScreenDoorState from './states/ScreenDoorState.vue';
|
||||
import { ScreenDoor } from 'src/graphics/screenDoor/ScreenDoor';
|
||||
import SpksSwitchState from './states/SpksSwitchState.vue';
|
||||
import { SpksSwitch } from 'src/graphics/spksSwitch/SpksSwitch';
|
||||
import TransponderState from './states/TransponderState.vue';
|
||||
import { Transponder } from 'src/graphics/transponder/Transponder';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
</script>
|
||||
|
88
src/components/line-app/dialogs/ConnectInfoDialog.vue
Normal file
88
src/components/line-app/dialogs/ConnectInfoDialog.vue
Normal file
@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<draggable-dialog
|
||||
ref="dialogRef"
|
||||
@show="onDialogShow"
|
||||
seamless
|
||||
title="仿真第三方接口状态信息"
|
||||
:width="300"
|
||||
:height="0"
|
||||
>
|
||||
<template v-slot:footer>
|
||||
<q-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
@request="onRequest"
|
||||
hide-bottom
|
||||
>
|
||||
<template v-slot:body-cell-state="props">
|
||||
<q-td :props="props">
|
||||
<div :class="[props.row.state == 0 ? 'table-green' : 'table-red']">
|
||||
{{ props.row.state == 0 ? '正常' : '异常' }}
|
||||
</div>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
</template>
|
||||
</draggable-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
|
||||
import { QTable } from 'quasar';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { useTestManageStore } from 'src/stores/testManage-store';
|
||||
|
||||
const testManageStore = useTestManageStore();
|
||||
const dialogRef = ref<InstanceType<typeof DraggableDialog>>();
|
||||
const tableRef = ref<QTable>();
|
||||
enum Type {
|
||||
'未定义',
|
||||
'动力学',
|
||||
'半实物列车',
|
||||
}
|
||||
const columns: QTable['columns'] = [
|
||||
{
|
||||
name: 'type',
|
||||
label: '接口服务',
|
||||
field: (row) => Type[row.type],
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'state',
|
||||
label: '服务状态',
|
||||
field: (row) => (row.state == 0 ? '正常' : '异常'),
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
const rows = ref<state.SimulationThirdPartyApiServiceState[]>([]);
|
||||
|
||||
watch(
|
||||
() => testManageStore.connectInfo,
|
||||
() => {
|
||||
onDialogShow();
|
||||
}
|
||||
);
|
||||
|
||||
const onRequest: QTable['onRequest'] = async () => {
|
||||
const datas = testManageStore.connectInfo?.states;
|
||||
if (datas) {
|
||||
rows.value = datas;
|
||||
}
|
||||
};
|
||||
|
||||
const onDialogShow = () => {
|
||||
tableRef.value?.requestServerInteraction();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.table-red {
|
||||
color: red;
|
||||
}
|
||||
.table-green {
|
||||
color: green;
|
||||
}
|
||||
</style>
|
@ -2,48 +2,181 @@
|
||||
<q-card flat bordered>
|
||||
<q-card-section class="flex justify-between">
|
||||
<span class="text-h6">列车信息</span>
|
||||
<q-btn color="primary" label="曲线图" @click="open" />
|
||||
<div>
|
||||
<!-- <q-btn
|
||||
color="primary"
|
||||
label="设置"
|
||||
@click="setTrain"
|
||||
style="margin-right: 10px"
|
||||
/> -->
|
||||
<q-btn-dropdown color="primary" label="操作">
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="(item, index) in options"
|
||||
:key="index"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="doTrainOperation(item)"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="曲线图"
|
||||
style="margin-left: 10px"
|
||||
@click="open"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-list v-if="trainInfo" dense>
|
||||
<q-item v-for="(item, index) in list" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
<q-item-label
|
||||
:style="{
|
||||
color:
|
||||
item.key === 'conn' || item.key === 'connType'
|
||||
? trainInfo.conn
|
||||
? '#0F0'
|
||||
: '#F00'
|
||||
: '',
|
||||
}"
|
||||
>{{ item.label }}</q-item-label
|
||||
>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label>
|
||||
<q-item-label
|
||||
caption
|
||||
:style="{
|
||||
color:
|
||||
item.key === 'conn' || item.key === 'connType'
|
||||
? trainInfo.conn
|
||||
? '#0F0'
|
||||
: '#F00'
|
||||
: '',
|
||||
}"
|
||||
>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label
|
||||
>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-separator inset />
|
||||
<q-item v-for="(item, index) in list2" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-separator inset />
|
||||
<q-item v-for="(item, index) in list3" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<div class="q-gutter-y-md" style="max-width: 380px">
|
||||
<q-tabs
|
||||
v-model="tab"
|
||||
inline-label
|
||||
outside-arrows
|
||||
mobile-arrows
|
||||
class="bg-purple text-white shadow-2"
|
||||
>
|
||||
<q-tab name="tab1" label="动力学" />
|
||||
<q-tab name="tab2" label="半实物" />
|
||||
<q-tab name="tab3" label="速传" />
|
||||
<q-tab name="tab4" label="雷达" />
|
||||
<q-tab name="tab5" label="加速度计" />
|
||||
<q-tab name="tab6" label="BTM" />
|
||||
</q-tabs>
|
||||
</div>
|
||||
<q-separator />
|
||||
<q-tab-panels v-model="tab" animated>
|
||||
<q-tab-panel name="tab1">
|
||||
<q-item v-for="(item, index) in list2" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="tab2">
|
||||
<q-item v-for="(item, index) in list3" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="tab3">
|
||||
<q-item v-for="(item, index) in list4" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="tab4">
|
||||
<q-item v-for="(item, index) in list5" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="tab5">
|
||||
<q-item v-for="(item, index) in list6" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="tab6">
|
||||
<q-item v-for="(item, index) in list7" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>
|
||||
<div
|
||||
style="word-wrap: break-word; width: 150px; text-align: right"
|
||||
>
|
||||
{{
|
||||
item.formatFn
|
||||
? item.formatFn(trainInfo[item.key])
|
||||
: trainInfo[item.key]
|
||||
}}
|
||||
</div>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-tab-panel>
|
||||
</q-tab-panels>
|
||||
</q-list>
|
||||
</q-card>
|
||||
</template>
|
||||
@ -53,20 +186,29 @@ import { useLineStore } from 'src/stores/line-store';
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import SetTrainParam from 'src/components/draw-app/dialogs/SetTrainParam.vue';
|
||||
import { Dialog } from 'quasar';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import SetTrainLink from 'src/components/draw-app/dialogs/SetTrainLink.vue';
|
||||
import { useTccStore } from 'src/stores/tcc-store';
|
||||
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof ITrainState;
|
||||
formatFn?(v: ITrainState[keyof ITrainState]): string;
|
||||
}
|
||||
|
||||
const tab = ref('tab1');
|
||||
const lineStore = useLineStore();
|
||||
const trainInfo = ref<ITrainState | null>();
|
||||
const list: KeyType[] = [
|
||||
{ label: '列车索引', key: 'id' },
|
||||
{ label: '连接状态', key: 'conn', formatFn: connStateFormat },
|
||||
{ label: '连接平台', key: 'connType', formatFn: connTypeFormat },
|
||||
{ label: '列车长度', key: 'trainLength', formatFn: trainLengthFormat },
|
||||
{ label: '车头所在设备', key: 'headDeviceId', formatFn: getDeviveName },
|
||||
{ label: '车头所在设备的偏移量', key: 'headOffset', formatFn: offsetFormat },
|
||||
{ label: '车尾所在设备', key: 'tailDeviceId', formatFn: getTailDeviveName },
|
||||
{ label: '车尾所在设备的偏移量', key: 'tailOffset', formatFn: offsetFormat },
|
||||
{ label: '是否上行', key: 'runDirection', formatFn: upFormat },
|
||||
{ label: '车头方向是否上行', key: 'headDirection', formatFn: upFormat },
|
||||
{
|
||||
@ -111,14 +253,24 @@ const list2: KeyType[] = [
|
||||
{ label: '坡道阻力', key: 'rampResistance', formatFn: resistanceFormat },
|
||||
{ label: '曲线阻力', key: 'curveResistance', formatFn: resistanceFormat },
|
||||
{ label: '列车运行速度', key: 'speed', formatFn: speedFormat },
|
||||
{ label: '头车速传1速度值', key: 'headSensorSpeed1', formatFn: speedFormat },
|
||||
{ label: '头车速传2速度值', key: 'headSensorSpeed2', formatFn: speedFormat },
|
||||
{ label: '尾车速传1速度值', key: 'tailSensorSpeed1', formatFn: speedFormat },
|
||||
{ label: '尾车速传2速度值', key: 'tailSensorSpeed2', formatFn: speedFormat },
|
||||
{ label: '头车雷达速度值', key: 'headRadarSpeed', formatFn: speedFormat },
|
||||
{ label: '尾车雷达速度值', key: 'tailRadarSpeed', formatFn: speedFormat },
|
||||
// { label: '通讯中断', key: 'udpInterruption', formatFn: upFormat },
|
||||
{ label: '加速度', key: 'acceleration', formatFn: accelerationFormat },
|
||||
{ label: '基本阻力参数A', key: 'davisParamA' },
|
||||
{ label: '基本阻力参数B', key: 'davisParamB' },
|
||||
{ label: '基本阻力参数C', key: 'davisParamC' },
|
||||
{ label: '曲线阻力参数R1', key: 'curveResistanceParamR1' },
|
||||
{ label: '曲线阻力参数R2', key: 'curveResistanceParamR2' },
|
||||
{ label: '曲线阻力参数R3', key: 'curveResistanceParamR3' },
|
||||
{ label: '曲线阻力参数R4', key: 'curveResistanceParamR4' },
|
||||
{ label: '旋转质量参数', key: 'revolvingMassParam' },
|
||||
{ label: '是否跳跃', key: 'jump', formatFn: upFormat },
|
||||
{ label: '打滑加速度', key: 'slipA', formatFn: accelerationFormat },
|
||||
{ label: '打滑冲击率', key: 'slipA', formatFn: chongjilvFormat },
|
||||
{ label: '打滑持续时间', key: 'slipA', formatFn: haomiaoFormat },
|
||||
{ label: '前溜/后溜', key: 'slide', formatFn: msFormat },
|
||||
{ label: '过标/欠标', key: 'stopSign', formatFn: mmFormat },
|
||||
{ label: '空转加速度', key: 'idlingA', formatFn: accelerationFormat },
|
||||
{ label: '空转冲击率', key: 'idlingR', formatFn: chongjilvFormat },
|
||||
{ label: '空转持续时间', key: 'idlingD', formatFn: haomiaoFormat },
|
||||
];
|
||||
const list3: KeyType[] = [
|
||||
// 半实物信息
|
||||
@ -176,6 +328,74 @@ const list3: KeyType[] = [
|
||||
{ label: '整列车门关好', key: 'allDoorClose', formatFn: upFormat },
|
||||
// { label: '通讯中断', key: 'udpInterruption', formatFn: upFormat },
|
||||
];
|
||||
|
||||
const list4: KeyType[] = [
|
||||
// { label: '头车速传1速度值', key: 'headSensorSpeed1', formatFn: speedFormat },
|
||||
// { label: '头车速传2速度值', key: 'headSensorSpeed2', formatFn: speedFormat },
|
||||
// { label: '尾车速传1速度值', key: 'tailSensorSpeed1', formatFn: speedFormat },
|
||||
// { label: '尾车速传2速度值', key: 'tailSensorSpeed2', formatFn: speedFormat },
|
||||
{ label: '1端速传1是否有效', key: 'aSpeedSensorEnableA', formatFn: upFormat },
|
||||
{ label: '1端速传2是否有效', key: 'aSpeedSensorEnableB', formatFn: upFormat },
|
||||
{ label: '1端速度输出', key: 'aAccOutSpeed', formatFn: msFormat },
|
||||
{ label: '2端速传1是否有效', key: 'bSpeedSensorEnableA', formatFn: upFormat },
|
||||
{ label: '2端速传2是否有效', key: 'bSpeedSensorEnableB', formatFn: upFormat },
|
||||
{ label: '2端速度输出', key: 'bAccOutSpeed', formatFn: msFormat },
|
||||
];
|
||||
const list5: KeyType[] = [
|
||||
// { label: '头车雷达速度值', key: 'headRadarSpeed', formatFn: speedFormat },
|
||||
// { label: '尾车雷达速度值', key: 'tailRadarSpeed', formatFn: speedFormat },
|
||||
{ label: '1端雷达是否有效', key: 'aRadarEnable', formatFn: upFormat },
|
||||
{ label: '1端雷达测速差值', key: 'aRadarCheckSpeedDiff', formatFn: msFormat },
|
||||
{
|
||||
label: '1端雷达检测时间(秒)',
|
||||
key: 'aRadarCheckTime',
|
||||
formatFn: timeFormat,
|
||||
},
|
||||
{ label: '1端雷达速度输出', key: 'aRadarOutSpeed', formatFn: msFormat },
|
||||
{ label: '2端雷达是否有效', key: 'bRadarEnable', formatFn: upFormat },
|
||||
{ label: '2端雷达测速差值', key: 'bRadarCheckSpeedDiff', formatFn: msFormat },
|
||||
{
|
||||
label: '2端雷达检测时间',
|
||||
key: 'bRadarCheckTime',
|
||||
formatFn: timeFormat,
|
||||
},
|
||||
{ label: '2端雷达速度输出', key: 'bRadarOutSpeed', formatFn: msFormat },
|
||||
];
|
||||
const list6: KeyType[] = [
|
||||
{ label: '加速度', key: 'acceleration', formatFn: accelerationFormat },
|
||||
{ label: '1端加速度计是否有效', key: 'aAccEnable', formatFn: upFormat },
|
||||
{ label: '1端加速度测速差值', key: 'aAccCheckSpeedDiff', formatFn: msFormat },
|
||||
{
|
||||
label: '1端加速度持续时间',
|
||||
key: 'aAccCheckTime',
|
||||
formatFn: timeFormat,
|
||||
},
|
||||
{ label: '2端加速度计是否有效', key: 'bAccEnable', formatFn: upFormat },
|
||||
{ label: '2端加速度测速差值', key: 'bAccCheckSpeedDiff', formatFn: msFormat },
|
||||
{
|
||||
label: '2端加速度持续时间',
|
||||
key: 'bAccCheckTime',
|
||||
formatFn: timeFormat,
|
||||
},
|
||||
];
|
||||
const list7: KeyType[] = [
|
||||
{ label: '数据流水号', key: 'dataSerialNumber' },
|
||||
{ label: '应答器计数', key: 'baliseCount' },
|
||||
{ label: '报文计数器', key: 'messageCounter' },
|
||||
{ label: '报文', key: 'telegram' },
|
||||
];
|
||||
function mmFormat(v: number) {
|
||||
return v + 'mm';
|
||||
}
|
||||
function percentFormat(v: number) {
|
||||
return v + '%';
|
||||
}
|
||||
function msFormat(v: number) {
|
||||
return v + 'm/s';
|
||||
}
|
||||
function timeFormat(v: number) {
|
||||
return v + 's';
|
||||
}
|
||||
function upFormat(v: boolean) {
|
||||
return v ? '是' : '否';
|
||||
}
|
||||
@ -208,12 +428,31 @@ function speedFormat(v: number) {
|
||||
}
|
||||
function accelerationFormat(v: number) {
|
||||
const n = floatDecimal(v);
|
||||
return `${n} m/s`;
|
||||
return `${n} m/s²`;
|
||||
}
|
||||
function chongjilvFormat(v: number) {
|
||||
return `${v} m/s³`;
|
||||
}
|
||||
function haomiaoFormat(v: number) {
|
||||
return `${v} ms`;
|
||||
}
|
||||
function trainLengthFormat(v: number) {
|
||||
return `${v / 1000} m`;
|
||||
}
|
||||
|
||||
function connStateFormat(v: boolean) {
|
||||
return v ? '已连接' : '未连接';
|
||||
}
|
||||
function connTypeFormat(v: state.TrainConnState.TrainConnType) {
|
||||
if (v === state.TrainConnState.TrainConnType.NONE) {
|
||||
return '无';
|
||||
} else if (v === state.TrainConnState.TrainConnType.PC_SIM) {
|
||||
return 'PC仿真';
|
||||
} else if (v === state.TrainConnState.TrainConnType.VOBC) {
|
||||
return '半实物';
|
||||
} else {
|
||||
return '无';
|
||||
}
|
||||
}
|
||||
function floatDecimal(v: number, x = 2) {
|
||||
// 小数精确位数
|
||||
const n = v.toFixed(x);
|
||||
@ -278,6 +517,28 @@ function getDeviveName() {
|
||||
}
|
||||
return name;
|
||||
}
|
||||
function getTailDeviveName() {
|
||||
const headDeviceId = trainInfo.value?.tailDeviceId;
|
||||
const devicePort = trainInfo.value?.tailDevicePort;
|
||||
let dev: Turnout | Section | undefined;
|
||||
let name = '';
|
||||
if (devicePort) {
|
||||
dev = turnouts.value.find((item) => {
|
||||
return item.datas.id == headDeviceId;
|
||||
}) as Turnout;
|
||||
if (dev) {
|
||||
name = `${dev?.datas.code}_${devicePort}`;
|
||||
}
|
||||
} else {
|
||||
dev = sections.value.find((item) => {
|
||||
return item.datas.id == headDeviceId;
|
||||
}) as Section;
|
||||
if (dev) {
|
||||
name = `${dev?.datas.code}`;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
@ -300,7 +561,8 @@ watch(
|
||||
);
|
||||
});
|
||||
if (find) {
|
||||
trainInfo.value.copyFrom(find);
|
||||
// console.log(find, '1111');
|
||||
trainInfo.value = find as ITrainState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -336,4 +598,75 @@ function open() {
|
||||
if (!trainInfo.value) return;
|
||||
lineStore.setEchartsTrainId(trainInfo.value.id);
|
||||
}
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '设置参数',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '列车连接',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '列车驾驶台',
|
||||
value: 3,
|
||||
},
|
||||
];
|
||||
|
||||
function doTrainOperation(option: { label: string; value: number }) {
|
||||
if (option.value == 1) {
|
||||
setTrain();
|
||||
} else if (option.value == 2) {
|
||||
linkTrain();
|
||||
} else if (option.value == 3) {
|
||||
openTccDialog();
|
||||
}
|
||||
}
|
||||
|
||||
function linkTrain() {
|
||||
if (!lineStore.selectedGraphics) return;
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
const train = lineStore.selectedGraphics[0] as Train;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '列车连接',
|
||||
message: '',
|
||||
component: SetTrainLink,
|
||||
componentProps: {
|
||||
trainId: train.code,
|
||||
simulationId: lineStore.simulationId,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
}
|
||||
|
||||
function setTrain() {
|
||||
if (!lineStore.selectedGraphics) return;
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
const train = lineStore.selectedGraphics[0] as Train;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '列车设置',
|
||||
message: '',
|
||||
component: SetTrainParam,
|
||||
componentProps: {
|
||||
train: train,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
}
|
||||
|
||||
function openTccDialog() {
|
||||
const trainId = trainInfo.value?.id ? +trainInfo.value?.id : 0;
|
||||
useTccStore().setTccParam(
|
||||
trainId,
|
||||
trainInfo.value?.trainControlMapId as number
|
||||
);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.q-item {
|
||||
min-height: 32px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,78 +1,30 @@
|
||||
<template>
|
||||
<QCard flat bordered>
|
||||
<QCardSection>
|
||||
<q-card flat bordered>
|
||||
<q-card-section>
|
||||
<div class="text-h6">站台状态</div>
|
||||
</QCardSection>
|
||||
<QSeparator inset />
|
||||
<QCardSection>
|
||||
<QForm>
|
||||
<QInput
|
||||
outlined
|
||||
readonly
|
||||
v-model="platformState.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<QInput
|
||||
outlined
|
||||
readonly
|
||||
v-model.number="platformState.code"
|
||||
label="名称"
|
||||
/>
|
||||
</QForm>
|
||||
</QCardSection>
|
||||
<QCardSection>
|
||||
<QList dense bordered padding class="rounded-borders q-my-sm">
|
||||
<QItem>
|
||||
<QCheckbox
|
||||
dense
|
||||
v-model="platformState.empj"
|
||||
outlined
|
||||
label="EMP继电器状态"
|
||||
disable
|
||||
/>
|
||||
</QItem>
|
||||
<template v-if="isSpksInfoShow">
|
||||
<QSeparator class="q-mt-sm" />
|
||||
<QItemLabel header>Spks继电器状态</QItemLabel>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<QCheckbox
|
||||
v-for="item in platformState.spksState"
|
||||
:key="item.id"
|
||||
dense
|
||||
v-model="item.xh"
|
||||
:label="item.code"
|
||||
disable
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
<template v-if="isMkxInfoShow">
|
||||
<QSeparator class="q-mt-sm" />
|
||||
<QItemLabel header
|
||||
>门控箱继电器状态 ({{ platformState.mkxJState.code }})</QItemLabel
|
||||
>
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<QCheckbox
|
||||
v-for="reply in platformState.mkxJState.replyState"
|
||||
v-model="reply.xh"
|
||||
:label="reply.code"
|
||||
:key="reply.id"
|
||||
dense
|
||||
disable
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</QList>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section>
|
||||
<q-list dense>
|
||||
<q-item v-for="(item, index) in list" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(platformState[item.key])
|
||||
: platformState[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { ref, watch, watchEffect, onUnmounted, computed } from 'vue';
|
||||
import { ref, watch, watchEffect, onUnmounted } from 'vue';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { PlatformState } from 'src/drawApp/graphics/PlatformInteraction';
|
||||
@ -92,6 +44,28 @@ const platformState = ref<{
|
||||
mkxJState: new state.MkxJState(),
|
||||
});
|
||||
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof PlatformState;
|
||||
formatFn?(v: PlatformState[keyof PlatformState]): string;
|
||||
}
|
||||
|
||||
const list: KeyType[] = [
|
||||
{ label: '站台索引', key: 'id' },
|
||||
{ label: '站台名称', key: 'code' },
|
||||
{ label: 'EMP继电器状态', key: 'empj', formatFn: getEMPRelayState },
|
||||
{ label: 'SPKSX旁路', key: 'spksState', formatFn: getSPKSXRelayState },
|
||||
{ label: 'SPKS1', key: 'spksState', formatFn: getSPKS1RelayState },
|
||||
{ label: 'SPKS3', key: 'spksState', formatFn: getSPKS3RelayState },
|
||||
{ label: '站台确认继电器', key: 'mkxJState', formatFn: getConfirmRelayState },
|
||||
{
|
||||
label: '站台关门继电器',
|
||||
key: 'mkxJState',
|
||||
formatFn: getCloseSPKS1RelayState,
|
||||
},
|
||||
{ label: '站台开门继电器', key: 'mkxJState', formatFn: getOpenRelayState },
|
||||
];
|
||||
|
||||
const stop = watchEffect(() => {
|
||||
if (
|
||||
lineStore.selectedGraphics?.length == 1 &&
|
||||
@ -100,7 +74,7 @@ const stop = watchEffect(() => {
|
||||
setPlatformState(lineStore.selectedGraphics[0] as Platform);
|
||||
}
|
||||
});
|
||||
onUnmounted(stop);
|
||||
|
||||
watch(
|
||||
() => lineStore.socketStates,
|
||||
(val) => {
|
||||
@ -122,21 +96,6 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
const isSpksInfoShow = computed(() => {
|
||||
const selected = lineStore.selectedGraphics;
|
||||
if (!selected) return;
|
||||
const platform = selected[0] as Platform;
|
||||
console.log(platform.states);
|
||||
return platform.states.spksState?.length !== 0;
|
||||
});
|
||||
|
||||
const isMkxInfoShow = computed(() => {
|
||||
const selected = lineStore.selectedGraphics;
|
||||
if (!selected) return;
|
||||
const platform = selected[0] as Platform;
|
||||
return platform.states.mkxJState?.replyState?.length !== 0;
|
||||
});
|
||||
|
||||
function setPlatformState(platform: Platform) {
|
||||
platformState.value = {
|
||||
id: platform.datas.id,
|
||||
@ -146,4 +105,44 @@ function setPlatformState(platform: Platform) {
|
||||
mkxJState: platform.states.mkxJState ?? new state.MkxJState(),
|
||||
};
|
||||
}
|
||||
|
||||
function getEMPRelayState(v: boolean) {
|
||||
if (v) return 'Q';
|
||||
return 'H';
|
||||
}
|
||||
|
||||
function getSPKSXRelayState(spksState: state.ReplyState[]) {
|
||||
if (spksState.find((item) => item.code == 'SPKSX旁路')?.xh) return 'Q';
|
||||
return 'H';
|
||||
}
|
||||
|
||||
function getSPKS1RelayState(spksState: state.ReplyState[]) {
|
||||
if (spksState.find((item) => item.code == 'SPKS1')?.xh) return 'Q';
|
||||
return 'H';
|
||||
}
|
||||
|
||||
function getSPKS3RelayState(spksState: state.ReplyState[]) {
|
||||
if (spksState.find((item) => item.code == 'SPKS3')?.xh) return 'Q';
|
||||
return 'H';
|
||||
}
|
||||
|
||||
function getConfirmRelayState(mkxJState: state.MkxJState) {
|
||||
if (mkxJState.replyState.find((item) => item.code == '站台确认继电器')?.xh)
|
||||
return 'Q';
|
||||
return 'H';
|
||||
}
|
||||
|
||||
function getCloseSPKS1RelayState(mkxJState: state.MkxJState) {
|
||||
if (mkxJState.replyState.find((item) => item.code == '站台关门继电器')?.xh)
|
||||
return 'Q';
|
||||
return 'H';
|
||||
}
|
||||
|
||||
function getOpenRelayState(mkxJState: state.MkxJState) {
|
||||
if (mkxJState.replyState.find((item) => item.code == '站台开门继电器')?.xh)
|
||||
return 'Q';
|
||||
return 'H';
|
||||
}
|
||||
|
||||
onUnmounted(stop);
|
||||
</script>
|
||||
|
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<q-card flat bordered>
|
||||
<q-card
|
||||
flat
|
||||
bordered
|
||||
v-for="(item, index) in relayState"
|
||||
:key="item.id"
|
||||
style="margin-bottom: 10px"
|
||||
>
|
||||
<q-card-section class="flex justify-between">
|
||||
<span class="text-h6">继电器状态</span>
|
||||
<q-btn-dropdown color="primary" label="操作">
|
||||
@ -9,7 +15,7 @@
|
||||
:key="item.label"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="changePosition(item.value)"
|
||||
@click="changePosition(item.value, index)"
|
||||
>
|
||||
<q-item-section>{{ item.label }}</q-item-section>
|
||||
</q-item>
|
||||
@ -17,10 +23,21 @@
|
||||
</q-btn-dropdown>
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section class="q-gutter-sm">
|
||||
<q-input outlined readonly v-model="relayState.id" label="id" />
|
||||
<q-input outlined readonly v-model="relayState.code" label="名称" />
|
||||
<q-checkbox disable v-model="relayState.xh" label="是否吸合" />
|
||||
<q-card-section>
|
||||
<q-list dense>
|
||||
<q-item v-for="(item, i) in list" :key="i">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(relayState[index][item.key])
|
||||
: relayState[index][item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
@ -32,29 +49,57 @@ import { useQuasar } from 'quasar';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { Relay } from 'src/graphics/relay/Relay';
|
||||
import { RelayState } from 'src/drawApp/relayCabinetGraphics/RelayInteraction';
|
||||
import { request } from 'src/protos/request';
|
||||
|
||||
const $q = useQuasar();
|
||||
const lineStore = useLineStore();
|
||||
const relayState = ref({
|
||||
id: 0,
|
||||
code: '',
|
||||
xh: false,
|
||||
});
|
||||
const relayState = ref<
|
||||
{
|
||||
id: number;
|
||||
code: string;
|
||||
xh: boolean;
|
||||
force: boolean;
|
||||
}[]
|
||||
>([
|
||||
{
|
||||
id: 0,
|
||||
code: '',
|
||||
xh: false,
|
||||
force: false,
|
||||
},
|
||||
]);
|
||||
let operateOptions: {
|
||||
label: string;
|
||||
value: boolean;
|
||||
}[] = [];
|
||||
let copySelectGraphic: Relay | null = null;
|
||||
value: request.Relay.Operation;
|
||||
}[] = [
|
||||
{ label: '强制前接点位(吸起)', value: request.Relay.Operation.ForceQw },
|
||||
{ label: ' 强制后接点位(落下)', value: request.Relay.Operation.ForceHw },
|
||||
{ label: ' 取消强制', value: request.Relay.Operation.CancelForce },
|
||||
];
|
||||
let copySelectGraphic: Relay[] | null = null;
|
||||
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof RelayState;
|
||||
formatFn?(v: RelayState[keyof RelayState]): string;
|
||||
}
|
||||
|
||||
const list: KeyType[] = [
|
||||
{ label: '继电器索引', key: 'id' },
|
||||
{ label: '继电器名称', key: 'code' },
|
||||
{ label: '继电器状态', key: 'xh', formatFn: getRelayStateName },
|
||||
{ label: '是否强制', key: 'force', formatFn: getName },
|
||||
];
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
(val, oldVal) => {
|
||||
if (oldVal?.length == 1 && oldVal[0] instanceof Relay) {
|
||||
unSubscribeState(oldVal[0]);
|
||||
if (oldVal && oldVal.length >= 1) {
|
||||
unSubscribeState(oldVal as Relay[]);
|
||||
}
|
||||
if (val?.length == 1 && val[0] instanceof Relay) {
|
||||
copySelectGraphic = toRaw(val[0]);
|
||||
setNewRelayState(val[0]);
|
||||
if (val && val.length >= 1) {
|
||||
copySelectGraphic = toRaw(val as Relay[]);
|
||||
initRelayState(val as Relay[]);
|
||||
} else {
|
||||
copySelectGraphic = null;
|
||||
}
|
||||
@ -63,44 +108,50 @@ watch(
|
||||
|
||||
onMounted(() => {
|
||||
if (lineStore.selectedGraphics) {
|
||||
setNewRelayState(lineStore.selectedGraphics[0] as Relay);
|
||||
initRelayState(lineStore.selectedGraphics as Relay[]);
|
||||
}
|
||||
});
|
||||
|
||||
function setNewRelayState(relay: Relay) {
|
||||
relayState.value = {
|
||||
id: relay.datas.id,
|
||||
code: relay.datas.code,
|
||||
xh: relay.states.xh || false,
|
||||
};
|
||||
operateOptions = relay.states.xh
|
||||
? [{ label: '驱动落下', value: false }]
|
||||
: [{ label: '驱动吸起', value: true }];
|
||||
subscribeState(relay);
|
||||
function getRelayStateName(v: boolean) {
|
||||
if (v) return 'Q';
|
||||
return 'H';
|
||||
}
|
||||
|
||||
function subscribeState(g: Relay) {
|
||||
g.on('stateupdate', updateState);
|
||||
function getName(v: boolean) {
|
||||
if (v) return '是';
|
||||
return '否';
|
||||
}
|
||||
|
||||
function unSubscribeState(g: Relay) {
|
||||
g.off('stateupdate', updateState);
|
||||
function initRelayState(relays: Relay[]) {
|
||||
copySelectGraphic = toRaw(relays);
|
||||
relayState.value = [];
|
||||
relays.forEach((relay) =>
|
||||
relayState.value.push({
|
||||
id: relay.datas.id,
|
||||
code: relay.datas.code,
|
||||
xh: relay.states.xh || false,
|
||||
force: relay.states.force || false,
|
||||
})
|
||||
);
|
||||
subscribeState(relays);
|
||||
}
|
||||
|
||||
function updateState(newVal: RelayState) {
|
||||
relayState.value.xh = newVal.states.xh || false;
|
||||
operateOptions = newVal.states.xh
|
||||
? [{ label: '驱动落下', value: false }]
|
||||
: [{ label: '驱动吸起', value: true }];
|
||||
for (let i = 0; i < relayState.value.length; i++) {
|
||||
if (+newVal.code == relayState.value[i].id) {
|
||||
relayState.value[i].xh = newVal.states.xh || false;
|
||||
relayState.value[i].force = newVal.states.force || false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function changePosition(td: boolean) {
|
||||
function changePosition(operation: request.Relay.Operation, index: number) {
|
||||
if (lineStore.simulationId) {
|
||||
setRelayState({
|
||||
id: relayState.value.id,
|
||||
mapId: lineStore.mapId as number,
|
||||
simulationId: lineStore.simulationId,
|
||||
td,
|
||||
mapId: lineStore.mapId as number,
|
||||
deviceId: relayState.value[index].id,
|
||||
operation,
|
||||
})
|
||||
.then(() => {
|
||||
$q.notify({ type: 'positive', message: '修改继电器状态成功' });
|
||||
@ -115,6 +166,18 @@ function changePosition(td: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
function subscribeState(g: Relay[]) {
|
||||
g.forEach((item) => {
|
||||
item.on('stateupdate', updateState);
|
||||
});
|
||||
}
|
||||
|
||||
function unSubscribeState(g: Relay[]) {
|
||||
g.forEach((item) => {
|
||||
item.off('stateupdate', updateState);
|
||||
});
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (copySelectGraphic) {
|
||||
unSubscribeState(copySelectGraphic);
|
||||
|
@ -20,280 +20,128 @@
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="screenDoorState.code"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input outlined readonly v-model.number="code" label="名称" />
|
||||
<q-checkbox
|
||||
dense
|
||||
style="margin-top: 10px"
|
||||
v-model="screenDoorState.mgj"
|
||||
outlined
|
||||
label="屏蔽门关闭"
|
||||
:disable="true"
|
||||
/>
|
||||
<template :key="item" v-for="item in screenDoorState.asdStates">
|
||||
<q-list dense bordered padding class="rounded-borders q-my-sm">
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model.number="item.code"
|
||||
label="门名称"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="item.kmdw"
|
||||
outlined
|
||||
label="开门到位(实际)"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="item.gmdw"
|
||||
outlined
|
||||
label="关门到位(实际)"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="item.mgj"
|
||||
outlined
|
||||
label="关闭(表示)"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</template>
|
||||
<q-list dense>
|
||||
<q-item v-for="(item, index) in list" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(screenDoorState[item.key])
|
||||
: screenDoorState[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section>
|
||||
<div>
|
||||
<template :key="item.id" v-for="item in screenDoorState.asdStates">
|
||||
<q-list dense>
|
||||
<q-item v-for="(listItem, index) in smallDoorlist" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ listItem.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
listItem.formatFn
|
||||
? listItem.formatFn(item[listItem.key])
|
||||
: item[listItem.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-separator inset />
|
||||
</template>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-dialog v-model="selectAsd">
|
||||
<q-card style="width: 400px; max-width: 80vw">
|
||||
<q-card-section>
|
||||
<div class="text-h6">请选择滑动门</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-pt-none">
|
||||
<template :key="item" v-for="item in asdOptions">
|
||||
<q-checkbox
|
||||
v-model="asdCodes"
|
||||
:val="item"
|
||||
:label="item < 10 ? '0' + item : item + ''"
|
||||
/>
|
||||
</template>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right">
|
||||
<q-btn
|
||||
flat
|
||||
label="确定"
|
||||
color="primary"
|
||||
@click="handleAsdOperation"
|
||||
/>
|
||||
<q-btn flat label="关闭" color="primary" @click="closeAsdOperation" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<!-- <q-card-actions align="center">
|
||||
<q-btn label="修改" type="submit" color="primary" @click="submitState" />
|
||||
<q-btn
|
||||
label="重置"
|
||||
type="reset"
|
||||
color="primary"
|
||||
flat
|
||||
class="q-ml-sm"
|
||||
@click="onReset"
|
||||
/>
|
||||
</q-card-actions> -->
|
||||
</q-card>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import { ref, watch, onMounted, onUnmounted, toRaw } from 'vue';
|
||||
import { ScreenDoor } from 'src/graphics/screenDoor/ScreenDoor';
|
||||
import { request } from 'src/protos/request';
|
||||
// import { state } from 'src/protos/device_state';
|
||||
import { screenDoorOperate } from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { ScreenDoorState } from 'src/drawApp/graphics/ScreenDoorInteraction';
|
||||
import ScreenDoorOperation from 'src/components/draw-app/dialogs/ScreenDoorOperation.vue';
|
||||
import { Dialog } from 'quasar';
|
||||
import { state } from 'src/protos/device_state';
|
||||
|
||||
// string code = 1; //滑动门的编号
|
||||
// bool kmdw = 2; //开门到位(实际位置)
|
||||
// bool gmdw = 3; //关门到位(实际位置)
|
||||
// bool mgj = 4; //门关继电器
|
||||
const lineStore = useLineStore();
|
||||
const screenDoorState = ref<ScreenDoorState>(new ScreenDoorState());
|
||||
const code = ref('');
|
||||
const selectAsd = ref(false);
|
||||
const asdCodes = ref<number[]>([]);
|
||||
const asdOptions = ref<number[]>([]);
|
||||
let asdOperation: null | request.Psd.Operation = null;
|
||||
const operationOptions = ref<
|
||||
{ label: string; value: request.Psd.Operation; group?: number }[]
|
||||
>([]);
|
||||
|
||||
const options = [
|
||||
// {
|
||||
// label: '四编组开门',
|
||||
// value: request.Psd.Operation.Km,
|
||||
// },
|
||||
// {
|
||||
// label: '取消四编组开门',
|
||||
// value: request.Psd.Operation.CancelKm,
|
||||
// },
|
||||
const sonDoorAmount = ref(0);
|
||||
const operationOptions = [
|
||||
{
|
||||
label: '关门',
|
||||
value: request.Psd.Operation.Gm,
|
||||
label: '设置参数',
|
||||
value: request.Psd.Operation.SetParams,
|
||||
},
|
||||
];
|
||||
const screenDoorForce = ref<request.Psd.Force>(0);
|
||||
const screenDoorForceOption = [
|
||||
{
|
||||
label: '无强制',
|
||||
value: request.Psd.Force.F_NONE,
|
||||
},
|
||||
{
|
||||
label: '取消关门',
|
||||
value: request.Psd.Operation.CancelGm,
|
||||
label: '强制开门',
|
||||
value: request.Psd.Force.F_ASD_KM,
|
||||
},
|
||||
// {
|
||||
// label: '强制四编组开门',
|
||||
// value: request.Psd.Operation.ForceKm,
|
||||
// },
|
||||
{
|
||||
label: '强制关门',
|
||||
value: request.Psd.Operation.Gm,
|
||||
},
|
||||
{
|
||||
label: '滑动门无法开门',
|
||||
value: request.Psd.Operation.AsdCannotOpen,
|
||||
},
|
||||
{
|
||||
label: '取消滑动门无法开门',
|
||||
value: request.Psd.Operation.CancelAsdCannotOpen,
|
||||
},
|
||||
{
|
||||
label: '滑动门无法关闭',
|
||||
value: request.Psd.Operation.AsdCannotClose,
|
||||
},
|
||||
{
|
||||
label: '取消滑动门无法关闭',
|
||||
value: request.Psd.Operation.CancelAsdCannotClose,
|
||||
value: request.Psd.Force.F_ASD_GM,
|
||||
},
|
||||
];
|
||||
const screenDoorFault = ref<request.Psd.Fault>(0);
|
||||
const asdCodes = ref<number[]>([]);
|
||||
const asdOptions = ref<number[]>([]);
|
||||
let copySelectGraphic: ScreenDoor | null = null;
|
||||
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof ScreenDoorState;
|
||||
formatFn?(v: ScreenDoorState[keyof ScreenDoorState]): string;
|
||||
}
|
||||
|
||||
const list: KeyType[] = [
|
||||
{ label: '屏蔽门索引', key: 'id' },
|
||||
{ label: '屏蔽门名称', key: 'code', formatFn: getNameFormat },
|
||||
{ label: '屏蔽门关闭', key: 'mgj', formatFn: getName },
|
||||
{ label: '间隙探测障碍物', key: 'zaw', formatFn: getName },
|
||||
{ label: '屏蔽门强制', key: 'param', formatFn: getForceName },
|
||||
{ label: '设置故障', key: 'param', formatFn: getFaultName },
|
||||
];
|
||||
|
||||
interface smallDoorKeyType {
|
||||
label: string;
|
||||
key: keyof state.AsdState;
|
||||
formatFn?(v: state.AsdState[keyof state.AsdState]): string;
|
||||
}
|
||||
|
||||
const smallDoorlist: smallDoorKeyType[] = [
|
||||
{ label: '门名称', key: 'code' },
|
||||
{ label: '是否强制', key: 'force', formatFn: getName },
|
||||
{ label: '关闭', key: 'mgj', formatFn: getName },
|
||||
{ label: '有障碍物', key: 'zaw', formatFn: getName },
|
||||
];
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
(val) => {
|
||||
if (val?.length == 1 && val[0].type == ScreenDoor.Type) {
|
||||
initScreenDoorState(val[0] as ScreenDoor);
|
||||
(val, oldVal) => {
|
||||
if (oldVal?.length == 1 && oldVal[0] instanceof ScreenDoor) {
|
||||
unSubscribeState(oldVal[0]);
|
||||
}
|
||||
if (val?.length == 1 && val[0] instanceof ScreenDoor) {
|
||||
copySelectGraphic = toRaw(val[0]);
|
||||
initScreenDoorState(val[0]);
|
||||
} else {
|
||||
copySelectGraphic = null;
|
||||
screenDoorState.value = new ScreenDoorState();
|
||||
}
|
||||
}
|
||||
);
|
||||
function initScreenDoorState(screenDoor: ScreenDoor) {
|
||||
code.value = screenDoor.datas.code;
|
||||
operationOptions.value = [];
|
||||
asdOptions.value = [];
|
||||
if (lineStore.screenDoorGroupList.length) {
|
||||
lineStore.screenDoorGroupList.forEach((item) => {
|
||||
operationOptions.value.push({
|
||||
label: `${item.trainGroupAmount}编组开门`,
|
||||
value: request.Psd.Operation.Km,
|
||||
group: item.trainGroupAmount,
|
||||
});
|
||||
operationOptions.value.push({
|
||||
label: `取消${item.trainGroupAmount}编组开门`,
|
||||
value: request.Psd.Operation.CancelKm,
|
||||
group: item.trainGroupAmount,
|
||||
});
|
||||
operationOptions.value.push({
|
||||
label: `强制${item.trainGroupAmount}编组开门`,
|
||||
value: request.Psd.Operation.ForceKm,
|
||||
group: item.trainGroupAmount,
|
||||
});
|
||||
});
|
||||
}
|
||||
options.forEach((option) => {
|
||||
operationOptions.value.push(option);
|
||||
});
|
||||
if (screenDoor.datas.sonDoorAmount) {
|
||||
for (let i = 1; i <= screenDoor.datas.sonDoorAmount; i++) {
|
||||
asdOptions.value.push(i);
|
||||
}
|
||||
}
|
||||
screenDoorState.value = screenDoor.states.clone() as ScreenDoorState;
|
||||
}
|
||||
// function submitState() {
|
||||
// if (lineStore.simulationId) {
|
||||
// }
|
||||
// }
|
||||
// function onReset() {
|
||||
// if (lineStore.selectedGraphics) {
|
||||
// initScreenDoorState(lineStore.selectedGraphics[0] as ScreenDoor);
|
||||
// }
|
||||
// }
|
||||
function doScreenDoorOperation(item: {
|
||||
label: string;
|
||||
value: request.Psd.Operation;
|
||||
group?: number;
|
||||
}) {
|
||||
const list = [
|
||||
request.Psd.Operation.CancelAsdCannotClose,
|
||||
request.Psd.Operation.AsdCannotClose,
|
||||
request.Psd.Operation.AsdCannotOpen,
|
||||
request.Psd.Operation.CancelAsdCannotOpen,
|
||||
];
|
||||
if (list.includes(item.value)) {
|
||||
selectAsd.value = true;
|
||||
asdOperation = item.value;
|
||||
} else {
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
screenDoorOperate({
|
||||
simulationId,
|
||||
mapId,
|
||||
deviceId: +screenDoorState.value.code,
|
||||
operation: item.value,
|
||||
group: item.group,
|
||||
}).catch((err) => {
|
||||
errorNotify('操作失败', { message: err.origin.response.data.title });
|
||||
});
|
||||
}
|
||||
}
|
||||
function closeAsdOperation() {
|
||||
asdCodes.value = [];
|
||||
selectAsd.value = false;
|
||||
}
|
||||
function handleAsdOperation() {
|
||||
selectAsd.value = true;
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
screenDoorOperate({
|
||||
simulationId,
|
||||
mapId,
|
||||
deviceId: +screenDoorState.value.code,
|
||||
operation: asdOperation as request.Psd.Operation,
|
||||
asdCodes: asdCodes.value,
|
||||
})
|
||||
.catch((err) => {
|
||||
errorNotify('操作失败', { message: err.origin.response.data.title });
|
||||
})
|
||||
.finally(() => {
|
||||
asdCodes.value = [];
|
||||
});
|
||||
selectAsd.value = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (lineStore.selectedGraphics) {
|
||||
@ -301,20 +149,84 @@ onMounted(() => {
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => lineStore.socketStates,
|
||||
(val) => {
|
||||
if (val && screenDoorState.value.code) {
|
||||
const find = val.find((item) => {
|
||||
return (
|
||||
item.graphicType == ScreenDoor.Type &&
|
||||
(item as ScreenDoorState).code == screenDoorState.value.code
|
||||
);
|
||||
});
|
||||
if (find) {
|
||||
screenDoorState.value = find.clone() as ScreenDoorState;
|
||||
}
|
||||
function getNameFormat() {
|
||||
return code.value;
|
||||
}
|
||||
|
||||
function getName(v: boolean) {
|
||||
if (v) return '是';
|
||||
return '否';
|
||||
}
|
||||
|
||||
function getForceName() {
|
||||
return (
|
||||
screenDoorForceOption.find((item) => item.value == screenDoorForce.value)
|
||||
?.label || ''
|
||||
);
|
||||
}
|
||||
|
||||
function getFaultName() {
|
||||
if (screenDoorFault.value == 1) return '是';
|
||||
return '否';
|
||||
}
|
||||
|
||||
function initScreenDoorState(screenDoor: ScreenDoor) {
|
||||
copySelectGraphic = toRaw(screenDoor);
|
||||
code.value = screenDoor.datas.code;
|
||||
asdOptions.value = [];
|
||||
sonDoorAmount.value = screenDoor.datas.sonDoorAmount;
|
||||
if (screenDoor.datas.sonDoorAmount) {
|
||||
for (let i = 1; i <= screenDoor.datas.sonDoorAmount; i++) {
|
||||
asdOptions.value.push(i);
|
||||
}
|
||||
}
|
||||
);
|
||||
updateState(screenDoor);
|
||||
subscribeState(screenDoor);
|
||||
}
|
||||
|
||||
function updateState(screenDoor: ScreenDoor) {
|
||||
screenDoorState.value = screenDoor.states.clone() as ScreenDoorState;
|
||||
asdCodes.value = screenDoorState.value.param.asdCodes;
|
||||
screenDoorForce.value = screenDoorState.value.param.force;
|
||||
screenDoorFault.value = screenDoorState.value.param.fault;
|
||||
}
|
||||
|
||||
function doScreenDoorOperation(item: {
|
||||
label: string;
|
||||
value: request.Psd.Operation;
|
||||
}) {
|
||||
if (!lineStore.simulationId) return;
|
||||
if (item.label == '设置参数') {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
component: ScreenDoorOperation,
|
||||
componentProps: {
|
||||
id: +screenDoorState.value.id,
|
||||
code: code.value,
|
||||
sonDoorAmount: sonDoorAmount.value,
|
||||
asdCodesProp: screenDoorState.value.param.asdCodes,
|
||||
screenDoorForceProp: screenDoorState.value.param.force,
|
||||
screenDoorFaultProp: screenDoorState.value.param.fault,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onCancel(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function subscribeState(g: ScreenDoor) {
|
||||
g.on('stateupdate', updateState);
|
||||
}
|
||||
|
||||
function unSubscribeState(g: ScreenDoor) {
|
||||
g.off('stateupdate', updateState);
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (copySelectGraphic) {
|
||||
unSubscribeState(copySelectGraphic);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -9,7 +9,7 @@
|
||||
:key="index"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="toDo(item)"
|
||||
@click="doSectionOperation(item)"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
@ -20,42 +20,17 @@
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="sectionState.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model.number="sectionState.code"
|
||||
label="名称"
|
||||
/>
|
||||
</q-form>
|
||||
<q-list dense bordered padding class="rounded-borders q-my-sm">
|
||||
<q-item>
|
||||
<q-list dense>
|
||||
<q-item v-for="(item, index) in list" :key="index">
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="sectionState.occupied"
|
||||
outlined
|
||||
label="是否占用"
|
||||
:disable="true"
|
||||
/>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="sectionState.axleFault"
|
||||
outlined
|
||||
label="是否计轴故障"
|
||||
:disable="true"
|
||||
/>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(sectionState[item.key])
|
||||
: sectionState[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
@ -64,118 +39,151 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import { Section, type ISectionState } from 'src/graphics/section/Section';
|
||||
import { ref, watch, onMounted, onUnmounted, toRaw } from 'vue';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { request } from 'src/protos/request';
|
||||
import { Dialog } from 'quasar';
|
||||
import SectionOperation from 'src/components/draw-app/dialogs/SectionOperation.vue';
|
||||
import { setAxleSectionState } from 'src/api/Simulation';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { SectionStates } from 'src/drawApp/graphics/SectionInteraction';
|
||||
|
||||
const $q = useQuasar();
|
||||
const lineStore = useLineStore();
|
||||
const sectionState = ref({
|
||||
id: 0,
|
||||
code: '',
|
||||
axleFault: false,
|
||||
occupied: false,
|
||||
axleDrst: false,
|
||||
axlePdrst: false,
|
||||
});
|
||||
let copySelectGraphic: Section | null = null;
|
||||
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof SectionStates;
|
||||
formatFn?(v: SectionStates[keyof SectionStates]): string;
|
||||
}
|
||||
|
||||
const list: KeyType[] = [
|
||||
{ label: '轨道索引', key: 'id' },
|
||||
{ label: '轨道名称', key: 'code' },
|
||||
{ label: '是否占用', key: 'axleFault', formatFn: getName },
|
||||
{ label: '是否计轴故障', key: 'occupied', formatFn: getName },
|
||||
{ label: '是否计轴复位', key: 'axleDrst', formatFn: getName },
|
||||
{ label: '是否计轴预复位', key: 'axlePdrst', formatFn: getName },
|
||||
];
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
(val) => {
|
||||
if (val?.length == 1 && val[0].type == Section.Type) {
|
||||
setSectionState(val[0] as Section);
|
||||
(val, oldVal) => {
|
||||
if (oldVal?.length == 1 && oldVal[0] instanceof Section) {
|
||||
unSubscribeState(oldVal[0]);
|
||||
}
|
||||
if (val?.length == 1 && val[0] instanceof Section) {
|
||||
copySelectGraphic = toRaw(val[0]);
|
||||
initSectionState(val[0] as Section);
|
||||
} else {
|
||||
copySelectGraphic = null;
|
||||
sectionState.value = {
|
||||
id: 0,
|
||||
code: '',
|
||||
axleFault: false,
|
||||
occupied: false,
|
||||
axleDrst: false,
|
||||
axlePdrst: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
function setSectionState(section: Section) {
|
||||
|
||||
onMounted(() => {
|
||||
if (lineStore.selectedGraphics) {
|
||||
initSectionState(lineStore.selectedGraphics[0] as Section);
|
||||
}
|
||||
});
|
||||
|
||||
function getName(v: boolean) {
|
||||
if (v) return '是';
|
||||
return '否';
|
||||
}
|
||||
|
||||
function initSectionState(section: Section) {
|
||||
copySelectGraphic = toRaw(section);
|
||||
sectionState.value = {
|
||||
id: section.datas.id,
|
||||
code: section.datas.code,
|
||||
axleFault: section.states.axleFault ?? false,
|
||||
occupied: section.states.occupied ?? false,
|
||||
axleDrst: section.states.axleDrst ?? false,
|
||||
axlePdrst: section.states.axlePdrst ?? false,
|
||||
};
|
||||
subscribeState(section);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (lineStore.selectedGraphics) {
|
||||
setSectionState(lineStore.selectedGraphics[0] as Section);
|
||||
}
|
||||
});
|
||||
function updateState(newVal: Section) {
|
||||
sectionState.value = {
|
||||
id: newVal.id,
|
||||
code: sectionState.value.code,
|
||||
axleFault: newVal.states.axleFault ?? false,
|
||||
occupied: newVal.states.occupied ?? false,
|
||||
axleDrst: newVal.states.axleDrst ?? false,
|
||||
axlePdrst: newVal.states.axlePdrst ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '设置计轴直接复位',
|
||||
value: request.Section.Operation.SetDrst,
|
||||
label: '设置参数',
|
||||
value: request.Section.Operation.SetParams,
|
||||
},
|
||||
{
|
||||
label: '取消计轴直接复位',
|
||||
value: request.Section.Operation.CancelDrst,
|
||||
},
|
||||
{
|
||||
label: '设置计轴预复位',
|
||||
value: request.Section.Operation.SetPdrst,
|
||||
},
|
||||
{
|
||||
label: '取消计轴预复位',
|
||||
value: request.Section.Operation.CancelPdrst,
|
||||
},
|
||||
{
|
||||
label: '设置区段故障占用',
|
||||
label: '设置故障占用',
|
||||
value: request.Section.Operation.SetFaultOcc,
|
||||
},
|
||||
{
|
||||
label: '取消区段故障占用',
|
||||
value: request.Section.Operation.CancelFaultOcc,
|
||||
},
|
||||
];
|
||||
function toDo(item: { label: string; value: number }) {
|
||||
|
||||
function doSectionOperation(item: { label: string; value: number }) {
|
||||
if (!lineStore.simulationId) return;
|
||||
const obj = {
|
||||
simulationId: lineStore?.simulationId || '',
|
||||
mapId: lineStore.mapId as number,
|
||||
id: sectionState.value.id,
|
||||
operation: item.value,
|
||||
};
|
||||
setAxleSectionState(obj)
|
||||
// .then(() => {
|
||||
// $q.notify({ type: 'positive', message: '修改区段状态成功' });
|
||||
// })
|
||||
.catch((err) => {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
if (item.label == '设置参数') {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
component: SectionOperation,
|
||||
componentProps: {
|
||||
id: sectionState.value.id,
|
||||
code: sectionState.value.code,
|
||||
axleDrst: sectionState.value.axleDrst,
|
||||
axlePdrst: sectionState.value.axlePdrst,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onCancel(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
}
|
||||
watch(
|
||||
() => lineStore.socketStates,
|
||||
(val) => {
|
||||
if (val && sectionState.value.id) {
|
||||
const find = val.find((item): item is SectionStates => {
|
||||
return (
|
||||
item.graphicType == Section.Type &&
|
||||
(item as ISectionState).id == sectionState.value.id
|
||||
);
|
||||
});
|
||||
if (find) {
|
||||
sectionState.value = {
|
||||
id: find.id,
|
||||
code: find.code,
|
||||
axleFault: find.axleFault,
|
||||
occupied: find.occupied,
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const obj = {
|
||||
simulationId: lineStore?.simulationId || '',
|
||||
mapId: lineStore.mapId as number,
|
||||
deviceId: sectionState.value.id,
|
||||
operation: request.Section.Operation.SetFaultOcc,
|
||||
};
|
||||
setAxleSectionState(obj).catch((e) =>
|
||||
errorNotify('区段操作失败:' + e.title, e)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function subscribeState(g: Section) {
|
||||
g.on('stateupdate', updateState);
|
||||
}
|
||||
|
||||
function unSubscribeState(g: Section) {
|
||||
g.off('stateupdate', updateState);
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (copySelectGraphic) {
|
||||
unSubscribeState(copySelectGraphic);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -20,159 +20,183 @@
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="signalState.code"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input outlined readonly v-model="index" label="索引" hint="" />
|
||||
<q-input outlined readonly v-model.number="code" label="名称" />
|
||||
<q-select
|
||||
v-model="signalState.aspect"
|
||||
style="margin-top: 10px"
|
||||
label="灯亮状态"
|
||||
outlined
|
||||
:options="aspectOptions"
|
||||
emitValue
|
||||
mapOptions
|
||||
:disable="true"
|
||||
>
|
||||
</q-select>
|
||||
<q-list dense>
|
||||
<q-item v-for="(item, index) in list" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(signalState[item.key])
|
||||
: signalState[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
<!-- <q-card-actions align="center">
|
||||
<q-btn label="修改" type="submit" color="primary" @click="submitState" />
|
||||
<q-btn
|
||||
label="重置"
|
||||
type="reset"
|
||||
color="primary"
|
||||
flat
|
||||
class="q-ml-sm"
|
||||
@click="onReset"
|
||||
/>
|
||||
</q-card-actions> -->
|
||||
</q-card>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import { ref, watch, onMounted, onUnmounted, toRaw } from 'vue';
|
||||
import { Signal } from 'src/graphics/signal/Signal';
|
||||
import { request } from 'src/protos/request';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { setSignalState } from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { SignalState } from 'src/drawApp/graphics/SignalInteraction';
|
||||
import { Dialog } from 'quasar';
|
||||
import SignalOperation from 'src/components/draw-app/dialogs/SignalOperation.vue';
|
||||
import { request } from 'src/protos/request';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { state } from 'src/protos/device_state';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
const signalState = ref<SignalState>(new SignalState());
|
||||
const code = ref('');
|
||||
const index = ref(0);
|
||||
|
||||
interface SignalDsItem {
|
||||
label: string;
|
||||
value: request.Signal.DS;
|
||||
}
|
||||
const signalDsOptions = ref<SignalDsItem[]>([]);
|
||||
const hDs = {
|
||||
label: '红灯断丝',
|
||||
value: request.Signal.DS.DS_H,
|
||||
};
|
||||
const uDs = {
|
||||
label: '黄灯断丝',
|
||||
value: request.Signal.DS.DS_U,
|
||||
};
|
||||
const lDs = {
|
||||
label: '绿灯断丝',
|
||||
value: request.Signal.DS.DS_L,
|
||||
};
|
||||
const aDs = {
|
||||
label: '蓝灯断丝',
|
||||
value: request.Signal.DS.DS_A,
|
||||
};
|
||||
const bDs = {
|
||||
label: '白灯断丝',
|
||||
value: request.Signal.DS.DS_B,
|
||||
};
|
||||
|
||||
interface SignalForceItem {
|
||||
label: string;
|
||||
value: request.Signal.Force;
|
||||
}
|
||||
const signalForceOptions = ref<SignalForceItem[]>([]);
|
||||
const noForce = {
|
||||
label: '无强制',
|
||||
value: request.Signal.Force.SF_NONE,
|
||||
};
|
||||
const mieDeng = {
|
||||
label: '灭灯',
|
||||
value: request.Signal.Force.SF_M,
|
||||
};
|
||||
const hongDeng = {
|
||||
label: '红灯',
|
||||
value: request.Signal.Force.SF_H,
|
||||
};
|
||||
const huangDeng = {
|
||||
label: '黄灯',
|
||||
value: request.Signal.Force.SF_U,
|
||||
};
|
||||
const lvDeng = {
|
||||
label: '绿灯',
|
||||
value: request.Signal.Force.SF_L,
|
||||
};
|
||||
const huanghongDeng = {
|
||||
label: '黄红灯',
|
||||
value: request.Signal.Force.SF_HU,
|
||||
};
|
||||
const lanDeng = {
|
||||
label: '蓝灯',
|
||||
value: request.Signal.Force.SF_A,
|
||||
};
|
||||
const baiDeng = {
|
||||
label: '白灯',
|
||||
value: request.Signal.Force.SF_B,
|
||||
};
|
||||
|
||||
const aspectOptions = [
|
||||
{ label: '无用值', value: 0 },
|
||||
{ label: '物理灭灯', value: 1 },
|
||||
{ label: '绿灯亮', value: 2 },
|
||||
{ label: '红灯亮', value: 3 },
|
||||
{ label: '黄灯亮', value: 4 },
|
||||
{ label: '红黄灯亮', value: 5 },
|
||||
{ label: '白灯亮', value: 6 },
|
||||
{ label: '蓝灯亮', value: 7 },
|
||||
{ label: '灭灯', value: state.Signal.Aspect.OFF },
|
||||
{ label: '红灯亮', value: state.Signal.Aspect.H },
|
||||
{ label: '绿灯亮', value: state.Signal.Aspect.L },
|
||||
{ label: '黄灯亮', value: state.Signal.Aspect.U },
|
||||
{ label: '红黄灯亮', value: state.Signal.Aspect.HU },
|
||||
{ label: '白灯亮', value: state.Signal.Aspect.B },
|
||||
{ label: '蓝灯亮', value: state.Signal.Aspect.A },
|
||||
];
|
||||
const options = [
|
||||
{
|
||||
label: '开红灯',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.H,
|
||||
operation: request.Signal.Operation.Display,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '开绿灯',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.L,
|
||||
operation: request.Signal.Operation.Display,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '开黄灯',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.U,
|
||||
operation: request.Signal.Operation.Display,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '开引导',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.HU,
|
||||
operation: request.Signal.Operation.Display,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '关灯',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.OFF,
|
||||
operation: request.Signal.Operation.Display,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '设置红灯断丝故障',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.H,
|
||||
operation: request.Signal.Operation.LightHFaultDs,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '设置绿灯断丝故障',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.H,
|
||||
operation: request.Signal.Operation.LightLFaultDs,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '设置黄灯断丝故障',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.H,
|
||||
operation: request.Signal.Operation.LightUFaultDs,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '取消红灯断丝故障',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.H,
|
||||
operation: request.Signal.Operation.LightHCancelDs,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '取消绿灯断丝故障',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.H,
|
||||
operation: request.Signal.Operation.LightLCancelDs,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '取消黄灯断丝故障',
|
||||
value: {
|
||||
aspect: state.Signal.Aspect.H,
|
||||
operation: request.Signal.Operation.LightUCancelDs,
|
||||
},
|
||||
},
|
||||
const options = [{ label: '设置参数' }];
|
||||
let copySelectGraphic: Signal | null = null;
|
||||
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof SignalState;
|
||||
formatFn?(v: SignalState[keyof SignalState]): string;
|
||||
}
|
||||
|
||||
const list: KeyType[] = [
|
||||
{ label: '信号机索引', key: 'code' },
|
||||
{ label: '信号机名称', key: 'code', formatFn: getNameFormat },
|
||||
{ label: '灯亮状态', key: 'aspect', formatFn: getAspectName },
|
||||
{ label: '信号机强制', key: 'param', formatFn: getForceName },
|
||||
{ label: '信号机断丝', key: 'param', formatFn: getDsName },
|
||||
];
|
||||
|
||||
function getNameFormat(v: number) {
|
||||
if (v) {
|
||||
return code.value;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getAspectName(aspect: state.Signal.Aspect) {
|
||||
return aspectOptions.find((item) => item.value == aspect)?.label || '';
|
||||
}
|
||||
function getForceName(param: request.SignalParam) {
|
||||
return (
|
||||
signalForceOptions.value.find((item) => item.value == param.force)?.label ||
|
||||
''
|
||||
);
|
||||
}
|
||||
function getDsName(param: request.SignalParam) {
|
||||
let s = '';
|
||||
signalDsOptions.value.forEach((item) => {
|
||||
if (param.dsList.includes(item.value)) {
|
||||
const label = s ? item.label + '、' : item.label;
|
||||
s += label;
|
||||
}
|
||||
});
|
||||
return s || '无';
|
||||
}
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
(val) => {
|
||||
if (val?.length == 1 && val[0].type == Signal.Type) {
|
||||
(val, oldVal) => {
|
||||
if (oldVal?.length == 1 && oldVal[0] instanceof Signal) {
|
||||
unSubscribeState(oldVal[0]);
|
||||
}
|
||||
if (val?.length == 1 && val[0] instanceof Signal) {
|
||||
copySelectGraphic = toRaw(val[0]);
|
||||
initSignalState(val[0] as Signal);
|
||||
} else {
|
||||
copySelectGraphic = null;
|
||||
signalState.value = new SignalState();
|
||||
}
|
||||
}
|
||||
);
|
||||
const mt = ref(0);
|
||||
function initSignalState(signal: Signal) {
|
||||
copySelectGraphic = toRaw(signal);
|
||||
// index.value = signal.datas.index;
|
||||
initOptions(signal.datas.mt);
|
||||
mt.value = signal.datas.mt;
|
||||
code.value = signal.datas.code;
|
||||
signalState.value = signal.states.clone() as SignalState;
|
||||
subscribeState(signal);
|
||||
}
|
||||
|
||||
function updateState(newVal: SignalState) {
|
||||
signalState.value = newVal.clone() as SignalState;
|
||||
}
|
||||
// function submitState() {
|
||||
// if (lineStore.simulationId) {
|
||||
@ -183,21 +207,26 @@ function initSignalState(signal: Signal) {
|
||||
// initSignalState(lineStore.selectedGraphics[0] as Signal);
|
||||
// }
|
||||
// }
|
||||
function doSignalOperation(item: {
|
||||
label: string;
|
||||
value: { aspect: state.Signal.Aspect; operation: request.Signal.Operation };
|
||||
}) {
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
setSignalState({
|
||||
simulationId,
|
||||
mapId,
|
||||
id: +signalState.value.code,
|
||||
aspect: item.value.aspect,
|
||||
operation: item.value.operation,
|
||||
}).catch((err) => {
|
||||
errorNotify('操作失败', { message: err.origin.response.data.title });
|
||||
});
|
||||
function doSignalOperation(item: { label: string }) {
|
||||
if (!lineStore.simulationId) return;
|
||||
if (item.label == '设置参数') {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '道岔设置参数',
|
||||
message: '',
|
||||
component: SignalOperation,
|
||||
componentProps: {
|
||||
id: +signalState.value.code,
|
||||
code: code.value,
|
||||
mt: mt.value,
|
||||
param: signalState.value.param,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onCancel(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@ -206,20 +235,97 @@ onMounted(() => {
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => lineStore.socketStates,
|
||||
(val) => {
|
||||
if (val && signalState.value.code) {
|
||||
const find = val.find((item) => {
|
||||
return (
|
||||
item.graphicType == Signal.Type &&
|
||||
(item as SignalState).code == signalState.value.code
|
||||
);
|
||||
});
|
||||
if (find) {
|
||||
signalState.value = find.clone() as SignalState;
|
||||
}
|
||||
}
|
||||
function initOptions(mt: graphicData.Signal.Model) {
|
||||
switch (mt) {
|
||||
case graphicData.Signal.Model.HL:
|
||||
signalDsOptions.value = [hDs, lDs];
|
||||
signalForceOptions.value = [noForce, mieDeng, hongDeng, lvDeng];
|
||||
break;
|
||||
case graphicData.Signal.Model.AB:
|
||||
signalDsOptions.value = [aDs, bDs];
|
||||
signalForceOptions.value = [noForce, mieDeng, lanDeng, baiDeng];
|
||||
break;
|
||||
case graphicData.Signal.Model.HBU_DU:
|
||||
signalDsOptions.value = [hDs, bDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
baiDeng,
|
||||
huangDeng,
|
||||
];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_FU:
|
||||
signalDsOptions.value = [hDs, lDs];
|
||||
signalForceOptions.value = [noForce, mieDeng, hongDeng, lvDeng];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_DU_YY:
|
||||
signalDsOptions.value = [hDs, lDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
lvDeng,
|
||||
huangDeng,
|
||||
huanghongDeng,
|
||||
];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_YY:
|
||||
signalDsOptions.value = [hDs, lDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
lvDeng,
|
||||
huanghongDeng,
|
||||
];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_FL_DU_YY:
|
||||
signalDsOptions.value = [hDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
huangDeng,
|
||||
huanghongDeng,
|
||||
];
|
||||
break;
|
||||
case graphicData.Signal.Model.HLU_DU:
|
||||
signalDsOptions.value = [hDs, lDs, uDs];
|
||||
signalForceOptions.value = [
|
||||
noForce,
|
||||
mieDeng,
|
||||
hongDeng,
|
||||
lvDeng,
|
||||
huangDeng,
|
||||
];
|
||||
break;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function subscribeState(g: Signal) {
|
||||
if (g) {
|
||||
g.on('stateupdate', updateState);
|
||||
}
|
||||
}
|
||||
|
||||
function unSubscribeState(g: Signal) {
|
||||
if (g) {
|
||||
g.off('stateupdate', updateState);
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (copySelectGraphic) {
|
||||
unSubscribeState(copySelectGraphic);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.border-box {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
margin-left: 0;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,26 +1,24 @@
|
||||
<template>
|
||||
<q-card flat bordered>
|
||||
<q-card-section class="row justify-between items-center q-pb-none">
|
||||
<q-card-section class="flex justify-between">
|
||||
<div class="text-h6">车站状态</div>
|
||||
<q-btn color="primary" @click="openIbp">打开IBP</q-btn>
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="stationState.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model.number="stationState.code"
|
||||
label="名称"
|
||||
/>
|
||||
</q-form>
|
||||
<q-list dense>
|
||||
<q-item v-for="(item, index) in list" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(stationState[item.key])
|
||||
: stationState[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
@ -28,10 +26,20 @@
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useIbpStore } from 'src/stores/ibp-store';
|
||||
import { StationState } from 'src/drawApp/graphics/StationInteraction';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
const stationState = ref({ id: 0, code: '' });
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof StationState;
|
||||
formatFn?(v: StationState[keyof StationState]): string;
|
||||
}
|
||||
|
||||
const list: KeyType[] = [
|
||||
{ label: '车站索引', key: 'id' },
|
||||
{ label: '车站名称', key: 'code' },
|
||||
];
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
@ -47,14 +55,6 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
function openIbp() {
|
||||
const selected = lineStore.selectedGraphics;
|
||||
if (!selected) return;
|
||||
const station = selected[0] as Station;
|
||||
if (!station) return;
|
||||
useIbpStore().openIbpScene(station);
|
||||
}
|
||||
|
||||
function setStationState(station: Station) {
|
||||
stationState.value = {
|
||||
id: station.datas.id,
|
||||
|
300
src/components/line-app/states/TransponderState.vue
Normal file
300
src/components/line-app/states/TransponderState.vue
Normal file
@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<q-card flat bordered>
|
||||
<q-card-section class="flex justify-between">
|
||||
<div class="text-h6">应答器状态</div>
|
||||
<q-btn-dropdown color="primary" label="操作">
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="(item, index) in options"
|
||||
:key="index"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="doTransponderOperation(item.value)"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section>
|
||||
<q-list dense>
|
||||
<q-item v-for="(item, index) in list" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>
|
||||
<div
|
||||
style="word-wrap: break-word; width: 150px; text-align: right"
|
||||
>
|
||||
{{
|
||||
item.formatFn
|
||||
? item.formatFn(transponderState[item.key])
|
||||
: transponderState[item.key]
|
||||
}}
|
||||
</div>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<template
|
||||
v-if="
|
||||
transponderType === TransponderTypeEnum.VB ||
|
||||
transponderType === TransponderTypeEnum.IB
|
||||
"
|
||||
>
|
||||
<q-item v-for="(item, index) in list1" :key="index">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption
|
||||
><div
|
||||
style="word-wrap: break-word; width: 150px; text-align: right"
|
||||
>
|
||||
{{
|
||||
item.formatFn
|
||||
? item.formatFn(transponderState[item.key])
|
||||
: transponderState[item.key]
|
||||
}}
|
||||
</div></q-item-label
|
||||
>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { ref, watch, onMounted, toRaw, onUnmounted } from 'vue';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { TransponderState } from 'src/drawApp/graphics/TransponderInteraction';
|
||||
import {
|
||||
Transponder,
|
||||
TransponderTypeEnum,
|
||||
} from 'src/graphics/transponder/Transponder';
|
||||
import MoveTransponder from 'src/components/draw-app/dialogs/MoveTransponder.vue';
|
||||
import UpdateMessageTransponder from 'src/components/draw-app/dialogs/UpdateMessageTransponder.vue';
|
||||
import { Dialog } from 'quasar';
|
||||
import {
|
||||
resetMessageTransponder,
|
||||
resetPositionTransponder,
|
||||
stopTransponderTelegram,
|
||||
sendTransponderTelegram,
|
||||
} from 'src/api/Simulation';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
|
||||
const lineStore = useLineStore();
|
||||
const transponderState = ref<TransponderState>(new TransponderState());
|
||||
const code = ref('');
|
||||
const type = ref(0);
|
||||
const kilometer = ref(0);
|
||||
enum TransponderOperation {
|
||||
MovePosition = 1,
|
||||
ResetPosition = 2,
|
||||
ModifyMessage = 3,
|
||||
ResetMessage = 4,
|
||||
StopMessage = 5,
|
||||
SendMessage = 6,
|
||||
}
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '移动应答器位置',
|
||||
value: TransponderOperation.MovePosition,
|
||||
},
|
||||
{
|
||||
label: '复位应答器',
|
||||
value: TransponderOperation.ResetPosition,
|
||||
},
|
||||
{
|
||||
label: '修改报文',
|
||||
value: TransponderOperation.ModifyMessage,
|
||||
},
|
||||
{
|
||||
label: '重置报文',
|
||||
value: TransponderOperation.ResetMessage,
|
||||
},
|
||||
{
|
||||
label: '停止发送报文',
|
||||
value: TransponderOperation.StopMessage,
|
||||
},
|
||||
{
|
||||
label: '取消停止发送报文',
|
||||
value: TransponderOperation.SendMessage,
|
||||
},
|
||||
];
|
||||
|
||||
const directionOptions = [
|
||||
{ label: '左行', value: 0 },
|
||||
{ label: '右行', value: 1 },
|
||||
];
|
||||
let copySelectGraphic: Transponder | null = null;
|
||||
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof TransponderState;
|
||||
formatFn?(v: TransponderState[keyof TransponderState]): string;
|
||||
}
|
||||
|
||||
const list: KeyType[] = [
|
||||
{ label: '应答器索引', key: 'code' },
|
||||
{ label: '应答器名称', key: 'code', formatFn: getNameFormat },
|
||||
{ label: '坐标系', key: 'km', formatFn: getCoordinateSystemFormat },
|
||||
{ label: '公里标', key: 'km', formatFn: getKilometerFormat },
|
||||
{ label: '方向', key: 'km', formatFn: getDirectionFormat },
|
||||
{ label: '停止发送报文', key: 'work', formatFn: workFormat },
|
||||
{ label: '固定用户报文', key: 'fixedUserTelegram' },
|
||||
{ label: '固定报文', key: 'fixedTelegram' },
|
||||
];
|
||||
const list1: KeyType[] = [
|
||||
{
|
||||
label: '可变用户报文',
|
||||
key: 'variableUserTelegram',
|
||||
},
|
||||
{ label: '可变报文', key: 'variableTelegram' },
|
||||
];
|
||||
|
||||
function getNameFormat(v: string) {
|
||||
return code.value || v;
|
||||
}
|
||||
function getCoordinateSystemFormat(v: graphicData.KilometerSystem) {
|
||||
return v.coordinateSystem;
|
||||
}
|
||||
function getKilometerFormat(v: graphicData.KilometerSystem) {
|
||||
return v.kilometer + 'mm';
|
||||
}
|
||||
function getDirectionFormat(v: graphicData.KilometerSystem) {
|
||||
return (
|
||||
directionOptions.find((item) => item.value == v.direction)?.label || ''
|
||||
);
|
||||
}
|
||||
function workFormat(v: boolean) {
|
||||
return v ? '否' : '是';
|
||||
}
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
(val, oldVal) => {
|
||||
if (oldVal?.length == 1 && oldVal[0] instanceof Transponder) {
|
||||
unSubscribeState(oldVal[0]);
|
||||
}
|
||||
if (val?.length == 1 && val[0] instanceof Transponder) {
|
||||
copySelectGraphic = toRaw(val[0]);
|
||||
initTransponderState(val[0] as Transponder);
|
||||
} else {
|
||||
copySelectGraphic = null;
|
||||
transponderState.value = new TransponderState();
|
||||
}
|
||||
}
|
||||
);
|
||||
const transponderType = ref();
|
||||
function initTransponderState(transponder: Transponder) {
|
||||
transponderType.value = transponder.datas.type;
|
||||
copySelectGraphic = toRaw(transponder);
|
||||
code.value = transponder.datas.code;
|
||||
type.value = transponder.datas.type;
|
||||
kilometer.value = transponder.states.km?.kilometer || 0;
|
||||
transponderState.value = transponder.states.clone() as TransponderState;
|
||||
subscribeState(transponder);
|
||||
}
|
||||
|
||||
function updateState(newVal: TransponderState) {
|
||||
transponderState.value = newVal.clone() as TransponderState;
|
||||
kilometer.value = transponderState.value.km.kilometer;
|
||||
}
|
||||
|
||||
function doTransponderOperation(operation: number) {
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
if (operation === TransponderOperation.MovePosition) {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '移动应答器位置',
|
||||
message: '',
|
||||
component: MoveTransponder,
|
||||
componentProps: {
|
||||
code: code.value,
|
||||
coordinateSystem: transponderState.value.km?.coordinateSystem,
|
||||
kilometer: transponderState.value.km?.kilometer,
|
||||
direction: transponderState.value.km?.direction,
|
||||
id: transponderState.value.id,
|
||||
type: type.value,
|
||||
variableTelegram: transponderState.value.variableTelegram,
|
||||
variableUserTelegram: transponderState.value.variableUserTelegram,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
} else if (operation === TransponderOperation.ResetPosition) {
|
||||
resetPositionTransponder({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: transponderState.value.id,
|
||||
}).catch((e) => {
|
||||
errorNotify('复位应答器失败:' + e.title, e);
|
||||
});
|
||||
} else if (operation === TransponderOperation.ModifyMessage) {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '修改应答器报文',
|
||||
message: '',
|
||||
component: UpdateMessageTransponder,
|
||||
componentProps: {
|
||||
code: code.value,
|
||||
fixedTelegram: transponderState.value.fixedTelegram,
|
||||
fixedUserTelegram: transponderState.value.fixedUserTelegram,
|
||||
id: transponderState.value.id,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
} else if (operation === TransponderOperation.ResetMessage) {
|
||||
resetMessageTransponder({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: transponderState.value.id,
|
||||
}).catch((e) => errorNotify('重置应答器报文失败:' + e.title, e));
|
||||
} else if (operation === TransponderOperation.StopMessage) {
|
||||
stopTransponderTelegram({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: transponderState.value.id,
|
||||
}).catch((e) => errorNotify('停止应答器报文失败:' + e.title, e));
|
||||
} else if (operation === TransponderOperation.SendMessage) {
|
||||
sendTransponderTelegram({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: transponderState.value.id,
|
||||
}).catch((e) => errorNotify('取消停止应答器报文失败:' + e.title, e));
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (lineStore.selectedGraphics) {
|
||||
initTransponderState(lineStore.selectedGraphics[0] as Transponder);
|
||||
}
|
||||
});
|
||||
|
||||
function subscribeState(g: Transponder) {
|
||||
if (g) {
|
||||
g.on('stateupdate', updateState);
|
||||
}
|
||||
}
|
||||
|
||||
function unSubscribeState(g: Transponder) {
|
||||
if (g) {
|
||||
g.off('stateupdate', updateState);
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (copySelectGraphic) {
|
||||
unSubscribeState(copySelectGraphic);
|
||||
}
|
||||
});
|
||||
</script>
|
@ -9,7 +9,7 @@
|
||||
:key="index"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="toDo(item)"
|
||||
@click="doTurnoutOperation(item)"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
@ -20,183 +20,17 @@
|
||||
</q-card-section>
|
||||
<q-separator inset />
|
||||
<q-card-section>
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
readonly
|
||||
v-model="turnoutState.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input dense outlined readonly v-model="name" label="名称" hint="" />
|
||||
<q-list dense bordered padding class="rounded-borders q-my-sm">
|
||||
<q-item>
|
||||
<q-list dense>
|
||||
<q-item v-for="(item, index) in list" :key="index">
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.normal"
|
||||
outlined
|
||||
label="定位(表示)"
|
||||
:disable="true"
|
||||
/>
|
||||
<q-item-label>{{ item.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.reverse"
|
||||
outlined
|
||||
label="反位(表示)"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.dw"
|
||||
outlined
|
||||
label="定位(实际)"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.fw"
|
||||
outlined
|
||||
label="反位(实际)"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-list dense bordered padding class="rounded-borders q-my-sm">
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.force"
|
||||
outlined
|
||||
label="是否强制(屏蔽联锁驱动)"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.qdc"
|
||||
outlined
|
||||
label="联锁定操驱动"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.qfc"
|
||||
outlined
|
||||
label="联锁反操驱动"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.qyc"
|
||||
outlined
|
||||
label="联锁允许操驱动"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.dc"
|
||||
outlined
|
||||
label="是否定操"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.fc"
|
||||
outlined
|
||||
label="是否反操"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.yc"
|
||||
outlined
|
||||
label="是否允许操作"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-list dense bordered padding class="rounded-borders q-my-sm">
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.sb"
|
||||
outlined
|
||||
label="是否有失表故障"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<!-- <q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.dwsb"
|
||||
outlined
|
||||
label="是否有定位失表故障"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item> -->
|
||||
<!-- <q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.fwsb"
|
||||
outlined
|
||||
label="是否有反位失表故障"
|
||||
:disable="true"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item> -->
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-checkbox
|
||||
dense
|
||||
v-model="turnoutState.jc"
|
||||
outlined
|
||||
label="是否有挤岔故障"
|
||||
:disable="true"
|
||||
/>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>{{
|
||||
item.formatFn
|
||||
? item.formatFn(turnoutState[item.key])
|
||||
: turnoutState[item.key]
|
||||
}}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
@ -206,95 +40,156 @@
|
||||
<script setup lang="ts">
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { ref, watch, onMounted, onUnmounted } from 'vue';
|
||||
import { SetSwitchParams, setSwitchPosition } from 'src/api/Simulation';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { request } from 'src/protos/request';
|
||||
import { ref, watch, onMounted, onUnmounted, toRaw } from 'vue';
|
||||
import { Dialog } from 'quasar';
|
||||
import { TurnoutStates } from 'src/drawApp/graphics/TurnoutInteraction';
|
||||
import { JlGraphic } from 'jl-graphic';
|
||||
import TurnoutOperation from 'src/components/draw-app/dialogs/TurnoutOperation.vue';
|
||||
import { request } from 'src/protos/request';
|
||||
|
||||
const $q = useQuasar();
|
||||
const lineStore = useLineStore();
|
||||
const turnoutState = ref<TurnoutStates>(new TurnoutStates());
|
||||
const name = ref('');
|
||||
const graphic = ref();
|
||||
const forcePosition = ref<request.Points.Force>(0);
|
||||
const turnoutForceOption = [
|
||||
{
|
||||
label: '无强制',
|
||||
value: request.Points.Force.FP_NONE,
|
||||
},
|
||||
{
|
||||
label: '定位',
|
||||
value: request.Points.Force.FP_DW,
|
||||
},
|
||||
{
|
||||
label: '反位',
|
||||
value: request.Points.Force.FP_FW,
|
||||
},
|
||||
{
|
||||
label: '失表',
|
||||
value: request.Points.Force.FP_SB,
|
||||
},
|
||||
];
|
||||
const options = [{ label: '设置参数' }];
|
||||
let copySelectGraphic: Turnout | null = null;
|
||||
|
||||
interface KeyType {
|
||||
label: string;
|
||||
key: keyof TurnoutStates;
|
||||
formatFn?(v: TurnoutStates[keyof TurnoutStates]): string;
|
||||
}
|
||||
|
||||
const list: KeyType[] = [
|
||||
{ label: '道岔索引', key: 'code' },
|
||||
{ label: '道岔名称', key: 'code', formatFn: getNameFormat },
|
||||
{ label: '定位(表示)', key: 'normal', formatFn: getName },
|
||||
{ label: '反位(表示)', key: 'reverse', formatFn: getName },
|
||||
{ label: '定位(实际)', key: 'dw', formatFn: getName },
|
||||
{ label: '反位(实际)', key: 'fw', formatFn: getName },
|
||||
{ label: '联锁定操驱动', key: 'qdc', formatFn: getName },
|
||||
{ label: '联锁反操驱动', key: 'qfc', formatFn: getName },
|
||||
{ label: '联锁允许操驱动', key: 'qyc', formatFn: getName },
|
||||
{ label: '是否定操采集', key: 'dc', formatFn: getName },
|
||||
{ label: '是否反操采集', key: 'fc', formatFn: getName },
|
||||
{ label: '是否允许操作采集', key: 'yc', formatFn: getName },
|
||||
{ label: '道岔强制', key: 'param', formatFn: getForceName },
|
||||
];
|
||||
|
||||
watch(
|
||||
() => lineStore.selectedGraphics,
|
||||
(val, oldVal) => {
|
||||
if (oldVal?.length == 1 && oldVal[0].type == Turnout.Type) {
|
||||
unSubscribeState(oldVal[0] as JlGraphic);
|
||||
if (oldVal?.length == 1 && oldVal[0] instanceof Turnout) {
|
||||
unSubscribeState(oldVal[0]);
|
||||
}
|
||||
if (val?.length == 1 && val[0].type == Turnout.Type) {
|
||||
graphic.value = val[0];
|
||||
setTurnoutState(val[0] as Turnout);
|
||||
if (val?.length == 1 && val[0] instanceof Turnout) {
|
||||
copySelectGraphic = toRaw(val[0]);
|
||||
initTurnoutState(val[0] as Turnout);
|
||||
} else {
|
||||
turnoutState.value = new TurnoutStates();
|
||||
name.value = '';
|
||||
graphic.value = null;
|
||||
copySelectGraphic = null;
|
||||
}
|
||||
}
|
||||
);
|
||||
function setTurnoutState(turnout: Turnout) {
|
||||
graphic.value = turnout;
|
||||
turnoutState.value = turnout.states.clone() as TurnoutStates;
|
||||
name.value = turnout.datas.code;
|
||||
subscribeState(turnout as JlGraphic);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (lineStore.selectedGraphics) {
|
||||
setTurnoutState(lineStore.selectedGraphics[0] as Turnout);
|
||||
}
|
||||
});
|
||||
onUnmounted(() => {
|
||||
if (graphic.value) {
|
||||
unSubscribeState(graphic.value as JlGraphic);
|
||||
initTurnoutState(lineStore.selectedGraphics[0] as Turnout);
|
||||
}
|
||||
});
|
||||
|
||||
const options = [
|
||||
{ label: '定操', value: request.Turnout.Operation.DC },
|
||||
{ label: '取消定操', value: request.Turnout.Operation.CancelDC },
|
||||
{ label: '反操', value: request.Turnout.Operation.FC },
|
||||
{ label: '取消反操', value: request.Turnout.Operation.CancelFC },
|
||||
{ label: '设置失表故障', value: request.Turnout.Operation.SetSB },
|
||||
{ label: '取消失表故障', value: request.Turnout.Operation.CancelSB },
|
||||
{ label: '设置挤岔故障', value: request.Turnout.Operation.SetJC },
|
||||
{ label: '取消挤岔故障', value: request.Turnout.Operation.CancelJC },
|
||||
{ label: '强制定位', value: request.Turnout.Operation.ForceDw },
|
||||
{ label: '强制反位', value: request.Turnout.Operation.ForceFw },
|
||||
{ label: '取消强制', value: request.Turnout.Operation.CancelForce },
|
||||
];
|
||||
function toDo(item: { label: string; value: number }) {
|
||||
if (!lineStore.simulationId) return;
|
||||
const obj: SetSwitchParams = {
|
||||
simulationId: lineStore?.simulationId || '',
|
||||
mapId: lineStore.mapId as number,
|
||||
deviceId: turnoutState.value.id,
|
||||
operation: item.value,
|
||||
};
|
||||
setSwitchPosition(obj).catch((err) => {
|
||||
const error = err as ApiError;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: error.title,
|
||||
});
|
||||
});
|
||||
function getNameFormat(v: number) {
|
||||
if (v) {
|
||||
return name.value;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function subscribeState(g: JlGraphic) {
|
||||
function getName(v: boolean) {
|
||||
if (v) return '是';
|
||||
return '否';
|
||||
}
|
||||
|
||||
function getForceName(param: request.Points.Force) {
|
||||
return turnoutForceOption.find((item) => item.value == param)?.label || '';
|
||||
}
|
||||
|
||||
function initTurnoutState(turnout: Turnout) {
|
||||
copySelectGraphic = toRaw(turnout);
|
||||
turnoutState.value = turnout.states.clone() as TurnoutStates;
|
||||
forcePosition.value = turnoutState.value.param?.forcePosition;
|
||||
name.value = turnout.datas.code;
|
||||
subscribeState(turnout);
|
||||
}
|
||||
|
||||
function updateState(newVal: TurnoutStates) {
|
||||
turnoutState.value = newVal.clone() as TurnoutStates;
|
||||
forcePosition.value = turnoutState.value.param?.forcePosition;
|
||||
}
|
||||
|
||||
function doTurnoutOperation(item: { label: string }) {
|
||||
if (!lineStore.simulationId) return;
|
||||
if (item.label == '设置参数') {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '道岔设置参数',
|
||||
message: '',
|
||||
component: TurnoutOperation,
|
||||
componentProps: {
|
||||
id: turnoutState.value.id,
|
||||
code: name.value,
|
||||
force: forcePosition.value,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onCancel(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function subscribeState(g: Turnout) {
|
||||
if (g) {
|
||||
g.on('stateupdate', updateState);
|
||||
}
|
||||
}
|
||||
function unSubscribeState(g: JlGraphic) {
|
||||
|
||||
function unSubscribeState(g: Turnout) {
|
||||
if (g) {
|
||||
g.off('stateupdate', updateState);
|
||||
}
|
||||
}
|
||||
function updateState(newVal: TurnoutStates) {
|
||||
turnoutState.value = newVal.clone() as TurnoutStates;
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (copySelectGraphic) {
|
||||
unSubscribeState(copySelectGraphic);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.border-box {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
margin-left: 0;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,21 +1,22 @@
|
||||
function getHost(): string {
|
||||
if (process.env.ENV_MODE == 'test') {
|
||||
return 'test.joylink.club/bjrtss-server';
|
||||
return 'test.joylink.club/bjrtsts-server';
|
||||
} else if (process.env.ENV_MODE == 'publish') {
|
||||
return 'joylink.club/bjrtss-server';
|
||||
return 'joylink.club/bjrtsts-server';
|
||||
}
|
||||
// return '192.168.3.7:9091';
|
||||
// return '192.168.3.47:9091';
|
||||
// return '192.168.3.37:9091';
|
||||
// return '192.168.3.15:9091';
|
||||
// return '192.168.3.5:9091';
|
||||
// return '192.168.33.207:9091'; // 张骞
|
||||
// return '192.168.33.93:9091';
|
||||
// return '192.168.3.37:9091'; //卫志宏
|
||||
return '192.168.3.233:9091';
|
||||
// return 'test.joylink.club/bjrtsts-service'; // 测试
|
||||
return '192.168.33.233:9091';
|
||||
}
|
||||
|
||||
export function getHttpBase() {
|
||||
let protocol = 'http';
|
||||
if (['test', 'publish'].includes(process.env.ENV_MODE as string)) {
|
||||
if (['publish'].includes(process.env.ENV_MODE as string)) {
|
||||
protocol = 'https';
|
||||
}
|
||||
return `${protocol}://${getHost()}`;
|
||||
@ -23,17 +24,18 @@ export function getHttpBase() {
|
||||
|
||||
export function getWebsocketUrl() {
|
||||
let protocol = 'ws';
|
||||
let host = '192.168.3.233';
|
||||
let host = '192.168.33.233';
|
||||
// let host = 'test.joylink.club';
|
||||
let port = '8083';
|
||||
let url = `${protocol}://${host}:${port}`;
|
||||
if (process.env.ENV_MODE == 'test') {
|
||||
protocol = 'wss';
|
||||
host = 'test.joylink.club/bjrtss-server';
|
||||
// protocol = 'wss';
|
||||
host = 'test.joylink.club/bjrtsts-server';
|
||||
port = '';
|
||||
url = `${protocol}://${host}`;
|
||||
} else if (process.env.ENV_MODE == 'publish') {
|
||||
protocol = 'wss';
|
||||
host = 'joylink.club/bjrtss-server';
|
||||
host = 'joylink.club/bjrtsts-server';
|
||||
port = '';
|
||||
url = `${protocol}://${host}`;
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ function handleSubscribe(ibpScene: IGraphicScene) {
|
||||
const ibpStore = useIbpStore();
|
||||
const simulationId = lineStore.simulationId;
|
||||
const mapId = lineStore.mapId;
|
||||
const stationId = ibpStore.stationId;
|
||||
const ibpId = ibpStore.ibpId;
|
||||
ibpScene.subscribe({
|
||||
destination: `/rtsts/simulation/${simulationId}/ibp/${mapId}/${stationId}`,
|
||||
destination: `/rtsts/simulation/${simulationId}/ibp/${mapId}/${ibpId}`,
|
||||
messageConverter: (message: Uint8Array) => {
|
||||
const states: GraphicState[] = [];
|
||||
|
||||
|
@ -19,6 +19,12 @@ import { TrainWindow } from 'src/graphics/trainWindow/TrainWindow';
|
||||
import { Transponder } from 'src/graphics/transponder/Transponder';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { ConcentrationDividingLine } from 'src/graphics/concentrationDividingLine/ConcentrationDividingLine';
|
||||
import { IbpBox } from 'src/graphics/ibpBox/IbpBox';
|
||||
import { PslBox } from 'src/graphics/pslBox/PslBox';
|
||||
import { GarageDoor } from 'src/graphics/garageDoor/GarageDoor';
|
||||
import { CarWashing } from 'src/graphics/carWashing/CarWashing';
|
||||
import { FloodGate } from 'src/graphics/floodGate/FloodGate';
|
||||
import { GarageDoorBox } from 'src/graphics/garageDoorBox/GarageDoorBox';
|
||||
|
||||
export const drawCommonLayerList = [
|
||||
// 图层列表 默认显示的图层defaultShow: true
|
||||
@ -33,6 +39,8 @@ export const drawCommonLayerList = [
|
||||
{ label: '停车位置标', value: StopPosition.Type, defaultShow: true },
|
||||
{ label: 'Spks开关', value: SpksSwitch.Type, defaultShow: true },
|
||||
{ label: '门控箱', value: GatedBox.Type, defaultShow: true },
|
||||
{ label: 'Ibp盘', value: IbpBox.Type, defaultShow: true },
|
||||
{ label: 'Psl盘', value: PslBox.Type, defaultShow: true },
|
||||
{ label: '紧急关闭按钮', value: EsbButton.Type, defaultShow: true },
|
||||
{ label: '应答器', value: Transponder.Type, defaultShow: true },
|
||||
{ label: '车次窗', value: TrainWindow.Type, defaultShow: true },
|
||||
@ -51,4 +59,8 @@ export const drawCommonLayerList = [
|
||||
value: ConcentrationDividingLine.Type,
|
||||
defaultShow: true,
|
||||
},
|
||||
{ label: '车库门', value: GarageDoor.Type, defaultShow: true },
|
||||
{ label: '防淹门', value: FloodGate.Type, defaultShow: true },
|
||||
{ label: '洗车机', value: CarWashing.Type, defaultShow: true },
|
||||
{ label: '车库门设置', value: GarageDoorBox.Type, defaultShow: true },
|
||||
];
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { TrainTemplate } from 'src/graphics/train/Train';
|
||||
import { TrainDraw } from 'src/graphics/train/TrainDrawAssistant';
|
||||
import { Signal, SignalTemplate } from 'src/graphics/signal/Signal';
|
||||
import { GraphicData, IDrawApp, ContextMenu, MenuItemOptions } from 'jl-graphic';
|
||||
import {
|
||||
GraphicData,
|
||||
IDrawApp,
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
KeyListener,
|
||||
calculateDistanceFromPointToLine,
|
||||
getRectangleCenter,
|
||||
distance2,
|
||||
} from 'jl-graphic';
|
||||
import { TrainState } from './graphics/TrainInteraction';
|
||||
import {
|
||||
SignalData,
|
||||
@ -21,6 +30,12 @@ import { PolygonDraw } from 'src/graphics/polygon/PolygonDrawAssistant';
|
||||
import { Platform, PlatformTemplate } from 'src/graphics/platform/Platform';
|
||||
import { PlatformData, PlatformState } from './graphics/PlatformInteraction';
|
||||
import { PlatformDraw } from 'src/graphics/platform/PlatformDrawAssistant';
|
||||
import { IbpBox, IbpBoxTemplate } from 'src/graphics/ibpBox/IbpBox';
|
||||
import { IbpBoxData } from './graphics/IbpBoxInteraction';
|
||||
import { IbpBoxDraw } from 'src/graphics/ibpBox/IbpBoxDrawAssistant';
|
||||
import { PslBox, PslBoxTemplate } from 'src/graphics/pslBox/PslBox';
|
||||
import { PslBoxData } from './graphics/PslBoxInteraction';
|
||||
import { PslBoxDraw } from 'src/graphics/pslBox/PslBoxDrawAssistant';
|
||||
import {
|
||||
ScreenDoor,
|
||||
ScreenDoorTemplate,
|
||||
@ -81,6 +96,15 @@ import {
|
||||
GatedBoxData,
|
||||
DrawGatedBoxInteraction,
|
||||
} from './graphics/GatedBoxInteraction';
|
||||
import {
|
||||
GarageDoorBox,
|
||||
GarageDoorBoxTemplate,
|
||||
} from 'src/graphics/garageDoorBox/GarageDoorBox';
|
||||
import {
|
||||
GarageDoorBoxData,
|
||||
DrawGarageDoorBoxInteraction,
|
||||
} from './graphics/GarageDoorBoxInteraction';
|
||||
import { GarageDoorBoxDraw } from 'src/graphics/garageDoorBox/GarageDoorBoxAssistant';
|
||||
// import { EsbButton, EsbButtonTemplate } from 'src/graphics/esbButton/EsbButton';
|
||||
// import {
|
||||
// EsbButtonData,
|
||||
@ -95,7 +119,10 @@ import {
|
||||
Transponder,
|
||||
TransponderTemplate,
|
||||
} from 'src/graphics/transponder/Transponder';
|
||||
import { TransponderData } from './graphics/TransponderInteraction';
|
||||
import {
|
||||
TransponderData,
|
||||
TransponderState,
|
||||
} from './graphics/TransponderInteraction';
|
||||
import { SlopeKiloMarkerDrawAssistant } from 'src/graphics/slopeKiloMarker/SlopeKiloMarkerDrawAssistant';
|
||||
import {
|
||||
SlopeKiloMarker,
|
||||
@ -124,6 +151,21 @@ import { Dialog } from 'quasar';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { saveDraft } from 'src/api/DraftApi';
|
||||
import { SignalDraw } from 'src/graphics/signal/SignalDrawAssistant';
|
||||
import { CarWashingData } from './graphics/CarWashingInteraction';
|
||||
import {
|
||||
CarWashing,
|
||||
CarWashingTemplate,
|
||||
} from 'src/graphics/carWashing/CarWashing';
|
||||
import { CarWashingDraw } from 'src/graphics/carWashing/CarWashingDrawAssistant';
|
||||
import { FloodGateData } from './graphics/FloodGateInteraction';
|
||||
import { FloodGate, FloodGateTemplate } from 'src/graphics/floodGate/FloodGate';
|
||||
import { FloodGateDraw } from 'src/graphics/floodGate/FloodGateDrawAssistant';
|
||||
import { GarageDoorData } from './graphics/GarageDoorInteraction';
|
||||
import {
|
||||
GarageDoor,
|
||||
GarageDoorTemplate,
|
||||
} from 'src/graphics/garageDoor/GarageDoor';
|
||||
import { GarageDoorDraw } from 'src/graphics/garageDoor/GarageDoorDrawAssistant';
|
||||
|
||||
const UndoOptions: MenuItemOptions = {
|
||||
name: '撤销',
|
||||
@ -158,6 +200,8 @@ export function initCommonDrawApp(app: IDrawApp) {
|
||||
app,
|
||||
new PlatformTemplate(new PlatformData(), new PlatformState())
|
||||
);
|
||||
new IbpBoxDraw(app, new IbpBoxTemplate(new IbpBoxData()));
|
||||
new PslBoxDraw(app, new PslBoxTemplate(new PslBoxData()));
|
||||
new ScreenDoorDraw(
|
||||
app,
|
||||
new ScreenDoorTemplate(new ScreenDoorData(), new ScreenDoorState())
|
||||
@ -181,10 +225,17 @@ export function initCommonDrawApp(app: IDrawApp) {
|
||||
new OneClickGenerateDraw(app, new OneClickGenerateTemplate());
|
||||
new AxleCountingDraw(app, new AxleCountingTemplate(new AxleCountingData()));
|
||||
new SeparatorDraw(app, new SeparatorTemplate(new SeparatorData()));
|
||||
new TransponderDraw(app, new TransponderTemplate(new TransponderData()));
|
||||
new TransponderDraw(
|
||||
app,
|
||||
new TransponderTemplate(new TransponderData(), new TransponderState())
|
||||
);
|
||||
new StopPositionDraw(app, new StopPositionTemplate(new StopPositionData()));
|
||||
new SpksSwitchDraw(app, new SpksSwitchTemplate(new SpksSwitchData()));
|
||||
new GatedBoxDraw(app, new GatedBoxTemplate(new GatedBoxData()));
|
||||
new GarageDoorBoxDraw(
|
||||
app,
|
||||
new GarageDoorBoxTemplate(new GarageDoorBoxData())
|
||||
);
|
||||
// new EsbButtonDraw(
|
||||
// app,
|
||||
// new EsbButtonTemplate(new EsbButtonData(), new EsbButtonState())
|
||||
@ -205,10 +256,14 @@ export function initCommonDrawApp(app: IDrawApp) {
|
||||
app,
|
||||
new ConcentrationDividingLineTemplate(new ConcentrationDividingLineData())
|
||||
);
|
||||
new CarWashingDraw(app, new CarWashingTemplate(new CarWashingData()));
|
||||
new FloodGateDraw(app, new FloodGateTemplate(new FloodGateData()));
|
||||
new GarageDoorDraw(app, new GarageDoorTemplate(new GarageDoorData()));
|
||||
DrawSignalInteraction.init(app);
|
||||
DrawStopPositionInteraction.init(app);
|
||||
DrawSpksSwitchInteraction.init(app);
|
||||
DrawGatedBoxInteraction.init(app);
|
||||
DrawGarageDoorBoxInteraction.init(app);
|
||||
// DrawEsbButtonInteraction.init(app);
|
||||
|
||||
// 画布右键菜单
|
||||
@ -241,6 +296,99 @@ export function initCommonDrawApp(app: IDrawApp) {
|
||||
sectionCodePointList = [];
|
||||
otherLineList = [];
|
||||
});
|
||||
// KeyA 用于区段复制--控制生成的区段位置
|
||||
const graphicCopyPlugin = app.app.graphicCopyPlugin;
|
||||
const copySectionListener = new KeyListener({
|
||||
value: 'KeyA',
|
||||
global: true,
|
||||
onPress: () => {
|
||||
graphicCopyPlugin.updateMoveLimit('sectionPointLimit');
|
||||
},
|
||||
});
|
||||
graphicCopyPlugin.addGraphicControlers([
|
||||
{
|
||||
controlerList: [copySectionListener],
|
||||
check: () => {
|
||||
if (
|
||||
graphicCopyPlugin.copys.length == 1 &&
|
||||
graphicCopyPlugin.copys[0].type == Section.Type
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
moveLimitOption: {
|
||||
moveLimitName: 'sectionPointLimit',
|
||||
moveLimit: (e) => {
|
||||
const mousePos = app.toCanvasCoordinates(e.global);
|
||||
const selectSection = app.selectedGraphics[0] as Section;
|
||||
let selectSectionLeft = selectSection.localToCanvasPoint(
|
||||
selectSection.getStartPoint()
|
||||
);
|
||||
let selectSectionRight = selectSection.localToCanvasPoint(
|
||||
selectSection.getEndPoint()
|
||||
);
|
||||
[selectSectionLeft, selectSectionRight] =
|
||||
selectSectionLeft.x < selectSectionRight.x
|
||||
? [selectSectionLeft, selectSectionRight]
|
||||
: [selectSectionRight, selectSectionLeft];
|
||||
//要移动到目标位的区段
|
||||
const sections = app.queryStore.queryByType<Section>(Section.Type);
|
||||
const minDistanceSection = sections.reduce((prev, cur) => {
|
||||
const prevDistance = calculateDistanceFromPointToLine(
|
||||
prev.localToCanvasPoint(prev.getStartPoint()),
|
||||
prev.localToCanvasPoint(prev.getEndPoint()),
|
||||
mousePos
|
||||
);
|
||||
const curDistance = calculateDistanceFromPointToLine(
|
||||
cur.localToCanvasPoint(cur.getStartPoint()),
|
||||
cur.localToCanvasPoint(cur.getEndPoint()),
|
||||
mousePos
|
||||
);
|
||||
return prevDistance > curDistance ||
|
||||
(prevDistance == curDistance &&
|
||||
distance2(
|
||||
prev.localToCanvasPoint(prev.getStartPoint()),
|
||||
mousePos
|
||||
) >
|
||||
distance2(
|
||||
cur.localToCanvasPoint(cur.getStartPoint()),
|
||||
mousePos
|
||||
))
|
||||
? cur
|
||||
: prev;
|
||||
});
|
||||
const minDistanceRefSectionsPos =
|
||||
minDistanceSection.localToCanvasPoint(
|
||||
getRectangleCenter(
|
||||
minDistanceSection.lineGraphic.getLocalBounds()
|
||||
)
|
||||
);
|
||||
let minDistanceSectionLeft = minDistanceSection.localToCanvasPoint(
|
||||
minDistanceSection.getStartPoint()
|
||||
);
|
||||
let minDistanceSectionRight = minDistanceSection.localToCanvasPoint(
|
||||
minDistanceSection.getEndPoint()
|
||||
);
|
||||
[minDistanceSectionLeft, minDistanceSectionRight] =
|
||||
minDistanceSectionLeft.x < minDistanceSectionRight.x
|
||||
? [minDistanceSectionLeft, minDistanceSectionRight]
|
||||
: [minDistanceSectionRight, minDistanceSectionLeft];
|
||||
|
||||
if (mousePos.x > minDistanceRefSectionsPos.x) {
|
||||
graphicCopyPlugin.container.position.x =
|
||||
minDistanceSectionRight.x - selectSectionLeft.x;
|
||||
graphicCopyPlugin.container.position.y =
|
||||
minDistanceSectionRight.y - selectSectionLeft.y;
|
||||
} else {
|
||||
graphicCopyPlugin.container.position.x =
|
||||
minDistanceSectionLeft.x - selectSectionRight.x;
|
||||
graphicCopyPlugin.container.position.y =
|
||||
minDistanceSectionLeft.y - selectSectionRight.y;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
export function loadCommonDrawDatas(
|
||||
@ -258,6 +406,12 @@ export function loadCommonDrawDatas(
|
||||
storage.Platforms.forEach((platform) => {
|
||||
datas.push(new PlatformData(platform));
|
||||
});
|
||||
storage.ibpBoxs.forEach((ibpBox) => {
|
||||
datas.push(new IbpBoxData(ibpBox));
|
||||
});
|
||||
storage.pslBoxs.forEach((pslBox) => {
|
||||
datas.push(new PslBoxData(pslBox));
|
||||
});
|
||||
storage.screenDoors.forEach((screenDoor) => {
|
||||
datas.push(new ScreenDoorData(screenDoor));
|
||||
});
|
||||
@ -291,6 +445,9 @@ export function loadCommonDrawDatas(
|
||||
storage.gateBoxs.forEach((gatedBox) => {
|
||||
datas.push(new GatedBoxData(gatedBox));
|
||||
});
|
||||
storage.garageDoorBoxes.forEach((garageDoorBox) => {
|
||||
datas.push(new GarageDoorBoxData(garageDoorBox));
|
||||
});
|
||||
// storage.esbButtons.forEach((esbButton) => {
|
||||
// datas.push(new EsbButtonData(esbButton));
|
||||
// });
|
||||
@ -315,6 +472,15 @@ export function loadCommonDrawDatas(
|
||||
storage.concentrationDividingLines.forEach((concentrationDividingLine) => {
|
||||
datas.push(new ConcentrationDividingLineData(concentrationDividingLine));
|
||||
});
|
||||
storage.floodGates.forEach((flood) => {
|
||||
datas.push(new FloodGateData(flood));
|
||||
});
|
||||
storage.carWashings.forEach((carWashing) => {
|
||||
datas.push(new CarWashingData(carWashing));
|
||||
});
|
||||
storage.garageDoors.forEach((garageDoor) => {
|
||||
datas.push(new GarageDoorData(garageDoor));
|
||||
});
|
||||
return datas;
|
||||
}
|
||||
|
||||
@ -322,7 +488,9 @@ export function saveCommonDrawDatas(app: IDrawApp) {
|
||||
const storage = new graphicData.RtssGraphicStorage();
|
||||
const canvasData = app.canvas.saveData();
|
||||
storage.canvas = new graphicData.Canvas({
|
||||
...canvasData,
|
||||
width: canvasData.width,
|
||||
height: canvasData.height,
|
||||
backgroundColor: canvasData.backgroundColor,
|
||||
viewportTransform: toStorageTransform(canvasData.viewportTransform),
|
||||
});
|
||||
const graphics = app.queryStore.getAllGraphics();
|
||||
@ -330,6 +498,12 @@ export function saveCommonDrawDatas(app: IDrawApp) {
|
||||
if (Platform.Type === g.type) {
|
||||
const platformData = (g as Platform).saveData();
|
||||
storage.Platforms.push((platformData as PlatformData).data);
|
||||
} else if (IbpBox.Type === g.type) {
|
||||
const ibpBoxData = (g as IbpBox).saveData();
|
||||
storage.ibpBoxs.push((ibpBoxData as IbpBoxData).data);
|
||||
} else if (PslBox.Type === g.type) {
|
||||
const pslBoxData = (g as PslBox).saveData();
|
||||
storage.pslBoxs.push((pslBoxData as PslBoxData).data);
|
||||
} else if (Station.Type === g.type) {
|
||||
const stationData = (g as Station).saveData();
|
||||
storage.stations.push((stationData as StationData).data);
|
||||
@ -366,6 +540,11 @@ export function saveCommonDrawDatas(app: IDrawApp) {
|
||||
// } else if (EsbButton.Type === g.type) {
|
||||
// const esbButtonData = (g as EsbButton).saveData();
|
||||
// storage.esbButtons.push((esbButtonData as EsbButtonData).data);
|
||||
} else if (GarageDoorBox.Type === g.type) {
|
||||
const garageDoorBoxData = (g as GarageDoorBox).saveData();
|
||||
storage.garageDoorBoxes.push(
|
||||
(garageDoorBoxData as GarageDoorBoxData).data
|
||||
);
|
||||
} else if (Transponder.Type === g.type) {
|
||||
const transponderData = (g as Transponder).saveData();
|
||||
storage.transponders.push((transponderData as TransponderData).data);
|
||||
@ -393,6 +572,15 @@ export function saveCommonDrawDatas(app: IDrawApp) {
|
||||
storage.concentrationDividingLines.push(
|
||||
(concentrationDividingLineData as ConcentrationDividingLineData).data
|
||||
);
|
||||
} else if (g instanceof CarWashing) {
|
||||
const carWashingData = g.saveData();
|
||||
storage.carWashings.push((carWashingData as CarWashingData).data);
|
||||
} else if (g instanceof FloodGate) {
|
||||
const floodGateData = g.saveData();
|
||||
storage.floodGates.push((floodGateData as FloodGateData).data);
|
||||
} else if (g instanceof GarageDoor) {
|
||||
const garageDoorData = g.saveData();
|
||||
storage.garageDoors.push((garageDoorData as GarageDoorData).data);
|
||||
}
|
||||
});
|
||||
// storage.Platforms.forEach((item) => {
|
||||
|
88
src/drawApp/graphics/CarWashingInteraction.ts
Normal file
88
src/drawApp/graphics/CarWashingInteraction.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { FederatedMouseEvent } from 'pixi.js';
|
||||
import {
|
||||
CarWashing,
|
||||
ICarWashingData,
|
||||
} from 'src/graphics/carWashing/CarWashing';
|
||||
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic';
|
||||
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
|
||||
export class CarWashingData extends GraphicDataBase implements ICarWashingData {
|
||||
constructor(data?: graphicData.CarWashing) {
|
||||
let carWashing;
|
||||
if (!data) {
|
||||
carWashing = new graphicData.CarWashing({
|
||||
common: GraphicDataBase.defaultCommonInfo(CarWashing.Type),
|
||||
});
|
||||
} else {
|
||||
carWashing = data;
|
||||
}
|
||||
super(carWashing);
|
||||
}
|
||||
|
||||
public get data(): graphicData.CarWashing {
|
||||
return this.getData<graphicData.CarWashing>();
|
||||
}
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get linkSection(): number {
|
||||
return this.data.linkSection;
|
||||
}
|
||||
set linkSection(v: number) {
|
||||
this.data.linkSection = v;
|
||||
}
|
||||
get centralizedStations(): number[] {
|
||||
return this.data.centralizedStations;
|
||||
}
|
||||
set centralizedStations(v: number[]) {
|
||||
this.data.centralizedStations = v;
|
||||
}
|
||||
clone(): CarWashingData {
|
||||
return new CarWashingData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: CarWashingData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: CarWashingData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class CarWashingOperationInteraction extends GraphicInteractionPlugin<CarWashing> {
|
||||
static Name = 'car_washing_operation';
|
||||
constructor(scene: IGraphicScene) {
|
||||
super(CarWashingOperationInteraction.Name, scene);
|
||||
}
|
||||
static init(scene: IGraphicScene) {
|
||||
return new CarWashingOperationInteraction(scene);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): CarWashing[] | undefined {
|
||||
return grahpics.filter((g): g is CarWashing => g.type === CarWashing.Type);
|
||||
}
|
||||
bind(g: CarWashing): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.on('mousedown', this.onPress, this);
|
||||
}
|
||||
unbind(g: CarWashing): void {
|
||||
g.eventMode = 'none';
|
||||
g.cursor = 'default';
|
||||
g.off('mousedown', this.onPress, this);
|
||||
}
|
||||
onPress(e: FederatedMouseEvent) {
|
||||
const g = e.target as CarWashing;
|
||||
g.on('mouseleave', this.onRelease, this);
|
||||
g.on('mouseup', this.onRelease, this);
|
||||
}
|
||||
onRelease(e: FederatedMouseEvent) {
|
||||
const g = e.target as CarWashing;
|
||||
g.off('mouseleave', this.onRelease, this);
|
||||
g.off('mouseup', this.onRelease, this);
|
||||
}
|
||||
}
|
@ -66,7 +66,8 @@ export class EsbButtonData extends GraphicDataBase implements IEsbButtonData {
|
||||
|
||||
export class EsbButtonState
|
||||
extends GraphicStateBase
|
||||
implements IEsbButtonState {
|
||||
implements IEsbButtonState
|
||||
{
|
||||
constructor(data?: state.ButtonState) {
|
||||
let ibpButtonState;
|
||||
if (data) {
|
||||
|
85
src/drawApp/graphics/FloodGateInteraction.ts
Normal file
85
src/drawApp/graphics/FloodGateInteraction.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { FederatedMouseEvent } from 'pixi.js';
|
||||
import { FloodGate, IFloodGateData } from 'src/graphics/floodGate/FloodGate';
|
||||
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic';
|
||||
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
|
||||
export class FloodGateData extends GraphicDataBase implements IFloodGateData {
|
||||
constructor(data?: graphicData.FloodGate) {
|
||||
let floodGate;
|
||||
if (!data) {
|
||||
floodGate = new graphicData.FloodGate({
|
||||
common: GraphicDataBase.defaultCommonInfo(FloodGate.Type),
|
||||
});
|
||||
} else {
|
||||
floodGate = data;
|
||||
}
|
||||
super(floodGate);
|
||||
}
|
||||
|
||||
public get data(): graphicData.FloodGate {
|
||||
return this.getData<graphicData.FloodGate>();
|
||||
}
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get linkSection(): number {
|
||||
return this.data.linkSection;
|
||||
}
|
||||
set linkSection(v: number) {
|
||||
this.data.linkSection = v;
|
||||
}
|
||||
get centralizedStations(): number[] {
|
||||
return this.data.centralizedStations;
|
||||
}
|
||||
set centralizedStations(v: number[]) {
|
||||
this.data.centralizedStations = v;
|
||||
}
|
||||
clone(): FloodGateData {
|
||||
return new FloodGateData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: FloodGateData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: FloodGateData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class FloodGateOperationInteraction extends GraphicInteractionPlugin<FloodGate> {
|
||||
static Name = 'flood_gate_operation';
|
||||
constructor(scene: IGraphicScene) {
|
||||
super(FloodGateOperationInteraction.Name, scene);
|
||||
}
|
||||
static init(scene: IGraphicScene) {
|
||||
return new FloodGateOperationInteraction(scene);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): FloodGate[] | undefined {
|
||||
return grahpics.filter((g): g is FloodGate => g.type === FloodGate.Type);
|
||||
}
|
||||
bind(g: FloodGate): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.on('mousedown', this.onPress, this);
|
||||
}
|
||||
unbind(g: FloodGate): void {
|
||||
g.eventMode = 'none';
|
||||
g.cursor = 'default';
|
||||
g.off('mousedown', this.onPress, this);
|
||||
}
|
||||
onPress(e: FederatedMouseEvent) {
|
||||
const g = e.target as FloodGate;
|
||||
g.on('mouseleave', this.onRelease, this);
|
||||
g.on('mouseup', this.onRelease, this);
|
||||
}
|
||||
onRelease(e: FederatedMouseEvent) {
|
||||
const g = e.target as FloodGate;
|
||||
g.off('mouseleave', this.onRelease, this);
|
||||
g.off('mouseup', this.onRelease, this);
|
||||
}
|
||||
}
|
150
src/drawApp/graphics/GarageDoorBoxInteraction.ts
Normal file
150
src/drawApp/graphics/GarageDoorBoxInteraction.ts
Normal file
@ -0,0 +1,150 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import {
|
||||
GarageDoorBox,
|
||||
IGarageDoorBox,
|
||||
} from 'src/graphics/garageDoorBox/GarageDoorBox';
|
||||
import {
|
||||
IGraphicApp,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
IGraphicScene,
|
||||
MenuItemOptions,
|
||||
ContextMenu,
|
||||
} from 'jl-graphic';
|
||||
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import { usePslStore } from 'src/stores/psl-store';
|
||||
|
||||
export class GarageDoorBoxData
|
||||
extends GraphicDataBase
|
||||
implements IGarageDoorBox
|
||||
{
|
||||
constructor(data?: graphicData.GarageDoorBox) {
|
||||
let garageDoorBox;
|
||||
if (!data) {
|
||||
garageDoorBox = new graphicData.GarageDoorBox({
|
||||
common: GraphicDataBase.defaultCommonInfo(GarageDoorBox.Type),
|
||||
});
|
||||
} else {
|
||||
garageDoorBox = data;
|
||||
}
|
||||
super(garageDoorBox);
|
||||
}
|
||||
|
||||
public get data(): graphicData.GarageDoorBox {
|
||||
return this.getData<graphicData.GarageDoorBox>();
|
||||
}
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get flip(): boolean {
|
||||
return this.data.flip;
|
||||
}
|
||||
set flip(v: boolean) {
|
||||
this.data.flip = v;
|
||||
}
|
||||
get refGarageDoorId(): number {
|
||||
return this.data.refGarageDoorId;
|
||||
}
|
||||
set refGarageDoorId(v: number) {
|
||||
this.data.refGarageDoorId = v;
|
||||
}
|
||||
get refPslMapCode(): string {
|
||||
return this.data.refPslMapCode;
|
||||
}
|
||||
set refPslMapCode(v: string) {
|
||||
this.data.refPslMapCode = v;
|
||||
}
|
||||
clone(): GarageDoorBoxData {
|
||||
return new GarageDoorBoxData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: GarageDoorBoxData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: GarageDoorBoxData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
const flipConfig: MenuItemOptions = {
|
||||
name: '上下翻转',
|
||||
};
|
||||
const GarageDoorBoxEditMenu: ContextMenu = ContextMenu.init({
|
||||
name: '设置车库门编辑菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [flipConfig],
|
||||
},
|
||||
],
|
||||
});
|
||||
export class DrawGarageDoorBoxInteraction extends GraphicInteractionPlugin<GarageDoorBox> {
|
||||
static Name = 'garage_door_box_draw_right_menu';
|
||||
constructor(app: IGraphicApp) {
|
||||
super(DrawGarageDoorBoxInteraction.Name, app);
|
||||
app.registerMenu(GarageDoorBoxEditMenu);
|
||||
}
|
||||
static init(app: IGraphicApp) {
|
||||
return new DrawGarageDoorBoxInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): GarageDoorBox[] | undefined {
|
||||
return grahpics
|
||||
.filter((g) => g.type === GarageDoorBox.Type)
|
||||
.map((g) => g as GarageDoorBox);
|
||||
}
|
||||
bind(g: GarageDoorBox): void {
|
||||
g.on('_rightclick', this.onContextMenu, this);
|
||||
}
|
||||
|
||||
unbind(g: GarageDoorBox): void {
|
||||
g.off('_rightclick', this.onContextMenu, this);
|
||||
}
|
||||
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const garageDoorBox = target.getGraphic() as GarageDoorBox;
|
||||
this.app.updateSelected(garageDoorBox);
|
||||
flipConfig.handler = () => {
|
||||
garageDoorBox.datas.flip = !garageDoorBox.datas.flip;
|
||||
garageDoorBox.repaint();
|
||||
};
|
||||
GarageDoorBoxEditMenu.open(e.global);
|
||||
}
|
||||
}
|
||||
|
||||
export class GarageDoorBoxOperateInteraction extends GraphicInteractionPlugin<GarageDoorBox> {
|
||||
static Name = 'garage_door_box_operate_menu';
|
||||
constructor(app: IGraphicScene) {
|
||||
super(GarageDoorBoxOperateInteraction.Name, app);
|
||||
}
|
||||
static init(app: IGraphicScene) {
|
||||
return new GarageDoorBoxOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): GarageDoorBox[] | undefined {
|
||||
return grahpics
|
||||
.filter((g) => g.type === GarageDoorBox.Type)
|
||||
.map((g) => g as GarageDoorBox);
|
||||
}
|
||||
bind(g: GarageDoorBox): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.on('_leftclick', this.onLeftClick, this);
|
||||
}
|
||||
|
||||
unbind(g: GarageDoorBox): void {
|
||||
g.eventMode = 'none';
|
||||
g.off('_leftclick', this.onLeftClick, this);
|
||||
}
|
||||
onLeftClick(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const garageDoorBox = target.getGraphic() as GarageDoorBox;
|
||||
usePslStore().setPslParam(
|
||||
garageDoorBox.datas.id,
|
||||
garageDoorBox.datas.refPslMapCode
|
||||
);
|
||||
}
|
||||
}
|
88
src/drawApp/graphics/GarageDoorInteraction.ts
Normal file
88
src/drawApp/graphics/GarageDoorInteraction.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { FederatedMouseEvent } from 'pixi.js';
|
||||
import {
|
||||
GarageDoor,
|
||||
IGarageDoorData,
|
||||
} from 'src/graphics/garageDoor/GarageDoor';
|
||||
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic';
|
||||
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
|
||||
export class GarageDoorData extends GraphicDataBase implements IGarageDoorData {
|
||||
constructor(data?: graphicData.GarageDoor) {
|
||||
let garageDoor;
|
||||
if (!data) {
|
||||
garageDoor = new graphicData.GarageDoor({
|
||||
common: GraphicDataBase.defaultCommonInfo(GarageDoor.Type),
|
||||
});
|
||||
} else {
|
||||
garageDoor = data;
|
||||
}
|
||||
super(garageDoor);
|
||||
}
|
||||
|
||||
public get data(): graphicData.GarageDoor {
|
||||
return this.getData<graphicData.GarageDoor>();
|
||||
}
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get linkSection(): number {
|
||||
return this.data.linkSection;
|
||||
}
|
||||
set linkSection(v: number) {
|
||||
this.data.linkSection = v;
|
||||
}
|
||||
get centralizedStations(): number[] {
|
||||
return this.data.centralizedStations;
|
||||
}
|
||||
set centralizedStations(v: number[]) {
|
||||
this.data.centralizedStations = v;
|
||||
}
|
||||
clone(): GarageDoorData {
|
||||
return new GarageDoorData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: GarageDoorData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: GarageDoorData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class GarageDoorOperationInteraction extends GraphicInteractionPlugin<GarageDoor> {
|
||||
static Name = 'garage_door_operation';
|
||||
constructor(scene: IGraphicScene) {
|
||||
super(GarageDoorOperationInteraction.Name, scene);
|
||||
}
|
||||
static init(scene: IGraphicScene) {
|
||||
return new GarageDoorOperationInteraction(scene);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): GarageDoor[] | undefined {
|
||||
return grahpics.filter((g): g is GarageDoor => g.type === GarageDoor.Type);
|
||||
}
|
||||
bind(g: GarageDoor): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.on('mousedown', this.onPress, this);
|
||||
}
|
||||
unbind(g: GarageDoor): void {
|
||||
g.eventMode = 'none';
|
||||
g.cursor = 'default';
|
||||
g.off('mousedown', this.onPress, this);
|
||||
}
|
||||
onPress(e: FederatedMouseEvent) {
|
||||
const g = e.target as GarageDoor;
|
||||
g.on('mouseleave', this.onRelease, this);
|
||||
g.on('mouseup', this.onRelease, this);
|
||||
}
|
||||
onRelease(e: FederatedMouseEvent) {
|
||||
const g = e.target as GarageDoor;
|
||||
g.off('mouseleave', this.onRelease, this);
|
||||
g.off('mouseup', this.onRelease, this);
|
||||
}
|
||||
}
|
@ -6,11 +6,7 @@ import {
|
||||
IIbpButtonState,
|
||||
} from 'src/graphics/IBPButton/IBPButton';
|
||||
import { ibpGraphicData } from 'src/protos/ibpGraphics';
|
||||
import {
|
||||
GraphicInteractionPlugin,
|
||||
IGraphicScene,
|
||||
JlGraphic,
|
||||
} from 'jl-graphic';
|
||||
import { GraphicInteractionPlugin, IGraphicScene, JlGraphic } from 'jl-graphic';
|
||||
import { FederatedMouseEvent } from 'pixi.js';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { useIbpStore } from 'src/stores/ibp-store';
|
||||
@ -67,7 +63,8 @@ export class IBPButtonData extends GraphicDataBase implements IIBPButtonData {
|
||||
|
||||
export class IbpButtonState
|
||||
extends GraphicStateBase
|
||||
implements IIbpButtonState {
|
||||
implements IIbpButtonState
|
||||
{
|
||||
constructor(data?: state.ButtonState) {
|
||||
let ibpButtonState;
|
||||
if (data) {
|
||||
@ -109,6 +106,7 @@ export class IbpButtonState
|
||||
// IbpScene使用
|
||||
export class IbpButtonInteraction extends GraphicInteractionPlugin<IBPButton> {
|
||||
static Name = 'ibp_button_operate_menu';
|
||||
isMouseDown = false;
|
||||
constructor(app: IGraphicScene) {
|
||||
super(IbpButtonInteraction.Name, app);
|
||||
}
|
||||
@ -132,6 +130,7 @@ export class IbpButtonInteraction extends GraphicInteractionPlugin<IBPButton> {
|
||||
g.off('mouseleave', this.onMouseLeave);
|
||||
}
|
||||
onMouseDown(e: FederatedMouseEvent) {
|
||||
this.isMouseDown = true;
|
||||
const g = e.target as IBPButton;
|
||||
const changeState = useIbpStore().ibpButtonOperation;
|
||||
if (g.datas.isSelfReset) {
|
||||
@ -141,6 +140,7 @@ export class IbpButtonInteraction extends GraphicInteractionPlugin<IBPButton> {
|
||||
}
|
||||
}
|
||||
onMouseUp(e: FederatedMouseEvent) {
|
||||
this.isMouseDown = false;
|
||||
const changeState = useIbpStore().ibpButtonOperation;
|
||||
const g = e.target as IBPButton;
|
||||
if (g.datas.isSelfReset) {
|
||||
@ -148,10 +148,13 @@ export class IbpButtonInteraction extends GraphicInteractionPlugin<IBPButton> {
|
||||
}
|
||||
}
|
||||
onMouseLeave(e: FederatedMouseEvent) {
|
||||
const changeState = useIbpStore().ibpButtonOperation;
|
||||
const g = e.target as IBPButton;
|
||||
if (g.datas.isSelfReset) {
|
||||
changeState(g.datas.id, false);
|
||||
if (this.isMouseDown) {
|
||||
const changeState = useIbpStore().ibpButtonOperation;
|
||||
const g = e.target as IBPButton;
|
||||
if (g.datas.isSelfReset) {
|
||||
changeState(g.datas.id, false);
|
||||
}
|
||||
this.isMouseDown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
88
src/drawApp/graphics/IbpBoxInteraction.ts
Normal file
88
src/drawApp/graphics/IbpBoxInteraction.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import { IbpBox, IIbpBox } from 'src/graphics/ibpBox/IbpBox';
|
||||
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic';
|
||||
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useIbpStore } from 'src/stores/ibp-store';
|
||||
|
||||
export class IbpBoxData extends GraphicDataBase implements IIbpBox {
|
||||
constructor(data?: graphicData.IbpBox) {
|
||||
let ibpBox;
|
||||
if (!data) {
|
||||
ibpBox = new graphicData.IbpBox({
|
||||
common: GraphicDataBase.defaultCommonInfo(IbpBox.Type),
|
||||
});
|
||||
} else {
|
||||
ibpBox = data;
|
||||
}
|
||||
super(ibpBox);
|
||||
}
|
||||
|
||||
public get data(): graphicData.IbpBox {
|
||||
return this.getData<graphicData.IbpBox>();
|
||||
}
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get refStationId(): number {
|
||||
return this.data.refStationId;
|
||||
}
|
||||
set refStationId(v: number) {
|
||||
this.data.refStationId = v;
|
||||
}
|
||||
get refIbpMapCode(): string {
|
||||
return this.data.refIbpMapCode;
|
||||
}
|
||||
set refIbpMapCode(v: string) {
|
||||
this.data.refIbpMapCode = v;
|
||||
}
|
||||
clone(): IbpBoxData {
|
||||
return new IbpBoxData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: IbpBoxData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: IbpBoxData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class IbpBoxOperateInteraction extends GraphicInteractionPlugin<IbpBox> {
|
||||
static Name = 'Ibp_box_operate_menu';
|
||||
constructor(app: IGraphicScene) {
|
||||
super(IbpBoxOperateInteraction.Name, app);
|
||||
}
|
||||
static init(app: IGraphicScene) {
|
||||
return new IbpBoxOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): IbpBox[] | undefined {
|
||||
return grahpics
|
||||
.filter((g) => g.type === IbpBox.Type)
|
||||
.map((g) => g as IbpBox);
|
||||
}
|
||||
bind(g: IbpBox): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.on('_leftclick', this.onLeftClick, this);
|
||||
}
|
||||
|
||||
unbind(g: IbpBox): void {
|
||||
g.eventMode = 'none';
|
||||
g.off('_leftclick', this.onLeftClick, this);
|
||||
}
|
||||
onLeftClick(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const ibpBox = target.getGraphic() as IbpBox;
|
||||
const station = this.app.queryStore.queryById<Station>(
|
||||
ibpBox.datas.refStationId
|
||||
);
|
||||
|
||||
useIbpStore().openIbpScene(station, ibpBox.datas.refIbpMapCode, ibpBox.id);
|
||||
}
|
||||
}
|
@ -3,11 +3,7 @@ import { IIbpKeyData, IIbpKeyState, IbpKey } from 'src/graphics/ibpKey/IbpKey';
|
||||
import { ibpGraphicData } from 'src/protos/ibpGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import {
|
||||
GraphicInteractionPlugin,
|
||||
IGraphicScene,
|
||||
JlGraphic,
|
||||
} from 'jl-graphic';
|
||||
import { GraphicInteractionPlugin, IGraphicScene, JlGraphic } from 'jl-graphic';
|
||||
import { type FederatedMouseEvent } from 'pixi.js';
|
||||
import { useIbpStore } from 'src/stores/ibp-store';
|
||||
|
||||
|
83
src/drawApp/graphics/PslBoxInteraction.ts
Normal file
83
src/drawApp/graphics/PslBoxInteraction.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import { PslBox, IPslBox } from 'src/graphics/pslBox/PslBox';
|
||||
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic';
|
||||
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import { usePslStore } from 'src/stores/psl-store';
|
||||
|
||||
export class PslBoxData extends GraphicDataBase implements IPslBox {
|
||||
constructor(data?: graphicData.PslBox) {
|
||||
let pslBox;
|
||||
if (!data) {
|
||||
pslBox = new graphicData.PslBox({
|
||||
common: GraphicDataBase.defaultCommonInfo(PslBox.Type),
|
||||
});
|
||||
} else {
|
||||
pslBox = data;
|
||||
}
|
||||
super(pslBox);
|
||||
}
|
||||
|
||||
public get data(): graphicData.PslBox {
|
||||
return this.getData<graphicData.PslBox>();
|
||||
}
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get refPlatformId(): number {
|
||||
return this.data.refPlatformId;
|
||||
}
|
||||
set refPlatformId(v: number) {
|
||||
this.data.refPlatformId = v;
|
||||
}
|
||||
get refPslMapCode(): string {
|
||||
return this.data.refPslMapCode;
|
||||
}
|
||||
set refPslMapCode(v: string) {
|
||||
this.data.refPslMapCode = v;
|
||||
}
|
||||
clone(): PslBoxData {
|
||||
return new PslBoxData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: PslBoxData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: PslBoxData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class PslBoxOperateInteraction extends GraphicInteractionPlugin<PslBox> {
|
||||
static Name = 'Psl_box_operate_menu';
|
||||
constructor(app: IGraphicScene) {
|
||||
super(PslBoxOperateInteraction.Name, app);
|
||||
}
|
||||
static init(app: IGraphicScene) {
|
||||
return new PslBoxOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): PslBox[] | undefined {
|
||||
return grahpics
|
||||
.filter((g) => g.type === PslBox.Type)
|
||||
.map((g) => g as PslBox);
|
||||
}
|
||||
bind(g: PslBox): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.on('_leftclick', this.onLeftClick, this);
|
||||
}
|
||||
|
||||
unbind(g: PslBox): void {
|
||||
g.eventMode = 'none';
|
||||
g.off('_leftclick', this.onLeftClick, this);
|
||||
}
|
||||
onLeftClick(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const pslBox = target.getGraphic() as PslBox;
|
||||
usePslStore().setPslParam(pslBox.datas.id, pslBox.datas.refPslMapCode);
|
||||
}
|
||||
}
|
@ -4,11 +4,7 @@ import {
|
||||
IPslButtonState,
|
||||
PslButton,
|
||||
} from 'src/graphics/pslButton/pslButton';
|
||||
import {
|
||||
GraphicInteractionPlugin,
|
||||
IGraphicScene,
|
||||
JlGraphic,
|
||||
} from 'jl-graphic';
|
||||
import { GraphicInteractionPlugin, IGraphicScene, JlGraphic } from 'jl-graphic';
|
||||
import { pslGraphicData } from 'src/protos/pslGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { pslOperate } from 'src/api/Simulation';
|
||||
@ -65,7 +61,8 @@ export class PslButtonData extends GraphicDataBase implements IPslButtonData {
|
||||
}
|
||||
export class PslButtonState
|
||||
extends GraphicStateBase
|
||||
implements IPslButtonState {
|
||||
implements IPslButtonState
|
||||
{
|
||||
constructor(proto?: state.ButtonState) {
|
||||
let states;
|
||||
if (proto) {
|
||||
@ -136,7 +133,7 @@ export class PslButtonOperateInteraction extends GraphicInteractionPlugin<PslBut
|
||||
onMouseDown(e: FederatedMouseEvent) {
|
||||
const simulationId = useLineStore().simulationId;
|
||||
const mapId = useLineStore().mapId;
|
||||
const gateBoxId = usePslStore().gatedBoxId;
|
||||
const pslId = usePslStore().pslId;
|
||||
const target = e.target as DisplayObject;
|
||||
const pslButton = target.getGraphic() as PslButton;
|
||||
if (!simulationId || !mapId) {
|
||||
@ -146,7 +143,7 @@ export class PslButtonOperateInteraction extends GraphicInteractionPlugin<PslBut
|
||||
simulationId,
|
||||
mapId,
|
||||
buttonCode: pslButton.datas.code,
|
||||
gateBoxId: gateBoxId,
|
||||
pslId: pslId,
|
||||
down: !pslButton.states.down,
|
||||
})
|
||||
.then(() => {
|
||||
@ -160,7 +157,7 @@ export class PslButtonOperateInteraction extends GraphicInteractionPlugin<PslBut
|
||||
onMouseUp(e: FederatedMouseEvent) {
|
||||
const simulationId = useLineStore().simulationId;
|
||||
const mapId = useLineStore().mapId;
|
||||
const gateBoxId = usePslStore().gatedBoxId;
|
||||
const pslId = usePslStore().pslId;
|
||||
const target = e.target as DisplayObject;
|
||||
const pslButton = target.getGraphic() as PslButton;
|
||||
if (!simulationId || !mapId || !pslButton.datas.isSelfReset) {
|
||||
@ -170,7 +167,7 @@ export class PslButtonOperateInteraction extends GraphicInteractionPlugin<PslBut
|
||||
simulationId,
|
||||
mapId,
|
||||
buttonCode: pslButton.datas.code,
|
||||
gateBoxId: gateBoxId,
|
||||
pslId: pslId,
|
||||
down: false,
|
||||
})
|
||||
.then(() => {
|
||||
|
@ -9,11 +9,17 @@ import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import {
|
||||
ContextMenu,
|
||||
GraphicInteractionPlugin,
|
||||
IGraphicScene,
|
||||
JlGraphic,
|
||||
MenuItemOptions,
|
||||
} from 'jl-graphic';
|
||||
import { loadScreenDoorConfig } from '../commonApp';
|
||||
import { Dialog } from 'quasar';
|
||||
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import ScreenDoorOperation from 'src/components/draw-app/dialogs/ScreenDoorOperation.vue';
|
||||
import { request } from 'src/protos/request';
|
||||
|
||||
export class ScreenDoorData extends GraphicDataBase implements IScreenDoorData {
|
||||
constructor(data?: graphicData.ScreenDoor) {
|
||||
@ -60,7 +66,8 @@ export class ScreenDoorData extends GraphicDataBase implements IScreenDoorData {
|
||||
|
||||
export class ScreenDoorState
|
||||
extends GraphicStateBase
|
||||
implements IScreenDoorState {
|
||||
implements IScreenDoorState
|
||||
{
|
||||
constructor(proto?: state.PsdState) {
|
||||
let states;
|
||||
if (proto) {
|
||||
@ -73,6 +80,12 @@ export class ScreenDoorState
|
||||
get code(): string {
|
||||
return this.states.id + '';
|
||||
}
|
||||
get id(): number {
|
||||
return this.states.id;
|
||||
}
|
||||
set id(id: number) {
|
||||
this.states.id = id;
|
||||
}
|
||||
get asdStates(): state.AsdState[] {
|
||||
return this.states.asdStates;
|
||||
}
|
||||
@ -85,6 +98,18 @@ export class ScreenDoorState
|
||||
set mgj(v: boolean) {
|
||||
this.states.mgj = v;
|
||||
}
|
||||
get zaw() {
|
||||
return this.states.zaw;
|
||||
}
|
||||
set zaw(v: boolean) {
|
||||
this.states.zaw = v;
|
||||
}
|
||||
get param(): request.PsdParam {
|
||||
return this.states.param;
|
||||
}
|
||||
set param(param: request.PsdParam) {
|
||||
this.states.param = param;
|
||||
}
|
||||
get states(): state.PsdState {
|
||||
return this.getState<state.PsdState>();
|
||||
}
|
||||
@ -99,11 +124,21 @@ export class ScreenDoorState
|
||||
}
|
||||
}
|
||||
|
||||
const setSceenDoorParam: MenuItemOptions = { name: '设置参数' };
|
||||
const sceenDoorOperateMenu: ContextMenu = ContextMenu.init({
|
||||
name: '屏蔽门操作菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [setSceenDoorParam],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export class ScreenDoorOperateInteraction extends GraphicInteractionPlugin<ScreenDoor> {
|
||||
static Name = 'screen_door_operate_menu';
|
||||
constructor(app: IGraphicScene) {
|
||||
super(ScreenDoorOperateInteraction.Name, app);
|
||||
// app.registerMenu();
|
||||
app.registerMenu(sceenDoorOperateMenu);
|
||||
}
|
||||
static init(app: IGraphicScene) {
|
||||
return new ScreenDoorOperateInteraction(app);
|
||||
@ -118,14 +153,40 @@ export class ScreenDoorOperateInteraction extends GraphicInteractionPlugin<Scree
|
||||
g.cursor = 'pointer';
|
||||
g.selectable = true;
|
||||
g.on('_leftclick', this.onLeftClick, this);
|
||||
g.on('rightclick', this.onContextMenu, this);
|
||||
}
|
||||
|
||||
unbind(g: ScreenDoor): void {
|
||||
g.selectable = false;
|
||||
g.eventMode = 'none';
|
||||
g.off('_leftclick', this.onLeftClick, this);
|
||||
g.off('rightclick', this.onContextMenu, this);
|
||||
}
|
||||
onLeftClick() {
|
||||
useLineStore().stateProCountIncrease();
|
||||
}
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const screenDoor = target.getGraphic<ScreenDoor>();
|
||||
if (!screenDoor) return;
|
||||
this.app.updateSelected(screenDoor);
|
||||
const lineStore = useLineStore();
|
||||
setSceenDoorParam.handler = async () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
component: ScreenDoorOperation,
|
||||
componentProps: {
|
||||
id: screenDoor.id,
|
||||
code: screenDoor.datas.code,
|
||||
sonDoorAmount: screenDoor.datas.sonDoorAmount,
|
||||
asdCodesProp: screenDoor.states.param.asdCodes,
|
||||
screenDoorForceProp: screenDoor.states.param.force,
|
||||
screenDoorFaultProp: screenDoor.states.param.fault,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
};
|
||||
sceenDoorOperateMenu.open(e.global);
|
||||
}
|
||||
}
|
||||
|
@ -17,14 +17,15 @@ import {
|
||||
} from 'jl-graphic';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { SectionGraphicHitArea } from 'src/graphics/section/SectionDrawAssistant';
|
||||
import { Dialog, Notify } from 'quasar';
|
||||
import { Dialog } from 'quasar';
|
||||
import AddTrainDialog from '../../components/draw-app/dialogs/AddTrainDialog.vue';
|
||||
import { addTrain } from 'src/api/Simulation';
|
||||
import { successNotify } from '../../utils/CommonNotify';
|
||||
import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { getKmDistance } from '../lineScene';
|
||||
import SectionOperation from 'src/components/draw-app/dialogs/SectionOperation.vue';
|
||||
import { request } from 'src/protos/request';
|
||||
import { setAxleSectionState } from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
|
||||
export class SectionData extends GraphicDataBase implements ISectionData {
|
||||
constructor(data?: graphicData.Section) {
|
||||
@ -163,6 +164,18 @@ export class SectionStates extends GraphicStateBase implements ISectionState {
|
||||
set axleFault(axleFault: boolean) {
|
||||
this.states.axleFault = axleFault;
|
||||
}
|
||||
get axleDrst(): boolean {
|
||||
return this.states.axleDrst;
|
||||
}
|
||||
set axleDrst(axleDrst: boolean) {
|
||||
this.states.axleDrst = axleDrst;
|
||||
}
|
||||
get axlePdrst(): boolean {
|
||||
return this.states.axlePdrst;
|
||||
}
|
||||
set axlePdrst(axlePdrst: boolean) {
|
||||
this.states.axlePdrst = axlePdrst;
|
||||
}
|
||||
get states(): state.SectionState {
|
||||
return this.getState<state.SectionState>();
|
||||
}
|
||||
@ -180,11 +193,13 @@ export class SectionStates extends GraphicStateBase implements ISectionState {
|
||||
const addTrainConfig: MenuItemOptions = {
|
||||
name: '添加列车',
|
||||
};
|
||||
const setSectionParam: MenuItemOptions = { name: '设置参数' };
|
||||
const setFaultOcc: MenuItemOptions = { name: '设置故障占用' };
|
||||
const SectionOperateMenu: ContextMenu = ContextMenu.init({
|
||||
name: '区段操作菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [addTrainConfig],
|
||||
items: [setSectionParam, setFaultOcc, addTrainConfig],
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -234,9 +249,33 @@ export class SectionOperateInteraction extends GraphicInteractionPlugin<Section>
|
||||
const section = target.getGraphic<Section>();
|
||||
if (!section || section.datas.sectionType != SectionType.Physical) return;
|
||||
this.app.updateSelected(section);
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
addTrainConfig.disabled = !useLineStore().trainConfigList;
|
||||
const lineStore = useLineStore();
|
||||
setSectionParam.handler = async () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
component: SectionOperation,
|
||||
componentProps: {
|
||||
id: section.id,
|
||||
code: section.datas.code,
|
||||
axleDrst: section.states.axleDrst,
|
||||
axlePdrst: section.states.axlePdrst,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
};
|
||||
setFaultOcc.handler = async () => {
|
||||
const obj = {
|
||||
simulationId: lineStore?.simulationId || '',
|
||||
mapId: lineStore.mapId as number,
|
||||
deviceId: section.id,
|
||||
operation: request.Section.Operation.SetFaultOcc,
|
||||
};
|
||||
setAxleSectionState(obj).catch((e) =>
|
||||
errorNotify('区段操作失败:' + e.title, e)
|
||||
);
|
||||
};
|
||||
addTrainConfig.disabled = !lineStore.trainConfigList;
|
||||
addTrainConfig.handler = () => {
|
||||
const relations =
|
||||
section.relationManage.getRelationsOfGraphicAndOtherType(
|
||||
@ -251,7 +290,7 @@ export class SectionOperateInteraction extends GraphicInteractionPlugin<Section>
|
||||
if (
|
||||
(other.datas.axleCountingRef.length > 1 &&
|
||||
other.datas.type ==
|
||||
graphicData.AxleCounting.TypeDetectionPoint.AxleCounting) ||
|
||||
graphicData.AxleCounting.TypeDetectionPoint.AxleCounting) ||
|
||||
other.datas.axleCountingRef.length == 1
|
||||
) {
|
||||
if (rp.getParam() == 'A') {
|
||||
@ -263,44 +302,15 @@ export class SectionOperateInteraction extends GraphicInteractionPlugin<Section>
|
||||
}
|
||||
});
|
||||
const d = getKmDistance(BKm, AKm);
|
||||
Dialog.create({
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '创建列车',
|
||||
message: '',
|
||||
component: AddTrainDialog,
|
||||
componentProps: { dev: section, kmLength: d },
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk(
|
||||
(data: {
|
||||
offset: number;
|
||||
dir: 1 | 0;
|
||||
trainLength: string;
|
||||
wheelDiameter: number;
|
||||
}) => {
|
||||
const params = {
|
||||
simulationId,
|
||||
mapId,
|
||||
up: !!data.dir,
|
||||
id: section.datas.id,
|
||||
headOffset: data.offset,
|
||||
wheelDiameter: data.wheelDiameter,
|
||||
};
|
||||
if (data.trainLength) {
|
||||
Object.assign(params, { trainLength: +data.trainLength });
|
||||
}
|
||||
addTrain(params)
|
||||
.then(() => {
|
||||
successNotify('添加列车成功!');
|
||||
})
|
||||
.catch((err) => {
|
||||
const error = err as ApiError;
|
||||
Notify.create({
|
||||
type: 'negative',
|
||||
message: `添加列车失败!: ${error.title}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
SectionOperateMenu.open(e.global);
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ import { FederatedMouseEvent, DisplayObject } from 'pixi.js';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { SignalGraphicHitArea } from 'src/graphics/signal/SignalDrawAssistant';
|
||||
import { setSignalState } from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { request } from 'src/protos/request';
|
||||
import { Dialog } from 'quasar';
|
||||
import SignalOperation from 'src/components/draw-app/dialogs/SignalOperation.vue'
|
||||
|
||||
export class SignalData extends GraphicDataBase implements ISignalData {
|
||||
constructor(data?: graphicData.Signal) {
|
||||
@ -112,6 +112,12 @@ export class SignalState extends GraphicStateBase implements ISignalState {
|
||||
set aspect(v: number) {
|
||||
this.states.aspect = v;
|
||||
}
|
||||
get param(): request.SignalParam {
|
||||
return this.states.param;
|
||||
}
|
||||
set param(v: request.SignalParam) {
|
||||
this.states.param = v;
|
||||
}
|
||||
get states(): state.SignalState {
|
||||
return this.getState<state.SignalState>();
|
||||
}
|
||||
@ -129,22 +135,9 @@ export class SignalState extends GraphicStateBase implements ISignalState {
|
||||
const mirrorFlipConfig: MenuItemOptions = {
|
||||
name: '镜像翻转',
|
||||
};
|
||||
|
||||
const signalRedConfig: MenuItemOptions = {
|
||||
name: '开红灯',
|
||||
};
|
||||
const signalGreenConfig: MenuItemOptions = {
|
||||
name: '开绿灯',
|
||||
};
|
||||
const signalYellowConfig: MenuItemOptions = {
|
||||
name: '开黄灯',
|
||||
};
|
||||
const signalGuideConfig: MenuItemOptions = {
|
||||
name: '开引导',
|
||||
};
|
||||
const signalCloseConfig: MenuItemOptions = {
|
||||
name: '关灯',
|
||||
};
|
||||
const setSignalParam: MenuItemOptions = {
|
||||
name: '设置参数'
|
||||
}
|
||||
const SignalEditMenu: ContextMenu = ContextMenu.init({
|
||||
name: '信号机编辑菜单',
|
||||
groups: [
|
||||
@ -158,11 +151,12 @@ const SignalOperateMenu: ContextMenu = ContextMenu.init({
|
||||
groups: [
|
||||
{
|
||||
items: [
|
||||
signalRedConfig,
|
||||
signalGreenConfig,
|
||||
signalYellowConfig,
|
||||
signalGuideConfig,
|
||||
signalCloseConfig,
|
||||
setSignalParam
|
||||
// signalRedConfig,
|
||||
// signalGreenConfig,
|
||||
// signalYellowConfig,
|
||||
// signalGuideConfig,
|
||||
// signalCloseConfig,
|
||||
],
|
||||
},
|
||||
],
|
||||
@ -236,63 +230,24 @@ export class SignalOperateInteraction extends GraphicInteractionPlugin<Signal> {
|
||||
const target = e.target as DisplayObject;
|
||||
const signal = target.getGraphic() as Signal;
|
||||
this.app.updateSelected(signal);
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
signalCloseConfig.handler = () => {
|
||||
setSignalState({
|
||||
simulationId,
|
||||
mapId,
|
||||
id: signal.datas.id,
|
||||
aspect: state.Signal.Aspect.OFF,
|
||||
operation: request.Signal.Operation.Display,
|
||||
}).catch((err) => {
|
||||
errorNotify('操作失败', { message: err.origin.response.data.title });
|
||||
const lineStore = useLineStore();
|
||||
|
||||
setSignalParam.handler = () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '信号机设置参数',
|
||||
message: '',
|
||||
component: SignalOperation,
|
||||
componentProps: {
|
||||
id: signal.datas.id,
|
||||
code: signal.datas.code,
|
||||
mt: signal.datas.mt,
|
||||
param: signal.states.param,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
};
|
||||
signalRedConfig.handler = () => {
|
||||
setSignalState({
|
||||
simulationId,
|
||||
mapId,
|
||||
id: signal.datas.id,
|
||||
aspect: state.Signal.Aspect.H,
|
||||
operation: request.Signal.Operation.Display,
|
||||
}).catch((err) => {
|
||||
errorNotify('操作失败', { message: err.origin.response.data.title });
|
||||
});
|
||||
};
|
||||
signalGreenConfig.handler = () => {
|
||||
setSignalState({
|
||||
simulationId,
|
||||
mapId,
|
||||
id: signal.datas.id,
|
||||
aspect: state.Signal.Aspect.L,
|
||||
operation: request.Signal.Operation.Display,
|
||||
}).catch((err) => {
|
||||
errorNotify('操作失败', { message: err.origin.response.data.title });
|
||||
});
|
||||
};
|
||||
signalYellowConfig.handler = () => {
|
||||
setSignalState({
|
||||
simulationId,
|
||||
mapId,
|
||||
id: signal.datas.id,
|
||||
aspect: state.Signal.Aspect.U,
|
||||
operation: request.Signal.Operation.Display,
|
||||
}).catch((err) => {
|
||||
errorNotify('操作失败', { message: err.origin.response.data.title });
|
||||
});
|
||||
};
|
||||
signalGuideConfig.handler = () => {
|
||||
setSignalState({
|
||||
simulationId,
|
||||
mapId,
|
||||
id: signal.datas.id,
|
||||
aspect: state.Signal.Aspect.HU,
|
||||
operation: request.Signal.Operation.Display,
|
||||
}).catch((err) => {
|
||||
errorNotify('操作失败', { message: err.origin.response.data.title });
|
||||
});
|
||||
};
|
||||
}
|
||||
SignalOperateMenu.open(e.global);
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,7 @@ import {
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import {
|
||||
IGraphicScene,
|
||||
GraphicInteractionPlugin,
|
||||
JlGraphic,
|
||||
} from 'jl-graphic';
|
||||
import { IGraphicScene, GraphicInteractionPlugin, JlGraphic } from 'jl-graphic';
|
||||
import { KilometerSystem } from 'src/graphics/signal/Signal';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
|
||||
@ -43,6 +39,12 @@ export class StationData extends GraphicDataBase implements IStationData {
|
||||
set stationName(v: string) {
|
||||
this.data.stationName = v;
|
||||
}
|
||||
get stationNameAcronym(): string {
|
||||
return this.data.stationNameAcronym;
|
||||
}
|
||||
set stationNameAcronym(v: string) {
|
||||
this.data.stationNameAcronym = v;
|
||||
}
|
||||
get kilometerSystem(): KilometerSystem {
|
||||
if (!this.data.kilometerSystem) {
|
||||
this.data.kilometerSystem = new graphicData.KilometerSystem();
|
||||
@ -58,12 +60,6 @@ export class StationData extends GraphicDataBase implements IStationData {
|
||||
set concentrationStations(v: boolean) {
|
||||
this.data.concentrationStations = v;
|
||||
}
|
||||
get refIbpMapCode(): string {
|
||||
return this.data.refIbpMapCode;
|
||||
}
|
||||
set refIbpMapCode(v: string) {
|
||||
this.data.refIbpMapCode = v;
|
||||
}
|
||||
get depots(): boolean {
|
||||
return this.data.depots;
|
||||
}
|
||||
|
122
src/drawApp/graphics/TccButtonInteraction.ts
Normal file
122
src/drawApp/graphics/TccButtonInteraction.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { GraphicInteractionPlugin, IGraphicScene, JlGraphic } from 'jl-graphic';
|
||||
import { tccGraphicData } from 'src/protos/tccGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import { useTccStore } from 'src/stores/tcc-store';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import {
|
||||
ITccButtonData,
|
||||
ITccButtonState,
|
||||
TccButton,
|
||||
} from 'src/graphics/tccButton/TccButton';
|
||||
|
||||
export class TccButtonData extends GraphicDataBase implements ITccButtonData {
|
||||
constructor(data?: tccGraphicData.TccButton) {
|
||||
let tccButton;
|
||||
if (data) {
|
||||
tccButton = data;
|
||||
} else {
|
||||
tccButton = new tccGraphicData.TccButton({
|
||||
common: GraphicDataBase.defaultCommonInfo(TccButton.Type),
|
||||
});
|
||||
}
|
||||
super(tccButton);
|
||||
}
|
||||
|
||||
public get data(): tccGraphicData.TccButton {
|
||||
return this.getData<tccGraphicData.TccButton>();
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get isSelfReset(): boolean {
|
||||
return this.data.isSelfReset;
|
||||
}
|
||||
set isSelfReset(v: boolean) {
|
||||
this.data.isSelfReset = v;
|
||||
}
|
||||
clone(): TccButtonData {
|
||||
return new TccButtonData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: TccButtonData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: TccButtonData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
export class TccButtonState
|
||||
extends GraphicStateBase
|
||||
implements ITccButtonState
|
||||
{
|
||||
constructor(proto?: state.TrainControlState.EmergentButton) {
|
||||
let states;
|
||||
if (proto) {
|
||||
states = proto;
|
||||
} else {
|
||||
states = new state.TrainControlState.EmergentButton();
|
||||
}
|
||||
super(states, TccButton.Type);
|
||||
}
|
||||
get code(): string {
|
||||
return this.states.id + '';
|
||||
}
|
||||
get down(): boolean {
|
||||
return this.states.passed;
|
||||
}
|
||||
set down(v: boolean) {
|
||||
this.states.passed = v;
|
||||
}
|
||||
get states(): state.TrainControlState.EmergentButton {
|
||||
return this.getState<state.TrainControlState.EmergentButton>();
|
||||
}
|
||||
clone(): TccButtonState {
|
||||
return new TccButtonState(this.states.cloneMessage());
|
||||
}
|
||||
copyFrom(data: GraphicStateBase): void {
|
||||
pb_1.Message.copyInto(data._state, this._state);
|
||||
}
|
||||
eq(data: GraphicStateBase): boolean {
|
||||
return pb_1.Message.equals(this._state, data._state);
|
||||
}
|
||||
}
|
||||
|
||||
export class TccButtonOperateInteraction extends GraphicInteractionPlugin<TccButton> {
|
||||
static Name = 'tcc_button_operate_menu';
|
||||
constructor(app: IGraphicScene) {
|
||||
super(TccButtonOperateInteraction.Name, app);
|
||||
}
|
||||
static init(app: IGraphicScene) {
|
||||
return new TccButtonOperateInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): TccButton[] | undefined {
|
||||
return grahpics
|
||||
.filter((g) => g.type === TccButton.Type)
|
||||
.map((g) => g as TccButton);
|
||||
}
|
||||
bind(g: TccButton): void {
|
||||
g._tccButton.eventMode = 'static';
|
||||
g._tccButton.cursor = 'pointer';
|
||||
g._tccButton.on('_leftclick', this.onClick);
|
||||
}
|
||||
|
||||
unbind(g: TccButton): void {
|
||||
g._tccButton.eventMode = 'none';
|
||||
g._tccButton.off('_leftclick', this.onClick);
|
||||
}
|
||||
|
||||
onClick(e: FederatedMouseEvent): void {
|
||||
const target = e.target as DisplayObject;
|
||||
const tccButton = target.getGraphic<TccButton>();
|
||||
if (!tccButton) return;
|
||||
tccButton.states.down = !tccButton.states.down;
|
||||
tccButton.doRepaint();
|
||||
console.log(tccButton.states.down);
|
||||
}
|
||||
}
|
147
src/drawApp/graphics/TccHandleInteraction.ts
Normal file
147
src/drawApp/graphics/TccHandleInteraction.ts
Normal file
@ -0,0 +1,147 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import {
|
||||
ITccHandleData,
|
||||
ITccHandleState,
|
||||
TccHandle,
|
||||
} from 'src/graphics/tccHandle/TccHandle';
|
||||
import { tccGraphicData } from 'src/protos/tccGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { GraphicInteractionPlugin, IGraphicScene, JlGraphic } from 'jl-graphic';
|
||||
import { type FederatedMouseEvent, DisplayObject } from 'pixi.js';
|
||||
import { useTccStore } from 'src/stores/tcc-store';
|
||||
|
||||
export class TccHandleData extends GraphicDataBase implements ITccHandleData {
|
||||
constructor(data?: tccGraphicData.TccHandle) {
|
||||
let tccHandle;
|
||||
if (data) {
|
||||
tccHandle = data;
|
||||
} else {
|
||||
tccHandle = new tccGraphicData.TccHandle({
|
||||
common: GraphicDataBase.defaultCommonInfo(TccHandle.Type),
|
||||
});
|
||||
}
|
||||
super(tccHandle);
|
||||
}
|
||||
|
||||
public get data(): tccGraphicData.TccHandle {
|
||||
return this.getData<tccGraphicData.TccHandle>();
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
clone(): TccHandleData {
|
||||
return new TccHandleData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: TccHandleData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: TccHandleData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class TccHandleState
|
||||
extends GraphicStateBase
|
||||
implements ITccHandleState
|
||||
{
|
||||
constructor(data?: state.TrainControlState.PushHandler) {
|
||||
let tccHandleState;
|
||||
if (data) {
|
||||
tccHandleState = data;
|
||||
} else {
|
||||
tccHandleState = new state.TrainControlState.PushHandler();
|
||||
}
|
||||
super(tccHandleState, TccHandle.Type);
|
||||
}
|
||||
get code(): string {
|
||||
return this.states.id + '';
|
||||
}
|
||||
get states(): state.TrainControlState.PushHandler {
|
||||
return this.getState<state.TrainControlState.PushHandler>();
|
||||
}
|
||||
get gear(): number {
|
||||
return this.states.val;
|
||||
}
|
||||
set gear(v: number) {
|
||||
this.states.val = v;
|
||||
}
|
||||
clone(): TccHandleState {
|
||||
return new TccHandleState(this.states.cloneMessage());
|
||||
}
|
||||
copyFrom(data: GraphicStateBase): void {
|
||||
pb_1.Message.copyInto(data._state, this._state);
|
||||
}
|
||||
eq(data: GraphicStateBase): boolean {
|
||||
return pb_1.Message.equals(this._state, data._state);
|
||||
}
|
||||
}
|
||||
|
||||
export class TccHandleInteraction extends GraphicInteractionPlugin<TccHandle> {
|
||||
static Name = 'TccHandleInteraction';
|
||||
isMouseDown = false;
|
||||
mouseDownBeginPos = 0;
|
||||
mouseDownTccHandleBeginPos = 0;
|
||||
constructor(app: IGraphicScene) {
|
||||
super(TccHandleInteraction.Name, app);
|
||||
}
|
||||
static init(app: IGraphicScene) {
|
||||
return new TccHandleInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): TccHandle[] | undefined {
|
||||
return grahpics.filter((g): g is TccHandle => g instanceof TccHandle);
|
||||
}
|
||||
bind(g: TccHandle): void {
|
||||
g._tccHandle.eventMode = 'static';
|
||||
g._tccHandle.cursor = 'Move';
|
||||
g._tccHandle.onmousedown = (e) => {
|
||||
this.onMouseDown(e);
|
||||
};
|
||||
g._tccHandle.onmouseup = () => {
|
||||
this.isMouseDown = false;
|
||||
};
|
||||
g.onmousemove = (e) => {
|
||||
this.onMouseMove(e);
|
||||
};
|
||||
g.onmouseleave = () => {
|
||||
this.isMouseDown = false;
|
||||
};
|
||||
}
|
||||
unbind(g: TccHandle): void {
|
||||
g._tccHandle.eventMode = 'none';
|
||||
g._tccHandle.onmousedown = null;
|
||||
g._tccHandle.onmouseup = null;
|
||||
g.onmousemove = null;
|
||||
g.onmouseleave = null;
|
||||
}
|
||||
onMouseDown(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const tccHandle = target.getGraphic<TccHandle>();
|
||||
if (!tccHandle) return;
|
||||
this.isMouseDown = true;
|
||||
this.mouseDownBeginPos = e.clientY;
|
||||
this.mouseDownTccHandleBeginPos = tccHandle._tccHandle.y;
|
||||
}
|
||||
onMouseMove(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const tccHandle = target.getGraphic<TccHandle>();
|
||||
if (!tccHandle) return;
|
||||
if (
|
||||
this.isMouseDown &&
|
||||
tccHandle._tccHandle.y > -145 &&
|
||||
tccHandle._tccHandle.y < 145
|
||||
) {
|
||||
tccHandle._tccHandle.y =
|
||||
this.mouseDownTccHandleBeginPos + e.clientY - this.mouseDownBeginPos;
|
||||
if (tccHandle._tccHandle.y >= 145) {
|
||||
tccHandle._tccHandle.y = 144;
|
||||
} else if (tccHandle._tccHandle.y <= -145) {
|
||||
tccHandle._tccHandle.y = -144;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
209
src/drawApp/graphics/TccKeyInteraction.ts
Normal file
209
src/drawApp/graphics/TccKeyInteraction.ts
Normal file
@ -0,0 +1,209 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { ITccKeyData, ITccKeyState, TccKey } from 'src/graphics/tccKey/TccKey';
|
||||
import { tccGraphicData } from 'src/protos/tccGraphics';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { GraphicInteractionPlugin, IGraphicScene, JlGraphic } from 'jl-graphic';
|
||||
import { type FederatedMouseEvent, DisplayObject, Point } from 'pixi.js';
|
||||
import { useTccStore } from 'src/stores/tcc-store';
|
||||
|
||||
export class TccKeyData extends GraphicDataBase implements ITccKeyData {
|
||||
constructor(data?: tccGraphicData.TccKey) {
|
||||
let tccKey;
|
||||
if (data) {
|
||||
tccKey = data;
|
||||
} else {
|
||||
tccKey = new tccGraphicData.TccKey({
|
||||
common: GraphicDataBase.defaultCommonInfo(TccKey.Type),
|
||||
});
|
||||
}
|
||||
super(tccKey);
|
||||
}
|
||||
|
||||
public get data(): tccGraphicData.TccKey {
|
||||
return this.getData<tccGraphicData.TccKey>();
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get type(): tccGraphicData.TccKey.TccKeyType {
|
||||
return this.data.type;
|
||||
}
|
||||
set type(v: tccGraphicData.TccKey.TccKeyType) {
|
||||
this.data.type = v;
|
||||
}
|
||||
clone(): TccKeyData {
|
||||
return new TccKeyData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: TccKeyData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: TccKeyData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
export class TccKeyState extends GraphicStateBase implements ITccKeyState {
|
||||
constructor(data?: state.TrainControlState.DirectionKeySwitch) {
|
||||
let tccKeyState;
|
||||
if (data) {
|
||||
tccKeyState = data;
|
||||
} else {
|
||||
tccKeyState = new state.TrainControlState.DirectionKeySwitch();
|
||||
}
|
||||
super(tccKeyState, TccKey.Type);
|
||||
}
|
||||
get code(): string {
|
||||
return this.states.id + '';
|
||||
}
|
||||
get states(): state.TrainControlState.DirectionKeySwitch {
|
||||
return this.getState<state.TrainControlState.DirectionKeySwitch>();
|
||||
}
|
||||
get position(): number {
|
||||
return this.states.val;
|
||||
}
|
||||
set position(v: number) {
|
||||
this.states.val = v;
|
||||
}
|
||||
clone(): TccKeyState {
|
||||
return new TccKeyState(this.states.cloneMessage());
|
||||
}
|
||||
copyFrom(data: GraphicStateBase): void {
|
||||
pb_1.Message.copyInto(data._state, this._state);
|
||||
}
|
||||
eq(data: GraphicStateBase): boolean {
|
||||
return pb_1.Message.equals(this._state, data._state);
|
||||
}
|
||||
}
|
||||
|
||||
export class TccKeyInteraction extends GraphicInteractionPlugin<TccKey> {
|
||||
static Name = 'TccKeyInteraction';
|
||||
isMouseDown = false;
|
||||
changeOnce = false;
|
||||
mouseDownBeginPos = new Point();
|
||||
constructor(app: IGraphicScene) {
|
||||
super(TccKeyInteraction.Name, app);
|
||||
}
|
||||
static init(app: IGraphicScene) {
|
||||
return new TccKeyInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): TccKey[] | undefined {
|
||||
return grahpics.filter((g): g is TccKey => g instanceof TccKey);
|
||||
}
|
||||
bind(g: TccKey): void {
|
||||
g._tccKey.eventMode = 'static';
|
||||
g._tccKey.cursor = 'pointer';
|
||||
if (
|
||||
g.datas.type ==
|
||||
tccGraphicData.TccKey.TccKeyType.driverControllerActivationClint
|
||||
) {
|
||||
g._tccKey.on('_leftclick', this.onClick);
|
||||
} else {
|
||||
g._tccKey.onmousedown = (e) => {
|
||||
this.onMouseDown(e);
|
||||
};
|
||||
g._tccKey.onmouseup = () => {
|
||||
this.isMouseDown = false;
|
||||
this.changeOnce = false;
|
||||
};
|
||||
g.onmousemove = (e) => {
|
||||
this.onMousemove(e);
|
||||
};
|
||||
g.onmouseleave = () => {
|
||||
this.isMouseDown = false;
|
||||
this.changeOnce = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
unbind(g: TccKey): void {
|
||||
g._tccKey.eventMode = 'none';
|
||||
if (
|
||||
g.datas.type ==
|
||||
tccGraphicData.TccKey.TccKeyType.driverControllerActivationClint
|
||||
) {
|
||||
g._tccKey.off('_leftclick', this.onClick);
|
||||
} else {
|
||||
g._tccKey.onmousedown = null;
|
||||
g._tccKey.onmouseup = null;
|
||||
g.onmousemove = null;
|
||||
g.onmouseleave = null;
|
||||
}
|
||||
}
|
||||
onClick(e: FederatedMouseEvent): void {
|
||||
const target = e.target as DisplayObject;
|
||||
const tccKey = target.getGraphic<TccKey>();
|
||||
if (!tccKey) return;
|
||||
tccKey.state.position = tccKey?.state.position == 0 ? 1 : 0;
|
||||
tccKey.doRepaint();
|
||||
}
|
||||
onMouseDown(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const tccKey = target.getGraphic<TccKey>();
|
||||
if (!tccKey) return;
|
||||
this.isMouseDown = true;
|
||||
this.mouseDownBeginPos = tccKey
|
||||
.getGraphicApp()
|
||||
.getScene('tcc')
|
||||
.toCanvasCoordinates(e.global);
|
||||
}
|
||||
onMousemove(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const tccKey = target.getGraphic<TccKey>();
|
||||
if (!tccKey) return;
|
||||
if (this.isMouseDown) {
|
||||
const mouseEndPos = tccKey
|
||||
.getGraphicApp()
|
||||
.getScene('tcc')
|
||||
.toCanvasCoordinates(e.global);
|
||||
const { angle, direction } = calculateAngleAndDirection(
|
||||
this.mouseDownBeginPos,
|
||||
tccKey.position,
|
||||
mouseEndPos
|
||||
);
|
||||
if (
|
||||
direction == 'ssz' &&
|
||||
((angle > 45 && !this.changeOnce) || (angle > 90 && this.changeOnce)) &&
|
||||
(tccKey._tccKey.rotation == -Math.PI / 4 ||
|
||||
tccKey._tccKey.rotation == 0)
|
||||
) {
|
||||
this.changeOnce = true;
|
||||
tccKey._tccKey.rotation += Math.PI / 4;
|
||||
}
|
||||
if (
|
||||
direction == 'nsz' &&
|
||||
((angle > 45 && !this.changeOnce) || (angle > 90 && this.changeOnce)) &&
|
||||
(tccKey._tccKey.rotation == Math.PI / 4 || tccKey._tccKey.rotation == 0)
|
||||
) {
|
||||
this.changeOnce = true;
|
||||
tccKey._tccKey.rotation -= Math.PI / 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function calculateAngleAndDirection(
|
||||
pointA: Point,
|
||||
pointO: Point,
|
||||
pointB: Point
|
||||
) {
|
||||
const vectorAO = { x: pointA.x - pointO.x, y: pointA.y - pointO.y };
|
||||
const vectorOB = { x: pointB.x - pointO.x, y: pointB.y - pointO.y };
|
||||
const dotProduct = vectorAO.x * vectorOB.x + vectorAO.y * vectorOB.y;
|
||||
const magnitudeAO = Math.sqrt(vectorAO.x ** 2 + vectorAO.y ** 2);
|
||||
const magnitudeOB = Math.sqrt(vectorOB.x ** 2 + vectorOB.y ** 2);
|
||||
const angle =
|
||||
Math.acos(dotProduct / (magnitudeAO * magnitudeOB)) * (180 / Math.PI);
|
||||
const crossProduct = vectorAO.x * vectorOB.y - vectorAO.y * vectorOB.x;
|
||||
let rotationDirection = '';
|
||||
if (crossProduct > 0) {
|
||||
rotationDirection = 'ssz';
|
||||
} else {
|
||||
rotationDirection = 'nsz';
|
||||
}
|
||||
|
||||
return { angle: angle, direction: rotationDirection };
|
||||
}
|
59
src/drawApp/graphics/TccTextContentInteraction.ts
Normal file
59
src/drawApp/graphics/TccTextContentInteraction.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import {
|
||||
ITextContentData,
|
||||
TextContent,
|
||||
} from 'src/graphics/textContent/TextContent';
|
||||
import { tccGraphicData } from 'src/protos/tccGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
|
||||
export class TccTextData extends GraphicDataBase implements ITextContentData {
|
||||
constructor(data?: tccGraphicData.TccText) {
|
||||
let tccText;
|
||||
if (data) {
|
||||
tccText = data;
|
||||
} else {
|
||||
tccText = new tccGraphicData.TccText({
|
||||
common: GraphicDataBase.defaultCommonInfo(TextContent.Type),
|
||||
});
|
||||
}
|
||||
super(tccText);
|
||||
}
|
||||
|
||||
public get data(): tccGraphicData.TccText {
|
||||
return this.getData<tccGraphicData.TccText>();
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get content(): string {
|
||||
return this.data.content;
|
||||
}
|
||||
set content(v: string) {
|
||||
this.data.content = v;
|
||||
}
|
||||
get color(): string {
|
||||
return this.data.color;
|
||||
}
|
||||
set color(v: string) {
|
||||
this.data.color = v;
|
||||
}
|
||||
get fontSize(): number {
|
||||
return this.data.fontSize;
|
||||
}
|
||||
set fontSize(v: number) {
|
||||
this.data.fontSize = v;
|
||||
}
|
||||
clone(): TccTextData {
|
||||
return new TccTextData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: TccTextData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: TccTextData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
@ -10,10 +10,12 @@ import {
|
||||
ContextMenu,
|
||||
} from 'jl-graphic';
|
||||
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import { removeTrain, updateTrain } from 'src/api/Simulation';
|
||||
import { removeTrain } from 'src/api/Simulation';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { successNotify, errorNotify } from '../../utils/CommonNotify';
|
||||
import { Dialog } from 'quasar';
|
||||
import SetTrainParam from 'src/components/draw-app/dialogs/SetTrainParam.vue';
|
||||
import SetTrainLink from 'src/components/draw-app/dialogs/SetTrainLink.vue';
|
||||
export class TrainState extends GraphicStateBase implements ITrainState {
|
||||
constructor(proto?: state.TrainMapState) {
|
||||
let states;
|
||||
@ -395,6 +397,285 @@ export class TrainState extends GraphicStateBase implements ITrainState {
|
||||
set vobcInterruption(v: boolean) {
|
||||
this.states.vobcInterruption = v;
|
||||
}
|
||||
get davisParamA(): number {
|
||||
return +this.states.trainDynamicConfig.davisParamA;
|
||||
}
|
||||
set davisParamA(v: number) {
|
||||
this.states.trainDynamicConfig.davisParamA = v + '';
|
||||
}
|
||||
get davisParamB(): number {
|
||||
return +this.states.trainDynamicConfig.davisParamB;
|
||||
}
|
||||
set davisParamB(v: number) {
|
||||
this.states.trainDynamicConfig.davisParamB = v + '';
|
||||
}
|
||||
get davisParamC(): number {
|
||||
return +this.states.trainDynamicConfig.davisParamC;
|
||||
}
|
||||
set davisParamC(v: number) {
|
||||
this.states.trainDynamicConfig.davisParamC = v + '';
|
||||
}
|
||||
get curveResistanceParamR1(): number {
|
||||
return +this.states.trainDynamicConfig.curveResistanceParamR1;
|
||||
}
|
||||
set curveResistanceParamR1(v: number) {
|
||||
this.states.trainDynamicConfig.curveResistanceParamR1 = v + '';
|
||||
}
|
||||
get curveResistanceParamR2(): number {
|
||||
return +this.states.trainDynamicConfig.curveResistanceParamR2;
|
||||
}
|
||||
set curveResistanceParamR2(v: number) {
|
||||
this.states.trainDynamicConfig.curveResistanceParamR2 = v + '';
|
||||
}
|
||||
get curveResistanceParamR3(): number {
|
||||
return +this.states.trainDynamicConfig.curveResistanceParamR3;
|
||||
}
|
||||
set curveResistanceParamR3(v: number) {
|
||||
this.states.trainDynamicConfig.curveResistanceParamR3 = v + '';
|
||||
}
|
||||
get curveResistanceParamR4(): number {
|
||||
return +this.states.trainDynamicConfig.curveResistanceParamR4;
|
||||
}
|
||||
set curveResistanceParamR4(v: number) {
|
||||
this.states.trainDynamicConfig.curveResistanceParamR4 = v + '';
|
||||
}
|
||||
get revolvingMassParam(): number {
|
||||
return +this.states.trainDynamicConfig.revolvingMassParam;
|
||||
}
|
||||
set revolvingMassParam(v: number) {
|
||||
this.states.trainDynamicConfig.revolvingMassParam = v + '';
|
||||
}
|
||||
get jump(): boolean {
|
||||
return this.states.trainDynamicConfig.jump;
|
||||
}
|
||||
set jump(v: boolean) {
|
||||
this.states.trainDynamicConfig.jump = v;
|
||||
}
|
||||
get slipA(): number {
|
||||
return +this.states.trainDynamicConfig.slipA;
|
||||
}
|
||||
set slipA(v: number) {
|
||||
this.states.trainDynamicConfig.slipA = v + '';
|
||||
}
|
||||
get slipR(): number {
|
||||
return +this.states.trainDynamicConfig.slipR;
|
||||
}
|
||||
set slipR(v: number) {
|
||||
this.states.trainDynamicConfig.slipR = v + '';
|
||||
}
|
||||
get slipD(): number {
|
||||
return this.states.trainDynamicConfig.slipD;
|
||||
}
|
||||
set slipD(v: number) {
|
||||
this.states.trainDynamicConfig.slipD = v;
|
||||
}
|
||||
get slide(): number {
|
||||
return +this.states.trainDynamicConfig.slide;
|
||||
}
|
||||
set slide(v: number) {
|
||||
this.states.trainDynamicConfig.slide = v + '';
|
||||
}
|
||||
get idlingA(): number {
|
||||
return +this.states.trainDynamicConfig.idlingA;
|
||||
}
|
||||
set idlingA(v: number) {
|
||||
this.states.trainDynamicConfig.idlingA = v + '';
|
||||
}
|
||||
get idlingR(): number {
|
||||
return +this.states.trainDynamicConfig.idlingR;
|
||||
}
|
||||
set idlingR(v: number) {
|
||||
this.states.trainDynamicConfig.idlingR = v + '';
|
||||
}
|
||||
get idlingD(): number {
|
||||
return this.states.trainDynamicConfig.idlingD;
|
||||
}
|
||||
set idlingD(v: number) {
|
||||
this.states.trainDynamicConfig.idlingD = v;
|
||||
}
|
||||
get stopSign(): number {
|
||||
return this.states.trainDynamicConfig.stopSign;
|
||||
}
|
||||
set stopSign(v: number) {
|
||||
this.states.trainDynamicConfig.stopSign = v;
|
||||
}
|
||||
get aSpeedSensorEnableA(): boolean {
|
||||
return this.states.trainEndsA.speedSensorEnableA;
|
||||
}
|
||||
set aSpeedSensorEnableA(v: boolean) {
|
||||
this.states.trainEndsA.speedSensorEnableA = v;
|
||||
}
|
||||
get aSpeedSensorEnableB(): boolean {
|
||||
return this.states.trainEndsA.speedSensorEnableB;
|
||||
}
|
||||
set aSpeedSensorEnableB(v: boolean) {
|
||||
this.states.trainEndsA.speedSensorEnableB = v;
|
||||
}
|
||||
get aRadarEnable(): boolean {
|
||||
return this.states.trainEndsA.radarEnable;
|
||||
}
|
||||
set aRadarEnable(v: boolean) {
|
||||
this.states.trainEndsA.radarEnable = v;
|
||||
}
|
||||
get aRadarCheckSpeedDiff(): number {
|
||||
return +this.states.trainEndsA.radarCheckSpeedDiff;
|
||||
}
|
||||
set aRadarCheckSpeedDiff(v: number) {
|
||||
this.states.trainEndsA.radarCheckSpeedDiff + '';
|
||||
}
|
||||
get aRadarCheckTime(): number {
|
||||
return this.states.trainEndsA.radarCheckTime;
|
||||
}
|
||||
set aRadarCheckTime(v: number) {
|
||||
this.states.trainEndsA.radarCheckTime = v;
|
||||
}
|
||||
get bSpeedSensorEnableA(): boolean {
|
||||
return this.states.trainEndsB.speedSensorEnableA;
|
||||
}
|
||||
set bSpeedSensorEnableA(v: boolean) {
|
||||
this.states.trainEndsB.speedSensorEnableA = v;
|
||||
}
|
||||
get bSpeedSensorEnableB(): boolean {
|
||||
return this.states.trainEndsB.speedSensorEnableB;
|
||||
}
|
||||
set bSpeedSensorEnableB(v: boolean) {
|
||||
this.states.trainEndsB.speedSensorEnableB = v;
|
||||
}
|
||||
get bRadarEnable(): boolean {
|
||||
return this.states.trainEndsB.radarEnable;
|
||||
}
|
||||
set bRadarEnable(v: boolean) {
|
||||
this.states.trainEndsB.radarEnable;
|
||||
}
|
||||
get bRadarCheckSpeedDiff(): number {
|
||||
return +this.states.trainEndsB.radarCheckSpeedDiff;
|
||||
}
|
||||
set bRadarCheckSpeedDiff(v: number) {
|
||||
this.states.trainEndsB.radarCheckSpeedDiff = v + '';
|
||||
}
|
||||
get bRadarCheckTime(): number {
|
||||
return this.states.trainEndsB.radarCheckTime;
|
||||
}
|
||||
set bRadarCheckTime(v: number) {
|
||||
this.states.trainEndsB.radarCheckTime = v;
|
||||
}
|
||||
get aAccEnable(): boolean {
|
||||
return this.states.trainEndsA.accEnable;
|
||||
}
|
||||
set aAccEnable(v: boolean) {
|
||||
this.states.trainEndsA.accEnable = v;
|
||||
}
|
||||
get aAccCheckTime(): number {
|
||||
return this.states.trainEndsA.accCheckTime;
|
||||
}
|
||||
set aAccCheckTime(v: number) {
|
||||
this.states.trainEndsA.accCheckTime = v;
|
||||
}
|
||||
get aAccCheckSpeedDiff(): number {
|
||||
return +this.states.trainEndsA.accCheckSpeedDiff;
|
||||
}
|
||||
set aAccCheckSpeedDiff(v: number) {
|
||||
this.states.trainEndsA.accCheckSpeedDiff = v + '';
|
||||
}
|
||||
get aAccOutSpeed(): number {
|
||||
return this.states.trainEndsA.accOutSpeed;
|
||||
}
|
||||
set aAccOutSpeed(v: number) {
|
||||
this.states.trainEndsA.accOutSpeed = v;
|
||||
}
|
||||
get aRadarOutSpeed(): number {
|
||||
return this.states.trainEndsA.radarOutSpeed;
|
||||
}
|
||||
set aRadarOutSpeed(v: number) {
|
||||
this.states.trainEndsA.radarOutSpeed = v;
|
||||
}
|
||||
get bAccEnable(): boolean {
|
||||
return this.states.trainEndsB.accEnable;
|
||||
}
|
||||
set bAccEnable(v: boolean) {
|
||||
this.states.trainEndsB.accEnable = v;
|
||||
}
|
||||
get bAccCheckTime(): number {
|
||||
return this.states.trainEndsB.accCheckTime;
|
||||
}
|
||||
set bAccCheckTime(v: number) {
|
||||
this.states.trainEndsB.accCheckTime = v;
|
||||
}
|
||||
get bAccCheckSpeedDiff(): number {
|
||||
return +this.states.trainEndsB.accCheckSpeedDiff;
|
||||
}
|
||||
set bAccCheckSpeedDiff(v: number) {
|
||||
this.states.trainEndsB.accCheckSpeedDiff = v + '';
|
||||
}
|
||||
get bAccOutSpeed(): number {
|
||||
return this.states.trainEndsB.accOutSpeed;
|
||||
}
|
||||
set bAccOutSpeed(v: number) {
|
||||
this.states.trainEndsB.accOutSpeed = v;
|
||||
}
|
||||
get bRadarOutSpeed(): number {
|
||||
return this.states.trainEndsB.radarOutSpeed;
|
||||
}
|
||||
set bRadarOutSpeed(v: number) {
|
||||
this.states.trainEndsB.radarOutSpeed = v;
|
||||
}
|
||||
get tailDeviceId(): number {
|
||||
return this.states.tailDeviceId;
|
||||
}
|
||||
set tailDeviceId(v: number) {
|
||||
this.states.tailDeviceId = v;
|
||||
}
|
||||
get tailDevicePort(): string {
|
||||
return this.states.tailDevicePort;
|
||||
}
|
||||
set tailDevicePort(v: string) {
|
||||
this.states.tailDevicePort = v;
|
||||
}
|
||||
get tailOffset(): number {
|
||||
return this.states.tailOffset;
|
||||
}
|
||||
set tailOffset(v: number) {
|
||||
this.states.tailOffset = v;
|
||||
}
|
||||
get dataSerialNumber(): number {
|
||||
return this.states.btmState?.dataSerialNumber;
|
||||
}
|
||||
set dataSerialNumber(v: number) {
|
||||
this.states.btmState.dataSerialNumber = v;
|
||||
}
|
||||
get baliseCount(): number {
|
||||
return this.states.btmState?.baliseCount;
|
||||
}
|
||||
set baliseCount(v: number) {
|
||||
this.states.btmState.baliseCount = v;
|
||||
}
|
||||
get messageCounter(): number {
|
||||
return this.states.btmState?.messageCounter;
|
||||
}
|
||||
set messageCounter(v: number) {
|
||||
this.states.btmState.messageCounter = v;
|
||||
}
|
||||
get telegram(): string {
|
||||
return this.states.btmState?.telegram;
|
||||
}
|
||||
set telegram(v: string) {
|
||||
this.states.btmState.telegram = v;
|
||||
}
|
||||
get conn(): boolean {
|
||||
return this.states.connState.conn;
|
||||
}
|
||||
set conn(v: boolean) {
|
||||
this.states.connState.conn = v;
|
||||
}
|
||||
get connType(): state.TrainConnState.TrainConnType {
|
||||
return this.states.connState.connType;
|
||||
}
|
||||
set connType(v: state.TrainConnState.TrainConnType) {
|
||||
this.states.connState.connType = v;
|
||||
}
|
||||
get trainControlMapId(): number {
|
||||
return this.states.connState.TrainControlMapId;
|
||||
}
|
||||
clone(): TrainState {
|
||||
return new TrainState(this.states.cloneMessage());
|
||||
}
|
||||
@ -406,8 +687,14 @@ export class TrainState extends GraphicStateBase implements ITrainState {
|
||||
}
|
||||
}
|
||||
|
||||
const wheelDiameterChange: MenuItemOptions = {
|
||||
name: '列车轮径调整',
|
||||
// const wheelDiameterChange: MenuItemOptions = {
|
||||
// name: '列车轮径调整',
|
||||
// };
|
||||
const TrainParam: MenuItemOptions = {
|
||||
name: '设置参数',
|
||||
};
|
||||
const TrainLink: MenuItemOptions = {
|
||||
name: '列车连接',
|
||||
};
|
||||
const removeTrainConfig: MenuItemOptions = {
|
||||
name: '清除列车',
|
||||
@ -416,7 +703,7 @@ const TrainOperateMenu: ContextMenu = ContextMenu.init({
|
||||
name: '列车操作菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [wheelDiameterChange, removeTrainConfig],
|
||||
items: [TrainParam, TrainLink, removeTrainConfig],
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -457,45 +744,51 @@ export class TrainOperateInteraction extends GraphicInteractionPlugin<Train> {
|
||||
const lineStore = useLineStore();
|
||||
const simulationId = lineStore.simulationId || '';
|
||||
const mapId = lineStore.mapId as number;
|
||||
wheelDiameterChange.disabled = !useLineStore().trainConfigList;
|
||||
wheelDiameterChange.handler = () => {
|
||||
Dialog.create({
|
||||
title: '列车轮径调整',
|
||||
message: '列车轮径(mm)【770-840mm】, 请调整!',
|
||||
prompt: {
|
||||
model: train.states.wheelDiameter + '',
|
||||
isValid: (val) => +val >= 770 && +val <= 840,
|
||||
type: 'number',
|
||||
TrainParam.handler = () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '列车设置',
|
||||
message: '',
|
||||
component: SetTrainParam,
|
||||
componentProps: {
|
||||
train: train,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk((data) => {
|
||||
const params = {
|
||||
id: train.states.id,
|
||||
});
|
||||
};
|
||||
TrainLink.handler = () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '列车连接',
|
||||
message: '',
|
||||
component: SetTrainLink,
|
||||
componentProps: {
|
||||
trainId: train.code,
|
||||
simulationId: simulationId,
|
||||
wheelDiameter: +data,
|
||||
};
|
||||
updateTrain(params)
|
||||
.then(() => {
|
||||
successNotify('列车轮径调整成功!');
|
||||
})
|
||||
.catch((err) => {
|
||||
errorNotify('列车轮径调整失败!', err);
|
||||
});
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
};
|
||||
removeTrainConfig.handler = () => {
|
||||
removeTrain({
|
||||
simulationId,
|
||||
mapId,
|
||||
trainId: train.code,
|
||||
})
|
||||
.then(() => {
|
||||
successNotify('移除列车成功!');
|
||||
Dialog.create({
|
||||
title: '确认',
|
||||
message: `确认清除【${train.states.id}】列车吗?`,
|
||||
cancel: true,
|
||||
}).onOk(async () => {
|
||||
removeTrain({
|
||||
simulationId,
|
||||
mapId,
|
||||
trainId: train.code,
|
||||
})
|
||||
.catch((err) => {
|
||||
errorNotify('移除列车失败!', err);
|
||||
});
|
||||
.then(() => {
|
||||
successNotify('移除列车成功!');
|
||||
})
|
||||
.catch((err) => {
|
||||
errorNotify('移除列车失败!', err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
TrainOperateMenu.open(e.global);
|
||||
|
@ -1,17 +1,37 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import {
|
||||
ITransponderData,
|
||||
ITransponderState,
|
||||
Transponder,
|
||||
TransponderTypeEnum,
|
||||
} from 'src/graphics/transponder/Transponder';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
|
||||
import { KilometerSystem } from 'src/graphics/signal/Signal';
|
||||
import {
|
||||
ContextMenu,
|
||||
GraphicInteractionPlugin,
|
||||
IGraphicScene,
|
||||
JlGraphic,
|
||||
MenuItemOptions,
|
||||
} from 'jl-graphic';
|
||||
import { FederatedMouseEvent, DisplayObject } from 'pixi.js';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { Dialog } from 'quasar';
|
||||
import MoveTranspondere from '../../components/draw-app/dialogs/MoveTransponder.vue';
|
||||
import UpdateMessageTransponder from '../../components/draw-app/dialogs/UpdateMessageTransponder.vue';
|
||||
import {
|
||||
resetMessageTransponder,
|
||||
resetPositionTransponder,
|
||||
stopTransponderTelegram,
|
||||
sendTransponderTelegram
|
||||
} from 'src/api/Simulation';
|
||||
import { errorNotify } from 'src/utils/CommonNotify';
|
||||
import { state } from 'src/protos/device_state';
|
||||
|
||||
export class TransponderData
|
||||
extends GraphicDataBase
|
||||
implements ITransponderData
|
||||
{
|
||||
implements ITransponderData {
|
||||
constructor(data?: graphicData.Transponder) {
|
||||
let transponder;
|
||||
if (!data) {
|
||||
@ -54,12 +74,18 @@ export class TransponderData
|
||||
set centralizedStations(v: number[]) {
|
||||
this.data.centralizedStations = v;
|
||||
}
|
||||
get fixedTelegram(): Uint8Array {
|
||||
get fixedTelegram(): string {
|
||||
return this.data.fixedTelegram;
|
||||
}
|
||||
set fixedTelegram(v: Uint8Array) {
|
||||
set fixedTelegram(v: string) {
|
||||
this.data.fixedTelegram = v;
|
||||
}
|
||||
get fixedUserTelegram(): string {
|
||||
return this.data.fixedUserTelegram;
|
||||
}
|
||||
set fixedUserTelegram(v: string) {
|
||||
this.data.fixedUserTelegram = v;
|
||||
}
|
||||
get type(): TransponderTypeEnum {
|
||||
return this.data.type;
|
||||
}
|
||||
@ -76,3 +102,210 @@ export class TransponderData
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
||||
|
||||
const movePosition: MenuItemOptions = { name: '移动应答器位置' };
|
||||
const recoverPosition: MenuItemOptions = { name: '复位应答器' };
|
||||
const modifyMessage: MenuItemOptions = { name: '修改报文' };
|
||||
const resetMessage: MenuItemOptions = { name: '重置报文' };
|
||||
const stopSendMessage: MenuItemOptions = { name: '停止发送报文' };
|
||||
const cancelStopSendMessage: MenuItemOptions = { name: '取消停止发送报文' };
|
||||
const TransponderOperationMenu: ContextMenu = ContextMenu.init({
|
||||
name: '应答器操作',
|
||||
groups: [
|
||||
{
|
||||
items: [
|
||||
movePosition,
|
||||
recoverPosition,
|
||||
modifyMessage,
|
||||
resetMessage,
|
||||
stopSendMessage,
|
||||
cancelStopSendMessage,
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export class TransponderState
|
||||
extends GraphicStateBase
|
||||
implements ITransponderState {
|
||||
constructor(proto?: state.BaliseState) {
|
||||
let states;
|
||||
if (proto) {
|
||||
states = proto;
|
||||
} else {
|
||||
states = new state.BaliseState();
|
||||
}
|
||||
super(states, Transponder.Type);
|
||||
}
|
||||
get code(): string {
|
||||
return this.states.id + '';
|
||||
}
|
||||
get id(): number {
|
||||
return this.states.id;
|
||||
}
|
||||
set id(id: number) {
|
||||
this.states.id = id;
|
||||
}
|
||||
get km(): graphicData.KilometerSystem {
|
||||
return this.states.km
|
||||
? this.states.km
|
||||
: new graphicData.KilometerSystem({
|
||||
coordinateSystem: '',
|
||||
kilometer: 0,
|
||||
direction: 0,
|
||||
});
|
||||
}
|
||||
set km(v: graphicData.KilometerSystem) {
|
||||
this.states.km = new graphicData.KilometerSystem(v);
|
||||
}
|
||||
get fixedTelegram(): string {
|
||||
return this.states.fixedTelegram;
|
||||
}
|
||||
set fixedTelegram(v: string) {
|
||||
this.states.fixedTelegram = v;
|
||||
}
|
||||
get fixedUserTelegram(): string {
|
||||
return this.states.fixedUserTelegram;
|
||||
}
|
||||
set fixedUserTelegram(v: string) {
|
||||
this.states.fixedUserTelegram = v;
|
||||
}
|
||||
get variableTelegram(): string {
|
||||
return this.states.variableTelegram;
|
||||
}
|
||||
set variableTelegram(v: string) {
|
||||
this.states.variableTelegram = v;
|
||||
}
|
||||
get variableUserTelegram(): string {
|
||||
return this.states.variableUserTelegram;
|
||||
}
|
||||
set variableUserTelegram(v: string) {
|
||||
this.states.variableUserTelegram = v;
|
||||
}
|
||||
get work(): boolean {
|
||||
return this.states.work;
|
||||
}
|
||||
set work(v: boolean) {
|
||||
this.states.work = v;
|
||||
}
|
||||
get states(): state.BaliseState {
|
||||
return this.getState<state.BaliseState>();
|
||||
}
|
||||
clone(): TransponderState {
|
||||
return new TransponderState(this.states.cloneMessage());
|
||||
}
|
||||
copyFrom(data: GraphicStateBase): void {
|
||||
pb_1.Message.copyInto(data._state, this._state);
|
||||
}
|
||||
eq(data: GraphicStateBase): boolean {
|
||||
return pb_1.Message.equals(this._state, data._state);
|
||||
}
|
||||
}
|
||||
|
||||
export class TransponderOperationPlugin extends GraphicInteractionPlugin<Transponder> {
|
||||
static Name = 'transponder_operate_menu';
|
||||
constructor(app: IGraphicScene) {
|
||||
super(TransponderOperationPlugin.Name, app);
|
||||
app.registerMenu(TransponderOperationMenu);
|
||||
}
|
||||
static init(app: IGraphicScene) {
|
||||
return new TransponderOperationPlugin(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Transponder[] | undefined {
|
||||
return grahpics.filter<Transponder>(
|
||||
(g): g is Transponder => g instanceof Transponder
|
||||
);
|
||||
}
|
||||
bind(g: Transponder): void {
|
||||
g.polygonGraphic.eventMode = 'static';
|
||||
g.polygonGraphic.cursor = 'pointer';
|
||||
g.polygonGraphic.scalable = true;
|
||||
g.labelGraphic.eventMode = 'static';
|
||||
g.selectable = true;
|
||||
g.on('_rightclick', this.onContextMenu);
|
||||
}
|
||||
unbind(g: Transponder): void {
|
||||
g.polygonGraphic.eventMode = 'none';
|
||||
g.polygonGraphic.scalable = false;
|
||||
g.polygonGraphic.rotatable = false;
|
||||
g.labelGraphic.eventMode = 'none';
|
||||
g.selectable = false;
|
||||
g.off('_rightclick', this.onContextMenu);
|
||||
}
|
||||
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const transponder = target.getGraphic<Transponder>();
|
||||
if (!transponder) return;
|
||||
const lineStore = useLineStore();
|
||||
const simulationId = lineStore.simulationId || '';
|
||||
const mapId = lineStore.mapId as number;
|
||||
TransponderOperationMenu.open(e.global);
|
||||
movePosition.handler = async () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '移动应答器位置',
|
||||
message: '',
|
||||
component: MoveTranspondere,
|
||||
componentProps: {
|
||||
code: transponder.datas.code,
|
||||
coordinateSystem: transponder.states.km?.coordinateSystem,
|
||||
kilometer: transponder.states.km?.kilometer,
|
||||
direction: transponder.states.km?.direction,
|
||||
id: transponder.datas.id,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
};
|
||||
recoverPosition.handler = () => {
|
||||
resetPositionTransponder({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: transponder.datas.id,
|
||||
}).catch((e) => {
|
||||
errorNotify('复位应答器失败:' + e.title, e);
|
||||
});
|
||||
};
|
||||
modifyMessage.handler = () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '修改应答器报文',
|
||||
message: '',
|
||||
component: UpdateMessageTransponder,
|
||||
componentProps: {
|
||||
code: transponder.datas.code,
|
||||
fixedTelegram: transponder.states.fixedTelegram,
|
||||
fixedUserTelegram: transponder.states.fixedUserTelegram,
|
||||
id: transponder.datas.id,
|
||||
type: transponder.datas.type,
|
||||
variableTelegram: transponder.states.variableTelegram,
|
||||
variableUserTelegram: transponder.states.variableUserTelegram,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
});
|
||||
};
|
||||
resetMessage.handler = () => {
|
||||
resetMessageTransponder({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: transponder.datas.id,
|
||||
}).catch((e) => errorNotify('重置应答器报文失败:' + e.title, e));
|
||||
};
|
||||
stopSendMessage.handler = () => {
|
||||
stopTransponderTelegram({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: transponder.datas.id,
|
||||
}).catch((e) => errorNotify('停止发送应答器报文失败:' + e.title, e));
|
||||
};
|
||||
cancelStopSendMessage.handler = () => {
|
||||
sendTransponderTelegram({
|
||||
simulationId,
|
||||
mapId,
|
||||
baliseId: transponder.datas.id,
|
||||
}).catch((e) => errorNotify('取消停止发送应答器报文失败:' + e.title, e));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -22,15 +22,12 @@ import {
|
||||
TurnoutSectionHitArea,
|
||||
} from 'src/graphics/turnout/TurnoutDrawAssistant';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { setSwitchPosition } from 'src/api/Simulation';
|
||||
import { Dialog, Notify } from 'quasar';
|
||||
import AddTrainDialog from '../../components/draw-app/dialogs/AddTrainDialog.vue';
|
||||
import { addTrain } from 'src/api/Simulation';
|
||||
import { successNotify } from 'src/utils/CommonNotify';
|
||||
import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting';
|
||||
import { Dialog } from 'quasar';
|
||||
// import AddTrainDialog from '../../components/draw-app/dialogs/AddTrainDialog.vue';
|
||||
// import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting';
|
||||
import TurnoutOperation from 'src/components/draw-app/dialogs/TurnoutOperation.vue';
|
||||
// import { getKmDistance } from '../lineScene';
|
||||
import { request } from 'src/protos/request';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { getKmDistance } from '../lineScene';
|
||||
|
||||
function getDefaultEndPoint() {
|
||||
return {
|
||||
@ -40,16 +37,15 @@ function getDefaultEndPoint() {
|
||||
};
|
||||
}
|
||||
|
||||
const setNormalPosition: MenuItemOptions = { name: '定操' };
|
||||
const setReversePosition: MenuItemOptions = { name: '反操' };
|
||||
const setTurnoutParam: MenuItemOptions = { name: '设置参数' };
|
||||
|
||||
const addTrainConfig: MenuItemOptions = {
|
||||
name: '添加列车',
|
||||
};
|
||||
// const addTrainConfig: MenuItemOptions = {
|
||||
// name: '添加列车',
|
||||
// };
|
||||
|
||||
const TurnoutOperationMenu: ContextMenu = ContextMenu.init({
|
||||
name: 'Turnout操作',
|
||||
groups: [{ items: [setNormalPosition, setReversePosition, addTrainConfig] }],
|
||||
groups: [{ items: [setTurnoutParam] }],
|
||||
});
|
||||
|
||||
export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
|
||||
@ -93,105 +89,75 @@ export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
|
||||
const target = e.target as DisplayObject;
|
||||
const turnout = target.getGraphic<Turnout>();
|
||||
if (!turnout) return;
|
||||
const lineStore = useLineStore();
|
||||
this.app.updateSelected(turnout);
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
const setPosition = async (val: number) => {
|
||||
await setSwitchPosition({
|
||||
simulationId,
|
||||
mapId,
|
||||
deviceId: turnout.datas.id,
|
||||
operation: val,
|
||||
});
|
||||
};
|
||||
setNormalPosition.handler = async () => {
|
||||
await setPosition(request.Turnout.Operation.DC);
|
||||
};
|
||||
setReversePosition.handler = async () => {
|
||||
await setPosition(request.Turnout.Operation.FC);
|
||||
};
|
||||
|
||||
const port = (target as TurnoutSection).port;
|
||||
addTrainConfig.disabled = !port || !useLineStore().trainConfigList;
|
||||
addTrainConfig.handler = () => {
|
||||
const relations =
|
||||
turnout.relationManage.getRelationsOfGraphicAndOtherType(
|
||||
turnout,
|
||||
AxleCounting.Type
|
||||
);
|
||||
const findAc = relations.find((item) => {
|
||||
const rp = item.getRelationParam(turnout);
|
||||
const orp = item.getOtherRelationParam(turnout as Turnout);
|
||||
const ac = orp.g as AxleCounting;
|
||||
return (
|
||||
rp.getParam() == port &&
|
||||
((ac.datas.axleCountingRef.length > 1 &&
|
||||
ac.datas.type ==
|
||||
graphicData.AxleCounting.TypeDetectionPoint.AxleCounting) ||
|
||||
ac.datas.axleCountingRef.length == 1)
|
||||
);
|
||||
});
|
||||
const oKm = turnout.datas.kilometerSystem;
|
||||
let pKm;
|
||||
if (findAc) {
|
||||
const other = findAc.getOtherGraphic(turnout) as AxleCounting;
|
||||
pKm = other.datas.kilometerSystem;
|
||||
} else {
|
||||
const relations =
|
||||
turnout.relationManage.getRelationsOfGraphicAndOtherType(
|
||||
turnout,
|
||||
Turnout.Type
|
||||
);
|
||||
const findT = relations.find((item) => {
|
||||
const rp = item.getRelationParam(turnout);
|
||||
return rp.getParam() == port;
|
||||
});
|
||||
if (findT) {
|
||||
const other = findT.getOtherGraphic(turnout) as Turnout;
|
||||
pKm = other.datas.kilometerSystem;
|
||||
}
|
||||
}
|
||||
const d = getKmDistance(pKm, oKm);
|
||||
Dialog.create({
|
||||
title: '创建列车',
|
||||
setTurnoutParam.handler = async () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
title: '道岔设置参数',
|
||||
message: '',
|
||||
component: AddTrainDialog,
|
||||
componentProps: { dev: turnout, kmLength: d },
|
||||
component: TurnoutOperation,
|
||||
componentProps: {
|
||||
id: turnout.id,
|
||||
code: turnout.datas.code,
|
||||
force: turnout.states.param.forcePosition,
|
||||
},
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onOk(
|
||||
(data: {
|
||||
offset: number;
|
||||
dir: 1 | 0;
|
||||
trainLength: string;
|
||||
wheelDiameter: number;
|
||||
}) => {
|
||||
const params = {
|
||||
simulationId,
|
||||
mapId,
|
||||
up: !!data.dir,
|
||||
id: turnout.datas.id,
|
||||
devicePort: port,
|
||||
headOffset: data.offset,
|
||||
wheelDiameter: data.wheelDiameter,
|
||||
};
|
||||
if (data.trainLength) {
|
||||
Object.assign(params, { trainLength: +data.trainLength });
|
||||
}
|
||||
addTrain(params)
|
||||
.then(() => {
|
||||
successNotify('添加列车成功!');
|
||||
})
|
||||
.catch((err) => {
|
||||
const error = err as ApiError;
|
||||
Notify.create({
|
||||
type: 'negative',
|
||||
message: `添加列车失败!: ${error.title}`,
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// const port = (target as TurnoutSection).port;
|
||||
// addTrainConfig.disabled = !port || !lineStore.trainConfigList;
|
||||
// addTrainConfig.handler = () => {
|
||||
// const relations =
|
||||
// turnout.relationManage.getRelationsOfGraphicAndOtherType(
|
||||
// turnout,
|
||||
// AxleCounting.Type
|
||||
// );
|
||||
// const findAc = relations.find((item) => {
|
||||
// const rp = item.getRelationParam(turnout);
|
||||
// const orp = item.getOtherRelationParam(turnout as Turnout);
|
||||
// const ac = orp.g as AxleCounting;
|
||||
// return (
|
||||
// rp.getParam() == port &&
|
||||
// ((ac.datas.axleCountingRef.length > 1 &&
|
||||
// ac.datas.type ==
|
||||
// graphicData.AxleCounting.TypeDetectionPoint.AxleCounting) ||
|
||||
// ac.datas.axleCountingRef.length == 1)
|
||||
// );
|
||||
// });
|
||||
// const oKm = turnout.datas.kilometerSystem;
|
||||
// let pKm;
|
||||
// if (findAc) {
|
||||
// const other = findAc.getOtherGraphic(turnout) as AxleCounting;
|
||||
// pKm = other.datas.kilometerSystem;
|
||||
// } else {
|
||||
// const relations =
|
||||
// turnout.relationManage.getRelationsOfGraphicAndOtherType(
|
||||
// turnout,
|
||||
// Turnout.Type
|
||||
// );
|
||||
// const findT = relations.find((item) => {
|
||||
// const rp = item.getRelationParam(turnout);
|
||||
// return rp.getParam() == port;
|
||||
// });
|
||||
// if (findT) {
|
||||
// const other = findT.getOtherGraphic(turnout) as Turnout;
|
||||
// pKm = other.datas.kilometerSystem;
|
||||
// }
|
||||
// }
|
||||
// const d = getKmDistance(pKm, oKm);
|
||||
// if (lineStore.deviceOpreratDialogInstance) return;
|
||||
// lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
// title: '创建列车',
|
||||
// message: '',
|
||||
// component: AddTrainDialog,
|
||||
// componentProps: { dev: turnout, kmLength: d },
|
||||
// cancel: true,
|
||||
// persistent: true,
|
||||
// });
|
||||
// };
|
||||
TurnoutOperationMenu.open(e.global);
|
||||
}
|
||||
}
|
||||
@ -349,35 +315,11 @@ export class TurnoutStates extends GraphicStateBase implements ITurnoutState {
|
||||
set fw(v: boolean) {
|
||||
this.states.fw = v;
|
||||
}
|
||||
get force(): boolean {
|
||||
return this.states.force;
|
||||
get param(): request.PointsParam {
|
||||
return this.states.param;
|
||||
}
|
||||
set force(v: boolean) {
|
||||
this.states.force = v;
|
||||
}
|
||||
get sb(): boolean {
|
||||
return this.states.sb;
|
||||
}
|
||||
set sb(v: boolean) {
|
||||
this.states.sb = v;
|
||||
}
|
||||
get dwsb(): boolean {
|
||||
return this.states.dwsb;
|
||||
}
|
||||
set dwsb(v: boolean) {
|
||||
this.states.dwsb = v;
|
||||
}
|
||||
get fwsb(): boolean {
|
||||
return this.states.fwsb;
|
||||
}
|
||||
set fwsb(v: boolean) {
|
||||
this.states.fwsb = v;
|
||||
}
|
||||
get jc(): boolean {
|
||||
return this.states.jc;
|
||||
}
|
||||
set jc(v: boolean) {
|
||||
this.states.jc = v;
|
||||
set param(param: request.PointsParam) {
|
||||
this.states.param = param;
|
||||
}
|
||||
get qdc(): boolean {
|
||||
return this.states.qdc;
|
||||
|
@ -5,7 +5,9 @@ import {
|
||||
GraphicData,
|
||||
IDrawApp,
|
||||
KeyListener,
|
||||
newDrawApp, MenuItemOptions, ContextMenu
|
||||
newDrawApp,
|
||||
MenuItemOptions,
|
||||
ContextMenu,
|
||||
} from 'jl-graphic';
|
||||
import { ibpGraphicData } from 'src/protos/ibpGraphics';
|
||||
import { useIBPDrawStore } from 'src/stores/ibp-draw-store';
|
||||
@ -147,7 +149,10 @@ export function saveIBPDrawDatas(app: IDrawApp) {
|
||||
const storage = new ibpGraphicData.IBPGraphicStorage();
|
||||
const canvasData = app.canvas.saveData();
|
||||
storage.canvas = new graphicData.Canvas({
|
||||
...canvasData,
|
||||
width: canvasData.width,
|
||||
height: canvasData.height,
|
||||
backgroundColor: canvasData.backgroundColor,
|
||||
gridBackground: new graphicData.Grid(canvasData.gridBackground),
|
||||
viewportTransform: toStorageTransform(canvasData.viewportTransform),
|
||||
});
|
||||
|
||||
|
@ -34,6 +34,10 @@ export function initLineApp(): IGraphicApp {
|
||||
destination: `/rtsts/simulation/${simulationId}/state`,
|
||||
messageHandle: testManage.socketHandler,
|
||||
});
|
||||
lineApp.subscribe({
|
||||
destination: `/rtsts/simulation/${simulationId}/tpis`,
|
||||
messageHandle: testManage.socketHandlerConnectInfo,
|
||||
});
|
||||
return lineApp;
|
||||
}
|
||||
|
||||
@ -47,10 +51,10 @@ export function addSceneList(sceneList: ISceneName[]) {
|
||||
case SceneToPictureType.relayScene: // 继电器
|
||||
s = initRelayScene;
|
||||
break;
|
||||
default:
|
||||
case SceneToPictureType.lineScene:
|
||||
s = initLineScene;
|
||||
}
|
||||
if (lineApp) {
|
||||
if (lineApp && s) {
|
||||
s(lineApp, getSceneName(scene));
|
||||
} else {
|
||||
console.log('没有lineApp');
|
||||
|
@ -21,6 +21,27 @@ import {
|
||||
Signal,
|
||||
KilometerSystem,
|
||||
} from 'src/graphics/signal/Signal';
|
||||
import {
|
||||
FloodGateData,
|
||||
FloodGateOperationInteraction,
|
||||
} from './graphics/FloodGateInteraction';
|
||||
import { FloodGate, FloodGateTemplate } from 'src/graphics/floodGate/FloodGate';
|
||||
import {
|
||||
CarWashingData,
|
||||
CarWashingOperationInteraction,
|
||||
} from './graphics/CarWashingInteraction';
|
||||
import {
|
||||
CarWashing,
|
||||
CarWashingTemplate,
|
||||
} from 'src/graphics/carWashing/CarWashing';
|
||||
import {
|
||||
GarageDoorData,
|
||||
GarageDoorOperationInteraction,
|
||||
} from './graphics/GarageDoorInteraction';
|
||||
import {
|
||||
GarageDoor,
|
||||
GarageDoorTemplate,
|
||||
} from 'src/graphics/garageDoor/GarageDoor';
|
||||
import {
|
||||
PlatformData,
|
||||
PlatformOperateInteraction,
|
||||
@ -55,6 +76,7 @@ import {
|
||||
} from './graphics/SectionInteraction';
|
||||
import { Section, SectionTemplate } from 'src/graphics/section/Section';
|
||||
import { getPublishMapInfoByLineId } from 'src/api/PublishApi';
|
||||
import { initTranspondersState } from 'src/api/Simulation';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { toUint8Array } from 'js-base64';
|
||||
@ -89,7 +111,7 @@ import {
|
||||
} from './graphics/SectionLinkInteraction';
|
||||
import { AxleCountingSectionData } from './graphics/AxleCountingSectionInteraction';
|
||||
import { LogicSectionData } from './graphics/LogicSectionInteraction';
|
||||
import { Notify, QNotifyUpdateOptions } from 'quasar';
|
||||
import { Notify, QNotifyUpdateOptions, Dialog } from 'quasar';
|
||||
import {
|
||||
StopPosition,
|
||||
StopPositionTemplate,
|
||||
@ -106,6 +128,11 @@ import {
|
||||
SpksSwitchOperationInteraction,
|
||||
} from './graphics/SpksSwitchInteraction';
|
||||
import { GatedBoxData } from './graphics/GatedBoxInteraction';
|
||||
import { GarageDoorBoxData } from './graphics/GarageDoorBoxInteraction';
|
||||
import {
|
||||
GarageDoorBox,
|
||||
GarageDoorBoxTemplate,
|
||||
} from 'src/graphics/garageDoorBox/GarageDoorBox';
|
||||
import {
|
||||
EsbButtonData,
|
||||
EsbButtonOperationInteraction,
|
||||
@ -115,7 +142,11 @@ import {
|
||||
Transponder,
|
||||
TransponderTemplate,
|
||||
} from 'src/graphics/transponder/Transponder';
|
||||
import { TransponderData } from './graphics/TransponderInteraction';
|
||||
import {
|
||||
TransponderData,
|
||||
TransponderOperationPlugin,
|
||||
TransponderState,
|
||||
} from './graphics/TransponderInteraction';
|
||||
import {
|
||||
SlopeKiloMarker,
|
||||
SlopeKiloMarkerTemplate,
|
||||
@ -143,6 +174,7 @@ import {
|
||||
} from 'src/graphics/trackLogicSection/TrackLogicSection';
|
||||
import { TrackLogicSectionData } from './graphics/TrackLogicSectionInteraction';
|
||||
import { GatedBoxOperateInteraction } from './graphics/GatedBoxInteraction';
|
||||
import { GarageDoorBoxOperateInteraction } from './graphics/GarageDoorBoxInteraction';
|
||||
import { CategoryType } from 'src/components/CategoryType';
|
||||
import {
|
||||
AutoReturnBox,
|
||||
@ -153,16 +185,47 @@ import {
|
||||
AutoReturnBoxOperationInteraction,
|
||||
AutoReturnBoxState,
|
||||
} from './graphics/AutoReturnBoxInteraction';
|
||||
import { errorNotify, successNotify } from 'src/utils/CommonNotify';
|
||||
import { removeAllTrain } from 'src/api/Simulation';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { IbpBox, IbpBoxTemplate } from 'src/graphics/ibpBox/IbpBox';
|
||||
import { PslBox, PslBoxTemplate } from 'src/graphics/pslBox/PslBox';
|
||||
import {
|
||||
PslBoxData,
|
||||
PslBoxOperateInteraction,
|
||||
} from './graphics/PslBoxInteraction';
|
||||
import {
|
||||
IbpBoxData,
|
||||
IbpBoxOperateInteraction,
|
||||
} from './graphics/IbpBoxInteraction';
|
||||
|
||||
const showOptions: MenuItemOptions = {
|
||||
name: '显示控制',
|
||||
};
|
||||
const initTranspondersOptions: MenuItemOptions = {
|
||||
name: '应答器一键恢复',
|
||||
};
|
||||
const searchDeviceOptions: MenuItemOptions = {
|
||||
name: '设备检索',
|
||||
};
|
||||
const searchTrainOptions: MenuItemOptions = {
|
||||
name: '列车检索',
|
||||
};
|
||||
const clearAllTrainOptions: MenuItemOptions = {
|
||||
name: '清除所有列车',
|
||||
};
|
||||
|
||||
const DefaultCanvasMenu = new ContextMenu({
|
||||
name: '图层选择',
|
||||
groups: [
|
||||
{
|
||||
items: [showOptions],
|
||||
items: [
|
||||
showOptions,
|
||||
initTranspondersOptions,
|
||||
searchDeviceOptions,
|
||||
searchTrainOptions,
|
||||
clearAllTrainOptions,
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -182,6 +245,8 @@ export const layerList = [
|
||||
{ label: '停车位置标', value: StopPosition.Type, defaultShow: true },
|
||||
{ label: 'Spks开关', value: SpksSwitch.Type, defaultShow: true },
|
||||
{ label: '门控箱', value: GatedBox.Type, defaultShow: true },
|
||||
{ label: 'Ibp盘', value: IbpBox.Type, defaultShow: true },
|
||||
{ label: 'Psl盘', value: PslBox.Type, defaultShow: true },
|
||||
{ label: '紧急关闭按钮', value: EsbButton.Type, defaultShow: true },
|
||||
{ label: '应答器', value: Transponder.Type, defaultShow: true },
|
||||
// { label: 'Link', value: Link.Type, defaultShow: false },
|
||||
@ -195,6 +260,10 @@ export const layerList = [
|
||||
{ label: '轨道区段', value: TrackSection.Type, defaultShow: false },
|
||||
{ label: '轨道逻辑区段', value: TrackLogicSection.Type, defaultShow: false },
|
||||
{ label: '自动折返按钮箱', value: AutoReturnBox.Type, defaultShow: true },
|
||||
{ label: '车库门', value: GarageDoor.Type, defaultShow: true },
|
||||
{ label: '防淹门', value: FloodGate.Type, defaultShow: true },
|
||||
{ label: '洗车机', value: CarWashing.Type, defaultShow: true },
|
||||
{ label: '车库门设置', value: GarageDoorBox.Type, defaultShow: true },
|
||||
];
|
||||
|
||||
let lineScene: IGraphicScene;
|
||||
@ -248,7 +317,9 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
|
||||
new SpksSwitchTemplate(new SpksSwitchData()),
|
||||
new GatedBoxTemplate(new GatedBoxData()),
|
||||
new EsbButtonTemplate(new EsbButtonData(), new EsbButtonState()),
|
||||
new TransponderTemplate(new TransponderData()),
|
||||
new IbpBoxTemplate(new IbpBoxData()),
|
||||
new PslBoxTemplate(new PslBoxData()),
|
||||
new TransponderTemplate(new TransponderData(), new TransponderState()),
|
||||
new SlopeKiloMarkerTemplate(new SlopeKiloMarkerData()),
|
||||
// new LinkTemplate(new LinkData()),
|
||||
new TrainWindowTemplate(new TrainWindowData()),
|
||||
@ -261,6 +332,10 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
|
||||
new AutoReturnBoxData(),
|
||||
new AutoReturnBoxState()
|
||||
),
|
||||
new CarWashingTemplate(new CarWashingData()),
|
||||
new GarageDoorTemplate(new GarageDoorData()),
|
||||
new FloodGateTemplate(new FloodGateData()),
|
||||
new GarageDoorBoxTemplate(new GarageDoorBoxData()),
|
||||
];
|
||||
lineScene.registerGraphicTemplates(...graphicTemplate);
|
||||
SignalOperateInteraction.init(lineScene);
|
||||
@ -271,9 +346,16 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
|
||||
SectionOperateInteraction.init(lineScene);
|
||||
TrainOperateInteraction.init(lineScene);
|
||||
TurnoutOperationPlugin.init(lineScene);
|
||||
TransponderOperationPlugin.init(lineScene);
|
||||
EsbButtonOperationInteraction.init(lineScene);
|
||||
SpksSwitchOperationInteraction.init(lineScene);
|
||||
AutoReturnBoxOperationInteraction.init(lineScene);
|
||||
PslBoxOperateInteraction.init(lineScene);
|
||||
IbpBoxOperateInteraction.init(lineScene);
|
||||
CarWashingOperationInteraction.init(lineScene);
|
||||
GarageDoorOperationInteraction.init(lineScene);
|
||||
FloodGateOperationInteraction.init(lineScene);
|
||||
GarageDoorBoxOperateInteraction.init(lineScene);
|
||||
if (categoryType === CategoryType.TH) {
|
||||
GatedBoxOperateInteraction.init(lineScene);
|
||||
}
|
||||
@ -284,6 +366,41 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
|
||||
showOptions.handler = () => {
|
||||
lineStore.setShowLayerDialog(true);
|
||||
};
|
||||
initTranspondersOptions.handler = () => {
|
||||
if (!lineStore.simulationId) {
|
||||
return;
|
||||
}
|
||||
initTranspondersState(lineStore.simulationId).catch((e) =>
|
||||
errorNotify('一键恢复应答器失败!', e)
|
||||
);
|
||||
};
|
||||
searchDeviceOptions.handler = () => {
|
||||
lineStore.setShowDeviceSearch(true);
|
||||
};
|
||||
searchTrainOptions.handler = () => {
|
||||
lineStore.setShowTrainSearch(true);
|
||||
};
|
||||
clearAllTrainOptions.handler = () => {
|
||||
if (!lineStore.simulationId) {
|
||||
return;
|
||||
}
|
||||
Dialog.create({
|
||||
title: '确认',
|
||||
message: '确认清除所有列车吗?',
|
||||
cancel: true,
|
||||
}).onOk(async () => {
|
||||
try {
|
||||
await removeAllTrain({
|
||||
simulationId: lineStore.simulationId || '',
|
||||
mapId: lineStore.mapId || 0,
|
||||
});
|
||||
successNotify('清除所有列车成功!');
|
||||
} catch (err) {
|
||||
const error = err as ApiError;
|
||||
errorNotify('清除所有列车失败!', error.title);
|
||||
}
|
||||
});
|
||||
};
|
||||
DefaultCanvasMenu.open(e.global);
|
||||
});
|
||||
lineScene.on('postdataloaded', () => {
|
||||
@ -339,6 +456,11 @@ function handleSubscribe(lineScene: IGraphicScene) {
|
||||
states.push(new PlatformState(item));
|
||||
}
|
||||
});
|
||||
storage.allStatus.baliseState.forEach((item) => {
|
||||
if (item.id) {
|
||||
states.push(new TransponderState(item));
|
||||
}
|
||||
});
|
||||
storage.allStatus.trainState.forEach((item) => {
|
||||
// 列车
|
||||
if (!item.show) {
|
||||
@ -423,10 +545,10 @@ function ControlShowType(lineScene: IGraphicScene) {
|
||||
} else {
|
||||
g.visible = false;
|
||||
}
|
||||
if (g.type == Transponder.Type) {
|
||||
// 应答器不显示名称
|
||||
(g as Transponder).labelGraphic.visible = false;
|
||||
}
|
||||
// if (g.type == Transponder.Type) {
|
||||
// // 应答器不显示名称
|
||||
// (g as Transponder).labelGraphic.visible = false;
|
||||
// }
|
||||
});
|
||||
lineStore.setShowLayer(showTypeList);
|
||||
}
|
||||
@ -523,6 +645,24 @@ export async function loadLineDatas(): Promise<IGraphicStorage> {
|
||||
storage.autoReturnBoxs.forEach((autoReturnBox) => {
|
||||
datas.push(new AutoReturnBoxData(autoReturnBox));
|
||||
});
|
||||
storage.ibpBoxs.forEach((ibpBox) => {
|
||||
datas.push(new IbpBoxData(ibpBox));
|
||||
});
|
||||
storage.pslBoxs.forEach((pslBox) => {
|
||||
datas.push(new PslBoxData(pslBox));
|
||||
});
|
||||
storage.carWashings.forEach((carWashing) => {
|
||||
datas.push(new CarWashingData(carWashing));
|
||||
});
|
||||
storage.garageDoors.forEach((garageDoor) => {
|
||||
datas.push(new GarageDoorData(garageDoor));
|
||||
});
|
||||
storage.floodGates.forEach((floodGate) => {
|
||||
datas.push(new FloodGateData(floodGate));
|
||||
});
|
||||
storage.garageDoorBoxes.forEach((garageDoorBox) => {
|
||||
datas.push(new GarageDoorBoxData(garageDoorBox));
|
||||
});
|
||||
// const linkIdGenerator = new IdGenerator(Link.Type);
|
||||
// storage.CalculateLink.forEach((link) => {
|
||||
// const g = new LinkData(link);
|
||||
|
@ -5,7 +5,9 @@ import {
|
||||
IGraphicStorage,
|
||||
KeyListener,
|
||||
newDrawApp,
|
||||
GraphicData, ContextMenu, MenuItemOptions
|
||||
GraphicData,
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
} from 'jl-graphic';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { pslGraphicData } from 'src/protos/pslGraphics';
|
||||
@ -164,7 +166,9 @@ export function savePslDrawDatas(app: IDrawApp) {
|
||||
const storage = new pslGraphicData.PslGraphicStorage();
|
||||
const canvasData = app.canvas.saveData();
|
||||
storage.canvas = new graphicData.Canvas({
|
||||
...canvasData,
|
||||
width: canvasData.width,
|
||||
height: canvasData.height,
|
||||
backgroundColor: canvasData.backgroundColor,
|
||||
viewportTransform: toStorageTransform(canvasData.viewportTransform),
|
||||
});
|
||||
const graphics = app.queryStore.getAllGraphics();
|
||||
|
@ -60,7 +60,7 @@ function handleSubscribe(pslScene: IGraphicScene) {
|
||||
const pslStore = usePslStore();
|
||||
const simulationId = lineStore.simulationId;
|
||||
const mapId = lineStore.mapId;
|
||||
const pslId = pslStore.gatedBoxId;
|
||||
const pslId = pslStore.pslId;
|
||||
const app = pslScene;
|
||||
app.subscribe({
|
||||
destination: `/rtsts/simulation/${simulationId}/psl/${mapId}/${pslId}`,
|
||||
|
@ -15,6 +15,7 @@ import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
|
||||
import { setRelayState } from 'src/api/Simulation';
|
||||
import { ApiError } from 'src/boot/axios';
|
||||
import { errorNotify, successNotify } from 'src/utils/CommonNotify';
|
||||
import { request } from 'src/protos/request';
|
||||
|
||||
export class RelayData extends GraphicDataBase implements IRelayData {
|
||||
constructor(data?: relayCabinetGraphicData.Relay) {
|
||||
@ -78,6 +79,12 @@ export class RelayState extends GraphicStateBase implements IRelayState {
|
||||
set xh(xh: boolean) {
|
||||
this.states.xh = xh;
|
||||
}
|
||||
get force(): boolean {
|
||||
return this.states.force;
|
||||
}
|
||||
set force(force: boolean) {
|
||||
this.states.force = force;
|
||||
}
|
||||
get states(): state.ReplyState {
|
||||
return this.getState<state.ReplyState>();
|
||||
}
|
||||
@ -92,14 +99,15 @@ export class RelayState extends GraphicStateBase implements IRelayState {
|
||||
}
|
||||
}
|
||||
|
||||
const setOpen: MenuItemOptions = { name: '驱动落下' };
|
||||
const setClose: MenuItemOptions = { name: '驱动吸起' };
|
||||
const setOpen: MenuItemOptions = { name: '强制后接点位(落下)' };
|
||||
const setClose: MenuItemOptions = { name: '强制前接点位(吸起)' };
|
||||
const cancelForce: MenuItemOptions = { name: '取消强制' };
|
||||
|
||||
export class RelayOperationPlugin extends GraphicInteractionPlugin<Relay> {
|
||||
static Name = 'relay_operate_menu';
|
||||
relayOperationMenu: ContextMenu = ContextMenu.init({
|
||||
name: 'Relay操作',
|
||||
groups: [{ items: [setOpen, setClose] }],
|
||||
groups: [{ items: [setOpen, setClose, cancelForce] }],
|
||||
});
|
||||
|
||||
constructor(app: IGraphicScene) {
|
||||
@ -135,14 +143,12 @@ export class RelayOperationPlugin extends GraphicInteractionPlugin<Relay> {
|
||||
this.app.updateSelected(relay);
|
||||
const simulationId = useLineStore().simulationId || '';
|
||||
const mapId = useLineStore().mapId as number;
|
||||
setOpen.disabled = !relay.states.xh;
|
||||
setClose.disabled = relay.states.xh;
|
||||
const changeRelayState = async (td: boolean) => {
|
||||
const changeRelayState = async (operation: request.Relay.Operation) => {
|
||||
setRelayState({
|
||||
id: relay.datas.id,
|
||||
mapId,
|
||||
simulationId,
|
||||
td,
|
||||
mapId,
|
||||
deviceId: relay.datas.id,
|
||||
operation,
|
||||
})
|
||||
.then(() => {
|
||||
successNotify('修改继电器状态成功');
|
||||
@ -153,10 +159,13 @@ export class RelayOperationPlugin extends GraphicInteractionPlugin<Relay> {
|
||||
});
|
||||
};
|
||||
setOpen.handler = () => {
|
||||
changeRelayState(false);
|
||||
changeRelayState(request.Relay.Operation.ForceHw);
|
||||
};
|
||||
setClose.handler = () => {
|
||||
changeRelayState(true);
|
||||
changeRelayState(request.Relay.Operation.ForceQw);
|
||||
};
|
||||
cancelForce.handler = () => {
|
||||
changeRelayState(request.Relay.Operation.CancelForce);
|
||||
};
|
||||
this.relayOperationMenu.open(e.global);
|
||||
}
|
||||
|
@ -205,7 +205,9 @@ export function saveDrawDatas(app: IDrawApp) {
|
||||
const storage = new relayCabinetGraphicData.RelayCabinetGraphicStorage();
|
||||
const canvasData = app.canvas.saveData();
|
||||
storage.canvas = new graphicData.Canvas({
|
||||
...canvasData,
|
||||
width: canvasData.width,
|
||||
height: canvasData.height,
|
||||
backgroundColor: canvasData.backgroundColor,
|
||||
viewportTransform: toStorageTransform(canvasData.viewportTransform),
|
||||
});
|
||||
const graphics = app.queryStore.getAllGraphics();
|
||||
|
@ -1,10 +1,12 @@
|
||||
import {
|
||||
ContextMenu,
|
||||
GraphicData,
|
||||
GraphicQueryStore,
|
||||
GraphicState,
|
||||
IGraphicApp,
|
||||
IGraphicScene,
|
||||
IGraphicStorage,
|
||||
MenuItemOptions,
|
||||
} from 'jl-graphic';
|
||||
import { getPublishMapInfoByLineId } from 'src/api/PublishApi';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
@ -24,7 +26,27 @@ import {
|
||||
} from 'src/graphics/phaseFailureProtector/PhaseFailureProtector';
|
||||
import { PhaseFailureProtectorData } from './relayCabinetGraphics/PhaseFailureProtectorInteraction';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import { Notify, QNotifyUpdateOptions } from 'quasar';
|
||||
import { Dialog, Notify, QNotifyUpdateOptions } from 'quasar';
|
||||
import CiCjQdListStateDialog from 'src/components/draw-app/dialogs/CiCjQdListStateDialog.vue';
|
||||
import { useTestManageStore } from 'src/stores/testManage-store';
|
||||
|
||||
const testManageStore = useTestManageStore();
|
||||
const CiCjQdListState: MenuItemOptions = {
|
||||
name: '驱采状态',
|
||||
};
|
||||
const canvasMenu = new ContextMenu({
|
||||
name: '图层选择',
|
||||
groups: [
|
||||
{
|
||||
items: [CiCjQdListState],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const refRelaysListMap = new Map<
|
||||
number,
|
||||
{ combinationtype: string; device: string }
|
||||
>();
|
||||
|
||||
export function initRelayScene(lineApp: IGraphicApp, sceneName: string) {
|
||||
// 继电器
|
||||
@ -46,28 +68,33 @@ export function initRelayScene(lineApp: IGraphicApp, sceneName: string) {
|
||||
];
|
||||
relayScene.registerGraphicTemplates(...relayGraphicTemplate);
|
||||
RelayOperationPlugin.init(relayScene);
|
||||
updataOnChangeScene(relayScene);
|
||||
relayScene.on('postdataloaded', () => {
|
||||
handleSubscribe(relayScene);
|
||||
const map = new Map<number, string>();
|
||||
refRelaysList.forEach((device) => {
|
||||
device.combinationtypes.forEach((combinationtype) => {
|
||||
combinationtype.refRelays.forEach((relayId) => {
|
||||
map.set(relayId, device.code);
|
||||
refRelaysListMap.set(relayId, {
|
||||
combinationtype: combinationtype.code,
|
||||
device: device.code,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
const relays = relayScene.queryStore.queryByType<Relay>(Relay.Type);
|
||||
relays.forEach((relay) => {
|
||||
relay.refDevice.text = map.get(relay.id)?.replace(/_/g, '\n') as string;
|
||||
relay.refDevice.text = refRelaysListMap
|
||||
.get(relay.id)
|
||||
?.device.replace(/_/g, '\n') as string;
|
||||
});
|
||||
const phaseFailureProtectors =
|
||||
relayScene.queryStore.queryByType<PhaseFailureProtector>(
|
||||
PhaseFailureProtector.Type
|
||||
);
|
||||
phaseFailureProtectors.forEach((phaseFailureProtector) => {
|
||||
phaseFailureProtector.refDevice.text = map
|
||||
.get(phaseFailureProtector.id)
|
||||
?.replace(/_/g, '\n') as string;
|
||||
phaseFailureProtector.refDevice.text = refRelaysListMap.get(
|
||||
phaseFailureProtector.id
|
||||
)?.device as string;
|
||||
});
|
||||
});
|
||||
lineApp.on('destroy', () => {
|
||||
@ -75,6 +102,24 @@ export function initRelayScene(lineApp: IGraphicApp, sceneName: string) {
|
||||
});
|
||||
}
|
||||
|
||||
export function updataOnChangeScene(relayScene: IGraphicScene) {
|
||||
relayScene.registerMenu(canvasMenu);
|
||||
relayScene.canvas.on('_rightclick', (e) => {
|
||||
const lineStore = useLineStore();
|
||||
CiCjQdListState.handler = async () => {
|
||||
if (lineStore.deviceOpreratDialogInstance) return;
|
||||
lineStore.deviceOpreratDialogInstance = Dialog.create({
|
||||
component: CiCjQdListStateDialog,
|
||||
cancel: true,
|
||||
persistent: true,
|
||||
}).onCancel(() => {
|
||||
lineStore.deviceOpreratDialogInstance = null;
|
||||
});
|
||||
};
|
||||
canvasMenu.open(e.global);
|
||||
});
|
||||
}
|
||||
|
||||
function handleSubscribe(relayScene: IGraphicScene) {
|
||||
const lineStore = useLineStore();
|
||||
const simulationId = lineStore.simulationId;
|
||||
@ -92,6 +137,7 @@ function handleSubscribe(relayScene: IGraphicScene) {
|
||||
states.push(new RelayState(relayState));
|
||||
}
|
||||
});
|
||||
testManageStore.setStationQc(storage.allStatus.stationQc);
|
||||
} else {
|
||||
storage.varStatus.updatedReply.forEach((relayState) => {
|
||||
if (relayState.id) {
|
||||
@ -123,7 +169,6 @@ function handleSubscribe(relayScene: IGraphicScene) {
|
||||
});
|
||||
}
|
||||
|
||||
let refRelaysList: relayCabinetGraphicData.DeviceRelateRelay[] = [];
|
||||
async function loadRelayDatas(): Promise<IGraphicStorage> {
|
||||
const lineStore = useLineStore();
|
||||
const mapId = lineStore.mapId;
|
||||
@ -148,6 +193,8 @@ async function loadRelayDatas(): Promise<IGraphicStorage> {
|
||||
datas.push(new PhaseFailureProtectorData(phaseFailureProtector));
|
||||
});
|
||||
refRelaysList = storage.deviceRelateRelayList;
|
||||
sceneCiCjQdListMap.set(`${lineStore.sceneName}+ciCjList`, storage.ciCjList);
|
||||
sceneCiCjQdListMap.set(`${lineStore.sceneName}+ciQdList`, storage.ciQdList);
|
||||
return Promise.resolve({
|
||||
canvasProperty: storage.canvas,
|
||||
datas: datas,
|
||||
@ -158,3 +205,11 @@ async function loadRelayDatas(): Promise<IGraphicStorage> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//关联继电器列表
|
||||
let refRelaysList: relayCabinetGraphicData.DeviceRelateRelay[] = [];
|
||||
//采集列表和驱动列表
|
||||
export const sceneCiCjQdListMap = new Map<
|
||||
string,
|
||||
relayCabinetGraphicData.CiCj | relayCabinetGraphicData.CiQd
|
||||
>();
|
||||
|
226
src/drawApp/tccApp.ts
Normal file
226
src/drawApp/tccApp.ts
Normal file
@ -0,0 +1,226 @@
|
||||
import { fromUint8Array, toUint8Array } from 'js-base64';
|
||||
import {
|
||||
CombinationKey,
|
||||
IDrawApp,
|
||||
IGraphicStorage,
|
||||
KeyListener,
|
||||
newDrawApp,
|
||||
GraphicData,
|
||||
ContextMenu,
|
||||
MenuItemOptions,
|
||||
} from 'jl-graphic';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { tccGraphicData } from 'src/protos/tccGraphics';
|
||||
import { saveDraft, getDraft } from 'src/api/DraftApi';
|
||||
import { useTccDrawStore } from 'src/stores/tcc-draw-store';
|
||||
import { successNotify, errorNotify } from '../utils/CommonNotify';
|
||||
import { toStorageTransform } from './graphics/GraphicDataBase';
|
||||
import { Dialog } from 'quasar';
|
||||
import { checkMapData } from 'src/api/Simulation';
|
||||
import { TccButtonData, TccButtonState } from './graphics/TccButtonInteraction';
|
||||
import { TccButtonDraw } from 'src/graphics/tccButton/TccButtonDrawAssistant';
|
||||
import { TccButton, TccButtonTemplate } from 'src/graphics/tccButton/TccButton';
|
||||
import {
|
||||
TextContent,
|
||||
TextContentTemplate,
|
||||
} from 'src/graphics/textContent/TextContent';
|
||||
import { TccTextData } from './graphics/TccTextContentInteraction';
|
||||
import { TextContentDraw } from 'src/graphics/textContent/TextContentDrawAssistant';
|
||||
import { TccKeyDraw } from 'src/graphics/tccKey/TccKeyDrawAssistant';
|
||||
import { TccKey, TccKeyTemplate } from 'src/graphics/tccKey/TccKey';
|
||||
import { TccKeyData, TccKeyState } from './graphics/TccKeyInteraction';
|
||||
import { TccHandleDraw } from 'src/graphics/tccHandle/TccHandleDrawAssistant';
|
||||
import { TccHandle, TccHandleTemplate } from 'src/graphics/tccHandle/TccHandle';
|
||||
import { TccHandleData, TccHandleState } from './graphics/TccHandleInteraction';
|
||||
|
||||
const UndoOptions: MenuItemOptions = {
|
||||
name: '撤销',
|
||||
};
|
||||
const RedoOptions: MenuItemOptions = {
|
||||
name: '重做',
|
||||
};
|
||||
const SelectAllOptions: MenuItemOptions = {
|
||||
name: '全选',
|
||||
};
|
||||
|
||||
export const DefaultCanvasMenu = new ContextMenu({
|
||||
name: '绘制-画布菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [UndoOptions, RedoOptions],
|
||||
},
|
||||
{
|
||||
items: [SelectAllOptions],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let drawApp: IDrawApp | null = null;
|
||||
|
||||
export function getTccDrawApp(): IDrawApp | null {
|
||||
return drawApp;
|
||||
}
|
||||
|
||||
export function destroyTccDrawApp(): void {
|
||||
if (drawApp) {
|
||||
drawApp.destroy();
|
||||
drawApp = null;
|
||||
}
|
||||
}
|
||||
|
||||
export function initTccDrawApp(): IDrawApp {
|
||||
drawApp = newDrawApp({
|
||||
dataLoader: loadTccDrawDatas,
|
||||
});
|
||||
const app = drawApp;
|
||||
//根据草稿图类型加载绘图工具
|
||||
new TccButtonDraw(
|
||||
app,
|
||||
new TccButtonTemplate(new TccButtonData(), new TccButtonState())
|
||||
);
|
||||
new TextContentDraw(app, new TextContentTemplate(new TccTextData()));
|
||||
new TccKeyDraw(
|
||||
drawApp,
|
||||
new TccKeyTemplate(new TccKeyData(), new TccKeyState())
|
||||
);
|
||||
new TccHandleDraw(
|
||||
drawApp,
|
||||
new TccHandleTemplate(new TccHandleData(), new TccHandleState())
|
||||
);
|
||||
|
||||
// 画布右键菜单
|
||||
app.registerMenu(DefaultCanvasMenu);
|
||||
app.canvas.on('_rightclick', (e) => {
|
||||
if (app.drawing) return;
|
||||
UndoOptions.disabled = !app.opRecord.hasUndo;
|
||||
RedoOptions.disabled = !app.opRecord.hasRedo;
|
||||
|
||||
UndoOptions.handler = () => {
|
||||
app.opRecord.undo();
|
||||
};
|
||||
RedoOptions.handler = () => {
|
||||
app.opRecord.redo();
|
||||
};
|
||||
SelectAllOptions.handler = () => {
|
||||
app.selectAllGraphics();
|
||||
};
|
||||
DefaultCanvasMenu.open(e.global);
|
||||
});
|
||||
app.addKeyboardListener(
|
||||
new KeyListener({
|
||||
value: 'KeyS',
|
||||
global: true,
|
||||
combinations: [CombinationKey.Ctrl],
|
||||
onPress: () => {
|
||||
saveTccDrawToServer(app);
|
||||
},
|
||||
})
|
||||
);
|
||||
return drawApp;
|
||||
}
|
||||
|
||||
export function checkTccDataToServer(app: IDrawApp) {
|
||||
const base64 = saveTccDrawDatas(app);
|
||||
checkMapData({ mapProto: base64 })
|
||||
.then((res) => {
|
||||
if (res.data.success) {
|
||||
successNotify('校验数据成功!');
|
||||
} else {
|
||||
let message = '';
|
||||
res.data.errors.forEach((err: string) => {
|
||||
message += `<div>${err};<div>`;
|
||||
});
|
||||
Dialog.create({
|
||||
title: '校验失败',
|
||||
message: message,
|
||||
html: true,
|
||||
persistent: true,
|
||||
ok: {
|
||||
ali: 'center',
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
errorNotify(err.message, err);
|
||||
});
|
||||
}
|
||||
|
||||
export function saveTccDrawToServer(app: IDrawApp) {
|
||||
const base64 = saveTccDrawDatas(app);
|
||||
const tccDrawStore = useTccDrawStore();
|
||||
const id = tccDrawStore.draftId;
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
saveDraft(id as number, { proto: base64 })
|
||||
.then(() => {
|
||||
successNotify('保存数据成功!');
|
||||
})
|
||||
.catch((err) => {
|
||||
errorNotify(err.message, err);
|
||||
});
|
||||
}
|
||||
|
||||
export function saveTccDrawDatas(app: IDrawApp) {
|
||||
const storage = new tccGraphicData.TccGraphicStorage();
|
||||
const canvasData = app.canvas.saveData();
|
||||
storage.canvas = new graphicData.Canvas({
|
||||
width: canvasData.width,
|
||||
height: canvasData.height,
|
||||
backgroundColor: canvasData.backgroundColor,
|
||||
viewportTransform: toStorageTransform(canvasData.viewportTransform),
|
||||
});
|
||||
const graphics = app.queryStore.getAllGraphics();
|
||||
graphics.forEach((g) => {
|
||||
if (g instanceof TccButton) {
|
||||
storage.tccButtons.push(g.saveData<TccButtonData>().data);
|
||||
} else if (g instanceof TextContent) {
|
||||
storage.tccTexts.push(g.saveData<TccTextData>().data);
|
||||
} else if (g instanceof TccKey) {
|
||||
storage.tccKeys.push(g.saveData<TccKeyData>().data);
|
||||
} else if (g instanceof TccHandle) {
|
||||
storage.tccHandles.push(g.saveData<TccHandleData>().data);
|
||||
}
|
||||
});
|
||||
const base64 = fromUint8Array(storage.serialize());
|
||||
console.log('保存数据', storage);
|
||||
return base64;
|
||||
}
|
||||
|
||||
export async function loadTccDrawDatas(): Promise<IGraphicStorage> {
|
||||
// console.log('加载数据', base64);
|
||||
const tccDrawStore = useTccDrawStore();
|
||||
const id = tccDrawStore.draftId;
|
||||
if (!id) {
|
||||
throw new Error('获取数据异常:为获取到草稿地图ID');
|
||||
}
|
||||
const { proto: base64 } = await getDraft(id);
|
||||
if (base64) {
|
||||
const storage = tccGraphicData.TccGraphicStorage.deserialize(
|
||||
toUint8Array(base64)
|
||||
);
|
||||
// app.updateCanvas(storage.canvas);
|
||||
const datas: GraphicData[] = [];
|
||||
storage.tccButtons.forEach((tccButton) => {
|
||||
datas.push(new TccButtonData(tccButton));
|
||||
});
|
||||
storage.tccKeys.forEach((tccKey) => {
|
||||
datas.push(new TccKeyData(tccKey));
|
||||
});
|
||||
storage.tccHandles.forEach((tccHandle) => {
|
||||
datas.push(new TccHandleData(tccHandle));
|
||||
});
|
||||
storage.tccTexts.forEach((tccText) => {
|
||||
datas.push(new TccTextData(tccText));
|
||||
});
|
||||
return {
|
||||
canvasProperty: storage.canvas,
|
||||
datas: datas,
|
||||
};
|
||||
} else {
|
||||
return Promise.resolve({
|
||||
datas: [],
|
||||
});
|
||||
}
|
||||
}
|
125
src/drawApp/tccScene.ts
Normal file
125
src/drawApp/tccScene.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import {
|
||||
GraphicData,
|
||||
GraphicState,
|
||||
IGraphicApp,
|
||||
IGraphicScene,
|
||||
IGraphicStorage,
|
||||
} from 'jl-graphic';
|
||||
import { getPublishMapInfoById } from 'src/api/PublishApi';
|
||||
import { useTccStore } from 'src/stores/tcc-store';
|
||||
import { toUint8Array } from 'js-base64';
|
||||
import { useLineStore } from 'src/stores/line-store';
|
||||
import { state } from 'src/protos/device_state';
|
||||
import {
|
||||
TccButtonData,
|
||||
TccButtonOperateInteraction,
|
||||
TccButtonState,
|
||||
} from './graphics/TccButtonInteraction';
|
||||
import { tccGraphicData } from 'src/protos/tccGraphics';
|
||||
import { TccButtonTemplate } from 'src/graphics/tccButton/TccButton';
|
||||
import { TextContentTemplate } from 'src/graphics/textContent/TextContent';
|
||||
import { TccTextData } from './graphics/TccTextContentInteraction';
|
||||
import { TccKeyTemplate } from 'src/graphics/tccKey/TccKey';
|
||||
import {
|
||||
TccKeyData,
|
||||
TccKeyInteraction,
|
||||
TccKeyState,
|
||||
} from './graphics/TccKeyInteraction';
|
||||
import { TccHandleTemplate } from 'src/graphics/tccHandle/TccHandle';
|
||||
import {
|
||||
TccHandleData,
|
||||
TccHandleInteraction,
|
||||
TccHandleState,
|
||||
} from './graphics/TccHandleInteraction';
|
||||
|
||||
export function initTccScene(lineApp: IGraphicApp, sceneName: string) {
|
||||
const tccScene = lineApp.initScene(sceneName, {
|
||||
dataLoader: loadTccDatas,
|
||||
mouseToolOptions: {
|
||||
boxSelect: false,
|
||||
wheelZoom: false,
|
||||
},
|
||||
});
|
||||
const graphicTemplate = [
|
||||
new TccButtonTemplate(new TccButtonData(), new TccButtonState()),
|
||||
new TextContentTemplate(new TccTextData()),
|
||||
new TccKeyTemplate(new TccKeyData(), new TccKeyState()),
|
||||
new TccHandleTemplate(new TccHandleData(), new TccHandleState()),
|
||||
];
|
||||
TccButtonOperateInteraction.init(tccScene);
|
||||
TccKeyInteraction.init(tccScene);
|
||||
TccHandleInteraction.init(tccScene);
|
||||
tccScene.registerGraphicTemplates(...graphicTemplate);
|
||||
tccScene.on('postdataloaded', () => {
|
||||
handleSubscribe(tccScene);
|
||||
});
|
||||
return tccScene;
|
||||
}
|
||||
|
||||
function handleSubscribe(tccScene: IGraphicScene) {
|
||||
const lineStore = useLineStore();
|
||||
const tccStore = useTccStore();
|
||||
const simulationId = lineStore.simulationId;
|
||||
const tccId = tccStore.tccId;
|
||||
const app = tccScene;
|
||||
app.subscribe({
|
||||
destination: `/rtsts/simulation/${simulationId}/train/control/${tccId}`,
|
||||
messageConverter: (message: Uint8Array) => {
|
||||
const states: GraphicState[] = [];
|
||||
const storage = state.TrainControlState.deserialize(message);
|
||||
if (storage.ebutton) {
|
||||
states.push(new TccButtonState(storage.ebutton));
|
||||
}
|
||||
if (storage.dirKey) {
|
||||
states.push(new TccKeyState(storage.dirKey));
|
||||
}
|
||||
storage?.driverKey.forEach((driverKey) => {
|
||||
const data = new state.TrainControlState.DirectionKeySwitch({
|
||||
id: driverKey.id,
|
||||
val: driverKey.val ? 1 : 0,
|
||||
});
|
||||
states.push(new TccKeyState(data));
|
||||
});
|
||||
if (storage.pushHandler) {
|
||||
states.push(new TccHandleState(storage.pushHandler));
|
||||
}
|
||||
return states;
|
||||
},
|
||||
graphicQueryer: (state, store) => {
|
||||
return store.queryById(+state.code);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function loadTccDatas(): Promise<IGraphicStorage> {
|
||||
const tccStore = useTccStore();
|
||||
const { proto: base64 } = await getPublishMapInfoById(
|
||||
tccStore.trainControlMapId
|
||||
);
|
||||
if (base64) {
|
||||
const storage = tccGraphicData.TccGraphicStorage.deserialize(
|
||||
toUint8Array(base64)
|
||||
);
|
||||
const datas: GraphicData[] = [];
|
||||
storage.tccButtons.forEach((tccButton) => {
|
||||
datas.push(new TccButtonData(tccButton));
|
||||
});
|
||||
storage.tccKeys.forEach((tccKey) => {
|
||||
datas.push(new TccKeyData(tccKey));
|
||||
});
|
||||
storage.tccHandles.forEach((tccHandle) => {
|
||||
datas.push(new TccHandleData(tccHandle));
|
||||
});
|
||||
storage.tccTexts.forEach((tccText) => {
|
||||
datas.push(new TccTextData(tccText));
|
||||
});
|
||||
return Promise.resolve({
|
||||
canvasProperty: storage.canvas,
|
||||
datas: datas,
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve({
|
||||
datas: [],
|
||||
});
|
||||
}
|
||||
}
|
@ -45,6 +45,9 @@ export class IBPButton extends JlGraphic {
|
||||
this.sprite.anchor.set(0.5);
|
||||
this.addChild(this.sprite);
|
||||
}
|
||||
get code(): string {
|
||||
return this.datas.code;
|
||||
}
|
||||
get datas() {
|
||||
return this.getDatas<IIBPButtonData>();
|
||||
}
|
||||
|
@ -58,6 +58,10 @@ export class Arrow extends JlGraphic implements ILineGraphic {
|
||||
this.arrowGraphic.endFill();
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.datas.code;
|
||||
}
|
||||
|
||||
get datas(): IArrowData {
|
||||
return this.getDatas<IArrowData>();
|
||||
}
|
||||
|
@ -45,6 +45,9 @@ export class AutoReturnBox extends JlGraphic {
|
||||
this.addChild(this.circleBody);
|
||||
this.codeGraph.name = 'atb_code';
|
||||
}
|
||||
get code(): string {
|
||||
return this.datas.code;
|
||||
}
|
||||
get datas(): IAutoReturnBoxData {
|
||||
return this.getDatas<IAutoReturnBoxData>();
|
||||
}
|
||||
|
@ -94,7 +94,9 @@ export class AxleCounting extends JlGraphic {
|
||||
this.kilometerGraph.name = 'kilometer';
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.datas.code;
|
||||
}
|
||||
get datas(): IAxleCountingData {
|
||||
return this.getDatas<IAxleCountingData>();
|
||||
}
|
||||
|
@ -55,7 +55,9 @@ export class AxleCountingSection extends JlGraphic {
|
||||
this.addChild(this.lineGraphic);
|
||||
this.addChild(this.labelGraphic);
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.datas.code;
|
||||
}
|
||||
get datas(): IAxleCountingSectionData {
|
||||
return this.getDatas<IAxleCountingSectionData>();
|
||||
}
|
||||
|
89
src/graphics/carWashing/CarWashing.ts
Normal file
89
src/graphics/carWashing/CarWashing.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import { Graphics } from 'pixi.js';
|
||||
import {
|
||||
GraphicData,
|
||||
JlGraphic,
|
||||
JlGraphicTemplate,
|
||||
VectorText,
|
||||
} from 'jl-graphic';
|
||||
|
||||
export interface ICarWashingData extends GraphicData {
|
||||
get code(): string;
|
||||
set code(v: string);
|
||||
get linkSection(): number;
|
||||
set linkSection(v: number);
|
||||
get centralizedStations(): number[];
|
||||
set centralizedStations(v: number[]);
|
||||
clone(): ICarWashingData;
|
||||
copyFrom(data: ICarWashingData): void;
|
||||
eq(other: ICarWashingData): boolean;
|
||||
}
|
||||
|
||||
const carWashingConsts = {
|
||||
codeFontSize: 12,
|
||||
codeColor: 0xffffff,
|
||||
bodyRectLineColor: 0xffffff,
|
||||
bodyRectLineWidth: 2,
|
||||
bodyRectWidth: 10,
|
||||
bodyRectHeight: 20,
|
||||
bodyColor: 0x000000,
|
||||
};
|
||||
export class CarWashing extends JlGraphic {
|
||||
static Type = 'carWashing';
|
||||
codeGraph: VectorText = new VectorText('');
|
||||
rectBody: Graphics = new Graphics();
|
||||
|
||||
constructor() {
|
||||
super(CarWashing.Type);
|
||||
this.addChild(this.codeGraph);
|
||||
this.addChild(this.rectBody);
|
||||
this.codeGraph.name = 'carw_code';
|
||||
}
|
||||
get code(): string {
|
||||
return this.datas.code;
|
||||
}
|
||||
get datas(): ICarWashingData {
|
||||
return this.getDatas<ICarWashingData>();
|
||||
}
|
||||
doRepaint(): void {
|
||||
const codeGraph = this.codeGraph;
|
||||
codeGraph.text = this.datas.code;
|
||||
codeGraph.style.fill = carWashingConsts.codeColor;
|
||||
codeGraph.setVectorFontSize(carWashingConsts.codeFontSize);
|
||||
codeGraph.anchor.set(0.5);
|
||||
const codeTransform = this.datas?.childTransforms?.find(
|
||||
(item) => item.name === 'carw_code'
|
||||
);
|
||||
if (codeTransform) {
|
||||
const position = codeTransform?.transform.position;
|
||||
const rotation = codeTransform?.transform?.rotation;
|
||||
codeGraph.position.set(position?.x, position?.y);
|
||||
codeGraph.rotation = rotation || 0;
|
||||
} else {
|
||||
codeGraph.position.set(0, -30);
|
||||
}
|
||||
this.rectBody.clear();
|
||||
this.rectBody.beginFill(carWashingConsts.bodyColor, 0);
|
||||
this.rectBody.lineStyle(
|
||||
carWashingConsts.bodyRectLineWidth,
|
||||
carWashingConsts.bodyRectLineColor
|
||||
);
|
||||
this.rectBody.drawRect(
|
||||
-carWashingConsts.bodyRectWidth / 2,
|
||||
-carWashingConsts.bodyRectHeight / 2,
|
||||
carWashingConsts.bodyRectWidth,
|
||||
carWashingConsts.bodyRectHeight
|
||||
);
|
||||
this.rectBody.endFill();
|
||||
}
|
||||
}
|
||||
|
||||
export class CarWashingTemplate extends JlGraphicTemplate<CarWashing> {
|
||||
constructor(dataTemplate: ICarWashingData) {
|
||||
super(CarWashing.Type, { dataTemplate });
|
||||
}
|
||||
new(): CarWashing {
|
||||
const carWashing = new CarWashing();
|
||||
carWashing.loadData(this.datas);
|
||||
return carWashing;
|
||||
}
|
||||
}
|
128
src/graphics/carWashing/CarWashingDrawAssistant.ts
Normal file
128
src/graphics/carWashing/CarWashingDrawAssistant.ts
Normal file
@ -0,0 +1,128 @@
|
||||
import { DisplayObject, FederatedMouseEvent, Point } from 'pixi.js';
|
||||
import {
|
||||
AbsorbableLine,
|
||||
AbsorbablePosition,
|
||||
GraphicDrawAssistant,
|
||||
GraphicInteractionPlugin,
|
||||
GraphicTransformEvent,
|
||||
IDrawApp,
|
||||
JlGraphic,
|
||||
} from 'jl-graphic';
|
||||
import { CarWashing, CarWashingTemplate, ICarWashingData } from './CarWashing';
|
||||
|
||||
export interface ICarWashingDataDrawOptions {
|
||||
newData: () => ICarWashingData;
|
||||
}
|
||||
export class CarWashingDraw extends GraphicDrawAssistant<
|
||||
CarWashingTemplate,
|
||||
ICarWashingData
|
||||
> {
|
||||
_carWashing: CarWashing | null = null;
|
||||
constructor(app: IDrawApp, template: CarWashingTemplate) {
|
||||
super(
|
||||
app,
|
||||
template,
|
||||
'svguse:../../drawIcon.svg#icon-car-washing',
|
||||
'洗车机CarWashing'
|
||||
);
|
||||
CarWashingInteraction.init(app);
|
||||
}
|
||||
public get carWashing(): CarWashing {
|
||||
if (!this._carWashing) {
|
||||
this._carWashing = this.graphicTemplate.new();
|
||||
this._carWashing.loadData(this.graphicTemplate.datas);
|
||||
this.container.addChild(this._carWashing);
|
||||
}
|
||||
return this._carWashing;
|
||||
}
|
||||
|
||||
onLeftUp(e: FederatedMouseEvent): void {
|
||||
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
|
||||
this.createAndStore(true);
|
||||
}
|
||||
|
||||
redraw(p: Point): void {
|
||||
this.carWashing.repaint();
|
||||
this.container.position.set(p.x, p.y);
|
||||
}
|
||||
|
||||
prepareData(data: ICarWashingData): boolean {
|
||||
data.transform = this.container.saveTransform();
|
||||
data.code = 'CarWash';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 构建吸附线
|
||||
* @param carWashing
|
||||
*/
|
||||
function buildAbsorbablePositions(
|
||||
carWashing: CarWashing
|
||||
): AbsorbablePosition[] {
|
||||
const aps: AbsorbablePosition[] = [];
|
||||
const carWashings = carWashing.queryStore.queryByType<CarWashing>(
|
||||
CarWashing.Type
|
||||
);
|
||||
const canvas = carWashing.getCanvas();
|
||||
carWashings.forEach((item) => {
|
||||
if (item.id === carWashing.id) {
|
||||
return;
|
||||
}
|
||||
const ala = new AbsorbableLine(
|
||||
new Point(item.x, 0),
|
||||
new Point(item.x, canvas.height)
|
||||
);
|
||||
const alb = new AbsorbableLine(
|
||||
new Point(0, item.y),
|
||||
new Point(canvas.width, item.y)
|
||||
);
|
||||
aps.push(ala);
|
||||
aps.push(alb);
|
||||
});
|
||||
return aps;
|
||||
}
|
||||
|
||||
export class CarWashingInteraction extends GraphicInteractionPlugin<CarWashing> {
|
||||
static Name = 'car_washing_transform';
|
||||
constructor(app: IDrawApp) {
|
||||
super(CarWashingInteraction.Name, app);
|
||||
}
|
||||
static init(app: IDrawApp) {
|
||||
return new CarWashingInteraction(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): CarWashing[] | undefined {
|
||||
return grahpics
|
||||
.filter((g) => g.type === CarWashing.Type)
|
||||
.map((g) => g as CarWashing);
|
||||
}
|
||||
bind(g: CarWashing): void {
|
||||
g.eventMode = 'static';
|
||||
g.cursor = 'pointer';
|
||||
g.scalable = true;
|
||||
g.rotatable = true;
|
||||
g.codeGraph.draggable = true;
|
||||
g.codeGraph.selectable = true;
|
||||
g.codeGraph.rotatable = true;
|
||||
g.codeGraph.transformSave = true;
|
||||
g.codeGraph.eventMode = 'static';
|
||||
g.on('transformstart', this.transformstart, this);
|
||||
}
|
||||
unbind(g: CarWashing): void {
|
||||
g.eventMode = 'none';
|
||||
g.scalable = false;
|
||||
g.rotatable = false;
|
||||
g.codeGraph.draggable = false;
|
||||
g.codeGraph.selectable = false;
|
||||
g.codeGraph.rotatable = false;
|
||||
g.codeGraph.transformSave = false;
|
||||
g.codeGraph.eventMode = 'none';
|
||||
g.off('transformstart', this.transformstart, this);
|
||||
}
|
||||
transformstart(e: GraphicTransformEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const carWashing = target.getGraphic() as CarWashing;
|
||||
carWashing.getGraphicApp().setOptions({
|
||||
absorbablePositions: buildAbsorbablePositions(carWashing),
|
||||
});
|
||||
}
|
||||
}
|
@ -54,7 +54,9 @@ export class ConcentrationDividingLine
|
||||
this.transformSave = true;
|
||||
this.addChild(this.lineGraphic);
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.datas.code;
|
||||
}
|
||||
get datas(): IConcentrationDividingLineData {
|
||||
return this.getDatas<IConcentrationDividingLineData>();
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user