列车连接操作&列车连接状态

This commit is contained in:
joylink_fanyuhong 2024-03-19 10:22:17 +08:00
parent 1fa571f777
commit eee398eaa1
7 changed files with 399 additions and 11 deletions

@ -1 +1 @@
Subproject commit 225f92b91cd0ff0371b9fd785f91ddf05903ea8a Subproject commit 6dff8221d5e43e87727328fcd3260559ff13a2a3

View File

@ -417,3 +417,16 @@ export async function sendTransponderTelegram(data: {
}) { }) {
return await api.put(`${UriBase}/balise/telegram/send`, data); 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

@ -0,0 +1,97 @@
<!-- eslint-disable vue/no-mutating-props -->
<template>
<draggable-dialog
seamless
title="列车连接"
v-model="showLoadTransData"
:width="300"
:height="175"
>
<q-card style="width: 300px">
<q-card-section>
<q-form ref="myForm" @submit="onCreate" class="q-gutter-md">
<q-select
v-model="connType"
label="连接平台"
outlined
:options="connectOptions"
emitValue
:rules="[(val) => !!val || '连接平台不能为空!']"
mapOptions
hint=""
>
</q-select>
<q-card-actions align="right" class="text-primary">
<q-btn
flat
label="取消"
@click="showLoadTransData = false"
v-close-popup
/>
<q-btn flat label="确认" type="submit" />
</q-card-actions>
</q-form>
</q-card-section>
</q-card>
</draggable-dialog>
</template>
<script setup lang="ts">
import { QForm } from 'quasar';
import { onMounted, ref } from 'vue';
import DraggableDialog from 'src/components/common/DraggableDialog.vue';
import { getCanLinkPlatForm, updateTrainConn } from 'src/api/Simulation';
import { successNotify, errorNotify } from 'src/utils/CommonNotify';
const props = defineProps({
simulationId: {
type: String,
required: true,
},
trainId: {
type: String,
required: true,
},
});
const connType = ref<number>(0);
const connectOptions = ref<{ label: string; value: number }[]>([]);
const showLoadTransData = ref(true);
onMounted(() => {
connectOptions.value = [];
getCanLinkPlatForm(props.simulationId)
.then((resp) => {
const list: { label: string; value: number }[] = [];
resp.data.forEach((element: { connType: number }) => {
if (element.connType === 1) {
list.push({ label: '半实物', value: 1 });
} else if (element.connType === 2) {
list.push({ label: 'PC仿真', value: 2 });
}
});
connectOptions.value = list;
})
.catch((e) => {
errorNotify('获取列车可连接第三方平台失败!', e);
});
});
const myForm = ref<QForm | null>(null);
function onCreate() {
myForm.value?.validate().then(async (res) => {
updateTrainConn({
id: props.trainId + '',
simulationId: props.simulationId,
connType: connType.value,
})
.then(() => {
successNotify('列车连接成功!');
showLoadTransData.value = false;
})
.catch((e) => {
errorNotify('列车连接失败', e);
});
});
}
</script>
<style scoped></style>

View File

@ -3,27 +3,68 @@
<q-card-section class="flex justify-between"> <q-card-section class="flex justify-between">
<span class="text-h6">列车信息</span> <span class="text-h6">列车信息</span>
<div> <div>
<q-btn <!-- <q-btn
color="primary" color="primary"
label="设置" label="设置"
@click="setTrain" @click="setTrain"
style="margin-right: 10px" 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"
/> />
<q-btn color="primary" label="曲线图" @click="open" />
</div> </div>
</q-card-section> </q-card-section>
<q-separator inset /> <q-separator inset />
<q-list v-if="trainInfo" dense> <q-list v-if="trainInfo" dense>
<q-item v-for="(item, index) in list" :key="index"> <q-item v-for="(item, index) in list" :key="index">
<q-item-section> <q-item-section>
<q-item-label>{{ item.label }}</q-item-label> <q-item-label
:style="{
color:
item.key === 'conn' || item.key === 'connType'
? trainInfo.conn
? '#0F0'
: '#F00'
: '',
}"
>{{ item.label }}</q-item-label
>
</q-item-section> </q-item-section>
<q-item-section side> <q-item-section side>
<q-item-label caption>{{ <q-item-label
caption
:style="{
color:
item.key === 'conn' || item.key === 'connType'
? trainInfo.conn
? '#0F0'
: '#F00'
: '',
}"
>{{
item.formatFn item.formatFn
? item.formatFn(trainInfo[item.key]) ? item.formatFn(trainInfo[item.key])
: trainInfo[item.key] : trainInfo[item.key]
}}</q-item-label> }}</q-item-label
>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-separator inset /> <q-separator inset />
@ -147,6 +188,8 @@ import { Turnout } from 'src/graphics/turnout/Turnout';
import { Section } from 'src/graphics/section/Section'; import { Section } from 'src/graphics/section/Section';
import SetTrainParam from 'src/components/draw-app/dialogs/SetTrainParam.vue'; import SetTrainParam from 'src/components/draw-app/dialogs/SetTrainParam.vue';
import { Dialog } from 'quasar'; import { Dialog } from 'quasar';
import { state } from 'src/protos/device_state';
import SetTrainLink from 'src/components/draw-app/dialogs/SetTrainLink.vue';
interface KeyType { interface KeyType {
label: string; label: string;
@ -158,6 +201,8 @@ const lineStore = useLineStore();
const trainInfo = ref<ITrainState | null>(); const trainInfo = ref<ITrainState | null>();
const list: KeyType[] = [ const list: KeyType[] = [
{ label: '列车索引', key: 'id' }, { label: '列车索引', key: 'id' },
{ label: '连接状态', key: 'conn', formatFn: connStateFormat },
{ label: '连接平台', key: 'connType', formatFn: connTypeFormat },
{ label: '列车长度', key: 'trainLength', formatFn: trainLengthFormat }, { label: '列车长度', key: 'trainLength', formatFn: trainLengthFormat },
{ label: '车头所在设备', key: 'headDeviceId', formatFn: getDeviveName }, { label: '车头所在设备', key: 'headDeviceId', formatFn: getDeviveName },
{ label: '车头所在设备的偏移量', key: 'headOffset', formatFn: offsetFormat }, { label: '车头所在设备的偏移量', key: 'headOffset', formatFn: offsetFormat },
@ -393,7 +438,20 @@ function haomiaoFormat(v: number) {
function trainLengthFormat(v: number) { function trainLengthFormat(v: number) {
return `${v / 1000} m`; 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) { function floatDecimal(v: number, x = 2) {
// //
const n = v.toFixed(x); const n = v.toFixed(x);
@ -540,6 +598,42 @@ function open() {
lineStore.setEchartsTrainId(trainInfo.value.id); lineStore.setEchartsTrainId(trainInfo.value.id);
} }
const options = [
{
label: '设置参数',
value: 1,
},
{
label: '列车连接',
value: 2,
},
];
function doTrainOperation(option: { label: string; value: number }) {
if (option.value == 1) {
setTrain();
} else if (option.value == 2) {
linkTrain();
}
}
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() { function setTrain() {
if (!lineStore.selectedGraphics) return; if (!lineStore.selectedGraphics) return;
if (lineStore.deviceOpreratDialogInstance) return; if (lineStore.deviceOpreratDialogInstance) return;

View File

@ -15,6 +15,7 @@ import { useLineStore } from 'src/stores/line-store';
import { successNotify, errorNotify } from '../../utils/CommonNotify'; import { successNotify, errorNotify } from '../../utils/CommonNotify';
import { Dialog } from 'quasar'; import { Dialog } from 'quasar';
import SetTrainParam from 'src/components/draw-app/dialogs/SetTrainParam.vue'; 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 { export class TrainState extends GraphicStateBase implements ITrainState {
constructor(proto?: state.TrainMapState) { constructor(proto?: state.TrainMapState) {
let states; let states;
@ -660,6 +661,18 @@ export class TrainState extends GraphicStateBase implements ITrainState {
set telegram(v: string) { set telegram(v: string) {
this.states.btmState.telegram = v; 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;
}
clone(): TrainState { clone(): TrainState {
return new TrainState(this.states.cloneMessage()); return new TrainState(this.states.cloneMessage());
} }
@ -677,6 +690,9 @@ export class TrainState extends GraphicStateBase implements ITrainState {
const TrainParam: MenuItemOptions = { const TrainParam: MenuItemOptions = {
name: '设置参数', name: '设置参数',
}; };
const TrainLink: MenuItemOptions = {
name: '列车连接',
};
const removeTrainConfig: MenuItemOptions = { const removeTrainConfig: MenuItemOptions = {
name: '清除列车', name: '清除列车',
}; };
@ -684,7 +700,7 @@ const TrainOperateMenu: ContextMenu = ContextMenu.init({
name: '列车操作菜单', name: '列车操作菜单',
groups: [ groups: [
{ {
items: [TrainParam, removeTrainConfig], items: [TrainParam, TrainLink, removeTrainConfig],
}, },
], ],
}); });
@ -738,6 +754,20 @@ export class TrainOperateInteraction extends GraphicInteractionPlugin<Train> {
persistent: true, persistent: true,
}); });
}; };
TrainLink.handler = () => {
if (lineStore.deviceOpreratDialogInstance) return;
lineStore.deviceOpreratDialogInstance = Dialog.create({
title: '列车连接',
message: '',
component: SetTrainLink,
componentProps: {
trainId: train.code,
simulationId: simulationId,
},
cancel: true,
persistent: true,
});
};
removeTrainConfig.handler = () => { removeTrainConfig.handler = () => {
Dialog.create({ Dialog.create({
title: '确认', title: '确认',

View File

@ -14,6 +14,7 @@ import { DevicePort, Section } from '../section/Section';
import { AxleCounting } from '../axleCounting/AxleCounting'; import { AxleCounting } from '../axleCounting/AxleCounting';
import { getKmDistance } from 'src/drawApp/lineScene'; import { getKmDistance } from 'src/drawApp/lineScene';
import { graphicData } from 'src/protos/stationLayoutGraphics'; import { graphicData } from 'src/protos/stationLayoutGraphics';
import { state } from 'src/protos/device_state';
export interface ITrainData extends GraphicData { export interface ITrainData extends GraphicData {
get code(): string; // 车号 get code(): string; // 车号
@ -235,6 +236,10 @@ export interface ITrainState extends GraphicState {
set messageCounter(v: number); set messageCounter(v: number);
get telegram(): string; get telegram(): string;
set telegram(v: string); set telegram(v: string);
get conn(): boolean; // 连接状态
set conn(v: boolean);
get connType(): state.TrainConnState.TrainConnType;
set connType(v: state.TrainConnState.TrainConnType);
} }
interface bodyWH { interface bodyWH {
width: number; // 宽 width: number; // 宽

View File

@ -1015,6 +1015,103 @@ export namespace state {
return StationState.deserialize(bytes); return StationState.deserialize(bytes);
} }
} }
export class TrainConnState extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {
conn?: boolean;
connType?: TrainConnState.TrainConnType;
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") {
if ("conn" in data && data.conn != undefined) {
this.conn = data.conn;
}
if ("connType" in data && data.connType != undefined) {
this.connType = data.connType;
}
}
}
get conn() {
return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean;
}
set conn(value: boolean) {
pb_1.Message.setField(this, 1, value);
}
get connType() {
return pb_1.Message.getFieldWithDefault(this, 2, TrainConnState.TrainConnType.NONE) as TrainConnState.TrainConnType;
}
set connType(value: TrainConnState.TrainConnType) {
pb_1.Message.setField(this, 2, value);
}
static fromObject(data: {
conn?: boolean;
connType?: TrainConnState.TrainConnType;
}): TrainConnState {
const message = new TrainConnState({});
if (data.conn != null) {
message.conn = data.conn;
}
if (data.connType != null) {
message.connType = data.connType;
}
return message;
}
toObject() {
const data: {
conn?: boolean;
connType?: TrainConnState.TrainConnType;
} = {};
if (this.conn != null) {
data.conn = this.conn;
}
if (this.connType != null) {
data.connType = this.connType;
}
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.conn != false)
writer.writeBool(1, this.conn);
if (this.connType != TrainConnState.TrainConnType.NONE)
writer.writeEnum(2, this.connType);
if (!w)
return writer.getResultBuffer();
}
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TrainConnState {
const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TrainConnState();
while (reader.nextField()) {
if (reader.isEndGroup())
break;
switch (reader.getFieldNumber()) {
case 1:
message.conn = reader.readBool();
break;
case 2:
message.connType = reader.readEnum();
break;
default: reader.skipField();
}
}
return message;
}
serializeBinary(): Uint8Array {
return this.serialize();
}
static deserializeBinary(bytes: Uint8Array): TrainConnState {
return TrainConnState.deserialize(bytes);
}
}
export namespace TrainConnState {
export enum TrainConnType {
NONE = 0,
VOBC = 1,
PC_SIM = 2
}
}
export class TrainState extends pb_1.Message { export class TrainState extends pb_1.Message {
#one_of_decls: number[][] = []; #one_of_decls: number[][] = [];
constructor(data?: any[] | { constructor(data?: any[] | {
@ -1041,6 +1138,7 @@ export namespace state {
tailOffset?: number; tailOffset?: number;
tailDevicePort?: string; tailDevicePort?: string;
btmState?: BTMState; btmState?: BTMState;
connState?: TrainConnState;
}) { }) {
super(); super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
@ -1114,6 +1212,9 @@ export namespace state {
if ("btmState" in data && data.btmState != undefined) { if ("btmState" in data && data.btmState != undefined) {
this.btmState = data.btmState; this.btmState = data.btmState;
} }
if ("connState" in data && data.connState != undefined) {
this.connState = data.connState;
}
} }
} }
get id() { get id() {
@ -1272,6 +1373,15 @@ export namespace state {
get has_btmState() { get has_btmState() {
return pb_1.Message.getField(this, 23) != null; return pb_1.Message.getField(this, 23) != null;
} }
get connState() {
return pb_1.Message.getWrapperField(this, TrainConnState, 24) as TrainConnState;
}
set connState(value: TrainConnState) {
pb_1.Message.setWrapperField(this, 24, value);
}
get has_connState() {
return pb_1.Message.getField(this, 24) != null;
}
static fromObject(data: { static fromObject(data: {
id?: string; id?: string;
up?: boolean; up?: boolean;
@ -1296,6 +1406,7 @@ export namespace state {
tailOffset?: number; tailOffset?: number;
tailDevicePort?: string; tailDevicePort?: string;
btmState?: ReturnType<typeof BTMState.prototype.toObject>; btmState?: ReturnType<typeof BTMState.prototype.toObject>;
connState?: ReturnType<typeof TrainConnState.prototype.toObject>;
}): TrainState { }): TrainState {
const message = new TrainState({}); const message = new TrainState({});
if (data.id != null) { if (data.id != null) {
@ -1367,6 +1478,9 @@ export namespace state {
if (data.btmState != null) { if (data.btmState != null) {
message.btmState = BTMState.fromObject(data.btmState); message.btmState = BTMState.fromObject(data.btmState);
} }
if (data.connState != null) {
message.connState = TrainConnState.fromObject(data.connState);
}
return message; return message;
} }
toObject() { toObject() {
@ -1394,6 +1508,7 @@ export namespace state {
tailOffset?: number; tailOffset?: number;
tailDevicePort?: string; tailDevicePort?: string;
btmState?: ReturnType<typeof BTMState.prototype.toObject>; btmState?: ReturnType<typeof BTMState.prototype.toObject>;
connState?: ReturnType<typeof TrainConnState.prototype.toObject>;
} = {}; } = {};
if (this.id != null) { if (this.id != null) {
data.id = this.id; data.id = this.id;
@ -1464,6 +1579,9 @@ export namespace state {
if (this.btmState != null) { if (this.btmState != null) {
data.btmState = this.btmState.toObject(); data.btmState = this.btmState.toObject();
} }
if (this.connState != null) {
data.connState = this.connState.toObject();
}
return data; return data;
} }
serialize(): Uint8Array; serialize(): Uint8Array;
@ -1516,6 +1634,8 @@ export namespace state {
writer.writeString(22, this.tailDevicePort); writer.writeString(22, this.tailDevicePort);
if (this.has_btmState) if (this.has_btmState)
writer.writeMessage(23, this.btmState, () => this.btmState.serialize(writer)); writer.writeMessage(23, this.btmState, () => this.btmState.serialize(writer));
if (this.has_connState)
writer.writeMessage(24, this.connState, () => this.connState.serialize(writer));
if (!w) if (!w)
return writer.getResultBuffer(); return writer.getResultBuffer();
} }
@ -1594,6 +1714,9 @@ export namespace state {
case 23: case 23:
reader.readMessage(message.btmState, () => message.btmState = BTMState.deserialize(reader)); reader.readMessage(message.btmState, () => message.btmState = BTMState.deserialize(reader));
break; break;
case 24:
reader.readMessage(message.connState, () => message.connState = TrainConnState.deserialize(reader));
break;
default: reader.skipField(); default: reader.skipField();
} }
} }
@ -2893,6 +3016,7 @@ export namespace state {
tailOffset?: number; tailOffset?: number;
tailDevicePort?: string; tailDevicePort?: string;
btmState?: BTMState; btmState?: BTMState;
connState?: TrainConnState;
}) { }) {
super(); super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [20], this.#one_of_decls); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [20], this.#one_of_decls);
@ -3104,6 +3228,9 @@ export namespace state {
if ("btmState" in data && data.btmState != undefined) { if ("btmState" in data && data.btmState != undefined) {
this.btmState = data.btmState; this.btmState = data.btmState;
} }
if ("connState" in data && data.connState != undefined) {
this.connState = data.connState;
}
} }
} }
get id() { get id() {
@ -3532,6 +3659,15 @@ export namespace state {
get has_btmState() { get has_btmState() {
return pb_1.Message.getField(this, 69) != null; return pb_1.Message.getField(this, 69) != null;
} }
get connState() {
return pb_1.Message.getWrapperField(this, TrainConnState, 70) as TrainConnState;
}
set connState(value: TrainConnState) {
pb_1.Message.setWrapperField(this, 70, value);
}
get has_connState() {
return pb_1.Message.getField(this, 70) != null;
}
static fromObject(data: { static fromObject(data: {
id?: string; id?: string;
up?: boolean; up?: boolean;
@ -3602,6 +3738,7 @@ export namespace state {
tailOffset?: number; tailOffset?: number;
tailDevicePort?: string; tailDevicePort?: string;
btmState?: ReturnType<typeof BTMState.prototype.toObject>; btmState?: ReturnType<typeof BTMState.prototype.toObject>;
connState?: ReturnType<typeof TrainConnState.prototype.toObject>;
}): TrainMapState { }): TrainMapState {
const message = new TrainMapState({}); const message = new TrainMapState({});
if (data.id != null) { if (data.id != null) {
@ -3811,6 +3948,9 @@ export namespace state {
if (data.btmState != null) { if (data.btmState != null) {
message.btmState = BTMState.fromObject(data.btmState); message.btmState = BTMState.fromObject(data.btmState);
} }
if (data.connState != null) {
message.connState = TrainConnState.fromObject(data.connState);
}
return message; return message;
} }
toObject() { toObject() {
@ -3884,6 +4024,7 @@ export namespace state {
tailOffset?: number; tailOffset?: number;
tailDevicePort?: string; tailDevicePort?: string;
btmState?: ReturnType<typeof BTMState.prototype.toObject>; btmState?: ReturnType<typeof BTMState.prototype.toObject>;
connState?: ReturnType<typeof TrainConnState.prototype.toObject>;
} = {}; } = {};
if (this.id != null) { if (this.id != null) {
data.id = this.id; data.id = this.id;
@ -4092,6 +4233,9 @@ export namespace state {
if (this.btmState != null) { if (this.btmState != null) {
data.btmState = this.btmState.toObject(); data.btmState = this.btmState.toObject();
} }
if (this.connState != null) {
data.connState = this.connState.toObject();
}
return data; return data;
} }
serialize(): Uint8Array; serialize(): Uint8Array;
@ -4236,6 +4380,8 @@ export namespace state {
writer.writeString(68, this.tailDevicePort); writer.writeString(68, this.tailDevicePort);
if (this.has_btmState) if (this.has_btmState)
writer.writeMessage(69, this.btmState, () => this.btmState.serialize(writer)); writer.writeMessage(69, this.btmState, () => this.btmState.serialize(writer));
if (this.has_connState)
writer.writeMessage(70, this.connState, () => this.connState.serialize(writer));
if (!w) if (!w)
return writer.getResultBuffer(); return writer.getResultBuffer();
} }
@ -4452,6 +4598,9 @@ export namespace state {
case 69: case 69:
reader.readMessage(message.btmState, () => message.btmState = BTMState.deserialize(reader)); reader.readMessage(message.btmState, () => message.btmState = BTMState.deserialize(reader));
break; break;
case 70:
reader.readMessage(message.connState, () => message.connState = TrainConnState.deserialize(reader));
break;
default: reader.skipField(); default: reader.skipField();
} }
} }