防淹门、车库门、洗车机调整

This commit is contained in:
joylink_fanyuhong 2024-03-13 15:31:26 +08:00
parent 4314e0db79
commit dd5f77d6f1
19 changed files with 1345 additions and 5 deletions

View File

@ -75,4 +75,10 @@
<path d="M20 27H39" stroke="#FFFFFF"/>
<path d="M29 27V43" stroke="#FFFFFF"/>
</symbol>
<symbol id="icon-flood-gate" viewBox="0 0 129 139">
<path fill-rule="evenodd" stroke="rgba(255, 255, 255, 1)" stroke-width="3" d="M0 1.5L61.5 1.5M61.5 1.5L123 1.5M61.5 1.5L61.5 137.5L0 137.5L123 137.5">
</symbol>
<symbol id="icon-car-washing" viewBox="0 0 57 57" fill="none">
<rect x="1.5" y="8.5" width="47" height="47" stroke="#FFFFFF" fill="none" stroke-width="3"/>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -139,6 +139,15 @@
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>
</q-card-section>
</template>
<template v-else-if="drawStore.selectedGraphics.length > 1">
@ -217,6 +226,12 @@ import { TrackLogicSection } from 'src/graphics/trackLogicSection/TrackLogicSect
import MultipleSelectProperty from './properties/multipleSelectProperty.vue';
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';
const drawStore = useDrawStore();
</script>

View File

@ -0,0 +1,100 @@
<template>
<q-form>
<q-input
outlined
readonly
v-model="carWashingModel.id"
label="id"
hint=""
/>
<q-input
outlined
class="q-mt-sm"
v-model="carWashingModel.code"
@blur="onUpdate"
label="名称"
/>
<q-select
outlined
style="margin-top: 10px"
v-model="carWashingModel.linkSection"
:options="sectionList"
:map-options="true"
:emit-value="true"
@update:model-value="onUpdate"
label="关联区段"
></q-select>
<q-field class="q-mt-lg" outlined label="所属集中站" stack-label>
<template #control>
<q-chip
color="primary"
text-color="white"
v-for="(id, index) in carWashingModel.centralizedStations"
:key="index"
removable
@remove="removeStation(index)"
square
>{{ getName(id) }}</q-chip
>
<q-btn round color="primary" size="xs" icon="add" @click="addStation" />
</template>
</q-field>
</q-form>
</template>
<script setup lang="ts">
import { useFormData } from 'src/components/DrawAppFormUtils';
import { useDrawStore } from 'src/stores/draw-store';
import { onMounted, reactive } from 'vue';
import { Section } from 'src/graphics/section/Section';
import { CarWashingData } from 'src/drawApp/graphics/CarWashingInteraction';
import { Station } from 'src/graphics/station/Station';
import AddCentralizedStationDialog from '../dialogs/AddCentralizedStationDialog.vue';
import { useQuasar } from 'quasar';
const drawStore = useDrawStore();
const sectionList: { label: string; value: number }[] = reactive([]);
const { data: carWashingModel, onUpdate } = useFormData(
new CarWashingData(),
drawStore.getDrawApp()
);
onMounted(() => {
const sections = drawStore
.getDrawApp()
.queryStore.queryByType<Section>(Section.Type);
sections.forEach((p) => {
sectionList.push({
value: p.id,
label: `${p.datas.code}`,
});
});
});
function removeStation(index: number) {
carWashingModel.centralizedStations.splice(index, 1);
onUpdate();
}
const $q = useQuasar();
function addStation() {
$q.dialog({
title: '',
message: '',
component: AddCentralizedStationDialog,
cancel: true,
persistent: true,
}).onOk((data: number) => {
carWashingModel.centralizedStations.push(data);
onUpdate();
});
}
function getName(id: number) {
try {
const station = drawStore.getDrawApp().queryStore.queryById<Station>(id);
return station.datas.code;
} catch (error) {
return id;
}
}
</script>

View File

@ -0,0 +1,95 @@
<template>
<q-form>
<q-input outlined readonly v-model="floodGateModel.id" label="id" hint="" />
<q-input
outlined
class="q-mt-sm"
v-model="floodGateModel.code"
@blur="onUpdate"
label="名称"
/>
<q-select
outlined
style="margin-top: 10px"
v-model="floodGateModel.linkSection"
:options="sectionList"
:map-options="true"
:emit-value="true"
@update:model-value="onUpdate"
label="关联区段"
></q-select>
<q-field class="q-mt-lg" outlined label="所属集中站" stack-label>
<template #control>
<q-chip
color="primary"
text-color="white"
v-for="(id, index) in floodGateModel.centralizedStations"
:key="index"
removable
@remove="removeStation(index)"
square
>{{ getName(id) }}</q-chip
>
<q-btn round color="primary" size="xs" icon="add" @click="addStation" />
</template>
</q-field>
</q-form>
</template>
<script setup lang="ts">
import { useFormData } from 'src/components/DrawAppFormUtils';
import { useDrawStore } from 'src/stores/draw-store';
import { onMounted, reactive } from 'vue';
import { Section } from 'src/graphics/section/Section';
import { FloodGateData } from 'src/drawApp/graphics/FloodGateInteraction';
import AddCentralizedStationDialog from '../dialogs/AddCentralizedStationDialog.vue';
import { useQuasar } from 'quasar';
import { Station } from 'src/graphics/station/Station';
const drawStore = useDrawStore();
const sectionList: { label: string; value: number }[] = reactive([]);
const { data: floodGateModel, onUpdate } = useFormData(
new FloodGateData(),
drawStore.getDrawApp()
);
onMounted(() => {
const sections = drawStore
.getDrawApp()
.queryStore.queryByType<Section>(Section.Type);
sections.forEach((p) => {
sectionList.push({
value: p.id,
label: `${p.datas.code}`,
});
});
});
function removeStation(index: number) {
floodGateModel.centralizedStations.splice(index, 1);
onUpdate();
}
const $q = useQuasar();
function addStation() {
$q.dialog({
title: '',
message: '',
component: AddCentralizedStationDialog,
cancel: true,
persistent: true,
}).onOk((data: number) => {
floodGateModel.centralizedStations.push(data);
onUpdate();
});
}
function getName(id: number) {
try {
const station = drawStore.getDrawApp().queryStore.queryById<Station>(id);
return station.datas.code;
} catch (error) {
return id;
}
}
</script>

View File

@ -0,0 +1,101 @@
<template>
<q-form>
<q-input
outlined
readonly
v-model="garageDoorModel.id"
label="id"
hint=""
/>
<q-input
outlined
class="q-mt-sm"
v-model="garageDoorModel.code"
@blur="onUpdate"
label="名称"
/>
<q-select
outlined
style="margin-top: 10px"
v-model="garageDoorModel.linkSection"
:options="sectionList"
:map-options="true"
:emit-value="true"
@update:model-value="onUpdate"
label="关联区段"
></q-select>
<q-field class="q-mt-lg" outlined label="所属集中站" stack-label>
<template #control>
<q-chip
color="primary"
text-color="white"
v-for="(id, index) in garageDoorModel.centralizedStations"
:key="index"
removable
@remove="removeStation(index)"
square
>{{ getName(id) }}</q-chip
>
<q-btn round color="primary" size="xs" icon="add" @click="addStation" />
</template>
</q-field>
</q-form>
</template>
<script setup lang="ts">
import { useFormData } from 'src/components/DrawAppFormUtils';
import { useDrawStore } from 'src/stores/draw-store';
import { onMounted, reactive } from 'vue';
import { GarageDoorData } from 'src/drawApp/graphics/GarageDoorInteraction';
import { Section } from 'src/graphics/section/Section';
import AddCentralizedStationDialog from '../dialogs/AddCentralizedStationDialog.vue';
import { useQuasar } from 'quasar';
import { Station } from 'src/graphics/station/Station';
const drawStore = useDrawStore();
const sectionList: { label: string; value: number }[] = reactive([]);
const { data: garageDoorModel, onUpdate } = useFormData(
new GarageDoorData(),
drawStore.getDrawApp()
);
onMounted(() => {
const sections = drawStore
.getDrawApp()
.queryStore.queryByType<Section>(Section.Type);
sections.forEach((p) => {
sectionList.push({
value: p.id,
label: `${p.datas.code}`,
});
});
});
const $q = useQuasar();
function removeStation(index: number) {
garageDoorModel.centralizedStations.splice(index, 1);
onUpdate();
}
function addStation() {
$q.dialog({
title: '',
message: '',
component: AddCentralizedStationDialog,
cancel: true,
persistent: true,
}).onOk((data: number) => {
garageDoorModel.centralizedStations.push(data);
onUpdate();
});
}
function getName(id: number) {
try {
const station = drawStore.getDrawApp().queryStore.queryById<Station>(id);
return station.datas.code;
} catch (error) {
return id;
}
}
</script>

View File

@ -21,6 +21,9 @@ 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';
export const drawCommonLayerList = [
// 图层列表 默认显示的图层defaultShow: true
@ -55,4 +58,7 @@ 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 },
];

View File

@ -142,6 +142,21 @@ import { Dialog } from 'quasar';
import { useDrawStore } from 'src/stores/draw-store';
import { saveDraft } from 'src/api/DraftApi';
import { SignalDraw } from 'src/graphics/signal/SignalDrawAssistant';
import { CarWashingData } from './graphics/CarWashingInteraction';
import {
CarWashing,
CarWashingTemplate,
} from 'src/graphics/carWashing/CarWashing';
import { CarWashingDraw } from 'src/graphics/carWashing/CarWashingDrawAssistant';
import { FloodGateData } from './graphics/FloodGateInteraction';
import { FloodGate, FloodGateTemplate } from 'src/graphics/floodGate/FloodGate';
import { FloodGateDraw } from 'src/graphics/floodGate/FloodGateDrawAssistant';
import { GarageDoorData } from './graphics/GarageDoorInteraction';
import {
GarageDoor,
GarageDoorTemplate,
} from 'src/graphics/garageDoor/GarageDoor';
import { GarageDoorDraw } from 'src/graphics/garageDoor/GarageDoorDrawAssistant';
const UndoOptions: MenuItemOptions = {
name: '撤销',
@ -228,6 +243,9 @@ 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);
@ -437,6 +455,15 @@ export function loadCommonDrawDatas(
storage.concentrationDividingLines.forEach((concentrationDividingLine) => {
datas.push(new ConcentrationDividingLineData(concentrationDividingLine));
});
storage.floodGates.forEach((flood) => {
datas.push(new FloodGateData(flood));
});
storage.carWashings.forEach((carWashing) => {
datas.push(new CarWashingData(carWashing));
});
storage.garageDoors.forEach((garageDoor) => {
datas.push(new GarageDoorData(garageDoor));
});
return datas;
}
@ -523,6 +550,15 @@ export function saveCommonDrawDatas(app: IDrawApp) {
storage.concentrationDividingLines.push(
(concentrationDividingLineData as ConcentrationDividingLineData).data
);
} else if (g instanceof CarWashing) {
const carWashingData = g.saveData();
storage.carWashings.push((carWashingData as CarWashingData).data);
} else if (g instanceof FloodGate) {
const floodGateData = g.saveData();
storage.floodGates.push((floodGateData as FloodGateData).data);
} else if (g instanceof GarageDoor) {
const garageDoorData = g.saveData();
storage.garageDoors.push((garageDoorData as GarageDoorData).data);
}
});
// storage.Platforms.forEach((item) => {

View File

@ -0,0 +1,88 @@
import * as pb_1 from 'google-protobuf';
import { FederatedMouseEvent } from 'pixi.js';
import {
CarWashing,
ICarWashingData,
} from 'src/graphics/carWashing/CarWashing';
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { GraphicDataBase } from './GraphicDataBase';
export class CarWashingData extends GraphicDataBase implements ICarWashingData {
constructor(data?: graphicData.CarWashing) {
let carWashing;
if (!data) {
carWashing = new graphicData.CarWashing({
common: GraphicDataBase.defaultCommonInfo(CarWashing.Type),
});
} else {
carWashing = data;
}
super(carWashing);
}
public get data(): graphicData.CarWashing {
return this.getData<graphicData.CarWashing>();
}
get code(): string {
return this.data.code;
}
set code(v: string) {
this.data.code = v;
}
get linkSection(): number {
return this.data.linkSection;
}
set linkSection(v: number) {
this.data.linkSection = v;
}
get centralizedStations(): number[] {
return this.data.centralizedStations;
}
set centralizedStations(v: number[]) {
this.data.centralizedStations = v;
}
clone(): CarWashingData {
return new CarWashingData(this.data.cloneMessage());
}
copyFrom(data: CarWashingData): void {
pb_1.Message.copyInto(data.data, this.data);
}
eq(other: CarWashingData): boolean {
return pb_1.Message.equals(this.data, other.data);
}
}
export class CarWashingOperationInteraction extends GraphicInteractionPlugin<CarWashing> {
static Name = 'car_washing_operation';
constructor(scene: IGraphicScene) {
super(CarWashingOperationInteraction.Name, scene);
}
static init(scene: IGraphicScene) {
return new CarWashingOperationInteraction(scene);
}
filter(...grahpics: JlGraphic[]): CarWashing[] | undefined {
return grahpics.filter((g): g is CarWashing => g.type === CarWashing.Type);
}
bind(g: CarWashing): void {
g.eventMode = 'static';
g.cursor = 'pointer';
g.on('mousedown', this.onPress, this);
}
unbind(g: CarWashing): void {
g.eventMode = 'none';
g.cursor = 'default';
g.off('mousedown', this.onPress, this);
}
onPress(e: FederatedMouseEvent) {
const g = e.target as CarWashing;
g.on('mouseleave', this.onRelease, this);
g.on('mouseup', this.onRelease, this);
}
onRelease(e: FederatedMouseEvent) {
const g = e.target as CarWashing;
g.off('mouseleave', this.onRelease, this);
g.off('mouseup', this.onRelease, this);
}
}

View File

@ -0,0 +1,85 @@
import * as pb_1 from 'google-protobuf';
import { FederatedMouseEvent } from 'pixi.js';
import { FloodGate, IFloodGateData } from 'src/graphics/floodGate/FloodGate';
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { GraphicDataBase } from './GraphicDataBase';
export class FloodGateData extends GraphicDataBase implements IFloodGateData {
constructor(data?: graphicData.FloodGate) {
let floodGate;
if (!data) {
floodGate = new graphicData.FloodGate({
common: GraphicDataBase.defaultCommonInfo(FloodGate.Type),
});
} else {
floodGate = data;
}
super(floodGate);
}
public get data(): graphicData.FloodGate {
return this.getData<graphicData.FloodGate>();
}
get code(): string {
return this.data.code;
}
set code(v: string) {
this.data.code = v;
}
get linkSection(): number {
return this.data.linkSection;
}
set linkSection(v: number) {
this.data.linkSection = v;
}
get centralizedStations(): number[] {
return this.data.centralizedStations;
}
set centralizedStations(v: number[]) {
this.data.centralizedStations = v;
}
clone(): FloodGateData {
return new FloodGateData(this.data.cloneMessage());
}
copyFrom(data: FloodGateData): void {
pb_1.Message.copyInto(data.data, this.data);
}
eq(other: FloodGateData): boolean {
return pb_1.Message.equals(this.data, other.data);
}
}
export class FloodGateOperationInteraction extends GraphicInteractionPlugin<FloodGate> {
static Name = 'flood_gate_operation';
constructor(scene: IGraphicScene) {
super(FloodGateOperationInteraction.Name, scene);
}
static init(scene: IGraphicScene) {
return new FloodGateOperationInteraction(scene);
}
filter(...grahpics: JlGraphic[]): FloodGate[] | undefined {
return grahpics.filter((g): g is FloodGate => g.type === FloodGate.Type);
}
bind(g: FloodGate): void {
g.eventMode = 'static';
g.cursor = 'pointer';
g.on('mousedown', this.onPress, this);
}
unbind(g: FloodGate): void {
g.eventMode = 'none';
g.cursor = 'default';
g.off('mousedown', this.onPress, this);
}
onPress(e: FederatedMouseEvent) {
const g = e.target as FloodGate;
g.on('mouseleave', this.onRelease, this);
g.on('mouseup', this.onRelease, this);
}
onRelease(e: FederatedMouseEvent) {
const g = e.target as FloodGate;
g.off('mouseleave', this.onRelease, this);
g.off('mouseup', this.onRelease, this);
}
}

View File

@ -0,0 +1,88 @@
import * as pb_1 from 'google-protobuf';
import { FederatedMouseEvent } from 'pixi.js';
import {
GarageDoor,
IGarageDoorData,
} from 'src/graphics/garageDoor/GarageDoor';
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { GraphicDataBase } from './GraphicDataBase';
export class GarageDoorData extends GraphicDataBase implements IGarageDoorData {
constructor(data?: graphicData.GarageDoor) {
let garageDoor;
if (!data) {
garageDoor = new graphicData.GarageDoor({
common: GraphicDataBase.defaultCommonInfo(GarageDoor.Type),
});
} else {
garageDoor = data;
}
super(garageDoor);
}
public get data(): graphicData.GarageDoor {
return this.getData<graphicData.GarageDoor>();
}
get code(): string {
return this.data.code;
}
set code(v: string) {
this.data.code = v;
}
get linkSection(): number {
return this.data.linkSection;
}
set linkSection(v: number) {
this.data.linkSection = v;
}
get centralizedStations(): number[] {
return this.data.centralizedStations;
}
set centralizedStations(v: number[]) {
this.data.centralizedStations = v;
}
clone(): GarageDoorData {
return new GarageDoorData(this.data.cloneMessage());
}
copyFrom(data: GarageDoorData): void {
pb_1.Message.copyInto(data.data, this.data);
}
eq(other: GarageDoorData): boolean {
return pb_1.Message.equals(this.data, other.data);
}
}
export class GarageDoorOperationInteraction extends GraphicInteractionPlugin<GarageDoor> {
static Name = 'garage_door_operation';
constructor(scene: IGraphicScene) {
super(GarageDoorOperationInteraction.Name, scene);
}
static init(scene: IGraphicScene) {
return new GarageDoorOperationInteraction(scene);
}
filter(...grahpics: JlGraphic[]): GarageDoor[] | undefined {
return grahpics.filter((g): g is GarageDoor => g.type === GarageDoor.Type);
}
bind(g: GarageDoor): void {
g.eventMode = 'static';
g.cursor = 'pointer';
g.on('mousedown', this.onPress, this);
}
unbind(g: GarageDoor): void {
g.eventMode = 'none';
g.cursor = 'default';
g.off('mousedown', this.onPress, this);
}
onPress(e: FederatedMouseEvent) {
const g = e.target as GarageDoor;
g.on('mouseleave', this.onRelease, this);
g.on('mouseup', this.onRelease, this);
}
onRelease(e: FederatedMouseEvent) {
const g = e.target as GarageDoor;
g.off('mouseleave', this.onRelease, this);
g.off('mouseup', this.onRelease, this);
}
}

View File

@ -21,6 +21,27 @@ import {
Signal,
KilometerSystem,
} from 'src/graphics/signal/Signal';
import {
FloodGateData,
FloodGateOperationInteraction,
} from './graphics/FloodGateInteraction';
import { FloodGate, FloodGateTemplate } from 'src/graphics/floodGate/FloodGate';
import {
CarWashingData,
CarWashingOperationInteraction,
} from './graphics/CarWashingInteraction';
import {
CarWashing,
CarWashingTemplate,
} from 'src/graphics/carWashing/CarWashing';
import {
GarageDoorData,
GarageDoorOperationInteraction,
} from './graphics/GarageDoorInteraction';
import {
GarageDoor,
GarageDoorTemplate,
} from 'src/graphics/garageDoor/GarageDoor';
import {
PlatformData,
PlatformOperateInteraction,
@ -161,10 +182,16 @@ import {
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';
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: '显示控制',
@ -227,6 +254,9 @@ 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 },
];
let lineScene: IGraphicScene;
@ -295,6 +325,9 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
new AutoReturnBoxData(),
new AutoReturnBoxState()
),
new CarWashingTemplate(new CarWashingData()),
new GarageDoorTemplate(new GarageDoorData()),
new FloodGateTemplate(new FloodGateData()),
];
lineScene.registerGraphicTemplates(...graphicTemplate);
SignalOperateInteraction.init(lineScene);
@ -311,6 +344,9 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
AutoReturnBoxOperationInteraction.init(lineScene);
PslBoxOperateInteraction.init(lineScene);
IbpBoxOperateInteraction.init(lineScene);
CarWashingOperationInteraction.init(lineScene);
GarageDoorOperationInteraction.init(lineScene);
FloodGateOperationInteraction.init(lineScene);
if (categoryType === CategoryType.TH) {
GatedBoxOperateInteraction.init(lineScene);
}
@ -606,6 +642,15 @@ export async function loadLineDatas(): Promise<IGraphicStorage> {
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));
});
// const linkIdGenerator = new IdGenerator(Link.Type);
// storage.CalculateLink.forEach((link) => {
// const g = new LinkData(link);

View File

@ -0,0 +1,89 @@
import { Graphics } from 'pixi.js';
import {
GraphicData,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'jl-graphic';
export interface ICarWashingData extends GraphicData {
get code(): string;
set code(v: string);
get linkSection(): number;
set linkSection(v: number);
get centralizedStations(): number[];
set centralizedStations(v: number[]);
clone(): ICarWashingData;
copyFrom(data: ICarWashingData): void;
eq(other: ICarWashingData): boolean;
}
const carWashingConsts = {
codeFontSize: 12,
codeColor: 0xffffff,
bodyRectLineColor: 0xffffff,
bodyRectLineWidth: 2,
bodyRectWidth: 10,
bodyRectHeight: 20,
bodyColor: 0x000000,
};
export class CarWashing extends JlGraphic {
static Type = 'carWashing';
codeGraph: VectorText = new VectorText('');
rectBody: Graphics = new Graphics();
constructor() {
super(CarWashing.Type);
this.addChild(this.codeGraph);
this.addChild(this.rectBody);
this.codeGraph.name = 'carw_code';
}
get code(): string {
return this.datas.code;
}
get datas(): ICarWashingData {
return this.getDatas<ICarWashingData>();
}
doRepaint(): void {
const codeGraph = this.codeGraph;
codeGraph.text = this.datas.code;
codeGraph.style.fill = carWashingConsts.codeColor;
codeGraph.setVectorFontSize(carWashingConsts.codeFontSize);
codeGraph.anchor.set(0.5);
const codeTransform = this.datas?.childTransforms?.find(
(item) => item.name === 'carw_code'
);
if (codeTransform) {
const position = codeTransform?.transform.position;
const rotation = codeTransform?.transform?.rotation;
codeGraph.position.set(position?.x, position?.y);
codeGraph.rotation = rotation || 0;
} else {
codeGraph.position.set(0, -30);
}
this.rectBody.clear();
this.rectBody.beginFill(carWashingConsts.bodyColor, 0);
this.rectBody.lineStyle(
carWashingConsts.bodyRectLineWidth,
carWashingConsts.bodyRectLineColor
);
this.rectBody.drawRect(
-carWashingConsts.bodyRectWidth / 2,
-carWashingConsts.bodyRectHeight / 2,
carWashingConsts.bodyRectWidth,
carWashingConsts.bodyRectHeight
);
this.rectBody.endFill();
}
}
export class CarWashingTemplate extends JlGraphicTemplate<CarWashing> {
constructor(dataTemplate: ICarWashingData) {
super(CarWashing.Type, { dataTemplate });
}
new(): CarWashing {
const carWashing = new CarWashing();
carWashing.loadData(this.datas);
return carWashing;
}
}

View File

@ -0,0 +1,128 @@
import { DisplayObject, FederatedMouseEvent, Point } from 'pixi.js';
import {
AbsorbableLine,
AbsorbablePosition,
GraphicDrawAssistant,
GraphicInteractionPlugin,
GraphicTransformEvent,
IDrawApp,
JlGraphic,
} from 'jl-graphic';
import { CarWashing, CarWashingTemplate, ICarWashingData } from './CarWashing';
export interface ICarWashingDataDrawOptions {
newData: () => ICarWashingData;
}
export class CarWashingDraw extends GraphicDrawAssistant<
CarWashingTemplate,
ICarWashingData
> {
_carWashing: CarWashing | null = null;
constructor(app: IDrawApp, template: CarWashingTemplate) {
super(
app,
template,
'svguse:../../drawIcon.svg#icon-car-washing',
'洗车机CarWashing'
);
CarWashingInteraction.init(app);
}
public get carWashing(): CarWashing {
if (!this._carWashing) {
this._carWashing = this.graphicTemplate.new();
this._carWashing.loadData(this.graphicTemplate.datas);
this.container.addChild(this._carWashing);
}
return this._carWashing;
}
onLeftUp(e: FederatedMouseEvent): void {
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
this.createAndStore(true);
}
redraw(p: Point): void {
this.carWashing.repaint();
this.container.position.set(p.x, p.y);
}
prepareData(data: ICarWashingData): boolean {
data.transform = this.container.saveTransform();
data.code = 'CarWash';
return true;
}
}
/**
* 线
* @param carWashing
*/
function buildAbsorbablePositions(
carWashing: CarWashing
): AbsorbablePosition[] {
const aps: AbsorbablePosition[] = [];
const carWashings = carWashing.queryStore.queryByType<CarWashing>(
CarWashing.Type
);
const canvas = carWashing.getCanvas();
carWashings.forEach((item) => {
if (item.id === carWashing.id) {
return;
}
const ala = new AbsorbableLine(
new Point(item.x, 0),
new Point(item.x, canvas.height)
);
const alb = new AbsorbableLine(
new Point(0, item.y),
new Point(canvas.width, item.y)
);
aps.push(ala);
aps.push(alb);
});
return aps;
}
export class CarWashingInteraction extends GraphicInteractionPlugin<CarWashing> {
static Name = 'car_washing_transform';
constructor(app: IDrawApp) {
super(CarWashingInteraction.Name, app);
}
static init(app: IDrawApp) {
return new CarWashingInteraction(app);
}
filter(...grahpics: JlGraphic[]): CarWashing[] | undefined {
return grahpics
.filter((g) => g.type === CarWashing.Type)
.map((g) => g as CarWashing);
}
bind(g: CarWashing): void {
g.eventMode = 'static';
g.cursor = 'pointer';
g.scalable = true;
g.rotatable = true;
g.codeGraph.draggable = true;
g.codeGraph.selectable = true;
g.codeGraph.rotatable = true;
g.codeGraph.transformSave = true;
g.codeGraph.eventMode = 'static';
g.on('transformstart', this.transformstart, this);
}
unbind(g: CarWashing): void {
g.eventMode = 'none';
g.scalable = false;
g.rotatable = false;
g.codeGraph.draggable = false;
g.codeGraph.selectable = false;
g.codeGraph.rotatable = false;
g.codeGraph.transformSave = false;
g.codeGraph.eventMode = 'none';
g.off('transformstart', this.transformstart, this);
}
transformstart(e: GraphicTransformEvent) {
const target = e.target as DisplayObject;
const carWashing = target.getGraphic() as CarWashing;
carWashing.getGraphicApp().setOptions({
absorbablePositions: buildAbsorbablePositions(carWashing),
});
}
}

View File

@ -0,0 +1,99 @@
import { Graphics } from 'pixi.js';
import {
GraphicData,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'jl-graphic';
export interface IFloodGateData extends GraphicData {
get code(): string;
set code(v: string);
get linkSection(): number;
set linkSection(v: number);
get centralizedStations(): number[];
set centralizedStations(v: number[]);
clone(): IFloodGateData;
copyFrom(data: IFloodGateData): void;
eq(other: IFloodGateData): boolean;
}
const floodGateConsts = {
codeFontSize: 12,
codeColor: 0xffffff,
bodyLineColor: 0xffffff,
bodyLineWidth: 2,
bodyColor: 0x000000,
bodyRectWidth: 10,
bodyRectHeight: 20,
};
export class FloodGate extends JlGraphic {
static Type = 'floodGate';
codeGraph: VectorText = new VectorText('');
lineBody: Graphics = new Graphics();
constructor() {
super(FloodGate.Type);
this.addChild(this.codeGraph);
this.addChild(this.lineBody);
this.codeGraph.name = 'flood_code';
}
get code(): string {
return this.datas.code;
}
get datas(): IFloodGateData {
return this.getDatas<IFloodGateData>();
}
doRepaint(): void {
const codeGraph = this.codeGraph;
codeGraph.text = this.datas.code;
codeGraph.style.fill = floodGateConsts.codeColor;
codeGraph.setVectorFontSize(floodGateConsts.codeFontSize);
codeGraph.anchor.set(0.5);
const codeTransform = this.datas?.childTransforms?.find(
(item) => item.name === 'flood_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.lineBody.clear();
this.lineBody.lineStyle(
floodGateConsts.bodyLineWidth,
floodGateConsts.bodyLineColor
);
this.lineBody.moveTo(
-floodGateConsts.bodyRectWidth / 2,
-floodGateConsts.bodyRectHeight / 2
);
this.lineBody.lineTo(
floodGateConsts.bodyRectWidth / 2,
-floodGateConsts.bodyRectHeight / 2
);
this.lineBody.moveTo(
-floodGateConsts.bodyRectWidth / 2,
floodGateConsts.bodyRectHeight / 2
);
this.lineBody.lineTo(
floodGateConsts.bodyRectWidth / 2,
floodGateConsts.bodyRectHeight / 2
);
this.lineBody.moveTo(0, -floodGateConsts.bodyRectHeight / 2);
this.lineBody.lineTo(0, floodGateConsts.bodyRectHeight / 2);
}
}
export class FloodGateTemplate extends JlGraphicTemplate<FloodGate> {
constructor(dataTemplate: IFloodGateData) {
super(FloodGate.Type, { dataTemplate });
}
new(): FloodGate {
const floodGate = new FloodGate();
floodGate.loadData(this.datas);
return floodGate;
}
}

View File

@ -0,0 +1,126 @@
import { DisplayObject, FederatedMouseEvent, Point } from 'pixi.js';
import {
AbsorbableLine,
AbsorbablePosition,
GraphicDrawAssistant,
GraphicInteractionPlugin,
GraphicTransformEvent,
IDrawApp,
JlGraphic,
} from 'jl-graphic';
import { FloodGate, FloodGateTemplate, IFloodGateData } from './FloodGate';
export interface IFloodGateDataDrawOptions {
newData: () => IFloodGateData;
}
export class FloodGateDraw extends GraphicDrawAssistant<
FloodGateTemplate,
IFloodGateData
> {
_floodGate: FloodGate | null = null;
constructor(app: IDrawApp, template: FloodGateTemplate) {
super(
app,
template,
'svguse:../../drawIcon.svg#icon-flood-gate',
'车库门FloodGate'
);
FloodGateInteraction.init(app);
}
public get floodGate(): FloodGate {
if (!this._floodGate) {
this._floodGate = this.graphicTemplate.new();
this._floodGate.loadData(this.graphicTemplate.datas);
this.container.addChild(this._floodGate);
}
return this._floodGate;
}
onLeftUp(e: FederatedMouseEvent): void {
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
this.createAndStore(true);
}
redraw(p: Point): void {
this.floodGate.repaint();
this.container.position.set(p.x, p.y);
}
prepareData(data: IFloodGateData): boolean {
data.transform = this.container.saveTransform();
data.code = 'FloodGate';
return true;
}
}
/**
* 线
* @param floodGate
*/
function buildAbsorbablePositions(floodGate: FloodGate): AbsorbablePosition[] {
const aps: AbsorbablePosition[] = [];
const floodGates = floodGate.queryStore.queryByType<FloodGate>(
FloodGate.Type
);
const canvas = floodGate.getCanvas();
floodGates.forEach((item) => {
if (item.id === floodGate.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 FloodGateInteraction extends GraphicInteractionPlugin<FloodGate> {
static Name = 'flood_gate_transform';
constructor(app: IDrawApp) {
super(FloodGateInteraction.Name, app);
}
static init(app: IDrawApp) {
return new FloodGateInteraction(app);
}
filter(...grahpics: JlGraphic[]): FloodGate[] | undefined {
return grahpics
.filter((g) => g.type === FloodGate.Type)
.map((g) => g as FloodGate);
}
bind(g: FloodGate): 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: FloodGate): 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 floodGate = target.getGraphic() as FloodGate;
floodGate.getGraphicApp().setOptions({
absorbablePositions: buildAbsorbablePositions(floodGate),
});
}
}

View File

@ -0,0 +1,99 @@
import { Graphics } from 'pixi.js';
import {
GraphicData,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'jl-graphic';
export interface IGarageDoorData extends GraphicData {
get code(): string;
set code(v: string);
get linkSection(): number;
set linkSection(v: number);
get centralizedStations(): number[];
set centralizedStations(v: number[]);
clone(): IGarageDoorData;
copyFrom(data: IGarageDoorData): void;
eq(other: IGarageDoorData): boolean;
}
const garageConsts = {
codeFontSize: 12,
codeColor: 0xffffff,
bodyLineColor: 0xffffff,
bodyLineWidth: 2,
bodyColor: 0x000000,
bodyRectWidth: 10,
bodyRectHeight: 20,
};
export class GarageDoor extends JlGraphic {
static Type = 'garageDoor';
codeGraph: VectorText = new VectorText('');
lineBody: Graphics = new Graphics();
constructor() {
super(GarageDoor.Type);
this.addChild(this.codeGraph);
this.addChild(this.lineBody);
this.codeGraph.name = 'garage_code';
}
get code(): string {
return this.datas.code;
}
get datas(): IGarageDoorData {
return this.getDatas<IGarageDoorData>();
}
doRepaint(): void {
const codeGraph = this.codeGraph;
codeGraph.text = this.datas.code;
codeGraph.style.fill = garageConsts.codeColor;
codeGraph.setVectorFontSize(garageConsts.codeFontSize);
codeGraph.anchor.set(0.5);
const codeTransform = this.datas?.childTransforms?.find(
(item) => item.name === 'garage_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.lineBody.clear();
this.lineBody.lineStyle(
garageConsts.bodyLineWidth,
garageConsts.bodyLineColor
);
this.lineBody.moveTo(
-garageConsts.bodyRectWidth / 2,
-garageConsts.bodyRectHeight / 2
);
this.lineBody.lineTo(
garageConsts.bodyRectWidth / 2,
-garageConsts.bodyRectHeight / 2
);
this.lineBody.moveTo(
-garageConsts.bodyRectWidth / 2,
garageConsts.bodyRectHeight / 2
);
this.lineBody.lineTo(
garageConsts.bodyRectWidth / 2,
garageConsts.bodyRectHeight / 2
);
this.lineBody.moveTo(0, -garageConsts.bodyRectHeight / 2);
this.lineBody.lineTo(0, garageConsts.bodyRectHeight / 2);
}
}
export class GarageDoorTemplate extends JlGraphicTemplate<GarageDoor> {
constructor(dataTemplate: IGarageDoorData) {
super(GarageDoor.Type, { dataTemplate });
}
new(): GarageDoor {
const garageDoor = new GarageDoor();
garageDoor.loadData(this.datas);
return garageDoor;
}
}

View File

@ -0,0 +1,128 @@
import { DisplayObject, FederatedMouseEvent, Point } from 'pixi.js';
import {
AbsorbableLine,
AbsorbablePosition,
GraphicDrawAssistant,
GraphicInteractionPlugin,
GraphicTransformEvent,
IDrawApp,
JlGraphic,
} from 'jl-graphic';
import { GarageDoor, GarageDoorTemplate, IGarageDoorData } from './GarageDoor';
export interface IGarageDoorDataDrawOptions {
newData: () => IGarageDoorData;
}
export class GarageDoorDraw extends GraphicDrawAssistant<
GarageDoorTemplate,
IGarageDoorData
> {
_garageDoor: GarageDoor | null = null;
constructor(app: IDrawApp, template: GarageDoorTemplate) {
super(
app,
template,
'svguse:../../drawIcon.svg#icon-flood-gate',
'防淹门GarageDoor'
);
GarageDoorInteraction.init(app);
}
public get garageDoor(): GarageDoor {
if (!this._garageDoor) {
this._garageDoor = this.graphicTemplate.new();
this._garageDoor.loadData(this.graphicTemplate.datas);
this.container.addChild(this._garageDoor);
}
return this._garageDoor;
}
onLeftUp(e: FederatedMouseEvent): void {
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
this.createAndStore(true);
}
redraw(p: Point): void {
this.garageDoor.repaint();
this.container.position.set(p.x, p.y);
}
prepareData(data: IGarageDoorData): boolean {
data.transform = this.container.saveTransform();
data.code = 'GarageDoor';
return true;
}
}
/**
* 线
* @param garageDoor
*/
function buildAbsorbablePositions(
garageDoor: GarageDoor
): AbsorbablePosition[] {
const aps: AbsorbablePosition[] = [];
const garageDoors = garageDoor.queryStore.queryByType<GarageDoor>(
GarageDoor.Type
);
const canvas = garageDoor.getCanvas();
garageDoors.forEach((item) => {
if (item.id === garageDoor.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 GarageDoorInteraction extends GraphicInteractionPlugin<GarageDoor> {
static Name = 'garage_door_transform';
constructor(app: IDrawApp) {
super(GarageDoorInteraction.Name, app);
}
static init(app: IDrawApp) {
return new GarageDoorInteraction(app);
}
filter(...grahpics: JlGraphic[]): GarageDoor[] | undefined {
return grahpics
.filter((g) => g.type === GarageDoor.Type)
.map((g) => g as GarageDoor);
}
bind(g: GarageDoor): 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: GarageDoor): 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 garageDoor = target.getGraphic() as GarageDoor;
garageDoor.getGraphicApp().setOptions({
absorbablePositions: buildAbsorbablePositions(garageDoor),
});
}
}

View File

@ -274,6 +274,9 @@ import SignalDirectionConfig from 'src/components/draw-app/properties/SignalDire
import { distance2, JlGraphic } from 'jl-graphic';
import { IbpBox } from 'src/graphics/ibpBox/IbpBox';
import { PslBox } from 'src/graphics/pslBox/PslBox';
import { CarWashing } from 'src/graphics/carWashing/CarWashing';
import { FloodGate } from 'src/graphics/floodGate/FloodGate';
import { GarageDoor } from 'src/graphics/garageDoor/GarageDoor';
const $q = useQuasar();
const route = useRoute();
@ -439,6 +442,9 @@ onMounted(() => {
ConcentrationDividingLine.Type,
IbpBox.Type,
PslBox.Type,
CarWashing.Type,
FloodGate.Type,
GarageDoor.Type,
];
switch (drawStore.categoryType) {
case CategoryType.TH: