Compare commits

..

9 Commits

Author SHA1 Message Date
joylink_zhaoerwei
bae53824c3 道岔 2024-01-22 10:44:00 +08:00
joylink_zhaoerwei
d1f03f2cfc 道岔 2024-01-19 16:17:27 +08:00
joylink_zhaoerwei
fdf2a9c00e 引入路径修改 2024-01-11 14:06:13 +08:00
joylink_zhaoerwei
b820922888 站台车站 2024-01-10 16:16:57 +08:00
joylink_zhaoerwei
0b8055bb73 车站站台计轴 2024-01-05 17:42:53 +08:00
dong
99baef2afd 列车调整 2024-01-04 16:43:53 +08:00
dong
b7b9da32eb 代码调整 2024-01-04 16:25:55 +08:00
dong
02059fe2a8 列车、分隔符、应答器替换 2024-01-04 15:32:53 +08:00
dong
1dc177544b 测试图像组件化分支 2024-01-04 13:55:16 +08:00
190 changed files with 12937 additions and 22450 deletions

6
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "rts-sim-testing-message"]
path = rts-sim-testing-message
url = http://120.46.212.6:3000/joylink/rts-sim-testing-message.git
[submodule "bj-rtss-message"]
path = bj-rtss-message
url = ../bj-rtss-message.git

1
bj-rtss-message Submodule

@ -0,0 +1 @@
Subproject commit 999608fa88a430cba9bef8915f76993a0e4c6d8e

10502
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -22,13 +22,13 @@
"default-passive-events": "^2.0.0",
"echarts": "^5.4.3",
"google-protobuf": "^3.21.2",
"jl-graphic": "git+http://120.46.212.6:3000/joylink/graphic-pixi.git#v0.1.11",
"jl-graphic": "git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#v0.1.8",
"rt-graphic-component": "git+https://git.code.tencent.com/jl-framework/rt-graphic-component.git#c7eb525",
"js-base64": "^3.7.5",
"pinia": "^2.0.11",
"quasar": "^2.6.0",
"vue": "^3.0.0",
"vue-router": "^4.0.0",
"xlsx": "^0.18.5"
"vue-router": "^4.0.0"
},
"devDependencies": {
"@quasar/app-vite": "^1.0.0",
@ -46,7 +46,7 @@
"typescript": "^4.5.4"
},
"engines": {
"node": "^20 || ^18 || ^16 || ^14.19",
"node": "^18 || ^16 || ^14.19",
"npm": ">= 6.13.4",
"yarn": ">= 1.21.1"
}

View File

@ -32,11 +32,6 @@
<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"/>
@ -80,10 +75,4 @@
<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: 13 KiB

After

Width:  |  Height:  |  Size: 11 KiB

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

View File

@ -7,7 +7,7 @@ const os = require('os');
const { exec } = require('child_process');
const messageDir = resolve(__dirname, '../rts-sim-testing-message');
const messageDir = resolve(__dirname, '../bj-rtss-message');
const protoDir = resolve(messageDir, 'protos');
const destDir = resolve(__dirname, '../src/protos');

View File

@ -118,8 +118,7 @@ export async function getPublishMapInfoByLineId(
export function saveToDraft(
id: number,
data: {
draftName: string;
category: string;
name: string;
}
) {
return api.post(`${PublishUriBase}/saveAsDrafting/${id}`, data);

View File

@ -1,6 +1,4 @@
import { api } from 'src/boot/axios';
import { request } from 'src/protos/request';
import { TrainConfigData } from './TrainModelApi';
const UriBase = '/api/v1/simulation';
@ -22,16 +20,6 @@ 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
@ -41,43 +29,36 @@ export interface TrainEnd {
* @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;
}
/**
*
@ -93,48 +74,22 @@ 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;
deviceId: number;
operation: request.Section.Operation;
param?: {
mockDrst: boolean;
mockPdrst: boolean;
};
id: number;
operation: number;
}) {
return await api.post(`${UriBase}/axleSection/operation`, data);
}
// {
// simulationId: string;
// mapId: number;
// id: number;
// operation: number;
// aspect: number;
// }
export interface SignalOperationReq {
export async function setSignalState(data: {
simulationId: string;
mapId: number;
deviceId: number;
operation: request.Signal.Operation;
param: {
force: request.Signal.Force;
dsList: request.Signal.DS[];
};
}
export async function setSignalState(data: SignalOperationReq) {
id: number;
operation: number;
aspect: number;
}) {
return await api.post(`${UriBase}/signal/operation`, data);
}
@ -143,7 +98,6 @@ export interface SetSwitchParams {
mapId: number;
deviceId: number;
operation: number;
param: { forcePosition: number };
}
export async function setSwitchPosition(data: SetSwitchParams) {
@ -155,7 +109,7 @@ export interface IbpButtonOperationParams {
down: boolean;
mapId: number;
simulationId: string;
ibpId: number;
stationId: number;
}
export async function ibpButtonOperation(params: IbpButtonOperationParams) {
return await api.post(`${UriBase}/ibp/btn/operation`, params);
@ -175,7 +129,7 @@ export async function esbButtonOperation(params: EsbButtonOperationParams) {
export interface IbpKeyOperationParams {
simulationId: string;
mapId: number;
ibpId: number;
stationId: number;
gear: number;
keyId: number;
}
@ -238,10 +192,10 @@ export async function getSimulationChannelName(): Promise<string> {
* @returns
*/
export async function setRelayState(data: {
simulationId: string;
id: number;
mapId: number;
deviceId: number;
operation: request.Relay.Operation;
simulationId: string;
td: boolean;
}) {
return await api.post(`${UriBase}/relay/operation`, data);
}
@ -270,7 +224,7 @@ export async function getMapKilometerRange(
export async function pslOperate(data: {
simulationId: string;
mapId: number;
pslId: number;
gateBoxId: number;
buttonCode: string;
down: boolean;
}) {
@ -283,150 +237,9 @@ export async function screenDoorOperate(data: {
simulationId: string;
mapId: number;
deviceId: number;
operation: request.Psd.Operation;
param: {
asdCodes: number[];
force: request.Psd.Force;
fault: request.Psd.Fault;
};
operation: number;
asdCodes?: number[];
group?: number;
}) {
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);
}

View File

@ -27,37 +27,15 @@ 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;
}
/**

View File

@ -67,9 +67,6 @@ 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
@ -77,10 +74,6 @@ 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) => {

View File

@ -3,7 +3,6 @@
ref="dialogRef"
@hide="onHide"
v-bind="$attrs"
@show="emit('show')"
transitionShow="jump-up"
transitionHide="jump-down"
class="column"
@ -12,22 +11,17 @@
:style="{
transform: `translate3d(${offset.x}px, ${offset.y}px, 1px)`,
background: `${props.bgColor}`,
border: `${props.bgBorder}`,
}"
style="max-width: 2000px"
>
<q-bar
ref="headerRef"
class="non-selectable q-gutter-l"
style="
cursor: move;
border-top-right-radius: 0;
border-top-left-radius: 0;
"
style="cursor: move"
:style="`height: ${props.titleHeight}px;background: ${props.titleColor}`"
>
<div
:style="`height: 100%; line-height: ${props.titleHeight}px; color:${props.fontColor};font-size: ${props.fontSize}px;`"
:style="`color:${props.fontColor};font-size: ${props.fontSize}px;`"
>
{{ props.title }}
</div>
@ -51,10 +45,7 @@
import { QBar, useDialogPluginComponent } from 'quasar';
import { ref, onMounted, onUnmounted, reactive } from 'vue';
const emit = defineEmits({
...useDialogPluginComponent.emitsObject,
show: () => true,
});
const emit = defineEmits([...useDialogPluginComponent.emits]);
const props = withDefaults(
defineProps<{
@ -66,11 +57,10 @@ const props = withDefaults(
width?: number;
height?: number;
bgColor?: string;
bgBorder?: string;
}>(),
{
width: 500,
height: 800,
height: 600,
titleColor: 'rgb(25,118,210)',
titleHeight: 36,
fontSize: 20,
@ -78,8 +68,7 @@ const props = withDefaults(
}
);
const { dialogRef, onDialogHide /* , onDialogCancel, onDialogOK */ } =
useDialogPluginComponent();
const { dialogRef, onDialogHide } = useDialogPluginComponent();
const headerRef = ref<InstanceType<typeof QBar> | null>(null);
@ -89,7 +78,6 @@ const offset = reactive({
});
const start = { x: 0, y: 0 };
const startOffset = { x: 0, y: 0 };
onMounted(() => {
window.addEventListener('mousedown', onMouseDown);
@ -100,24 +88,16 @@ onUnmounted(() => {
});
function onMove(e: MouseEvent) {
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];
[offset.x, offset.y] = [e.screenX - start.x, e.screenY - start.y];
}
function onMouseUp() {
window.removeEventListener('mousemove', onMove);
window.removeEventListener('mouseup', onMouseUp);
startOffset.x = 0;
startOffset.y = 0;
}
function onMouseDown(e: MouseEvent) {
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;
if (headerRef.value?.$el !== e.target) return;
start.x = e.screenX - offset.x;
start.y = e.screenY - offset.y;
window.addEventListener('mousemove', onMove);
window.addEventListener('mouseup', onMouseUp);
}

View File

@ -39,17 +39,12 @@
<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"
@ -95,6 +90,7 @@
></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"
@ -139,18 +135,6 @@
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">
@ -168,10 +152,6 @@ 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';
@ -216,6 +196,7 @@ 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';
@ -227,16 +208,35 @@ 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>

View File

@ -1,49 +0,0 @@
<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>

View File

@ -1,16 +1,12 @@
<!-- eslint-disable vue/no-mutating-props -->
<template>
<draggable-dialog
seamless
title="添加列车"
v-model="showAddTrainOperation"
:width="300"
:height="525"
>
<q-dialog ref="dialogRef">
<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"
@ -18,21 +14,7 @@
/>
<q-input
type="number"
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"
dense
outlined
:label="`列车偏移(mm)【长度${props.kmLength}mm】`"
:max="kmLength"
@ -44,6 +26,7 @@
<q-select
v-model="dir"
label="运行方向"
dense
outlined
:options="dirOptions"
emitValue
@ -54,6 +37,7 @@
<q-select
v-model="trainConfig"
label="列车配置"
dense
outlined
:options="trainConfigOption"
:option-label="
@ -71,43 +55,39 @@
</q-select>
<q-input
type="number"
dense
outlined
:label="`列车轮径(mm)【750-840mm】`"
:max="840"
:min="750"
:label="`列车轮径(mm)【${
trainConfig ? trainConfig.min_diameter : ''
}-${trainConfig ? trainConfig.max_diameter : ''}mm`"
:max="trainConfig?.max_diameter"
:min="trainConfig?.min_diameter"
v-model.number="wheelDiameter"
lazy-rules
:rules="wheelDiameterRules"
/>
<q-card-actions align="right" class="text-primary">
<q-btn
flat
label="取消"
@click="showAddTrainOperation = false"
v-close-popup
/>
<q-btn flat label="取消" @click="onDialogCancel" v-close-popup />
<q-btn flat label="确认" type="submit" :disable="!trainConfig" />
</q-card-actions>
</q-form>
</q-card-section>
</q-card>
</draggable-dialog>
</q-dialog>
</template>
<script setup lang="ts">
import { QForm } from 'quasar';
import { TrainConfigData, TrainConfigItem } from 'src/api/TrainModelApi';
import { QForm, useDialogPluginComponent } from 'quasar';
import { 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, onUnmounted } from 'vue';
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
import { addTrain } from 'src/api/Simulation';
import { errorNotify } from 'src/utils/CommonNotify';
import { computed, onMounted, ref } from 'vue';
const props = defineProps({
dev: {
type: Section,
type: [Section, Turnout],
required: true,
},
kmLength: {
@ -128,10 +108,10 @@ const dirOptions = [
{ label: '上行', value: 1 },
{ label: '下行', value: 0 },
];
const trainSpeed = ref(0);
const trainId = ref(1);
const showAddTrainOperation = ref(true);
defineEmits([...useDialogPluginComponent.emits]);
const { dialogRef, onDialogOK, onDialogCancel } = useDialogPluginComponent();
const offsetRules = [
(val: string) => (val !== null && val !== '') || '偏移量不能为空!',
@ -148,45 +128,12 @@ const myForm = ref<QForm | null>(null);
function onCreate() {
myForm.value?.validate().then(async (res) => {
if (res) {
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,
onDialogOK({
dir: dir.value,
offset: offset.value,
trainLength: trainConfig.value?.total_length,
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;
}
});
}
@ -194,7 +141,13 @@ function onCreate() {
const wheelDiameter = ref(800);
const wheelDiameterRules = [
(val: string) => (val !== null && val !== '') || '列车轮径不能为空!',
(val: number) => (val >= 750 && val <= 840) || '列车轮径在750到840mm之间',
(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之间`,
];
const trainConfigOption = computed(() => {
@ -205,17 +158,15 @@ 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>

View File

@ -1,251 +0,0 @@
<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>

View File

@ -66,8 +66,6 @@ const deviceTypeMap = {
8: '信号机故障报警仪',
9: '断路器',
10: '电源屏',
11: '车库门',
12: '洗车机',
};
const columns: QTable['columns'] = [
{

View File

@ -1,167 +0,0 @@
<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>

View File

@ -1,143 +0,0 @@
<!-- 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>

View File

@ -1,124 +0,0 @@
<!-- 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>

View File

@ -1,179 +0,0 @@
<!-- 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>

View File

@ -1,108 +0,0 @@
<!-- 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>

View File

@ -1,97 +0,0 @@
<!-- 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>

View File

@ -1,598 +0,0 @@
<!-- 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>

View File

@ -1,262 +0,0 @@
<!-- 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>

View File

@ -1,89 +0,0 @@
<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>

View File

@ -1,123 +0,0 @@
<!-- 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>

View File

@ -1,220 +0,0 @@
<!-- 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>

View File

@ -43,77 +43,30 @@
</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, reactive } from 'vue';
import { onMounted, onUnmounted, reactive } from 'vue';
const ibpDrawStore = useIBPDrawStore();
const canvas = reactive({
width: 1920,
height: 1080,
backgroundColor: '#706e6e',
gridBackground: {
hasGrid: false,
lineColor: '#c2aeae',
space: 50,
},
backgroundColor: '#ffffff',
});
onMounted(() => {
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);
// 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');
});
function onUpdate() {

View File

@ -1,80 +0,0 @@
<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>

View File

@ -1,100 +0,0 @@
<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>

View File

@ -1,95 +0,0 @@
<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>

View File

@ -1,78 +0,0 @@
<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>

View File

@ -1,101 +0,0 @@
<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>

View File

@ -24,7 +24,7 @@
class="q-mt-sm"
@blur="onUpdate"
v-model="gatedBoxModel.refGatedBoxMapCode"
:options="pslNameList"
:options="props.pslNameList"
label="关联PSL地图"
/>
</q-form>
@ -34,31 +34,24 @@
import { GatedBoxData } from 'src/drawApp/graphics/GatedBoxInteraction';
import { useFormData } from 'src/components/DrawAppFormUtils';
import { useDrawStore } from 'src/stores/draw-store';
import { onMounted, reactive, ref } from 'vue';
import { onMounted, reactive, defineProps } 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);

View File

@ -1,72 +0,0 @@
<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>

View File

@ -1,72 +0,0 @@
<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>

View File

@ -86,8 +86,6 @@ 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 = [

View File

@ -32,9 +32,14 @@ const upDownOptions = [
];
function setSignalDirection(signal: Signal, v1: { x: number; y: number }) {
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 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 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);

View File

@ -19,15 +19,6 @@
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">
@ -83,6 +74,14 @@
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>
@ -91,9 +90,17 @@ import { useFormData } from 'src/components/DrawAppFormUtils';
import { StationData } from 'src/drawApp/graphics/StationInteraction';
import { Station } from 'src/graphics/station/Station';
import { useDrawStore } from 'src/stores/draw-store';
import { onMounted, watchEffect } from 'vue';
import { defineProps, onMounted, watchEffect } from 'vue';
const drawStore = useDrawStore();
const props = defineProps({
ibpNameList: {
type: Array,
required: true,
},
});
const { data: stationModel, onUpdate } = useFormData(
new StationData(),
drawStore.getDrawApp()
@ -103,6 +110,7 @@ const directionOptions = [
{ label: '左行', value: 0 },
{ label: '右行', value: 1 },
];
let optionsStations: { label: string; value: number }[] = [];
watchEffect(() => {

View File

@ -1,28 +0,0 @@
<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>

View File

@ -1,24 +0,0 @@
<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>

View File

@ -1,44 +0,0 @@
<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>

View File

@ -1,50 +0,0 @@
<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>

View File

@ -50,22 +50,6 @@
@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

View File

@ -101,6 +101,12 @@ import { useFormData } from 'src/components/DrawAppFormUtils';
import AddCentralizedStationDialog from '../dialogs/AddCentralizedStationDialog.vue';
import { Station } from 'src/graphics/station/Station';
enum DevicePort {
A = 0,
B = 1,
C = 2,
}
const drawStore = useDrawStore();
const $q = useQuasar();
@ -157,9 +163,9 @@ const sectionRelations = computed(() => {
);
return sectionRelations.map(
(relation) =>
`${relation.getRelationParam(turnout).param}: ${
`${DevicePort[relation.getRelationParam(turnout).param]}: ${
relation.getOtherGraphic<Section>(turnout).datas.code
}(${relation.getOtherRelationParam(turnout).param})`
}(${DevicePort[relation.getOtherRelationParam(turnout).param]})`
);
});
@ -173,9 +179,9 @@ const turnoutRelations = computed(() => {
);
return turnoutRelations.map(
(relation) =>
`${relation.getRelationParam(turnout).param}: ${
`${DevicePort[relation.getRelationParam(turnout).param]}: ${
relation.getOtherGraphic<Turnout>(turnout).datas.code
}(${relation.getOtherRelationParam(turnout).param})`
}(${DevicePort[relation.getOtherRelationParam(turnout).param]})`
);
});

View File

@ -25,9 +25,6 @@
<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>
@ -54,8 +51,6 @@ 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>

View File

@ -1,88 +0,0 @@
<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>

View File

@ -2,181 +2,48 @@
<q-card flat bordered>
<q-card-section class="flex justify-between">
<span class="text-h6">列车信息</span>
<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-btn color="primary" label="曲线图" @click="open" />
</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
:style="{
color:
item.key === 'conn' || item.key === 'connType'
? trainInfo.conn
? '#0F0'
: '#F00'
: '',
}"
>{{ item.label }}</q-item-label
>
<q-item-label>{{ item.label }}</q-item-label>
</q-item-section>
<q-item-section side>
<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-label caption>{{
item.formatFn
? item.formatFn(trainInfo[item.key])
: trainInfo[item.key]
}}</q-item-label>
</q-item-section>
</q-item>
<q-separator inset />
<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-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>
</q-list>
</q-card>
</template>
@ -186,29 +53,20 @@ 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 },
{
@ -253,24 +111,14 @@ 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: '基本阻力参数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 },
{ label: '加速度', key: 'acceleration', formatFn: accelerationFormat },
];
const list3: KeyType[] = [
//
@ -328,74 +176,6 @@ 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 ? '是' : '否';
}
@ -428,31 +208,12 @@ function speedFormat(v: number) {
}
function accelerationFormat(v: number) {
const n = floatDecimal(v);
return `${n} m/s²`;
}
function chongjilvFormat(v: number) {
return `${v} m/s³`;
}
function haomiaoFormat(v: number) {
return `${v} ms`;
return `${n} m/s`;
}
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);
@ -517,28 +278,6 @@ 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,
@ -561,8 +300,7 @@ watch(
);
});
if (find) {
// console.log(find, '1111');
trainInfo.value = find as ITrainState;
trainInfo.value.copyFrom(find);
}
}
}
@ -598,75 +336,4 @@ 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>

View File

@ -1,30 +1,78 @@
<template>
<q-card flat bordered>
<q-card-section>
<QCard flat bordered>
<QCardSection>
<div class="text-h6">站台状态</div>
</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>
</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>
</template>
<script setup lang="ts">
import { useLineStore } from 'src/stores/line-store';
import { ref, watch, watchEffect, onUnmounted } from 'vue';
import { ref, watch, watchEffect, onUnmounted, computed } from 'vue';
import { Platform } from 'src/graphics/platform/Platform';
import { state } from 'src/protos/device_state';
import { PlatformState } from 'src/drawApp/graphics/PlatformInteraction';
@ -44,28 +92,6 @@ 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 &&
@ -74,7 +100,7 @@ const stop = watchEffect(() => {
setPlatformState(lineStore.selectedGraphics[0] as Platform);
}
});
onUnmounted(stop);
watch(
() => lineStore.socketStates,
(val) => {
@ -96,6 +122,21 @@ 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,
@ -105,44 +146,4 @@ 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>

View File

@ -1,11 +1,5 @@
<template>
<q-card
flat
bordered
v-for="(item, index) in relayState"
:key="item.id"
style="margin-bottom: 10px"
>
<q-card flat bordered>
<q-card-section class="flex justify-between">
<span class="text-h6">继电器状态</span>
<q-btn-dropdown color="primary" label="操作">
@ -15,7 +9,7 @@
:key="item.label"
clickable
v-close-popup
@click="changePosition(item.value, index)"
@click="changePosition(item.value)"
>
<q-item-section>{{ item.label }}</q-item-section>
</q-item>
@ -23,21 +17,10 @@
</q-btn-dropdown>
</q-card-section>
<q-separator inset />
<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 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-card>
</template>
@ -49,57 +32,29 @@ 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: number;
code: string;
xh: boolean;
force: boolean;
}[]
>([
{
id: 0,
code: '',
xh: false,
force: false,
},
]);
const relayState = ref({
id: 0,
code: '',
xh: false,
});
let operateOptions: {
label: string;
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 },
];
value: boolean;
}[] = [];
let copySelectGraphic: Relay | null = null;
watch(
() => lineStore.selectedGraphics,
(val, oldVal) => {
if (oldVal && oldVal.length >= 1) {
unSubscribeState(oldVal as Relay[]);
if (oldVal?.length == 1 && oldVal[0] instanceof Relay) {
unSubscribeState(oldVal[0]);
}
if (val && val.length >= 1) {
copySelectGraphic = toRaw(val as Relay[]);
initRelayState(val as Relay[]);
if (val?.length == 1 && val[0] instanceof Relay) {
copySelectGraphic = toRaw(val[0]);
setNewRelayState(val[0]);
} else {
copySelectGraphic = null;
}
@ -108,50 +63,44 @@ watch(
onMounted(() => {
if (lineStore.selectedGraphics) {
initRelayState(lineStore.selectedGraphics as Relay[]);
setNewRelayState(lineStore.selectedGraphics[0] as Relay);
}
});
function getRelayStateName(v: boolean) {
if (v) return 'Q';
return 'H';
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 getName(v: boolean) {
if (v) return '是';
return '否';
function subscribeState(g: Relay) {
g.on('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 unSubscribeState(g: Relay) {
g.off('stateupdate', updateState);
}
function updateState(newVal: RelayState) {
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;
}
}
relayState.value.xh = newVal.states.xh || false;
operateOptions = newVal.states.xh
? [{ label: '驱动落下', value: false }]
: [{ label: '驱动吸起', value: true }];
}
function changePosition(operation: request.Relay.Operation, index: number) {
function changePosition(td: boolean) {
if (lineStore.simulationId) {
setRelayState({
simulationId: lineStore.simulationId,
id: relayState.value.id,
mapId: lineStore.mapId as number,
deviceId: relayState.value[index].id,
operation,
simulationId: lineStore.simulationId,
td,
})
.then(() => {
$q.notify({ type: 'positive', message: '修改继电器状态成功' });
@ -166,18 +115,6 @@ function changePosition(operation: request.Relay.Operation, index: number) {
}
}
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);

View File

@ -20,128 +20,280 @@
</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(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-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-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, onUnmounted, toRaw } from 'vue';
import { ref, watch, onMounted } 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 sonDoorAmount = ref(0);
const operationOptions = [
{
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.Force.F_ASD_KM,
},
{
label: '强制关门',
value: request.Psd.Force.F_ASD_GM,
},
];
const screenDoorFault = ref<request.Psd.Fault>(0);
const selectAsd = ref(false);
const asdCodes = ref<number[]>([]);
const asdOptions = ref<number[]>([]);
let copySelectGraphic: ScreenDoor | null = null;
let asdOperation: null | request.Psd.Operation = null;
const operationOptions = ref<
{ label: string; value: request.Psd.Operation; group?: number }[]
>([]);
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 },
const options = [
// {
// label: '',
// value: request.Psd.Operation.Km,
// },
// {
// label: '',
// value: request.Psd.Operation.CancelKm,
// },
{
label: '关门',
value: request.Psd.Operation.Gm,
},
{
label: '取消关门',
value: request.Psd.Operation.CancelGm,
},
// {
// 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,
},
];
watch(
() => lineStore.selectedGraphics,
(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]);
(val) => {
if (val?.length == 1 && val[0].type == ScreenDoor.Type) {
initScreenDoorState(val[0] as ScreenDoor);
} 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) {
@ -149,84 +301,20 @@ onMounted(() => {
}
});
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);
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;
}
}
}
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>

View File

@ -9,7 +9,7 @@
:key="index"
clickable
v-close-popup
@click="doSectionOperation(item)"
@click="toDo(item)"
>
<q-item-section>
<q-item-label>{{ item.label }}</q-item-label>
@ -20,17 +20,42 @@
</q-card-section>
<q-separator inset />
<q-card-section>
<q-list dense>
<q-item v-for="(item, index) in list" :key="index">
<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-item-section>
<q-item-label>{{ item.label }}</q-item-label>
<q-checkbox
dense
v-model="sectionState.occupied"
outlined
label="是否占用"
:disable="true"
/>
</q-item-section>
<q-item-section side>
<q-item-label caption>{{
item.formatFn
? item.formatFn(sectionState[item.key])
: sectionState[item.key]
}}</q-item-label>
</q-item>
<q-item>
<q-item-section>
<q-checkbox
dense
v-model="sectionState.axleFault"
outlined
label="是否计轴故障"
:disable="true"
/>
</q-item-section>
</q-item>
</q-list>
@ -39,151 +64,118 @@
</template>
<script setup lang="ts">
import { useLineStore } from 'src/stores/line-store';
import { ref, watch, onMounted, onUnmounted, toRaw } from 'vue';
import { Section } from 'src/graphics/section/Section';
import { ref, watch, onMounted } from 'vue';
import { Section, type ISectionState } 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 { errorNotify } from 'src/utils/CommonNotify';
import { useQuasar } from 'quasar';
import { ApiError } from 'src/boot/axios';
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, 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);
(val) => {
if (val?.length == 1 && val[0].type == Section.Type) {
setSectionState(val[0] as Section);
} else {
copySelectGraphic = null;
sectionState.value = {
id: 0,
code: '',
axleFault: false,
occupied: false,
axleDrst: false,
axlePdrst: false,
};
}
}
);
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);
function setSectionState(section: 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);
}
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,
};
}
onMounted(() => {
if (lineStore.selectedGraphics) {
setSectionState(lineStore.selectedGraphics[0] as Section);
}
});
const options = [
{
label: '设置参数',
value: request.Section.Operation.SetParams,
label: '设置计轴直接复位',
value: request.Section.Operation.SetDrst,
},
{
label: '设置故障占用',
label: '取消计轴直接复位',
value: request.Section.Operation.CancelDrst,
},
{
label: '设置计轴预复位',
value: request.Section.Operation.SetPdrst,
},
{
label: '取消计轴预复位',
value: request.Section.Operation.CancelPdrst,
},
{
label: '设置区段故障占用',
value: request.Section.Operation.SetFaultOcc,
},
{
label: '取消区段故障占用',
value: request.Section.Operation.CancelFaultOcc,
},
];
function doSectionOperation(item: { label: string; value: number }) {
function toDo(item: { label: string; value: number }) {
if (!lineStore.simulationId) return;
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;
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,
});
});
} 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)
);
}
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,
};
}
}
}
}
function subscribeState(g: Section) {
g.on('stateupdate', updateState);
}
function unSubscribeState(g: Section) {
g.off('stateupdate', updateState);
}
onUnmounted(() => {
if (copySelectGraphic) {
unSubscribeState(copySelectGraphic);
}
});
);
</script>

View File

@ -20,183 +20,159 @@
</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(signalState[item.key])
: signalState[item.key]
}}</q-item-label>
</q-item-section>
</q-item>
</q-list>
<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-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, onUnmounted, toRaw } from 'vue';
import { ref, watch, onMounted } from 'vue';
import { Signal } from 'src/graphics/signal/Signal';
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';
import { setSignalState } from 'src/api/Simulation';
import { errorNotify } from 'src/utils/CommonNotify';
import { SignalState } from 'src/drawApp/graphics/SignalInteraction';
const lineStore = useLineStore();
const signalState = ref<SignalState>(new SignalState());
const code = ref('');
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 index = ref(0);
const aspectOptions = [
{ 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 },
{ label: '无用值', value: 0 },
{ label: '物理灭灯', value: 1 },
{ label: '绿灯亮', value: 2 },
{ label: '红灯亮', value: 3 },
{ label: '黄灯亮', value: 4 },
{ label: '红黄灯亮', value: 5 },
{ label: '白灯亮', value: 6 },
{ label: '蓝灯亮', value: 7 },
];
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 },
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,
},
},
];
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, oldVal) => {
if (oldVal?.length == 1 && oldVal[0] instanceof Signal) {
unSubscribeState(oldVal[0]);
}
if (val?.length == 1 && val[0] instanceof Signal) {
copySelectGraphic = toRaw(val[0]);
(val) => {
if (val?.length == 1 && val[0].type == Signal.Type) {
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) {
@ -207,26 +183,21 @@ function updateState(newVal: SignalState) {
// initSignalState(lineStore.selectedGraphics[0] as Signal);
// }
// }
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;
});
}
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 });
});
}
onMounted(() => {
@ -235,97 +206,20 @@ onMounted(() => {
}
});
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;
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 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>

View File

@ -1,24 +1,26 @@
<template>
<q-card flat bordered>
<q-card-section class="flex justify-between">
<q-card-section class="row justify-between items-center q-pb-none">
<div class="text-h6">车站状态</div>
<q-btn color="primary" @click="openIbp">打开IBP</q-btn>
</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(stationState[item.key])
: stationState[item.key]
}}</q-item-label>
</q-item-section>
</q-item>
</q-list>
<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-card-section>
</q-card>
</template>
@ -26,20 +28,10 @@
import { useLineStore } from 'src/stores/line-store';
import { ref, watch, onMounted } from 'vue';
import { Station } from 'src/graphics/station/Station';
import { StationState } from 'src/drawApp/graphics/StationInteraction';
import { useIbpStore } from 'src/stores/ibp-store';
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,
@ -55,6 +47,14 @@ 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,

View File

@ -1,300 +0,0 @@
<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>

View File

@ -9,7 +9,7 @@
:key="index"
clickable
v-close-popup
@click="doTurnoutOperation(item)"
@click="toDo(item)"
>
<q-item-section>
<q-item-label>{{ item.label }}</q-item-label>
@ -20,17 +20,183 @@
</q-card-section>
<q-separator inset />
<q-card-section>
<q-list dense>
<q-item v-for="(item, index) in list" :key="index">
<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-item-section>
<q-item-label>{{ item.label }}</q-item-label>
<q-checkbox
dense
v-model="turnoutState.normal"
outlined
label="定位(表示)"
:disable="true"
/>
</q-item-section>
<q-item-section side>
<q-item-label caption>{{
item.formatFn
? item.formatFn(turnoutState[item.key])
: turnoutState[item.key]
}}</q-item-label>
</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>
</q-item>
</q-list>
@ -40,156 +206,95 @@
<script setup lang="ts">
import { Turnout } from 'src/graphics/turnout/Turnout';
import { useLineStore } from 'src/stores/line-store';
import { ref, watch, onMounted, onUnmounted, toRaw } from 'vue';
import { Dialog } from 'quasar';
import { TurnoutStates } from 'src/drawApp/graphics/TurnoutInteraction';
import TurnoutOperation from 'src/components/draw-app/dialogs/TurnoutOperation.vue';
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 { TurnoutStates } from 'src/drawApp/graphics/TurnoutInteraction';
import { JlGraphic } from 'jl-graphic';
const $q = useQuasar();
const lineStore = useLineStore();
const turnoutState = ref<TurnoutStates>(new TurnoutStates());
const name = 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 },
];
const graphic = ref();
watch(
() => lineStore.selectedGraphics,
(val, oldVal) => {
if (oldVal?.length == 1 && oldVal[0] instanceof Turnout) {
unSubscribeState(oldVal[0]);
if (oldVal?.length == 1 && oldVal[0].type == Turnout.Type) {
unSubscribeState(oldVal[0] as JlGraphic);
}
if (val?.length == 1 && val[0] instanceof Turnout) {
copySelectGraphic = toRaw(val[0]);
initTurnoutState(val[0] as Turnout);
if (val?.length == 1 && val[0].type == Turnout.Type) {
graphic.value = val[0];
setTurnoutState(val[0] as Turnout);
} else {
turnoutState.value = new TurnoutStates();
name.value = '';
copySelectGraphic = null;
graphic.value = 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) {
initTurnoutState(lineStore.selectedGraphics[0] as Turnout);
setTurnoutState(lineStore.selectedGraphics[0] as Turnout);
}
});
onUnmounted(() => {
if (graphic.value) {
unSubscribeState(graphic.value as JlGraphic);
}
});
function getNameFormat(v: number) {
if (v) {
return name.value;
}
return '';
}
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 }) {
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;
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;
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 subscribeState(g: Turnout) {
function subscribeState(g: JlGraphic) {
if (g) {
g.on('stateupdate', updateState);
}
}
function unSubscribeState(g: Turnout) {
function unSubscribeState(g: JlGraphic) {
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;
function updateState(newVal: TurnoutStates) {
turnoutState.value = newVal.clone() as TurnoutStates;
}
</style>
</script>

View File

@ -1,22 +1,21 @@
function getHost(): string {
if (process.env.ENV_MODE == 'test') {
return 'test.joylink.club/bjrtsts-server';
return 'test.joylink.club/bjrtss-server';
} else if (process.env.ENV_MODE == 'publish') {
return 'joylink.club/bjrtsts-server';
return 'joylink.club/bjrtss-server';
}
// return '192.168.3.7:9091';
// return '192.168.3.47:9091';
// return '192.168.3.37:9091';
// return '192.168.33.207:9091'; // 张骞
// return '192.168.33.93:9091';
// return '192.168.3.15:9091';
// return '192.168.3.5:9091';
// return '192.168.3.37:9091'; //卫志宏
// return 'test.joylink.club/bjrtsts-service'; // 测试
return '192.168.33.233:9091';
return '192.168.3.233:9091';
}
export function getHttpBase() {
let protocol = 'http';
if (['publish'].includes(process.env.ENV_MODE as string)) {
if (['test', 'publish'].includes(process.env.ENV_MODE as string)) {
protocol = 'https';
}
return `${protocol}://${getHost()}`;
@ -24,18 +23,17 @@ export function getHttpBase() {
export function getWebsocketUrl() {
let protocol = 'ws';
let host = '192.168.33.233';
// let host = 'test.joylink.club';
let host = '192.168.3.233';
let port = '8083';
let url = `${protocol}://${host}:${port}`;
if (process.env.ENV_MODE == 'test') {
// protocol = 'wss';
host = 'test.joylink.club/bjrtsts-server';
protocol = 'wss';
host = 'test.joylink.club/bjrtss-server';
port = '';
url = `${protocol}://${host}`;
} else if (process.env.ENV_MODE == 'publish') {
protocol = 'wss';
host = 'joylink.club/bjrtsts-server';
host = 'joylink.club/bjrtss-server';
port = '';
url = `${protocol}://${host}`;
}

View File

@ -39,9 +39,9 @@ function handleSubscribe(ibpScene: IGraphicScene) {
const ibpStore = useIbpStore();
const simulationId = lineStore.simulationId;
const mapId = lineStore.mapId;
const ibpId = ibpStore.ibpId;
const stationId = ibpStore.stationId;
ibpScene.subscribe({
destination: `/rtsts/simulation/${simulationId}/ibp/${mapId}/${ibpId}`,
destination: `/rtsts/simulation/${simulationId}/ibp/${mapId}/${stationId}`,
messageConverter: (message: Uint8Array) => {
const states: GraphicState[] = [];

View File

@ -19,12 +19,6 @@ 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
@ -39,8 +33,6 @@ 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 },
@ -59,8 +51,4 @@ 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 },
];

View File

@ -1,17 +1,10 @@
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,
KeyListener,
calculateDistanceFromPointToLine,
getRectangleCenter,
distance2,
} from 'jl-graphic';
import { TrainState } from './graphics/TrainInteraction';
import {
SignalData,
DrawSignalInteraction,
@ -27,15 +20,13 @@ import { ConcentrationDividingLineDraw } from 'src/graphics/concentrationDividin
import { Polygon, PolygonTemplate } from 'src/graphics/polygon/Polygon';
import { PolygonData } from './graphics/PolygonInteraction';
import { PolygonDraw } from 'src/graphics/polygon/PolygonDrawAssistant';
import { Platform, PlatformTemplate } from 'src/graphics/platform/Platform';
import { StyleType } from 'rt-graphic-component/components/common/common';
import {
Platform,
PlatformDraw,
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,
@ -45,8 +36,11 @@ import {
ScreenDoorState,
} from './graphics/ScreenDoorInteraction';
import { ScreenDoorDraw } from 'src/graphics/screenDoor/ScreenDoorDrawAssistant';
import { Station, StationTemplate } from 'src/graphics/station/Station';
import { StationDraw } from 'src/graphics/station/StationDrawAssistant';
import {
Station,
StationDraw,
StationTemplate,
} from 'src/graphics/station/Station';
import { StationData, StationState } from './graphics/StationInteraction';
import {
OneClickGenerateDraw,
@ -64,15 +58,20 @@ import {
} from 'src/graphics/axleCounting/AxleCounting';
import { AxleCountingDraw } from 'src/graphics/axleCounting/AxleCountingDrawAssistant';
import { AxleCountingData } from './graphics/AxleCountingInteraction';
import { Turnout, TurnoutTemplate } from 'src/graphics/turnout/Turnout';
import { TurnoutDraw } from 'src/graphics/turnout/TurnoutDrawAssistant';
import {
Turnout,
TurnoutTemplate,
TurnoutDraw,
handleData,
} from 'src/graphics/turnout/Turnout';
import { TurnoutData, TurnoutStates } from './graphics/TurnoutInteraction';
import { Section, SectionTemplate } from 'src/graphics/section/Section';
import { SectionDraw } from 'src/graphics/section/SectionDrawAssistant';
import { SectionData, SectionStates } from './graphics/SectionInteraction';
import { toStorageTransform } from './graphics/GraphicDataBase';
import { SeparatorDraw } from 'src/graphics/separator/SeparatorDrawAssistant';
import { Separator, SeparatorTemplate } from 'src/graphics/separator/Separator';
import { Separator } from 'src/graphics/separator/Separator';
import { SeparatorTemplate } from 'rt-graphic-component/components/packages/Separator/Separator';
import { SeparatorData } from './graphics/SeparatorInteraction';
import { StopPositionDraw } from 'src/graphics/stopPosition/StopPositionDrawAssistant';
import {
@ -96,15 +95,6 @@ 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,
@ -114,15 +104,10 @@ import { GarageDoorBoxDraw } from 'src/graphics/garageDoorBox/GarageDoorBoxAssis
import { SpksSwitchDraw } from 'src/graphics/spksSwitch/SpksSwitchDrawAssistant';
import { GatedBoxDraw } from 'src/graphics/gatedBox/GatedBoxDrawAssistant';
// import { EsbButtonDraw } from 'src/graphics/esbButton/EsbButtonDrawAssistant';
import { TransponderDraw } from 'src/graphics/transponder/TransponderDrawAssistant';
import {
Transponder,
TransponderTemplate,
} from 'src/graphics/transponder/Transponder';
import {
TransponderData,
TransponderState,
} from './graphics/TransponderInteraction';
import { Transponder } from 'src/graphics/transponder/Transponder';
import { TransponderDraw } from 'rt-graphic-component/components/packages/Transponder/TransponderDrawAssistant';
import { TransponderTemplate } from 'rt-graphic-component/components/packages/Transponder/Transponder';
import { TransponderData } from './graphics/TransponderInteraction';
import { SlopeKiloMarkerDrawAssistant } from 'src/graphics/slopeKiloMarker/SlopeKiloMarkerDrawAssistant';
import {
SlopeKiloMarker,
@ -151,21 +136,6 @@ 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: '撤销',
@ -198,20 +168,19 @@ export const DefaultCanvasMenu = new ContextMenu({
export function initCommonDrawApp(app: IDrawApp) {
new PlatformDraw(
app,
new PlatformTemplate(new PlatformData(), new PlatformState())
new PlatformTemplate(new PlatformData(), new PlatformState(), StyleType.GP),
'svguse:../../drawIcon.svg#icon-platform'
);
new IbpBoxDraw(app, new IbpBoxTemplate(new IbpBoxData()));
new PslBoxDraw(app, new PslBoxTemplate(new PslBoxData()));
new ScreenDoorDraw(
app,
new ScreenDoorTemplate(new ScreenDoorData(), new ScreenDoorState())
);
new StationDraw(
app,
new StationTemplate(new StationData(), new StationState())
new StationTemplate(new StationData(), new StationState(), StyleType.GP),
'svguse:../../drawIcon.svg#icon-station'
);
// new SignalDraw(app, new SignalTemplate(new SignalData(), new SignalState()));
new TrainDraw(app, new TrainTemplate(new TrainState()));
new SectionDraw(
app,
new SectionTemplate(new SectionData(), new SectionStates())
@ -219,23 +188,21 @@ export function initCommonDrawApp(app: IDrawApp) {
new SignalDraw(app, new SignalTemplate(new SignalData(), new SignalState()));
new TurnoutDraw(
app,
new TurnoutTemplate(new TurnoutData(), new TurnoutStates())
new TurnoutTemplate(
new TurnoutData(),
new TurnoutStates(),
StyleType.GP,
handleData
)
);
new TrainWindowDraw(app, new TrainWindowTemplate(new TrainWindowData()));
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 TransponderState())
);
new TransponderDraw(app, new TransponderTemplate(new TransponderData()));
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())
@ -256,14 +223,10 @@ 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);
// 画布右键菜单
@ -296,99 +259,6 @@ 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(
@ -406,12 +276,6 @@ 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));
});
@ -445,9 +309,6 @@ 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));
// });
@ -472,15 +333,6 @@ 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;
}
@ -488,9 +340,7 @@ export function saveCommonDrawDatas(app: IDrawApp) {
const storage = new graphicData.RtssGraphicStorage();
const canvasData = app.canvas.saveData();
storage.canvas = new graphicData.Canvas({
width: canvasData.width,
height: canvasData.height,
backgroundColor: canvasData.backgroundColor,
...canvasData,
viewportTransform: toStorageTransform(canvasData.viewportTransform),
});
const graphics = app.queryStore.getAllGraphics();
@ -498,12 +348,6 @@ 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);
@ -540,11 +384,6 @@ 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);
@ -572,15 +411,6 @@ 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) => {

View File

@ -1,88 +0,0 @@
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);
}
}

View File

@ -66,8 +66,7 @@ export class EsbButtonData extends GraphicDataBase implements IEsbButtonData {
export class EsbButtonState
extends GraphicStateBase
implements IEsbButtonState
{
implements IEsbButtonState {
constructor(data?: state.ButtonState) {
let ibpButtonState;
if (data) {

View File

@ -1,85 +0,0 @@
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);
}
}

View File

@ -1,150 +0,0 @@
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
);
}
}

View File

@ -1,88 +0,0 @@
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);
}
}

View File

@ -6,7 +6,11 @@ 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';
@ -63,8 +67,7 @@ export class IBPButtonData extends GraphicDataBase implements IIBPButtonData {
export class IbpButtonState
extends GraphicStateBase
implements IIbpButtonState
{
implements IIbpButtonState {
constructor(data?: state.ButtonState) {
let ibpButtonState;
if (data) {
@ -106,7 +109,6 @@ 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);
}
@ -130,7 +132,6 @@ 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) {
@ -140,7 +141,6 @@ 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,13 +148,10 @@ export class IbpButtonInteraction extends GraphicInteractionPlugin<IBPButton> {
}
}
onMouseLeave(e: FederatedMouseEvent) {
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;
const changeState = useIbpStore().ibpButtonOperation;
const g = e.target as IBPButton;
if (g.datas.isSelfReset) {
changeState(g.datas.id, false);
}
}
}

View File

@ -1,88 +0,0 @@
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);
}
}

View File

@ -3,7 +3,11 @@ 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';

View File

@ -1,83 +0,0 @@
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);
}
}

View File

@ -4,7 +4,11 @@ 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';
@ -61,8 +65,7 @@ export class PslButtonData extends GraphicDataBase implements IPslButtonData {
}
export class PslButtonState
extends GraphicStateBase
implements IPslButtonState
{
implements IPslButtonState {
constructor(proto?: state.ButtonState) {
let states;
if (proto) {
@ -133,7 +136,7 @@ export class PslButtonOperateInteraction extends GraphicInteractionPlugin<PslBut
onMouseDown(e: FederatedMouseEvent) {
const simulationId = useLineStore().simulationId;
const mapId = useLineStore().mapId;
const pslId = usePslStore().pslId;
const gateBoxId = usePslStore().gatedBoxId;
const target = e.target as DisplayObject;
const pslButton = target.getGraphic() as PslButton;
if (!simulationId || !mapId) {
@ -143,7 +146,7 @@ export class PslButtonOperateInteraction extends GraphicInteractionPlugin<PslBut
simulationId,
mapId,
buttonCode: pslButton.datas.code,
pslId: pslId,
gateBoxId: gateBoxId,
down: !pslButton.states.down,
})
.then(() => {
@ -157,7 +160,7 @@ export class PslButtonOperateInteraction extends GraphicInteractionPlugin<PslBut
onMouseUp(e: FederatedMouseEvent) {
const simulationId = useLineStore().simulationId;
const mapId = useLineStore().mapId;
const pslId = usePslStore().pslId;
const gateBoxId = usePslStore().gatedBoxId;
const target = e.target as DisplayObject;
const pslButton = target.getGraphic() as PslButton;
if (!simulationId || !mapId || !pslButton.datas.isSelfReset) {
@ -167,7 +170,7 @@ export class PslButtonOperateInteraction extends GraphicInteractionPlugin<PslBut
simulationId,
mapId,
buttonCode: pslButton.datas.code,
pslId: pslId,
gateBoxId: gateBoxId,
down: false,
})
.then(() => {

View File

@ -9,17 +9,11 @@ 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) {
@ -66,8 +60,7 @@ export class ScreenDoorData extends GraphicDataBase implements IScreenDoorData {
export class ScreenDoorState
extends GraphicStateBase
implements IScreenDoorState
{
implements IScreenDoorState {
constructor(proto?: state.PsdState) {
let states;
if (proto) {
@ -80,12 +73,6 @@ 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;
}
@ -98,18 +85,6 @@ 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>();
}
@ -124,21 +99,11 @@ 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(sceenDoorOperateMenu);
// app.registerMenu();
}
static init(app: IGraphicScene) {
return new ScreenDoorOperateInteraction(app);
@ -153,40 +118,14 @@ 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);
}
}

View File

@ -17,15 +17,14 @@ import {
} from 'jl-graphic';
import { useLineStore } from 'src/stores/line-store';
import { SectionGraphicHitArea } from 'src/graphics/section/SectionDrawAssistant';
import { Dialog } from 'quasar';
import { Dialog, Notify } 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) {
@ -164,18 +163,6 @@ 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>();
}
@ -193,13 +180,11 @@ 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: [setSectionParam, setFaultOcc, addTrainConfig],
items: [addTrainConfig],
},
],
});
@ -249,33 +234,9 @@ export class SectionOperateInteraction extends GraphicInteractionPlugin<Section>
const section = target.getGraphic<Section>();
if (!section || section.datas.sectionType != SectionType.Physical) return;
this.app.updateSelected(section);
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;
const simulationId = useLineStore().simulationId || '';
const mapId = useLineStore().mapId as number;
addTrainConfig.disabled = !useLineStore().trainConfigList;
addTrainConfig.handler = () => {
const relations =
section.relationManage.getRelationsOfGraphicAndOtherType(
@ -290,7 +251,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') {
@ -302,15 +263,44 @@ export class SectionOperateInteraction extends GraphicInteractionPlugin<Section>
}
});
const d = getKmDistance(BKm, AKm);
if (lineStore.deviceOpreratDialogInstance) return;
lineStore.deviceOpreratDialogInstance = Dialog.create({
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);
}

View File

@ -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,12 +112,6 @@ 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>();
}
@ -135,9 +129,22 @@ export class SignalState extends GraphicStateBase implements ISignalState {
const mirrorFlipConfig: MenuItemOptions = {
name: '镜像翻转',
};
const setSignalParam: MenuItemOptions = {
name: '设置参数'
}
const signalRedConfig: MenuItemOptions = {
name: '开红灯',
};
const signalGreenConfig: MenuItemOptions = {
name: '开绿灯',
};
const signalYellowConfig: MenuItemOptions = {
name: '开黄灯',
};
const signalGuideConfig: MenuItemOptions = {
name: '开引导',
};
const signalCloseConfig: MenuItemOptions = {
name: '关灯',
};
const SignalEditMenu: ContextMenu = ContextMenu.init({
name: '信号机编辑菜单',
groups: [
@ -151,12 +158,11 @@ const SignalOperateMenu: ContextMenu = ContextMenu.init({
groups: [
{
items: [
setSignalParam
// signalRedConfig,
// signalGreenConfig,
// signalYellowConfig,
// signalGuideConfig,
// signalCloseConfig,
signalRedConfig,
signalGreenConfig,
signalYellowConfig,
signalGuideConfig,
signalCloseConfig,
],
},
],
@ -230,24 +236,63 @@ export class SignalOperateInteraction extends GraphicInteractionPlugin<Signal> {
const target = e.target as DisplayObject;
const signal = target.getGraphic() as Signal;
this.app.updateSelected(signal);
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,
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 });
});
}
};
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);
}
}

View File

@ -7,7 +7,11 @@ 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';
@ -39,12 +43,6 @@ 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();
@ -60,6 +58,12 @@ 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;
}

View File

@ -1,122 +0,0 @@
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);
}
}

View File

@ -1,147 +0,0 @@
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;
}
}
}
}

View File

@ -1,209 +0,0 @@
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 };
}

View File

@ -1,59 +0,0 @@
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);
}
}

View File

@ -10,12 +10,10 @@ import {
ContextMenu,
} from 'jl-graphic';
import { DisplayObject, FederatedMouseEvent } from 'pixi.js';
import { removeTrain } from 'src/api/Simulation';
import { removeTrain, updateTrain } 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;
@ -397,285 +395,6 @@ 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());
}
@ -687,14 +406,8 @@ export class TrainState extends GraphicStateBase implements ITrainState {
}
}
// const wheelDiameterChange: MenuItemOptions = {
// name: '列车轮径调整',
// };
const TrainParam: MenuItemOptions = {
name: '设置参数',
};
const TrainLink: MenuItemOptions = {
name: '列车连接',
const wheelDiameterChange: MenuItemOptions = {
name: '列车轮径调整',
};
const removeTrainConfig: MenuItemOptions = {
name: '清除列车',
@ -703,7 +416,7 @@ const TrainOperateMenu: ContextMenu = ContextMenu.init({
name: '列车操作菜单',
groups: [
{
items: [TrainParam, TrainLink, removeTrainConfig],
items: [wheelDiameterChange, removeTrainConfig],
},
],
});
@ -744,51 +457,45 @@ export class TrainOperateInteraction extends GraphicInteractionPlugin<Train> {
const lineStore = useLineStore();
const simulationId = lineStore.simulationId || '';
const mapId = lineStore.mapId as number;
TrainParam.handler = () => {
if (lineStore.deviceOpreratDialogInstance) return;
lineStore.deviceOpreratDialogInstance = Dialog.create({
title: '列车设置',
message: '',
component: SetTrainParam,
componentProps: {
train: train,
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',
},
cancel: true,
persistent: true,
});
};
TrainLink.handler = () => {
if (lineStore.deviceOpreratDialogInstance) return;
lineStore.deviceOpreratDialogInstance = Dialog.create({
title: '列车连接',
message: '',
component: SetTrainLink,
componentProps: {
trainId: train.code,
}).onOk((data) => {
const params = {
id: train.states.id,
simulationId: simulationId,
},
cancel: true,
persistent: true,
wheelDiameter: +data,
};
updateTrain(params)
.then(() => {
successNotify('列车轮径调整成功!');
})
.catch((err) => {
errorNotify('列车轮径调整失败!', err);
});
});
};
removeTrainConfig.handler = () => {
Dialog.create({
title: '确认',
message: `确认清除【${train.states.id}】列车吗?`,
cancel: true,
}).onOk(async () => {
removeTrain({
simulationId,
mapId,
trainId: train.code,
removeTrain({
simulationId,
mapId,
trainId: train.code,
})
.then(() => {
successNotify('移除列车成功!');
})
.then(() => {
successNotify('移除列车成功!');
})
.catch((err) => {
errorNotify('移除列车失败!', err);
});
});
.catch((err) => {
errorNotify('移除列车失败!', err);
});
};
TrainOperateMenu.open(e.global);

View File

@ -1,37 +1,17 @@
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, GraphicStateBase } from './GraphicDataBase';
import { GraphicDataBase } 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) {
@ -74,18 +54,12 @@ export class TransponderData
set centralizedStations(v: number[]) {
this.data.centralizedStations = v;
}
get fixedTelegram(): string {
get fixedTelegram(): Uint8Array {
return this.data.fixedTelegram;
}
set fixedTelegram(v: string) {
set fixedTelegram(v: Uint8Array) {
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;
}
@ -102,210 +76,3 @@ 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));
};
}
}

View File

@ -22,12 +22,15 @@ import {
TurnoutSectionHitArea,
} from 'src/graphics/turnout/TurnoutDrawAssistant';
import { useLineStore } from 'src/stores/line-store';
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 { 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 { request } from 'src/protos/request';
import { ApiError } from 'src/boot/axios';
import { getKmDistance } from '../lineScene';
function getDefaultEndPoint() {
return {
@ -37,15 +40,16 @@ function getDefaultEndPoint() {
};
}
const setTurnoutParam: MenuItemOptions = { name: '设置参数' };
const setNormalPosition: MenuItemOptions = { name: '定操' };
const setReversePosition: MenuItemOptions = { name: '反操' };
// const addTrainConfig: MenuItemOptions = {
// name: '添加列车',
// };
const addTrainConfig: MenuItemOptions = {
name: '添加列车',
};
const TurnoutOperationMenu: ContextMenu = ContextMenu.init({
name: 'Turnout操作',
groups: [{ items: [setTurnoutParam] }],
groups: [{ items: [setNormalPosition, setReversePosition, addTrainConfig] }],
});
export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
@ -89,75 +93,105 @@ 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);
setTurnoutParam.handler = async () => {
if (lineStore.deviceOpreratDialogInstance) return;
lineStore.deviceOpreratDialogInstance = Dialog.create({
title: '道岔设置参数',
message: '',
component: TurnoutOperation,
componentProps: {
id: turnout.id,
code: turnout.datas.code,
force: turnout.states.param.forcePosition,
},
cancel: true,
persistent: true,
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 || !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,
// });
// };
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: '创建列车',
message: '',
component: AddTrainDialog,
componentProps: { dev: turnout, 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: 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}`,
});
});
}
);
};
TurnoutOperationMenu.open(e.global);
}
}
@ -315,11 +349,35 @@ export class TurnoutStates extends GraphicStateBase implements ITurnoutState {
set fw(v: boolean) {
this.states.fw = v;
}
get param(): request.PointsParam {
return this.states.param;
get force(): boolean {
return this.states.force;
}
set param(param: request.PointsParam) {
this.states.param = 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;
}
get qdc(): boolean {
return this.states.qdc;

View File

@ -5,9 +5,7 @@ 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';
@ -149,10 +147,7 @@ export function saveIBPDrawDatas(app: IDrawApp) {
const storage = new ibpGraphicData.IBPGraphicStorage();
const canvasData = app.canvas.saveData();
storage.canvas = new graphicData.Canvas({
width: canvasData.width,
height: canvasData.height,
backgroundColor: canvasData.backgroundColor,
gridBackground: new graphicData.Grid(canvasData.gridBackground),
...canvasData,
viewportTransform: toStorageTransform(canvasData.viewportTransform),
});

View File

@ -34,10 +34,6 @@ export function initLineApp(): IGraphicApp {
destination: `/rtsts/simulation/${simulationId}/state`,
messageHandle: testManage.socketHandler,
});
lineApp.subscribe({
destination: `/rtsts/simulation/${simulationId}/tpis`,
messageHandle: testManage.socketHandlerConnectInfo,
});
return lineApp;
}
@ -51,10 +47,10 @@ export function addSceneList(sceneList: ISceneName[]) {
case SceneToPictureType.relayScene: // 继电器
s = initRelayScene;
break;
case SceneToPictureType.lineScene:
default:
s = initLineScene;
}
if (lineApp && s) {
if (lineApp) {
s(lineApp, getSceneName(scene));
} else {
console.log('没有lineApp');

View File

@ -10,6 +10,7 @@ import {
} from 'jl-graphic';
import { TrainState } from './graphics/TrainInteraction';
import { Train, TrainTemplate } from 'src/graphics/train/Train';
// import { TrainTemplate } from 'rt-graphic-component/components/packages/Train/Train';
import { TrainOperateInteraction } from './graphics/TrainInteraction';
import {
SignalData,
@ -21,33 +22,13 @@ 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,
PlatformState,
} from './graphics/PlatformInteraction';
import { PlatformTemplate, Platform } from 'src/graphics/platform/Platform';
import { StyleType } from 'rt-graphic-component/components/common/common';
import { Platform, PlatformTemplate } from 'src/graphics/platform/Platform';
import {
ScreenDoorData,
ScreenDoorState,
@ -68,7 +49,11 @@ import {
TurnoutOperationPlugin,
TurnoutStates,
} from './graphics/TurnoutInteraction';
import { Turnout, TurnoutTemplate } from 'src/graphics/turnout/Turnout';
import {
Turnout,
TurnoutTemplate,
handleData,
} from 'src/graphics/turnout/Turnout';
import {
SectionData,
SectionOperateInteraction,
@ -76,7 +61,6 @@ 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';
@ -103,7 +87,8 @@ import {
SectionLink,
SectionLinkTemplate,
} from 'src/graphics/sectionLink/SectionLink';
import { Separator, SeparatorTemplate } from 'src/graphics/separator/Separator';
import { Separator } from 'src/graphics/separator/Separator';
import { SeparatorTemplate } from 'rt-graphic-component/components/packages/Separator/Separator';
import { SeparatorData } from './graphics/SeparatorInteraction';
import {
SectionLinkData,
@ -111,7 +96,7 @@ import {
} from './graphics/SectionLinkInteraction';
import { AxleCountingSectionData } from './graphics/AxleCountingSectionInteraction';
import { LogicSectionData } from './graphics/LogicSectionInteraction';
import { Notify, QNotifyUpdateOptions, Dialog } from 'quasar';
import { Notify, QNotifyUpdateOptions } from 'quasar';
import {
StopPosition,
StopPositionTemplate,
@ -128,25 +113,14 @@ 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,
EsbButtonState,
} from './graphics/EsbButtonInteraction';
import {
Transponder,
TransponderTemplate,
} from 'src/graphics/transponder/Transponder';
import {
TransponderData,
TransponderOperationPlugin,
TransponderState,
} from './graphics/TransponderInteraction';
import { Transponder } from 'src/graphics/transponder/Transponder';
import { TransponderTemplate } from 'rt-graphic-component/components/packages/Transponder/Transponder';
import { TransponderData } from './graphics/TransponderInteraction';
import {
SlopeKiloMarker,
SlopeKiloMarkerTemplate,
@ -174,7 +148,6 @@ 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,
@ -185,47 +158,16 @@ 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,
initTranspondersOptions,
searchDeviceOptions,
searchTrainOptions,
clearAllTrainOptions,
],
items: [showOptions],
},
],
});
@ -245,8 +187,6 @@ 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 },
@ -260,10 +200,6 @@ 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;
@ -302,10 +238,15 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
const graphicTemplate = [
new TrainTemplate(new TrainState()),
new SignalTemplate(new SignalData(), new SignalState()),
new PlatformTemplate(new PlatformData(), new PlatformState()),
new PlatformTemplate(new PlatformData(), new PlatformState(), StyleType.GP),
new ScreenDoorTemplate(new ScreenDoorData(), new ScreenDoorState()),
new StationTemplate(new StationData(), new StationState()),
new TurnoutTemplate(new TurnoutData(), new TurnoutStates()),
new StationTemplate(new StationData(), new StationState(), StyleType.GP),
new TurnoutTemplate(
new TurnoutData(),
new TurnoutStates(),
StyleType.GP,
handleData
),
new SectionTemplate(new SectionData(), new SectionStates()),
new AxleCountingTemplate(new AxleCountingData()),
new TrainWindowTemplate(new TrainWindowData()),
@ -317,9 +258,7 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
new SpksSwitchTemplate(new SpksSwitchData()),
new GatedBoxTemplate(new GatedBoxData()),
new EsbButtonTemplate(new EsbButtonData(), new EsbButtonState()),
new IbpBoxTemplate(new IbpBoxData()),
new PslBoxTemplate(new PslBoxData()),
new TransponderTemplate(new TransponderData(), new TransponderState()),
new TransponderTemplate(new TransponderData()),
new SlopeKiloMarkerTemplate(new SlopeKiloMarkerData()),
// new LinkTemplate(new LinkData()),
new TrainWindowTemplate(new TrainWindowData()),
@ -332,10 +271,6 @@ 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);
@ -346,16 +281,9 @@ 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);
}
@ -366,41 +294,6 @@ 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', () => {
@ -456,11 +349,6 @@ 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) {
@ -545,10 +433,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);
}
@ -645,24 +533,6 @@ 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);

View File

@ -5,9 +5,7 @@ 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';
@ -166,9 +164,7 @@ export function savePslDrawDatas(app: IDrawApp) {
const storage = new pslGraphicData.PslGraphicStorage();
const canvasData = app.canvas.saveData();
storage.canvas = new graphicData.Canvas({
width: canvasData.width,
height: canvasData.height,
backgroundColor: canvasData.backgroundColor,
...canvasData,
viewportTransform: toStorageTransform(canvasData.viewportTransform),
});
const graphics = app.queryStore.getAllGraphics();

View File

@ -60,7 +60,7 @@ function handleSubscribe(pslScene: IGraphicScene) {
const pslStore = usePslStore();
const simulationId = lineStore.simulationId;
const mapId = lineStore.mapId;
const pslId = pslStore.pslId;
const pslId = pslStore.gatedBoxId;
const app = pslScene;
app.subscribe({
destination: `/rtsts/simulation/${simulationId}/psl/${mapId}/${pslId}`,

View File

@ -15,7 +15,6 @@ 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) {
@ -79,12 +78,6 @@ 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>();
}
@ -99,15 +92,14 @@ export class RelayState extends GraphicStateBase implements IRelayState {
}
}
const setOpen: MenuItemOptions = { name: '强制后接点位(落下)' };
const setClose: MenuItemOptions = { name: '强制前接点位(吸起)' };
const cancelForce: MenuItemOptions = { name: '取消强制' };
const setOpen: MenuItemOptions = { name: '驱动落下' };
const setClose: MenuItemOptions = { name: '驱动吸起' };
export class RelayOperationPlugin extends GraphicInteractionPlugin<Relay> {
static Name = 'relay_operate_menu';
relayOperationMenu: ContextMenu = ContextMenu.init({
name: 'Relay操作',
groups: [{ items: [setOpen, setClose, cancelForce] }],
groups: [{ items: [setOpen, setClose] }],
});
constructor(app: IGraphicScene) {
@ -143,12 +135,14 @@ export class RelayOperationPlugin extends GraphicInteractionPlugin<Relay> {
this.app.updateSelected(relay);
const simulationId = useLineStore().simulationId || '';
const mapId = useLineStore().mapId as number;
const changeRelayState = async (operation: request.Relay.Operation) => {
setOpen.disabled = !relay.states.xh;
setClose.disabled = relay.states.xh;
const changeRelayState = async (td: boolean) => {
setRelayState({
simulationId,
id: relay.datas.id,
mapId,
deviceId: relay.datas.id,
operation,
simulationId,
td,
})
.then(() => {
successNotify('修改继电器状态成功');
@ -159,13 +153,10 @@ export class RelayOperationPlugin extends GraphicInteractionPlugin<Relay> {
});
};
setOpen.handler = () => {
changeRelayState(request.Relay.Operation.ForceHw);
changeRelayState(false);
};
setClose.handler = () => {
changeRelayState(request.Relay.Operation.ForceQw);
};
cancelForce.handler = () => {
changeRelayState(request.Relay.Operation.CancelForce);
changeRelayState(true);
};
this.relayOperationMenu.open(e.global);
}

View File

@ -205,9 +205,7 @@ export function saveDrawDatas(app: IDrawApp) {
const storage = new relayCabinetGraphicData.RelayCabinetGraphicStorage();
const canvasData = app.canvas.saveData();
storage.canvas = new graphicData.Canvas({
width: canvasData.width,
height: canvasData.height,
backgroundColor: canvasData.backgroundColor,
...canvasData,
viewportTransform: toStorageTransform(canvasData.viewportTransform),
});
const graphics = app.queryStore.getAllGraphics();

View File

@ -1,12 +1,10 @@
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';
@ -26,27 +24,7 @@ import {
} from 'src/graphics/phaseFailureProtector/PhaseFailureProtector';
import { PhaseFailureProtectorData } from './relayCabinetGraphics/PhaseFailureProtectorInteraction';
import { state } from 'src/protos/device_state';
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 }
>();
import { Notify, QNotifyUpdateOptions } from 'quasar';
export function initRelayScene(lineApp: IGraphicApp, sceneName: string) {
// 继电器
@ -68,33 +46,28 @@ 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) => {
refRelaysListMap.set(relayId, {
combinationtype: combinationtype.code,
device: device.code,
});
map.set(relayId, device.code);
});
});
});
const relays = relayScene.queryStore.queryByType<Relay>(Relay.Type);
relays.forEach((relay) => {
relay.refDevice.text = refRelaysListMap
.get(relay.id)
?.device.replace(/_/g, '\n') as string;
relay.refDevice.text = map.get(relay.id)?.replace(/_/g, '\n') as string;
});
const phaseFailureProtectors =
relayScene.queryStore.queryByType<PhaseFailureProtector>(
PhaseFailureProtector.Type
);
phaseFailureProtectors.forEach((phaseFailureProtector) => {
phaseFailureProtector.refDevice.text = refRelaysListMap.get(
phaseFailureProtector.id
)?.device as string;
phaseFailureProtector.refDevice.text = map
.get(phaseFailureProtector.id)
?.replace(/_/g, '\n') as string;
});
});
lineApp.on('destroy', () => {
@ -102,24 +75,6 @@ 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;
@ -137,7 +92,6 @@ function handleSubscribe(relayScene: IGraphicScene) {
states.push(new RelayState(relayState));
}
});
testManageStore.setStationQc(storage.allStatus.stationQc);
} else {
storage.varStatus.updatedReply.forEach((relayState) => {
if (relayState.id) {
@ -169,6 +123,7 @@ function handleSubscribe(relayScene: IGraphicScene) {
});
}
let refRelaysList: relayCabinetGraphicData.DeviceRelateRelay[] = [];
async function loadRelayDatas(): Promise<IGraphicStorage> {
const lineStore = useLineStore();
const mapId = lineStore.mapId;
@ -193,8 +148,6 @@ 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,
@ -205,11 +158,3 @@ async function loadRelayDatas(): Promise<IGraphicStorage> {
});
}
}
//关联继电器列表
let refRelaysList: relayCabinetGraphicData.DeviceRelateRelay[] = [];
//采集列表和驱动列表
export const sceneCiCjQdListMap = new Map<
string,
relayCabinetGraphicData.CiCj | relayCabinetGraphicData.CiQd
>();

View File

@ -1,226 +0,0 @@
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: [],
});
}
}

View File

@ -1,125 +0,0 @@
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: [],
});
}
}

View File

@ -45,9 +45,6 @@ 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>();
}

View File

@ -58,10 +58,6 @@ export class Arrow extends JlGraphic implements ILineGraphic {
this.arrowGraphic.endFill();
}
get code(): string {
return this.datas.code;
}
get datas(): IArrowData {
return this.getDatas<IArrowData>();
}

View File

@ -45,9 +45,6 @@ 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>();
}

View File

@ -1,135 +1,9 @@
import { Color, Container, Graphics } from 'pixi.js';
import {
GraphicData,
GraphicRelationParam,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'jl-graphic';
import { IRelatedRefData, protoPort2Data } from '../CommonGraphics';
import { KilometerSystem } from '../signal/Signal';
AxleCounting,
IAxleCountingData,
AxleCountingTemplate,
AxleCountingConsts,
} from 'rt-graphic-component/components/packages/AxleCounting/AxleCounting';
enum TypeDetectionPoint {
AxleCounting = 0,
SectionBoundary = 1,
}
export interface IAxleCountingData extends GraphicData {
get code(): string; // 编号
set code(v: string);
get kilometerSystem(): KilometerSystem;
set kilometerSystem(v: KilometerSystem);
get axleCountingRef(): IRelatedRefData[]; //关联的设备
set axleCountingRef(ref: IRelatedRefData[]);
get type(): TypeDetectionPoint; // 计轴、区段边界
set type(v: TypeDetectionPoint);
get centralizedStations(): number[];
set centralizedStations(v: number[]);
clone(): IAxleCountingData;
copyFrom(data: IAxleCountingData): void;
eq(other: IAxleCountingData): boolean;
}
export const AxleCountingConsts = {
radius: 6,
borderWidth: 1,
circleColorBlue: '0x08F80D',
circleColorRed: '0xff0000',
codeFontSize: 22,
codeOffsetY: 30,
kilometerCodeColor: '0xFFFFFF',
kilometerCodeFontSize: 14,
kilometerCodeOffsetY: 95,
offsetSection: 50,
};
class TwoCircleGraphic extends Container {
circleA: Graphics = new Graphics();
circleB: Graphics = new Graphics();
line: Graphics = new Graphics();
constructor() {
super();
this.addChild(this.circleA);
this.addChild(this.circleB);
this.addChild(this.line);
}
draw(data: IAxleCountingData): void {
this.drawCircle(this.circleA, data);
this.drawCircle(this.circleB, data);
this.circleA.position.set(-12, 0);
this.circleB.position.set(12, 0);
this.line.clear();
let color = AxleCountingConsts.circleColorBlue;
if (data.type == 1) {
color = AxleCountingConsts.circleColorRed;
}
this.line.lineStyle(1, new Color(color));
this.line.moveTo(-24, 0);
this.line.lineTo(24, 0);
}
drawCircle(circle: Graphics, data: IAxleCountingData): void {
circle.clear();
let color = AxleCountingConsts.circleColorBlue;
if (data.type == 1) {
color = AxleCountingConsts.circleColorRed;
}
circle.lineStyle(AxleCountingConsts.borderWidth, new Color(color));
circle.beginFill(color, 1);
circle.drawCircle(0, 0, AxleCountingConsts.radius);
circle.endFill;
}
clear(): void {
this.circleA.clear();
this.circleB.clear();
}
}
export class AxleCounting extends JlGraphic {
static Type = 'AxleCounting';
twoCircle: TwoCircleGraphic = new TwoCircleGraphic();
kilometerGraph: VectorText = new VectorText(''); //公里标
direction: number;
constructor(direction: number) {
super(AxleCounting.Type);
this.addChild(this.twoCircle);
this.addChild(this.kilometerGraph);
this.kilometerGraph.name = 'kilometer';
this.direction = direction;
}
get code(): string {
return this.datas.code;
}
get datas(): IAxleCountingData {
return this.getDatas<IAxleCountingData>();
}
doRepaint(): void {
this.twoCircle.draw(this.datas);
}
buildRelation(): void {
this.loadRelations();
}
loadRelations(): void {
if (this.datas.axleCountingRef.length) {
this.datas.axleCountingRef.forEach((device) => {
this.relationManage.addRelation(
new GraphicRelationParam(this, 'A'),
new GraphicRelationParam(
this.queryStore.queryById(device.id),
protoPort2Data(device.devicePort)
)
);
});
}
}
}
export class AxleCountingTemplate extends JlGraphicTemplate<AxleCounting> {
constructor(dataTemplate: IAxleCountingData) {
super(AxleCounting.Type, {
dataTemplate,
});
}
new(): AxleCounting {
const axleCounting = new AxleCounting(1);
axleCounting.loadData(this.datas);
return axleCounting;
}
}
export { AxleCounting, AxleCountingTemplate, AxleCountingConsts };
export type { IAxleCountingData };

View File

@ -175,7 +175,8 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
});
axleCountingRefs.forEach((axleCountingRef) => {
map.set(
`${axleCountingRef.id}-${graphicData.RelatedRef.DevicePort[axleCountingRef.devicePort]
`${axleCountingRef.id}-${
graphicData.RelatedRef.DevicePort[axleCountingRef.devicePort]
}`,
1
);
@ -379,21 +380,12 @@ export class AxleCountingInteraction extends GraphicInteractionPlugin<AxleCounti
g.cursor = 'pointer';
g.scalable = true;
g.rotatable = true;
g.kilometerGraph.eventMode = 'static';
g.kilometerGraph.cursor = 'pointer';
g.kilometerGraph.draggable = true;
g.kilometerGraph.selectable = true;
g.kilometerGraph.transformSave = true;
g.on('selected', this.onSelected, this);
}
unbind(g: AxleCounting): void {
g.eventMode = 'none';
g.scalable = false;
g.rotatable = false;
g.kilometerGraph.eventMode = 'none';
g.kilometerGraph.draggable = false;
g.kilometerGraph.selectable = false;
g.kilometerGraph.transformSave = false;
g.off('selected', this.onSelected, this);
}
onSelected(): void {

View File

@ -55,9 +55,7 @@ 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>();
}

View File

@ -1,89 +0,0 @@
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;
}
}

View File

@ -1,128 +0,0 @@
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),
});
}
}

Some files were not shown because too many files have changed in this diff Show More