huangmp 4 jaren geleden
bovenliggende
commit
9d397e7aaf

BIN
public/img/icon/add_location.png


BIN
public/img/icon/location.png


BIN
public/img/icon/location1.png


BIN
public/img/icon/location2.png


BIN
public/img/icon/menjin.png


+ 18 - 0
src/api/device/doordevice.js

@@ -48,6 +48,24 @@ export const update = (row) => {
   })
 }
 
+export const updateBatch = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/doordevice/updateBatch',
+    method: 'post',
+    data: row
+  })
+}
+
+export const edit = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/doordevice/update',
+    method: 'post',
+    data: row
+  })
+}
+
+
+
 export const remoteOpenDoor = (id, isOpen) => {
   return request({
     url: '/api/cyzh-smart-device/doordevice/remoteOpenDoor',

+ 78 - 17
src/components/map/comps/device-list.vue

@@ -7,37 +7,53 @@
       <tab :list="tabList" width="4.4rem"></tab>
     </div>
 
-    <div class="device" v-for="(item,index) in list" :key="index">
-      <div class="card" style="padding:13px 20px;" @click="clickDevice(item)">
+    <div class="device" v-loading="loading" style="height:100%">
+      <div class="card" style="padding:13px 20px;" @click.stop="clickDevice(item)" v-for="(item,index) in list"
+        :key="index">
         <div class="left">
           <div class="name text-cut">
             {{item.name}}
           </div>
+
           <div class="address text-cut" style="display:flex">
             <span v-if="$isEmpty(item.latitude)||$isEmpty(item.longitude)" style="color:#fa3534;margin-right:4px">
               [未设置坐标]</span>
-            <img v-else src="/img/icon/location.png"
+            <img v-else src="../../../../public/img/icon/location2.png"
               style="width:16px;height:16px;margin-right:2px;margin-top:2px"></img>
             {{item.address}}
           </div>
         </div>
+        <!-- 中间菜单 -->
         <div class="right">
           <div class="status">
             <span style="color:#fa3534" v-if="item.deviceStatus==0">离线</span>
             <span style="color:#19be6b" v-else-if="item.deviceStatus==1">在线</span>
             <span style="color:#82848a" v-else>未知</span>
+
+
+            <el-dropdown>
+              <i class="el-icon-s-operation" style="color:#3b8ff4;margin-left:10px"></i>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item @click.native="dropdownClick(item)"
+                  v-for="(item1,index1) in operationList" :key="index1" :icon="item1.icon">
+                  {{item1.name}}
+                </el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+
           </div>
           <div class="time">
             {{item.createTime | formatDate}}
           </div>
         </div>
       </div>
+      <div class="pagination" style="display:flex;justify-content: flex-end">
+        <el-pagination @current-change="currentChange" small background :page-count="page.pages"
+          layout="prev, pager, next">
+        </el-pagination>
+      </div>
     </div>
-    <div class="pagination" style="display:flex;justify-content: flex-end">
-      <el-pagination @current-change="currentChange" small background :page-count="page.pages"
-        layout="prev, pager, next">
-      </el-pagination>
-    </div>
+
 
   </div>
 </template>
@@ -56,6 +72,7 @@
     },
     data() {
       return {
+        loading: false,
         page: {
           current: 1,
           size: 10,
@@ -71,6 +88,22 @@
             label: "监控设备",
             value: 1
           }
+        ],
+        operationList: [{
+          index:0,
+            icon: 'el-icon-view',
+            name: '详情',
+          },
+          {
+            index:1,
+            icon: 'el-icon-edit',
+            name: '编辑'
+          },
+          {
+            index:2,
+            icon: 'el-icon-delete',
+            name: '删除'
+          }
         ]
       }
     },
@@ -79,19 +112,42 @@
     },
     filters: {
       formatDate(date) {
+        if (!date) {
+          return "未知"
+        }
         return dateTime.format(new Date(date), 'mm-dd HH:MM:SS')
       }
     },
     methods: {
-      clickDevice(item) {
-        this.$emit('click', item)
+      dropdownClick(item){
+        let index=item.index
+        switch (index){
+          case 0:
+            break;
+          default:
+            break;
+        }
+      },
+      clickDevice(data) {
+        this.list.forEach(item => {
+          item.id == data.id ? item.show = true : item.show = false
+        })
+        this.$emit('click', data)
+      },
+      async fetchDeviceList() {
+        this.loading = true
+        let res = await getList(this.page.current, this.page.size)
+        let data = res.data.data
+        this.initData(data)
+        this.loading = false
       },
-      fetchDeviceList() {
-        getList(this.page.current, this.page.size).then(res => {
-          let data = res.data.data
-          this.list = data.records
-          this.page.pages = data.pages
+      initData(data) {
+        let list = data.records
+        list.forEach(item => {
+          item.show = false
         })
+        this.list = list
+        this.page.pages = data.pages
       },
       currentChange(current) {
         this.page.current = current
@@ -105,7 +161,6 @@
   * {
     box-sizing: border-box;
   }
-
   /* 设备列表 */
   .container {
     border-top: 1px solid #f2f1ed;
@@ -130,8 +185,13 @@
       width: 65%
     }
 
+    .center-menu {
+      width: 100%;
+      height: 100%
+    }
+
     .right {
-      width: 35%;
+      width: 28%;
       text-align: right
     }
   }
@@ -145,6 +205,7 @@
   }
 
   .name {
+    width: 100%;
     color: #272727;
     font-size: 15px;
     font-weight: 500

+ 303 - 0
src/components/map/comps/door-device-form.vue

@@ -0,0 +1,303 @@
+<template>
+  <div>
+    <el-dialog :modal-append-to-body="true" :append-to-body="true" :title="title" :before-close="beforeClose"  :center="true"
+      :visible.sync="dialogShow" width="45%" :close-on-click-modal="false" top="4%">
+      <avue-form ref="avueForm" :option="option" v-model="model" @submit="submit"></avue-form>
+    </el-dialog>
+  </div>
+</template>
+<script>
+  import {update} from "@/api/device/doordevice.js"
+  import {
+    deepClone
+  } from '@/util/util.js'
+  export default {
+    data() {
+      return {
+        isAdd: false,
+
+        dialogShow: false,
+        model: {},
+        option: {
+          detail: true,
+          labelWidth: 110,
+          group: [{
+            label: '基本信息',
+            prop: 'group1',
+            column: [{
+              label: "设备名称",
+              prop: "name",
+              overHidden: true,
+              rules: [{
+                required: true,
+                message: "请输入名称",
+                trigger: "blur"
+              }]
+            }, {
+              label: "设备序列号",
+              prop: "serialNum",
+              labelWidth: 100,
+              width: 150,
+              rules: [{
+                required: true,
+                message: "请输入Mac编码",
+                trigger: "blur"
+              }],
+            }, {
+              label: "进出方向",
+              prop: "isOut",
+              type: "select",
+              width: 80,
+              hide: true,
+              align: "center",
+              dicData: [{
+                  label: "进",
+                  value: 1,
+                },
+                {
+                  label: "出",
+                  value: 2
+                }
+              ],
+              rules: [{
+                required: true,
+                message: "请输入进出方向",
+                trigger: "blur"
+              }]
+            }, ]
+          }, {
+            label: '所属信息',
+            prop: 'group2',
+            column: [{
+                label: "所属园区",
+                prop: "agencyId",
+                type: "select",
+                search: true,
+                remote: true,
+                searchSpan: 4,
+                searchFilterable: true,
+                hide: true,
+                dataType: "string",
+                cascaderItem: ['residentialId'],
+                dicUrl: "/api/cyzh-community/agency/list?size=500&id={{key}}",
+                dicFormatter: (res) => {
+                  return res.data.records; //返回字典的层级结构
+                },
+                props: {
+                  label: "name",
+                  value: "id"
+                },
+                rules: [{
+                  required: true,
+                  message: "请选择所属区域",
+                  trigger: "change"
+                }],
+              },
+              {
+                label: "所属区域",
+                prop: "residentialId",
+                type: "select",
+                search: true,
+                searchSpan: 4,
+                searchFilterable: true,
+                hide: true,
+                cascaderItem: ['buildingId'],
+                dicUrl: "/api/cyzh-community/residential/list?size=500&agencyId={{key}}",
+                dicFormatter: (res) => {
+                  return res.data.records; //返回字典的层级结构
+                },
+                dateType: "string",
+                props: {
+                  label: "name",
+                  value: "id"
+                },
+                rules: [{
+                  required: true,
+                  message: "请选择所属区域",
+                  trigger: "change"
+                }],
+              },
+              {
+                label: "所属楼栋",
+                prop: "buildingId",
+                type: "select",
+                search: true,
+                searchSpan: 4,
+                searchFilterable: true,
+                hide: true,
+                cascaderItem: ['unitId'],
+                dicUrl: "/api/cyzh-community/building/list?size=500&residentialId={{key}}",
+                dicFormatter: (res) => {
+                  return res.data.records; //返回字典的层级结构
+                },
+                props: {
+                  label: "name",
+                  value: "id"
+                },
+                rules: [{
+                  required: false,
+                  message: "请选择所属楼栋",
+                  trigger: "change"
+                }],
+              },
+              {
+                label: "所属单元",
+                prop: "unitId",
+                type: "select",
+                search: true,
+                searchSpan: 4,
+                searchFilterable: true,
+                hide: true,
+                cascaderItem: ['floorId'],
+                dicUrl: "/api/cyzh-community/unit/list?size=500&buildingId={{key}}",
+                dicFormatter: (res) => {
+                  return res.data.records; //返回字典的层级结构
+                },
+                props: {
+                  label: "name",
+                  value: "id"
+                },
+                rules: [{
+                  required: false,
+                  message: "请选择所属单元",
+                  trigger: "change"
+                }],
+              },
+              {
+                label: "所属楼层",
+                prop: "floorId",
+                type: "select",
+                search: true,
+                searchFilterable: true,
+                hide: true,
+                searchSpan: 4,
+                dateType: "string",
+                cascaderItem: ['roomId'],
+                dicUrl: "/api/cyzh-community/floor/list?size=500&unitId={{key}}",
+                dicFormatter: (res) => {
+                  return res.data.records; //返回字典的层级结构
+                },
+                props: {
+                  label: "name",
+                  value: "id"
+                },
+                rules: [{
+                  required: false,
+                  message: "请选择所属楼层",
+                  trigger: "change"
+                }],
+              },
+              {
+                label: "所属房间",
+                prop: "roomId",
+                type: "select",
+                hide: true,
+                dicUrl: "/api/cyzh-community/room/list?size=500&floorId={{key}}",
+                dicFormatter: (res) => {
+                  return res.data.records; //返回字典的层级结构
+                },
+                dateType: "number",
+                props: {
+                  label: "name",
+                  value: "id"
+                },
+                rules: [{
+                  required: false,
+                  message: "请选择所属房间",
+                  trigger: "change"
+                }],
+              },
+            ]
+          }, {
+            label: '位置信息',
+            prop: 'group3',
+            column: [{
+                label: "经度",
+                prop: "longitude",
+                width: 100,
+                overHidden: true,
+                hide: true,
+                rules: [{
+                  required: false,
+                  message: "请输入经度",
+                  trigger: "blur"
+                }]
+              },
+              {
+                label: "纬度",
+                prop: "latitude",
+                width: 100,
+                overHidden: true,
+                hide: true,
+                rules: [{
+                  required: false,
+                  message: "请输入纬度",
+                  trigger: "blur"
+                }]
+              },
+              {
+                label: "安装地址",
+                prop: "address",
+                hide: true,
+                overHidden: true,
+                rules: [{
+                  required: false,
+                  message: "请输入具体地址",
+                  trigger: "blur"
+                }]
+              },
+            ]
+          }],
+
+        }
+      }
+    },
+    computed: {
+      title() {
+        if (this.isAdd) {
+          return '添加设备'
+        }
+        if (this.option.detail) {
+          return '设备详情'
+        } else {
+          return '编辑设备'
+        }
+      }
+    },
+    methods: {
+      showDialog(model, detail = true) {
+        this.isAdd = false
+        this.model = model
+        this.option.detail = detail
+        this.dialogShow = true
+      },
+      showAddForm(model) {
+        this.isAdd = true
+        this.dialogShow = true
+        this.option.detail = false
+        this.model = model
+      },
+      beforeClose(done){
+        console.log("close");
+        this.$refs.avueForm.resetForm()
+        done()
+        this.$emit('closed')
+      },
+      async submit(form, done) {
+        let data = deepClone(form)
+        let res = await update(data)
+        done()
+        if (res.data.success) {
+          this.dialogShow = false;
+          this.$refs.avueForm.resetForm()
+          this.$message.success('操作成功')
+          this.$emit('reloadData',res.data.data)
+        } else {
+          this.$message.success('操作失败')
+        }
+
+      },
+    }
+  }
+</script>
+x

+ 7 - 87
src/components/map/demo.html

@@ -1,89 +1,9 @@
 <!DOCTYPE html>
-<html lang="en">
-
-  <head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <meta http-equiv="X-UA-Compatible" content="ie=edge">
-    <title>点击标记弹出信息窗口</title>
-  </head>
-  <script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77"></script>
-  <style type="text/css">
-    html,
-    body {
-      height: 100%;
-      margin: 0px;
-      padding: 0px;
-    }
-
-    #container {
-      width: 100%;
-      height: 100%;
-    }
-  </style>
-
-  <body onload="initMap()">
-    <div id="container"></div>
-    <script>
-      function initMap() {
-        var center = new TMap.LatLng(39.984104, 116.307503); //设置中心点坐标
-        //初始化地图
-        var map = new TMap.Map("container", {
-          center: center
-        });
-
-        //初始marker
-        var marker = new TMap.MultiMarker({
-          id: 'marker-layer',
-          map: map,
-          styles: {
-            "marker": new TMap.MarkerStyle({
-              "width": 24,
-              "height": 35,
-              "anchor": {
-                x: 12,
-                y: 35
-              },
-              "src": 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/markerDefault.png'
-            })
-          },
-          geometries: [{
-            "id": 'demo1',
-            "styleId": 'marker',
-            "position": new TMap.LatLng(39.984104, 116.307503),
-            "properties": {
-              "title": "marker"
-            }
-          }, {
-            "id": 'demo2',
-            "styleId": 'marker',
-            "position": new TMap.LatLng(39.974104, 116.347503),
-            "properties": {
-              "title": "marker"
-            },
-
-          }]
-        });
-        //初始化infoWindow
-        var infoWindow = new TMap.InfoWindow({
-          map: map,
-          position: new TMap.LatLng(39.984104, 116.307503),
-          offset: {
-            x: 0,
-            y: -32
-          } //设置信息窗相对position偏移像素
-        });
-        infoWindow.close(); //初始关闭信息窗关闭
-        //监听标注点击事件
-        marker.on("click", function(evt) {
-          //设置infoWindow
-          infoWindow.open(); //打开信息窗
-          infoWindow.setPosition(evt.geometry.position); //设置信息窗位置
-          var content=`<span>名称:${item.name}</span><br/><span>地址:${item.address}</span>`
-          infoWindow.setContent(evt.geometry.position.toString()); //设置信息窗内容
-        })
-      }
-    </script>
-  </body>
-
+<html>
+	<head>
+		<meta charset="utf-8">
+		<title></title>
+	</head>
+	<body>
+	</body>
 </html>

+ 572 - 0
src/components/map/divide - 副本.vue

@@ -0,0 +1,572 @@
+<template>
+  <div class="device-body" style="height:100%;">
+    <!-- 地图 -->
+    <div id="container" style="height:100%"></div>
+    <!-- 搜索框 -->
+    <div id="panel" style="display:flex;justify-content: center;align-items: center">
+      <div class="search">
+        <el-select @change="setSuggestion" :clearable="true" @clear="clear" v-model="value" style="width:100%"
+          filterable remote reserve-keyword placeholder="请输入地址关键词" :remote-method="getSuggestions" :loading="loading">
+          <el-option v-for="(item,index) in suggestionList" :key="index" :label="item.name" :value="item">
+            <span style="float: left">{{ item.name }}</span>
+            <el-tooltip class="item" effect="dark" :content="item.address" placement="top-start">
+              <span style="float: right; color: #8492a6; font-size: 13px;">{{textCut(item.address)}}</span>
+            </el-tooltip>
+          </el-option>
+        </el-select>
+      </div>
+
+      <div style="margin-left: 10px" v-if="!ismove">
+        <el-button @click="addDevice" icon="el-icon-plus" :type="isAdd?'primary':''" circle></el-button>
+      </div>
+
+
+      <div style="margin-left: 10px">
+        <el-button @click="operaMarkers" size="small" v-text="ismove?'保存':'移动设备位置'" :type="ismove?'primary':''"
+          :style="ismove?'border-radius:4px 0 0 4px':''"></el-button>
+        <el-button @click="cancelMove" size="small" v-if="ismove"
+          style="margin:0;border-radius:0 4px 4px 0;border:1px solid #62a5f6">取消</el-button>
+      </div>
+    </div>
+    <!-- 设备列表 -->
+    <device-list @click="clickDevice" ref="deviceList"></device-list>
+
+    <door-device-form ref="doorDeviceForm" @reloadData="reloadData"></door-device-form>
+  </div>
+</template>
+
+<script>
+
+</script>
+
+<script>
+  import {
+    deepClone
+  } from '@/util/util.js'
+  import doorDeviceForm from "./comps/door-device-form.vue"
+  import {
+    getDoorDeviceCoordinates
+  } from "@/api/device/doordevice.js"
+  import * as mapUtil from "./js/mapUtil.js"
+  import deviceList from "./comps/device-list.vue"
+  import {
+    updateBatch,
+    getList,
+    remove
+  } from "@/api/device/doordevice.js"
+  let _this = this
+  let TMap, map, markers, editor, geocoder;
+  let infoWindow; //窗口
+  export default {
+    components: {
+      deviceList,
+      doorDeviceForm
+    },
+    data() {
+      return {
+        markerGeometries: [],
+
+        ismove: false,
+        isAdd: false,
+        isEdit:false,
+
+
+        dialogVisible: false,
+        //标记坐标集合
+        coordinates: [],
+
+        //搜索
+        value: '',
+        suggestionList: [],
+        loading: false,
+      };
+    },
+    computed: {
+      textCut() {
+        return data => {
+          let len = 7
+          if (data.length >= len) {
+            data = data.substring(0, len) + "..."
+          }
+          return data
+        }
+      }
+    },
+    created() {
+      this.init()
+    },
+    methods: {
+      reloadData(data) {
+        //关闭添加
+        this.isAdd = false
+        //更新设备列表
+        this.$refs.deviceList.fetchDeviceList()
+        let position = markers.getGeometryById("add").position
+        //删除添加标记
+        markers.remove(["add"])
+        //添加新的标记
+        markers.add([{
+          id: data.id,
+          styleId: 'marker',
+          position,
+          content: data.name
+        }])
+      },
+      async init() {
+        _this = this
+        await this.getDoorDeviceCoordinates()
+        this.initMap()
+      },
+      addDevice() {
+        infoWindow.close();
+        this.ismove = false
+        this.isAdd = !this.isAdd
+        if (this.isAdd) {
+          let center = map.getCenter()
+          this.addMarkers('add', center)
+
+          this.$notify({
+            title: '提示',
+            type: 'success',
+            message: '已激活添加设备操作,请点击地图选点再添加设备',
+            duration: 6000
+          });
+
+        } else {
+          markers.remove(["add"])
+        }
+      },
+      async getSuggestions(name) {
+        let params = {
+          name
+        }
+        let res = await getList(1, 10, params)
+        let data = res.data.data
+        this.suggestionList = data.records
+        this.$refs.deviceList.initData(data)
+      },
+      clear() {
+        this.getSuggestions()
+      },
+      setSuggestion(item) {
+        //先关闭窗口
+        infoWindow.close();
+        //再打开窗口
+        this.openInfoWindow(item)
+      },
+      // animation:qq.maps.MarkerAnimation.DROP,
+      clickDevice(item) {
+        let flag = this.coordinates.some(line => line.id == item.id)
+        if (flag) {
+          map.setCenter(new TMap.LatLng(item.latitude, item.longitude))
+          //先关闭窗口
+          infoWindow.close();
+          //再打开窗口
+          this.openInfoWindow(item)
+          return
+        } else {
+          this.isEdit=true
+          //选取设备坐标
+          let id = item.id + 'add'
+          let position = map.getCenter()
+          let content = '选取设备坐标'
+          this.addMarkers(id, position, content)
+
+          this.$notify({
+            title: '提示',
+            type: 'success',
+            message: '请点击地图选取设备坐标',
+            duration: 6000
+          });
+        }
+      },
+      //获取设备坐标集合
+      async getDoorDeviceCoordinates() {
+        let res = await getDoorDeviceCoordinates()
+        this.coordinates = res.data.data
+      },
+      async initMap() {
+        let scripts = ['https://map.qq.com/api/gljs?libraries=service&v=1.exp',
+          'https://map.qq.com/api/js?v=2.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77',
+          'https://map.qq.com/api/gljs?libraries=tools&v=1.exp'
+        ]
+        TMap = await mapUtil.loadMap(scripts)
+        //创建地图
+        this.createMap()
+        //新建逆地址服务类
+        geocoder = new TMap.service.Geocoder();
+
+        //创建标点集合类
+        this.createMarkers()
+        //创建标点拖动类
+        this.markersDrag()
+        //设置中心位置
+        this.setCenter()
+
+
+      },
+      //逆地址
+      async getAddress(location) {
+        let address = (await geocoder.getAddress({
+          location
+        })).result.address
+        return address
+      },
+
+      /**
+       * 创建地图
+       */
+      createMap() {
+        let _this = this
+        //获取中心点
+        map = new TMap.Map('container', {
+          zoom: 19,
+          baseMap: {
+            type: 'vector',
+            features: ['base', 'building3d'], // 隐藏矢量文字
+          },
+        });
+        map.on("click", async (evt) => {
+          let lat = evt.latLng.getLat().toFixed(6);
+          let lng = evt.latLng.getLng().toFixed(6);
+          let model = {
+            latitude: lat,
+            longitude: lng,
+            address: ''
+          }
+          let position = new TMap.LatLng(lat, lng)
+
+          if (!this.isAdd && !this.isEdit) {
+            return
+          }
+          //逆地址解释
+          model.address = await this.getAddress(position)
+          if (_this.isAdd) {
+            this.showAddForm(model,position)
+            return
+          }
+          if (_this.isEdit) {
+            console.log("修改");
+          }
+
+        })
+      },
+      async showAddForm(model,position){
+        let id = 'add'
+        let geometries = deepClone(markers.geometries) || null
+        if (!geometries) {
+          _this.addMarkers(id, position)
+          _this.$refs.doorDeviceForm.showAddForm(model)
+          return
+        }
+        let flag = geometries.find(item => item.id == "add")
+        if (!flag) {
+          _this.addMarkers(id, position)
+          _this.$refs.doorDeviceForm.showAddForm(model)
+          return
+        }
+        markers.updateGeometries([{
+          id,
+          position,
+          styleId: 'addStyle',
+          content: '点击地图选点',
+        }])
+        _this.$refs.doorDeviceForm.showAddForm(model)
+      },
+      addMarkers(id, position, content = '点击地图选点') {
+        markers.add([{
+          id,
+          styleId: 'addStyle',
+          position,
+          content,
+        }])
+      },
+      //设置中心位置
+      setCenter() {
+        let arr = mapUtil.getPointsCenter(this.coordinates, "latitude", "longitude")
+        if (this.$isNotEmpty(arr) && this.$isNotEmpty(arr[0]) && this.$isNotEmpty(arr[1])) {
+          map.setCenter(new TMap.LatLng(arr[0], arr[1]));
+        } else {
+          //ip定位获取中心点
+          mapUtil.ipLocate(TMap, markers, map)
+        }
+      },
+      /**
+       * 创建区域
+       */
+      crearePolygon() {
+        let polygon = new TMap.MultiPolygon({
+          map,
+          geometries: [{
+            paths,
+          }]
+        });
+      },
+      /**
+       * 新建一个标点集合
+       */
+      createMarkers() {
+        //创建标点集合对象
+        markers = new TMap.MultiMarker({
+          id: 'marker-layer',
+          enableCollision: false,
+          map,
+          styles: {
+            'label': new TMap.LabelStyle({
+              'color': '#3777FF', //颜色属性
+              'size': 20, //文字大小属性
+              'offset': {
+                x: 0,
+                y: 0
+              }, //文字偏移属性单位为像素
+              'angle': 90, //文字旋转属性
+              'alignment': 'center', //文字水平对齐属性
+              'verticalAlignment': 'middle' //文字垂直对齐属性
+            })
+          },
+          styles: {
+            "marker": new TMap.MarkerStyle({
+              "width": 30,
+              "height": 30,
+              "anchor": {
+                x: 16,
+                y: 32
+              },
+              "src": '/img/device/door-device.png',
+              "color": '#333', // 标注点文本颜色
+              "size": 14, // 标注点文本文字大小
+              "direction": 'bottom', // 标注点文本文字相对于标注点图片的方位
+              "offset": {
+                x: 0,
+                y: 8
+              }, // 标注点文本文字基于direction方位的偏移属性
+              "strokeColor": '#fff', // 标注点文本描边颜色
+              "strokeWidth": 2, // 标注点文本描边宽度
+            }),
+            "addStyle": new TMap.MarkerStyle({
+              "width": 30,
+              "height": 30,
+              "anchor": {
+                x: 20,
+                y: 30
+              },
+              "src": '/img/icon/add_location.png',
+              "color": '#e54d42', // 标注点文本颜色
+              "size": 14, // 标注点文本文字大小
+              "direction": 'bottom', // 标注点文本文字相对于标注点图片的方位
+              "offset": {
+                x: 0,
+                y: 8
+              }, // 标注点文本文字基于direction方位的偏移属性
+              "strokeColor": '#fff', // 标注点文本描边颜色
+              "strokeWidth": 2, // 标注点文本描边宽度
+            }),
+          },
+          geometries: []
+        });
+        //更新标点坐标
+        if (this.$isEmpty(this.coordinates)) {
+          return
+        }
+        let geometries = []
+        this.coordinates.forEach((item) => {
+          let obj = {
+            "id": item.id,
+            "styleId": 'marker',
+            "content": item.name,
+            "position": new TMap.LatLng(item.latitude, item.longitude),
+            "properties": item,
+          }
+          geometries.push(obj)
+        })
+        markers.updateGeometries(geometries);
+        //点击标记弹出信息窗口
+        let position = new TMap.LatLng(this.coordinates[0].latitude, this.coordinates[0].longitude)
+        //初始化infoWindow
+        infoWindow = new TMap.InfoWindow({
+          map,
+          position,
+          offset: {
+            x: 0,
+            y: -32
+          } //设置信息窗相对position偏移像素
+        });
+        infoWindow.close(); //初始关闭信息窗关闭
+        //监听标注点击事件
+        markers.on("click", (evt) => {
+          let item = evt.geometry.properties
+          if (!this.ismove) {
+            this.openInfoWindow(item)
+          }
+        })
+      },
+      //开启标记拖动
+      markersDrag() {
+        // 初始化几何图形及编辑器
+        editor = new TMap.tools.GeometryEditor({
+          map, // 编辑器绑定的地图对象
+          overlayList: [{
+            overlay: markers, // 可编辑图层
+            id: "marker",
+            selectedStyleId: "addStyle" // 被选中的marker会变为高亮样式
+          }],
+          actionMode: TMap.tools.constants.EDITOR_ACTION.INTERACT, // 编辑器的工作模式
+          activeOverlayId: "marker", // 激活图层
+          selectable: false
+        });
+      },
+      openInfoWindow(data) {
+        //设置infoWindow
+        infoWindow.open(); //打开信息窗
+        infoWindow.setPosition(new TMap.LatLng(data.latitude, data.longitude)); //设置信息窗位置
+        let content = `<div>
+          <div style="color: #272727;font-size: 15px;font-weight: 500;display:flex;justify-content: flex-start">名称:${data.name}</div>
+          <div style="margin-top:6px;font-size: 13px;font-weight: 300;display:flex;justify-content: flex-start">地址:${data.address}</div>
+          <div style="display: flex;justify-content: flex-end;padding-top:8px;font-size:12px;cursor: pointer">
+            <span id="detail" style="color: #2979ff;margin-right: 6px;text-decoration: underline">详情</span>
+            <span id="edit" style="color: #2979ff;margin-right: 6px;text-decoration: underline">编辑</span>
+            <span id="del" style="color: #fa3534;text-decoration: underline" >删除</span>
+          </div>
+        </div>`
+        infoWindow.setContent(content); //设置信息窗内容
+        //详情
+        document.getElementById("detail").addEventListener("click", function() {
+          _this.detail(data)
+        });
+        document.getElementById("edit").addEventListener("click", function() {
+          _this.edit(data)
+        });
+        document.getElementById("del").addEventListener("click", function() {
+          _this.delDevice(data)
+        });
+      },
+      operaMarkers() {
+        if (this.ismove) {
+          this.save()
+        } else {
+          this.move()
+        }
+      },
+      cancelMove() {
+        markers.updateGeometries(this.markerGeometries)
+        this.ismove = false
+        editor.setSelectable(false)
+      },
+      move() {
+        //移动前先把旧的数据保存起来
+        this.markerGeometries = deepClone(markers.getGeometries())
+        console.log(this.markerGeometries, "oldMarkerGeometries");
+
+        this.$notify({
+          title: '提示',
+          type: 'success',
+          message: '已激活拖动操作,请点击所要移动的标记再拖动',
+          duration: 6000
+        });
+        infoWindow.close()
+        markers.remove(["add"])
+        this.isAdd = false
+        this.ismove = true
+        editor.setSelectable(true)
+      },
+      async save() {
+        this.ismove = false
+        editor.setSelectable(false)
+        let oldMarkers = this.markerGeometries
+        let newMarkers = markers.getGeometries()
+
+        let updateObj = []
+        oldMarkers.forEach((oldItem) => {
+          let id = oldItem.id
+          let newItem = newMarkers.find(line => line.id == id)
+
+          let oldLat = oldItem.position.lat.toFixed(6)
+          let newLat = newItem.position.lat.toFixed(6)
+
+          let oldLng = oldItem.position.lng.toFixed(6)
+          let newLng = newItem.position.lng.toFixed(6)
+
+          if (oldLat != newLat || oldLng != newLng) {
+            let model = newItem.properties
+            model.latitude = newLat
+            model.longitude = newLng
+            updateObj.push(model)
+          }
+        })
+        console.log(updateObj, "updateObj");
+        if (this.$isNotEmpty(updateObj)) {
+          let res = await updateBatch(updateObj)
+          if (res.data.success) {
+            this.$message.success('操作成功')
+          }
+        }
+      },
+      detail(data) {
+        infoWindow.close();
+        _this.$refs.doorDeviceForm.showDialog(data)
+      },
+      edit(data) {
+        infoWindow.close();
+        _this.$refs.doorDeviceForm.showDialog(data, false)
+      },
+      delDevice(data) {
+        //先关闭窗口
+        infoWindow.close();
+        this.$confirm("确定删除该设备?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return remove(data.id);
+          })
+          .then(() => {
+            //更新设备列表
+            this.$refs.deviceList.fetchDeviceList()
+            //删除标记
+            markers.remove([data.id])
+            this.message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+
+    }
+  };
+</script>
+
+
+<style scoped lang="scss">
+  .device-body {
+    height: 100%;
+    margin: 0px;
+    padding: 0px;
+  }
+
+  #container {
+    width: 78%;
+    height: 100%;
+  }
+
+  /* 搜索框 */
+  #panel {
+    display: flex;
+    position: absolute;
+    z-index: 9999;
+    top: 30px;
+    left: 30px;
+  }
+
+
+
+  .search {
+    display: flex;
+    width: 280px;
+  }
+
+  /* 编辑器 */
+  #toolControl {
+    display: flex
+  }
+</style>

+ 426 - 55
src/components/map/divide.vue

@@ -1,49 +1,83 @@
 <template>
-  <div class="device-body">
+  <div class="device-body" style="height:100%;">
     <!-- 地图 -->
-    <div id="container"></div>
+    <div id="container" style="height:100%"></div>
     <!-- 搜索框 -->
-    <div id="panel">
+    <div id="panel" style="display:flex;justify-content: center;align-items: center">
       <div class="search">
-        <el-select @change="setSuggestion" style="width:100%" v-model="value" filterable remote reserve-keyword
-          placeholder="请输入设备名称搜索" :remote-method="getSuggestions" :loading="loading">
-          <el-option v-for="(item,index) in suggestionList" :key="index" :label="item.title" :value="index">
-            <span style="float: left">{{ item.title }}</span>
+        <el-select @change="setSuggestion" :clearable="true" @clear="clear" v-model="value" style="width:100%"
+          filterable remote reserve-keyword placeholder="请输入地址关键词" :remote-method="getSuggestions" :loading="loading">
+          <el-option v-for="(item,index) in suggestionList" :key="index" :label="item.name" :value="item">
+            <span style="float: left">{{ item.name }}</span>
             <el-tooltip class="item" effect="dark" :content="item.address" placement="top-start">
               <span style="float: right; color: #8492a6; font-size: 13px;">{{textCut(item.address)}}</span>
             </el-tooltip>
           </el-option>
         </el-select>
       </div>
+
+      <div style="margin-left: 10px" v-if="operaType!=3">
+        <el-button @click="addDevice" icon="el-icon-plus" :type="operaType==1?'primary':''" circle></el-button>
+      </div>
+
+
+      <div style="margin-left: 10px">
+        <el-button @click="operaMarkers" size="small" v-text="operaType==3?'保存':'移动设备位置'"
+          :type="operaType==3?'primary':''" :style="operaType==3?'border-radius:4px 0 0 4px':''"></el-button>
+        <el-button @click="cancelMove" size="small" v-if="operaType==3"
+          style="margin:0;border-radius:0 4px 4px 0;border:1px solid #62a5f6">取消</el-button>
+      </div>
     </div>
     <!-- 设备列表 -->
-    <device-list @click="clickDevice"></device-list>
+    <device-list @click="clickDevice" ref="deviceList"></device-list>
+
+    <door-device-form ref="doorDeviceForm" @reloadData="reloadData"></door-device-form>
   </div>
 </template>
 
 <script>
+
+</script>
+
+<script>
+  import {
+    deepClone
+  } from '@/util/util.js'
+  import doorDeviceForm from "./comps/door-device-form.vue"
   import {
     getDoorDeviceCoordinates
   } from "@/api/device/doordevice.js"
   import * as mapUtil from "./js/mapUtil.js"
   import deviceList from "./comps/device-list.vue"
-  var TMap, map, markers;
-  var infoWindow; //窗口
-  var editor; // 编辑器
+  import {
+    edit,
+    updateBatch,
+    getList,
+    remove
+  } from "@/api/device/doordevice.js"
+  let _this = this
+  let TMap, map, markers, editor, geocoder;
+  let infoWindow; //窗口
   export default {
     components: {
-      deviceList
+      deviceList,
+      doorDeviceForm
     },
     data() {
       return {
-        timer: null,
+        markerGeometries: [],
 
-        dialogVisible: true,
+        //0无操作,1添加操作,2修改操作,3移动操作
+        operaType: 0,
+        operaEditItem: '',
 
+        dialogVisible: false,
         //标记坐标集合
         coordinates: [],
 
+        //搜索
         value: '',
+        suggestionList: [],
         loading: false,
       };
     },
@@ -56,39 +90,106 @@
           }
           return data
         }
-      }
+      },
     },
-    async created() {
-      await this.getDoorDeviceCoordinates()
-      this.initMap()
+    created() {
+      this.init()
     },
     methods: {
+      reloadData(data) {
+        //关闭添加
+        this.operaType = 0
+        //更新设备列表
+        this.$refs.deviceList.fetchDeviceList()
+        let position = markers.getGeometryById("add").position
+        //删除添加标记
+        markers.remove(["add"])
+        //添加新的标记
+        markers.add([{
+          id: data.id,
+          styleId: 'marker',
+          position,
+          content: data.name
+        }])
+      },
+      async init() {
+        _this = this
+        await this.getDoorDeviceCoordinates()
+        this.initMap()
+      },
+      addDevice() {
+        infoWindow.close();
+        if (this.operaType == 1) {
+          this.operaType = 0
+        } else {
+          this.operaType = 1
+        }
+        if (this.operaType == 1) {
+          let center = map.getCenter()
+          this.addMarkers('add', center)
+
+          this.$notify({
+            title: '提示',
+            type: 'success',
+            message: '已激活添加设备操作,请点击地图选点再添加设备',
+            duration: 6000
+          });
+
+        } else {
+          markers.remove(["add"])
+        }
+      },
+      async getSuggestions(name) {
+        let params = {
+          name
+        }
+        let res = await getList(1, 10, params)
+        let data = res.data.data
+        this.suggestionList = data.records
+        this.$refs.deviceList.initData(data)
+      },
+      clear() {
+        this.getSuggestions()
+      },
+      setSuggestion(item) {
+        //先关闭窗口
+        infoWindow.close();
+        //再打开窗口
+        this.openInfoWindow(item)
+      },
       // animation:qq.maps.MarkerAnimation.DROP,
       clickDevice(item) {
         let flag = this.coordinates.some(line => line.id == item.id)
         if (flag) {
+          map.setCenter(new TMap.LatLng(item.latitude, item.longitude))
           //先关闭窗口
           infoWindow.close();
           //再打开窗口
           this.openInfoWindow(item)
           return
         }
-        this.addMarkers()
-      },
-      addMarkers() {
-        let mapCenter = map.getCenter(); //获取地图中心点坐标
-        let marker = {
-          "id": '',
-          "styleId": 'marker',
-          'position': mapCenter,
-          map
+        this.operaType = 2
+        //选取设备坐标
+        let id = item.id + 'edit'
+        //获取所有的标记点,如果存在编辑中的标记,先移除再添加
+        let geometries = deepClone(markers.geometries) || null
+        if (geometries) {
+          let editItem = geometries.find(item => item.id.indexOf('edit') >= 0)
+          if (editItem) {
+            markers.remove([editItem.id])
+          }
         }
-        markers.add([{
-          "id": "", //点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
-          "styleId": 'myStyle', //指定样式id
-          "position": mapCenter,
-          "properties": {}
-        }])
+        this.operaEditItem = item
+        let position = map.getCenter()
+        this.addMarkers(id, position, this.operaEditItem.name)
+
+        this.$notify({
+          title: '提示',
+          type: 'success',
+          message: '请点击地图选取设备坐标',
+          duration: 6000
+        });
+
       },
       //获取设备坐标集合
       async getDoorDeviceCoordinates() {
@@ -97,31 +198,148 @@
       },
       async initMap() {
         let scripts = ['https://map.qq.com/api/gljs?libraries=service&v=1.exp',
+          'https://map.qq.com/api/js?v=2.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77',
           'https://map.qq.com/api/gljs?libraries=tools&v=1.exp'
         ]
         TMap = await mapUtil.loadMap(scripts)
         //创建地图
         this.createMap()
+        //新建逆地址服务类
+        geocoder = new TMap.service.Geocoder();
+
         //创建标点集合类
         this.createMarkers()
+        //创建标点拖动类
+        this.markersDrag()
         //设置中心位置
         this.setCenter()
+
+
+      },
+      //逆地址
+      async getAddress(location) {
+        let address = (await geocoder.getAddress({
+          location
+        })).result.address
+        return address
       },
+
       /**
        * 创建地图
        */
       createMap() {
+        let _this = this
         //获取中心点
         map = new TMap.Map('container', {
           zoom: 19,
+          baseMap: {
+            type: 'vector',
+            features: ['base', 'building3d'], // 隐藏矢量文字
+          },
         });
-        map.on("click", function(evt) {
-          var lat = evt.latLng.getLat().toFixed(6);
-          var lng = evt.latLng.getLng().toFixed(6);
-          let arr = lat + "," + lng;
-          console.log(arr);
-        })
+        map.on("click", async (evt) => {
+          let lat = evt.latLng.getLat().toFixed(6);
+          let lng = evt.latLng.getLng().toFixed(6);
+          let model = {
+            latitude: lat,
+            longitude: lng,
+            address: ''
+          }
+          let position = new TMap.LatLng(lat, lng)
 
+          if (this.operaType != 1 && this.operaType != 2) {
+            return
+          }
+          //逆地址解释
+          model.address = await this.getAddress(position)
+          if (this.operaType == 1) {
+            this.showAddForm(model, position)
+            return
+          }
+          if (this.operaType == 2) {
+            this.showEditForm(model, position)
+          }
+
+        })
+      },
+      confirmEdit() {
+        //旧的标记会带有edit字符,保存成功后需要移除edit字符
+        let id = this.operaEditItem.id + 'edit'
+        let old = markers.getGeometryById(id)
+        let model = {
+          id: this.operaEditItem.id,
+          latitude: old.position.lat,
+          longitude: old.position.lng
+        }
+        this.$confirm(`确定选取该坐标作为设备【${this.operaEditItem.name}】的坐标?`, {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "success"
+          })
+          .then(() => {
+            return edit(model);
+          })
+          .then(() => {
+            this.$refs.deviceList.fetchDeviceList()
+            markers.remove([id])
+            this.addMarkers(this.operaEditItem.id, old.position, this.operaEditItem.name, 'marker')
+            this.message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      async showEditForm(model, position) {
+        let geometries = deepClone(markers.geometries) || null
+        let id = this.operaEditItem.id + 'edit'
+        if (!geometries) {
+          this.addMarkers(id, position, this.operaEditItem.name)
+          this.confirmEdit()
+          return
+        }
+        let flag = geometries.find(item => item.id == id)
+        if (!flag) {
+          this.addMarkers(id, position)
+          this.confirmEdit()
+          return
+        }
+        markers.updateGeometries([{
+          id,
+          position,
+          styleId: 'addStyle',
+          content: this.operaEditItem.name,
+        }])
+        this.confirmEdit()
+      },
+      async showAddForm(model, position) {
+        let id = 'add'
+        let geometries = deepClone(markers.geometries) || null
+        if (!geometries) {
+          _this.addMarkers(id, position)
+          _this.$refs.doorDeviceForm.showAddForm(model)
+          return
+        }
+        let flag = geometries.find(item => item.id == "add")
+        if (!flag) {
+          _this.addMarkers(id, position)
+          _this.$refs.doorDeviceForm.showAddForm(model)
+          return
+        }
+        markers.updateGeometries([{
+          id,
+          position,
+          styleId: 'addStyle',
+          content: '点击地图选点',
+        }])
+        _this.$refs.doorDeviceForm.showAddForm(model)
+      },
+      addMarkers(id, position, content = '点击地图选点', styleId = 'addStyle') {
+        markers.add([{
+          id,
+          styleId,
+          position,
+          content,
+        }])
       },
       //设置中心位置
       setCenter() {
@@ -137,7 +355,7 @@
        * 创建区域
        */
       crearePolygon() {
-        var polygon = new TMap.MultiPolygon({
+        let polygon = new TMap.MultiPolygon({
           map,
           geometries: [{
             paths,
@@ -151,7 +369,21 @@
         //创建标点集合对象
         markers = new TMap.MultiMarker({
           id: 'marker-layer',
+          enableCollision: false,
           map,
+          styles: {
+            'label': new TMap.LabelStyle({
+              'color': '#3777FF', //颜色属性
+              'size': 20, //文字大小属性
+              'offset': {
+                x: 0,
+                y: 0
+              }, //文字偏移属性单位为像素
+              'angle': 90, //文字旋转属性
+              'alignment': 'center', //文字水平对齐属性
+              'verticalAlignment': 'middle' //文字垂直对齐属性
+            })
+          },
           styles: {
             "marker": new TMap.MarkerStyle({
               "width": 30,
@@ -160,8 +392,35 @@
                 x: 16,
                 y: 32
               },
-              "src": '/img/device/door-device.png'
-            })
+              "src": '/img/device/door-device.png',
+              "color": '#333', // 标注点文本颜色
+              "size": 14, // 标注点文本文字大小
+              "direction": 'bottom', // 标注点文本文字相对于标注点图片的方位
+              "offset": {
+                x: 0,
+                y: 8
+              }, // 标注点文本文字基于direction方位的偏移属性
+              "strokeColor": '#fff', // 标注点文本描边颜色
+              "strokeWidth": 2, // 标注点文本描边宽度
+            }),
+            "addStyle": new TMap.MarkerStyle({
+              "width": 30,
+              "height": 30,
+              "anchor": {
+                x: 20,
+                y: 30
+              },
+              "src": '/img/icon/add_location.png',
+              "color": '#e54d42', // 标注点文本颜色
+              "size": 14, // 标注点文本文字大小
+              "direction": 'bottom', // 标注点文本文字相对于标注点图片的方位
+              "offset": {
+                x: 0,
+                y: 8
+              }, // 标注点文本文字基于direction方位的偏移属性
+              "strokeColor": '#fff', // 标注点文本描边颜色
+              "strokeWidth": 2, // 标注点文本描边宽度
+            }),
           },
           geometries: []
         });
@@ -170,17 +429,17 @@
           return
         }
         let geometries = []
-        this.coordinates.forEach((item, index) => {
+        this.coordinates.forEach((item) => {
           let obj = {
             "id": item.id,
             "styleId": 'marker',
+            "content": item.name,
             "position": new TMap.LatLng(item.latitude, item.longitude),
             "properties": item,
           }
           geometries.push(obj)
         })
         markers.updateGeometries(geometries);
-
         //点击标记弹出信息窗口
         let position = new TMap.LatLng(this.coordinates[0].latitude, this.coordinates[0].longitude)
         //初始化infoWindow
@@ -195,14 +454,29 @@
         infoWindow.close(); //初始关闭信息窗关闭
         //监听标注点击事件
         markers.on("click", (evt) => {
+          console.log(this.operaType == 0);
           let item = evt.geometry.properties
-          this.openInfoWindow(item)
+          if (this.operaType == 0) {
+            this.openInfoWindow(item)
+          }
         })
       },
+      //开启标记拖动
+      markersDrag() {
+        // 初始化几何图形及编辑器
+        editor = new TMap.tools.GeometryEditor({
+          map, // 编辑器绑定的地图对象
+          overlayList: [{
+            overlay: markers, // 可编辑图层
+            id: "marker",
+            selectedStyleId: "addStyle" // 被选中的marker会变为高亮样式
+          }],
+          actionMode: TMap.tools.constants.EDITOR_ACTION.INTERACT, // 编辑器的工作模式
+          activeOverlayId: "marker", // 激活图层
+          selectable: false
+        });
+      },
       openInfoWindow(data) {
-        if (this.timer) {
-          clearTimeout(this.timer)
-        }
         //设置infoWindow
         infoWindow.open(); //打开信息窗
         infoWindow.setPosition(new TMap.LatLng(data.latitude, data.longitude)); //设置信息窗位置
@@ -210,16 +484,113 @@
           <div style="color: #272727;font-size: 15px;font-weight: 500;display:flex;justify-content: flex-start">名称:${data.name}</div>
           <div style="margin-top:6px;font-size: 13px;font-weight: 300;display:flex;justify-content: flex-start">地址:${data.address}</div>
           <div style="display: flex;justify-content: flex-end;padding-top:8px;font-size:12px;cursor: pointer">
-            <span style="color: #2979ff;margin-right: 6px;text-decoration: underline">移动</span>
-            <span style="color: #fa3534;text-decoration: underline">删除</span>
+            <span id="detail" style="color: #2979ff;margin-right: 6px;text-decoration: underline">详情</span>
+            <span id="edit" style="color: #2979ff;margin-right: 6px;text-decoration: underline">编辑</span>
+            <span id="del" style="color: #fa3534;text-decoration: underline" >删除</span>
           </div>
         </div>`
         infoWindow.setContent(content); //设置信息窗内容
-        //3s后关闭
-        this.timer = setTimeout(() => {
-          infoWindow.close();
-        }, 3000)
-      }
+        //详情
+        document.getElementById("detail").addEventListener("click", function() {
+          _this.detail(data)
+        });
+        document.getElementById("edit").addEventListener("click", function() {
+          _this.edit(data)
+        });
+        document.getElementById("del").addEventListener("click", function() {
+          _this.delDevice(data)
+        });
+      },
+      operaMarkers() {
+        if (this.operaType == 3) {
+          this.save()
+        } else {
+          this.move()
+        }
+      },
+      cancelMove() {
+        markers.updateGeometries(this.markerGeometries)
+        this.operaType = 0
+        editor.setSelectable(false)
+      },
+      move() {
+        //移动前先把旧的数据保存起来
+        this.markerGeometries = deepClone(markers.getGeometries())
+        console.log(this.markerGeometries, "oldMarkerGeometries");
+
+        this.$notify({
+          title: '提示',
+          type: 'success',
+          message: '已激活拖动操作,请点击所要移动的标记再拖动',
+          duration: 6000
+        });
+        infoWindow.close()
+        markers.remove(["add"])
+        this.operaType = 3
+        editor.setSelectable(true)
+      },
+      async save() {
+        this.operaType = 0
+        editor.setSelectable(false)
+        let oldMarkers = this.markerGeometries
+        let newMarkers = markers.getGeometries()
+
+        let updateObj = []
+        oldMarkers.forEach((oldItem) => {
+          let id = oldItem.id
+          let newItem = newMarkers.find(line => line.id == id)
+
+          let oldLat = oldItem.position.lat.toFixed(6)
+          let newLat = newItem.position.lat.toFixed(6)
+
+          let oldLng = oldItem.position.lng.toFixed(6)
+          let newLng = newItem.position.lng.toFixed(6)
+
+          if (oldLat != newLat || oldLng != newLng) {
+            let model = newItem.properties
+            model.latitude = newLat
+            model.longitude = newLng
+            updateObj.push(model)
+          }
+        })
+        console.log(updateObj, "updateObj");
+        if (this.$isNotEmpty(updateObj)) {
+          let res = await updateBatch(updateObj)
+          if (res.data.success) {
+            this.$message.success('操作成功')
+          }
+        }
+      },
+      detail(data) {
+        infoWindow.close();
+        _this.$refs.doorDeviceForm.showDialog(data)
+      },
+      edit(data) {
+        infoWindow.close();
+        _this.$refs.doorDeviceForm.showDialog(data, false)
+      },
+      delDevice(data) {
+        //先关闭窗口
+        infoWindow.close();
+        this.$confirm("确定删除该设备?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return remove(data.id);
+          })
+          .then(() => {
+            //更新设备列表
+            this.$refs.deviceList.fetchDeviceList()
+            //删除标记
+            markers.remove([data.id])
+            this.message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
 
     }
   };

+ 26 - 0
src/views/dashboard/smartoperationcenter/smartoperationcenter.vue

@@ -1,4 +1,29 @@
 <template>
+  <div class="full">
+    <divide></divide>
+  </div>
+</template>
+
+<script>
+  import divide from "@/components/map/divide.vue"
+  export default {
+    components: {
+      divide
+    },
+    data() {
+      return {
+
+      };
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+
+</style>
+
+
+<!-- <template>
   <div class="body">
     <el-row>
       <el-col :span="18">
@@ -87,3 +112,4 @@
     }
   }
 </style>
+ -->

+ 0 - 2
src/views/smartaccess/comps/face-card.vue

@@ -169,7 +169,6 @@
   import {
     getToken
   } from '@/util/auth';
-  import website from '@/config/website';
   //常驻人员
   import staffForm from "../form/staff.vue"
   import {
@@ -193,7 +192,6 @@
   //
   import {
     getList2 as getSnapList,
-    exportExcel
   } from "@/api/estate/snaprecord.js";
   //菜单
   import menuList from "./menu-list.vue"

+ 1 - 1
vue.config.js

@@ -26,7 +26,7 @@ module.exports = {
     proxy: {
       '/api': {
         //本地服务接口地址
-        target: 'http://192.168.1.120',
+        target: 'http://192.168.1.69',
         // target: 'http://8.135.18.59',
         //远程演示服务地址,可用于直接启动项目
         // target: 'https://saber.bladex.vip/api',