洗车机操作状态调整

This commit is contained in:
joylink_fanyuhong 2024-04-02 15:59:19 +08:00
parent 107f3e50d9
commit 2fcab2d9e9
11 changed files with 501 additions and 11 deletions

@ -1 +1 @@
Subproject commit e64115ada314a096debd061cf54ee774f1091aa7 Subproject commit 8117a06f1ebccc1e239e56cfc0a3137f499c8515

View File

@ -491,3 +491,15 @@ export async function ckmUpdateParams(data: {
}) { }) {
return await api.put(`${UriBase}/ckm/operation`, data); return await api.put(`${UriBase}/ckm/operation`, data);
} }
export async function xcjUpdateParams(data: {
simulationId: string;
mapId: number;
deviceId: number;
operation: request.Xcj.Operation;
param: {
fault: request.Xcj.Fault;
};
}) {
return await api.put(`${UriBase}/xcj/operation`, data);
}

View File

@ -0,0 +1,115 @@
<!-- eslint-disable vue/no-mutating-props -->
<template>
<draggable-dialog
v-model="showXcjOperation"
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 xcjFaultOption"
:key="option.value"
v-model="xcjFault"
:val="option.value"
:label="option.label"
/>
</div>
<q-card-actions align="right" class="text-primary">
<q-btn
flat
label="取消"
@click="showXcjOperation = 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 { xcjUpdateParams } 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,
},
xcjFaultProp: {
type: Number,
required: true,
},
});
const lineStore = useLineStore();
const showXcjOperation = ref(true);
const xcjFault = ref<request.Xcj.Fault>(0);
const xcjFaultOption = [
{
label: '无故障',
value: request.Xcj.Fault.FA_NONE,
},
{
label: '故障',
value: request.Xcj.Fault.FA_Fault,
},
];
onMounted(() => {
xcjFault.value = props.xcjFaultProp;
});
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.Xcj.Operation.SetParams,
param: {
fault: xcjFault.value,
},
};
xcjUpdateParams(obj).catch((e) => errorNotify('操作失败:' + e.title, e));
showXcjOperation.value = false;
}
});
}
onUnmounted(() => {
lineStore.deviceOpreratDialogInstance = null;
});
</script>
<style scoped></style>

View File

@ -34,6 +34,9 @@
<flood-gate-state <flood-gate-state
v-else-if="lineStore.selectedGraphicType === FloodGate.Type" v-else-if="lineStore.selectedGraphicType === FloodGate.Type"
></flood-gate-state> ></flood-gate-state>
<car-washing-state
v-else-if="lineStore.selectedGraphicType === CarWashing.Type"
></car-washing-state>
</div> </div>
</q-scroll-area> </q-scroll-area>
</template> </template>
@ -66,6 +69,8 @@ import { GarageDoor } from 'src/graphics/garageDoor/GarageDoor';
import GarageDoorState from './states/GarageDoorState.vue'; import GarageDoorState from './states/GarageDoorState.vue';
import { FloodGate } from 'src/graphics/floodGate/FloodGate'; import { FloodGate } from 'src/graphics/floodGate/FloodGate';
import FloodGateState from './states/FloodGateState.vue'; import FloodGateState from './states/FloodGateState.vue';
import CarWashingState from './states/CarWashingState.vue';
import { CarWashing } from 'src/graphics/carWashing/CarWashing';
const lineStore = useLineStore(); const lineStore = useLineStore();
</script> </script>

View File

@ -0,0 +1,182 @@
<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 operationOptions"
:key="index"
clickable
v-close-popup
@click="doCarWashingOperation(item)"
>
<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>{{
item.formatFn
? item.formatFn(carWashingState[item.key])
: carWashingState[item.key]
}}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card-section>
</q-card>
</template>
<script setup lang="ts">
import { useLineStore } from 'src/stores/line-store';
import { ref, watch, onMounted, onUnmounted, toRaw } from 'vue';
import { request } from 'src/protos/request';
import { CarWashing } from 'src/graphics/carWashing/CarWashing';
import XcjOperation from 'src/components/draw-app/dialogs/XcjOperation.vue';
import { CarWashingState } from 'src/drawApp/graphics/CarWashingInteraction';
import { Dialog } from 'quasar';
const lineStore = useLineStore();
const carWashingState = ref<CarWashingState>(new CarWashingState());
const code = ref('');
const operationOptions = [
{
label: '设置参数',
value: request.Xcj.Operation.SetParams,
},
];
const carWashingFault = ref<request.Xcj.Fault>(0);
let copySelectGraphic: CarWashing | null = null;
interface KeyType {
label: string;
key: keyof CarWashingState;
formatFn?(v: CarWashingState[keyof CarWashingState]): string;
}
const list: KeyType[] = [
{ label: '洗车机索引', key: 'id' },
{ label: '洗车机名称', key: 'code', formatFn: getNameFormat },
{ label: '洗车请求', key: 'xqj', formatFn: getBoolFormat },
{ label: '是否停稳', key: 'twjList', formatFn: getTwFormat },
{ label: '通过请求', key: 'tgqj', formatFn: getBoolFormat },
{ label: '洗车就绪', key: 'xcjxj', formatFn: getBoolFormat },
{ label: '洗车允许', key: 'xcyxj', formatFn: getBoolFormat },
{ label: '移动允许', key: 'cfjList', formatFn: getYXFormat },
{ label: '紧急停车', key: 'jtj', formatFn: getBoolFormat },
{ label: '通过允许', key: 'tgyxj', formatFn: getBoolFormat },
];
watch(
() => lineStore.selectedGraphics,
(val, oldVal) => {
if (oldVal?.length == 1 && oldVal[0] instanceof CarWashing) {
unSubscribeState(oldVal[0]);
}
if (val?.length == 1 && val[0] instanceof CarWashing) {
copySelectGraphic = toRaw(val[0]);
initCarWashingState(val[0]);
} else {
copySelectGraphic = null;
carWashingState.value = new CarWashingState();
}
}
);
onMounted(() => {
if (lineStore.selectedGraphics) {
initCarWashingState(lineStore.selectedGraphics[0] as CarWashing);
}
});
function getNameFormat() {
console.log(code.value, '1111111');
return code.value;
}
function getBoolFormat(v: boolean) {
return v ? '是' : '否';
}
function getTwFormat(v: boolean[]) {
if (v.length === 2) {
return `头部${v[0] ? '停稳' : '未停稳'};尾部${v[1] ? '停稳' : '未停稳'};`;
} else if (v.length === 3) {
return `头部${v[0] ? '停稳' : '未停稳'};中部${
v[1] ? '停稳' : '未停稳'
};尾部${v[2] ? '停稳' : '未停稳'};`;
} else {
return '状态显示错误';
}
}
function getYXFormat(v: boolean[]) {
if (v.length === 2) {
return `头部${v[0] ? '允许' : '不允许'};尾部${v[1] ? '允许' : '不允许'};`;
} else if (v.length === 3) {
return `头部${v[0] ? '允许' : '不允许'};中部${
v[1] ? '允许' : '不允许'
};尾部${v[2] ? '允许' : '不允许'};`;
} else {
return '状态显示错误';
}
}
function initCarWashingState(carWashing: CarWashing) {
copySelectGraphic = toRaw(carWashing);
code.value = carWashing.datas.code;
console.log(code.value, carWashing);
updateState(carWashing);
subscribeState(carWashing);
}
function updateState(carWashing: CarWashing) {
carWashingState.value = carWashing.states.clone() as CarWashingState;
carWashingFault.value = carWashingState.value.param.fault;
}
function doCarWashingOperation(item: {
label: string;
value: request.Xcj.Operation;
}) {
if (!lineStore.simulationId) return;
if (item.label == '设置参数') {
if (lineStore.deviceOpreratDialogInstance) return;
lineStore.deviceOpreratDialogInstance = Dialog.create({
component: XcjOperation,
componentProps: {
id: +carWashingState.value.id,
code: code.value,
xcjFaultProp: carWashingState.value.param.fault,
},
cancel: true,
persistent: true,
}).onCancel(() => {
lineStore.deviceOpreratDialogInstance = null;
});
}
}
function subscribeState(g: CarWashing) {
g.on('stateupdate', updateState);
}
function unSubscribeState(g: CarWashing) {
g.off('stateupdate', updateState);
}
onUnmounted(() => {
if (copySelectGraphic) {
unSubscribeState(copySelectGraphic);
}
});
</script>

View File

@ -104,7 +104,6 @@ watch(
); );
onMounted(() => { onMounted(() => {
console.log('1111111111');
if (lineStore.selectedGraphics) { if (lineStore.selectedGraphics) {
initFloodGateState(lineStore.selectedGraphics[0] as FloodGate); initFloodGateState(lineStore.selectedGraphics[0] as FloodGate);
} }

View File

@ -9,7 +9,7 @@ function getHost(): string {
// return '192.168.3.7:9091'; // return '192.168.3.7:9091';
// return '192.168.3.47:9091'; // return '192.168.3.47:9091';
// return '192.168.3.37:9091'; // return '192.168.3.37:9091';
//return '192.168.33.207:9091'; // 张骞 return '192.168.33.207:9091'; // 张骞
// return '192.168.33.93:9091'; // return '192.168.33.93:9091';
// return '192.168.3.37:9091'; //卫志宏 // return '192.168.3.37:9091'; //卫志宏
// return 'test.joylink.club/bjrtsts-service'; // 测试 // return 'test.joylink.club/bjrtsts-service'; // 测试

View File

@ -142,7 +142,10 @@ import { Dialog } from 'quasar';
import { useDrawStore } from 'src/stores/draw-store'; import { useDrawStore } from 'src/stores/draw-store';
import { saveDraft } from 'src/api/DraftApi'; import { saveDraft } from 'src/api/DraftApi';
import { SignalDraw } from 'src/graphics/signal/SignalDrawAssistant'; import { SignalDraw } from 'src/graphics/signal/SignalDrawAssistant';
import { CarWashingData } from './graphics/CarWashingInteraction'; import {
CarWashingData,
CarWashingState,
} from './graphics/CarWashingInteraction';
import { import {
CarWashing, CarWashing,
CarWashingTemplate, CarWashingTemplate,
@ -246,7 +249,10 @@ export function initCommonDrawApp(app: IDrawApp) {
app, app,
new ConcentrationDividingLineTemplate(new ConcentrationDividingLineData()) new ConcentrationDividingLineTemplate(new ConcentrationDividingLineData())
); );
new CarWashingDraw(app, new CarWashingTemplate(new CarWashingData())); new CarWashingDraw(
app,
new CarWashingTemplate(new CarWashingData(), new CarWashingState())
);
new GarageDoorDraw( new GarageDoorDraw(
app, app,
new GarageDoorTemplate(new GarageDoorData(), new GarageDoorState()) new GarageDoorTemplate(new GarageDoorData(), new GarageDoorState())

View File

@ -1,13 +1,25 @@
import * as pb_1 from 'google-protobuf'; import * as pb_1 from 'google-protobuf';
import { FederatedMouseEvent } from 'pixi.js'; import { FederatedMouseEvent, DisplayObject } from 'pixi.js';
import { import {
CarWashing, CarWashing,
ICarWashingData, ICarWashingData,
ICarWashingState,
} from 'src/graphics/carWashing/CarWashing'; } from 'src/graphics/carWashing/CarWashing';
import { GraphicInteractionPlugin, JlGraphic, IGraphicScene } from 'jl-graphic'; import {
GraphicInteractionPlugin,
JlGraphic,
IGraphicScene,
MenuItemOptions,
ContextMenu,
} from 'jl-graphic';
import { graphicData } from 'src/protos/stationLayoutGraphics'; import { graphicData } from 'src/protos/stationLayoutGraphics';
import { GraphicDataBase } from './GraphicDataBase'; import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
import { state } from 'src/protos/device_state';
import { request } from 'src/protos/request';
import { useLineStore } from 'src/stores/line-store';
import { Dialog } from 'quasar';
import XcjOperation from 'src/components/draw-app/dialogs/XcjOperation.vue';
export class CarWashingData extends GraphicDataBase implements ICarWashingData { export class CarWashingData extends GraphicDataBase implements ICarWashingData {
constructor(data?: graphicData.CarWashing) { constructor(data?: graphicData.CarWashing) {
@ -60,10 +72,110 @@ export class CarWashingData extends GraphicDataBase implements ICarWashingData {
} }
} }
export class CarWashingState
extends GraphicStateBase
implements ICarWashingState
{
constructor(proto?: state.XcjState) {
let states;
if (proto) {
states = proto;
} else {
states = new state.XcjState();
}
super(states, CarWashing.Type);
}
get code(): string {
return this.states.id + '';
}
get id(): number {
return this.states.id;
}
set id(id: number) {
this.states.id = id;
}
get param(): request.XcjParam {
return this.states.param;
}
set param(param: request.XcjParam) {
this.states.param = param;
}
get xqj(): boolean {
return this.states.xqj;
}
set xqj(v: boolean) {
this.states.xqj = v;
}
get twjList(): boolean[] {
return this.states.twjList;
}
set twjList(v: boolean[]) {
this.states.twjList = v;
}
get tgqj(): boolean {
return this.states.tgqj;
}
set tgqj(v: boolean) {
this.states.tgqj = v;
}
get xcjxj(): boolean {
return this.states.xcjxj;
}
set xcjxj(v: boolean) {
this.states.xcjxj = v;
}
get xcyxj(): boolean {
return this.states.xcyxj;
}
set xcyxj(v: boolean) {
this.states.xcyxj = v;
}
get cfjList(): boolean[] {
return this.states.cfjList;
}
set cfjList(v: boolean[]) {
this.states.cfjList = v;
}
get jtj(): boolean {
return this.states.jtj;
}
set jtj(v: boolean) {
this.states.jtj = v;
}
get tgyxj(): boolean {
return this.states.tgyxj;
}
set tgyxj(v: boolean) {
this.states.tgyxj = v;
}
get states(): state.XcjState {
return this.getState<state.XcjState>();
}
clone(): CarWashingState {
return new CarWashingState(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);
}
}
const setXcjParam: MenuItemOptions = { name: '设置参数' };
const xcjOperateMenu: ContextMenu = ContextMenu.init({
name: '洗车机操作菜单',
groups: [
{
items: [setXcjParam],
},
],
});
export class CarWashingOperationInteraction extends GraphicInteractionPlugin<CarWashing> { export class CarWashingOperationInteraction extends GraphicInteractionPlugin<CarWashing> {
static Name = 'car_washing_operation'; static Name = 'car_washing_operation';
constructor(scene: IGraphicScene) { constructor(scene: IGraphicScene) {
super(CarWashingOperationInteraction.Name, scene); super(CarWashingOperationInteraction.Name, scene);
scene.registerMenu(xcjOperateMenu);
} }
static init(scene: IGraphicScene) { static init(scene: IGraphicScene) {
return new CarWashingOperationInteraction(scene); return new CarWashingOperationInteraction(scene);
@ -74,12 +186,16 @@ export class CarWashingOperationInteraction extends GraphicInteractionPlugin<Car
bind(g: CarWashing): void { bind(g: CarWashing): void {
g.eventMode = 'static'; g.eventMode = 'static';
g.cursor = 'pointer'; g.cursor = 'pointer';
g.selectable = true;
g.on('mousedown', this.onPress, this); g.on('mousedown', this.onPress, this);
g.on('_rightclick', this.onContextMenu);
} }
unbind(g: CarWashing): void { unbind(g: CarWashing): void {
g.eventMode = 'none'; g.eventMode = 'none';
g.cursor = 'default'; g.cursor = 'default';
g.selectable = false;
g.off('mousedown', this.onPress, this); g.off('mousedown', this.onPress, this);
g.off('_rightclick', this.onContextMenu);
} }
onPress(e: FederatedMouseEvent) { onPress(e: FederatedMouseEvent) {
const g = e.target as CarWashing; const g = e.target as CarWashing;
@ -91,4 +207,25 @@ export class CarWashingOperationInteraction extends GraphicInteractionPlugin<Car
g.off('mouseleave', this.onRelease, this); g.off('mouseleave', this.onRelease, this);
g.off('mouseup', this.onRelease, this); g.off('mouseup', this.onRelease, this);
} }
onContextMenu(e: FederatedMouseEvent) {
const target = e.target as DisplayObject;
const carWashing = target.getGraphic<CarWashing>();
if (!carWashing) return;
const lineStore = useLineStore();
setXcjParam.handler = async () => {
if (lineStore.deviceOpreratDialogInstance) return;
lineStore.deviceOpreratDialogInstance = Dialog.create({
component: XcjOperation,
componentProps: {
id: carWashing.id,
code: carWashing.datas.code,
xcjFaultProp: carWashing.states.param.fault,
},
cancel: true,
persistent: true,
});
};
xcjOperateMenu.open(e.global);
}
} }

View File

@ -23,6 +23,7 @@ import {
} from 'src/graphics/signal/Signal'; } from 'src/graphics/signal/Signal';
import { import {
CarWashingData, CarWashingData,
CarWashingState,
CarWashingOperationInteraction, CarWashingOperationInteraction,
} from './graphics/CarWashingInteraction'; } from './graphics/CarWashingInteraction';
import { import {
@ -327,7 +328,7 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
new AutoReturnBoxData(), new AutoReturnBoxData(),
new AutoReturnBoxState() new AutoReturnBoxState()
), ),
new CarWashingTemplate(new CarWashingData()), new CarWashingTemplate(new CarWashingData(), new CarWashingState()),
new GarageDoorTemplate(new GarageDoorData(), new GarageDoorState()), new GarageDoorTemplate(new GarageDoorData(), new GarageDoorState()),
new FloodGateTemplate(new FloodGateData(), new FloodGateState()), new FloodGateTemplate(new FloodGateData(), new FloodGateState()),
]; ];
@ -464,6 +465,11 @@ function handleSubscribe(lineScene: IGraphicScene) {
states.push(new FloodGateState(item)); states.push(new FloodGateState(item));
} }
}); });
storage.allStatus.xcjStates.forEach((item) => {
if (item.id) {
states.push(new CarWashingState(item));
}
});
storage.allStatus.trainState.forEach((item) => { storage.allStatus.trainState.forEach((item) => {
// 列车 // 列车
if (!item.show) { if (!item.show) {

View File

@ -1,12 +1,14 @@
import { Graphics } from 'pixi.js'; import { Graphics } from 'pixi.js';
import { import {
GraphicData, GraphicData,
GraphicState,
JlGraphic, JlGraphic,
JlGraphicTemplate, JlGraphicTemplate,
VectorText, VectorText,
linePoint, linePoint,
} from 'jl-graphic'; } from 'jl-graphic';
import { Section, SectionType } from '../section/Section'; import { Section, SectionType } from '../section/Section';
import { request } from 'src/protos/request';
export interface ICarWashingData extends GraphicData { export interface ICarWashingData extends GraphicData {
get code(): string; get code(): string;
@ -21,6 +23,28 @@ export interface ICarWashingData extends GraphicData {
copyFrom(data: ICarWashingData): void; copyFrom(data: ICarWashingData): void;
eq(other: ICarWashingData): boolean; eq(other: ICarWashingData): boolean;
} }
export interface ICarWashingState extends GraphicState {
get id(): number;
set id(v: number);
get param(): request.XcjParam;
set param(v: request.XcjParam);
get xqj(): boolean; //洗车请求
set xqj(v: boolean);
get twjList(): boolean[]; //停稳
set twjList(v: boolean[]);
get tgqj(): boolean; //通过请求
set tgqj(v: boolean);
get xcjxj(): boolean; //洗车就绪
set xcjxj(v: boolean);
get xcyxj(): boolean; //洗车允许
set xcyxj(v: boolean);
get cfjList(): boolean[]; //移动允许
set cfjList(v: boolean[]);
get jtj(): boolean; //紧急停车
set jtj(v: boolean);
get tgyxj(): boolean; //通过允许
set tgyxj(v: boolean);
}
const carWashingConsts = { const carWashingConsts = {
codeFontSize: 12, codeFontSize: 12,
@ -48,6 +72,9 @@ export class CarWashing extends JlGraphic {
get datas(): ICarWashingData { get datas(): ICarWashingData {
return this.getDatas<ICarWashingData>(); return this.getDatas<ICarWashingData>();
} }
get states(): ICarWashingState {
return this.getStates<ICarWashingState>();
}
doRepaint(): void { doRepaint(): void {
const codeGraph = this.codeGraph; const codeGraph = this.codeGraph;
codeGraph.text = this.datas.code; codeGraph.text = this.datas.code;
@ -106,12 +133,13 @@ export class CarWashing extends JlGraphic {
} }
export class CarWashingTemplate extends JlGraphicTemplate<CarWashing> { export class CarWashingTemplate extends JlGraphicTemplate<CarWashing> {
constructor(dataTemplate: ICarWashingData) { constructor(dataTemplate: ICarWashingData, stateTemplate?: ICarWashingState) {
super(CarWashing.Type, { dataTemplate }); super(CarWashing.Type, { dataTemplate, stateTemplate });
} }
new(): CarWashing { new(): CarWashing {
const carWashing = new CarWashing(); const carWashing = new CarWashing();
carWashing.loadData(this.datas); carWashing.loadData(this.datas);
carWashing.loadState(this.states);
return carWashing; return carWashing;
} }
} }