Browse Source

Merge branch 'develop' of git.sagacloud.cn:web/wanda-editer into develop

zhangyu 4 years ago
parent
commit
fa2b47fcc8
38 changed files with 4356 additions and 908 deletions
  1. 4 3
      package.json
  2. 19 0
      src/api/editer.js
  3. BIN
      src/assets/images/copy.png
  4. BIN
      src/assets/images/iconBlackBottom.png
  5. BIN
      src/assets/images/iconBlackTop.png
  6. BIN
      src/assets/images/iconLightBottom.png
  7. BIN
      src/assets/images/iconLightTop.png
  8. BIN
      src/assets/images/past.png
  9. BIN
      src/assets/images/selectSimilar.png
  10. 150 64
      src/components/baseEditer.vue
  11. 247 107
      src/components/edit/attr_select.vue
  12. 1381 0
      src/components/edit/edit-dialog-tree.vue
  13. 779 125
      src/components/edit/edit-dialog.vue
  14. 233 0
      src/components/edit/floorList.vue
  15. 53 40
      src/components/edit/left_toolbar.vue
  16. 59 25
      src/components/edit/right_toolbar.vue
  17. 662 442
      src/components/edit/top_toolbar.vue
  18. 330 81
      src/components/mapClass/EditScence.ts
  19. 2 0
      src/components/mapClass/SGraphAddListCommand.ts
  20. 3 0
      src/components/mapClass/SGraphDeleteCommand.ts
  21. 3 0
      src/components/mapClass/SGraphDeleteListCommand.ts
  22. 0 1
      src/components/urlMsg.js
  23. 230 0
      src/directives/dom.js
  24. 24 0
      src/directives/repeat-click.js
  25. 2 1
      src/lib/items/SCustomLegendItem.ts
  26. 2 1
      src/lib/items/SFHFQZoneLegendItem.ts
  27. 12 1
      src/lib/items/SImageLegendItem.ts
  28. 12 0
      src/lib/items/SImageMarkerItem.ts
  29. 12 0
      src/lib/items/SLineLegendItem.ts
  30. 16 2
      src/lib/items/SLineMarkerItem.ts
  31. 2 1
      src/lib/items/SSCPZZoneLegendItem.ts
  32. 22 0
      src/lib/items/STextMarkerItem.ts
  33. 2 1
      src/lib/items/SZoneLegendItem.ts
  34. 6 3
      src/lib/items/TipelineItem.ts
  35. 16 1
      src/store/index.ts
  36. 28 5
      src/views/drafts.vue
  37. 43 2
      src/views/editer.vue
  38. 2 2
      vue.config.js

+ 4 - 3
package.json

@@ -9,11 +9,12 @@
   },
   "dependencies": {
     "@saga-web/base": "2.1.27",
-    "@saga-web/big": "1.0.111",
+    "@saga-web/big": "1.0.113",
     "@saga-web/draw": "2.1.107",
-    "@saga-web/feng-map": "1.0.44",
-    "@saga-web/graph": "2.1.124",
+    "@saga-web/feng-map": "1.0.47",
+    "@saga-web/graph": "2.1.126",
     "ant-design-vue": "^1.6.0",
+    "axios": "^0.19.2",
     "core-js": "^3.6.4",
     "element-ui": "^2.13.2",
     "meri-design": "^1.2.9",

+ 19 - 0
src/api/editer.js

@@ -112,4 +112,23 @@ export function deleteByCategory(params){
 // 推荐
 export function graphElementOrderInfoLocal(params){
     return httputils.getJson(`${testApi}/graphElement/orderInfoLocal`, params)
+}
+// 查询图
+export function graphQuery(params){
+    return httputils.postJson(`${testApi}/graph/query`, params)
+}
+
+// 查询图例绑定的楼层
+export function queryFloorByNode(params) {
+    return httputils.getJson(`${testApi}/node/qfloor`, params)
+}
+
+// 批量绑定工程信息化数据
+export function bindAttachObject(params){
+    return httputils.postJson(`${testApi}/node/bindAttachObject`, params)
+}
+
+// 查询所有绘图的楼层
+export function queryFullFloor(params) {
+    return httputils.getJson(`${testApi}/graph/fullFloor`, params)
 }

BIN
src/assets/images/copy.png


BIN
src/assets/images/iconBlackBottom.png


BIN
src/assets/images/iconBlackTop.png


BIN
src/assets/images/iconLightBottom.png


BIN
src/assets/images/iconLightTop.png


BIN
src/assets/images/past.png


BIN
src/assets/images/selectSimilar.png


+ 150 - 64
src/components/baseEditer.vue

@@ -18,7 +18,8 @@ import {
   saveGroup,
   readGroup,
   queryTypeGraph,
-  publishGraph
+  publishGraph,
+  graphQuery
 } from "@/api/editer.js";
 import { STopologyParser } from "./../lib/parsers/STopologyParser";
 import { uuid } from "@/components/mapClass/until";
@@ -29,6 +30,7 @@ import { Loading } from "element-ui";
 import { Message } from "element-ui";
 import { SCircleItem } from "@/lib/items/SCircleItem";
 import menuList from "@/components/edit/menu_list.vue";
+import { mapState } from "vuex";
 window.FENGMAP = null;
 const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
 //// 底图空间增加字段 isExtracted:boolean true 已被提取过
@@ -81,19 +83,22 @@ export default {
     // 挂在bus
     this.getBus();
     if (this.urlMsg.categoryId) {
-      store.dispatch("getGraphElement", { PageSize: 1000, Deleted: false, GraphCategoryIds:[this.urlMsg.categoryId] });
+      store.dispatch("getGraphElement", {
+        PageSize: 1000,
+        Deleted: false,
+        GraphCategoryIds: [this.urlMsg.categoryId]
+      });
     }
-    window.vm = this;
+    // window.vm = this;
     const that = this;
     document.onkeydown = function(event) {
-      console.log('ctrl',event,isMac)
       const e = event || window.event || arguments.callee.caller.arguments[0];
       if (e && e.key == "Control") {
         // 按 ctrl
         that.scene.isDownCtrl = true;
       }
-      if(e && e.key == "Meta" && isMac){
-           console.log('meta',event,isMac)
+      if (e && e.key == "Meta" && isMac) {
+        console.log("meta", event, isMac);
         // 如果为苹果键
         that.scene.isDownCtrl = true;
       }
@@ -103,22 +108,29 @@ export default {
       if (e && e.key == "Control") {
         // 按 ctrl
         that.scene.isDownCtrl = false;
-        this.scene.setCmd = "choice";
+        // that.scene.setCmd = "choice";
       }
-      if(e && e.key == "Meta" && isMac){
+      if (e && e.key == "Meta" && isMac) {
         // 如果为苹果键
         that.scene.isDownCtrl = false;
-        this.scene.setCmd = "choice";
+        // that.scene.setCmd = "choice";
       }
     };
     // 监听粘贴事件
-    // document.onpaste = e =>{
-    //   const text = e.clipboardData.getData('Text')
-    //   this.scene.crossPagePaste(text)
-    // }
+    document.onpaste = e => {
+      if (this.isCopy == "true") {
+        return;
+      }
+      const text = e.clipboardData.getData("Text");
+      this.scene.crossPagePaste(text);
+    };
     // 自动保存(时间差为一分钟)
+    // 如果为复制状态则不需要自动保存
+
     this.autoSave = setInterval(() => {
-      this.saveMsgNoMessage();
+      if (this.isCopy != "true") {
+        this.saveMsgNoMessage();
+      }
     }, 300000);
   },
   methods: {
@@ -132,7 +144,7 @@ export default {
       document.getElementById(`canvas`).focus();
       this.clearGraphy();
       this.scene = new EditScence();
-
+      this.scene.isCopy = this.isCopy; //是否为复制状态
       if (this.urlMsg.fmapID.includes("null")) {
         this.loadings.close();
         this.view.scene = this.scene;
@@ -154,7 +166,16 @@ export default {
         )
           .then(response => {
             console.log("获取rf成功", response);
-            this.parserData(floorid);
+            this.getGraphDetail().then(res => {
+              if (res.Content.length == 1) {
+                const data = res.Content[0];
+                if (data.MaxY && data.MinX) {
+                  window.FENGMAP.maxY = data.MaxY;
+                  window.FENGMAP.minX = data.MinX;
+                }
+              }
+              this.parserData(floorid);
+            });
             // this.readGraph();
             // loadings.close();
           })
@@ -172,7 +193,7 @@ export default {
       if (floor == "g80") {
         // 屋顶
         if (window.FENGMAP.frImg) {
-          const pj = this.urlMsg.fmapID.split('_')[0]
+          const pj = this.urlMsg.fmapID.split("_")[0];
           // 单张图片
           if (!ProjectRf[pj]) {
             const imgItem = new SImageItem(
@@ -195,16 +216,16 @@ export default {
                   null,
                   `${this.mapServerURL}/webtheme/${this.urlMsg.fmapID}/${t.name}`
                 );
-                item.width = t.width
-                item.height = t.height
-                item.moveTo(t.x, t.y)
+                item.width = t.width;
+                item.height = t.height;
+                item.moveTo(t.x, t.y);
                 item.connect("imgLoadOver", this, () => {
                   this.countRf(ProjectRf[pj].length);
                 });
                 this.scene.addItem(item);
-              })
+              });
               this.view.scene = this.scene;
-            } catch(e) {
+            } catch (e) {
               console.log(e);
             }
           }
@@ -221,14 +242,14 @@ export default {
       }
     },
     // 解析楼地板
-    loadBoard(floor){
+    loadBoard(floor) {
       window.FENGMAP.loadFloor(floor, res => {
-        const zone = new SBoardItem(null, res)
+        const zone = new SBoardItem(null, res);
         this.scene.addItem(zone);
-      })
+      });
     },
     // 解析底图
-    readBaseMap(floor){
+    readBaseMap(floor) {
       this.loadBoard(this.floorList[floor]);
       window.FENGMAP.parseData(this.floorList[floor], res => {
         if (res.err) {
@@ -248,7 +269,7 @@ export default {
         this.scene.spaceList = this.fParser.spaceList;
         this.fParser.wallList.forEach(t => {
           // if (!t.data.HasHole) {
-            this.scene.addItem(t)
+          this.scene.addItem(t);
           // }
         });
         this.fParser.virtualWallList.forEach(t => this.scene.addItem(t));
@@ -257,10 +278,12 @@ export default {
         this.fParser.casementList.forEach(t => this.scene.addItem(t));
         this.fParser.pList = [];
         res.PList.forEach(t => {
-          const item = new SCircleItem(null, t);
-          this.fParser.pList.push(item);
-          this.scene.fidToItem[t.SourceId] = item;
-          this.scene.addItem(item);
+          if (t.Pos.X >= 0 && t.Pos.Y <= 0) {
+            const item = new SCircleItem(null, t);
+            this.fParser.pList.push(item);
+            this.scene.fidToItem[t.SourceId] = item;
+            this.scene.addItem(item);
+          }
         });
         this.view.scene = this.scene;
         this.readGraph();
@@ -280,7 +303,11 @@ export default {
           parserData.zoneLegendList.forEach(t => {
             this.scene.addItem(t);
             // 记录提取
-            if (t.data.Properties && t.data.Properties.FID) {
+            if (
+              t.data.Properties &&
+              t.data.Properties.FID &&
+              this.scene.fidToItem[t.data.Properties.FID]
+            ) {
               this.scene.fidToItem[t.data.Properties.FID].isExtracted = true;
             }
             this.scene.Nodes.push(t);
@@ -302,7 +329,11 @@ export default {
           parserData.imageLegendList.forEach(t => {
             this.scene.addItem(t);
             // 记录提取
-            if (t.data.Properties && t.data.Properties.FID) {
+            if (
+              t.data.Properties &&
+              t.data.Properties.FID &&
+              this.scene.fidToItem[t.data.Properties.FID]
+            ) {
               this.scene.fidToItem[t.data.Properties.FID].isExtracted = true;
             }
             this.scene.Nodes.push(t);
@@ -351,25 +382,29 @@ export default {
             }
           });
         }
-        console.log(11111111111111111111111111);
+
+        // if(this.urlMsg.projectId==1000384 && this.urlMsg.FloorID =='f2'){
+        //           console.log('对河南红谷滩兼容');
+        // }else{
         this.view.fitSceneToView();
+        // }
         // 设置初始化缩放比例
         this.initScale = this.view.scale;
         this.view.maxScale = this.initScale * 10;
         this.view.minScale = this.initScale / 10;
         bus2.$emit("initScale", this.view.scale);
         bus2.$emit("elementDataChange", this.scene);
-        this.loadings.close()
+        this.loadings.close();
       });
     },
     // 顶楼为多张图时计数器
     countRf(len) {
-      this.count++
+      this.count++;
       console.log(len == this.count);
       if (len == this.count) {
         this.readGraph();
       } else {
-        console.log('所有图片未加载完成');
+        console.log("所有图片未加载完成");
       }
     },
     // 监听变化
@@ -407,6 +442,9 @@ export default {
       bus.$on("changeFontColor", val => {
         this.scene.updatedFontColor(val);
       });
+      bus.$on('changeCopystatus',val=>{
+         this.scene.isCopy = val;
+      })
       bus.$on("itemWidth", val => {
         this.scene.updatedWidth(Number(val));
       });
@@ -481,7 +519,7 @@ export default {
         if (val.type == "Image") {
           const list = this.fParser.pList
             .map(t => {
-              if (val.key.indexOf(t.data.Type)>-1 && val.age.Url) {
+              if (val.key.indexOf(t.data.Type) > -1 && val.age.Url) {
                 if (!t.isExtracted) {
                   t.isExtracted = true;
                   const data = {
@@ -498,22 +536,37 @@ export default {
                     Size: { Width: 0, Height: 0 }, // 大小
                     Type: val.age.Type,
                     Properties: {
-                        IconUrl: '/serve/topology-wanda/Picture/query/' + val.age.Url,
-                        Url: '/serve/topology-wanda/Picture/query/' + val.age.Url,
-                        Num: 1, // 此num与信息工程化得num无关
-                        Size: {
-                          Width: val.age.Size?val.age.Size.Width?val.age.Size.Width:32:32,  //icon 的宽
-                          Height: val.age.Size?val.age.Size.Height?val.age.Size.Height:32:32,   //icon 的高
-                        },
-                        font: 16,    //font
-                        color: "#1F2429",  //字体颜色
-                        FrameColor: val.age.FrameColor,
-                        GraphCategoryId: val.age.GraphCategoryId,
-                        InfoSystemId: val.age.InfoSystemId?val.age.InfoSystemId:'',   //信息工程话分类ID分类
-                        FID: t.data.SourceId,
-                        InfoTypeId:val.age.InfoTypeId.length? val.age.InfoTypeId :[],
-                        InfoLocal:val.age.InfoLocal.length ?val.age.InfoLocal :[]
-                    },
+                      IconUrl:
+                        "/serve/topology-wanda/Picture/query/" + val.age.Url,
+                      Url: "/serve/topology-wanda/Picture/query/" + val.age.Url,
+                      Num: 1, // 此num与信息工程化得num无关
+                      Size: {
+                        Width: val.age.Size
+                          ? val.age.Size.Width
+                            ? val.age.Size.Width
+                            : 32
+                          : 32, //icon 的宽
+                        Height: val.age.Size
+                          ? val.age.Size.Height
+                            ? val.age.Size.Height
+                            : 32
+                          : 32 //icon 的高
+                      },
+                      font: 16, //font
+                      color: "#1F2429", //字体颜色
+                      FrameColor: val.age.FrameColor,
+                      GraphCategoryId: val.age.GraphCategoryId,
+                      InfoSystemId: val.age.InfoSystemId
+                        ? val.age.InfoSystemId
+                        : "", //信息工程话分类ID分类
+                      FID: t.data.SourceId,
+                      InfoTypeId: val.age.InfoTypeId.length
+                        ? val.age.InfoTypeId
+                        : [],
+                      InfoLocal: val.age.InfoLocal.length
+                        ? val.age.InfoLocal
+                        : []
+                    }
                   };
                   const item = new SImageLegendItem(null, data);
                   item.selectable = true;
@@ -530,7 +583,7 @@ export default {
         } else if (val.type == "Zone") {
           const list = this.fParser.spaceList
             .map(t => {
-              if (val.key.indexOf(t.data.Type)>-1 && val.age.Url) {
+              if (val.key.indexOf(t.data.Type) > -1 && val.age.Url) {
                 if (!t.isExtracted) {
                   t.isExtracted = true;
                   return {
@@ -561,7 +614,8 @@ export default {
                         : [],
                       InfoLocal: val.age.InfoLocal.length
                         ? val.age.InfoLocal
-                        : []
+                        : [],
+                      lengendName: this._legend.Name //图例名称
                     },
                     Num: 1
                   };
@@ -684,8 +738,8 @@ export default {
         this.changeScaleByClick = false;
       });
       // 更改图例数据工程化数据
-      bus.$on("changeAttachObjectIds", arr => {
-        this.scene.upadatAttachObjectIds(arr);
+      bus.$on("changeAttachObjectIds", (arr, flag) => {
+        this.scene.upadatAttachObjectIds(arr, flag);
       });
       // redo
       bus.$on("changeRedo", () => {
@@ -700,10 +754,34 @@ export default {
       bus.$on("toggleItem", item => {
         this.scene.toggleItem(item);
       });
-      // 
-      bus.$on('itemAngle', ang => {
+      //
+      bus.$on("itemAngle", ang => {
         this.scene.updateItemAng(ang);
-      })
+      }),
+      // 更改item样式
+      bus.$on("changeLengendItem", item => {
+        this.scene.changeLengendItem(item);
+      }),
+      //复制操作
+      bus.$on("copymsg", () => {
+        this.scene.copy();
+      });
+      //粘贴操作
+      bus.$on("stickmsg", () => {
+        const text = sessionStorage.getItem("copyString");
+        this.scene.crossPagePaste(text);
+      });
+      //选中同类
+      bus.$on("selectSimilar", () => {
+        this.scene.selectSimilar();
+      });
+    },
+    // 获取图最大最小值
+    getGraphDetail() {
+      const data = {
+        Filters: `categoryId='${this.urlMsg.categoryId}';projectId='${this.urlMsg.projectId}';BuildingID='${this.urlMsg.BuildingID}';FloorID='${this.urlMsg.FloorID}'`
+      };
+      return graphQuery(data);
     },
     // 读取数据
     readGroup() {
@@ -785,7 +863,9 @@ export default {
         ProjectID: this.urlMsg.projectId, // 项目ID
         BuildingID: this.urlMsg.BuildingID, // 建筑ID
         FloorID: this.urlMsg.FloorID, // 楼层id
-        Seq // 楼层id
+        Seq, // 楼层id
+        MinX: window.FENGMAP.minX,
+        MaxY: window.FENGMAP.maxY
       };
       return new Promise(resolve => {
         saveGroup(data)
@@ -827,7 +907,9 @@ export default {
           ProjectID: this.urlMsg.projectId, // 项目ID
           BuildingID: this.urlMsg.BuildingID, // 建筑ID
           FloorID: this.urlMsg.FloorID, // 楼层id
-          Seq // 楼层id
+          Seq, // 楼层id
+          MinX: window.FENGMAP.minX,
+          MaxY: window.FENGMAP.maxY
         };
         saveGroup(data)
           .then(res => {
@@ -900,7 +982,6 @@ export default {
     params = decodeURIComponent(params);
     // params = "categoryId=NTXT&ProjectID=5&BuildingID=1&FloorID=1"; // mock 参数
     const paramsArr = params.split("&");
-    console.log("paramsArr", paramsArr);
     const obj = {};
     paramsArr.map(item => {
       const arr = item.split("=");
@@ -908,6 +989,11 @@ export default {
     });
     this.urlMsg = obj;
   },
+  computed: {
+    ...mapState({
+      isCopy:'isCopy'
+    })
+  },
   beforeDestroy() {
     // 销毁自动保存
     clearInterval(this.autoSave);

+ 247 - 107
src/components/edit/attr_select.vue

@@ -32,7 +32,7 @@
             :label="item.src"
             :value="item.id"
           >
-            <img :src="item.src" alt width='180' />
+            <img :src="item.src" alt width="180" />
           </a-select-option>
         </a-select>
       </div>
@@ -56,7 +56,12 @@
           <a-input-number v-model="fontSize" :min="1" @change="changeFont" style="width: 168px" />
         </div>
         <div class="color-choice">
-          <swatches v-model="fontColor" :swatches="swatchesFont" popover-x="left" @close="changeFontColor" />
+          <swatches
+            v-model="fontColor"
+            :swatches="swatchesFont"
+            popover-x="left"
+            @close="changeFontColor"
+          />
         </div>
       </div>
       <div class="row">
@@ -115,17 +120,22 @@
       <div v-if="type =='Image'|| type == 'Line'">
         <div class="row">
           <div class="row-tit">显示名称</div>
-          <a-button type="link" class="edit-option-btn" @click="OpenEditStatus">{{isEdit? "取消编辑" : editStatus[type]}}</a-button>
+          <a-button
+            type="link"
+            class="edit-option-btn"
+            @click="OpenEditStatus"
+          >{{isEdit? "取消编辑" : editStatus[type]}}</a-button>
         </div>
         <div :class="['row' ,type == 'Line'?'disabled-textarea':'']">
-          <a-textarea :disabled="type == 'Line' "
-                  placeholder=""
-                  v-model="lengedName"
-                  allow-clear
-                  @change="changeLengedName"
-                  :rows="2"
+          <a-textarea
+            :disabled="type == 'Line' "
+            placeholder
+            v-model="lengedName"
+            allow-clear
+            @change="changeLengedName"
+            :rows="2"
           />
-<!--          <a-input v-model="lengedName" @change="changeLengedName" />-->
+          <!--          <a-input v-model="lengedName" @change="changeLengedName" />-->
         </div>
         <div class="row" v-show="type =='Image'">
           <div class="row-tit">字号</div>
@@ -133,7 +143,12 @@
             <a-input-number v-model="fontSize" :min="1" @change="changeFont" style="width: 168px" />
           </div>
           <div class="color-choice">
-            <swatches v-model="fontColor" :swatches="swatchesFont" @close="changeFontColor" popover-x="left" />
+            <swatches
+              v-model="fontColor"
+              :swatches="swatchesFont"
+              @close="changeFontColor"
+              popover-x="left"
+            />
           </div>
         </div>
         <!-- 当为设备状态时 -->
@@ -179,13 +194,13 @@
           </div>
           <div class="row">
             <a-textarea
-                    placeholder=""
-                    v-model="lengedName"
-                    allow-clear
-                    @change="changeLengedName"
-                    :rows="2"
+              placeholder
+              v-model="lengedName"
+              allow-clear
+              @change="changeLengedName"
+              :rows="2"
             />
-<!--            <a-input v-model="lengedName" @change="changeLengedName" />-->
+            <!--            <a-input v-model="lengedName" @change="changeLengedName" />-->
           </div>
           <div class="row">
             <div class="row-tit">字号</div>
@@ -198,7 +213,12 @@
               />
             </div>
             <div class="color-choice">
-              <swatches v-model="fontColor" :swatches="swatchesFont" @close="changeFontColor" popover-x="left" />
+              <swatches
+                v-model="fontColor"
+                :swatches="swatchesFont"
+                @close="changeFontColor"
+                popover-x="left"
+              />
             </div>
           </div>
         </div>
@@ -206,14 +226,14 @@
           <!-- 石材铺装 -->
           <div class="row">
             <div class="row-tit">图例说明</div>
-            <a-button type="link" class="edit-option-btn" @click="OpenEditStatus">{{isEdit? "取消编辑" : editStatus[type]}}</a-button>
+            <a-button
+              type="link"
+              class="edit-option-btn"
+              @click="OpenEditStatus"
+            >{{isEdit? "取消编辑" : editStatus[type]}}</a-button>
           </div>
           <div class="row">
-            <a-textarea
-              @change="changeitemExplain"
-              v-model="itemExplain"
-              :rows="4"
-            />
+            <a-textarea @change="changeitemExplain" v-model="itemExplain" :rows="4" />
           </div>
           <div class="row">
             <div class="row-tit">描边</div>
@@ -241,32 +261,82 @@
           <!-- 自定义 -->
           <div class="row-tit">
             <span style="margin-right:10px;color:#8d9399">填充颜色</span>
-            <el-color-picker show-alpha v-model="CUSTOMbgColor" @change='changBgColor' style="vertical-align:middle;"></el-color-picker>
+            <el-color-picker
+              show-alpha
+              v-model="CUSTOMbgColor"
+              @change="changBgColor"
+              style="vertical-align:middle;"
+            ></el-color-picker>
           </div>
           <div class="row-tit">
             <span style="margin-right:10px;color:#8d9399">边框颜色</span>
-            <el-color-picker show-alpha v-model="CUSTOMbdColor" @change='changBdColor' style="vertical-align:middle;"></el-color-picker>
+            <el-color-picker
+              show-alpha
+              v-model="CUSTOMbdColor"
+              @change="changBdColor"
+              style="vertical-align:middle;"
+            ></el-color-picker>
           </div>
           <div class="row">
             <div class="row-tit">显示名称</div>
-            <a-button type="link" class="edit-option-btn" @click="OpenEditStatus">{{isEdit? "取消编辑" : editStatus[type]}}</a-button>
+            <a-button
+              type="link"
+              class="edit-option-btn"
+              @click="OpenEditStatus"
+            >{{isEdit? "取消编辑" : editStatus[type]}}</a-button>
           </div>
           <div class="row">
-            <a-textarea placeholder="" v-model="lengedName" allow-clear @change="changeLengedName" :rows="2"/>
+            <a-textarea
+              placeholder
+              v-model="lengedName"
+              allow-clear
+              @change="changeLengedName"
+              :rows="2"
+            />
           </div>
           <div class="row">
             <div class="row-tit">字号</div>
             <div class="grid-content">
-              <a-input-number v-model="fontSize" :min="1" @change="changeFont" style="width: 168px" />
+              <a-input-number
+                v-model="fontSize"
+                :min="1"
+                @change="changeFont"
+                style="width: 168px"
+              />
             </div>
             <div class="color-choice">
-              <swatches v-model="fontColor" :swatches="swatchesFont" @close="changeFontColor" popover-x="left" />
+              <swatches
+                v-model="fontColor"
+                :swatches="swatchesFont"
+                @close="changeFontColor"
+                popover-x="left"
+              />
             </div>
           </div>
         </div>
-        <div v-if="!SubType">
+        <div v-show="!SubType">
           <!-- 普通分区 -->
           <div class="row">
+            <!-- 修改图例 -->
+            <div class="row-tit">图例名称</div>
+            <div>
+              <a-spin :spinning="isGetLengend">
+                <a-dropdown :trigger="['click']">
+                  <a class="ant-dropdown-link" @click="changeLengend">{{lengendName}}</a>
+                  <a-menu slot="overlay">
+                    <a-menu-item
+                      @click="changeLengendItem(item)"
+                      v-for="(item,key) in lengendArr"
+                      :key="key"
+                    >
+                      <a href="javascript:;">{{item.Name}}</a>
+                    </a-menu-item>
+                  </a-menu>
+                </a-dropdown>
+              </a-spin>
+            </div>
+          </div>
+          <div class="row">
             <div class="row-tit">显示名称</div>
             <a-button
               type="link"
@@ -276,13 +346,13 @@
           </div>
           <div class="row">
             <a-textarea
-                    placeholder=""
-                    v-model="lengedName"
-                    allow-clear
-                    @change="changeLengedName"
-                    :rows="2"
+              placeholder
+              v-model="lengedName"
+              allow-clear
+              @change="changeLengedName"
+              :rows="2"
             />
-<!--            <a-input v-model="lengedName" @change="changeLengedName" />-->
+            <!--            <a-input v-model="lengedName" @change="changeLengedName" />-->
           </div>
           <div class="row">
             <div class="row-tit">字号</div>
@@ -295,7 +365,12 @@
               />
             </div>
             <div class="color-choice">
-              <swatches v-model="fontColor" :swatches="swatchesFont" @close="changeFontColor" popover-x="left" />
+              <swatches
+                v-model="fontColor"
+                :swatches="swatchesFont"
+                @close="changeFontColor"
+                popover-x="left"
+              />
             </div>
           </div>
         </div>
@@ -315,7 +390,11 @@
         </div>
 
         <div class="grid-content" style="margin-top: 12px;">
-          <a-card class="attr-card" v-for="(item,index) in attrCards" :key="index">{{item.sbjc ||item.wzjc}}</a-card>
+          <a-card
+            class="attr-card"
+            v-for="(item,index) in attrCards"
+            :key="index"
+          >{{item.sbjc ||item.wzjc}}</a-card>
         </div>
       </a-spin>
     </div>
@@ -349,7 +428,7 @@
         </a-collapse-panel>
       </a-collapse>
     </div>
-    <editDialog ref="dialog" :attrCards="attrCards" :GraphElementId="GraphElementId" :InfoLocal="InfoLocal" :sysNum="imageNum" :key="keys" />
+    <editDialog ref="dialog" :attrCards="attrCards" :lengedName="lengedName" :GraphElementId="GraphElementId" :InfoLocal="InfoLocal" :sysNum="imageNum" :key="keys" />
 <!--    <editDialog ref="dialog" :attrCards="attrCards" :getmajorId="getmajorId" :InfoLocal="InfoLocal" :sysNum="imageNum" :key="new Date().getTime()" />-->
     <!--    <editDialog ref="dialog" :typeEdit="2" :getmajorId="'1001'" :sysNum="5" />-->
   </div>
@@ -359,6 +438,7 @@
 import editDialog from "./edit-dialog";
 import Swatches from "vue-swatches";
 import bus from "@/bus";
+import bus2 from "@/bus2";
 import "vue-swatches/dist/vue-swatches.css";
 import { SLineStyle } from "@saga-web/graph/lib";
 import { SItemStatus } from "@saga-web/big";
@@ -369,8 +449,9 @@ import {
 } from "@/api/editer.js";
 import { getUrlMsg } from "@/components/urlMsg.js";
 // mapclass里边的没有透明度
-import { hexify } from "@/utils/rgbaUtil"
-import { SCustomLegendItem } from '@/lib/items/SCustomLegendItem';
+import { hexify } from "@/utils/rgbaUtil";
+import { SCustomLegendItem } from "@/lib/items/SCustomLegendItem";
+import { graphElementGroup } from "@/api/editer.js";
 export default {
   name: "attr_select",
   props: ["type", "focusItemList"],
@@ -385,7 +466,7 @@ export default {
         { value: "拖动画布:", keys: "Space", events: "Click" },
         { value: "加选对象:", keys: "Ctrl", events: "Press" },
         { value: "确认操作:", keys: "Enter" },
-        { value: "取消对象:", keys: "Enter" }
+        { value: "取消对象:", keys: "Esc" }
       ],
       numberValue: 3,
       fontSize: 12, //字体大小
@@ -442,7 +523,7 @@ export default {
         "#8E43AD",
         "#3D556E",
         "#222F3D",
-        "#00000000",
+        "#00000000"
       ],
       swatchesFont: [
         "#1fbc9c",
@@ -471,11 +552,17 @@ export default {
       spinning: false,
       isEdit: false,
       getmajorId: "",
-      InfoLocal:[],
-      GraphElementId:'',//图例Id
-      CUSTOMbgColor: 'rgba(0,0,0,0.15)', // 自定义多边形背景色
-      CUSTOMbdColor: 'rgba(0,0,0,1)', // 自定义多边形线条色
-      keys:new Date().getTime()
+      InfoLocal: [],
+      GraphElementId: "", //图例Id
+      CUSTOMbgColor: "rgba(0,0,0,0.15)", // 自定义多边形背景色
+      CUSTOMbdColor: "rgba(0,0,0,1)", // 自定义多边形线条色
+      keys: new Date().getTime(),
+      getCategroyIdS: [], //选择原件的数据
+      categoryId: "", //类型ide
+      lengendName: "", //lengend图例Id
+      isGetLengend: false,
+      isOpenGend: false,
+      lengendArr: [] //图例数组
     };
   },
   methods: {
@@ -518,14 +605,14 @@ export default {
       }
     },
     // 用户自定义多边形 修改背景色
-    changBgColor(val){
+    changBgColor(val) {
       const color = hexify(val); // 转为16进制
-      bus.$emit('CUSTOMbgColor',color)
+      bus.$emit("CUSTOMbgColor", color);
     },
     // 用户自定义多边形 修改现调颜色
-    changBdColor(val){
+    changBdColor(val) {
       const color = hexify(val); // 转为16进制
-      bus.$emit('CUSTOMbdColor',color)
+      bus.$emit("CUSTOMbdColor", color);
     },
     customRequest(info) {
       const formData = new FormData();
@@ -559,10 +646,10 @@ export default {
       }
     },
     handleEdit() {
-      this.keys = new Date().getTime()
-      setTimeout(()=>{
-          this.$refs.dialog.showModal();
-      })
+      this.keys = new Date().getTime();
+      setTimeout(() => {
+        this.$refs.dialog.showModal();
+      });
     },
     // 修改设备数量
     changeImageNum() {
@@ -600,13 +687,50 @@ export default {
     // 更改工程信息化数据
     changeAttachObjectIds(arr) {
       bus.$emit("changeAttachObjectIds", arr);
+    },
+    // 下拉框获取图例数据
+    changeLengend(val) {
+      this.isGetLengend = true;
+      this.lengendArr = [];
+      const obj = {
+        InfoSystems: this.getCategroyIdS,
+        Type: "Zone",
+        categoryId: this.categoryId
+      };
+      return graphElementGroup(obj)
+        .then(res => {
+          const arr = [];
+          res.Data.forEach(res => {
+            if (res.GraphElements && res.GraphElements.length) {
+              res.GraphElements.forEach(item => {
+                if (
+                  !(item.SubType && item.SubType == "FHFQ") &&
+                  !(item.SubType && item.SubType == "SCPZ")
+                ) {
+                  arr.push(item);
+                }
+              });
+            }
+          });
+          this.isGetLengend = false;
+          this.lengendArr = arr;
+          console.log("arrarrarr", this.lengendArr);
+        })
+        .catch(() => {
+          this.isGetLengend = false;
+        });
+    },
+    // 点击修改图例item
+    changeLengendItem(item) {
+      this.lengendName = item.Name;
+      // 修改图例
+      bus.$emit('changeLengendItem',item)
     }
   },
   watch: {
     focusItemList: function(newval) {
-      console.log('------------')
-      console.log(FENGMAP)
-      console.log('newval',newval)
+      console.log("------------");
+      console.log("newval", newval);
       const Item = newval.itemList[0];
       this.GraphElementId = Item.data.GraphElementId;
       this.imageNum = 1; //切换item初始化
@@ -663,14 +787,14 @@ export default {
         } else if (newval.itemType == "baseImage") {
           this.lineWidth = Item.lineWidth;
           this.borderColor = Item.strokeColor.value;
-        }else if (
+        } else if (
           newval.itemType == "Zone" ||
           newval.itemType == "Line" ||
           newval.itemType == "Image"
         ) {
           setTimeout(() => {
-            this.isEdit = (Item.status == SItemStatus.Edit);
-          }, 300)
+            this.isEdit = Item.status == SItemStatus.Edit;
+          }, 300);
           if (newval.itemType == "Image") {
             this.imageNum = Item.num;
             this.lengedName = Item.name;
@@ -690,6 +814,9 @@ export default {
             this.borderColor = Item.strokeColor ? Item.strokeColor.value : "";
             this.fillColor = Item.fillColor ? Item.fillColor.value : "";
             this.itemExplain = "";
+            this.lengendName = Item.data.Properties.lengendName
+              ? Item.data.Properties.lengendName
+              : Item.name; //图例名称
             if (Item.data.Properties.ItemExplain) {
               this.itemExplain = Item.data.Properties.ItemExplain
                 ? Item.data.Properties.ItemExplain
@@ -698,10 +825,14 @@ export default {
             if (newval.itemList.length) {
               if (newval.itemList[0] instanceof SCustomLegendItem) {
                 const fColor = newval.itemList[0].fillColor;
-                this.CUSTOMbgColor = `rgba(${fColor.red}, ${fColor.green}, ${fColor.blue}, ${fColor.alpha/100})`
+                this.CUSTOMbgColor = `rgba(${fColor.red}, ${fColor.green}, ${
+                  fColor.blue
+                }, ${fColor.alpha / 100})`;
 
                 const bColor = newval.itemList[0].strokeColor;
-                this.CUSTOMbdColor = `rgba(${bColor.red}, ${bColor.green}, ${bColor.blue}, ${bColor.alpha/100})`
+                this.CUSTOMbdColor = `rgba(${bColor.red}, ${bColor.green}, ${
+                  bColor.blue
+                }, ${bColor.alpha / 100})`;
               }
             }
           }
@@ -711,14 +842,14 @@ export default {
       const assetnumList = [];
       let params = {};
       this.attrCards = [];
-      if(Item.data.AttachObjectIds && Item.data.AttachObjectIds.length ){
-          Item.data.AttachObjectIds.map(item => {
-        if (item.type == "Zone") {
-          locationList.push(item.id);
-        } else if (item.type == "Image") {
-          assetnumList.push(item.id);
-        }
-      });
+      if (Item.data.AttachObjectIds && Item.data.AttachObjectIds.length) {
+        Item.data.AttachObjectIds.map(item => {
+          if (item.type == "Zone") {
+            locationList.push(item.id);
+          } else if (item.type == "Image") {
+            assetnumList.push(item.id);
+          }
+        });
       }
       // if(newval.itemType == 'Zone'){
       this.spinning = true;
@@ -727,26 +858,26 @@ export default {
       } else {
         params = { locationList: [""] };
       }
-      queryGlsmsLocation({ plazaId: getUrlMsg().projectId }, params).then(
-        res => {
+      queryGlsmsLocation({ plazaId: getUrlMsg().projectId }, params)
+        .then(res => {
           this.spinning = false;
           if (res.data.result == "success") {
             console.log(res.data);
             if (res.data.data && res.data.data.length) {
-              let ZoneData = res.data.data
-              ZoneData.map(item=>{
-                item.type='Zone'
-              })
+              const ZoneData = res.data.data;
+              ZoneData.map(item => {
+                item.type = "Zone";
+              });
               this.attrCards = this.attrCards.concat(ZoneData);
             }
           } else {
             // this.$message.error("工程信息化中的位置信息获取失败");
           }
-        }
-      ).catch(()=>{
-        this.spinning = false;
-        // this.$message.error("工程信息化中的位置信息获取失败");
-      });
+        })
+        .catch(() => {
+          this.spinning = false;
+          // this.$message.error("工程信息化中的位置信息获取失败");
+        });
       // }else if(newval.itemType == 'Image'){
       this.spinning = true;
       if (assetnumList.length) {
@@ -754,37 +885,46 @@ export default {
       } else {
         params = { assetnumList: [""] };
       }
-      queryGlsmsAsset({ plazaId: getUrlMsg().projectId }, params).then(res => {
-        this.spinning = false;
-        if (res.data.result == "success") {
-          console.log(res.data);
-          if (res.data.data && res.data.data.length) {
-            let data =  res.data.data;
-            data.map(item=>{
-              item.type='Image'
-            })
-            this.attrCards = this.attrCards.concat(data);
+      queryGlsmsAsset({ plazaId: getUrlMsg().projectId }, params)
+        .then(res => {
+          this.spinning = false;
+          if (res.data.result == "success") {
+            console.log(res.data);
+            if (res.data.data && res.data.data.length) {
+              const data = res.data.data;
+              data.map(item => {
+                item.type = "Image";
+              });
+              this.attrCards = this.attrCards.concat(data);
+            }
+          } else {
+            // this.$message.error("工程信息化中的设备信息获取失败");
           }
-        } else {
+        })
+        .catch(() => {
+          this.spinning = false;
           // this.$message.error("工程信息化中的设备信息获取失败");
-        }
-      }).catch(()=>{
-        this.spinning = false;
-        // this.$message.error("工程信息化中的设备信息获取失败");
-      });
+        });
       // }
       console.log(this.attrCards);
     }
+  },
+  mounted() {
+    // 获取原件id
+    bus2.$on("getCategroyIdS", data => {
+      this.getCategroyIdS = data;
+    });
+    this.categoryId = getUrlMsg().categoryId;
   }
 };
 </script>
 
 <style scoped lang="less">
-  .disabled-textarea{
-    /deep/ .ant-input{
-      resize: none;
-    }
+.disabled-textarea {
+  /deep/ .ant-input {
+    resize: none;
   }
+}
 /deep/ .ant-spin-nested-loading {
   height: 100% !important;
   .ant-spin-container {
@@ -811,7 +951,7 @@ export default {
         width: 26px !important;
         height: 26px !important;
         border-radius: 2px !important;
-        border: 1px solid #dcdcdc ;
+        border: 1px solid #dcdcdc;
       }
     }
     .row-tit {
@@ -819,7 +959,7 @@ export default {
       font-size: 14px;
     }
   }
-  .row:first-child{
+  .row:first-child {
     margin-top: 0;
   }
   .grid {
@@ -831,7 +971,7 @@ export default {
   }
 
   .grid-content {
-     /*margin-top: 12px;*/
+    /*margin-top: 12px;*/
     height: calc(100% - 48px);
     overflow-y: scroll;
     position: relative;

File diff suppressed because it is too large
+ 1381 - 0
src/components/edit/edit-dialog-tree.vue


File diff suppressed because it is too large
+ 779 - 125
src/components/edit/edit-dialog.vue


+ 233 - 0
src/components/edit/floorList.vue

@@ -0,0 +1,233 @@
+<template>
+  <div class='floor-box'>
+    <div class='floor-list'>
+      <div class='icon-top' v-if='floorsArr.length>8'>
+        <!-- @click='changeFloor(1,currIndex)' -->
+        <img v-show='parseInt(marginTop) !== 0' v-repeat-click='increase' src='@/assets/images/iconBlackTop.png' alt />
+        <img class='disabled' v-show='parseInt(marginTop) === 0' src='@/assets/images/iconLightTop.png' alt />
+      </div>
+      <div class='floor-out' :style='{ height:conHeight + "px" }'>
+        <!--  放开marginTop样式  -->
+        <div class='floor-center' :style='{ marginTop : marginTop }'>
+          <div class='floor-item' :class='item.FloorId == currentFloorId?"isActive":""' @click='tabFloor(item,index)'
+            v-for='(item,index) in floorsArr' :key='index'>{{item.Name}}</div>
+        </div>
+      </div>
+      <div class='icon-bottom' v-if='floorsArr.length>8'>
+        <!-- v-repeat-click='decrease' -->
+        <img v-show='parseInt(marginTop) !== marginTopMax' v-repeat-click='decrease'
+          src='@/assets/images/iconBlackBottom.png' alt />
+        <img class='disabled' v-show='parseInt(marginTop) === marginTopMax' src='@/assets/images/iconLightBottom.png'
+          alt />
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import RepeatClick from '@/directives/repeat-click'
+
+export default {
+  directives: {
+    repeatClick: RepeatClick,
+  },
+  data() {
+    return {
+      currentFloorId: null,
+      marginTop: 0,
+      marginTopMax: 0,
+      showNumber: 8, //需要展示的楼层数   //TODO:
+      height: 39, //一个楼层的高度
+      currIndex: 0, //当前楼层在 楼层数组中的下标,上下箭头使用
+      conHeight: 0, // floor-out 的高度
+    }
+  },
+  props: {
+    floorsArr: {
+      type: Array,
+      default: () => {
+        return []
+      },
+    }
+  },
+  methods: {
+    /**
+     * @description 点击上箭头,marginTop<0时执行楼层滚动
+     */
+    increase() {
+      const marginTop = parseInt(this.marginTop)
+      marginTop < 0 && this.changeFloor(1, this.currIndex)
+    },
+    /**
+     * @description 点击下箭头,marginTop小于最大值marginTopMax时,执行楼层滚动
+     */
+    decrease() {
+      const marginTop = Math.abs(parseInt(this.marginTop)),
+      marginTopMax = Math.abs(parseInt(this.marginTopMax))
+      marginTop < marginTopMax && this.changeFloor(-1, this.currIndex)
+    },
+    init() {
+      // 修复在设备设施页面中,楼层组件不够 8个楼层时,出现的样式问题,
+      this.conHeight = this.floorsArr.length * 37.5
+      this.conHeight = this.conHeight >= 300 ? 300 : this.conHeight
+      this.showNumber = this.floorsArr.length > 8 ? 8 : this.floorsArr.length
+
+      this.marginTopMax = -(this.floorsArr.length - this.showNumber) * this.height
+      this.changeFloor(0, 0);
+      this.tabFloor(this.floorsArr[0], 0);
+    },
+    /**
+     * @name changeFloor
+     * @param {Number} flag 1:向上滚动楼层, -1向下滚动 , 0:进入页面初始化时,执行位置处理
+     * @description 点击图例下方的,上下切换按钮
+     */
+    changeFloor(flag, index) {
+      const len = this.floorsArr.length
+      this.currIndex = index
+      // 点击上箭头
+      if (flag === 1) {
+        index--
+        this.currIndex = index
+      } else if (flag === -1) {
+        //点击下箭头
+        index++
+        this.currIndex = index
+      }
+      this.handlePosition(flag, index, len)
+    },
+    /**
+     * @name tabFloor
+     * @param {Object} item 选中的楼层信息
+     * @param {Number} index 楼层信息在floorsArr数组中的位置
+     */
+    tabFloor(item, index) {
+      this.currentFloorId = item.FloorId;
+      this.$emit("emitFloor", item)
+      this.handlePosition(2, index, this.floorsArr.length)
+    },
+    /**
+     * @description 楼层位置动画处理
+     * @param flag 1:向上滚动楼层, -1向下滚动 , 0:进入页面初始化时,执行位置处理 2:直接点击楼层
+     * @param index 楼层 floorsArr
+     * @param len floorsArr
+     */
+    handlePosition(flag, index, len) {
+      // 取出当前 marginTop
+      let marginTop = parseInt(this.marginTop)
+      switch (flag) {
+        // 初始化进入页面,位置处理
+        case 0:
+        // 直接点击楼层,滚动楼层
+        case 2:
+          // 将 marginTop 设置为对应的index 应滚动的距离
+          marginTop = -index * this.height
+          // marginTop 过大时,取最大值marginTopMax
+          if (Math.abs(marginTop) >= Math.abs(this.marginTopMax)) {
+            marginTop = parseInt(this.marginTopMax)
+          }
+          // marginTop>0时,取0,防止楼层上边出现空白
+          marginTop = marginTop >= 0 ? 0 : marginTop
+          // index为0,marginTop设置为0
+          index == 0 && (marginTop = 0)
+          // index为最后一个,设置为最大marginTopMax
+          index == len - 1 && (marginTop = parseInt(this.marginTopMax))
+          this.marginTop = marginTop + 'px'
+          break
+        //  1:向上滚动楼层
+        case 1:
+          this.marginTop = marginTop + this.height + 'px'
+          break
+        // -1向下滚动楼层
+        case -1:
+          this.marginTop = marginTop + this.height * -1 + 'px'
+          break
+        default:
+          break
+      }
+    },
+  },
+  watch: {
+    floorsArr: {
+      handler() {
+        this.init()
+      },
+      immediate: true,
+      deep: true
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.floor-box {
+  .floor-list {
+    width: 44px;
+    // height: 212px;
+    background: rgba(255, 255, 255, 1);
+    box-shadow: 0px 2px 15px 0px rgba(31, 36, 41, 0.08);
+    border-radius: 2px;
+    position: relative;
+    padding: 6px 4px;
+    text-align: center;
+    .floor-out {
+      // max-height: 300px; //TODO:
+      min-height: 38px;
+      overflow: hidden;
+      position: relative;
+      overflow-y: auto;
+      &::-webkit-scrollbar {
+        display: none;
+      }
+
+      .floor-center {
+        transition: all linear 0.5s;
+        .floor-item {
+          line-height: 28px;
+          height: 28px;
+          cursor: pointer;
+          position: relative;
+          &::after {
+            position: absolute;
+            left: 50%;
+            margin-left: -20%;
+            bottom: -6px;
+            content: "";
+            width: 14px;
+            height: 1px;
+            background: rgba(195, 199, 203, 1);
+            border: 0px solid rgba(228, 229, 231, 1);
+          }
+          & + .floor-item {
+            margin-top: 10px;
+          }
+        }
+      }
+    }
+
+    .icon-top {
+      cursor: pointer;
+      height: 18px;
+      img {
+        width: 18px;
+        height: 100%;
+        margin-top: -10px;
+      }
+    }
+    .icon-bottom {
+      cursor: pointer;
+      height: 18px;
+      img {
+        width: 18px;
+        height: 100%;
+        margin-top: -10px;
+      }
+    }
+    .isActive {
+      border-radius: 4px;
+      color: #025baa;
+      background: #e1f2ff;
+    }
+  }
+  .disabled {
+    cursor: not-allowed !important;
+  }
+}
+</style>

+ 53 - 40
src/components/edit/left_toolbar.vue

@@ -145,6 +145,9 @@
         </div>
       </div>
     </transition>
+    <!-- 左侧导航蒙版 -->
+    <div class="left_toolbar_mask" v-show="isCopy=='true'">
+    </div>
   </div>
 </template>
 <script>
@@ -283,13 +286,14 @@ export default {
         { name: "绘制", id: "draw" },
         { name: "点选", id: "select" }
       ],
-      tabActive: "select"
+      tabActive: "select",
     };
   },
   computed: {
     ...mapState({
       GraphCategoryIds: "GraphCategoryIds",
-      GraphElement: "GraphElement"
+      GraphElement: "GraphElement",
+      isCopy:'isCopy'
     })
   },
   methods: {
@@ -312,27 +316,27 @@ export default {
       });
       items.isChoice = true;
       this.$emit("setCmdType", items.type);
-      if (items.name == "画多边形"){
-        bus.$emit('changeDrawType','draw')
+      if (items.name == "画多边形") {
+        bus.$emit("changeDrawType", "draw");
         const item = {
-            "Color":"#57C5FC",
-            "Deleted":false,
-            "FillColor":"#57c5fc0F",
-            "Id":"-10",
-            "InfoLocal":[],
-            "InfoTypeId":[],
-            "LineDash":"solid",
-            "LineWidth":2,
-            "Name":"",
-            "SubType":"CUSTOM",
-            "Type":"Zone",
-            "Unit":"",
-            "Url":"137ee878925448a699ec10c33e67fc95"
-        }
+          Color: "#57C5FC",
+          Deleted: false,
+          FillColor: "#57c5fc0F",
+          Id: "-10",
+          InfoLocal: [],
+          InfoTypeId: [],
+          LineDash: "solid",
+          LineWidth: 2,
+          Name: "",
+          SubType: "CUSTOM",
+          Type: "Zone",
+          Unit: "",
+          Url: "137ee878925448a699ec10c33e67fc95"
+        };
         this.$emit("toolActionClick", item);
       }
     },
-   async showDrawer(item) {
+    async showDrawer(item) {
       this.showDrawerItem = item;
       this.isExtract = false;
       if (item.isChoice) {
@@ -351,19 +355,19 @@ export default {
         // 接口请求
         this.itemList = [];
         this.spinning = true;
-      //   const data = {
-      //     GraphCategoryIds: this.categoryId,
-      //     Type: item.type
-      //   };
-      // await  queryGroup(data).then(res => {
-      //     this.itemList = res.Data;
-      //   });
+        //   const data = {
+        //     GraphCategoryIds: this.categoryId,
+        //     Type: item.type
+        //   };
+        // await  queryGroup(data).then(res => {
+        //     this.itemList = res.Data;
+        //   });
         const arr = {
           InfoSystems: this.categoryIdS,
           Type: item.type,
-          categoryId:this.categoryId
+          categoryId: this.categoryId
         };
-       await graphElementGroup(arr).then(res => {
+        await graphElementGroup(arr).then(res => {
           this.spinning = false;
           res.Data.map(item => {
             this.itemList.push(item);
@@ -381,6 +385,8 @@ export default {
     getSelectId(data) {
       this.categoryIdS = data;
       this.drawerVisible = false;
+      // 同步选择原件数据
+      bus2.$emit('getCategroyIdS',data)
     },
     onClose() {
       this.visible = false;
@@ -442,7 +448,7 @@ export default {
       }
     },
     getBus() {
-      bus2.$off('exportItem');
+      bus2.$off("exportItem");
       bus2.$on("exportItem", data => {
         this.data = [];
         if (data.length) {
@@ -451,8 +457,8 @@ export default {
           for (let i = 0; i < this.GraphElement.length; i++) {
             const t = this.GraphElement[i];
             for (let j = 0; j < data.length; j++) {
-              if(t.Type == data[j].type){
-                if (t.InfoTypeId.indexOf(data[j].key) > -1){
+              if (t.Type == data[j].type) {
+                if (t.InfoTypeId.indexOf(data[j].key) > -1) {
                   const obj = {
                     key: data[j].key,
                     name: t.Name,
@@ -461,20 +467,20 @@ export default {
                     type: data[j].type,
                     address: data[j].address,
                     id: t.Id
-                  }
+                  };
                   if (!map[t.Id]) {
-                    map[t.Id] = obj
+                    map[t.Id] = obj;
                   } else {
-                    map[t.Id].number += obj.number
-                    map[t.Id].key += obj.key
+                    map[t.Id].number += obj.number;
+                    map[t.Id].key += obj.key;
                   }
                 }
               }
             }
           }
           try {
-            for(const k in map) {
-              this.data.push(map[k])
+            for (const k in map) {
+              this.data.push(map[k]);
             }
           } catch (err) {
             console.log(err);
@@ -502,7 +508,7 @@ export default {
     changeDrawType(v) {
       // bus.$emit("changeDrawType", v.target.value);
       bus.$emit("changeDrawType", v);
-    }
+    },
   },
   watch: {
     cmdType(cmd) {
@@ -552,8 +558,6 @@ export default {
       obj[arr[0]] = arr[1];
     });
     this.categoryId = obj.categoryId;
-    // this.categoryIdS.push(obj.categoryId);
-    this.categoryId;
   }
 };
 </script>
@@ -836,5 +840,14 @@ export default {
     background: #c3c7cb;
     margin: 0 auto;
   }
+  .left_toolbar_mask{
+    position: absolute;
+    width: 100%;
+    height:e("calc(100% - 56px)");
+    background: rgba(0, 0, 0, 0.11);
+    left: 0;
+    top: 56px;
+    cursor:not-allowed;
+  }
 }
 </style>

+ 59 - 25
src/components/edit/right_toolbar.vue

@@ -24,16 +24,31 @@
       </a-tab-pane>
       <a-tab-pane key="2" tab="元素" force-render>
         <div class="element">
-          <a-input-search placeholder="搜索" style="margin-bottom: 12px;" v-model="key" @search="onSearch" />
+          <a-input-search
+            placeholder="搜索"
+            style="margin-bottom: 12px;"
+            v-model="key"
+            @search="onSearch"
+          />
           <ul class="element-list">
-            <li v-for="ele in elementData" :key="ele.id" @click="clickElement(ele)" v-show="key?ele.name.search(key) != -1:true">
-              <el-image style="width: 45px; height: 26px; margin-top: 6px;" :src="ele.data.Properties.IconUrl" fit="contain"></el-image>
+            <li
+              v-for="ele in elementData"
+              :key="ele.id"
+              @click="clickElement(ele)"
+              v-show="key?ele.name.search(key) != -1:true"
+            >
+              <el-image
+                style="width: 45px; height: 26px; margin-top: 6px;"
+                :src="ele.data.Properties.IconUrl"
+                fit="contain"
+              ></el-image>
               <span class="element-name">{{ele.name}}</span>
             </li>
           </ul>
         </div>
       </a-tab-pane>
     </a-tabs>
+    <div class="right_toolbar_mask"  v-show="isCopy=='true'"></div>
   </div>
 </template>
 <script>
@@ -42,7 +57,7 @@ import bus from "@/bus";
 import bus2 from "@/bus2";
 import { SImageMarkerItem } from "@/lib/items/SImageMarkerItem";
 import { SImageLegendItem } from "@/lib/items/SImageLegendItem";
-
+import { mapState } from "vuex";
 const msgList = [
   {
     msg: "",
@@ -89,8 +104,13 @@ export default {
   components: {
     attrSelect
   },
+   computed: {
+    ...mapState({
+      isCopy:'isCopy'
+    })
+  },
   created() {
-    this.listenElementData();
+    this.listenElementData()
   },
   data() {
     return {
@@ -99,13 +119,13 @@ export default {
       elementData: [],
       key: "",
       isLock: true,
-      aspectRatio: 1,// 元素宽高比
+      aspectRatio: 1, // 元素宽高比
     };
   },
   methods: {
     // 获取元素数据
     listenElementData() {
-      bus2.$off('elementDataChange')
+      bus2.$off("elementDataChange");
       bus2.$on("elementDataChange", val => {
         this.elementData = [];
         if (val.Nodes.length) {
@@ -117,7 +137,6 @@ export default {
         if (val.Relations.length) {
           this.elementData = this.elementData.concat(val.Relations);
         }
-        console.log(this.elementData);
       });
     },
     callback(key) {
@@ -131,7 +150,7 @@ export default {
     lockItem() {
       this.isLock = !this.isLock;
       if (this.isLock) {
-        let width,height;
+        let width, height;
         this.msgList.forEach(item => {
           if (item.name == "Width") {
             width = item.msg;
@@ -148,7 +167,7 @@ export default {
         if (this.isLock) {
           const height = item.msg / this.aspectRatio;
           this.msgList.find(item => {
-            return item.name == "Height"
+            return item.name == "Height";
           }).msg = height;
           bus.$emit("itemHeight", height);
         }
@@ -157,7 +176,7 @@ export default {
         if (this.isLock) {
           const width = item.msg * this.aspectRatio;
           this.msgList.find(item => {
-            return item.name == "Width"
+            return item.name == "Width";
           }).msg = width;
           bus.$emit("itemWidth", width);
         }
@@ -173,21 +192,21 @@ export default {
           }
         });
         bus.$emit("itemPositon", x, y);
-      } else if (item.name == 'Angle') {
+      } else if (item.name == "Angle") {
         if (item.msg.length > 0 && !isNaN(Number(item.msg))) {
           if (item.msg > 360) {
-            item.msg = 360
+            item.msg = 360;
           }
           if (item.msg < -360) {
-            item.msg = -360
+            item.msg = -360;
           }
-          bus.$emit('itemAngle', item.msg)
+          bus.$emit("itemAngle", item.msg);
         }
       }
     },
     // 点击选中元素
-    clickElement(ele){
-      bus.$emit('toggleItem',ele)
+    clickElement(ele) {
+      bus.$emit("toggleItem", ele);
     }
   },
   watch: {
@@ -207,14 +226,14 @@ export default {
           if (item.name == "Height") {
             item.msg = 0;
           }
-          if (item.name == 'Angle') {
-            item.msg = '0'
+          if (item.name == "Angle") {
+            item.msg = "0";
           }
         });
         this.aspectRatio = 1;
       } else {
         // 属性输入框宽高显示的数值
-        let inputW,inputH;
+        let inputW, inputH;
         this.msgList.forEach(item => {
           const Item = newVal.itemList[0];
           const width = Item.boundingRect().width;
@@ -238,7 +257,9 @@ export default {
               item.msg = Item.img.width;
             }
             // 针对图片及Icon
-            if (Item instanceof SImageMarkerItem || Item instanceof SImageLegendItem) {
+            if (
+              Item instanceof SImageMarkerItem
+            ) {
               item.disable = false;
             } else {
               item.disable = true;
@@ -252,7 +273,9 @@ export default {
               item.msg = Item.img.height;
             }
             // 针对图片及Icon
-            if (Item instanceof SImageMarkerItem || Item instanceof SImageLegendItem) {
+            if (
+              Item instanceof SImageMarkerItem
+            ) {
               item.disable = false;
             } else {
               item.disable = true;
@@ -261,11 +284,12 @@ export default {
           }
           if (item.name == "Angle") {
             if (Item instanceof SImageLegendItem) {
-              item.disable = false
+              item.disable = false;
+              item.msg = Item.img.rotate;
             } else {
-              item.disable = true
+              item.disable = true;
+              item.msg = 0;
             }
-            item.msg = Item.img.rotate
           }
         });
         this.aspectRatio = inputW / inputH;
@@ -286,6 +310,7 @@ li {
   height: 100%;
   background: rgba(255, 255, 255, 1);
   box-shadow: 1px 2px 10px 0px rgba(0, 0, 0, 0.11);
+  position: relative;
   .atabless {
     height: 100%;
     width: 100%;
@@ -360,6 +385,15 @@ li {
       }
     }
   }
+  .right_toolbar_mask{
+    width: 280px;
+    height: 100%;
+    background: rgba(0, 0, 0, 0.11);
+    cursor:not-allowed;
+    position: absolute;
+    left: 0;
+    top: 0;
+  }
 }
 /deep/ .ant-tabs .ant-tabs-top-content.ant-tabs-content-animated {
   height: calc(100% - 60px);

File diff suppressed because it is too large
+ 662 - 442
src/components/edit/top_toolbar.vue


+ 330 - 81
src/components/mapClass/EditScence.ts

@@ -36,6 +36,8 @@ export class EditScence extends SGraphScene {
     undoStack = new SUndoStack();
     /** 判断是否为苹果电脑 */
     public isMac = /macintosh|mac os x/i.test(navigator.userAgent);
+    /** 是否为复制状态 */
+    public isCopy = "false"
     /** 命令 1 绘制直线 */
     private cmd = 'choice';
     /** 获取当前状态 */
@@ -65,10 +67,10 @@ export class EditScence extends SGraphScene {
     isAbsorbing: boolean = false;
     /** 吸附展示item    */
     highLight: HighlightItem | null = null;
-    /** 矩形选择区域  */
-    rectSelectItem: SRectSelectItem | null = null;
-    /** 框选    */
-    isRectSelection: number = 0;
+    // /** 矩形选择区域  */
+    // rectSelectItem: SRectSelectItem | null = null;
+    // /** 框选    */
+    // isRectSelection: number = 0;
     /** 当前选中焦点Item */
     focusItem: SGraphItem | null = null;
     /** 当前选中焦点ItemList */
@@ -104,7 +106,6 @@ export class EditScence extends SGraphScene {
         ItemColor.virtualWallColor = new SColor("#d4d4d4")
         ItemColor.selectColor = new SColor("#f0f0f0")
         ItemColor.spaceBorderColor = new SColor("#d4d4d4");
-        console.log('isMac',this.isMac)
     }
     /** 绘制图例样式 */
     _legend: any | null = null;
@@ -261,7 +262,7 @@ export class EditScence extends SGraphScene {
         // 起始锚点
         item.startAnchor = anc;
         if (anc) {
-            anc.parent ?.connect('changePos', item, item.changePos)
+            anc.parent?.connect('changePos', item, item.changePos)
             item.anchor1ID = anc.id;
             item.node1Id = anc.parent.id;
         }
@@ -295,7 +296,8 @@ export class EditScence extends SGraphScene {
                 TextPos: { X: 0, Y: 0 },
                 InfoTypeId: this._legend.InfoTypeId.length ? this._legend.InfoTypeId : [],
                 InfoSystemId: this._legend.InfoSystemId ? this._legend.InfoSystemId : '',
-                InfoLocal: this._legend.InfoLocal.length ? this._legend.InfoLocal : []
+                InfoLocal: this._legend.InfoLocal.length ? this._legend.InfoLocal : [],
+                lengendName: this._legend.Name, //图例名称
             },
         }
         let Polylines = null;
@@ -352,7 +354,8 @@ export class EditScence extends SGraphScene {
                     TextPos: { X: item.data.Location.Points[0].X, Y: -item.data.Location.Points[0].Y },
                     InfoTypeId: this._legend.InfoTypeId.length ? this._legend.InfoTypeId : [],
                     InfoSystemId: this._legend.InfoSystemId ? this._legend.InfoSystemId : '',
-                    InfoLocal: this._legend.InfoLocal.length ? this._legend.InfoLocal : []
+                    InfoLocal: this._legend.InfoLocal.length ? this._legend.InfoLocal : [],
+                    lengendName: this._legend.Name, //图例名称
                 },
             }
             let Polylines = null;
@@ -402,6 +405,7 @@ export class EditScence extends SGraphScene {
         this.Markers.push(item);
         this.grabItem == null;
         this.focusItem = item;
+        this.undoStack.push(new SGraphAddCommand(this, item));
         this.finishCreated(item);
         this.scenceUpdate(this);
     }
@@ -438,6 +442,7 @@ export class EditScence extends SGraphScene {
         this.focusItem = item;
         this.cmd = 'choice';
         this.finishCreated(item);
+        this.undoStack.push(new SGraphAddCommand(this, item));
         this.scenceUpdate(this);
     }
 
@@ -463,8 +468,8 @@ export class EditScence extends SGraphScene {
                 Url: '/serve/topology-wanda/Picture/query/' + this._legend.Url,
                 Num: 1, // 此num与信息工程化得num无关
                 Size: {
-                    Width: this._legend.Size?this._legend.Size.Width?this._legend.Size.Width:32:32,  //icon 的宽
-                    Height: this._legend.Size?this._legend.Size.Height?this._legend.Size.Height:32:32,   //icon 的高
+                    Width: this._legend.Size ? this._legend.Size.Width ? this._legend.Size.Width : 32 : 32,  //icon 的宽
+                    Height: this._legend.Size ? this._legend.Size.Height ? this._legend.Size.Height : 32 : 32,   //icon 的高
                 },
                 font: 16,    //font
                 color: "#1F2429",  //字体颜色
@@ -485,6 +490,7 @@ export class EditScence extends SGraphScene {
         this.grabItem = null;
         this.focusItem = item;
         this.finishCreated(item);
+        this.undoStack.push(new SGraphAddCommand(this, item));
         this.scenceUpdate(this);
         if (event.ctrlKey) {
             this.cmd = cmd;
@@ -713,7 +719,7 @@ export class EditScence extends SGraphScene {
                 fillColorT = fillColor + Transparency[15];
                 if (this.focusItem instanceof SSCPZZoneLegendItem || this.focusItem instanceof SFHFQZoneLegendItem) {
                     const sc = new SColor(this.focusItem.fillColor);
-                    const alp = ((sc.alpha/255)*100).toFixed()
+                    const alp = ((sc.alpha / 255) * 100).toFixed()
                     fillColorT = fillColor + Transparency[alp];
                     // fillColorT = fillColor + Transparency[80];
                 }
@@ -740,7 +746,7 @@ export class EditScence extends SGraphScene {
      * 更新工程信息化的相关数据
      * @param AttachObjectIds Array
      */
-    upadatAttachObjectIds(AttachObjectIds: []): void {
+    upadatAttachObjectIds(AttachObjectIds: [], flag: boolean): void {
         if (this.focusItem) {
             this.focusItem.data.AttachObjectIds = AttachObjectIds;
             // 重新选中focusitem
@@ -754,15 +760,18 @@ export class EditScence extends SGraphScene {
                 item instanceof SFHFQZoneLegendItem
             ) {
                 let arr = item.data.AttachObjectIds;
-                if (arr && arr.length && arr[arr.length - 1].name) {
+                if (arr && arr.length && arr[arr.length - 1].name && flag) {
                     let name = item.name;
-                    if (name) {
-                        item.name = name + `\n${arr[arr.length - 1].name}`;
-                        item.text = name + `\n${arr[arr.length - 1].name}`;
-                    } else {
-                        item.name = arr[arr.length - 1].name;
-                        item.text = arr[arr.length - 1].name;
-                    }
+                    let nameArr = name.split("\n");
+                    // if (nameArr[nameArr.length - 1] != arr[arr.length - 1].name) //最后一行的名称和将要添加的名称如果不同(增加)
+                    if (nameArr.indexOf(arr[arr.length - 1].name) == -1) //将要添加的名称和每一行的名称都不同(新增)
+                        if (name) {
+                            item.name = name + `\n${arr[arr.length - 1].name}`;
+                            item.text = name + `\n${arr[arr.length - 1].name}`;
+                        } else {
+                            item.name = arr[arr.length - 1].name;
+                            item.text = arr[arr.length - 1].name;
+                        }
                 }
                 // 绑定工程信息化数据后设置状态
                 if (item.data.AttachObjectIds && item.data.AttachObjectIds.length) {
@@ -777,7 +786,7 @@ export class EditScence extends SGraphScene {
     /**
      * 自定义多边形修改背景色
     */
-    updateCustomBgColor(val: string):void{
+    updateCustomBgColor(val: string): void {
         if (this.focusItem) {
             const newMsg = new SColor(val);
             const oldMsg = this.focusItem.fillColor;
@@ -789,7 +798,7 @@ export class EditScence extends SGraphScene {
     /**
      * 自定义多边形修改边框色
     */
-    updateCustomBdColor(val: string):void{
+    updateCustomBdColor(val: string): void {
         if (this.focusItem) {
             const newMsg = new SColor(val);
             const oldMsg = this.focusItem.strokeColor;
@@ -801,6 +810,10 @@ export class EditScence extends SGraphScene {
      * 删除指定item
      */
     deleiteItem(): void {
+        // 如果为复制状态则删除失效
+        if (this.isCopy == "true") {
+            return
+        }
         if (this.focusItem) {
             if ((this.focusItem instanceof SZoneLegendItem ||
                 this.focusItem instanceof SSCPZZoneLegendItem ||
@@ -949,10 +962,23 @@ export class EditScence extends SGraphScene {
         } else {
             this.undoStack.redo();
             this.scenceUpdate(this);
+            const command = this.undoStack.command(this.undoStack.index);
+            // 如果为删除命令,重做需要讲数据数组中的item重新删去
+            if (command && command.command == "DeleteCommand") {
+                this.clearDataItem(command.item)
+            } else if (command && command.command == "DeleteCommandList") {
+                command.itemList.forEach(element => {
+                    this.clearDataItem(element)
+                });
+            } else if (command && command.command == "SGraphAddCommand") {
+                this.addDataItem(command.item)
+            } else if (command && command.command == "AddListCommand") {
+                command.itemList.forEach(element => {
+                    this.addDataItem(element)
+                });
+            }
         }
-
     }
-
     /**
     * 执行重做操作执行
     */
@@ -960,11 +986,75 @@ export class EditScence extends SGraphScene {
         if (this.grabItem && this.grabItem.undo) {
             this.grabItem.undo()
         } else {
+            const command = this.undoStack.command(this.undoStack.index);
+            // 如果为删除命令,重做需要讲数据数组中的item重新放回data中
+            if (command && command.command == "DeleteCommand") {
+                this.addDataItem(command.item)
+            } else if (command && command.command == "DeleteCommandList") {
+                command.itemList.forEach(element => {
+                    this.addDataItem(element)
+                });
+            } else if (command && command.command == "SGraphAddCommand") {
+                this.clearDataItem(command.item)
+            } else if (command && command.command == "AddListCommand") {
+                command.itemList.forEach(element => {
+                    this.clearDataItem(element)
+                });
+            }
             this.undoStack.undo();
             this.scenceUpdate(this);
         }
     }
     /**
+     * 清除data数据中指定的item
+     */
+    clearDataItem(commanditem: any) {
+        let a = -1
+        this.Nodes.forEach((item: any, index: number) => {
+            if (item.id == commanditem.id) {
+                a = index
+            }
+        });
+        if (a > -1) {
+            this.Nodes.splice(a, 1);
+        }
+        let b = -1;
+        this.Markers.forEach((item: any, index: number) => {
+            if (item.id == commanditem.id) {
+                b = index
+            }
+        });
+        if (b > -1) {
+            this.Markers.splice(b, 1);
+        }
+        let c = -1;
+        this.Relations.forEach((item: any, index: number) => {
+            if (item.id == commanditem.id) {
+                c = index
+            }
+        });
+        if (c > -1) {
+            this.Relations.splice(c, 1);
+        }
+    }
+
+    /**
+     * 增加指定Item到data数据中
+     */
+
+    addDataItem(item: any) {
+        //清空指定的item
+        this.clearDataItem(item);
+        // 重新填入
+        if (item instanceof STextMarkerItem || item instanceof SImageMarkerItem || item instanceof SLineMarkerItem || item instanceof SCustomLegendItem) {
+            this.Markers.push(item)
+        } else if (item instanceof SFHFQZoneLegendItem || item instanceof SSCPZZoneLegendItem || item instanceof SImageLegendItem || item instanceof SZoneLegendItem) {
+            this.Nodes.push(item)
+        } else if (item instanceof TipelineItem) {
+            this.Relations.push(item)
+        }
+    }
+    /**
      * 完成事件创建的回调函数
      */
     finishCreated(item: any) {
@@ -1044,6 +1134,11 @@ export class EditScence extends SGraphScene {
             return this.grabItem.onMouseDown(event);
         }
         switch (this.cmd) {
+            case 'choice':
+                if (!super.onMouseDown(event)) {
+                    this.addRectSelect(event);
+                }
+                break
             case 'baseLine':
                 this.addLine(event);
                 break;
@@ -1084,7 +1179,7 @@ export class EditScence extends SGraphScene {
             this.highLight.visible = false;
             this.absorbSpace(event);
         }
-        if (this.grabItem){
+        if (this.grabItem) {
             if (this.grabItem instanceof TipelineItem) {
                 const anc = this.clickIsAnchor(event);
                 if (anc) {
@@ -1093,6 +1188,8 @@ export class EditScence extends SGraphScene {
                     event.y = p.y;
                     return this.grabItem.onMouseMove(event);
                 }
+            } else if (this.grabItem instanceof SRectSelectItem) {
+                return this.grabItem.onMouseMove(event);
             }
         }
         return super.onMouseMove(event)
@@ -1109,6 +1206,14 @@ export class EditScence extends SGraphScene {
             } else if (this.grabItem instanceof TipelineItem) {
                 this.updateTipeAnc(event);
                 return true;
+            } else if (this.grabItem instanceof SRectSelectItem) {
+                this.groupSelect(event.ctrlKey);
+                this.removeItem(this.grabItem);
+                this.grabItem = null;
+                if (this.view) {
+                    this.view.update()
+                }
+                return true;
             }
             return this.grabItem.onMouseUp(event);
         }
@@ -1142,7 +1247,7 @@ export class EditScence extends SGraphScene {
             this.deleiteItem()
         }
         // 删除键功能--兼容苹果mac
-        if (event.code == 'Backspace' && this.isMac){
+        if (event.code == 'Backspace' && this.isMac) {
             this.deleiteItem()
         }
         // 复制粘贴
@@ -1152,7 +1257,7 @@ export class EditScence extends SGraphScene {
                 this.copy()
             } else if (event.code == 'KeyV') {
                 console.log('ctrl v')
-                this.paste()
+                // this.paste()
             }
         }
         return false
@@ -1162,7 +1267,7 @@ export class EditScence extends SGraphScene {
      * 复制
      *
      */
-    copy(){
+    copy() {
         if (this.selectContainer.itemList.length) {
             this.copyString = {
                 Nodes: [],
@@ -1182,15 +1287,15 @@ export class EditScence extends SGraphScene {
             })
             // 生成复制字符串
             console.log(this.copyString)
-            return
             // 获取input dom
             const input = document.createElement('input');
             input.setAttribute('id', 'COPYINPUT')
             input.value = JSON.stringify(this.copyString)
+            sessionStorage.setItem("copyString", input.value);
             document.body.appendChild(input);
             input.select()
             document.execCommand('copy');
-            input.style.display='none';
+            input.style.display = 'none';
             console.log(input.value, Date.now());
             document.body.removeChild(input)
         }
@@ -1200,25 +1305,27 @@ export class EditScence extends SGraphScene {
      * 粘贴
      *
      */
-    paste(){
+    paste() {
         const parserData = new STopologyParser(null);
         // 需要深拷贝
         parserData.parseData(JSON.parse(JSON.stringify(this.copyString)))
-        // 不需要复制区域
-        // parserData.zoneLegendList.forEach(t => {
-        //     if (t instanceof SCustomLegendItem) {
-        //         if (this.view) {
-        //             t.pos.x += 10 / this.view.scale
-        //             t.pos.y += 10 / this.view.scale
-        //         }
-        //         this.addItem(t)
-        //         this.Nodes.push(t);
-        //         graphItemList.push(t)
-        //     }
-        //  // 加到node
-        //  // 加命令
-        // })
         const graphItemList = [];
+        // 不需要复制区域
+        parserData.zoneLegendList.forEach(t => {
+            // if (t instanceof SCustomLegendItem) {
+            if (this.view) {
+                t.pos.x += 10 / this.view.scale
+                t.pos.y += 10 / this.view.scale
+            }
+            t.moveable = true;
+            this.addItem(t)
+            this.Nodes.push(t);
+            this.selectContainer.toggleItem(t);
+            graphItemList.push(t)
+            // }
+            // 加到node
+            // 加命令
+        })
         parserData.imageLegendList.forEach(t => {
             if (this.view) {
                 t.pos.x += 10 / this.view.scale
@@ -1227,6 +1334,7 @@ export class EditScence extends SGraphScene {
             t.moveable = true;
             this.addItem(t)
             this.Nodes.push(t);
+            this.selectContainer.toggleItem(t);
             graphItemList.push(t)
         })
         parserData.imageMarkerList.forEach(t => {
@@ -1237,6 +1345,7 @@ export class EditScence extends SGraphScene {
             t.moveable = true;
             this.addItem(t)
             this.Markers.push(t);
+            this.selectContainer.toggleItem(t);
             graphItemList.push(t)
         })
         parserData.lineMarkerList.forEach(t => {
@@ -1247,6 +1356,7 @@ export class EditScence extends SGraphScene {
             t.moveable = true;
             this.addItem(t)
             this.Markers.push(t);
+            this.selectContainer.toggleItem(t);
             graphItemList.push(t)
         })
         parserData.textMarkerList.forEach(t => {
@@ -1257,6 +1367,7 @@ export class EditScence extends SGraphScene {
             t.moveable = true;
             this.addItem(t)
             this.Markers.push(t);
+            this.selectContainer.toggleItem(t);
             graphItemList.push(t)
         })
         parserData.relationList.forEach(t => {
@@ -1268,6 +1379,7 @@ export class EditScence extends SGraphScene {
             t.moveable = true;
             this.addItem(t)
             this.Relations.push(t);
+            this.selectContainer.toggleItem(t);
             graphItemList.push(t)
         })
         this.scenceUpdate(this);
@@ -1280,29 +1392,30 @@ export class EditScence extends SGraphScene {
      * 跨页面粘贴
      *
      */
-    crossPagePaste(crossPageString: string){
+    crossPagePaste(crossPageString: string) {
         try {
             console.log(crossPageString);
             const pageObj = JSON.parse(crossPageString)
-            
             const parserData = new STopologyParser(null);
+            const graphItemList = [];
             // 需要深拷贝
             parserData.parseData(JSON.parse(JSON.stringify(pageObj)))
             // 不需要复制区域
-            // parserData.zoneLegendList.forEach(t => {
-            //     if (t instanceof SCustomLegendItem) {
-            //         if (this.view) {
-            //             t.pos.x += 10 / this.view.scale
-            //             t.pos.y += 10 / this.view.scale
-            //         }
-            //         this.addItem(t)
-            //         this.Nodes.push(t);
-            //         graphItemList.push(t)
-            //     }
-            //  // 加到node
-            //  // 加命令
-            // })
-            const graphItemList = [];
+            parserData.zoneLegendList.forEach(t => {
+                // if (t instanceof SCustomLegendItem) {
+                if (this.view) {
+                    t.pos.x += 10 / this.view.scale
+                    t.pos.y += 10 / this.view.scale
+                }
+                t.moveable = true;
+                this.addItem(t)
+                this.Nodes.push(t);
+                this.selectContainer.toggleItem(t);
+                graphItemList.push(t)
+                // }
+                // 加到node
+                // 加命令
+            })
             parserData.imageLegendList.forEach(t => {
                 if (this.view) {
                     t.pos.x += 10 / this.view.scale
@@ -1311,6 +1424,7 @@ export class EditScence extends SGraphScene {
                 t.moveable = true;
                 this.addItem(t)
                 this.Nodes.push(t);
+                this.selectContainer.toggleItem(t);
                 graphItemList.push(t)
             })
             parserData.imageMarkerList.forEach(t => {
@@ -1321,6 +1435,7 @@ export class EditScence extends SGraphScene {
                 t.moveable = true;
                 this.addItem(t)
                 this.Markers.push(t);
+                this.selectContainer.toggleItem(t);
                 graphItemList.push(t)
             })
             parserData.lineMarkerList.forEach(t => {
@@ -1331,6 +1446,7 @@ export class EditScence extends SGraphScene {
                 t.moveable = true;
                 this.addItem(t)
                 this.Markers.push(t);
+                this.selectContainer.toggleItem(t);
                 graphItemList.push(t)
             })
             parserData.textMarkerList.forEach(t => {
@@ -1341,6 +1457,7 @@ export class EditScence extends SGraphScene {
                 t.moveable = true;
                 this.addItem(t)
                 this.Markers.push(t);
+                this.selectContainer.toggleItem(t);
                 graphItemList.push(t)
             })
             parserData.relationList.forEach(t => {
@@ -1352,19 +1469,35 @@ export class EditScence extends SGraphScene {
                 t.moveable = true;
                 this.addItem(t)
                 this.Relations.push(t);
+                this.selectContainer.toggleItem(t);
                 graphItemList.push(t)
             })
             this.scenceUpdate(this);
             if (graphItemList.length) {
-                this.AddListCommand(graphItemList)
+                this.AddListCommand(graphItemList);
             }
         } catch (e) {
             console.log(e);
         }
     }
 
+    /** 同类选中    */
+    selectSimilar() {
+        let typeList = [...new Set(this.selectContainer.itemList.map(item => { return item.data.GraphElementId }).filter(d => { return d }))];
+        this.selectContainer.clear();
+        this.Nodes.forEach(item => {
+            if (typeList.indexOf(item.data.GraphElementId) != -1)
+                this.selectContainer.toggleItem(item);
+        });
+        this.Relations.forEach(item => {
+            if (typeList.indexOf(item.data.GraphElementId) != -1)
+                this.selectContainer.toggleItem(item);
+        });
+        document.getElementById(`canvas`).focus();
+    }
+
     /** 类型转换    */
-    itemToType(obj:SGraphItem):String{
+    itemToType(obj: SGraphItem): String {
         if (obj instanceof STextMarkerItem) {
             return 'Markers'
         } else if (obj instanceof SImageMarkerItem) {
@@ -1393,6 +1526,10 @@ export class EditScence extends SGraphScene {
      * @return	boolean
      */
     onDoubleClick(event: SMouseEvent): boolean {
+        // 如果为复制状态则双击失效
+        if (this.isCopy == "true") {
+            return true
+        }
         if (!this.isEditStatus) {
             return true
         } else {
@@ -1416,7 +1553,7 @@ export class EditScence extends SGraphScene {
                 if (this.grabItem.status == SItemStatus.Create) {
                     if (this.grabItem.pointList.length) {
                         this.grabItem.endAnchor = anc;
-                        anc.parent ?.connect('changePos', this.grabItem, this.grabItem.changePos)
+                        anc.parent?.connect('changePos', this.grabItem, this.grabItem.changePos)
                     }
                     this.grabItem.anchor2ID = anc.id
                     this.grabItem.node2Id = anc.parent.id
@@ -1510,7 +1647,7 @@ export class EditScence extends SGraphScene {
                 if (this.grabItem.status == SItemStatus.Create) {
                     // 点击在item内、创建状态且端点列表不为空时将直线结束端点和item绑定
                     if (this.grabItem.line.length) {
-                        if (this.grabItem.startItem ?.id == item.id) {
+                        if (this.grabItem.startItem?.id == item.id) {
                             this.grabItem.endItem = null;
                         } else {
                             this.grabItem.endItem = item;
@@ -1524,7 +1661,7 @@ export class EditScence extends SGraphScene {
                     // 点击在item内、编辑状态且点击的为结束端点时
                     if (this.grabItem.curIndex == 1) {
                         // 直线关联的起始item是直线结束端点所在的item时,不吸附在点击item中心并将直线关联的结束item置为null
-                        if (this.grabItem.startItem ?.id == item.id) {
+                        if (this.grabItem.startItem?.id == item.id) {
                             this.grabItem.endItem = null;
                         } else {// 反正吸附,关联
                             this.grabItem.endItem = item;
@@ -1532,7 +1669,7 @@ export class EditScence extends SGraphScene {
                             item.connect('onMove', this.grabItem, this.grabItem.changePos);
                         }
                     } else if (this.grabItem.curIndex == 0) {
-                        if (this.grabItem.endItem ?.id == item.id) {
+                        if (this.grabItem.endItem?.id == item.id) {
                             this.grabItem.startItem = null;
                         } else {
                             this.grabItem.startItem = item;
@@ -1606,7 +1743,7 @@ export class EditScence extends SGraphScene {
         this.Nodes.forEach(image => {
             // image.showAnchor = false;
             if (image.anchorList && image.anchorList.length) {
-                if(image.img && image.img instanceof SImageItem) {
+                if (image.img && image.img instanceof SImageItem) {
                     let scenePoint = image.img.mapFromScene(event.x, event.y);
                     if (image.img.contains(scenePoint.x, scenePoint.y)) {
                         let anchor = image.anchorList[0]
@@ -1627,8 +1764,8 @@ export class EditScence extends SGraphScene {
                             len = dis;
                         }
                     }
-                // let scenePoint = image.mapFromScene(event.x, event.y);
-                // if (image.contains(scenePoint.x, scenePoint.y)) {
+                    // let scenePoint = image.mapFromScene(event.x, event.y);
+                    // if (image.contains(scenePoint.x, scenePoint.y)) {
                     // image.anchorList.forEach(anchor => {
                     //     let anchorPoint = anchor.mapToScene(0, 0);
                     //     let dis = SMathUtil.pointDistance(
@@ -1637,13 +1774,13 @@ export class EditScence extends SGraphScene {
                     //         anchorPoint.x,
                     //         anchorPoint.y
                     //     );
-                        // if (len < 0) {
-                        //     len = anchor.sceneDis;
-                        // }
-                        // if (dis < len) {
-                        //     minAnchor = anchor;
-                        //     len = dis;
-                        // }
+                    // if (len < 0) {
+                    //     len = anchor.sceneDis;
+                    // }
+                    // if (dis < len) {
+                    //     minAnchor = anchor;
+                    //     len = dis;
+                    // }
                     // })
                 }
             }
@@ -1863,10 +2000,10 @@ export class EditScence extends SGraphScene {
 
     /**
      * 图标旋转更新角度
-     * 
+     *
      * @param   ang 旋转角度
     */
-    updateItemAng(ang: number) :void{
+    updateItemAng(ang: number): void {
         if (this.focusItem) {
             if (this.focusItem instanceof SImageLegendItem) {
                 const oldMsg = this.focusItem.img.rotate;
@@ -1878,13 +2015,125 @@ export class EditScence extends SGraphScene {
         }
     }
 
-    /** 
+    /**
      * 框选
     */
     addRectSelect(event: SMouseEvent) {
         let point = new SPoint(event.x, event.y);
         let rect = new SRectSelectItem(null, point);
         this.addItem(rect);
-        this.rectSelectItem = rect;
+        this.grabItem = rect;
+    }
+
+    /**
+     * 计算框选交集
+    */
+    groupSelect(ctrl: boolean) {
+        if (!ctrl) {
+            this.selectContainer.clear()
+        }
+        if (this.grabItem instanceof SRectSelectItem) {
+            let left,top,w,h;
+            if(this.grabItem.startPoint.x < this.grabItem.endPoint.x) {
+                left = this.grabItem.startPoint.x;
+                w = this.grabItem.endPoint.x - this.grabItem.startPoint.x
+            } else {
+                left = this.grabItem.endPoint.x
+                w = this.grabItem.startPoint.x - this.grabItem.endPoint.x
+            }
+            if (this.grabItem.startPoint.y < this.grabItem.endPoint.y) {
+                top = this.grabItem.startPoint.y;
+                h = this.grabItem.endPoint.y - this.grabItem.startPoint.y
+            } else {
+                top = this.grabItem.endPoint.y;
+                h = this.grabItem.startPoint.y - this.grabItem.endPoint.y
+            }
+            const rect = new SRect(left,top,w,h);
+            this.arrToSelect(this.Nodes, rect)
+            this.arrToSelect(this.Markers, rect)
+            this.arrToSelect(this.Relations, rect)
+        }
+    }
+    /**
+     * 选中item:框选
+    */
+    private arrToSelect(arr: SGraphItem[], rect: SRect) {
+        if (Array.isArray(arr) && arr.length) {
+            arr.forEach(t => {
+                if (t.parent) {
+                    let temp = t.boundingRect();
+                    let lefttop = t.mapToScene(temp.left, temp.top)
+                    let rightbottom = t.mapToScene(temp.right, temp.bottom)
+                    let r = new SRect(lefttop, rightbottom)
+                    if (rect.isIn(r)) {
+                        this.selectContainer.toggleItem(t)
+                    }
+                }
+            })
+        }
+    }
+    /**
+     * 修改item样式
+     */
+    changeLengendItem(legend: any) {
+        if (this.focusItem) {
+            //   如果更改得item类相同,则不需要
+            if (this.focusItem.data.GraphElementId == legend.Id) {
+                return
+            }
+            const OutLine: any = []
+            if (this.focusItem.pointList) {
+                this.focusItem.pointList.forEach(item => {
+                    OutLine.push({ X: item.x, Y: item.y })
+                })
+            }
+            const SubType = legend.SubType ? legend.SubType : '';
+            const LegendData: Legend = {
+                ID: uuid(),
+                Name: this.focusItem.name,
+                GraphElementType: legend.Type,
+                Num: 1,
+                GraphElementId: legend.Id,
+                AttachObjectIds: this.focusItem.data.AttachObjectIds,
+                Type: "Zone",
+                Pos: { X: this.focusItem.data.Pos.X, Y: this.focusItem.data.Pos.Y },
+                OutLine: OutLine,
+                SubType: SubType,
+                Properties: {
+                    IconUrl: '/serve/topology-wanda/Picture/query/' + legend.Url,
+                    StrokeColor: legend.Color,
+                    FillColor: legend.FillColor,
+                    LineDash: legend.LineDash,
+                    LineWidth: legend.LineWidth,
+                    font: 14,
+                    color: "#1F2429",
+                    TextPos: { X: this.focusItem.data.Properties.TextPos.X, Y: this.focusItem.data.Properties.TextPos.Y },
+                    InfoTypeId: legend.InfoTypeId.length ? legend.InfoTypeId : [],
+                    InfoSystemId: legend.InfoSystemId ? legend.InfoSystemId : '',
+                    InfoLocal: legend.InfoLocal.length ? legend.InfoLocal : [],
+                    lengendName: legend.Name, //图例名称
+                },
+            }
+            let Polylines = null;
+            if (SubType == "SCPZ") {
+                Polylines = new SSCPZZoneLegendItem(null, LegendData);
+            } else if (SubType == "FHFQ") {
+                Polylines = new SFHFQZoneLegendItem(null, LegendData);
+            } else if (SubType == "CUSTOM") {
+                Polylines = new SCustomLegendItem(null, LegendData);
+            } else {
+                Polylines = new SZoneLegendItem(null, LegendData);
+            }
+            Polylines.selectable = true;
+            //设置状态
+            Polylines.status = SItemStatus.Normal;
+            // Polylines.moveable = true;
+            this.addItem(Polylines);
+            Polylines.connect("finishCreated", this, this.finishCreated);
+            // 删除item
+            this.deleiteItem();
+            this.grabItem = Polylines;
+            this.focusItem = Polylines;
+        }
     }
 }

+ 2 - 0
src/components/mapClass/SGraphAddListCommand.ts

@@ -11,6 +11,8 @@ import { SUndoCommand } from "@saga-web/base/lib";
 export class SGraphAddListCommand extends SGraphCommand {
     /** 命令item对象    */
     itemList: SGraphItem[];
+    /** 命令名称    */
+    readonly command: string = "AddListCommand"
     /** 命令item的父类   */
     parent: SGraphItem | null;
     constructor(scene: SGraphScene, itemList: SGraphItem[]) {

+ 3 - 0
src/components/mapClass/SGraphDeleteCommand.ts

@@ -12,6 +12,9 @@ import { SUndoCommand } from "@saga-web/base/lib";
 export class SGraphDeleteCommand extends SGraphCommand {
     /** 命令item对象    */
     item: SGraphItem;
+    desc:string ='DeleteCommand';
+      /** 命令名称    */
+    readonly command: string = "DeleteCommand"
     /** 命令item的父类   */
     parent: SGraphItem | null;
 

+ 3 - 0
src/components/mapClass/SGraphDeleteListCommand.ts

@@ -11,6 +11,9 @@ import { SUndoCommand } from "@saga-web/base/lib";
 export class SGraphDeleteListCommand extends SGraphCommand {
     /** 命令item对象    */
     itemList: SGraphItem[];
+    desc: string = 'DeleteCommandList'
+    /** 命令名称    */
+    readonly command: string = "DeleteCommandList"
     /** 命令item的父类   */
     parent: SGraphItem | null;
     constructor(scene: SGraphScene, itemList: SGraphItem[]) {

+ 0 - 1
src/components/urlMsg.js

@@ -11,7 +11,6 @@ if (!params) {
 params = decodeURIComponent(params);
 // params = "categoryId=NTXT&ProjectID=5&BuildingID=1&FloorID=1"; // mock 参数
 const paramsArr = params.split("&");
-console.log("paramsArr", paramsArr);
 const obj = {};
 paramsArr.map(item => {
     const arr = item.split("=");

+ 230 - 0
src/directives/dom.js

@@ -0,0 +1,230 @@
+/* istanbul ignore next */
+
+import Vue from 'vue'
+
+const isServer = Vue.prototype.$isServer
+const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g
+const MOZ_HACK_REGEXP = /^moz([A-Z])/
+const ieVersion = isServer ? 0 : Number(document.documentMode)
+
+/* istanbul ignore next */
+const trim = function(string) {
+    return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '')
+}
+/* istanbul ignore next */
+const camelCase = function(name) {
+    return name
+        .replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
+            return offset ? letter.toUpperCase() : letter
+        })
+        .replace(MOZ_HACK_REGEXP, 'Moz$1')
+}
+
+/* istanbul ignore next */
+export const on = (function() {
+    if (!isServer && document.addEventListener) {
+        return function(element, event, handler) {
+            if (element && event && handler) {
+                element.addEventListener(event, handler, false)
+            }
+        }
+    } else {
+        return function(element, event, handler) {
+            if (element && event && handler) {
+                element.attachEvent('on' + event, handler)
+            }
+        }
+    }
+})()
+
+/* istanbul ignore next */
+export const off = (function() {
+    if (!isServer && document.removeEventListener) {
+        return function(element, event, handler) {
+            if (element && event) {
+                element.removeEventListener(event, handler, false)
+            }
+        }
+    } else {
+        return function(element, event, handler) {
+            if (element && event) {
+                element.detachEvent('on' + event, handler)
+            }
+        }
+    }
+})()
+
+/* istanbul ignore next */
+export const once = function(el, event, fn) {
+    var listener = function() {
+        if (fn) {
+            fn.apply(this, arguments)
+        }
+        off(el, event, listener)
+    }
+    on(el, event, listener)
+}
+
+/* istanbul ignore next */
+export function hasClass(el, cls) {
+    if (!el || !cls) return false
+    if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.')
+    if (el.classList) {
+        return el.classList.contains(cls)
+    } else {
+        return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1
+    }
+}
+
+/* istanbul ignore next */
+export function addClass(el, cls) {
+    if (!el) return
+    var curClass = el.className
+    var classes = (cls || '').split(' ')
+
+    for (var i = 0, j = classes.length; i < j; i++) {
+        var clsName = classes[i]
+        if (!clsName) continue
+
+        if (el.classList) {
+            el.classList.add(clsName)
+        } else if (!hasClass(el, clsName)) {
+            curClass += ' ' + clsName
+        }
+    }
+    if (!el.classList) {
+        el.className = curClass
+    }
+}
+
+/* istanbul ignore next */
+export function removeClass(el, cls) {
+    if (!el || !cls) return
+    var classes = cls.split(' ')
+    var curClass = ' ' + el.className + ' '
+
+    for (var i = 0, j = classes.length; i < j; i++) {
+        var clsName = classes[i]
+        if (!clsName) continue
+
+        if (el.classList) {
+            el.classList.remove(clsName)
+        } else if (hasClass(el, clsName)) {
+            curClass = curClass.replace(' ' + clsName + ' ', ' ')
+        }
+    }
+    if (!el.classList) {
+        el.className = trim(curClass)
+    }
+}
+
+/* istanbul ignore next */
+export const getStyle =
+    ieVersion < 9
+        ? function(element, styleName) {
+              if (isServer) return
+              if (!element || !styleName) return null
+              styleName = camelCase(styleName)
+              if (styleName === 'float') {
+                  styleName = 'styleFloat'
+              }
+              try {
+                  switch (styleName) {
+                      case 'opacity':
+                          try {
+                              return element.filters.item('alpha').opacity / 100
+                          } catch (e) {
+                              return 1.0
+                          }
+                      default:
+                          return element.style[styleName] || element.currentStyle ? element.currentStyle[styleName] : null
+                  }
+              } catch (e) {
+                  return element.style[styleName]
+              }
+          }
+        : function(element, styleName) {
+              if (isServer) return
+              if (!element || !styleName) return null
+              styleName = camelCase(styleName)
+              if (styleName === 'float') {
+                  styleName = 'cssFloat'
+              }
+              try {
+                  var computed = document.defaultView.getComputedStyle(element, '')
+                  return element.style[styleName] || computed ? computed[styleName] : null
+              } catch (e) {
+                  return element.style[styleName]
+              }
+          }
+
+/* istanbul ignore next */
+export function setStyle(element, styleName, value) {
+    if (!element || !styleName) return
+
+    if (typeof styleName === 'object') {
+        for (var prop in styleName) {
+            if (styleName.hasOwnProperty(prop)) {
+                setStyle(element, prop, styleName[prop])
+            }
+        }
+    } else {
+        styleName = camelCase(styleName)
+        if (styleName === 'opacity' && ieVersion < 9) {
+            element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')'
+        } else {
+            element.style[styleName] = value
+        }
+    }
+}
+
+export const isScroll = (el, vertical) => {
+    if (isServer) return
+
+    const determinedDirection = vertical !== null || vertical !== undefined
+    const overflow = determinedDirection ? (vertical ? getStyle(el, 'overflow-y') : getStyle(el, 'overflow-x')) : getStyle(el, 'overflow')
+
+    return overflow.match(/(scroll|auto)/)
+}
+
+export const getScrollContainer = (el, vertical) => {
+    if (isServer) return
+
+    let parent = el
+    while (parent) {
+        if ([window, document, document.documentElement].includes(parent)) {
+            return window
+        }
+        if (isScroll(parent, vertical)) {
+            return parent
+        }
+        parent = parent.parentNode
+    }
+
+    return parent
+}
+
+export const isInContainer = (el, container) => {
+    if (isServer || !el || !container) return false
+
+    const elRect = el.getBoundingClientRect()
+    let containerRect
+
+    if ([window, document, document.documentElement, null, undefined].includes(container)) {
+        containerRect = {
+            top: 0,
+            right: window.innerWidth,
+            bottom: window.innerHeight,
+            left: 0,
+        }
+    } else {
+        containerRect = container.getBoundingClientRect()
+    }
+
+    return (
+        elRect.top < containerRect.bottom &&
+        elRect.bottom > containerRect.top &&
+        elRect.right > containerRect.left &&
+        elRect.left < containerRect.right
+    )
+}

+ 24 - 0
src/directives/repeat-click.js

@@ -0,0 +1,24 @@
+import { once, on } from './dom'
+
+export default {
+    bind(el, binding, vnode) {
+        let interval = null
+        let startTime
+        const handler = () => vnode.context[binding.expression].apply()
+        const clear = () => {
+            if (Date.now() - startTime < 100) {
+                handler()
+            }
+            clearInterval(interval)
+            interval = null
+        }
+
+        on(el, 'mousedown', (e) => {
+            if (e.button !== 0) return
+            startTime = Date.now()
+            once(document, 'mouseup', clear)
+            clearInterval(interval)
+            interval = setInterval(handler, 100)
+        })
+    },
+}

+ 2 - 1
src/lib/items/SCustomLegendItem.ts

@@ -211,7 +211,8 @@ export class SCustomLegendItem extends SPolygonItem {
     onMouseDown(event: SMouseEvent): boolean {
         if (event.buttons == 1)
         this.$emit("legendItemClick", event);
-        return super.onMouseDown(event);
+        super.onMouseDown(event)
+        return true;
     } // Function onMouseDown()
 
     toData(): any {

+ 2 - 1
src/lib/items/SFHFQZoneLegendItem.ts

@@ -210,7 +210,8 @@ export class SFHFQZoneLegendItem extends SPolygonItem {
     onMouseDown(event: SMouseEvent): boolean {
         if (event.buttons == 1)
         this.$emit("legendItemClick", event);
-        return super.onMouseDown(event);
+        super.onMouseDown(event);
+        return true
     } // Function onMouseDown()
 
     toData(): any {

+ 12 - 1
src/lib/items/SImageLegendItem.ts

@@ -136,9 +136,20 @@ export class SImageLegendItem extends SIconTextItem {
     onMouseDown(event: SMouseEvent): boolean {
         if (event.buttons == 1)
         this.$emit("legendItemClick", event);
-        return super.onMouseDown(event);
+        super.onMouseDown(event);
+        return true;
     } // Function onMouseDown()
 
+    /**
+     * 移动item后的处理,计算其他信息,将原点置为场景原点
+     *
+     * @param   x   x坐标
+     * @param   y   y坐标
+     * */
+    moveToOrigin(x: number, y: number): void {
+        // 不做处理
+    } // Function moveToOrigin()
+
     toData(): Legend {
         this.data.Pos = { X: this.x, Y: this.y };
         this.data.Size = { Width: this.width, Height: this.height };

+ 12 - 0
src/lib/items/SImageMarkerItem.ts

@@ -4,6 +4,7 @@ import { SPainter, SColor, SPoint } from "@saga-web/draw";
 import { Marker } from '../types/Marker';
 import { ItemOrder } from '@saga-web/big/lib';
 import { hexify, uuid } from "@/components/mapClass/until";
+import { SMouseEvent } from '@saga-web/base/lib';
 
 /**
  * 标识对象Item(图标类型)
@@ -60,6 +61,17 @@ export class SImageMarkerItem extends SImageItem {
         this.update();
     } // Function computeImgSize()
 
+    /**
+     * 鼠标按下事件
+     *
+     * @param   event   保存事件参数
+     * @return  boolean
+     */
+    onMouseDown(event: SMouseEvent): boolean {
+        super.onMouseDown(event)
+        return true;
+    } // Function onMouseDown()
+
     toData(): Marker {
         this.data.Pos = {X: this.x, Y: this.y};
         this.data.Size = {Width: this.width, Height: this.height};

+ 12 - 0
src/lib/items/SLineLegendItem.ts

@@ -4,6 +4,7 @@ import { SPoint } from "@saga-web/draw/lib";
 import { SPolylineItem } from '@saga-web/big/lib';
 import { Legend } from '../types/Legend';
 import { uuid } from '@/components/mapClass/until';
+import { SMouseEvent } from '@saga-web/base/lib';
 
 /**
  * 图例节点Item(线类型)
@@ -44,6 +45,17 @@ export class SLineLegendItem extends SPolylineItem {
         }
     }
 
+    /**
+     * 鼠标按下事件
+     *
+     * @param   event   保存事件参数
+     * @return  boolean
+     */
+    onMouseDown(event: SMouseEvent): boolean {
+        super.onMouseDown(event)
+        return true;
+    } // Function onMouseDown()
+    
     toData(): Legend {
         this.data.Pos = {X: this.x, Y: this.y};
         this.data.Properties.Line = this.pointList.map(pos => {

+ 16 - 2
src/lib/items/SLineMarkerItem.ts

@@ -4,6 +4,7 @@ import { SPoint, SPainter, SColor, SLineCapStyle } from "@saga-web/draw/lib";
 import { ItemOrder, SLineItem, SItemStatus } from '@saga-web/big/lib';
 import { Marker } from '../types/Marker';
 import { uuid } from '@/components/mapClass/until';
+import { SMouseEvent } from '@saga-web/base/lib';
 
 /**
  * 标识对象Item(线类型)
@@ -89,18 +90,31 @@ export class SLineMarkerItem extends SLineItem {
             // 判断删除equip后,不移动
             if (this.startItem.parent) {
                 let scenePoint: SPoint = this.startItem.boundingRect().center();
-                this.line[0] = this.startItem.mapToScene(scenePoint.x, scenePoint.y);
+                let p = this.startItem.mapToScene(scenePoint.x, scenePoint.y);
+                this.line[0] = new SPoint(p.x - this.x, p.y - this.y)
             }
         }
         if (this.endItem) {
             // 删除equip后
             if (this.endItem.parent) {
                 let scenePoint: SPoint = this.endItem.boundingRect().center();
-                this.line[1] = this.endItem.mapToScene(scenePoint.x, scenePoint.y);
+                let p = this.endItem.mapToScene(scenePoint.x, scenePoint.y);
+                this.line[1] = new SPoint(p.x - this.x, p.y - this.y)
             }
         }
     }
 
+    /**
+     * 鼠标按下事件
+     *
+     * @param   event   保存事件参数
+     * @return  boolean
+     */
+    onMouseDown(event: SMouseEvent): boolean {
+        super.onMouseDown(event)
+        return true;
+    } // Function onMouseDown()
+    
     toData(): Marker {
         this.data.Pos = { X: this.x, Y: this.y };
         this.data.Properties.Line = this.line.map(pos => {

+ 2 - 1
src/lib/items/SSCPZZoneLegendItem.ts

@@ -218,7 +218,8 @@ export class SSCPZZoneLegendItem extends SPolygonItem {
     onMouseDown(event: SMouseEvent): boolean {
         if (event.buttons == 1)
         this.$emit("legendItemClick", event);
-        return super.onMouseDown(event);
+        super.onMouseDown(event);
+        return true;
     } // Function onMouseDown()
 
     toData(): any {

+ 22 - 0
src/lib/items/STextMarkerItem.ts

@@ -3,6 +3,7 @@ import { SPainter, SColor,SFont, SPoint } from "@saga-web/draw";
 import { Marker } from '../types/Marker';
 import { ItemOrder } from '@saga-web/big/lib';
 import { uuid } from '@/components/mapClass/until';
+import { SMouseEvent } from '@saga-web/base/lib';
 
 /**
  * 标识对象Item(文本类型)
@@ -60,6 +61,27 @@ export class STextMarkerItem extends STextItem {
         this.origin = new SPoint(this.width / 2, this.height / 2);
     } // Function drawFormatText()
 
+    /**
+     * 移动item后的处理,计算其他信息,将原点置为场景原点
+     *
+     * @param   x   x坐标
+     * @param   y   y坐标
+     * */
+    moveToOrigin(x: number, y: number): void {
+        // 不做处理
+    } // Function moveToOrigin()
+
+    /**
+     * 鼠标按下事件
+     *
+     * @param   event   保存事件参数
+     * @return  boolean
+     */
+    onMouseDown(event: SMouseEvent): boolean {
+        super.onMouseDown(event)
+        return true;
+    } // Function onMouseDown()
+    
     toData(): Marker {
         this.data.Pos = {X: this.x, Y: this.y};
         this.data.Size = {Width: this.width, Height: this.height};

+ 2 - 1
src/lib/items/SZoneLegendItem.ts

@@ -211,7 +211,8 @@ export class SZoneLegendItem extends SPolygonItem {
     onMouseDown(event: SMouseEvent): boolean {
         if (event.buttons == 1)
         this.$emit("legendItemClick", event);
-        return super.onMouseDown(event);
+        super.onMouseDown(event);
+        return true;
     } // Function onMouseDown()
 
     toData(): any {

+ 6 - 3
src/lib/items/TipelineItem.ts

@@ -92,15 +92,17 @@ export class TipelineItem extends SPolylineItem {
     if (this.startAnchor) {
       // 判断删除equip后,不移动
       if (this.startAnchor.parent && this.startAnchor.parent.parent) {
-        this.pointList[0] = this.startAnchor.mapToScene(0, 0);
+        let p = this.startAnchor.mapToScene(0, 0);
+        this.pointList[0] = new SPoint(p.x - this.x, p.y - this.y)
       }
     }
     if (this.endAnchor) {
       // 删除equip后
       if (this.endAnchor.parent && this.endAnchor.parent.parent) {
+        let p = this.endAnchor.mapToScene(0, 0);
         this.pointList[
           this.pointList.length - 1
-        ] = this.endAnchor.mapToScene(0, 0);
+        ] = new SPoint(p.x - this.x, p.y - this.y)
       }
     }
   }
@@ -155,7 +157,8 @@ export class TipelineItem extends SPolylineItem {
     onMouseDown(event: SMouseEvent): boolean {
       if (event.buttons == 1)
       this.$emit("legendItemClick", event);
-      return super.onMouseDown(event);
+      super.onMouseDown(event);
+      return true;
   } // Function onMouseDown()
 
   /** 获取data数据  */

+ 16 - 1
src/store/index.ts

@@ -9,7 +9,10 @@ export default new Vuex.Store({
     GraphCategoryIds: ['NTXT'], //系统类型
     TypeIdToGraphElement: {}, //typeid到图例元素的映射
     token: null,
-    GraphElement:[]
+    GraphElement:[],
+    isRemember: false,
+    rememberBtn: "bind",
+    isCopy:'' //是否为复制状态
   },
   mutations: {
     TypeIdToGraphElement(state, data) {
@@ -32,6 +35,16 @@ export default new Vuex.Store({
     SETSSOTOKEN(state, data) {
       state.token = data
     },
+    setIsRemember(state, data) {
+      state.isRemember = data
+    },
+    setRememberBtn(state, data) {
+      state.rememberBtn = data
+    },
+    SETISCOPY(state, data) {
+      state.isCopy = data;
+      console.log('SETISCOPY',data)
+    },
   },
   actions: {
     getElementType({ commit }, params) {
@@ -47,6 +60,8 @@ export default new Vuex.Store({
   },
   getters: {
     token: (state) => state.token,
+    isRemember: (state) => state.isRemember,
+    rememberBtn: (state) => state.rememberBtn,
   },
   modules: {
   }

+ 28 - 5
src/views/drafts.vue

@@ -104,7 +104,8 @@ import {
   queryStatistic,
   deleteGraph,
   publishGraph,
-  deleteByCategory
+  deleteByCategory,
+  graphQuery
 } from "@/api/editer.js";
 import { STopologyParser } from "./../lib/parsers/STopologyParser";
 import { uuid } from "@/components/mapClass/until";
@@ -350,10 +351,12 @@ export default {
       this.legendData = [];
       this.systemName = "";
       this.floorName = "";
+      this.seq =''
       this.systemName = items.Gcode;
       this.floorName = id.Code;
       this.floorId = id.Gname;
       this.categoryId = items.Id;
+      this.seq = id.Seq;
       // this.getLegend();
       this.checkFloor(id.Gname);
       console.log(items);
@@ -374,6 +377,7 @@ export default {
             this.systemName = "";
             this.floorName = "";
             this.floorId = "";
+            this.seq = "";
             this.categoryId = "";
             if (data.length) {
               (function recursion(newObj) {
@@ -412,6 +416,7 @@ export default {
                 this.floorName = this.treeData[0].children[0].children[0].Code;
                 this.floorId = this.treeData[0].children[0].children[0].Gname;
                 this.categoryId = this.treeData[0].children[0].Id;
+                this.seq =  this.treeData[0].children[0].Seq;
                 // this.getLegend();
                 this.checkFloor(this.treeData[0].children[0].children[0].Gname);
               } else {
@@ -421,6 +426,7 @@ export default {
                 this.floorName = this.treeData[0].children[0].Code;
                 this.floorId = this.treeData[0].children[0].Gname;
                 this.categoryId = this.treeData[0].Id;
+                this.seq =  this.treeData[0].children[0].Seq;
                 // this.getLegend();
                 this.checkFloor(this.treeData[0].children[0].Gname);
               }
@@ -435,6 +441,7 @@ export default {
           if (this.treeData.length == 0) {
             this.checkFloor("");
           }
+          console.log(' this.treeData', this.treeData)
         })
         .catch(() => {
           loadings.close();
@@ -450,7 +457,6 @@ export default {
         graphId: this.graphId,
         categoryId: this.categoryId
       }).then(res => {
-        console.log(res);
         this.legendLoading = false;
         if (res.data.Result == "success") {
           const data = res.data.Data;
@@ -491,7 +497,7 @@ export default {
         spinner: "el-icon-loading",
         background: "rgba(0, 0, 0, 0.7)"
       });
-      let params = {
+      const params = {
         "BuildingID": this.BuildingID,
         "CategoryID": this.categoryId,
         "FloorID": this.floorId,
@@ -563,6 +569,13 @@ export default {
         }
       });
     },
+    // 获取图最大最小值
+    getGraphDetail(){
+      const data = {
+        Filters:`categoryId='${this.categoryId}';projectId='${this.projectId}';BuildingID='${this.BuildingID}';FloorID='${this.floorId}'`
+      };
+      return graphQuery(data);
+    },
     // 读取数据
     readGroup(floorid) {
       const data = {
@@ -587,13 +600,14 @@ export default {
           "/wandaEditer/editer?" +
           encodeURIComponent(data);
         window.open(url, true); */
-         
+
         // 发布成功跳转草稿箱
         const token = this.$store.getters["token"];
         this.$router.push({
           path: "editer",
           query: {
             categoryId: this.categoryId,
+            seq:this.seq,
             projectId: this.projectId,
             BuildingID: 1,
             FloorName: this.floorName,
@@ -622,7 +636,16 @@ export default {
       }
       setTimeout(() => {
         this.view.scene = this.scene;
-        this.parserData(floorid);
+        this.getGraphDetail().then(res => {
+          if (res.Content.length == 1) {
+            const data = res.Content[0];
+            if (data.MaxY && data.MinX) {
+              fengmap.maxY = data.MaxY;
+              fengmap.minX = data.MinX;
+            }
+          }
+          this.parserData(floorid);
+        });
         this.readGroup(floorid).then(data => {
           if (data.Result == "success") {
             this.graphId = data.Data[0].ID;

+ 43 - 2
src/views/editer.vue

@@ -2,7 +2,7 @@
   <div class="wandaEditer">
     <!-- 顶部工具栏 -->
     <div class="top_toolbar">
-      <topToolbar></topToolbar>
+      <topToolbar ref="topToolbar" @openConfirmDialog="dialogVisible = true"></topToolbar>
     </div>
     <div class="content">
       <!-- 左侧工具栏 -->
@@ -25,6 +25,18 @@
         <rightToolbar :focusItemList="focusItemList"></rightToolbar>
       </div>
     </div>
+    <el-dialog
+      title="操作提示"
+      :visible.sync="dialogVisible"
+      width="600px">
+      <div style="margin-bottom: 15px;">您打开的是已发布的平面图,您可以进行如下操作:</div>
+      <p>1、直接选择平面图中的元素进行复制,然后贴到其他平面图;</p>
+      <p>2、点击“启动编辑”对当前平面图进行编辑;</p>
+      <span slot="footer" class="dialog-footer">
+        <el-button size="small" @click="dialogVisible = false">取 消</el-button>
+        <el-button size="small" type="primary" @click="handleOpenUrl">打 开</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
 
@@ -34,12 +46,14 @@ import leftToolbar from "@/components/edit/left_toolbar.vue";
 import topToolbar from "@/components/edit/top_toolbar.vue";
 import rightToolbar from "@/components/edit/right_toolbar.vue";
 import bus from "@/bus";
+import {mapMutations} from 'vuex'
 export default {
   name: "wandaEditer",
   data() {
     return {
       cmdType: "choice",
-      focusItemList: null
+      focusItemList: null,
+      dialogVisible: false
     };
   },
   components: {
@@ -49,6 +63,7 @@ export default {
     rightToolbar
   },
   methods: {
+    ...mapMutations(['SETISCOPY']),
     // 左侧工具栏 点击事件
     toolActionClick(item) {
       this.cmdType = item.Type;
@@ -59,7 +74,30 @@ export default {
     },
     changeFocusItem(item) {
       this.focusItemList = item;
+    },
+    handleOpenUrl() {
+      this.$refs.topToolbar.handleOpenUrl();
+      this.dialogVisible = false;
+    }
+  },
+   created() {
+    const href = window.location.href;
+    // 参数处理
+    let params = href.split("?")[1];
+    if (!params) {
+      // 参数有问题
+      return false;
     }
+    params = decodeURIComponent(params);
+    const paramsArr = params.split("&");
+    const obj = {};
+    paramsArr.map(item => {
+      const arr = item.split("=");
+      obj[arr[0]] = arr[1];
+    });
+    this.urlMsg = obj;
+    const isCopy = obj.isCopy ? obj.isCopy :'false';
+    this.SETISCOPY(isCopy)
   }
 };
 </script>
@@ -96,4 +134,7 @@ export default {
     }
   }
 }
+/deep/ .el-dialog__body {
+  padding: 10px 20px;
+}
 </style>

+ 2 - 2
vue.config.js

@@ -17,7 +17,7 @@ module.exports = {
             },
             '/serve': {
                 // target: 'http://192.168.200.87:8088/',
-                // target: 'http://192.168.200.83:8085/',
+                // target: 'http://10.199.143.129:8080',
                 target: 'http://60.205.177.43:8080', //阿里云
                 changeOrigin: true,
                 secure: false,
@@ -26,7 +26,7 @@ module.exports = {
                 },
             },
             '/data': {
-                // target: 'http://192.168.200.87:9003',
+                // target: "http://10.199.143.126",
                 target: 'http://60.205.177.43', //阿里云
                 changeOrigin: true,
                 secure: false,