zhaobao 2 жил өмнө
parent
commit
2b9060ceb6

+ 2 - 2
src/layout/components/Navbar.vue

@@ -90,8 +90,8 @@ export default {
 
         /** ckq */
         { name: '数字全景', icon: 'el-icon-s-platform', href: 'http://localhost:8080/', permit: 'aqpt_panorama', id: 0 },
-        { name: '双重预防【采空区信息&人员巡检】', icon: 'icon-common_quality', path: '/aqpt/scene', permit: 'aqpt_workflow', id: 3 },
-        { name: '设备管理【传感器】', icon: 'icon-common_equipment', path: '/aqpt/equipment', permit: 'aqpt_equipment', id: 4 },
+        { name: '双重预防', icon: 'icon-common_quality', path: '/aqpt/scene', permit: 'aqpt_workflow', id: 3 },
+        { name: '设备管理', icon: 'icon-common_equipment', path: '/aqpt/equipment', permit: 'aqpt_equipment', id: 4 },
         { name: '预警中心', icon: 'icon-common_saving', path: '/alert', permit: 'aqpt_alert_center', id: 1 },
         { name: '工作台', icon: 'icon-common_task', path: '/task', permit: 'aqpt_task_center', id: 2 },
         // { name: '作业票', icon: 'icon-common_satisfaction', path: '/aqpt/ticket', permit: 'aqpt_ticket', id: 5 },

+ 31 - 4
src/router/modules/aqpt.js

@@ -103,10 +103,11 @@ const aqptRouter = [
     path: '/goaf',
     component: Layout,
     name: 'goaf',
-    redirect: '/aqpt/info',
+    redirect: '/goaf/info',
     meta: {
-      title: '采空区信息',
-      permit: 'aqpt_danger'
+      title: '采空区管理',
+      permit: 'aqpt_danger',
+      icon: 'icon-common_riskmanagement'
     },
     groupId: [3],
     children: [
@@ -114,7 +115,33 @@ const aqptRouter = [
         path: 'info',
         component: () => import('@/views/goaf/info/index'),
         name: 'goaf-info',
-        meta: { title: '采空区信息配置', noCache: true, icon: 'icon-common_riskmanagement', permit: 'aqpt_danger' }
+        meta: {
+          title: '采空区信息配置',
+          noCache: true,
+          permit: 'aqpt_danger'
+        }
+      },
+      {
+        path: 'sensor',
+        component: () => import('@/views/goaf/sensor/index'),
+        name: 'goaf-sensor',
+        meta: {
+          title: '传感器配置',
+          noCache: true,
+          // icon: 'icon-common_equipment',
+          permit: 'aqpt_danger'
+        }
+      },
+      {
+        path: 'map',
+        component: () => import('@/views/goaf/map/index'),
+        name: 'goaf-map',
+        meta: {
+          title: '可视化编辑',
+          noCache: true,
+          // icon: 'icon-common_equipment',
+          permit: 'aqpt_danger'
+        }
       }
     ]
   },

+ 3 - 4
src/views/goaf/info/components/Goaf.vue

@@ -4,7 +4,7 @@
     :modal-append-to-body="false"
     :modal="false"
     :wrapper-closable="false"
-    size="35%"
+    size="36%"
     :visible.sync="dialogVisible"
   >
     <div class="content-container goaf">
@@ -67,6 +67,7 @@
               type="date"
               placeholder="请选择形成时间"
               class="date"
+              value-format="yyyy-MM-dd"
               :default-value="new Date(2010, 9, 1)"
               style="width:200px"
             />
@@ -212,7 +213,6 @@ export default {
         if (valid) {
           switch (this.actionType) {
             case 'ADD':
-              this.formData.positionIdList = this.formData.positionId.toString()
               createHazardRisk(this.formData).then((resp) => {
                 const { code, msg } = resp
                 if (code === 0) {
@@ -228,7 +228,6 @@ export default {
               break
 
             case 'UPDATE':
-              this.formData.positionIdList = this.formData.positionId.toString()
               updateHazardRisk(this.formData).then((resp) => {
                 const { code, msg } = resp
                 if (code === 0) {
@@ -244,7 +243,7 @@ export default {
               break
           }
         } else {
-          console.log('error submit!!')
+          this.$message.error('error submit!!')
           return false
         }
       })

+ 13 - 39
src/views/goaf/info/components/GoafInfo.vue

@@ -15,7 +15,7 @@
     </el-row>
 
     <el-row class="m-top-15">
-      <el-table v-loading="listLoading" class="page-table" border fit :data="dataList" style="width: 100%;height:80vh" :span-method="arraySpanMethod">
+      <el-table v-loading="listLoading" class="page-table" border fit :data="dataList" :span-method="arraySpanMethod">
         <!-- <el-table-column type="index" label="序号" header-align="center" align="center" width="60" /> -->
         <el-table-column prop="goafOrebelt" label="矿带" />
         <el-table-column prop="goafOreheight" label="中段" />
@@ -25,11 +25,9 @@
         <el-table-column prop="goafAvinWidth" label="平均倾向宽度" />
         <el-table-column prop="goafAvexHeight" label="平均暴露高度">
           <template v-slot="{row}">
-            <span>{{ row.goafAvexHeight==0?'已填充”':row.goafAvexHeigh }}</span>
+            <span>{{ row.goafAvexHeight==0?'已填充”':row.goafAvexHeight }}</span>
           </template>
         </el-table-column>
-
-        <el-table-column prop="goafOrebelt" label="风险单元" />
         <el-table-column prop="goafVoidVolume" label="体积">
           <template v-slot="{row}">
             <span>{{ row.goafVoidVolume==0?'已填充':row.goafVoidVolume }}</span>
@@ -42,7 +40,7 @@
         <el-table-column prop="goafExpLocation" label="勘探位置" />
         <el-table-column prop="goafRockLithology" label="围岩岩性" />
         <el-table-column prop="goafRockStability" label="围岩稳定性" />
-        <el-table-column prop="goafFormationTime" label="形成时间" />
+        <el-table-column prop="goafFormationTime" label="形成时间" width="150" />
         <!-- <el-table-column prop="goafCanfillVolume" label="可充填体积(m³)" />
         <el-table-column prop="goafRemainVolume" label="剩余可充填体积(m³)" /> -->
         <el-table-column prop="goafFillMethod" label="充填方式">
@@ -88,30 +86,6 @@ export default {
         data: {
           goafName: ''
         }
-      },
-      viewData: {
-        'ocId': '',
-        'goafOrebelt': 0,
-        'goafOrebody': 0,
-        'goafOreheight': 0,
-        'goafName': '0',
-        'goafAvexArea': 0,
-        'goafAvinWidth': 0,
-        'goafAvexHeight': 0,
-        'goafVoidVolume': 0,
-        'goafKeyTrend': 0,
-        'goafKeyDipangle': 0,
-        'goafRoofpillarThickness': 0,
-        'goafIncoavThickness': 0,
-        'goafExpLocation': '',
-        'goafRockLithology': '',
-        'goafRockStability': '',
-        'goafFormationTime': '',
-        'goafCanfillVolume': 0,
-        'goafRemainVolume': 0,
-        'goafFillMethod': 0,
-        'goafIsFill': 0,
-        'goafInfoRemak': ''
       }
     }
   },
@@ -145,11 +119,9 @@ export default {
     }
     this.dataList = items
     this.total = 20
-    // this.conditions.page = 1
-    // this.conditions.limit = 1
   },
   methods: {
-    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
+    arraySpanMethod({ rowIndex, columnIndex }) {
       if (columnIndex < 2) {
         if (rowIndex < 1) {
           return [this.conditions.limit || 10, 1]
@@ -158,9 +130,7 @@ export default {
         }
       }
     },
-    loadData(hazardId, hazardTitle) {
-      this.conditions.hazardId = hazardId
-      this.viewData.hazardTitle = hazardTitle
+    loadData() {
       this.getData()
     },
 
@@ -182,9 +152,7 @@ export default {
     },
     // "Add Risk" Model
     handleAdd() {
-      const hazardId = this.conditions.hazardId
-      const hazardTitle = this.viewData.hazardTitle
-      this.$refs['goaf'].showAddModel(hazardId, hazardTitle)
+      this.$refs['goaf'].showAddModel()
     },
 
     // "Edit Risk" Model
@@ -263,8 +231,14 @@ export default {
         }
     }
 </style>
-<style>
+<style lang="scss">
 .goaf .el-table__body tr.hover-row>td {
   background-color: #306379;
 }
+.goaf{
+      .page-table{
+        height: calc(100vh - 260px);
+        overflow-y: auto;
+      }
+    }
 </style>

+ 668 - 0
src/views/goaf/map/components/VisualEditor.vue

@@ -0,0 +1,668 @@
+<template>
+  <div class="map-container">
+    <nav>
+      <map-selector :default-val="formData.mapId" @setMapInfo="handleSelectMap" />
+      <!-- <div class="page-title">
+        现场分布图
+      </div> -->
+      <el-button size="mini" type="primary" style="margin-left:15px;" @click="submit">保存</el-button>
+    </nav>
+    <div class="layout-map">
+      <div class="left-side">
+        <div class="title">作业项目</div>
+        <div v-for="(item,index) in markerItems" :key="index" :class="checkItemIndex===index?'item active':'item'" @click="checkItem(item,index)">
+          <img :src="item.icon" alt="" class="icon">
+          <div class="name">{{ item.name }}</div>
+        </div>
+      </div>
+      <div id="vmap" />
+      <div class="rightSide">
+        <div v-if="type==1" class="remark">
+          <div class="title">使用说明</div>
+          <ul>
+            <li>1.点击作业项目下面的图标</li>
+            <li>2.点击地图绘制点</li>
+            <li>3.编辑信息保存点位</li>
+          </ul>
+        </div>
+        <div v-if="type==2||type=='drage'" class="saveForm">
+          <div class="title">作业点基本信息</div>
+          <div class="item">
+            <div class="lable">作业项目:</div>
+            <div class="content">
+              <img class="icon" :src="saveForm.icon" alt="">
+              <span>{{ saveForm.name }}</span>
+            </div>
+            <el-select v-model="saveForm.goafId" style="width:200px">
+              <el-option :value="0" label="采空区" />
+            </el-select>
+          </div>
+          <div class="item">
+            <div class="lable">名称:</div>
+            <div class="content">
+              <span>{{ saveForm.name }}</span>
+            </div>
+          </div>
+          <div class="bt-wrap">
+            <div class="bt save" @click="save">保存</div>
+            <div class="bt margin" @click="cancel">撤销</div>
+          </div>
+        </div>
+        <div v-if="type==3" class="deleteForm">
+          <div class="title">作业点基本信息</div>
+          <div class="item">
+            <div class="lable">作业项目:</div>
+            <div class="content">
+              <img class="icon" :src="deleteForm.icon" alt="">
+              <span>{{ deleteForm.name }}</span>
+            </div>
+          </div>
+          <div class="item">
+            <div class="lable">名称:</div>
+            <div class="content">
+              <span>{{ deleteForm.name }}</span>
+            </div>
+          </div>
+          <div class="bt-wrap">
+            <div class="bt" @click="save">保存</div>
+            <div class="bt delete margin" @click="delMarker">删除</div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+  </div>
+</template>
+
+<script>
+import * as L from 'leaflet'
+import '@geoman-io/leaflet-geoman-free'
+import MapSelector from '@/components/MapSelector'
+import { getMapLayerById, createMapLayer, getMapLayerByList } from '@/api/system/mapLayerApi'
+const markerIcon = L.icon({
+  iconUrl: require('@/assets/images/icon/4.png'),
+  shadowUrl: require('@/assets/images/icon/4hover.png'),
+  iconSize: [60, 70],
+  shadowSize: [60, 70],
+  iconAnchor: [16, 52],
+  popupAnchor: [1, -38]
+})
+L.Marker.prototype.options.icon = markerIcon
+
+import { addApi, delApi, updateApi } from '@/api/aqpt/visualEditor'
+export default {
+  name: 'GoafVisualEditor',
+  components: {
+    MapSelector
+  },
+  data() {
+    return {
+      viewData: {},
+      formData: {
+        mapId: undefined,
+        layerId: undefined,
+        layerVector: ''
+      },
+      type: 1,
+      checkItemIndex: -1,
+      state: 0,
+      markerItems: [
+        { icon: require('@/assets/images/icon/4.png'), name: '动火作业' }
+      ],
+      map: undefined,
+      geoLayer: undefined,
+      conditions: {
+        layerId: undefined
+      },
+      saveForm: {
+        'icon': '',
+        'name': '',
+        'goaflayerId': '',
+        'ocId': '',
+        'goafId': '',
+        'goafName': '',
+        'mapId': '',
+        'layerId': '',
+        'layerCatId': '',
+        'layerTitle': '',
+        'layerMarker': '',
+        'layerVector': '',
+        'layerVectorType': ''
+      },
+      deleteForm: {
+        'icon': '',
+        'name': '',
+        'goaflayerId': '',
+        'ocId': '',
+        'goafId': '',
+        'goafName': '',
+        'mapId': '',
+        'layerId': '',
+        'layerCatId': '',
+        'layerTitle': '',
+        'layerMarker': '',
+        'layerVector': '',
+        'layerVectorType': ''
+      },
+      layer: null,
+      layers: [],
+      layerGroup: [],
+      imageOverlay: undefined
+    }
+  },
+  watch: {},
+  mounted() {
+    this.initMap()
+  },
+  methods: {
+
+    // 加载数据
+    load(layerId) {
+      this.conditions.layerId = layerId
+      this.getData()
+    },
+    // 初始化
+    getData() {
+      getMapLayerById(this.conditions.layerId).then((resp) => {
+        const { code, data, msg } = resp
+        if (code === 0) {
+          this.viewData = data
+          this.setRasterLayer()
+        } else {
+          this.$message.error(msg)
+        }
+      }).catch((error) => {
+        console.log(error)
+      })
+    },
+
+    // 初始化地图
+    initMap() {
+      var yx = L.latLng
+      var xy = function xy(x, y) {
+        if (L.Util.isArray(x)) {
+          return yx(x[1], x[0])
+        }
+        return yx(y, x)
+      }
+      var bounds = [xy(-600, -600), xy(300, 300)]
+      this.map = L.map('vmap', {
+        crs: L.CRS.Simple, // 一个简单的CRS,可将经度和纬度直接映射到x其中y。可用于平面地图(例如游戏地图)
+        minZoom: 0,
+        maxZoom: 18,
+        zoom: 0,
+        maxBounds: bounds, // 地图拖动到边界后自动弹回
+        maxBoundsViscosity: 0.2,
+        attributionControl: false,
+        zoomControl: true // zoomControl(缩放控制):确定缩放控制是否默认加载在地图上。
+      })
+      this.geoLayer = L.geoJson(null, { pmIgnore: false })
+      this.geoLayer.addTo(this.map)
+      this.mapListener()
+      if (!this.viewData.layerVector) return
+      this.geoLayer.addData(this.viewData.layerVector)
+    },
+
+    // 设置地图背景图
+    setRasterLayer() {
+      var yx = L.latLng
+      var xy = function xy(x, y) {
+        if (L.Util.isArray(x)) {
+          return yx(x[1], x[0])
+        }
+        return yx(y, x)
+      }
+      var bounds = [xy(-600, -600), xy(300, 300)]
+      if (this.imageOverlay) {
+        this.imageOverlay.setUrl(this.viewData.mapRasterLayer)
+      } else {
+        this.imageOverlay = L.imageOverlay(this.viewData.mapRasterLayer, bounds).addTo(this.map)
+      }
+
+      this.map.fitBounds(bounds)
+      this.map.scrollWheelZoom.disable()
+      this.getMapLayers()
+    },
+
+    // 选择地图
+    handleSelectMap(obj) {
+      this.viewData.mapRasterLayer = obj.mapRasterLayer
+      this.viewData.mapId = obj.mapId
+      this.formData.mapId = obj.mapId
+      this.setRasterLayer()
+    },
+    createMapLayer() {
+      createMapLayer().then(() => {
+
+      })
+    },
+    formSuccess() {
+      this.$emit('formSuccess')
+    },
+    mapListener() {
+      const self = this
+      this.map.on('pm:drawstart', (e) => { // 绘制开始时事件
+        if (e.shape === 'Marker') {
+          const iconUrl = this.saveForm.icon
+          const layer = e.workingLayer
+          var icon = L.icon({
+            iconUrl,
+            shadowUrl: iconUrl,
+            shadowSize: [60, 70],
+            iconSize: [60, 70]
+          })
+          layer.setIcon(icon)
+        }
+      })
+      this.map.on('pm:create', (e) => {
+        if (e.shape === 'Marker') {
+          const iconUrl = this.saveForm.icon
+          const name = this.saveForm.name
+          const typeId = this.checkItemIndex + 1
+          const layer = e.layer
+          var icon = L.icon({
+            iconUrl,
+            shadowUrl: iconUrl,
+            name,
+            typeId,
+            shadowSize: [60, 70],
+            iconSize: [60, 70]
+          })
+          layer.setIcon(icon)
+          layer.on('click', function(ev) {
+            self.type = 3
+            self.markerId = ev.target._leaflet_id
+            self.deleteForm.name = ev.target.options.icon.options.name
+            self.deleteForm.icon = ev.target.options.icon.options.iconUrl
+          })
+          self.layer = layer
+          layer.addTo(this.layerGroup)
+        }
+        this.map.pm.disableDraw(e.shape)
+      })
+    },
+    // 获取地图图层数据
+    getMapLayers() {
+      const obj = {}
+      obj.mapId = this.mapId
+      getMapLayerByList(obj).then((resp) => {
+        const { code, data, msg } = resp
+        if (code === 0) {
+          this.mapLayerList = data
+          this.initMapLayers()
+        } else {
+          this.$message.error(msg)
+        }
+      }).catch((error) => {
+        console.log(error)
+      })
+    },
+
+    // 初始化地图图层
+    initMapLayers() {
+      var layerList = this.mapLayerList
+      console.log
+      this.layerGroup = L.layerGroup().addTo(this.map)
+      var vectorGeoJson = []
+      if (layerList != null && layerList.length > 0) {
+        layerList.forEach((item) => {
+          item.layerMarker && vectorGeoJson.push(JSON.parse(item.layerMarker))
+          item.layerVector && vectorGeoJson.push(JSON.parse(item.layerVector))
+        })
+        L.geoJSON(vectorGeoJson, { }).addTo(this.map)
+      }
+    },
+    submit() {
+      // 图层操作完,一次导出geoJSON
+      const layers = this.map._layers
+      console.log({
+        layers,
+        geoLayer: this.geoLayer,
+        geoJson: this.createGeoJson()
+      })
+    },
+    formatlayer(data) {
+      const enums = {
+        'Marker': 'Point'
+      }
+      return {
+        'type': 'Feature',
+        'properties': {
+          'name': 'Coors Field',
+          'amenity': 'Baseball Stadium',
+          'popupContent': 'This is where the Rockies play!',
+          'subType': data.shape,
+          'radius': data.layer._radius
+        },
+        'leaflet_id': data.layer._leaflet_id,
+        'geometry': {
+          'type': enums[data.shape] || data.shape,
+          'coordinates': data.layer._latlng
+        }
+      }
+    },
+    drawLayer(params, map = this.map) {
+      var layer = null
+      const _latlng = params.geometry.coordinates.latlng
+      const latlng = Array.isArray(_latlng) ? _latlng(item => [item.lat, item.lng]) : [_latlng.lat, _latlng.lng]
+      switch (params.type) {
+        case 'Marker' :
+          layer = L.marker([latlng]).addTo(map)
+          break
+        case 'Line' :
+          layer = L.polyline([latlng]).addTo(map)
+          break
+        case 'Circle' :
+          layer = L.circle([latlng], {
+            color: 'red',
+            fillColor: '#f03',
+            fillOpacity: 0.5,
+            radius: params.properties.radius
+          }).addTo(map)
+          break
+        case 'Rectangle' :
+          layer = L.rectangle(latlng).addTo(map)
+          break
+        case 'Polygon' :
+          layer = L.polygon(latlng).addTo(map)
+          break
+      }
+      return layer
+    },
+    createGeoJson() {
+      var layerArray = []
+      this.map.eachLayer(function(layer) {
+        if (layer.pm !== 'undefined' && layer.pm != null && layer.pm !== '') {
+          if (layer.pm._enabled === false && layer.pm.options.draggable === true) {
+            layerArray.push(layer)
+          }
+        }
+      })
+      var geojson = L.layerGroup(layerArray).toGeoJSON()
+      for (var n = 0; n < geojson.features.length; n++) {
+        var nowJson = JSON.stringify(geojson.features[n])
+        for (var m = n + 1; m < geojson.features.length; m++) {
+          var nextJson = JSON.stringify(geojson.features[m])
+          if (nowJson === nextJson) {
+            geojson.features.splice(n, 1)
+          }
+        }
+      }
+      return geojson
+    },
+
+    checkItem(item, index) {
+      if (this.state === 1) {
+        this.$message('请保存后再操作!')
+        return
+      }
+      this.checkItemIndex = index
+      this.type = 2
+      this.saveForm.icon = item.icon
+      this.saveForm.name = item.name
+      this.map.pm.enableDraw('Marker', { snappable: false, tooltips: false })// tooltips: { 'placeMarker': '点击放置标记' },
+      this.state = 1
+    },
+    save() {
+      if (this.type === 3) {
+        // 删除表单里面的保存
+        this.type = 1
+      } else if (this.type === 'drage') {
+        updateApi({
+          'jobactivityTitle': this.layer.options.icon.options.name,
+          'jobactQywzjd': this.layer._latlng.lng,
+          'jobactQywzwd': this.layer._latlng.lat,
+          'veditId': this.veditId,
+          'typeId': this.layer.options.icon.options.typeId
+        }).then(() => {
+          this.type = 1
+          this.checkItemIndex = -1
+          this.state = 2
+          this.saveForm = {
+            'icon': '',
+            'name': '',
+            'goaflayerId': '',
+            'ocId': '',
+            'goafId': '',
+            'goafName': '',
+            'mapId': '',
+            'layerId': '',
+            'layerCatId': '',
+            'layerTitle': '',
+            'layerMarker': '',
+            'layerVector': '',
+            'layerVectorType': ''
+          }
+          this.$message.success('修改成功!')
+          this.dragstartMarker = undefined
+          // this.getLayers()
+        })
+      } else {
+        // 新增
+        addApi({
+          'jobactivityTitle': this.layer.options.icon.options.name,
+          'jobactQywzjd': this.layer._latlng.lng,
+          'jobactQywzwd': this.layer._latlng.lat,
+          'veditId': this.veditId,
+          'typeId': this.layer.options.icon.options.typeId
+        }).then(() => {
+          this.type = 1
+          this.checkItemIndex = -1
+          this.state = 2
+          this.saveForm = {
+            'icon': '',
+            'name': '',
+            'goaflayerId': '',
+            'ocId': '',
+            'goafId': '',
+            'goafName': '',
+            'mapId': '',
+            'layerId': '',
+            'layerCatId': '',
+            'layerTitle': '',
+            'layerMarker': '',
+            'layerVector': '',
+            'layerVectorType': ''
+          }
+          this.$message.success('新增成功!')
+          // this.getLayers()
+        })
+      }
+    },
+    cancel() {
+      this.state = 2
+      this.checkItemIndex = -1
+      this.saveForm.icon = ''
+      this.saveForm.name = ''
+      if (this.type === 'drage') {
+        this.type = 1
+        this.dragstartMarker.marker.setLatLng(this.dragstartMarker._latlng)
+        this.dragstartMarker.marker.dragging.disable()
+        this.dragstartMarker = undefined
+        return
+      }
+      if (this.layer && this.layer._leaflet_id && this.map._layers[this.layer._leaflet_id]) {
+        this.map.removeLayer(this.map._layers[this.layer._leaflet_id])
+      }
+    },
+    delMarker() {
+      delApi(this.veditId).then(() => {
+        this.type = 1
+        this.state = 2
+        this.checkItemIndex = -1
+        this.deleteForm = {
+          'icon': '',
+          'name': '',
+          'goaflayerId': '',
+          'ocId': '',
+          'goafId': '',
+          'goafName': '',
+          'mapId': '',
+          'layerId': '',
+          'layerCatId': '',
+          'layerTitle': '',
+          'layerMarker': '',
+          'layerVector': '',
+          'layerVectorType': ''
+        }
+        if (this.map._layers[this.markerId]) {
+          this.map.removeLayer(this.map._layers[this.markerId])
+        }
+        this.$message.success('删除成功!')
+        // this.getLayers()
+      })
+    }
+
+  }
+}
+</script>
+    <style lang="scss" scoped>
+    .map-container{
+        padding: 15px;
+        nav{
+            height: 60px;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 10px 16px;
+            box-sizing: border-box;
+            background-color: #193142;
+            .page-title {
+                font-size: 18px;
+                font-weight: bold;
+                color: #FFFFFF;
+                font-weight: bold;
+            }
+        }
+        .layout-map{
+            display: flex;
+            justify-content: space-between;
+            height: calc(100vh - 160px);
+            margin-top: 10px;
+            .left-side{
+                min-width: 266px;
+                height: 100%;
+                overflow-y: auto;
+                background-color: #193142;
+                box-sizing: border-box;
+                .title{
+                    height: 42px;
+                    line-height: 42px;
+                    background-color: #36556b;
+                    font-size: 16px;
+                    color: #666;
+                    text-indent: 10px;
+                    color: #fff;
+                }
+                .item{
+                    display: flex;
+                    align-items: center;
+                    height: 48px;
+                    padding-left: 10px;
+                    cursor: default;
+                    &.active{
+                        background-color: rgba(45, 140, 240, 0.16);
+                    }
+                    .icon{
+                        width: 30px;
+                        display: block;
+                    }
+                    .name{
+                        font-size: 14px;
+                        padding-left: 12px;
+                        color: #fff;
+                    }
+                }
+            }
+            #vmap {
+                height: 100%;
+                flex: 1;
+                background: #8c939d;
+                box-sizing: border-box;
+            }
+            .rightSide{
+                width: 269px;
+                height: 100%;
+                overflow-y: auto;
+                background-color: #193142;
+                box-sizing: border-box;
+                padding: 17px 16px;
+                color: #fff;
+                .title{
+                    color: #fff;
+                    font-size: 16px;
+                    margin-bottom: 16px;
+                }
+                .remark{
+                    ul,li{
+                        list-style: none;
+                        margin: 0;
+                        padding: 0;
+                    }
+                    li{
+                        color: rgba(255, 255, 255, 0.7);
+                        line-height: 28px;
+                        font-size: 14px;
+                        margin-bottom: 8px;
+                    }
+                }
+                .saveForm,.deleteForm{
+                    .item{
+                        height: 48px;
+                        display: flex;
+                        justify-content: flex-start;
+                        align-items: center;
+                        font-size: 14px;
+                        border-bottom:2px solid rgba(45, 140, 240, 0.16);
+                        .lable{
+                        width: 80px;
+                        font-size: 14px;
+                        }
+                        .content{
+                        display: flex;
+                        justify-content: flex-start;
+                        align-items: center;
+                        overflow: hidden;
+                        text-overflow: ellipsis;
+                        .icon{
+                            width: 17.5px;
+                            display: block;
+                            margin-right:8px;
+                        }
+                        }
+                    }
+                }
+                .bt-wrap{
+                    margin-top: 65px;
+                    .bt{
+                        width: 100px;
+                        height: 36px;
+                        color: #fff;
+                        font-size: 14px;
+                        line-height: 36px;
+                        text-align: center;
+                        background-color: rgba(24, 144, 255, 0.3);
+                        display: inline-block;
+                        cursor: pointer;
+                        user-select: none;
+                    -moz-user-select: none;
+                    -webkit-user-select: none;
+                    -ms-user-select: none;
+                        &.save{
+                        background-color: #1890ff;
+                        }
+                        &.delete{
+                        background-color: #f97647;
+                        }
+                        &.margin{
+                            margin-left: 12px;
+                        }
+                    }
+                }
+
+            }
+        }
+
+    }
+    </style>
+

+ 16 - 0
src/views/goaf/map/index.vue

@@ -0,0 +1,16 @@
+<template>
+  <VisualEditor />
+</template>
+<script>
+import VisualEditor from './components/VisualEditor'
+export default {
+  components: {
+    VisualEditor
+  },
+  data() {
+    return {
+
+    }
+  }
+}
+</script>

+ 145 - 0
src/views/goaf/sensor/Model.vue

@@ -0,0 +1,145 @@
+<template>
+  <el-drawer
+    :title="title"
+    :modal-append-to-body="false"
+    :modal="false"
+    :wrapper-closable="false"
+    size="36%"
+    :visible.sync="dialogVisible"
+  >
+    <el-form ref="ruleForm" :model="formData" :rules="rules" label-position="right" label-width="160px">
+      <el-form-item label="传感器类型">
+        <el-select v-model="formData.sensorTypeId" style="width:200px">
+          <el-option v-for="item in sensors" :key="item.id" :value="item.id" :label="item.name" />
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <div class="btn-group">
+      <el-button type="primary" @click="submitForm('ruleForm')">确定</el-button>
+      <el-button class="cancel-btn" @click="dialogVisible = false">取消</el-button>
+    </div>
+  </el-drawer>
+</template>
+
+<script>
+import { createHazardRisk, updateHazardRisk } from '@/api/aqpt/hazardRiskApi'
+export default {
+  data() {
+    return {
+      title: '传感器配置',
+      ops: {
+        bar: {
+          keepShow: false,
+          background: 'rgba(144, 147, 153, 0.4)',
+          onlyShowBarOnScroll: false
+        }
+      },
+      dialogVisible: false,
+      sensors: [
+        { id: 1, name: '摄像头' },
+        { id: 2, name: '压力传感器' },
+        { id: 3, name: '位移传感器' },
+        { id: 4, name: '气体传感器' }
+      ],
+      formData: {
+        'sensorTypeId': '',
+        'ocId': '',
+        'sensorType': '',
+        'sensorTypeName': ''
+      },
+      rules: {
+      },
+      ctrlLevelList: [],
+      positionList: [],
+      viewData: {},
+      actionType: ''
+    }
+  },
+  mounted() {
+  },
+  methods: {
+
+    // Show Add Dialog
+    showAddModel(hazardId, hazardTitle) {
+      this.resetFormData()
+      this.actionType = 'ADD'
+      this.title = '新增传感器配置'
+      this.dialogVisible = true
+    },
+
+    // Show Edit Dialog
+    showEditModel(data) {
+      this.resetFormData()
+      this.formData = data
+      this.actionType = 'UPDATE'
+      this.title = '修改传感器配置'
+      this.dialogVisible = true
+    },
+
+    // Reset Form Data
+    resetFormData() {
+      this.formData = {
+        'sensorTypeId': '',
+        'ocId': '',
+        'sensorType': '',
+        'sensorTypeName': ''
+      }
+    },
+
+    // 提交
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.formData.sensorTypeName = this.sensors.filter(item => item.id === this.formData.sensorTypeId)[0].name
+          switch (this.actionType) {
+            case 'ADD':
+              createHazardRisk(this.formData).then((resp) => {
+                const { code, msg } = resp
+                if (code === 0) {
+                  this.dialogVisible = false
+                  this.$message.success(msg)
+                  this.formSuccess()
+                } else {
+                  this.$message.error(msg)
+                }
+              }).catch((error) => {
+                console.log(error)
+              })
+              break
+
+            case 'UPDATE':
+              updateHazardRisk(this.formData).then((resp) => {
+                const { code, msg } = resp
+                if (code === 0) {
+                  this.dialogVisible = false
+                  this.$message.success(msg)
+                  this.formSuccess()
+                } else {
+                  this.$message.error(msg)
+                }
+              }).catch((error) => {
+                console.log(error)
+              })
+              break
+          }
+        } else {
+          this.$message.error('error submit!!')
+          return false
+        }
+      })
+    },
+    formSuccess() {
+      this.$emit('formSuccess')
+    },
+    resetFormField(formName) {
+      this.$refs[formName].resetFields()
+    }
+  }
+}
+</script>
+<style scoped>
+.btn-group{
+  padding-left: 160px;
+  margin-top: 50px;
+}
+</style>

+ 122 - 0
src/views/goaf/sensor/index.vue

@@ -0,0 +1,122 @@
+<template>
+  <div class="content-container sensor">
+    <el-row class="tool-bar">
+      <el-col :span="12" class="left">
+        <div class="content-title">
+          传感器配置
+        </div>
+      </el-col>
+      <el-col :span="12" class="right">
+        <el-input v-model="conditions.data.sensorName" class="search-input m-right-15" placeholder="请输入传感器类型名称">
+          <el-button slot="append" icon="el-icon-search" @click="getData()" />
+        </el-input>
+        <el-button type="primary" @click="handleAdd">新增</el-button>
+      </el-col>
+    </el-row>
+
+    <el-row class="m-top-15">
+      <el-table v-loading="listLoading" class="page-table" border fit :data="dataList">
+        <el-table-column type="index" label="序号" header-align="center" align="center" width="60" />
+        <el-table-column prop="sensorTypeName" label="传感器类型名称" />
+        <el-table-column label="操作" header-align="center" align="center" width="170">
+          <template v-slot="{row}">
+            <el-button size="mini" type="primary" icon="el-icon-edit" @click="handleUpdate(row)">修改</el-button>
+            <el-button size="mini" type="danger" icon="el-icon-edit" @click="handleDelete(row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination-container" style="float:right;margin-right:40px;">
+        <pagination v-show="total>0" :total="total" :page.sync="conditions.page" :limit.sync="conditions.limit" @pagination="getData" />
+      </div>
+    </el-row>
+    <sensor-Model ref="sensor" @formSuccess="getData" />
+  </div>
+</template>
+
+<script>
+import { getHazardRiskByPage, deleteHazardRiskById } from '@/api/aqpt/hazardRiskApi'
+import { Pagination } from '@/components'
+import sensorModel from './Model'
+export default {
+  components: { Pagination, sensorModel },
+  data() {
+    return {
+      dataList: [],
+      total: 0,
+      listLoading: false,
+      conditions: {
+        page: 1,
+        limit: 10,
+        data: {
+          sensorTypeName: ''
+        }
+      }
+    }
+  },
+  created() {
+    const items = []
+    const item = {
+      'sensorTypeId': 1,
+      'ocId': 447,
+      'sensorType': 458,
+      'sensorTypeName': 'rocky.bechtelar'
+    }
+    for (let i = 0; i < 10; i++) {
+      items.push(item)
+    }
+    this.dataList = items
+    this.total = 20
+  },
+  methods: {
+    // fetch data
+    getData() {
+      this.listLoading = true
+      getHazardRiskByPage(this.conditions).then((resp) => {
+        this.listLoading = false
+        const { code, msg, data, total } = resp
+        if (code === 0) {
+          this.dataList = data
+          this.total = total
+        } else {
+          this.$message.error(msg)
+        }
+      }).catch((error) => {
+        console.log(error)
+      })
+    },
+    // "Add Risk" Model
+    handleAdd() {
+      this.$refs['sensor'].showAddModel()
+    },
+
+    // "Edit Risk" Model
+    handleUpdate(data) {
+      this.$refs['sensor'].showEditModel(JSON.parse(JSON.stringify(data)))
+    },
+
+    // Delete Action
+    handleDelete(data) {
+      const { hazardId, riskId, riskSource } = data
+      this.$confirm(`此操作将删除该数据${riskSource}, 是否继续?`, '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        deleteHazardRiskById(hazardId, riskId).then((resp) => {
+          const { code, msg } = resp
+          if (code === 0) {
+            this.getData()
+            this.$message.success(msg)
+          } else {
+            this.$message.error(msg)
+          }
+        }).catch((error) => {
+          console.log(error)
+        })
+      }).catch(() => {
+        this.$message.info('已取消删除')
+      })
+    }
+  }
+}
+</script>