添加发车计时器&简化浙大网新ESB

This commit is contained in:
fan 2023-11-16 15:52:31 +08:00
parent 741d7c0a12
commit c04d76c00f
12 changed files with 461 additions and 27 deletions

@ -1 +1 @@
Subproject commit 443710abd51f19620bfbc233c678d721c5b3c1d1
Subproject commit 9b1d2ca01f293f17aebd4936cb9077e480b26fc3

View File

@ -61,4 +61,11 @@
<path d="M20 27H39" stroke="#FFFFFF"/>
<path d="M29 27V43" stroke="#FFFFFF"/>
</symbol>
<symbol id="icon-departure-timer" viewBox="0 0 23 40" fill="none">
<rect x="0.5" y="0.5" width="22" height="39" stroke="white"/>
<rect x="4.5" y="8.5" width="14" height="8" stroke="white"/>
<rect x="4.5" y="24.5" width="14" height="8" stroke="white"/>
<path d="M11.5 9V16.5" stroke="white"/>
<path d="M11.5 25V32.5" stroke="white"/>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -121,6 +121,9 @@
<beacon-property
v-else-if="drawStore.selectedGraphicType === Beacon.Type"
></beacon-property>
<departure-timer-property
v-else-if="drawStore.selectedGraphicType === DepartureTimer.Type"
></departure-timer-property>
</q-card-section>
</template>
<template v-else-if="drawStore.selectedGraphics.length > 1">
@ -191,6 +194,8 @@ 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';
const drawStore = useDrawStore();
const ibpNameList: string[] = [];

View File

@ -0,0 +1,29 @@
<template>
<q-form>
<q-input
outlined
readonly
v-model="departureTimerModel.id"
label="id"
hint=""
/>
<q-input
outlined
class="q-mt-sm"
v-model="departureTimerModel.code"
@blur="onUpdate"
label="编号"
/>
</q-form>
</template>
<script setup lang="ts">
import { useFormData } from 'src/components/DrawAppFormUtils';
import { useDrawStore } from 'src/stores/draw-store';
import { DepartureTimerData } from 'src/drawApp/graphics/DepartureTimerInteraction';
const { data: departureTimerModel, onUpdate } = useFormData(
new DepartureTimerData(),
useDrawStore().getDrawApp()
);
</script>

View File

@ -0,0 +1,44 @@
import * as pb_1 from 'google-protobuf';
import {
DepartureTimer,
IDepartureTimer,
} from 'src/graphics/departureTimer/DepartureTimer';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { GraphicDataBase } from './GraphicDataBase';
export class DepartureTimerData
extends GraphicDataBase
implements IDepartureTimer
{
constructor(data?: graphicData.DepartureTimer) {
let departureTimer;
if (!data) {
departureTimer = new graphicData.DepartureTimer({
common: GraphicDataBase.defaultCommonInfo(DepartureTimer.Type),
});
} else {
departureTimer = data;
}
super(departureTimer);
}
public get data(): graphicData.DepartureTimer {
return this.getData<graphicData.DepartureTimer>();
}
get code(): string {
return this.data.code;
}
set code(v: string) {
this.data.code = v;
}
clone(): DepartureTimerData {
return new DepartureTimerData(this.data.cloneMessage());
}
copyFrom(data: DepartureTimerData): void {
pb_1.Message.copyInto(data.data, this.data);
}
eq(other: DepartureTimerData): boolean {
return pb_1.Message.equals(this.data, other.data);
}
}

View File

@ -47,6 +47,12 @@ import {
ZdwxEsbData,
ZdwxEsbState,
} from './graphics/ZdwxEsbInteraction';
import {
DepartureTimer,
DepartureTimerTemplate,
} from 'src/graphics/departureTimer/DepartureTimer';
import { DepartureTimerData } from './graphics/DepartureTimerInteraction';
import { DepartureTimerDraw } from 'src/graphics/departureTimer/DepartureTimerDrawAssistant';
let zdwxDrawApp: IDrawApp | null = null;
@ -67,6 +73,7 @@ export const drawZdwxLayerList = [
{ label: '轨道区段', value: TrackSection.Type, defaultShow: false },
{ label: '轨道逻辑区段', value: TrackLogicSection.Type, defaultShow: false },
{ label: '信标', value: Beacon.Type, defaultShow: true },
{ label: '发车计时器', value: DepartureTimer.Type, defaultShow: true },
];
function initZdwxShowLayer(app: IDrawApp) {
@ -109,6 +116,10 @@ export function initZdwxDrawApp(): IDrawApp {
new TrackLogicSectionTemplate(new TrackLogicSectionData())
);
new BeaconDraw(app, new BeaconTemplate(new BeaconData()));
new DepartureTimerDraw(
app,
new DepartureTimerTemplate(new DepartureTimerData())
);
new ZdwxEsbDraw(
app,
new ZdwxEsbTemplate(new ZdwxEsbData(), new ZdwxEsbState())
@ -155,6 +166,9 @@ export async function loadZdwxDrawDatas(): Promise<IGraphicStorage> {
storage.esbButtons.forEach((esbButton) => {
datas.push(new ZdwxEsbData(esbButton));
});
storage.departureTimers.forEach((departureTimer) => {
datas.push(new DepartureTimerData(departureTimer));
});
refDevicesList = storage.stationRelateDeviceList;
return Promise.resolve({
canvasProperty: storage.canvas,
@ -186,6 +200,11 @@ export function saveZdwxDrawDatas(app: IDrawApp) {
} else if (ZdwxEsb.Type === g.type) {
const zdwxEsbData = (g as ZdwxEsb).saveData();
storage.esbButtons.push((zdwxEsbData as ZdwxEsbData).data);
} else if (DepartureTimer.Type === g.type) {
const departureTimerData = (g as DepartureTimer).saveData();
storage.departureTimers.push(
(departureTimerData as DepartureTimerData).data
);
}
});
const base64 = fromUint8Array(storage.serialize());

View File

@ -0,0 +1,88 @@
import { Color, Graphics } from 'pixi.js';
import {
GraphicData,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'src/jl-graphic';
export interface IDepartureTimer extends GraphicData {
get code(): string;
set code(v: string);
clone(): IDepartureTimer;
copyFrom(data: IDepartureTimer): void;
eq(other: IDepartureTimer): boolean;
}
const departureTimerConsts = {
color: 0xff00ff,
lineWidth: 1,
rectWidth: 12,
rectHeight: 20,
codeFontSize: 12,
codeColor: 0xffffff,
};
export class DepartureTimer extends JlGraphic {
static Type = 'departureTimer';
body: Graphics = new Graphics();
codeGraph: VectorText = new VectorText('');
constructor() {
super(DepartureTimer.Type);
this.addChild(this.body);
this.addChild(this.codeGraph);
this.codeGraph.name = 'departure_timer_code';
}
get datas(): IDepartureTimer {
return this.getDatas<IDepartureTimer>();
}
get code(): string {
return this.datas.code;
}
doRepaint(): void {
const codeGraph = this.codeGraph;
codeGraph.text = this.datas.code;
codeGraph.style.fill = departureTimerConsts.codeColor;
codeGraph.setVectorFontSize(departureTimerConsts.codeFontSize);
codeGraph.anchor.set(0.5);
const codeTransform = this.datas?.childTransforms?.find(
(item) => item.name === 'departure_timer_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(-15, 10);
}
this.body.clear();
this.body.lineStyle(
departureTimerConsts.lineWidth,
departureTimerConsts.color
);
this.body.drawRect(
0,
0,
departureTimerConsts.rectWidth,
departureTimerConsts.rectHeight
);
this.body.drawRect(2, 4, 8, 4);
this.body.drawRect(2, 12, 8, 4);
this.body.moveTo(6, 4);
this.body.lineTo(6, 8);
this.body.moveTo(6, 12);
this.body.lineTo(6, 16);
}
}
export class DepartureTimerTemplate extends JlGraphicTemplate<DepartureTimer> {
constructor(dataTemplate: IDepartureTimer) {
super(DepartureTimer.Type, { dataTemplate });
}
new(): DepartureTimer {
const departureTimer = new DepartureTimer();
departureTimer.loadData(this.datas);
return departureTimer;
}
}

View File

@ -0,0 +1,142 @@
import { DisplayObject, FederatedMouseEvent, IHitArea, Point } from 'pixi.js';
import {
AbsorbableLine,
AbsorbablePosition,
GraphicDrawAssistant,
GraphicInteractionPlugin,
GraphicTransformEvent,
IDrawApp,
JlGraphic,
} from 'src/jl-graphic';
import {
DepartureTimer,
DepartureTimerTemplate,
IDepartureTimer,
} from './DepartureTimer';
export interface IDepartureTimerDrawOptions {
newData: () => IDepartureTimer;
}
export class DepartureTimerDraw extends GraphicDrawAssistant<
DepartureTimerTemplate,
IDepartureTimer
> {
_departureTimer: DepartureTimer | null = null;
constructor(app: IDrawApp, template: DepartureTimerTemplate) {
super(
app,
template,
'svguse:../../drawIcon.svg#icon-departure-timer',
'发车计时器DepartureTimer'
);
DepartureTimerInteraction.init(app);
}
public get departureTimer(): DepartureTimer {
if (!this._departureTimer) {
this._departureTimer = this.graphicTemplate.new();
this._departureTimer.loadData(this.graphicTemplate.datas);
this.container.addChild(this._departureTimer);
}
return this._departureTimer;
}
onLeftUp(e: FederatedMouseEvent): void {
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
this.createAndStore(true);
}
redraw(p: Point): void {
this.departureTimer.repaint();
this.container.position.set(p.x, p.y);
}
prepareData(data: IDepartureTimer): boolean {
data.transform = this.container.saveTransform();
data.code = 'DTI';
return true;
}
}
/**
* 线
* @param departureTimer
*/
function buildAbsorbablePositions(
departureTimer: DepartureTimer
): AbsorbablePosition[] {
const aps: AbsorbablePosition[] = [];
const departureTimers = departureTimer.queryStore.queryByType<DepartureTimer>(
DepartureTimer.Type
);
const canvas = departureTimer.getCanvas();
departureTimers.forEach((item) => {
if (item.id === departureTimer.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 DepartureTimerGraphicHitArea implements IHitArea {
departureTimer: DepartureTimer;
constructor(departureTimer: DepartureTimer) {
this.departureTimer = departureTimer;
}
contains(x: number, y: number): boolean {
return x >= 0 && x <= 26 && y >= 0 && y <= 40;
}
}
export class DepartureTimerInteraction extends GraphicInteractionPlugin<DepartureTimer> {
static Name = 'departure_timer_transform';
constructor(app: IDrawApp) {
super(DepartureTimerInteraction.Name, app);
}
static init(app: IDrawApp) {
return new DepartureTimerInteraction(app);
}
filter(...grahpics: JlGraphic[]): DepartureTimer[] | undefined {
return grahpics
.filter((g) => g.type === DepartureTimer.Type)
.map((g) => g as DepartureTimer);
}
bind(g: DepartureTimer): 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.body.hitArea = new DepartureTimerGraphicHitArea(g);
g.on('transformstart', this.transformstart, this);
}
unbind(g: DepartureTimer): 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 departureTimer = target.getGraphic() as DepartureTimer;
departureTimer.getGraphicApp().setOptions({
absorbablePositions: buildAbsorbablePositions(departureTimer),
});
}
}

View File

@ -38,8 +38,7 @@ export const zdwxEsbConsts = {
bodyRectHeight: 20,
bodyCircleRadius: 4,
bodyColor: 0xff0000,
rectOffset1: -9,
rectOffset2: -12,
rectOffset: -10,
};
export class ZdwxEsb extends JlGraphic {
static Type = 'esbButton';
@ -81,24 +80,14 @@ export class ZdwxEsb extends JlGraphic {
this.circleBody.arc(0, 0, zdwxEsbConsts.bodyCircleRadius, 0, Math.PI);
this.circleBody.moveTo(0, 0);
this.circleBody.lineTo(0, -6);
this.circleBody.moveTo(-4, 0);
this.circleBody.lineTo(4, 0);
} else {
this.circleBody.arc(0, 0, zdwxEsbConsts.bodyCircleRadius, Math.PI, 0);
this.circleBody.moveTo(0, 0);
this.circleBody.lineTo(0, 6);
this.circleBody.moveTo(-4, 0);
this.circleBody.lineTo(4, 0);
}
this.circleBody.drawRect(
zdwxEsbConsts.rectOffset1,
zdwxEsbConsts.rectOffset1,
zdwxEsbConsts.bodyRectWidth,
zdwxEsbConsts.bodyRectHeight
);
this.circleBody.drawRect(
zdwxEsbConsts.rectOffset2,
zdwxEsbConsts.rectOffset2,
zdwxEsbConsts.rectOffset,
zdwxEsbConsts.rectOffset,
zdwxEsbConsts.bodyRectWidth,
zdwxEsbConsts.bodyRectHeight
);

View File

@ -91,17 +91,10 @@ export class EsbBodyHitArea implements IHitArea {
contains(x: number, y: number): boolean {
let flag = false;
if (
x >= zdwxEsbConsts.rectOffset1 &&
x <= zdwxEsbConsts.rectOffset1 + zdwxEsbConsts.bodyRectWidth &&
y >= zdwxEsbConsts.rectOffset1 &&
y <= zdwxEsbConsts.rectOffset1 + zdwxEsbConsts.bodyRectHeight
) {
flag = true;
} else if (
x >= zdwxEsbConsts.rectOffset2 &&
x <= zdwxEsbConsts.rectOffset2 + zdwxEsbConsts.bodyRectWidth &&
y >= zdwxEsbConsts.rectOffset2 &&
y <= zdwxEsbConsts.rectOffset2 + zdwxEsbConsts.bodyRectHeight
x >= zdwxEsbConsts.rectOffset &&
x <= zdwxEsbConsts.rectOffset + zdwxEsbConsts.bodyRectWidth &&
y >= zdwxEsbConsts.rectOffset &&
y <= zdwxEsbConsts.rectOffset + zdwxEsbConsts.bodyRectHeight
) {
flag = true;
}

View File

@ -306,6 +306,7 @@ import ScreenDoorConfig from 'src/components/draw-app/properties/ScreenDoorConfi
import AxleCountingConfig from 'src/components/draw-app/properties/AxleCountingConfig.vue';
import { PictureType } from 'src/protos/picture';
import { Beacon } from 'src/graphics/beacon/Beacon';
import { DepartureTimer } from 'src/graphics/departureTimer/DepartureTimer';
const $q = useQuasar();
const route = useRoute();
@ -461,6 +462,7 @@ onMounted(() => {
break;
case CategoryType.ZDWX:
drawAssistantsTypes.push(Beacon.Type);
drawAssistantsTypes.push(DepartureTimer.Type);
break;
}
drawAssistantsTypes.forEach((type) => {

View File

@ -44,9 +44,10 @@ export namespace graphicData {
screenDoorConfig?: ScreenDoorConfig;
beacons?: Beacon[];
generateAxleCountingConfig?: GenerateAxleCountingConfig;
departureTimers?: DepartureTimer[];
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 37], this.#one_of_decls);
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 37, 39], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") {
if ("canvas" in data && data.canvas != undefined) {
this.canvas = data.canvas;
@ -144,6 +145,9 @@ export namespace graphicData {
if ("generateAxleCountingConfig" in data && data.generateAxleCountingConfig != undefined) {
this.generateAxleCountingConfig = data.generateAxleCountingConfig;
}
if ("departureTimers" in data && data.departureTimers != undefined) {
this.departureTimers = data.departureTimers;
}
}
}
get canvas() {
@ -350,6 +354,12 @@ export namespace graphicData {
get has_generateAxleCountingConfig() {
return pb_1.Message.getField(this, 38) != null;
}
get departureTimers() {
return pb_1.Message.getRepeatedWrapperField(this, DepartureTimer, 39) as DepartureTimer[];
}
set departureTimers(value: DepartureTimer[]) {
pb_1.Message.setRepeatedWrapperField(this, 39, value);
}
static fromObject(data: {
canvas?: ReturnType<typeof Canvas.prototype.toObject>;
Platforms?: ReturnType<typeof Platform.prototype.toObject>[];
@ -383,6 +393,7 @@ export namespace graphicData {
screenDoorConfig?: ReturnType<typeof ScreenDoorConfig.prototype.toObject>;
beacons?: ReturnType<typeof Beacon.prototype.toObject>[];
generateAxleCountingConfig?: ReturnType<typeof GenerateAxleCountingConfig.prototype.toObject>;
departureTimers?: ReturnType<typeof DepartureTimer.prototype.toObject>[];
}): RtssGraphicStorage {
const message = new RtssGraphicStorage({});
if (data.canvas != null) {
@ -481,6 +492,9 @@ export namespace graphicData {
if (data.generateAxleCountingConfig != null) {
message.generateAxleCountingConfig = GenerateAxleCountingConfig.fromObject(data.generateAxleCountingConfig);
}
if (data.departureTimers != null) {
message.departureTimers = data.departureTimers.map(item => DepartureTimer.fromObject(item));
}
return message;
}
toObject() {
@ -517,6 +531,7 @@ export namespace graphicData {
screenDoorConfig?: ReturnType<typeof ScreenDoorConfig.prototype.toObject>;
beacons?: ReturnType<typeof Beacon.prototype.toObject>[];
generateAxleCountingConfig?: ReturnType<typeof GenerateAxleCountingConfig.prototype.toObject>;
departureTimers?: ReturnType<typeof DepartureTimer.prototype.toObject>[];
} = {};
if (this.canvas != null) {
data.canvas = this.canvas.toObject();
@ -614,6 +629,9 @@ export namespace graphicData {
if (this.generateAxleCountingConfig != null) {
data.generateAxleCountingConfig = this.generateAxleCountingConfig.toObject();
}
if (this.departureTimers != null) {
data.departureTimers = this.departureTimers.map((item: DepartureTimer) => item.toObject());
}
return data;
}
serialize(): Uint8Array;
@ -684,6 +702,8 @@ export namespace graphicData {
writer.writeRepeatedMessage(37, this.beacons, (item: Beacon) => item.serialize(writer));
if (this.has_generateAxleCountingConfig)
writer.writeMessage(38, this.generateAxleCountingConfig, () => this.generateAxleCountingConfig.serialize(writer));
if (this.departureTimers.length)
writer.writeRepeatedMessage(39, this.departureTimers, (item: DepartureTimer) => item.serialize(writer));
if (!w)
return writer.getResultBuffer();
}
@ -789,6 +809,9 @@ export namespace graphicData {
case 38:
reader.readMessage(message.generateAxleCountingConfig, () => message.generateAxleCountingConfig = GenerateAxleCountingConfig.deserialize(reader));
break;
case 39:
reader.readMessage(message.departureTimers, () => pb_1.Message.addToRepeatedWrapperField(message, 39, DepartureTimer.deserialize(reader), DepartureTimer));
break;
default: reader.skipField();
}
}
@ -7077,6 +7100,99 @@ export namespace graphicData {
}
}
}
export class DepartureTimer extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {
common?: CommonInfo;
code?: string;
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") {
if ("common" in data && data.common != undefined) {
this.common = data.common;
}
if ("code" in data && data.code != undefined) {
this.code = data.code;
}
}
}
get common() {
return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo;
}
set common(value: CommonInfo) {
pb_1.Message.setWrapperField(this, 1, value);
}
get has_common() {
return pb_1.Message.getField(this, 1) != null;
}
get code() {
return pb_1.Message.getFieldWithDefault(this, 2, "") as string;
}
set code(value: string) {
pb_1.Message.setField(this, 2, value);
}
static fromObject(data: {
common?: ReturnType<typeof CommonInfo.prototype.toObject>;
code?: string;
}): DepartureTimer {
const message = new DepartureTimer({});
if (data.common != null) {
message.common = CommonInfo.fromObject(data.common);
}
if (data.code != null) {
message.code = data.code;
}
return message;
}
toObject() {
const data: {
common?: ReturnType<typeof CommonInfo.prototype.toObject>;
code?: string;
} = {};
if (this.common != null) {
data.common = this.common.toObject();
}
if (this.code != null) {
data.code = this.code;
}
return data;
}
serialize(): Uint8Array;
serialize(w: pb_1.BinaryWriter): void;
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
const writer = w || new pb_1.BinaryWriter();
if (this.has_common)
writer.writeMessage(1, this.common, () => this.common.serialize(writer));
if (this.code.length)
writer.writeString(2, this.code);
if (!w)
return writer.getResultBuffer();
}
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): DepartureTimer {
const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new DepartureTimer();
while (reader.nextField()) {
if (reader.isEndGroup())
break;
switch (reader.getFieldNumber()) {
case 1:
reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader));
break;
case 2:
message.code = reader.readString();
break;
default: reader.skipField();
}
}
return message;
}
serializeBinary(): Uint8Array {
return this.serialize();
}
static deserializeBinary(bytes: Uint8Array): DepartureTimer {
return DepartureTimer.deserialize(bytes);
}
}
export class UniqueIdOfStationLayout extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {