From eb07afb45219c7d4043593b71c76468be714f2b6 Mon Sep 17 00:00:00 2001 From: Yuan Date: Fri, 1 Sep 2023 14:30:45 +0800 Subject: [PATCH 1/3] lineApp --- graphic-pixi | 2 +- index.html | 45 +++++-- src/drawApp/index.ts | 19 +-- src/drawApp/lineApp.ts | 161 ++++++++++++++++++++---- src/drawApp/lineNetApp.ts | 17 ++- src/jl-graphic/app/JlGraphicApp.ts | 79 ++++++++++-- src/jl-graphic/message/MessageBroker.ts | 10 +- src/jl-graphic/plugins/CopyPlugin.ts | 3 + src/jl-graphic/ui/ContextMenu.ts | 8 ++ src/layouts/LineLayout.vue | 75 +++-------- src/stores/line-store.ts | 10 +- 11 files changed, 299 insertions(+), 130 deletions(-) diff --git a/graphic-pixi b/graphic-pixi index 7e9c9eb..df9615f 160000 --- a/graphic-pixi +++ b/graphic-pixi @@ -1 +1 @@ -Subproject commit 7e9c9eb31176294726103306dcca61b80b896cf7 +Subproject commit df9615fe48fb15a572746e51462e5508db7d4c07 diff --git a/index.html b/index.html index 3c8c78f..661de38 100644 --- a/index.html +++ b/index.html @@ -3,19 +3,42 @@ <%= productName %> - - - - - + + + + + - - - - - + + + + + - + diff --git a/src/drawApp/index.ts b/src/drawApp/index.ts index 86ddb8c..2159553 100644 --- a/src/drawApp/index.ts +++ b/src/drawApp/index.ts @@ -7,10 +7,11 @@ import { Signal, SignalTemplate } from 'src/graphics/signal/Signal'; import { SignalDraw } from 'src/graphics/signal/SignalDrawAssistant'; import { CombinationKey, - GraphicApp, + IGraphicApp, GraphicData, - JlDrawApp, + IDrawApp, KeyListener, + newDrawApp, } from 'src/jl-graphic'; import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; @@ -120,7 +121,7 @@ import { FederatedMouseEvent } from 'pixi.js'; // }); // } -function constructMenu(app: JlDrawApp): (e: FederatedMouseEvent) => void { +function constructMenu(app: IDrawApp): (e: FederatedMouseEvent) => void { const UndoOptions: MenuItemOptions = { name: '撤销', }; @@ -203,9 +204,9 @@ function constructMenu(app: JlDrawApp): (e: FederatedMouseEvent) => void { }; return handleRightClick; } -let drawApp: JlDrawApp | null = null; +let drawApp: IDrawApp | null = null; -export function getDrawApp(): JlDrawApp | null { +export function getDrawApp(): IDrawApp | null { return drawApp; } @@ -216,8 +217,8 @@ export function destroyDrawApp(): void { } } -export function initDrawApp(dom: HTMLElement): JlDrawApp { - drawApp = new JlDrawApp(dom); +export function initDrawApp(dom: HTMLElement): IDrawApp { + drawApp = newDrawApp(); const app = drawApp; //根据草稿图类型加载绘图工具 let drawAssistants: ( @@ -308,7 +309,7 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { return drawApp; } -export function saveDrawToServer(app: JlDrawApp) { +export function saveDrawToServer(app: IDrawApp) { const base64 = saveDrawDatas(app); const drawStore = useDrawStore(); const id = drawStore.draftId; @@ -325,7 +326,7 @@ export function saveDrawToServer(app: JlDrawApp) { } // const StorageKey = 'graphic-storage'; -export function saveDrawDatas(app: JlDrawApp) { +export function saveDrawDatas(app: IDrawApp) { const storage = new graphicData.RtssGraphicStorage(); const canvasData = app.canvas.saveData(); storage.canvas = new graphicData.Canvas({ diff --git a/src/drawApp/lineApp.ts b/src/drawApp/lineApp.ts index 0acef40..35bb09b 100644 --- a/src/drawApp/lineApp.ts +++ b/src/drawApp/lineApp.ts @@ -1,4 +1,9 @@ -import { GraphicApp, GraphicData, GraphicState } from 'src/jl-graphic'; +import { + GraphicData, + GraphicState, + IGraphicApp, + newGraphicApp, +} from 'src/jl-graphic'; import { TrainData, TrainOperateInteraction, @@ -51,7 +56,7 @@ import { TrainWindowData } from './graphics/TrainWindowInteraction'; import { SeparatorTemplate } from 'src/graphics/separator/Separator'; import { SeparatorData } from './graphics/SeparatorInteraction'; -let lineApp: GraphicApp | null = null; +let lineApp: IGraphicApp; import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; @@ -67,6 +72,11 @@ import { import { alert } from 'src/protos/alertInfo'; import { useLineNetStore } from 'src/stores/line-net-store'; import { QNotifyUpdateOptions, Notify } from 'quasar'; +import { + CanvasData, + ICanvasProperties, + IGraphicAppConfig, +} from 'src/jl-graphic/app/JlGraphicApp'; // const QuickJumpMenu = new ContextMenu({ // name: '快捷跳转', @@ -78,19 +88,99 @@ import { QNotifyUpdateOptions, Notify } from 'quasar'; // }); // let QuickJumpMenu: ContextMenu = new ContextMenu(); -export function getLineApp(): GraphicApp | null { +export function getLineApp() { return lineApp; } export function destroyLineApp(): void { if (lineApp) { lineApp.destroy(); - lineApp = null; } } -export function initLineApp(dom: HTMLElement): GraphicApp { - lineApp = new GraphicApp(dom); +export function initLineApp(): IGraphicApp { + const lineAppDataLoader: IGraphicAppConfig['dataLoader'] = async () => { + const lineStore = useLineStore(); + const lineId = lineStore.lineId; + if (!lineId) { + throw Error('请先选择线路'); + } + const { proto: base64, name: lineName } = await getPublishMapInfoByLineId( + lineId, + 'line' + ); + lineStore.setLineName(lineName); + const datas: GraphicData[] = []; + const canvasProperty = new CanvasData(); + if (base64) { + const storage = graphicData.RtssGraphicStorage.deserialize( + toUint8Array(base64) + ); + canvasProperty.copyFrom(storage.canvas); + storage.Platforms.forEach((platform) => { + const g = new PlatformData(platform); + datas.push(g); + }); + const quickJumpMenuItem: MenuItemOptions[] = []; + storage.stations.forEach((station) => { + datas.push(new StationData(station)); + const item: MenuItemOptions = { + name: station.name, + handler: () => { + const g = lineApp.queryStore.queryById(station.common.id); + if (g) { + lineApp.makeGraphicCenterShow(g); + } + }, + }; + quickJumpMenuItem.push(item); + }); + storage.train.forEach((train) => { + datas.push(new TrainData(train)); + }); + storage.turnouts.forEach((turnout) => { + datas.push(new TurnoutData(turnout)); + }); + storage.signals.forEach((signal) => { + datas.push(new SignalData(signal)); + }); + storage.section.forEach((section) => { + datas.push(new SectionData(section)); + }); + storage.logicSections.forEach((section) => { + datas.push(new LogicSectionData(section)); + }); + storage.separators.forEach((separator) => { + datas.push(new SeparatorData(separator)); + }); + storage.axleCountings.forEach((axleCounting) => { + datas.push(new AxleCountingData(axleCounting)); + }); + storage.trainWindows.forEach((trainWindow) => { + datas.push(new TrainWindowData(trainWindow)); + }); + } + return { datas, canvasProperty }; + }; + + lineApp = newGraphicApp({ + interactiveGraphicTypeIncludes: [ + Signal.Type, + Platform.Type, + Station.Type, + Train.Type, + LogicSection.Type, + Turnout.Type, + ], + mouseToolOptions: { + boxSelect: true, + viewportDrag: true, + wheelZoom: true, + boxSelectColor: '0xff0000', + }, + dataLoader: lineAppDataLoader, + }); + const graphicTemplate = [ new TrainTemplate(new TrainData(), new TrainState()), new SignalTemplate(new SignalData(), new SignalState()), @@ -104,34 +194,51 @@ export function initLineApp(dom: HTMLElement): GraphicApp { new TrainWindowTemplate(new TrainWindowData()), ]; lineApp.registerGraphicTemplates(...graphicTemplate); - lineApp.setOptions({ - mouseToolOptions: { - boxSelect: true, - viewportDrag: true, - wheelZoom: true, - boxSelectColor: '0xff0000', - }, - interactiveTypeOptions: { - interactiveGraphicTypeIncludes: [ - Signal.Type, - Platform.Type, - Station.Type, - Train.Type, - LogicSection.Type, - Turnout.Type, - ], - }, - }); SignalOperateInteraction.init(lineApp); PlatformOperateInteraction.init(lineApp); StationOperateInteraction.init(lineApp); TrainOperateInteraction.init(lineApp); TurnoutOperationPlugin.init(lineApp); LogicSectionOperationPlugin.init(lineApp); + + // lineApp.registerMenu( + // new ContextMenu({ + // name: '快捷跳转', + // groups: [ + // { + // items: lineApp.queryStore + // .queryByType(Station.Type) + // .map((station) => { + // console.log(station.name); + // return { + // name: station.name ?? '', + // handler: () => { + // lineApp.makeGraphicCenterShow(station); + // }, + // }; + // }), + // }, + // ], + // }) + // ); + + // const axleCountings = lineApp.queryStore.queryByType( + // AxleCounting.Type + // ); + // axleCountings.forEach((axleCounting) => { + // axleCounting.visible = false; + // }); + // const trainWindows = lineApp.queryStore.queryByType( + // TrainWindow.Type + // ); + // trainWindows.forEach((trainWindow) => { + // trainWindow.visible = false; + // }); + return lineApp; } -export async function loadLineDatas(app: GraphicApp) { +export async function loadLineDatas(app: IGraphicApp) { const lineStore = useLineStore(); const lineId = lineStore.lineId; if (!lineId) { @@ -147,7 +254,7 @@ export async function loadLineDatas(app: GraphicApp) { toUint8Array(base64) ); console.log('加载数据', storage); - app.updateCanvas(storage.canvas); + // app.updateCanvas(storage.canvas); const datas: GraphicData[] = []; storage.Platforms.forEach((platform) => { const g = new PlatformData(platform); @@ -191,7 +298,7 @@ export async function loadLineDatas(app: GraphicApp) { storage.trainWindows.forEach((trainWindow) => { datas.push(new TrainWindowData(trainWindow)); }); - await app.loadGraphic(datas); + // await app.loadGraphic(datas); //隐藏计轴--和车次窗 const axleCountings = app.queryStore.queryByType( diff --git a/src/drawApp/lineNetApp.ts b/src/drawApp/lineNetApp.ts index 7379894..d78159d 100644 --- a/src/drawApp/lineNetApp.ts +++ b/src/drawApp/lineNetApp.ts @@ -1,4 +1,9 @@ -import { GraphicApp, GraphicData, GraphicState } from 'src/jl-graphic'; +import { + IGraphicApp, + GraphicData, + GraphicState, + newGraphicApp, +} from 'src/jl-graphic'; import { getPublishLineNet } from 'src/api/PublishApi'; import { graphicData } from 'src/protos/stationLayoutGraphics'; import { state } from 'src/protos/ws_message'; @@ -30,9 +35,9 @@ import { getJwtToken } from 'src/configs/TokenManage'; import { alert } from 'src/protos/alertInfo'; import { QNotifyUpdateOptions, Notify } from 'quasar'; -let lineNetApp: GraphicApp | null = null; +let lineNetApp: IGraphicApp | null = null; -export function getLineNetApp(): GraphicApp | null { +export function getLineNetApp(): IGraphicApp | null { return lineNetApp; } @@ -43,8 +48,8 @@ export function destroyLineNetApp(): void { } } -export function initLineNetApp(dom: HTMLElement): GraphicApp { - lineNetApp = new GraphicApp(dom); +export function initLineNetApp(dom: HTMLElement): IGraphicApp { + lineNetApp = newGraphicApp(); const graphicTemplate = [ new RunLineTemplate(new RunLineData()), new PathLineTemplate(new PathLineData()), @@ -71,7 +76,7 @@ export function initLineNetApp(dom: HTMLElement): GraphicApp { return lineNetApp; } -export async function loadLineNetDatas(app: GraphicApp) { +export async function loadLineNetDatas(app: IGraphicApp) { const lineNetStore = useLineNetStore(); const { proto: base64, name: lineNetName } = await getPublishLineNet(); lineNetStore.setLineNetName(lineNetName); diff --git a/src/jl-graphic/app/JlGraphicApp.ts b/src/jl-graphic/app/JlGraphicApp.ts index 2026111..ddeecd0 100644 --- a/src/jl-graphic/app/JlGraphicApp.ts +++ b/src/jl-graphic/app/JlGraphicApp.ts @@ -445,9 +445,13 @@ export interface IGraphicScene extends EventEmitter { */ toCanvasCoordinates(p: Point): Point; /** - * 加载/重新加载数据 + * 加载/重新加载数据(若已经加载过,则不会重新加载) */ reload(): Promise; + /** + * 强制重新加载,无论是否已经加载过 + */ + forceReload(): Promise; /** * 绑定到dom * @param dom @@ -534,6 +538,7 @@ abstract class GraphicSceneBase pixi: Application; // Pixi 渲染器 viewport: Viewport; // 视口 canvas: JlCanvas; // 画布 + _loaded = false; // 是否已经加载 _dom?: HTMLElement; // 场景绑定到的dom节点 _viewportResizer?: NodeJS.Timeout; // 自动根据dom大小变化调整视口尺寸 graphicTemplateMap: Map = new Map< @@ -630,11 +635,7 @@ abstract class GraphicSceneBase return this.queryStore.getAllGraphics().filter((g) => g.selected); } - /** - * 重新加载数据 - */ - async reload(): Promise { - this.graphicStore.clear(); + private async load(): Promise { if (this._options.dataLoader) { const storage = await this._options.dataLoader(); if (storage.canvasProperty) { @@ -644,6 +645,25 @@ abstract class GraphicSceneBase await this.loadGraphic(storage.datas); } } + this._loaded = true; + } + + /** + * 重新加载数据 + */ + async reload(): Promise { + if (!this._loaded) { + this.graphicStore.clear(); + await this.load(); + } else { + console.debug('场景已经加载过数据,不重新加载', this); + } + } + + async forceReload(): Promise { + console.debug('场景强制重新加载数据', this); + this.graphicStore.clear(); + await this.load(); } /** @@ -712,6 +732,28 @@ abstract class GraphicSceneBase } } + /** + * 暂停 + */ + private pause() { + // 暂停动画 + this.animationManager.pause(); + // 取消消息订阅 + this.wsMsgBroker.unsubscribeAll(); + // 关闭所有上下文菜单 + this.menuPlugin.closeAll(); + } + + /** + * 恢复 + */ + private resume() { + // 恢复动画 + this.animationManager.resume(); + // 重新订阅 + this.wsMsgBroker.resubscribeAll(); + } + bindDom(dom: HTMLElement): void { this._dom = dom; this.pixi.resizeTo = dom; @@ -726,8 +768,8 @@ abstract class GraphicSceneBase // ); this.updateViewport(dom.clientWidth, dom.clientHeight); }, 1000); - // 恢复动画 - this.animationManager.resume(); + // 恢复 + this.resume(); } unbindDom(): void { @@ -735,8 +777,8 @@ abstract class GraphicSceneBase clearInterval(this._viewportResizer); this._dom.removeChild(this.pixi.view as unknown as Node); this._dom = undefined; - // 暂停动画 - this.animationManager.pause(); + // 暂停 + this.pause(); } } /** @@ -1096,6 +1138,11 @@ export interface IGraphicApp extends IGraphicScene { * @returns */ getScene(code: string): IGraphicScene; + /** + * 切换场景 + * @param dom + */ + switchScene(code: string, dom: HTMLElement): void; /** * 移除指定code场景 * @param code @@ -1197,6 +1244,18 @@ export class GraphicApp extends GraphicSceneBase implements IGraphicApp { return scene; } + switchScene(code: string, dom: HTMLElement): void { + const scene = this.getScene(code); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const [_code, pre] of this.scenes) { + if (pre.dom === dom) { + pre.unbindDom(); + break; + } + } + scene.bindDom(dom); + } + removeScene(code: string): void { const scene = this.scenes.get(code); if (scene) { diff --git a/src/jl-graphic/message/MessageBroker.ts b/src/jl-graphic/message/MessageBroker.ts index 99c9d1f..cec650b 100644 --- a/src/jl-graphic/message/MessageBroker.ts +++ b/src/jl-graphic/message/MessageBroker.ts @@ -222,17 +222,23 @@ export class AppWsMsgBroker { } } - unsbuscribeAll() { + unsubscribeAll() { this.subscriptions.forEach((record, destination) => { this.unsbuscribe(destination); }); } + resubscribeAll() { + this.subscriptions.forEach((handler, destination) => { + WsMsgCli.registerSubscription(destination, handler); + }); + } + /** * 取消所有订阅,从通用Stomp客户端移除此消息代理 */ close() { WsMsgCli.removeAppMsgBroker(this); - this.unsbuscribeAll(); + this.unsubscribeAll(); } } diff --git a/src/jl-graphic/plugins/CopyPlugin.ts b/src/jl-graphic/plugins/CopyPlugin.ts index 0821cae..381d875 100644 --- a/src/jl-graphic/plugins/CopyPlugin.ts +++ b/src/jl-graphic/plugins/CopyPlugin.ts @@ -3,6 +3,9 @@ import { IGraphicScene } from '../app'; import { JlGraphic } from '../core'; import { KeyListener } from './KeyboardPlugin'; +/** + * 图形复制插件 + */ export class GraphicCopyPlugin { container: Container; scene: IGraphicScene; diff --git a/src/jl-graphic/ui/ContextMenu.ts b/src/jl-graphic/ui/ContextMenu.ts index 065a268..8d56524 100644 --- a/src/jl-graphic/ui/ContextMenu.ts +++ b/src/jl-graphic/ui/ContextMenu.ts @@ -91,6 +91,14 @@ export class ContextMenuPlugin { this.app.pixi.stage.removeChild(menu); } } + /** + * 关闭所有菜单 + */ + closeAll() { + this.contextMenuMap.forEach((cm) => { + this.close(cm); + }); + } /** * 越界检查 * @param menu diff --git a/src/layouts/LineLayout.vue b/src/layouts/LineLayout.vue index 72c781f..028ca09 100644 --- a/src/layouts/LineLayout.vue +++ b/src/layouts/LineLayout.vue @@ -1,30 +1,24 @@ diff --git a/src/stores/line-store.ts b/src/stores/line-store.ts index 99e320c..277fc71 100644 --- a/src/stores/line-store.ts +++ b/src/stores/line-store.ts @@ -1,5 +1,5 @@ import { defineStore } from 'pinia'; -import { JlCanvas, JlGraphic, GraphicApp } from 'src/jl-graphic'; +import { IJlCanvas, JlGraphic, IGraphicApp } from 'src/jl-graphic'; import { initLineApp, getLineApp, destroyLineApp } from 'src/drawApp/lineApp'; export const useLineStore = defineStore('line', { @@ -26,18 +26,18 @@ export const useLineStore = defineStore('line', { }, }, actions: { - getLineApp(): GraphicApp { + getLineApp(): IGraphicApp { const app = getLineApp(); if (app == null) { throw new Error('未初始化app'); } return app; }, - getJlCanvas(): JlCanvas { + getJlCanvas(): IJlCanvas { return this.getLineApp().canvas; }, - initLineApp(dom: HTMLElement) { - const app = initLineApp(dom); + initLineApp() { + const app = initLineApp(); app.on('graphicselectedchange', () => { this.selectedGraphics = app.selectedGraphics; }); From bad9c90983642eebb52329bc5b8b13d0ceaef0fc Mon Sep 17 00:00:00 2001 From: Yuan Date: Fri, 1 Sep 2023 17:14:08 +0800 Subject: [PATCH 2/3] lineNetApp --- src/drawApp/lineApp.ts | 308 +++++++++------------------------- src/drawApp/lineNetApp.ts | 186 ++++++++++---------- src/layouts/LineLayout.vue | 50 +++--- src/pages/LineMonitorPage.vue | 14 +- src/pages/MonitorPage.vue | 8 +- src/stores/line-net-store.ts | 14 +- src/stores/line-store.ts | 17 +- 7 files changed, 239 insertions(+), 358 deletions(-) diff --git a/src/drawApp/lineApp.ts b/src/drawApp/lineApp.ts index 35bb09b..a0ac107 100644 --- a/src/drawApp/lineApp.ts +++ b/src/drawApp/lineApp.ts @@ -55,9 +55,6 @@ import { import { TrainWindowData } from './graphics/TrainWindowInteraction'; import { SeparatorTemplate } from 'src/graphics/separator/Separator'; import { SeparatorData } from './graphics/SeparatorInteraction'; - -let lineApp: IGraphicApp; - import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; import { @@ -69,24 +66,9 @@ import { LogicSectionOperationPlugin, LogicSectionState, } from './graphics/LogicSectionInteraction'; -import { alert } from 'src/protos/alertInfo'; -import { useLineNetStore } from 'src/stores/line-net-store'; -import { QNotifyUpdateOptions, Notify } from 'quasar'; -import { - CanvasData, - ICanvasProperties, - IGraphicAppConfig, -} from 'src/jl-graphic/app/JlGraphicApp'; +import { CanvasData, IGraphicAppConfig } from 'src/jl-graphic/app/JlGraphicApp'; -// const QuickJumpMenu = new ContextMenu({ -// name: '快捷跳转', -// groups: [ -// { -// items: [], -// }, -// ], -// }); -// let QuickJumpMenu: ContextMenu = new ContextMenu(); +let lineApp: IGraphicApp | null = null; export function getLineApp() { return lineApp; @@ -95,10 +77,12 @@ export function getLineApp() { export function destroyLineApp(): void { if (lineApp) { lineApp.destroy(); + lineApp = null; } } -export function initLineApp(): IGraphicApp { +export function initLineApp(lineId: number): IGraphicApp { + if (lineApp) return lineApp; const lineAppDataLoader: IGraphicAppConfig['dataLoader'] = async () => { const lineStore = useLineStore(); const lineId = lineStore.lineId; @@ -121,19 +105,8 @@ export function initLineApp(): IGraphicApp { const g = new PlatformData(platform); datas.push(g); }); - const quickJumpMenuItem: MenuItemOptions[] = []; storage.stations.forEach((station) => { datas.push(new StationData(station)); - const item: MenuItemOptions = { - name: station.name, - handler: () => { - const g = lineApp.queryStore.queryById(station.common.id); - if (g) { - lineApp.makeGraphicCenterShow(g); - } - }, - }; - quickJumpMenuItem.push(item); }); storage.train.forEach((train) => { datas.push(new TrainData(train)); @@ -201,207 +174,84 @@ export function initLineApp(): IGraphicApp { TurnoutOperationPlugin.init(lineApp); LogicSectionOperationPlugin.init(lineApp); - // lineApp.registerMenu( - // new ContextMenu({ - // name: '快捷跳转', - // groups: [ - // { - // items: lineApp.queryStore - // .queryByType(Station.Type) - // .map((station) => { - // console.log(station.name); - // return { - // name: station.name ?? '', - // handler: () => { - // lineApp.makeGraphicCenterShow(station); - // }, - // }; - // }), - // }, - // ], - // }) - // ); + lineApp.enableWsMassaging({ + wsUrl: getWebsocketUrl(), + token: getJwtToken() as string, + }); - // const axleCountings = lineApp.queryStore.queryByType( - // AxleCounting.Type - // ); - // axleCountings.forEach((axleCounting) => { - // axleCounting.visible = false; - // }); - // const trainWindows = lineApp.queryStore.queryByType( - // TrainWindow.Type - // ); - // trainWindows.forEach((trainWindow) => { - // trainWindow.visible = false; - // }); + lineApp.subscribe({ + destination: `/queue/line/${lineId}/device`, + messageConverter: (message: Uint8Array) => { + const states: GraphicState[] = []; + const storage = state.WsLineMessage.deserialize(message); + storage.signal.forEach((item) => { + if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { + states.push(new SignalState(item)); + } + }); + storage.platform.forEach((item) => { + if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { + states.push(new PlatformState(item)); + } + }); + storage.rtu.forEach((item) => { + if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { + states.push(new StationState(item)); + } + }); + storage.switch.forEach((item) => { + if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { + states.push(new TurnoutStates(item)); + } + }); + storage.track.forEach((item) => { + if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { + states.push(new LogicSectionState(item)); + } + }); + return states; + }, + }); return lineApp; } -export async function loadLineDatas(app: IGraphicApp) { - const lineStore = useLineStore(); - const lineId = lineStore.lineId; - if (!lineId) { - return; - } - const { proto: base64, name: lineName } = await getPublishMapInfoByLineId( - lineId, - 'line' +export async function bindLineAppTo(dom: HTMLElement) { + if (!lineApp) throw Error('请先初始化LineApp'); + lineApp.bindDom(dom); + + await lineApp.reload(); + + const quickJumpMenu = new ContextMenu({ + name: '快捷跳转', + groups: [ + { + items: lineApp.queryStore + .queryByType(Station.Type) + .map((station) => ({ + name: station.datas.name ?? '', + handler: () => { + lineApp?.makeGraphicCenterShow(station); + }, + })), + }, + ], + }); + lineApp.registerMenu(quickJumpMenu); + lineApp.canvas.on('_rightclick', (e) => { + quickJumpMenu.open(e.global); + }); + + const axleCountings = lineApp.queryStore.queryByType( + AxleCounting.Type ); - lineStore.setLineName(lineName); - if (base64) { - const storage = graphicData.RtssGraphicStorage.deserialize( - toUint8Array(base64) - ); - console.log('加载数据', storage); - // app.updateCanvas(storage.canvas); - const datas: GraphicData[] = []; - storage.Platforms.forEach((platform) => { - const g = new PlatformData(platform); - datas.push(g); - }); - const quickJumpMenuItem: MenuItemOptions[] = []; - storage.stations.forEach((station) => { - datas.push(new StationData(station)); - const item: MenuItemOptions = { - name: station.name, - handler: () => { - const g = app.queryStore.queryById(station.common.id); - if (g) { - app.makeGraphicCenterShow(g); - } - }, - }; - quickJumpMenuItem.push(item); - }); - storage.train.forEach((train) => { - datas.push(new TrainData(train)); - }); - storage.turnouts.forEach((turnout) => { - datas.push(new TurnoutData(turnout)); - }); - storage.signals.forEach((signal) => { - datas.push(new SignalData(signal)); - }); - storage.section.forEach((section) => { - datas.push(new SectionData(section)); - }); - storage.logicSections.forEach((section) => { - datas.push(new LogicSectionData(section)); - }); - storage.separators.forEach((separator) => { - datas.push(new SeparatorData(separator)); - }); - storage.axleCountings.forEach((axleCounting) => { - datas.push(new AxleCountingData(axleCounting)); - }); - storage.trainWindows.forEach((trainWindow) => { - datas.push(new TrainWindowData(trainWindow)); - }); - // await app.loadGraphic(datas); - - //隐藏计轴--和车次窗 - const axleCountings = app.queryStore.queryByType( - AxleCounting.Type - ); - axleCountings.forEach((axleCounting) => { - axleCounting.visible = false; - }); - const trainWindows = app.queryStore.queryByType( - TrainWindow.Type - ); - trainWindows.forEach((trainWindow) => { - trainWindow.visible = false; - }); - const QuickJumpMenu = new ContextMenu({ - name: '快捷跳转', - groups: [ - { - items: quickJumpMenuItem, - }, - ], - }); - app.registerMenu(QuickJumpMenu); - app.canvas.on('_rightclick', (e) => { - QuickJumpMenu.open(e.global); - }); - - app.enableWsMassaging({ - wsUrl: `${getWebsocketUrl()}`, - token: getJwtToken() as string, - }); - app.subscribe({ - destination: `/queue/line/${lineId}/device`, - messageConverter: (message: Uint8Array) => { - const states: GraphicState[] = []; - const storage = state.WsLineMessage.deserialize(message); - // console.log(storage, '1111'); - storage.signal.forEach((item) => { - if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { - states.push(new SignalState(item)); - } - }); - storage.platform.forEach((item) => { - if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { - states.push(new PlatformState(item)); - } - }); - storage.rtu.forEach((item) => { - if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { - states.push(new StationState(item)); - } - }); - storage.switch.forEach((item) => { - if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { - states.push(new TurnoutStates(item)); - } - }); - storage.track.forEach((item) => { - if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { - states.push(new LogicSectionState(item)); - } - }); - return states; - }, - }); - app.subscribe({ - destination: `/queue/line/${lineId}/train`, - messageConverter: (message: Uint8Array) => { - const states: GraphicState[] = []; - const trainStorage = state.WsLineTrainMessage.deserialize(message); - // console.log(trainStorage, '222'); - trainStorage.trainInfo.forEach((item) => { - if (item.rtuId !== 81 && item.rtuId !== 82 && item.rtuId) { - states.push(new TrainState(item)); - } - }); - return states; - }, - }); - let msgNotify: null | ((props?: QNotifyUpdateOptions | undefined) => void) = - null; - app.on('websocket-connect-state-change', (connected) => { - if (!connected && !msgNotify) { - msgNotify = Notify.create({ - type: 'negative', - timeout: 0, - position: 'top-right', - message: '通信链接已断开!', - }); - } else if (msgNotify && connected) { - msgNotify(); - msgNotify = null; - } - }); - const lineNetStore = useLineNetStore(); - app.subscribe({ - destination: '/queue/xian/ncc/alert', - messageHandle: (message: Uint8Array) => { - const storage = alert.NccAlertInfoMessage.deserialize(message); - lineNetStore.setAlarmInfo(storage.messages as []); - }, - }); - } else { - app.loadGraphic([]); - } + axleCountings.forEach((axleCounting) => { + axleCounting.visible = false; + }); + const trainWindows = lineApp.queryStore.queryByType( + TrainWindow.Type + ); + trainWindows.forEach((trainWindow) => { + trainWindow.visible = false; + }); } diff --git a/src/drawApp/lineNetApp.ts b/src/drawApp/lineNetApp.ts index d78159d..1c55b2a 100644 --- a/src/drawApp/lineNetApp.ts +++ b/src/drawApp/lineNetApp.ts @@ -33,7 +33,8 @@ import { toUint8Array } from 'js-base64'; import { getWebsocketUrl } from 'src/configs/UrlManage'; import { getJwtToken } from 'src/configs/TokenManage'; import { alert } from 'src/protos/alertInfo'; -import { QNotifyUpdateOptions, Notify } from 'quasar'; +import { Notify } from 'quasar'; +import { CanvasData, IGraphicAppConfig } from 'src/jl-graphic/app/JlGraphicApp'; let lineNetApp: IGraphicApp | null = null; @@ -48,8 +49,55 @@ export function destroyLineNetApp(): void { } } -export function initLineNetApp(dom: HTMLElement): IGraphicApp { - lineNetApp = newGraphicApp(); +export function initLineNetApp(): IGraphicApp { + const lineNetStore = useLineNetStore(); + const lineNetAppDataLoader: IGraphicAppConfig['dataLoader'] = async () => { + const { proto: base64, name: lineNetName } = await getPublishLineNet(); + lineNetStore.setLineNetName(lineNetName); + const datas: GraphicData[] = []; + const canvasProperty = new CanvasData(); + if (base64) { + const storage = graphicData.RtssGraphicStorage.deserialize( + toUint8Array(base64) + ); + canvasProperty.copyFrom(storage.canvas); + storage.runLines.forEach((runLine) => { + const g = new RunLineData(runLine); + datas.push(g); + }); + storage.pathLines.forEach((pathLine) => { + const g = new PathLineData(pathLine); + datas.push(g); + }); + storage.stationLines.forEach((stationLine) => { + const g = new StationLineData(stationLine); + datas.push(g); + }); + storage.trainLines.forEach((trainLine) => { + const g = new TrainLineData(trainLine); + datas.push(g); + }); + storage.rects.forEach((rect) => { + const g = new RectData(rect); + datas.push(g); + }); + } + return { datas, canvasProperty }; + }; + + lineNetApp = newGraphicApp({ + interactiveGraphicTypeIncludes: [ + RunLine.Type, + StationLine.Type, + TrainLine.Type, + ], + mouseToolOptions: { + boxSelect: false, + viewportDrag: true, + wheelZoom: true, + }, + dataLoader: lineNetAppDataLoader, + }); const graphicTemplate = [ new RunLineTemplate(new RunLineData()), new PathLineTemplate(new PathLineData()), @@ -58,98 +106,66 @@ export function initLineNetApp(dom: HTMLElement): IGraphicApp { new RectTemplate(new RectData()), ]; lineNetApp.registerGraphicTemplates(...graphicTemplate); - lineNetApp.setOptions({ - mouseToolOptions: { - boxSelect: false, - viewportDrag: true, - wheelZoom: true, - }, - interactiveTypeOptions: { - interactiveGraphicTypeIncludes: [ - RunLine.Type, - StationLine.Type, - TrainLine.Type, - ], + + RunLineOperateInteraction.init(lineNetApp); + + lineNetApp.enableWsMassaging({ + wsUrl: `${getWebsocketUrl()}`, + token: getJwtToken() as string, + }); + lineNetApp.subscribe({ + destination: '/queue/lineNet', + messageConverter: (message: Uint8Array) => { + const storage = state.WsLineNetMessage.deserialize(message); + const states: GraphicState[] = []; + storage.offset.forEach((item) => { + states.push(new TrainLineState(item)); + }); + return states; }, }); - RunLineOperateInteraction.init(lineNetApp); + lineNetApp.subscribe({ + destination: '/queue/xian/ncc/alert', + messageHandle: (message: Uint8Array) => { + const storage = alert.NccAlertInfoMessage.deserialize(message); + lineNetStore.setAlarmInfo(storage.messages as []); + }, + }); + + let msgNotify: ReturnType | null = null; + lineNetApp.on('websocket-connect-state-change', (connected) => { + if (!connected && !msgNotify) { + msgNotify = Notify.create({ + type: 'negative', + timeout: 0, + position: 'top-right', + message: '通信链接已断开!', + }); + } else if (msgNotify && connected) { + msgNotify(); + msgNotify = null; + } + }); return lineNetApp; } +export async function bindLineNetAppTo(dom: HTMLElement) { + if (!lineNetApp) throw Error('请先初始化LineApp'); + lineNetApp.bindDom(dom); + + await lineNetApp.reload(); + + const pathLineList = lineNetApp.queryStore.queryByType(PathLine.Type); + pathLineList.forEach((pathLine) => { + pathLine.visible = false; + }); +} + export async function loadLineNetDatas(app: IGraphicApp) { const lineNetStore = useLineNetStore(); const { proto: base64, name: lineNetName } = await getPublishLineNet(); lineNetStore.setLineNetName(lineNetName); if (base64) { - const storage = graphicData.RtssGraphicStorage.deserialize( - toUint8Array(base64) - ); - console.log('加载数据', storage); - app.updateCanvas(storage.canvas); - const datas: GraphicData[] = []; - storage.runLines.forEach((runLine) => { - const g = new RunLineData(runLine); - datas.push(g); - }); - storage.pathLines.forEach((pathLine) => { - const g = new PathLineData(pathLine); - datas.push(g); - }); - storage.stationLines.forEach((stationLine) => { - const g = new StationLineData(stationLine); - datas.push(g); - }); - storage.trainLines.forEach((trainLine) => { - const g = new TrainLineData(trainLine); - datas.push(g); - }); - storage.rects.forEach((rect) => { - const g = new RectData(rect); - datas.push(g); - }); - await app.loadGraphic(datas); - const pathLineList = app.queryStore.queryByType(PathLine.Type); - pathLineList.forEach((pathLine) => { - pathLine.visible = false; - }); - app.enableWsMassaging({ - wsUrl: `${getWebsocketUrl()}`, - token: getJwtToken() as string, - }); - app.subscribe({ - destination: '/queue/lineNet', - messageConverter: (message: Uint8Array) => { - const storage = state.WsLineNetMessage.deserialize(message); - const states: GraphicState[] = []; - storage.offset.forEach((item) => { - states.push(new TrainLineState(item)); - }); - return states; - }, - }); - app.subscribe({ - destination: '/queue/xian/ncc/alert', - messageHandle: (message: Uint8Array) => { - const storage = alert.NccAlertInfoMessage.deserialize(message); - lineNetStore.setAlarmInfo(storage.messages as []); - }, - }); - let msgNotify: null | ((props?: QNotifyUpdateOptions | undefined) => void) = - null; - app.on('websocket-connect-state-change', (connected) => { - if (!connected && !msgNotify) { - msgNotify = Notify.create({ - type: 'negative', - timeout: 0, - position: 'top-right', - message: '通信链接已断开!', - }); - } else if (msgNotify && connected) { - msgNotify(); - msgNotify = null; - } - }); } else { - app.loadGraphic([]); } } diff --git a/src/layouts/LineLayout.vue b/src/layouts/LineLayout.vue index 028ca09..010538b 100644 --- a/src/layouts/LineLayout.vue +++ b/src/layouts/LineLayout.vue @@ -13,15 +13,16 @@ diff --git a/src/pages/LineMonitorPage.vue b/src/pages/LineMonitorPage.vue index 8c8759d..c1ca729 100644 --- a/src/pages/LineMonitorPage.vue +++ b/src/pages/LineMonitorPage.vue @@ -15,7 +15,6 @@ import { onMounted, ref, watch, onUnmounted } from 'vue'; import { useLineStore } from 'src/stores/line-store'; import { useRoute } from 'vue-router'; import { useLineNetStore } from 'src/stores/line-net-store'; -import { loadLineDatas, getLineApp } from 'src/drawApp/lineApp'; import StateProperties from 'src/components/state-app/StateProperties.vue'; import { JlGraphic } from 'src/jl-graphic'; @@ -61,27 +60,22 @@ function onResize() { dom.style.width = props.sizeWidth + 'px'; dom.style.height = props.sizeHeight + 50 + 'px'; } - const lineApp = getLineApp(); - if (lineApp) { - lineApp.onDomResize(props.sizeWidth, props.sizeHeight - 32); - } } +const lineId = Number(route.params.lineId); +const lineApp = lineStore.initLineApp(lineId); + onMounted(() => { const dom = document.getElementById('line-app-container'); if (dom) { lineStore.setLineId(+route.params.lineId as number); - const lineApp = lineStore.initLineApp(dom); - loadLineDatas(lineApp); + lineStore.bindDom(dom); onResize(); - } else { - lineStore.setLineId(null); } drawerRight.value = false; setTimeout(() => { if (lineNetStore.alarmInfo.length) { try { - const lineApp = getLineApp(); if (lineApp) { const deviceId = lineNetStore.alarmInfo[0].locator_device_id; const faultDevice = lineApp.queryStore.queryById( diff --git a/src/pages/MonitorPage.vue b/src/pages/MonitorPage.vue index 18ae015..9908f5e 100644 --- a/src/pages/MonitorPage.vue +++ b/src/pages/MonitorPage.vue @@ -61,17 +61,13 @@ function onResize() { dom.style.width = props.sizeWidth + 'px'; dom.style.height = props.sizeHeight + 'px'; } - const lineNetApp = getLineNetApp(); - if (lineNetApp) { - lineNetApp.onDomResize(props.sizeWidth, props.sizeHeight); - } } onMounted(() => { const dom = document.getElementById('line-app-container'); if (dom) { - const lineApp = lineNetStore.initLineNetApp(dom); - loadLineNetDatas(lineApp); + lineNetStore.initLineNetApp(); + lineNetStore.bindDom(dom); onResize(); } }); diff --git a/src/stores/line-net-store.ts b/src/stores/line-net-store.ts index 136c08d..bd2bff4 100644 --- a/src/stores/line-net-store.ts +++ b/src/stores/line-net-store.ts @@ -1,9 +1,10 @@ import { defineStore } from 'pinia'; -import { JlCanvas, JlGraphic, GraphicApp } from 'src/jl-graphic'; +import { IJlCanvas, JlGraphic, IGraphicApp } from 'src/jl-graphic'; import { initLineNetApp, getLineNetApp, destroyLineNetApp, + bindLineNetAppTo, } from 'src/drawApp/lineNetApp'; export interface AlarmInfo { id: string; @@ -45,24 +46,27 @@ export const useLineNetStore = defineStore('lineNet', { }, }, actions: { - getLineNetApp(): GraphicApp { + getLineNetApp(): IGraphicApp { const app = getLineNetApp(); if (app == null) { throw new Error('未初始化app'); } return app; }, - getJlCanvas(): JlCanvas { + getJlCanvas(): IJlCanvas { return this.getLineNetApp().canvas; }, - initLineNetApp(dom: HTMLElement) { - const app = initLineNetApp(dom); + initLineNetApp() { + const app = initLineNetApp(); app.on('graphicselectedchange', () => { this.selectedGraphics = app.selectedGraphics; }); this.selectedGraphics = []; return app; }, + bindDom(dom: HTMLElement) { + bindLineNetAppTo(dom); + }, destroy() { this.selectedGraphics = null; destroyLineNetApp(); diff --git a/src/stores/line-store.ts b/src/stores/line-store.ts index 277fc71..30df460 100644 --- a/src/stores/line-store.ts +++ b/src/stores/line-store.ts @@ -1,6 +1,11 @@ import { defineStore } from 'pinia'; import { IJlCanvas, JlGraphic, IGraphicApp } from 'src/jl-graphic'; -import { initLineApp, getLineApp, destroyLineApp } from 'src/drawApp/lineApp'; +import { + initLineApp, + getLineApp, + destroyLineApp, + bindLineAppTo, +} from 'src/drawApp/lineApp'; export const useLineStore = defineStore('line', { state: () => ({ @@ -28,7 +33,7 @@ export const useLineStore = defineStore('line', { actions: { getLineApp(): IGraphicApp { const app = getLineApp(); - if (app == null) { + if (app === null) { throw new Error('未初始化app'); } return app; @@ -36,14 +41,18 @@ export const useLineStore = defineStore('line', { getJlCanvas(): IJlCanvas { return this.getLineApp().canvas; }, - initLineApp() { - const app = initLineApp(); + initLineApp(lineId: number) { + const app = initLineApp(lineId); + this.setLineId(lineId); app.on('graphicselectedchange', () => { this.selectedGraphics = app.selectedGraphics; }); this.selectedGraphics = []; return app; }, + bindDom(dom: HTMLElement) { + bindLineAppTo(dom); + }, destroy() { this.selectedGraphics = null; destroyLineApp(); From 1ec8e86ee8b163b142e6d890d554a485553b0c47 Mon Sep 17 00:00:00 2001 From: Yuan Date: Fri, 1 Sep 2023 17:15:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=A1=86=E6=9E=B6=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- graphic-pixi | 2 +- src/jl-graphic/plugins/CommonMousePlugin.ts | 22 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/graphic-pixi b/graphic-pixi index c66f841..cc73757 160000 --- a/graphic-pixi +++ b/graphic-pixi @@ -1 +1 @@ -Subproject commit c66f841526d22af7dcb8ce768ad96488f13468c3 +Subproject commit cc737578baa0dadef5c2b82b6ada66c117ba3d6b diff --git a/src/jl-graphic/plugins/CommonMousePlugin.ts b/src/jl-graphic/plugins/CommonMousePlugin.ts index 20eec59..76993ff 100644 --- a/src/jl-graphic/plugins/CommonMousePlugin.ts +++ b/src/jl-graphic/plugins/CommonMousePlugin.ts @@ -101,11 +101,27 @@ export class CommonMouseTool extends AppInteractionPlugin { return new CommonMouseTool(app); } + /** + * 计算对比色 + * @param rgb + * @returns + */ + private calContrastColor(rgb: number): number { + if (rgb > 0.45 && rgb < 0.55) { + return 0; + } else { + return 1 - rgb; + } + } + private updateBoxLineColor(cp: ICanvasProperties) { // 根据画布背景调整线色 const color = new Color(cp.backgroundColor); - const cn = color.toNumber() ^ 0xffffff; - this._boxLineColor.setValue(cn); + // 对比色 + const r = this.calContrastColor(color.red); + const g = this.calContrastColor(color.green); + const b = this.calContrastColor(color.blue); + this._boxLineColor.setValue([r, g, b]); } bind(): void { @@ -305,7 +321,7 @@ export class CommonMouseTool extends AppInteractionPlugin { if (!this.drag) return; // 绘制框选矩形框 this.box.clear(); - this.box.lineStyle({ width: 1, color: this._boxLineColor }); + this.box.lineStyle({ width: 2, color: this._boxLineColor }); const dsx = end.x - start.x; const dsy = end.y - start.y; let { x, y } = start;