区段状态

This commit is contained in:
Yuan 2023-07-27 15:05:43 +08:00
parent 15dce2e5b2
commit 7a4d2fe9a0
10 changed files with 383 additions and 19 deletions

View File

@ -45,3 +45,12 @@ export async function setSwitchStatus(lineId: string, state: State) {
console.error(err);
}
}
export async function setTrackStatus(lineId: string, state: State) {
try {
delete state._state;
delete state._graphicType;
return await api.post(`/mock/track/status/${lineId}`, state);
} catch (err) {
console.error(err);
}
}

View File

@ -1,11 +1,155 @@
import {
ILogicSectionData,
ILogicSectionState,
LimitType,
LogicSection,
} from 'src/graphics/logicSection/LogicSection';
import * as pb_1 from 'google-protobuf';
import { GraphicDataBase } from './GraphicDataBase';
import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { IPointData } from 'pixi.js';
import { DisplayObject, FederatedMouseEvent, IPointData } from 'pixi.js';
import { state } from 'src/protos/device_status';
import {
GraphicApp,
GraphicInteractionPlugin,
JlGraphic,
} from 'src/jl-graphic';
import { LogicSectionGraphicHitArea } from 'src/graphics/logicSection/LogicSectionDrawAssistant';
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
import { useLineStore } from 'src/stores/line-store';
import { setTrackStatus } from 'src/api/TurnoutApi';
let menuItemHandler: (propName: keyof ILogicSectionState) => void;
const ciOccupied: MenuItemOptions = {
name: '连锁报告区段占用 - ciOccupied',
handler: () => menuItemHandler('ciOccupied'),
};
const cbtcOccupied: MenuItemOptions = {
name: 'CBTC报告区段占用 - cbtcOccupied',
handler: () => menuItemHandler('cbtcOccupied'),
};
const locked: MenuItemOptions = {
name: '锁闭 - locked',
handler: () => menuItemHandler('locked'),
};
const failLocked: MenuItemOptions = {
name: '故障锁闭 - failLocked',
handler: () => menuItemHandler('failLocked'),
};
const cut: MenuItemOptions = {
name: '轨道切除 - cut',
handler: () => menuItemHandler('cut'),
};
const atcInvalid: MenuItemOptions = {
name: '轨道区段被ATC报告失效 - atcInvalid',
handler: () => menuItemHandler('atcInvalid'),
};
const overlap: MenuItemOptions = {
name: 'overlap - overlap',
handler: () => menuItemHandler('overlap'),
};
const blocked: MenuItemOptions = {
name: '轨道区段封锁 - blocked',
handler: () => menuItemHandler('blocked'),
};
const LogicSectionMenu = ContextMenu.init({
name: 'LogicSection菜单',
groups: [
{
items: [
ciOccupied,
cbtcOccupied,
locked,
failLocked,
cut,
atcInvalid,
overlap,
blocked,
],
},
],
});
export class LogicSectionOperationPlugin extends GraphicInteractionPlugin<LogicSection> {
static Name = 'logic_section_menu';
constructor(app: GraphicApp) {
super(LogicSectionOperationPlugin.Name, app);
app.registerMenu(LogicSectionMenu);
}
filter(...grahpics: JlGraphic[]): LogicSection[] | undefined {
return grahpics.filter((g): g is LogicSection => g instanceof LogicSection);
}
static init(app: GraphicApp) {
return new LogicSectionOperationPlugin(app);
}
bind(g: LogicSection): void {
g.eventMode = 'static';
g.cursor = 'pointer';
g.lineGraphic.hitArea = new LogicSectionGraphicHitArea(g);
g.on('rightclick', this.onContextMenu, this);
}
unbind(g: LogicSection): void {
g.off('rightclick', this.onContextMenu);
}
onContextMenu(e: FederatedMouseEvent) {
const target = e.target as DisplayObject;
const section = target.getGraphic() as LogicSection;
this.app.updateSelected(section);
const state = {
id: section.datas.code,
ciOccupied: section.states.cbtcOccupied,
cbtcOccupied: section.states.cbtcOccupied,
locked: section.states.locked,
failLocked: section.states.failLocked,
expectLock: false,
expectUnlock: false,
inRoute: false,
cut: section.states.cut,
atcInvalid: section.states.atcInvalid,
overlap: section.states.overlap,
blocked: section.states.blocked,
limitType: section.states.limitType,
speedLimit: section.states.speedLimit,
};
(Object.keys(state) as unknown as (keyof ILogicSectionState)[]).forEach(
(key: keyof ILogicSectionState) => {
const item = LogicSectionMenu.groups[0].items.find((item) =>
item.config.name.includes(key)
);
if (!item) return;
if (
section.states[key] === true &&
!item?.config?.name?.endsWith('✔️')
) {
if (item?.config?.name) item.config.name += '✔️';
}
if (
section.states[key] !== true &&
item?.config?.name?.endsWith('✔️')
) {
item.config.name = item?.config?.name.slice(
0,
item.config.name.length - 2
);
}
}
);
menuItemHandler = (propName) => {
const lineId = useLineStore().lineId?.toString();
if (!lineId) return;
console.log({ ...section.states });
setTrackStatus(lineId, {
...state,
[propName]: !section.states[propName],
});
};
LogicSectionMenu.open(e.global);
}
}
export class LogicSectionData
extends GraphicDataBase
@ -49,3 +193,115 @@ export class LogicSectionData
return pb_1.Message.equals(this.data, other.data);
}
}
export class LogicSectionState
extends GraphicStateBase
implements ILogicSectionState
{
constructor(proto?: state.Track) {
let states;
if (proto) {
states = proto;
} else {
states = new state.Track();
}
super(states, LogicSection.Type);
}
get code(): string {
return this.states.id;
}
get states(): state.Track {
return this.getState<state.Track>();
}
public get id(): string {
return this.states.id;
}
public set id(id: string) {
this.states.id = id;
}
public get ciOccupied(): boolean {
return this.states.ciOccupied;
}
public set ciOccupied(value: boolean) {
this.states.ciOccupied = value;
}
// CBTC报告区段占用
public get cbtcOccupied(): boolean {
return this.states.cbtcOccupied;
}
public set cbtcOccupied(value: boolean) {
this.states.cbtcOccupied = value;
}
//锁闭
public get locked(): boolean {
return this.states.locked;
}
public set locked(value: boolean) {
this.states.locked = value;
}
//故障锁闭
public get failLocked(): boolean {
return this.states.failLocked;
}
public set failLocked(value: boolean) {
this.states.failLocked = value;
}
//轨道切除
public get cut(): boolean {
return this.states.cut;
}
public set cut(value: boolean) {
this.states.cut = value;
}
//轨道区段被ATC报告失效
public get atcInvalid(): boolean {
return this.states.atcInvalid;
}
public set atcInvalid(value: boolean) {
this.states.atcInvalid = value;
}
// OVERLAP
public get overlap(): boolean {
return this.states.overlap;
}
public set overlap(value: boolean) {
this.states.overlap = value;
}
//轨道区段封锁
public get blocked(): boolean {
return this.states.blocked;
}
public set blocked(value: boolean) {
this.states.blocked = value;
}
//限速
public get speedLimit(): number {
return this.states.speedLimit;
}
public set speedLimit(value: number) {
this.states.speedLimit = value;
}
//限速类型
public get limitType(): LimitType {
return this.states.limitType;
}
public set limitType(value: LimitType) {
this.states.limitType = value;
}
clone(): LogicSectionState {
return new LogicSectionState(this.states.cloneMessage());
}
copyFrom(data: LogicSectionState): void {
pb_1.Message.copyInto(data.states, this.states);
}
eq(data: LogicSectionState): boolean {
return pb_1.Message.equals(this.states, data.states);
}
}

View File

@ -23,7 +23,7 @@ import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
import { setSwitchStatus } from 'src/api/TurnoutApi';
import { useLineStore } from 'src/stores/line-store';
let menuItemHandler: (propName: string) => void;
let menuItemHandler: (propName: keyof ITurnoutState) => void;
const ipSingleSwitchStusCiOccupied: MenuItemOptions = {
name: '连锁报告道岔占用-ipSingleSwitchStusCiOccupied',
@ -217,10 +217,9 @@ export class TurnoutOperationPlugin extends GraphicInteractionPlugin<Turnout> {
}
}
);
menuItemHandler = (propName: string) => {
menuItemHandler = (propName) => {
const lineId = useLineStore().lineId?.toString();
if (!lineId) return;
console.log({ ...turnout.states });
setSwitchStatus(lineId, {
...state,
id: turnout.datas.code,

View File

@ -84,7 +84,10 @@ import {
LogicSection,
LogicSectionTemplate,
} from 'src/graphics/logicSection/LogicSection';
import { LogicSectionData } from './graphics/LogicSectionInteraction';
import {
LogicSectionData,
LogicSectionState,
} from './graphics/LogicSectionInteraction';
import { FederatedMouseEvent } from 'pixi.js';
// export function fromStoragePoint(p: graphicData.Point): Point {
@ -254,7 +257,10 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
new SectionDraw(app, new SectionTemplate(new SectionData())),
new LogicSectionDraw(
app,
new LogicSectionTemplate(new LogicSectionData())
new LogicSectionTemplate(
new LogicSectionData(),
new LogicSectionState()
)
),
new TurnoutDraw(
app,

View File

@ -67,7 +67,11 @@ import {
LogicSection,
LogicSectionTemplate,
} from 'src/graphics/logicSection/LogicSection';
import { LogicSectionData } from './graphics/LogicSectionInteraction';
import {
LogicSectionData,
LogicSectionOperationPlugin,
LogicSectionState,
} from './graphics/LogicSectionInteraction';
import { alert } from 'src/protos/alertInfo';
import { useLineNetStore } from 'src/stores/line-net-store';
import { QNotifyUpdateOptions, Notify } from 'quasar';
@ -105,7 +109,7 @@ export function initLineApp(dom: HTMLElement): GraphicApp {
new StationTemplate(new StationData(), new StationState()),
new TurnoutTemplate(new TurnoutData(), new TurnoutStates()),
new SectionTemplate(new SectionData()),
new LogicSectionTemplate(new LogicSectionData()),
new LogicSectionTemplate(new LogicSectionData(), new LogicSectionState()),
new SeparatorTemplate(new SeparatorData()),
new AxleCountingTemplate(new AxleCountingData()),
new TrainWindowTemplate(new TrainWindowData()),
@ -133,6 +137,7 @@ export function initLineApp(dom: HTMLElement): GraphicApp {
StationOperateInteraction.init(lineApp);
TrainOperateInteraction.init(lineApp);
TurnoutOperationPlugin.init(lineApp);
LogicSectionOperationPlugin.init(lineApp);
return lineApp;
}
@ -246,6 +251,9 @@ export async function loadLineDatas(app: GraphicApp) {
storage.switch.forEach((item) => {
states.push(new TurnoutStates(item));
});
storage.track.forEach((item) => {
states.push(new LogicSectionState(item));
});
return states;
},
});

View File

@ -1,6 +1,8 @@
import { Graphics, IPointData } from 'pixi.js';
import {
GraphicAnimation,
GraphicData,
GraphicState,
JlGraphic,
JlGraphicTemplate,
VectorText,
@ -17,11 +19,37 @@ export interface ILogicSectionData extends GraphicData {
copyFrom(data: ILogicSectionData): void;
eq(other: ILogicSectionData): boolean;
}
export enum LimitType {
Unknown = 0,
//为1时CBTC限速
Cbtc = 1,
//为2时联锁限速
Interlock = 2,
//为4时同时限速。
CbtcInterlock = 4,
}
export interface ILogicSectionState extends GraphicState {
id: string; //设备唯一识别码,一般为设备名称
ciOccupied: boolean; //连锁报告区段占用
cbtcOccupied: boolean; // CBTC报告区段占用
locked: boolean; //锁闭
failLocked: boolean; //故障锁闭
// expectLock: boolean; //进路办理中,期望锁闭
// expectUnlock: boolean; //进路取消中, 期望解除锁闭
// inRoute: boolean; //是否在进路中锁闭, 控制是否需要显示锁闭
cut: boolean; //轨道切除
atcInvalid: boolean; //轨道区段被ATC报告失效
overlap: boolean; // OVERLAP
blocked: boolean; //轨道区段封锁
speedLimit: number; //限速
limitType: LimitType; //限速类型
}
export class LogicSection extends JlGraphic implements ILineGraphic {
static Type = 'LogicSection';
lineGraphic: Graphics;
labelGraphic: VectorText;
dt = 0;
constructor() {
super(LogicSection.Type);
@ -37,9 +65,20 @@ export class LogicSection extends JlGraphic implements ILineGraphic {
this.addChild(this.labelGraphic);
}
get code(): string {
return this.datas.code;
}
set code(code: string) {
this.datas.code = code;
}
get datas(): ILogicSectionData {
return this.getDatas<ILogicSectionData>();
}
get states(): ILogicSectionState {
return this.getStates<ILogicSectionState>();
}
get linePoints(): IPointData[] {
return this.datas.points;
}
@ -54,11 +93,27 @@ export class LogicSection extends JlGraphic implements ILineGraphic {
throw new Error('Link坐标数据异常');
}
this.lineGraphic.clear();
this.lineGraphic.lineStyle(
SectionConsts.lineWidth,
SectionConsts.lineColor
);
let lineColor = SectionConsts.idleColor;
if (this.states.ciOccupied) {
lineColor = SectionConsts.ciOccupiedColor;
} else if (this.states.cbtcOccupied) {
lineColor = SectionConsts.cbtcOccupiedColor;
} else if (this.states.locked) {
lineColor = SectionConsts.lockedColor;
} else if (this.states.failLocked) {
lineColor = SectionConsts.failLockedColor;
} else if (this.states.blocked) {
lineColor = SectionConsts.blockedColor;
}
if (this.states.cut) {
this.bindFlashAnimation(this.lineGraphic);
this.animation('flash')?.resume();
} else {
this.lineGraphic.visible = true;
this.removeAnimation('flash');
}
this.lineGraphic.clear().lineStyle(SectionConsts.lineWidth, lineColor);
this.datas.points.forEach((p, i) => {
if (i !== 0) {
@ -81,13 +136,35 @@ export class LogicSection extends JlGraphic implements ILineGraphic {
);
}
}
bindFlashAnimation(g: Graphics) {
const flashAnimation = GraphicAnimation.init({
name: 'flash',
run: (dt: number) => {
this.dt += dt;
if (this.dt > 60) {
this.dt = 0;
g.visible = true;
} else if (this.dt > 30) {
g.visible = false;
}
},
});
this.addAnimation(flashAnimation);
return flashAnimation;
}
}
export class LogicSectionTemplate extends JlGraphicTemplate<LogicSection> {
constructor(dataTemplate: ILogicSectionData) {
super(LogicSection.Type, { dataTemplate });
constructor(
dataTemplate: ILogicSectionData,
stateTemplate: ILogicSectionState
) {
super(LogicSection.Type, { dataTemplate, stateTemplate });
}
new() {
return new LogicSection();
const g = new LogicSection();
g.loadData(this.datas);
g.loadState(this.states);
return g;
}
}

View File

@ -41,7 +41,7 @@ export class LogicSectionDraw extends GraphicDrawAssistant<
}
}
class LogicSectionGraphicHitArea implements IHitArea {
export class LogicSectionGraphicHitArea implements IHitArea {
section: LogicSection;
constructor(section: LogicSection) {
this.section = section;

View File

@ -53,6 +53,12 @@ export interface ISectionData extends GraphicData {
export const SectionConsts = {
lineColor: '#5578b6',
idleColor: '#888', //空闲
ciOccupiedColor: '#f00', //非通信车占用
cbtcOccupiedColor: '#f49', //通信车占用
lockedColor: '#fff', //锁闭
failLockedColor: '#954', //故障锁闭
blockedColor: '#606', //封锁
lineWidth: 5,
};

View File

@ -43,6 +43,7 @@ export interface ITurnoutData extends GraphicData {
export const TurnoutConsts = {
lineColor: '#5578b6',
idleColor: '#888', //空闲
jammedLineColor: '#f00', //挤岔
ciOccupiedColor: '#f00', //非通信车占用
cbtcOccupiedColor: '#f49', //通信车占用
@ -295,6 +296,8 @@ export class Turnout extends JlGraphic {
this.lineColor = TurnoutConsts.lockedColor;
} else if (this.states.ipSingleSwitchStusFailLocked) {
this.lineColor = TurnoutConsts.failLockedColor;
} else {
this.lineColor = TurnoutConsts.idleColor;
}
this.graphics.sections.forEach((sectionGraphic) => sectionGraphic.paint());

@ -1 +1 @@
Subproject commit ec5889fd030d15bc93efdaf8f73d62039bde31a9
Subproject commit 605c24f4e3de26b317bce2b644efa83d69c63475