diff --git a/public/drawIcon.svg b/public/drawIcon.svg index 575f9fd..3a336c1 100644 --- a/public/drawIcon.svg +++ b/public/drawIcon.svg @@ -102,5 +102,12 @@ - + + + + + + + + diff --git a/src/drawApp/graphics/FAS/ManualAlarmButtonInteraction.ts b/src/drawApp/graphics/FAS/ManualAlarmButtonInteraction.ts new file mode 100644 index 0000000..470a069 --- /dev/null +++ b/src/drawApp/graphics/FAS/ManualAlarmButtonInteraction.ts @@ -0,0 +1,44 @@ +import * as pb_1 from 'google-protobuf'; +import { GraphicDataBase } from '../GraphicDataBase'; +import { + ManualAlarmButton, + IManualAlarmButtonData, +} from 'src/graphics/FAS/manualAlarmButton/ManualAlarmButton'; +import { iscsGraphicData } from 'src/protos/iscs_graphic_data'; + +export class ManualAlarmButtonData + extends GraphicDataBase + implements IManualAlarmButtonData +{ + constructor(data?: iscsGraphicData.ManualAlarmButton) { + let cctvButton; + if (data) { + cctvButton = data; + } else { + cctvButton = new iscsGraphicData.ManualAlarmButton({ + common: GraphicDataBase.defaultCommonInfo(ManualAlarmButton.Type), + }); + } + super(cctvButton); + } + + public get data(): iscsGraphicData.ManualAlarmButton { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + clone(): ManualAlarmButtonData { + return new ManualAlarmButtonData(this.data.cloneMessage()); + } + copyFrom(data: ManualAlarmButtonData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: ManualAlarmButtonData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/FAS/SmokeDetectorInteraction.ts b/src/drawApp/graphics/FAS/SmokeDetectorInteraction.ts new file mode 100644 index 0000000..0deb9e8 --- /dev/null +++ b/src/drawApp/graphics/FAS/SmokeDetectorInteraction.ts @@ -0,0 +1,44 @@ +import * as pb_1 from 'google-protobuf'; +import { GraphicDataBase } from '../GraphicDataBase'; +import { + SmokeDetector, + ISmokeDetectorData, +} from 'src/graphics/FAS/smokeDetector/SmokeDetector'; +import { iscsGraphicData } from 'src/protos/iscs_graphic_data'; + +export class SmokeDetectorData + extends GraphicDataBase + implements ISmokeDetectorData +{ + constructor(data?: iscsGraphicData.SmokeDetector) { + let cctvButton; + if (data) { + cctvButton = data; + } else { + cctvButton = new iscsGraphicData.SmokeDetector({ + common: GraphicDataBase.defaultCommonInfo(SmokeDetector.Type), + }); + } + super(cctvButton); + } + + public get data(): iscsGraphicData.SmokeDetector { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + clone(): SmokeDetectorData { + return new SmokeDetectorData(this.data.cloneMessage()); + } + copyFrom(data: SmokeDetectorData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: SmokeDetectorData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/iscsApp.ts b/src/drawApp/iscsApp.ts index 1a4df6d..388ebbb 100644 --- a/src/drawApp/iscsApp.ts +++ b/src/drawApp/iscsApp.ts @@ -35,6 +35,18 @@ import { FasFailureControlHostDraw } from 'src/graphics/FAS/fireFailureControlHo import { FasAlarm, FasAlarmTemplate } from 'src/graphics/FAS/fasAlarm/FasAlarm'; import { FasAlarmData } from './graphics/FAS/FasAlarmInteraction'; import { FasAlarmDraw } from 'src/graphics/FAS/fasAlarm/FasAlarmAssistant'; +import { + ManualAlarmButton, + ManualAlarmButtonTemplate, +} from 'src/graphics/FAS/manualAlarmButton/ManualAlarmButton'; +import { ManualAlarmButtonData } from './graphics/FAS/ManualAlarmButtonInteraction'; +import { ManualAlarmButtonDraw } from 'src/graphics/FAS/manualAlarmButton/ManualAlarmButtonAssistant'; +import { + SmokeDetector, + SmokeDetectorTemplate, +} from 'src/graphics/FAS/smokeDetector/SmokeDetector'; +import { SmokeDetectorData } from './graphics/FAS/SmokeDetectorInteraction'; +import { SmokeDetectorDraw } from 'src/graphics/FAS/smokeDetector/SmokeDetectorAssistant'; // import { getOnlyToken } from 'src/configs/TokenManage'; let drawApp: IDrawApp | null = null; @@ -74,6 +86,14 @@ export function initIscsDrawApp(): IDrawApp { new FasFailureControlHostTemplate(new FasFailureControlHostData()) ); new FasAlarmDraw(app, new FasAlarmTemplate(new FasAlarmData())); + new ManualAlarmButtonDraw( + app, + new ManualAlarmButtonTemplate(new ManualAlarmButtonData()) + ); + new SmokeDetectorDraw( + app, + new SmokeDetectorTemplate(new SmokeDetectorData()) + ); app.addKeyboardListener( new KeyListener({ @@ -242,6 +262,14 @@ export async function loadDrawDatas(): Promise { fasOfPlatformAlarm.fasAlarms.forEach((fasAlarm) => { datas.push(new FasAlarmData(fasAlarm)); }); + fasOfPlatformAlarm.manualAlarmButtons.forEach( + (manualAlarmButton) => { + datas.push(new ManualAlarmButtonData(manualAlarmButton)); + } + ); + fasOfPlatformAlarm.smokeDetectors.forEach((smokeDetector) => { + datas.push(new SmokeDetectorData(smokeDetector)); + }); break; } } @@ -332,6 +360,16 @@ export function saveDrawDatas(app: IDrawApp) { } else if (g instanceof FasAlarm) { const fasAlarmData = g.saveData(); fasStorage.fasAlarms.push((fasAlarmData as FasAlarmData).data); + } else if (g instanceof ManualAlarmButton) { + const manualAlarmButtonData = g.saveData(); + fasStorage.manualAlarmButtons.push( + (manualAlarmButtonData as ManualAlarmButtonData).data + ); + } else if (g instanceof SmokeDetector) { + const smokeDetectorData = g.saveData(); + fasStorage.smokeDetectors.push( + (smokeDetectorData as SmokeDetectorData).data + ); } }); storage.fasOfPlatformAlarmStorages[i] = fasStorage; diff --git a/src/graphics/FAS/fasAlarm/FasAlarmAssistant.ts b/src/graphics/FAS/fasAlarm/FasAlarmAssistant.ts index 285850e..c74259a 100644 --- a/src/graphics/FAS/fasAlarm/FasAlarmAssistant.ts +++ b/src/graphics/FAS/fasAlarm/FasAlarmAssistant.ts @@ -16,12 +16,7 @@ export class FasAlarmDraw extends GraphicDrawAssistant< > { _fasAlarm: FasAlarm | null = null; constructor(app: IDrawApp, template: FasAlarmTemplate) { - super( - app, - template, - 'svguse:../drawIcon.svg#icon-fas-alarm', - '火灾故障控制主机' - ); + super(app, template, 'svguse:../drawIcon.svg#icon-fas-alarm', '警铃'); FasAlarmInteraction.init(app); } diff --git a/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.json b/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.json new file mode 100644 index 0000000..8225724 --- /dev/null +++ b/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.json @@ -0,0 +1,21 @@ +{ + "frames": { + "normal.png": { + "frame": { "x": 0, "y": 0, "w": 26, "h": 24 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 26, "h": 24 }, + "sourceSize": { "w": 26, "h": 24 }, + "anchor": { "x": 0.5, "y": 0.5 } + } + }, + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.1", + "image": "ManualAlarmButton.png", + "format": "RGBA8888", + "size": { "w": 32, "h": 53 }, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:e7620bd2d73cc0b3e2deea9704e7eefc:f129a1d9e4b9ba57720b3861c22b155b:eb2d421f7759984b7713aa4aa5354134$" + } +} diff --git a/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.png b/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.png new file mode 100644 index 0000000..1450d17 Binary files /dev/null and b/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.png differ diff --git a/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.ts b/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.ts new file mode 100644 index 0000000..8a95c46 --- /dev/null +++ b/src/graphics/FAS/manualAlarmButton/ManualAlarmButton.ts @@ -0,0 +1,66 @@ +import { GraphicData, JlGraphic, JlGraphicTemplate } from 'jl-graphic'; +import { Assets, Sprite, Spritesheet, Texture } from 'pixi.js'; +// import { iscsGraphicData } from 'src/protos/iscs_graphic_data'; +import ManualAlarmButtonJson from './ManualAlarmButton.json'; +import ManualAlarmButtonAssets from './ManualAlarmButton.png'; + +export interface IManualAlarmButtonData extends GraphicData { + get code(): string; + set code(v: string); +} + +interface ManualAlarmButtonTextures { + normal: Texture; +} + +export class ManualAlarmButton extends JlGraphic { + static Type = 'ManualAlarmButton'; + _manualAlarmButton: Sprite; + manualAlarmButtonTextures: ManualAlarmButtonTextures; + __state = 0; + + constructor(manualAlarmButtonTextures: ManualAlarmButtonTextures) { + super(ManualAlarmButton.Type); + this._manualAlarmButton = new Sprite(); + this.manualAlarmButtonTextures = manualAlarmButtonTextures; + this._manualAlarmButton.anchor.set(0.5); + this.addChild(this._manualAlarmButton); + this._manualAlarmButton.texture = this.manualAlarmButtonTextures.normal; + } + get code(): string { + return this.datas.code; + } + get datas(): IManualAlarmButtonData { + return this.getDatas(); + } + + doRepaint(): void {} +} + +export class ManualAlarmButtonTemplate extends JlGraphicTemplate { + manualAlarmButtonTextures?: ManualAlarmButtonTextures; + constructor(dataTemplate: IManualAlarmButtonData) { + super(ManualAlarmButton.Type, { dataTemplate }); + this.loadAssets(); + } + new(): ManualAlarmButton { + if (this.manualAlarmButtonTextures) { + const g = new ManualAlarmButton(this.manualAlarmButtonTextures); + g.loadData(this.datas); + return g; + } + throw new Error('资源未加载/加载失败'); + } + async loadAssets(): Promise { + const texture = await Assets.load(ManualAlarmButtonAssets); + const manualAlarmButtonSheet = new Spritesheet( + texture, + ManualAlarmButtonJson + ); + const result = await manualAlarmButtonSheet.parse(); + this.manualAlarmButtonTextures = { + normal: result['normal.png'], + }; + return this.manualAlarmButtonTextures as ManualAlarmButtonTextures; + } +} diff --git a/src/graphics/FAS/manualAlarmButton/ManualAlarmButtonAssistant.ts b/src/graphics/FAS/manualAlarmButton/ManualAlarmButtonAssistant.ts new file mode 100644 index 0000000..edf6d51 --- /dev/null +++ b/src/graphics/FAS/manualAlarmButton/ManualAlarmButtonAssistant.ts @@ -0,0 +1,131 @@ +import { DisplayObject, FederatedMouseEvent, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + IDrawApp, + JlGraphic, +} from 'jl-graphic'; +import { + IManualAlarmButtonData, + ManualAlarmButton, + ManualAlarmButtonTemplate, +} from './ManualAlarmButton'; + +export class ManualAlarmButtonDraw extends GraphicDrawAssistant< + ManualAlarmButtonTemplate, + IManualAlarmButtonData +> { + _manualAlarmButton: ManualAlarmButton | null = null; + constructor(app: IDrawApp, template: ManualAlarmButtonTemplate) { + super( + app, + template, + 'svguse:../drawIcon.svg#icon-manual-alarm-button', + '手动火灾报警按钮' + ); + ManualAlarmButtonInteraction.init(app); + } + + bind(): void { + super.bind(); + if (!this._manualAlarmButton) { + this._manualAlarmButton = this.graphicTemplate.new(); + this.container.addChild(this._manualAlarmButton); + } + } + + public get manualAlarmButton(): ManualAlarmButton { + if (!this._manualAlarmButton) { + this._manualAlarmButton = this.graphicTemplate.new(); + this.container.addChild(this._manualAlarmButton); + } + return this._manualAlarmButton; + } + + redraw(cp: Point): void { + this.manualAlarmButton.position.copyFrom(cp); + } + onLeftUp(e: FederatedMouseEvent): void { + this.manualAlarmButton.position.copyFrom( + this.toCanvasCoordinates(e.global) + ); + this.createAndStore(true); + } + prepareData(data: IManualAlarmButtonData): boolean { + data.transform = this.manualAlarmButton.saveTransform(); + return true; + } + onEsc(): void { + this.finish(); + } +} + +/** + * 构建吸附线 + * @param manualAlarmButton + */ +function buildAbsorbablePositions( + manualAlarmButton: ManualAlarmButton +): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const manualAlarmButtons = + manualAlarmButton.queryStore.queryByType( + ManualAlarmButton.Type + ); + const canvas = manualAlarmButton.getCanvas(); + manualAlarmButtons.forEach((item) => { + if (item.id === manualAlarmButton.id) { + return; + } + const ala = new AbsorbableLine( + new Point(item.x, 0), + new Point(item.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, item.y), + new Point(canvas.width, item.y) + ); + aps.push(ala); + aps.push(alb); + }); + + return aps; +} + +export class ManualAlarmButtonInteraction extends GraphicInteractionPlugin { + static Name = 'manual_alarm_button_transform'; + constructor(app: IDrawApp) { + super(ManualAlarmButtonInteraction.Name, app); + } + static init(app: IDrawApp) { + return new ManualAlarmButtonInteraction(app); + } + filter(...grahpics: JlGraphic[]): ManualAlarmButton[] | undefined { + return grahpics + .filter((g) => g.type === ManualAlarmButton.Type) + .map((g) => g as ManualAlarmButton); + } + bind(g: ManualAlarmButton): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.on('transformstart', this.transformstart, this); + } + unbind(g: ManualAlarmButton): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.off('transformstart', this.transformstart, this); + } + transformstart(e: GraphicTransformEvent) { + const target = e.target as DisplayObject; + const manualAlarmButton = target.getGraphic() as ManualAlarmButton; + manualAlarmButton.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(manualAlarmButton), + }); + } +} diff --git a/src/graphics/FAS/smokeDetector/SmokeDetector.json b/src/graphics/FAS/smokeDetector/SmokeDetector.json new file mode 100644 index 0000000..f3f9546 --- /dev/null +++ b/src/graphics/FAS/smokeDetector/SmokeDetector.json @@ -0,0 +1,21 @@ +{ + "frames": { + "normal.png": { + "frame": { "x": 0, "y": 0, "w": 21, "h": 11 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 21, "h": 11 }, + "sourceSize": { "w": 21, "h": 11 }, + "anchor": { "x": 0.5, "y": 0.5 } + } + }, + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.1", + "image": "SmokeDetector.png", + "format": "RGBA8888", + "size": { "w": 21, "h": 11 }, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:e7620bd2d73cc0b3e2deea9704e7eefc:f129a1d9e4b9ba57720b3861c22b155b:eb2d421f7759984b7713aa4aa5354134$" + } +} diff --git a/src/graphics/FAS/smokeDetector/SmokeDetector.png b/src/graphics/FAS/smokeDetector/SmokeDetector.png new file mode 100644 index 0000000..debcf83 Binary files /dev/null and b/src/graphics/FAS/smokeDetector/SmokeDetector.png differ diff --git a/src/graphics/FAS/smokeDetector/SmokeDetector.ts b/src/graphics/FAS/smokeDetector/SmokeDetector.ts new file mode 100644 index 0000000..5426141 --- /dev/null +++ b/src/graphics/FAS/smokeDetector/SmokeDetector.ts @@ -0,0 +1,63 @@ +import { GraphicData, JlGraphic, JlGraphicTemplate } from 'jl-graphic'; +import { Assets, Sprite, Spritesheet, Texture } from 'pixi.js'; +// import { iscsGraphicData } from 'src/protos/iscs_graphic_data'; +import SmokeDetectorJson from './SmokeDetector.json'; +import SmokeDetectorAsset from './SmokeDetector.png'; + +export interface ISmokeDetectorData extends GraphicData { + get code(): string; + set code(v: string); +} + +interface SmokeDetectorTextures { + normal: Texture; +} + +export class SmokeDetector extends JlGraphic { + static Type = 'SmokeDetector'; + _smokeDetector: Sprite; + smokeDetectorTextures: SmokeDetectorTextures; + __state = 0; + + constructor(smokeDetectorTextures: SmokeDetectorTextures) { + super(SmokeDetector.Type); + this._smokeDetector = new Sprite(); + this.smokeDetectorTextures = smokeDetectorTextures; + this._smokeDetector.anchor.set(0.5); + this.addChild(this._smokeDetector); + this._smokeDetector.texture = this.smokeDetectorTextures.normal; + } + get code(): string { + return this.datas.code; + } + get datas(): ISmokeDetectorData { + return this.getDatas(); + } + + doRepaint(): void {} +} + +export class SmokeDetectorTemplate extends JlGraphicTemplate { + smokeDetectorTextures?: SmokeDetectorTextures; + constructor(dataTemplate: ISmokeDetectorData) { + super(SmokeDetector.Type, { dataTemplate }); + this.loadAssets(); + } + new(): SmokeDetector { + if (this.smokeDetectorTextures) { + const g = new SmokeDetector(this.smokeDetectorTextures); + g.loadData(this.datas); + return g; + } + throw new Error('资源未加载/加载失败'); + } + async loadAssets(): Promise { + const texture = await Assets.load(SmokeDetectorAsset); + const smokeDetectorSheet = new Spritesheet(texture, SmokeDetectorJson); + const result = await smokeDetectorSheet.parse(); + this.smokeDetectorTextures = { + normal: result['normal.png'], + }; + return this.smokeDetectorTextures as SmokeDetectorTextures; + } +} diff --git a/src/graphics/FAS/smokeDetector/SmokeDetectorAssistant.ts b/src/graphics/FAS/smokeDetector/SmokeDetectorAssistant.ts new file mode 100644 index 0000000..b82ec90 --- /dev/null +++ b/src/graphics/FAS/smokeDetector/SmokeDetectorAssistant.ts @@ -0,0 +1,123 @@ +import { DisplayObject, FederatedMouseEvent, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + IDrawApp, + JlGraphic, +} from 'jl-graphic'; +import { + ISmokeDetectorData, + SmokeDetector, + SmokeDetectorTemplate, +} from './SmokeDetector'; + +export class SmokeDetectorDraw extends GraphicDrawAssistant< + SmokeDetectorTemplate, + ISmokeDetectorData +> { + _smokeDetector: SmokeDetector | null = null; + constructor(app: IDrawApp, template: SmokeDetectorTemplate) { + super(app, template, 'svguse:../drawIcon.svg#icon-smoke-detector', '烟感'); + SmokeDetectorInteraction.init(app); + } + + bind(): void { + super.bind(); + if (!this._smokeDetector) { + this._smokeDetector = this.graphicTemplate.new(); + this.container.addChild(this._smokeDetector); + } + } + + public get smokeDetector(): SmokeDetector { + if (!this._smokeDetector) { + this._smokeDetector = this.graphicTemplate.new(); + this.container.addChild(this._smokeDetector); + } + return this._smokeDetector; + } + + redraw(cp: Point): void { + this.smokeDetector.position.copyFrom(cp); + } + onLeftUp(e: FederatedMouseEvent): void { + this.smokeDetector.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + prepareData(data: ISmokeDetectorData): boolean { + data.transform = this.smokeDetector.saveTransform(); + return true; + } + onEsc(): void { + this.finish(); + } +} + +/** + * 构建吸附线 + * @param smokeDetector + */ +function buildAbsorbablePositions( + smokeDetector: SmokeDetector +): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const smokeDetectors = smokeDetector.queryStore.queryByType( + SmokeDetector.Type + ); + const canvas = smokeDetector.getCanvas(); + smokeDetectors.forEach((item) => { + if (item.id === smokeDetector.id) { + return; + } + const ala = new AbsorbableLine( + new Point(item.x, 0), + new Point(item.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, item.y), + new Point(canvas.width, item.y) + ); + aps.push(ala); + aps.push(alb); + }); + + return aps; +} + +export class SmokeDetectorInteraction extends GraphicInteractionPlugin { + static Name = 'smoke_detector_transform'; + constructor(app: IDrawApp) { + super(SmokeDetectorInteraction.Name, app); + } + static init(app: IDrawApp) { + return new SmokeDetectorInteraction(app); + } + filter(...grahpics: JlGraphic[]): SmokeDetector[] | undefined { + return grahpics + .filter((g) => g.type === SmokeDetector.Type) + .map((g) => g as SmokeDetector); + } + bind(g: SmokeDetector): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.on('transformstart', this.transformstart, this); + } + unbind(g: SmokeDetector): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.off('transformstart', this.transformstart, this); + } + transformstart(e: GraphicTransformEvent) { + const target = e.target as DisplayObject; + const smokeDetector = target.getGraphic() as SmokeDetector; + smokeDetector.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(smokeDetector), + }); + } +} diff --git a/src/layouts/IscsDrawLayout.vue b/src/layouts/IscsDrawLayout.vue index 088a095..0e432dc 100644 --- a/src/layouts/IscsDrawLayout.vue +++ b/src/layouts/IscsDrawLayout.vue @@ -308,6 +308,8 @@ import CCTVMonitoring from 'src/components/Iscs/CCTVMonitoring.vue'; import FASPlaneGraph from 'src/components/Iscs/FASPlaneGraph.vue'; import { FasFailureControlHost } from 'src/graphics/FAS/fireFailureControlHost/FasFailureControlHost'; import { FasAlarm } from 'src/graphics/FAS/fasAlarm/FasAlarm'; +import { ManualAlarmButton } from 'src/graphics/FAS/manualAlarmButton/ManualAlarmButton'; +import { SmokeDetector } from 'src/graphics/FAS/smokeDetector/SmokeDetector'; const $q = useQuasar(); const route = useRoute(); @@ -394,6 +396,8 @@ function handleUtilsOption() { case '火灾报警平面图': drawAssistantsTypes.push(FasFailureControlHost.Type); drawAssistantsTypes.push(FasAlarm.Type); + drawAssistantsTypes.push(ManualAlarmButton.Type); + drawAssistantsTypes.push(SmokeDetector.Type); break; } drawAssistantsTypes.forEach((type) => {