<template>
    <div class="basePlan" id="basePlan" ref="basePlan">
        <planTooltip
            v-show="showTooltip"
            class="planTooltip-box"
            ref="planTooltip"
            @closeTooltip="showTooltip = false"
            :havItem="havItem"
            :contextMenuItem="contextMenuItem"
        ></planTooltip>
        <!-- 加载中 -->
        <div v-loading="planLoading" class="plan-loading" element-loading-text="平面图加载中"></div>
        <canvas style="border: none; outline: medium" id="persagy_plan" :width="canvasWidth" :height="canvasHeight" tabindex="0"></canvas>
    </div>
</template>
<script>
import { SFloorParser, getJsonz } from "@persagy-web/big";
import { SImageItem, SImageShowType, SGraphPropertyCommand } from "@persagy-web/graph";
import { SPlanView, SPlanParser, SPlanScene, SPlanDecorator, SPlanEquipment, SPlanZone } from "@/lib";
import planTooltip from "./planTooltip.vue";
import { mapState, mapMutations } from "vuex";
import base64ToFile from "@/utils/base64ToFile";
import { v1 as uuidv1 } from "uuid";
import bus from "@/bus/bus";
import { planerSave, planerRead, planerPublish } from "@/api/labsl";
import { equipQuery, spaceQuery } from "@/api/equipcomponent";
import { imgBaseUrl } from "@/api/imageservice";
export default {
    components: { planTooltip },
    data() {
        return {
            scene: null, //场景
            view: null, //视图
            canvasWidth: 700, //画布宽
            canvasHeight: 700, //画布高
            havItem: false, //右击是否选中item
            contextMenuItem: null, // 右键选中的item
            showTooltip: false, //是否显示tooltip
            planContent: {}, // 读图后存储图所有数据
            autoSave: null, // 自动保存定时器
            ruleNum: 0, //规则数量
            loadedRuleNum: 0, //已加载规则数量
            baseMapStyle: {
                // 底图样式
                default: {
                    strokeColor: "#F0F3F7",
                    fillColor: "#F0F3F7",
                    lineWidth: 1,
                    effect: {},
                },
            },
            changeScaleByClick: false, //区分滚轮，点击 事件改变的缩放比例
            initScale: 1,
            planLoading: true, //平面图顶部loading提示
            parser: null, //底图解析后的数据
            isInitSave:false, //初始化保存
        };
    },
    computed: {
        ...mapState([
            "editCmd",
            "legendObj",
            "graphId",
            "id",
            "projectId",
            "floorMap",
            "equipItemMap",
            "zoneIteMap",
            "buildingId",
            "floorId",
            "folderId",
            "objExtInfo",
            "styleMap",
            "ruleList",
            "version",
            "outline",
        ]),
    },
    mounted() {
        window.vim = this;

        // 如果为新建图、默认加载后保存使之生成缩略图
        if(this.$route.query.version == "1.0.1"){
           this.isInitSave = true
        }else {
            this.isInitSave = false
        }
        // 获取 canvas 的宽高
        this.canvasWidth = this.$refs.basePlan.offsetWidth;
        this.canvasHeight = this.$refs.basePlan.offsetHeight - 10;
        // 初始化场景类
        this.view = new SPlanView("persagy_plan");
        if (this.scene) this.view.scene = this.scene;
        this.init();

        // 初始化bus绑定事件
        this.initBusEvent();

        // 右键事件
        this.scene.getItem = this.onContextMenu;
        this.scene.emitChoice = this.emitChoice;

        //左键事件
        this.scene.vueOnMouseDown = this.vueOnMouseDown;

        // 屏蔽浏览器右键功能（防止与编辑器右键交互重合）
        document.getElementById("basePlan").oncontextmenu = function (e) {
            return false;
        };

        // 2分钟自动保存
        this.autoSave = setInterval(() => {
            this.autoSavePlan();
        }, 120000);
        // 页面销毁前,清除定时器
        this.$once("hook:beforeDestroy", () => {
            clearInterval(this.autoSave);
        });
    },
    methods: {
        ...mapMutations([
            "SETCHOICELEHEND",
            "SETLEGENDOBJ",
            "SETPROJECT",
            "SETVERSION",
            "ADDEQUIP",
            "REMOVEEQUIP",
            "ADDZONE",
            "REMOVEZONE",
            "DELETEITEM",
            "INITSTYLE",
            "INITRULELIST",
            "INITOBJEXTINFO",
            "ADDSTYLE",
            "SETOUTLINE",
            "DELETESTYLE",
        ]),

        // 清空画布
        clearImg() {
            this.scene = new SPlanScene();
            this.scene.imgServeUrl = imgBaseUrl;
            this.scene.emitChoice = this.emitChoice;
            this.scene.clearCmdStatus = this.clearCmdStatus;
            this.scene.vueOnMouseDown = this.vueOnMouseDown;
            this.scene.maskFinishCreated = this.maskFinishCreated;
            if (this.view) {
                this.view.update();
            }
        },
        /**
         * 区域显示的蒙板创建完成之后,存放vuex
         */
        maskFinishCreated(SBaseMaskEdit) {
            this.SETOUTLINE(SBaseMaskEdit);
        },
        // 初始化
        init() {
            this.clearImg();
            this.view ? (this.view.scene = this.scene) : null;
            // 读取平面图数据
            this.readPlanMsg().then((showBaseMap) => {
                // 判断是否有楼层底图，有则获取数据并解析
                if (this.floorMap) this.getMapBlob(showBaseMap);
            });
        },
        // 请求获取地图的压缩包
        getMapBlob(showBaseMap) {
            if (this.floorMap.includes("png") || this.floorMap.includes("jpg")) {
                const url = `/image-service/common/image_get?systemId=dataPlatform&key=${this.floorMap}`;
                this.getImage(url);
            } else {
                const url = `/image-service/common/file_get?systemId=revit&key=${this.floorMap}`;
                getJsonz(url).then((data) => {
                    // 解析数据并放入压缩包中
                    this.parserData(data, showBaseMap);
                });
            }
        },
        // 获取图片
        getImage(url) {
            const imgItem = new SImageItem(null, url);
            imgItem.showType = SImageShowType.AutoFit;
            imgItem.connect("imgLoadOver", this, () => {
                // 画板是否可拖动;
                this.scene.addItem(imgItem);
                this.view.DragMove = true;
                this.view.fitSceneToView();
                // 接口无规则字段时,在底图加载完成后关闭loading
                if (!this.planContent?.ruleList) {
                    this.planLoading = false;
                }
            });
        },
        // 解析数据并注入 scene 类中
        parserData(data, showBaseMap) {
            // 修改 vuex 底图显隐
            this.ADDSTYLE({
                id: "defaultMapStyle",
                style: {
                    ...this.styleMap.defaultMapStyle,
                    showBaseMap, //显隐值
                },
            });
            const parser = new SFloorParser();
            parser.parseData(data);
            this.parser = parser;
            parser.spaceList.forEach((t) => {
                //是否显示空间
                // t.visible = this.isSpaceSelectable;
                t.visible = showBaseMap;
                //设置样式
                Object.assign(t, this.baseMapStyle.default);
                //是否展示名称
                // t.showBaseName = true;
                // 是否可选
                t.selectable = false;
                // t.connect("onMouseDown", this, this.clickSpaceItem);

                // 添加图例
                this.scene.addItem(t);
            });
            parser.wallList.forEach((t) => {
                // 是否显示
                // t.visible = this.isShowWall;
                t.visible = showBaseMap;
                // 是否可选
                t.selectable = false;
                this.scene.addItem(t);
            });
            // parser.virtualWallList.forEach((t) => {
            //     // 是否显示
            //     // t.visible = this.isShowVirtualWall;
            //     t.visible = showBaseMap;
            //     // 是否可选
            //     t.selectable = false;
            //     this.scene.addItem(t);
            // });
            // parser.doorList.forEach((t) => {
            //     // 是否显示
            //     // t.visible = this.isShowDoor;
            //     t.visible = showBaseMap;
            //     // 是否可选
            //     t.selectable = false;
            //     this.scene.addItem(t);
            // });
            // parser.columnList.forEach((t) => {
            //     // 是否显示
            //     // t.visible = this.isShowColumn;
            //     t.visible = showBaseMap;
            //     // 是否可选
            //     t.selectable = false;
            //     this.scene.addItem(t);
            // });
            // parser.casementList.forEach((t) => {
            //     // 是否显示
            //     // t.visible = this.isShowWindow;
            //     t.visible = showBaseMap;
            //     // 是否可选
            //     t.selectable = false;
            //     this.scene.addItem(t);
            // });
            // 画板是否可拖动
            this.view.DragMove = true;
            this.view.fitSceneToView();
            // 接口无规则字段时,在底图加载完成后关闭loading
            // 加载完，如果符合条件，则走自动保存
            if(this.isInitSave){
                this.savePlanDraft();
            }
            if (!this.planContent?.ruleList) {
                this.planLoading = false;
            }
            // 设置初始化缩放比例
            this.initScale = this.view.scale;
            bus.$emit("initScale", this.view.scale);
        },

        // 恢复命令状态
        clearCmdStatus() {
            this.SETCHOICELEHEND("");
            this.SETLEGENDOBJ(null);
        },
        // 右键获取item
        onContextMenu(item, [event]) {
            this.showTooltip = true;
            if (item) {
                this.havItem = true;
                this.contextMenuItem = item;
            } else {
                this.havItem = false;
                this.contextMenuItem = null;
            }
            const doms = document.getElementsByClassName("planTooltip-box")[0];
            doms.style.left = event.offsetX + "px";
            doms.style.top = event.offsetY + "px";
        },
        // 左键事键
        vueOnMouseDown(e) {
            //  关闭tooltip
            this.showTooltip = false;
        },
        // 选中后的回调函数
        emitChoice(itemList) {
            bus.$emit("emitChoice", itemList);
        },
        //初始化bus绑定事件
        initBusEvent() {
            // 属性入栈
            bus.$off("undoAttr");
            bus.$on("undoAttr", (item, styletype, oldMsg, newMsg) => {
                this.scene.undoStack.push(new SGraphPropertyCommand(this.scene, item, styletype, oldMsg, newMsg));
            });
            // 改变样式
            bus.$off("updateStyle");
            bus.$on("updateStyle", (type, val) => {
                this.scene.updateStyle(type, val);
            });
            // 撤销
            bus.$off("planUndo");
            bus.$on("planUndo", (val) => {
                this.scene.undo();
            });
            // 重做
            bus.$off("planRedo");
            bus.$on("planRedo", (val) => {
                this.scene.redo();
            });
            // 删除
            bus.$off("deleteItem");
            bus.$on("deleteItem", (val) => {
                this.scene.deleteItem([val]);
                this.DELETEITEM();
            });
            // 复制
            bus.$off("copy");
            bus.$on("copy", (val) => {
                this.scene.copy();
            });
            // 粘贴
            bus.$off("paste");
            bus.$on("paste", (val) => {
                this.scene.paste();
            });
            // 保存
            bus.$off("savePlan");
            bus.$on("savePlan", (val) => {
                this.savePlanDraft();
            });
            // 设置实例置顶置底
            bus.$off("setOrder");
            bus.$on("setOrder", (val) => {
                this.scene.setItemOrder(val);
            });
            // 设置实例status状态
            bus.$off("setItemStatus");
            bus.$on("setItemStatus", (val) => {
                this.scene.setItemStatus();
            });
            // 下载图片
            bus.$off("savePlanImg");
            bus.$on("savePlanImg", () => {
                // 隐藏选择器
                this.scene.selectContainer.clear();
                this.view.saveImageSize(`${this.planContent.name}.png`, "png", this.canvasWidth, this.canvasHeight, this.view.backgroundColor.value);
            });
            // 发布图片
            bus.$off("issuePlan");
            bus.$on("issuePlan", () => {
                this.savePlanDraft().then(() => {
                    this.issueDraft();
                });
            });
            // 手动添加设备实例
            bus.$off("addEquipment");
            bus.$on("addEquipment", (equipList) => {
                this.mergeEquipData(equipList);
            });
            // 手动删除设备实例
            bus.$off("removeEquipment");
            bus.$on("removeEquipment", (classCode, delClassCode) => {
                this.removeEquipment(classCode, delClassCode);
            });
            // 手动添加空间实例
            bus.$off("addZone");
            bus.$on("addZone", (zoneList) => {
                this.mergeZoneData(zoneList);
            });
            // 手动删除空间实例
            bus.$off("removeZone");
            bus.$on("removeZone", (classCode, delClassCode) => {
                this.removeZone(classCode, delClassCode);
            });
            // 更改设备信息点
            bus.$off("changeEquipMsgPoint");
            bus.$on("changeEquipMsgPoint", (val) => {
                this.scene.changeEquipMsgPoint(val);
            });
            // 选中item
            bus.$off("chioceItem");
            bus.$on("chioceItem", (item) => {
                this.scene.toggleItem(item);
            });
            // 比例缩放
            bus.$off("scale");
            bus.$on("scale", (newV, oldV) => {
                this.changeScaleByClick = true;
                this.view.scaleByPoint(newV / oldV, this.canvasWidth / 2, this.canvasHeight / 2);
                this.changeScaleByClick = false;
            });
            // 更改对齐方式
            bus.$off("changeAlignItem");
            bus.$on("changeAlignItem", (val) => {
                this.scene.changeAlignItem(val);
            });
            // 底图显隐
            bus.$off("showBaseMap");
            bus.$on("showBaseMap", (val) => {
                this.showBaseMapFn(val);
            });

            // 取消区域显示
            bus.$off("deleteOutline");
            bus.$on("deleteOutline", () => {
                this.scene.removeItem(this.outline);
                this.scene.selectContainer.clear();
                this.view.update();
                this.SETOUTLINE(null);
            });
            // 更改背景色
            bus.$off("changeBackgroundColor");
            bus.$on("changeBackgroundColor", (val) => {
                this.changeBackgroundColor(val);
            });
        },
        // 更改底图背景色
        changeBackgroundColor(backgroundColor) {
            // 更新 vuex 中 styleMap 下 defaultMapStyle 的 backgroundColor 值
            this.ADDSTYLE({
                id: "defaultMapStyle",
                style: {
                    ...this.styleMap.defaultMapStyle,
                    backgroundColor, //背景色
                },
            });
            this.scene.changeBackgroundColor(backgroundColor);
        },
        // 是否显示底图
        showBaseMapFn(val) {
            // 更新 vuex 中 styleMap 下 defaultMapStyle 的 showBaseMap 值
            this.ADDSTYLE({
                id: "defaultMapStyle",
                style: {
                    ...this.styleMap.defaultMapStyle,
                    showBaseMap: val, //显隐值
                },
            });
            const { parser } = this;
            parser.spaceList.forEach((t) => {
                //是否显示空间
                t.visible = val;
            });
            parser.wallList.forEach((t) => {
                t.visible = val;
            });
            parser.virtualWallList.forEach((t) => {
                t.visible = val;
            });
            parser.doorList.forEach((t) => {
                t.visible = val;
            });
            parser.columnList.forEach((t) => {
                t.visible = val;
            });
            parser.casementList.forEach((t) => {
                t.visible = val;
            });
            if (this.view?.scene) this.view.fitSceneToView();
            // 设置初始化缩放比例
            this.initScale = this.view.scale;
            bus.$emit("initScale", this.view.scale);
        },
        // 读取拓扑图
        readPlanMsg() {
            const obj = {
                graphId: this.graphId,
                id: this.id,
            };
            return new Promise((resolve, reject) => {
                planerRead(obj).then((res) => {
                    // resolve 是否显示底图,供 parserData 使用
                    if (res?.content?.style?.defaultMapStyle?.showBaseMap === false) {
                        resolve(false);
                    } else {
                        resolve(true);
                    }
                    this.getDataSuc(res);
                });
            });
        },
        // 读图成功回调
        async getDataSuc(res) {
            if (res.result == "failure") return;
            this.SETPROJECT(res.content);
            this.planContent = res.content;
            // 初始化对象实例信息
            if (res.content.elements.objExtInfo?.length) {
                const objExtInfo = {};
                if (res.content.elements.objExtInfo?.length) {
                    res.content.elements.objExtInfo.forEach((item) => {
                        if (item?.properties?.id) objExtInfo[item.properties.id] = item;
                    });
                }
                this.INITOBJEXTINFO(objExtInfo);
            }
            // 初始化样式信息
            if (res.content.style) {
                // 拼接设备默认样式
                this.INITSTYLE(res.content.style);
            } else {
                this.INITSTYLE({});
            }
            // 底图背景颜色
            if (this.scene) {
                const backgroundColor = res.content.style?.defaultMapStyle?.backgroundColor
                    ? res.content.style?.defaultMapStyle?.backgroundColor
                    : "#00000000";
                this.changeBackgroundColor(backgroundColor);
                // 初始化保存图背景色
            }
            // 加载规则，显示实例数据
            if (res.content.ruleList?.length) {
                this.INITRULELIST(res.content.ruleList);
                this.ruleNum = res.content.ruleList.length;

                const ruleList = res.content.ruleList;
                // 同步执行规则,进行设备/设备组/空间的添加,删除
                for (let index = 0; index < ruleList.length; index++) {
                    const rule = ruleList[index];
                    // 查询规则
                    if (rule.commond && rule.commond === "query") {
                        const params = { ...rule.params, buildingId: this.buildingId, floorId: this.floorId };
                        if (rule?.returnType === "equip") {
                            const res = await equipQuery(params);
                            if (res.result === "success") this.mergeEquipData(res.content);
                        } else if (rule?.returnType === "zone") {
                            const res = await spaceQuery(params);
                            if (res.result === "success") this.mergeZoneData(res.content);
                        } else if (rule?.returnType === "equipGroup") {
                            console.error("请求设备组数据");
                            this.loadedRuleNum++;
                            if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
                        }
                    } else if (rule.commond && rule.commond === "delete") {
                        // 删除规则
                        // console.error("删除命令！！！", rule);
                        // 删除设备实例
                        if (rule?.returnType === "equip") {
                            const classCode = rule?.params?.classCode;
                            if (classCode) {
                                this.removeEquipment(classCode);
                            }
                        } else if (rule?.returnType === "zone") {
                            // 删除空间实例
                            const classCode = rule?.params?.classCode;
                            if (classCode) {
                                this.removeZone(classCode);
                            }
                        } else if (rule?.returnType === "equipGroup") {
                            // 删除设备组
                            //
                            this.loadedRuleNum++;
                            if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
                        }
                    }

                }
            } else {
                this.INITRULELIST([]);
                if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
            }

            // 加载区域显示
            if (res.content.outline) {
                const outline = res.content.outline;
                const item = this.scene.initMaskItem(outline);
                this.SETOUTLINE(item);
            }
        },
        // 解析设备数据
        mergeEquipData(equipList) {
            equipList.forEach((equip) => {

                if (!this.equipItemMap[equip.id]) {
                    if (this.objExtInfo[equip.id]) {
                        equip = { ...this.objExtInfo[equip.id], ...equip };
                    }
                    if (!equip.pos) {
                        //如果未维护设备在图中的坐标
                        if (equip.locationJson) {
                            // 判断设备是否维护BIM坐标
                            const { x, y, z } = equip.locationJson;
                            equip.pos = { x, y: -y, z };
                        } else {
                            // 否则显示默认坐标位置
                            equip.pos = { x: 0, y: 0, z: 0 };
                        }
                    }
                    // 添加设备对象类型
                    equip.properties = { type: "BaseEquipment" };
                    const equipItem = new SPlanEquipment(null, equip);
                    equipItem.visible = Boolean(equipItem.legendData.bimLocation);
                    // equipItem.connect("finishCreated", this.scene, this.scene.finishCreated);
                    equipItem.connect("onContextMenu", this, this.scene.getItem);
                    // console.log(equip.classCode, equip.codeName);
                    // TODO: 设备样式
                    const equipStyle = window.__systemConf.equipStyle;
                    // 使用设备自身的样式
                    if (this.styleMap[equip.id]) {
                        SPlanDecorator.equipDecorator(equipItem, this.styleMap[equip.id]);
                    } else if (this.styleMap[equip.classCode]) {
                        // 使用自身设备类的样式
                        SPlanDecorator.equipDecorator(equipItem, this.styleMap[equip.classCode]);
                    } else if (equipStyle[equip.classCode]) {
                        // 使用配置文件中的设备类样式
                        SPlanDecorator.equipDecorator(equipItem, equipStyle[equip.classCode]);
                    } else {
                        // 使用配置文件中的默认样式
                        SPlanDecorator.equipDecorator(equipItem, equipStyle["defaultEquipStyle"]);
                    }
                    this.scene.addItem(equipItem);
                    this.ADDEQUIP(equipItem);
                }
            });
            this.loadedRuleNum++;
            if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
        },
        /**
         * 删除设备实例
         *
         * @param { string }  classCode 删除的设备类code值
         * @param { string }  delClassCode 是否删除的设备类的样式值
         */
        removeEquipment(classCode, delClassCode = false) {
            for (const key in this.equipItemMap) {
                const equipItem = this.equipItemMap[key];
                if (equipItem?.legendData?.classCode === classCode) {
                    // 删除vuex中保存的设备实例
                    this.REMOVEEQUIP(equipItem);
                    // 删除图上的设备实例
                    this.scene.removeItem(equipItem);
                    // 点击左侧列表删除设备类,触发删除 vuex 设备类样式
                    if (delClassCode) {
                        this.DELETESTYLE(equipItem?.legendData?.id);
                    }
                }
            }
            // 点击左侧列表删除设备类,触发删除 vuex 设备类样式
            if (delClassCode) {
                this.DELETESTYLE(classCode);
            }
            this.view.update();
            this.loadedRuleNum++;
            if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
        },
        // 解析空间数据
        mergeZoneData(zoneList) {
            zoneList.forEach((zone) => {
                if (!this.zoneIteMap[zone.id]) {
                    if (this.objExtInfo[zone.id]) {
                        zone = { ...this.objExtInfo[zone.id], ...zone };
                    }
                    // 添加设备对象类型
                    zone.properties = { type: "BaseZone" };
                    const zoneItem = new SPlanZone(null, zone);
                    zoneItem.visible = Boolean(zoneItem.legendData.outline);
                    // zoneItem.connect("finishCreated", this.scene, this.scene.finishCreated);
                    zoneItem.connect("onContextMenu", this, this.scene.getItem);
                    // TODO: addItem 需要写在 zoneDecorator 修饰器前,保证在 SPlanZone中能使用 this.scene.view.scale
                    this.scene.addItem(zoneItem);
                    if (this.styleMap[zone.id]) {
                        SPlanDecorator.zoneDecorator(zoneItem, this.styleMap[zone.id]);
                    } else if (this.styleMap[zone.classCode]) {
                        SPlanDecorator.zoneDecorator(zoneItem, this.styleMap[zone.classCode]);
                    } else {
                        SPlanDecorator.zoneDecorator(zoneItem, this.styleMap["defaultZoneStyle"]);
                    }
                    this.ADDZONE(zoneItem);
                }
            });
            this.loadedRuleNum++;
            if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
        },
        /**
         * 删除空间实例
         *
         * @param { string }  classCode 删除的空间类code值
         * @param { string }  delClassCode 是否删除的设备类的样式值
         */
        removeZone(classCode, delClassCode = false) {
            for (const key in this.zoneIteMap) {
                const zoneItem = this.zoneIteMap[key];
                if (zoneItem?.legendData?.classCode === classCode) {
                    // 删除vuex中保存的空间实例
                    this.REMOVEZONE(zoneItem);
                    // 删除图上的空间实例
                    this.scene.removeItem(zoneItem);
                    //  点击左侧列表删除空间类,触发删除 vuex 空间类样式
                    if (delClassCode) {
                        this.DELETESTYLE(zoneItem?.legendData?.id);
                    }
                }
            }
            // 点击左侧列表删除空间类,触发删除 vuex 设备类样式
            if (delClassCode) {
                this.DELETESTYLE(classCode);
            }
            this.view.update();
            this.loadedRuleNum++;
            if (this.ruleNum === this.loadedRuleNum) this.loadMarkRelation();
        },
        // 加载通用元素和管线元素
        loadMarkRelation() {
            const anchorList = []; //保存锚点对象
            const parse = new SPlanParser();
            parse.parseData(this.planContent.elements);
            parse.markers.forEach((item) => {
                item.selectable = true;
                item.moveable = true;
                item.connect("finishCreated", this.scene, this.scene.finishCreated);
                item.connect("onContextMenu", this, this.scene.getItem);
                // 判断如果是图，需要拼接路径
                if (item.data.properties.type == "BaseImage") {
                    item.showSelect = false;
                    item.isTransform = false;
                    if (item.data.style?.default?.url) {
                        item.url = imgBaseUrl + item.data.style.default.url;
                    }
                }
                // 背景图片, 拼接路径
                if (item.data.properties.type == "BgImage") {
                    if (item.data.style?.default?.url) {
                        item.url = imgBaseUrl + item.data.style.default.url;
                    }
                }
                this.scene.addItem(item);
            });
            // 管线元素最后添加
            parse.relations.forEach((t) => {
                // 设置锚点
                if (t.anchor1Id) {
                    let startAnc = null;
                    anchorList.forEach((aItem) => {
                        if (aItem.id == t.anchor1Id) {
                            startAnc = aItem;
                        }
                    });

                    if (startAnc) {
                        startAnc.isConnected = true;
                        startAnc.parent?.connect("changePos", t, t.changePos);
                        t.startAnchor = startAnc || null;
                        console.log("startAnc", startAnc);
                    }
                }
                if (t.anchor12d) {
                    let endAnc = null;
                    anchorList.forEach((aItem) => {
                        if (aItem.id == t.anchor12d) {
                            endAnc = aItem;
                        }
                    });
                    if (endAnc) {
                        endAnc.isConnected = true;
                        endAnc.parent?.connect("changePos", t, t.changePos);
                        t.endAnchor = endAnc || null;
                    }
                }
                t.showSelect = false;
                t.connect("finishCreated", this.scene, this.scene.finishCreated);
                t.connect("onContextMenu", this, this.scene.getItem);
                this.scene.addItem(t);
            });
            if (this.view?.scene) this.view.fitSceneToView();
            // 接口有规则字段时,在使用rule接口查询,删除设备/空间后, 关闭loading
            if (this.planContent?.ruleList) {
                this.planLoading = false;
            }
            // 设置初始化缩放比例
            this.initScale = this.view.scale;
            bus.$emit("initScale", this.view.scale);
        },
        // 生成快照并保存草稿
        savePlanDraft() {
            const uuid = uuidv1();
            return Promise.all([this.generateSnap(uuid), this.saveDraft(uuid)])
                .then((vals) => {
                    // 重设版本号
                    if (vals[1].version && vals[1].id && vals[1].graphId) {
                        this.SETPROJECT(vals[1]);
                        this.$message.success(`保存成功`);
                        // ${vals[1].version}
                        const { folderId, folderName, buildingId, floorId, floorLocalName, name, floorMap } = this.$route.query;
                        this.$router.replace({
                            name: "Editer",
                            query: {
                                folderId,
                                folderName,
                                buildingId,
                                floorId,
                                floorLocalName,
                                name,
                                floorMap,
                                id: vals[1].id,
                                graphId: vals[1].graphId,
                                version: vals[1].version,
                                projectId:this.projectId
                            },
                        });
                    } else {
                        console.error(`保存图接口缺少返回参数！`);
                    }
                })
                .catch((msg) => {
                    this.$message.error(msg);
                });
        },
        // 生成快照
        generateSnap(uuid) {
            // 隐藏选择器
            this.scene.selectContainer.clear();
            setTimeout(() => {
                // base64数据
                const data = this.view.imageUrl("png");
                // 根据base64生成file
                const file = base64ToFile(data);
                const reader = new FileReader();
                const fileType = file.name.split(".");
                const imgType = fileType[fileType.length - 1];
                return new Promise((resolve, reject) => {
                    reader.onloadend = function () {
                        // 这个事件在读取结束后，无论成功或者失败都会触发
                        if (reader.error) {
                            console.log("reader error", reader.error);
                            reject(reader.error);
                        } else {
                            // 构造 XMLHttpRequest 对象，发送文件 Binary 数据
                            const xhr = new XMLHttpRequest();
                            xhr.open(
                                "POST",
                                `/image-service/common/image_upload?systemId=dataPlatform&secret=9e0891a7a8c8e885&overwrite=true&key=${uuid}.${imgType}`
                            );
                            xhr.send(reader.result);
                            xhr.onreadystatechange = function () {
                                if (xhr.readyState == 4) {
                                    if (xhr.status == 200) {
                                        resolve(xhr);
                                    }
                                }
                            };
                        }
                    };
                    reader.readAsArrayBuffer(file);
                });
            }, 80);
        },
        // 保存草稿
        saveDraft(uuid) {
            const { elements, outline } = this.scene.save();
            const { id, graphId, name, buildingId, floorId, folderId, state, projectId, label = [], note = "" } = this.planContent;
            const obj = {
                elements, // 平面图展示所需数据
                id, //图编号
                graphId, // 图 id
                name, // 名称
                folderId, // 文件夹 id
                projectId, // 项目id
                label, // 图标签
                buildingId, // 建筑 id
                floorId, // 楼层 id
                state, // 标记
                note, // 图说明
                style: this.styleMap, // 样式库
                ruleList: this.ruleList, // 实例数据获取规则
                pic: `${uuid}.png`, // 图快照
                version: this.version, // 版本号
                viewBackground: this.view.backgroundColor.value, //视图背景色
            };
            // 区域显示时,上送区域显示的outline点坐标数组
            if (outline) {
                obj.outline = outline;
            }
            return new Promise((resolve, reject) => {
                planerSave(obj).then((res) => {
                    if (res.result === "success") {
                        resolve(res.entityList[0]);
                    } else {
                        reject(res.message);
                    }
                });
            });
        },
        // 自动保存
        autoSavePlan() {
            if (this.scene && this.scene.undoStack.isChange) {
                this.savePlanDraft().then(() => {
                    this.scene.undoStack.isChange = false;
                });
            }
        },
        // 发布草稿
        issueDraft() {
            const pa = {
                graphId: this.graphId,
                id: this.id,
            };
            planerPublish(pa)
                .then((res) => {
                    if (res.result === "success") {
                        this.$message.success(`发布成功${res.entityList[0].version}`);
                        console.log(this.folderId);
                        this.$router.push({ name: "Home", params: { folderId: this.folderId } });
                    } else {
                        this.$message.error(`发布失败！失败原因：${res.message}`);
                    }
                })
                .catch((error) => {
                    this.$message.error(`发布失败！失败原因：${error}`);
                });
        },
    },
    watch: {
        editCmd(val) {
            // console.trace(val);
            if (this.scene) {
                // 设置当前编辑状态
                this.scene.editCmd = val;
            }
        },
        legendObj: {
            handler: function (val, oldVal) {
                this.scene.legendObj = val;
            },
            deep: true,
        },
        // 监听scale的变化
        "view.scale": {
            handler(scale) {
                // 滚轮触发的缩放
                if (!this.changeScaleByClick) {
                    bus.$emit("mouseScale", scale / this.initScale);
                }
            },
        },
    },
    beforeDestroy() {
        clearInterval(this.autoSave);
    },
};
</script>
<style lang="less" scoped>
.basePlan {
    width: 100%;
    height: 100%;
    position: relative;
    .planTooltip-box {
        position: absolute;
        left: 0;
        top: 0;
    }
    .plan-loading {
        position: absolute !important;
        top: 10px;
        left: 50%;
        width: 200px;
        height: 50px;
        z-index: 9;
        transform: translateX(-50%);
        /deep/ .el-loading-mask {
            border-radius: 3px;
            background-color: #edf2fc;
            .el-loading-spinner {
                display: flex;
                align-items: center;
                justify-content: center;
                margin-top: 0 !important;
                transform: translateY(-50%) !important;
                svg {
                    width: 20px;
                    height: 20px;
                    margin-right: 10px;
                    circle {
                        stroke: #909399;
                    }
                }
                .el-loading-text {
                    color: #909399;
                }
            }
        }
    }
}
</style>