CzRger 1 年間 前
コミット
41efbbbcbb
共有4 個のファイルを変更した711 個の追加437 個の削除を含む
  1. 187 15
      src/store/modules/gis.ts
  2. 8 422
      src/views/gis/layout/index.vue
  3. 439 0
      src/views/gis/map-info/overlay/qy/index.vue
  4. 77 0
      src/views/gis/map-info/overlay/qy/v2-table.vue

+ 187 - 15
src/store/modules/gis.ts

@@ -3,7 +3,9 @@ import * as layer from "ol/layer";
 import * as style from "ol/style";
 import * as ol from "ol";
 import * as format from "ol/format";
+import * as geom from 'ol/geom'
 import CommonStyle from "@/views/gis/map-info/style/common";
+import QyStyle from "@/views/gis/map-info/style/qy";
 import SbStyle from "@/views/gis/map-info/style/sb";
 import JqStyle from "@/views/gis/map-info/style/jq";
 import LgStyle from "@/views/gis/map-info/style/lg";
@@ -11,6 +13,8 @@ import CzwStyle from "@/views/gis/map-info/style/czw";
 import HczStyle from "@/views/gis/map-info/style/hcz";
 import store from "@/store";
 import axios from "axios";
+import {geometry} from "@turf/turf";
+import {formatPosition} from "@/utils/easyMap";
 
 const state = {
   menuRootName: '9cd5fbf9-35fd-4fb2-8c24-1f871afd67be',
@@ -30,6 +34,17 @@ const state = {
       feature: null,
       type: '',
       info: {}
+    },
+    qy: {
+      layer: null,
+      source: null,
+      overlay: null,
+      feature: null,
+      type: '',
+      info: {},
+      analysisLayer: null,
+      analysisSource: null,
+      analysisCircle: null,
     }
   },
   element: {
@@ -78,7 +93,9 @@ const state = {
       // },
     ],
     layer: null,
-  }
+  },
+  l: null,
+  s: null
 }
 
 const getters = {
@@ -95,8 +112,9 @@ const mutations = {
     const { show, name = null, code = null } = data
     state.videoParams = { show, name, code }
   },
-  SET_GIS_MAP(state, {map, defaultDom}) {
+  SET_GIS_MAP(state, {map, defaultDom, qyDom}) {
     state.map = map
+    // 基本要素
     state.gisParams.default.source = new source.Vector()
     state.gisParams.default.layer = new layer.Vector({
       zIndex: 200,
@@ -116,6 +134,130 @@ const mutations = {
       }
     })
     state.map.addOverlay(state.gisParams.default.overlay)
+    // 企业要素
+    state.gisParams.qy.source = new source.Vector()
+    state.gisParams.qy.layer = new layer.Vector({
+      zIndex: 202,
+      source: state.gisParams.qy.source,
+    })
+    state.gisParams.qy.layer.set('layerName', 'gisQy')
+    state.map.addLayer(state.gisParams.qy.layer)
+    state.gisParams.qy.overlay = new ol.Overlay({
+      id: 'gisQyDom',
+      element: qyDom.ref_dom,
+      autoPan: false,
+      offset: [0, -60],
+      positioning: 'bottom-center',
+      stopEvent: true,
+      autoPanAnimation: {
+        duration: 250
+      }
+    })
+    state.map.addOverlay(state.gisParams.qy.overlay)
+    // 企业-周边设备
+    state.gisParams.qy.analysisSource = new source.Vector()
+    state.gisParams.qy.analysisLayer = new layer.Vector({
+      zIndex: 202,
+      source: state.gisParams.qy.analysisSource,
+      style: [
+        new style.Style({
+          stroke: new style.Stroke({
+            color: '#2860F1',
+            width: 2,
+            lineDash: [10, 10]
+          }),
+          fill: new style.Fill({
+            color: 'rgba(20, 129, 241, 0.1)',
+          }),
+        })
+      ]
+    });
+    state.gisParams.qy.analysisCircle = new ol.Feature()
+    state.map.addLayer(state.gisParams.qy.analysisLayer)
+
+
+    // mock
+    state.s = new source.Vector()
+    state.l = new layer.Vector({
+      zIndex: 9999,
+      source: state.s,
+      style: [
+        new style.Style({
+          stroke: new style.Stroke({
+            color: '#000000',
+            width: 2,
+            lineDash: [10, 10]
+          }),
+          fill: new style.Fill({
+            color: 'rgba(20, 129, 241, 0.1)',
+          }),
+        })
+      ]
+    });
+    state.map.addLayer(state.l)
+  },
+  SET_GIS_PARAMS_QY(state, {wkt, id, info, config = {}}: any) {
+    const {
+      isAnalysis = false
+    } = config
+    if (state.gisParams.qy.layer) {
+      state.gisParams.qy.source?.clear()
+      try {
+        const newFeat: any = new format.WKT().readFeature(wkt)
+        const obj = {
+          coordinates: newFeat.getGeometry().getCoordinates(),
+          tab: '1',
+          name: info.name,
+          1: {
+            name: info.name,
+            people: info.lerep,
+            number: info.uniscid,
+            address: info.dom
+          },
+          2: {},
+          3: {},
+          4: {},
+          5: {
+            radius: 10,
+            center: newFeat.getGeometry().getCoordinates(),
+            tableData: [],
+            loading: false,
+            radiusTips: false
+          },
+        }
+        state.gisParams.qy.type = 'qy'
+        state.gisParams.qy.info = JSON.parse(JSON.stringify(obj))
+        let type
+        if (info.typeValue === 'lgszyjkscsb') {
+          type = 'lgszyjkscsb'
+        } else if (info.typeValue === 'jgzzmgs') {
+          type = 'jgzzmgs'
+        } else if (info.typeValue === 'lgsjkfzl') {
+          type = 'lgsjkyfl'
+        }
+        newFeat.set('defaultStyle', QyStyle.qyStyle(type))
+        newFeat.set('activeStyle', [...CommonStyle.activeStyle(), ...QyStyle.qyStyle(type)])
+        newFeat.set('analysisStyle', [...CommonStyle.analysisStyle(), ...QyStyle.qyStyle(type)])
+        newFeat.set('analysisActiveStyle', [...CommonStyle.activeStyle(), ...CommonStyle.analysisStyle(), ...QyStyle.qyStyle(type)])
+        newFeat.set('isAnalysis', isAnalysis)
+        newFeat.set('resetStyle', () => {
+          if (newFeat.get('isAnalysis')) {
+            newFeat.setStyle(newFeat.get('analysisStyle'))
+          } else {
+            newFeat.setStyle(newFeat.get('defaultStyle'))
+          }
+        })
+        newFeat.get('resetStyle')()
+        newFeat.set('featureType', JSON.parse(JSON.stringify(state.gisParams.qy.type)))
+        newFeat.set('info', JSON.parse(JSON.stringify(state.gisParams.qy.info)))
+        newFeat.set('apiData', JSON.parse(JSON.stringify(info)))
+        newFeat.setId(id)
+        state.gisParams.qy.source.addFeature(newFeat)
+        state.gisParams.qy.overlay.setPosition(newFeat.getGeometry().getCoordinates())
+      } catch (e) {
+        console.log('异常数据:', wkt, info, e)
+      }
+    }
   },
   SET_GIS_PARAMS_DEFAULT_SB(state, {wkt, id, info, config}) {
     const {
@@ -150,6 +292,7 @@ const mutations = {
         newFeat.get('resetStyle')()
         newFeat.set('featureType', JSON.parse(JSON.stringify(state.gisParams.default.type)))
         newFeat.set('info', JSON.parse(JSON.stringify(state.gisParams.default.info)))
+        newFeat.set('apiData', JSON.parse(JSON.stringify(info)))
         newFeat.setId(id)
         state.gisParams.default.source.addFeature(newFeat)
         state.gisParams.default.overlay.setPosition(newFeat.getGeometry().getCoordinates())
@@ -183,6 +326,7 @@ const mutations = {
         newFeat.get('resetStyle')()
         newFeat.set('featureType', JSON.parse(JSON.stringify(state.gisParams.default.type)))
         newFeat.set('info', JSON.parse(JSON.stringify(state.gisParams.default.info)))
+        newFeat.set('apiData', JSON.parse(JSON.stringify(info)))
         newFeat.setId(id)
         state.gisParams.default.source.addFeature(newFeat)
         state.gisParams.default.overlay.setPosition(newFeat.getGeometry().getCoordinates())
@@ -216,6 +360,7 @@ const mutations = {
         newFeat.get('resetStyle')()
         newFeat.set('featureType', JSON.parse(JSON.stringify(state.gisParams.default.type)))
         newFeat.set('info', JSON.parse(JSON.stringify(state.gisParams.default.info)))
+        newFeat.set('apiData', JSON.parse(JSON.stringify(info)))
         newFeat.setId(id)
         state.gisParams.default.source.addFeature(newFeat)
         state.gisParams.default.overlay.setPosition(newFeat.getGeometry().getCoordinates())
@@ -249,6 +394,7 @@ const mutations = {
         newFeat.get('resetStyle')()
         newFeat.set('featureType', JSON.parse(JSON.stringify(state.gisParams.default.type)))
         newFeat.set('info', JSON.parse(JSON.stringify(state.gisParams.default.info)))
+        newFeat.set('apiData', JSON.parse(JSON.stringify(info)))
         newFeat.setId(id)
         state.gisParams.default.source.addFeature(newFeat)
         state.gisParams.default.overlay.setPosition(newFeat.getGeometry().getCoordinates())
@@ -282,6 +428,7 @@ const mutations = {
         newFeat.get('resetStyle')()
         newFeat.set('featureType', JSON.parse(JSON.stringify(state.gisParams.default.type)))
         newFeat.set('info', JSON.parse(JSON.stringify(state.gisParams.default.info)))
+        newFeat.set('apiData', JSON.parse(JSON.stringify(info)))
         newFeat.setId(id)
         state.gisParams.default.source.addFeature(newFeat)
         state.gisParams.default.overlay.setPosition(newFeat.getGeometry().getCoordinates())
@@ -299,7 +446,7 @@ const mutations = {
     }
   },
   SET_GIS_ELEMENT(state) {
-    const arr = []
+    const arr: any = []
     state.element.list.forEach(p => {
       if (p.children?.length > 0) {
         p.children.forEach(s => {
@@ -321,7 +468,7 @@ const mutations = {
         'VERSION': '1.1.1',
         "exceptions": 'application/vnd.ogc.se_inimage',
         refresh: new Date().getTime(),
-        LAYERS: 'mysqlGeo:socialManagementEement',
+        LAYERS: 'mysqlGeo:socialManagementElement',
         CQL_FILTER: cql
       }
     })
@@ -334,26 +481,51 @@ const mutations = {
       state.map.on('singleclick', e => {
         if (state.element.list.some(v => v.active)) {
           let isFeature = false
-          e.map.forEachFeatureAtPixel(e.pixel, (feature) => {
-            console.log(feature)
-            isFeature = true
-          }, {
-            hitTolerance: 0,
-          });
-          axios.get(`/${store.state.app.apiProxy.geoserverApi}/geoserver/rest/layers`)
+          // e.map.forEachFeatureAtPixel(e.pixel, (feature) => {
+          //   console.log(feature)
+          //   isFeature = true
+          // }, {
+          //   hitTolerance: 0,
+          // });
           if (!isFeature) {
             const viewResolution = e.map.getView().getResolution()
+            console.log(viewResolution)
             const url = state.element.layer.getSource().getFeatureInfoUrl(e.coordinate, viewResolution, 'EPSG:4326', {
               'INFO_FORMAT': 'application/json',
               'FEATURE_COUNT': 10000
             })
+            console.log(url)
+            const BBOX = decodeURIComponent(url.split('?')[1].split('&').filter(v => v.includes('BBOX'))[0].split('=')[1]).split(',')
+            const wkt = [
+                [BBOX[0], BBOX[3]],
+                [BBOX[2], BBOX[3]],
+                [BBOX[2], BBOX[1]],
+                [BBOX[0], BBOX[1]],
+                [BBOX[0], BBOX[3]],
+            ]
+
+            const f = new format.WKT().readFeature(formatPosition.cpnTwpn([wkt]))
+
+            state.s.clear()
+            state.s.addFeature(f)
+
+            console.log(BBOX)
             if (url) {
               axios.get(url).then(res => {
                 if (res.status === 200) {
-                  console.log(res.data.features.length)
                   const item = res.data?.features?.[res.data?.features?.length - 1]
-                  console.log(item)
                   if (item) {
+                    console.log(item)
+                    if (['lgszyjkscsb', 'jgzzmgs', 'lgsjkfzl'].includes(item.properties.typeValue)) {
+                      console.log('企业')
+                      store.commit('gis/SET_GIS_PARAMS_QY', {
+                        wkt: `POINT(${item.geometry.coordinates.join(' ')})`,
+                        id: item.properties.id,
+                        info: item.properties
+                      })
+                    } else if (['gal', 'shl', 'myl'].includes(item.properties.typeValue)) {
+                      console.log('设备')
+                    }
                   }
                 }
               })
@@ -371,9 +543,9 @@ const actions = {
   LOAD_ACTIVE_QY_ID({ commit }: any, id: any) {
     commit('SET_ACTIVE_QY_ID', id)
   },
-  LOAD_GIS_MAP({ commit }: any, {map, defaultDom}: any) {
+  LOAD_GIS_MAP({ commit }: any, {map, defaultDom, qyDom}: any) {
     if (!state.map) {
-      commit('SET_GIS_MAP', {map, defaultDom})
+      commit('SET_GIS_MAP', {map, defaultDom, qyDom})
     }
   },
   LOAD_GIS_PARAMS_DEFAULT({ commit }: any, {type, wkt, id, info, config = {}}: any) {

+ 8 - 422
src/views/gis/layout/index.vue

@@ -61,99 +61,8 @@
       <el-button @click="mockHCZ1">模拟火车站1</el-button>
     </div>
   </div>
-
-  <div ref="ref_qyDom" class="qy-info" :class="`qy--info-${qyParams.qyInfo.tab}`">
-    <div class="qy-bg-icon qy-bg-icon-1"/>
-    <div class="qy-bg-icon qy-bg-icon-2"/>
-    <div class="qy-bg-icon qy-bg-icon-3"/>
-    <div class="qy-bg-icon qy-bg-icon-4"/>
-    <div class="qy-main">
-      <div class="qy-main-head">
-        <div class="qy-main-head-tips">【企业】</div>
-        <div class="qy-main-head-name">{{ qyParams.qyInfo.name }}</div>
-        <SvgIcon class="__hover" name="close_4" size="14" color="#8FFFFF" @click="onCloseQy"/>
-      </div>
-      <div class="qy-main-tab">
-        <template v-for="item in [
-              {label: '基本信息', value: '1', disabled: false},
-              {label: '税收信息', value: '2', disabled: true},
-              {label: '运输车辆', value: '3', disabled: true},
-              {label: '能耗消息', value: '4', disabled: true},
-              {label: '周边设备', value: '5', disabled: false},
-          ]">
-          <div class="qy-main-tab-item __hover" :class="{active: item.value === qyParams.qyInfo.tab, disabled: item.disabled}" @click="item.disabled ? undefined : qyParams.qyInfo.tab = item.value">{{item.label}}</div>
-        </template>
-      </div>
-      <div v-if="qyParams.qyInfo.tab === '1'" class="qy-main-content-1">
-        <div>企业名称:{{qyParams.qyInfo[qyParams.qyInfo.tab].name}}</div>
-        <div>企业法人:{{qyParams.qyInfo[qyParams.qyInfo.tab].people}}</div>
-        <div>统一社会信用代码:{{qyParams.qyInfo[qyParams.qyInfo.tab].number}}</div>
-        <div>经营地址:{{qyParams.qyInfo[qyParams.qyInfo.tab].address}}</div>
-      </div>
-      <div v-else-if="qyParams.qyInfo.tab === '5'" class="qy-main-content-5">
-        <div class="qy-main-content-5-radius">
-          周边范围:
-          <div class="radius-min __hover" @click="qyParams.qyInfo[qyParams.qyInfo.tab].radius > 1 ? (qyParams.qyInfo[qyParams.qyInfo.tab].radius--, handleRangeInput(qyParams.qyInfo[qyParams.qyInfo.tab].radius)) : undefined">-</div>
-          <CusFormColumn
-              link="number"
-              label=""
-              :clearable="false"
-              v-model:param="qyParams.qyInfo[qyParams.qyInfo.tab].radius"
-              @input="handleRangeInput"
-              @blur="handleRangeBlur"/>
-          <div class="radius-max __hover" @click="qyParams.qyInfo[qyParams.qyInfo.tab].radius < 60 ? (qyParams.qyInfo[qyParams.qyInfo.tab].radius++, handleRangeInput(qyParams.qyInfo[qyParams.qyInfo.tab].radius)) : undefined">+</div>
-          km
-          <div class="submit __hover" :style="`cursor: ${qyParams.qyInfo[qyParams.qyInfo.tab].radiusTips ? 'not-allowed' : ''};`" @click="onRadiusSubmit">确定</div>
-          <div class="reset __hover" @click="onRadiusReset">重置</div>
-          <div class="tips" v-if="qyParams.qyInfo[qyParams.qyInfo.tab].radiusTips"><SvgIcon name="tips" size="16" color="#FFB878"/>请输入1~60的正整数!</div>
-        </div>
-        <div class="qy-main-content-5-table" :style="`height: ${25 + (qyParams.qyInfo[qyParams.qyInfo.tab].tableData.length > 5 ? 5 * 25 : qyParams.qyInfo[qyParams.qyInfo.tab].tableData.length * 25)}px;`" v-loading="qyParams.qyInfo[qyParams.qyInfo.tab].loading" element-loading-background="rgba(0, 0, 0, 0.3)">
-          <el-auto-resizer>
-            <template #default="{ height, width }">
-              <V2Table
-                  :width="width"
-                  :height="height"
-                  :data="qyParams.qyInfo[qyParams.qyInfo.tab].tableData"
-                  :center="qyParams.qyInfo.coordinates"
-              />
-              <!--                <el-table-v2-->
-              <!--                    class="__gis-overlay_table-v2"-->
-              <!--                    :columns="qyParams.qyInfo[qyParams.qyInfo.tab].tableHead"-->
-              <!--                    :data="qyParams.qyInfo[qyParams.qyInfo.tab].tableData"-->
-              <!--                    :width="width"-->
-              <!--                    :height="height"-->
-              <!--                    fixed-->
-              <!--                    :row-height="25"-->
-              <!--                    :header-height="25"-->
-              <!--                >-->
-              <!--                  <template #empty></template>-->
-              <!--                </el-table-v2>-->
-            </template>
-          </el-auto-resizer>
-        </div>
-      </div>
-    </div>
-  </div>
-  <div ref="ref_sbDom" class="sb-info">
-    <div class="sb-info-head">
-      <SvgIcon class="__hover" name="tips" size="14" color="#8FFFFF"/>设备
-    </div>
-    <div class="sb-info-close __hover" @click="onCloseSb">
-      <img src="@/components/easyMap/images/close.png" alt=""/>
-    </div>
-    <div class="sb-main">
-      <div class="sb-item">
-        <div class="sb-item-label">名称:</div>
-        <div class="sb-item-value">{{qyParams.sbInfo?.name}}</div>
-      </div>
-      <div class="sb-item">
-        <div class="sb-item-label">状态:</div>
-        <div class="sb-item-value">{{qyParams.sbInfo?.online == '1' ? '在线' : '离线'}}</div>
-      </div>
-      <div class="play-button __hover" @click="onPlay">视频调阅</div>
-    </div>
-  </div>
   <GisDefaultDom ref="ref_gisDefault"/>
+  <GisQyDom ref="ref_gisQy"/>
 </template>
 
 <script lang="ts">
@@ -199,6 +108,7 @@ import {deviceQuery, enterpriseQuery} from "@/api/modules/enterprise";
 import {clearLocationDom} from '@/components/easyMap/func/location'
 import {clearMeasureDom} from '@/components/easyMap/func/measure'
 import GisDefaultDom from '../map-info/overlay/default/index.vue'
+import GisQyDom from '../map-info/overlay/qy/index.vue'
 
 export default defineComponent({
   name: '',
@@ -213,7 +123,8 @@ export default defineComponent({
     ExampleCom,
     VideoPlayKedaCom,
     V2Table,
-    GisDefaultDom
+    GisDefaultDom,
+    GisQyDom,
   },
   props: {},
   setup(props, {emit}) {
@@ -264,11 +175,13 @@ export default defineComponent({
     ]
     const ref_search = ref()
     const ref_gisDefault = ref()
+    const ref_gisQy = ref()
     const mapLoad = (map, func) => {
       state.map = map
       store.dispatch('gis/LOAD_GIS_MAP', {
         map: state.map,
-        defaultDom: ref_gisDefault.value
+        defaultDom: ref_gisDefault.value,
+        qyDom: ref_gisQy.value,
       })
       state.mapFunc = func
       store.commit('gis/SET_GIS_ELEMENT')
@@ -751,6 +664,7 @@ export default defineComponent({
       onRadiusReset,
       ref_sbDom,
       ref_gisDefault,
+      ref_gisQy,
       mockSB1,
       mockSB2,
       mockJQ1,
@@ -942,334 +856,6 @@ export default defineComponent({
   .gis-content {
     z-index: 4;
   }
-  .qy-info {
-    $bgColor: #2860CE;
-    $footH: 10px;
-    min-width: 315px;
-    min-height: 168px - $footH;
-    background-color: $bgColor;
-    position: relative;
-    display: flex;
-    justify-content: center;
-    &:after {
-      content: '';
-      position: absolute;
-      bottom: -$footH;
-      border-top: $footH solid $bgColor;
-      border-left: $footH solid transparent;
-      border-right: $footH solid transparent;
-    }
-    .qy-bg-icon {
-      width: 16px;
-      height: 16px;
-      background-image: url("@/views/gis/map-info/qy-dom-icon1.png");
-      background-repeat: no-repeat;
-      background-size: 100% 100%;
-      position: absolute;
-      z-index: 1;
-      &.qy-bg-icon-1 {
-        left: 0;
-        top: 0;
-      }
-      &.qy-bg-icon-2 {
-        right: 0;
-        top: 0;
-        transform: rotate(90deg);
-      }
-      &.qy-bg-icon-3 {
-        right: 0;
-        bottom: 0;
-        transform: rotate(180deg);
-      }
-      &.qy-bg-icon-4 {
-        left: 0;
-        bottom: 0;
-        transform: rotate(270deg);
-      }
-    }
-    .qy-main {
-      width: 100%;
-      height: auto;
-      z-index: 2;
-      padding: 12px;
-      .qy-main-head {
-        display: flex;
-        align-items: center;
-        position: relative;
-        &:after {
-          content: '';
-          position: absolute;
-          width: 100%;
-          height: 4px;
-          bottom: -9px;
-          background-image: url("@/views/gis/map-info/qy-info-icon2.png");
-          background-repeat: no-repeat;
-        }
-        .qy-main-head-tips {
-          font-size: 10px;
-          font-family: Microsoft YaHei;
-          font-weight: bold;
-          color: #8FFFFF;
-        }
-        .qy-main-head-name {
-          font-size: 14px;
-          font-family: Microsoft YaHei;
-          font-weight: bold;
-          color: #FFFFFF;
-        }
-        .svg-icon {
-          margin-left: auto;
-        }
-      }
-      .qy-main-tab {
-        margin: 20px 0 10px 0;
-        display: flex;
-        align-items: center;
-        .qy-main-tab-item {
-          font-size: 12px;
-          font-family: Microsoft YaHei;
-          font-weight: 400;
-          color: #CEE6FF;
-          height: 16px;
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          padding: 0 4px;
-          border-radius: 2px;
-          background-color: rgba(255, 255, 255, 0.2);
-          &.active {
-            background-color: #1280F1;
-            color: #61FFFF;
-          }
-          &.disabled {
-            cursor: not-allowed;
-            opacity: 0.7;
-          }
-          &:not(:last-child) {
-            margin-right: 2px;
-          }
-        }
-      }
-      .qy-main-content-1 {
-        font-size: 12px;
-        font-family: Microsoft YaHei;
-        font-weight: 400;
-        color: #FFFFFF;
-        >div {
-          line-height: 18px;
-        }
-      }
-      .qy-main-content-5 {
-        .qy-main-content-5-radius {
-          display: flex;
-          align-items: center;
-          font-size: 12px;
-          font-family: Microsoft YaHei;
-          font-weight: 400;
-          color: #FFFFFF;
-          .radius-min, .radius-max {
-            margin: 0 3px;
-            &:hover {
-              color: #409EFF;
-            }
-          }
-          :deep(.cus-form-column) {
-            max-width: unset;
-            width: 44px;
-            flex: unset;
-            .el-form-item {
-              margin: 0;
-              .el-form-item__content {
-                height: 18px;
-                .el-input {
-                  .el-input__wrapper {
-                    padding: 0;
-                    border-radius: 5px;
-                    background-color: transparent;
-                    .el-input__inner {
-                      color: #FFFFFF;
-                      background-color: transparent;
-                      height: 100%;
-                      text-align: center;
-                      border: 1px solid #ffffff;
-                      border-radius: 5px;
-                      &::placeholder {
-                        font-size: 12px;
-                        font-family: Microsoft YaHei;
-                      }
-                    }
-                  }
-                }
-              }
-            }
-          }
-          .submit {
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            width: 36px;
-            height: 18px;
-            background: #8FFFFF;
-            border-radius: 4px;
-            font-size: 12px;
-            font-family: Microsoft YaHei;
-            font-weight: 400;
-            color: #1174DB;
-            margin-left: 10px;
-          }
-          .reset {
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            width: 36px;
-            height: 18px;
-            border: 1px solid #8FFFFF;
-            border-radius: 4px;
-            font-size: 12px;
-            font-family: Microsoft YaHei;
-            font-weight: 400;
-            color: #8FFFFF;
-            margin-left: 8px;
-          }
-          .tips {
-            margin-left: auto;
-            display: flex;
-            align-items: center;
-            color: #FFB878;
-            .svg-icon {
-              margin-right: 2px;
-            }
-          }
-        }
-        .qy-main-content-5-table {
-          margin-top: 10px;
-          width: 440px;
-          :deep(.__gis-overlay_table-v2) {
-            .el-table-v2__header-cell{
-              justify-content: center;
-              &:nth-child(2) {
-                color: #00C6FC;
-              }
-            }
-            .el-table-v2__header-cell, .el-table-v2__row-cell {
-              width: 60px !important;
-              $w1: 60px;
-              $w3: 60px;
-              $w4: 60px;
-              $w5: 60px;
-              &:nth-child(1) {
-                width: $w1 !important;
-              }
-              &:nth-child(2) {
-                width: calc(100% - #{$w1} - #{$w3} - #{$w4} - #{$w5} - 6px) !important;
-              }
-              &:nth-child(3) {
-                width: $w3 !important;
-              }
-              &:nth-child(4) {
-                width: $w4 !important;
-              }
-              &:nth-child(5) {
-                width: $w5 !important;
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-  .sb-info {
-    $footH: 10px;
-    width: 220px;
-    background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
-    border-radius: 0px 4px 4px 4px;
-    position: relative;
-    display: flex;
-    justify-content: center;
-    &:after {
-      content: '';
-      position: absolute;
-      bottom: -$footH;
-      border-top: $footH solid #0043C4;
-      border-left: $footH solid transparent;
-      border-right: $footH solid transparent;
-    }
-    .sb-info-head {
-      min-width: 68px;
-      height: 18px;
-      position: absolute;
-      top: -18px;
-      left: 0;
-      font-size: 12px;
-      font-family: PingFang SC;
-      font-weight: 500;
-      color: #FFFFFF;
-      display: flex;
-      align-items: center;
-      line-height: 8px;
-      &:before {
-        z-index: -1;
-        content: '';
-        position: absolute;
-        width: 100%;
-        height: 100%;
-        background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
-        border-radius: 2px 2px 0 0;/* 设置圆角 */
-        transform: perspective(20px)rotateX(4deg);
-        /* 镜头距离元素表面的位置为8px,x轴为1.1倍y轴为1.3倍,绕x轴旋转5度 */
-        transform-origin: bottom left;
-        /* bottom left = left bottom = 0 100% 中心点偏移量*/
-      }
-      .svg-icon {
-        margin: 0 4px 0 6px;
-      }
-    }
-    .sb-info-close {
-      position: absolute;
-      right: 0;
-      top: -16px;
-    }
-    .sb-main {
-      width: 100%;
-      height: auto;
-      padding: 10px;
-      .sb-item {
-        display: flex;
-        .sb-item-label {
-          width: 42px;
-          font-size: 14px;
-          font-family: PingFang SC;
-          font-weight: 600;
-          color: #08FFFF;
-          line-height: 20px;
-        }
-        .sb-item-value {
-          flex: 1;
-          font-size: 14px;
-          font-family: PingFang SC;
-          font-weight: 400;
-          color: #FFFFFF;
-          line-height: 20px;
-        }
-      }
-      .play-button {
-        width: 76px;
-        height: 24px;
-        background: #1280F1;
-        border-radius: 2px;
-        border: 1px solid #4BA0FF;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        font-size: 14px;
-        font-family: PingFang SC;
-        font-weight: 400;
-        color: #FFFFFF;
-        margin-left: calc((100% - 76px) / 2);
-        margin-top: 10px;
-      }
-    }
-  }
 }
 
 .mockButtons {

+ 439 - 0
src/views/gis/map-info/overlay/qy/index.vue

@@ -0,0 +1,439 @@
+<template>
+  <div ref="ref_dom" class="gis-overlay-qy">
+    <div class="qy-bg-icon qy-bg-icon-1"/>
+    <div class="qy-bg-icon qy-bg-icon-2"/>
+    <div class="qy-bg-icon qy-bg-icon-3"/>
+    <div class="qy-bg-icon qy-bg-icon-4"/>
+    <div class="qy-main">
+      <div class="qy-main-head">
+        <div class="qy-main-head-tips">【企业】</div>
+        <div class="qy-main-head-name">{{ qyInfoCpt.name }}</div>
+        <SvgIcon class="__hover" name="close_4" size="14" color="#8FFFFF" @click="onCloseQy"/>
+      </div>
+      <div class="qy-main-tab">
+        <template v-for="item in [
+              {label: '基本信息', value: '1', disabled: false},
+              {label: '税收信息', value: '2', disabled: true},
+              {label: '运输车辆', value: '3', disabled: true},
+              {label: '能耗消息', value: '4', disabled: true},
+              {label: '周边设备', value: '5', disabled: false},
+          ]">
+          <div class="qy-main-tab-item __hover" :class="{active: item.value === qyInfoCpt.tab, disabled: item.disabled}" @click="item.disabled ? undefined : qyInfoCpt.tab = item.value">{{item.label}}</div>
+        </template>
+      </div>
+      <div v-if="qyInfoCpt.tab === '1'" class="qy-main-content-1">
+        <div>企业名称:{{qyInfoCpt['1'].name}}</div>
+        <div>企业法人:{{qyInfoCpt['1'].people}}</div>
+        <div>统一社会信用代码:{{qyInfoCpt['1'].number}}</div>
+        <div>经营地址:{{qyInfoCpt['1'].address}}</div>
+      </div>
+      <div v-else-if="qyInfoCpt.tab === '5'" class="qy-main-content-5">
+        <div class="qy-main-content-5-radius">
+          周边范围:
+          <div class="radius-min __hover" @click="qyInfoCpt['5'].radius > 1 ? (qyInfoCpt['5'].radius--, handleRangeInput(qyInfoCpt['5'].radius)) : undefined">-</div>
+          <CusFormColumn
+              link="number"
+              label=""
+              :clearable="false"
+              v-model:param="qyInfoCpt['5'].radius"
+              @input="handleRangeInput"/>
+          <div class="radius-max __hover" @click="qyInfoCpt['5'].radius < 60 ? (qyInfoCpt['5'].radius++, handleRangeInput(qyInfoCpt['5'].radius)) : undefined">+</div>
+          km
+          <div class="submit __hover" :style="`cursor: ${qyInfoCpt['5'].radiusTips ? 'not-allowed' : ''};`" @click="onRadiusSubmit">确定</div>
+          <div class="reset __hover" @click="onRadiusReset">重置</div>
+          <div class="tips" v-if="qyInfoCpt['5'].radiusTips"><SvgIcon name="tips" size="16" color="#FFB878"/>请输入1~60的正整数!</div>
+        </div>
+        <div class="qy-main-content-5-table" :style="`height: ${25 + (qyInfoCpt['5'].tableData.length > 5 ? 5 * 25 : qyInfoCpt['5'].tableData.length * 25)}px;`" v-loading="qyInfoCpt[qyInfoCpt.tab].loading" element-loading-background="rgba(0, 0, 0, 0.3)">
+          <el-auto-resizer>
+            <template #default="{ height, width }">
+              <V2Table
+                  :width="width"
+                  :height="height"
+                  :data="qyInfoCpt['5'].tableData"
+                  :center="qyInfoCpt['5'].center"
+              />
+            </template>
+          </el-auto-resizer>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import {
+  defineComponent,
+  computed,
+  onMounted,
+  ref,
+  reactive,
+  watch,
+  getCurrentInstance,
+  ComponentInternalInstance,
+  toRefs,
+  nextTick, markRaw
+} from 'vue'
+import {useStore} from 'vuex'
+import {useRouter, useRoute} from 'vue-router'
+import {ElMessage, ElMessageBox} from "element-plus";
+import V2Table from "./v2-table.vue";
+import * as turf from "@turf/turf";
+import * as geom from "ol/geom";
+import * as source from "ol/source";
+import * as layer from "ol/layer";
+import * as style from "ol/style";
+import * as ol from "ol";
+import * as format from "ol/format";
+import SbStyle from "@/views/gis/map-info/style/sb";
+import CommonStyle from "@/views/gis/map-info/style/common";
+
+export default defineComponent({
+  name: '',
+  components: {
+    V2Table,
+  },
+  props: {},
+  setup(props, {emit}) {
+    const store = useStore();
+    const router = useRouter();
+    const route = useRoute();
+    const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
+    const state = reactive({
+      qyInfo: <any>store.state.gis.gisParams.qy.info,
+    })
+    const qyInfoCpt = computed(() => {
+      return store.state.gis.gisParams.qy.info
+    })
+    const ref_dom = ref()
+    const handleRangeInput = (v) => {
+      const nV = Number(v)
+      if (!isNaN(Number(nV))) {
+        if (nV < 1 || nV > 60) {
+          qyInfoCpt.value['5'].radiusTips = true
+        } else {
+          qyInfoCpt.value['5'].radiusTips = false
+        }
+      }
+    }
+    const setCircle = () => {
+      const circle = turf.circle(qyInfoCpt.value['5'].center, qyInfoCpt.value['5'].radius, {steps: 1024, units: 'kilometers'})
+      store.state.gis.gisParams.qy.analysisCircle.setGeometry(new geom.Polygon(circle.geometry.coordinates))
+    }
+    const onRadiusSubmit = () => {
+      if (!qyInfoCpt.value['5'].radiusTips) {
+        store.state.gis.gisParams.qy.analysisSource.clear()
+        store.state.gis.gisParams.qy.analysisSource.addFeature(store.state.gis.gisParams.qy.analysisCircle)
+        setCircle()
+        qyInfoCpt.value['5'].tableData = []
+        qyInfoCpt.value['5'].loading = true
+        that.$api.deviceQuery({
+          lon: qyInfoCpt.value['5'].center[0],
+          lat: qyInfoCpt.value['5'].center[1],
+          radius: qyInfoCpt.value['5'].radius
+        }).then((res: any) => {
+          console.log(res.datas?.length)
+          // if (res.resp_code === 0 && res.datas?.length > 0) {
+          //   console.log(res.datas?.length)
+          //   const features: any = []
+          //   res.datas?.forEach(v => {
+          //     try {
+          //       const feat: any = new format.WKT().readFeature(`POINT(${v.longitude} ${v.latitude})`)
+          //       let type = ''
+          //       if (v.type === '公安类') {
+          //         type = 'galsb'
+          //       } else if (v.type === '社会类') {
+          //         type = 'shlsb'
+          //       } else if (v.type === '民用类') {
+          //         type = 'mylsb'
+          //       }
+          //       feat.set('defaultStyle', SbStyle.sbStyle(type))
+          //       feat.set('activeStyle', [...CommonStyle.activeStyle(), ...SbStyle.sbStyle(type)])
+          //       feat.set('analysisStyle', [...CommonStyle.analysisStyle(), ...SbStyle.sbStyle(type)])
+          //       feat.set('analysisActiveStyle', [...CommonStyle.activeStyle(), ...CommonStyle.analysisStyle(), ...SbStyle.sbStyle(type)])
+          //       feat.set('isAnalysis', true)
+          //       feat.set('resetStyle', () => {
+          //         if (feat.get('isAnalysis')) {
+          //           feat.setStyle(feat.get('analysisStyle'))
+          //         } else {
+          //           feat.setStyle(feat.get('defaultStyle'))
+          //         }
+          //       })
+          //       feat.setStyle(feat.get('analysisStyle'))
+          //       feat.set('featureType', 'sb')
+          //       feat.set('info', v)
+          //       feat.setId(v.deviceid)
+          //       features.push(feat)
+          //       state.qyParams.qyInfo['5'].tableData.push(v)
+          //     } catch (e) {
+          //       console.error('异常设备', v)
+          //     }
+          //   })
+          //   state.qyParams.analysisSource.addFeatures(features)
+          // }
+          qyInfoCpt.value['5'].loading = false
+        }).catch(() => {
+          qyInfoCpt.value['5'].loading = true
+        })
+      }
+    }
+    const onRadiusReset = () => {
+      qyInfoCpt.value['5'].radius = 10
+      qyInfoCpt.value['5'].radiusTips = false
+      onRadiusSubmit()
+    }
+    const onCloseQy = () => {
+
+    }
+    onMounted(() => {
+    })
+    return {
+      ...toRefs(state),
+      ref_dom,
+      onCloseQy,
+      handleRangeInput,
+      onRadiusSubmit,
+      onRadiusReset,
+      qyInfoCpt
+    }
+  },
+})
+</script>
+
+<style scoped lang="scss">
+.gis-overlay-qy {
+  $bgColor: #2860CE;
+  $footH: 10px;
+  min-width: 315px;
+  min-height: 168px - $footH;
+  background-color: $bgColor;
+  position: relative;
+  display: flex;
+  justify-content: center;
+  &:after {
+    content: '';
+    position: absolute;
+    bottom: -$footH;
+    border-top: $footH solid $bgColor;
+    border-left: $footH solid transparent;
+    border-right: $footH solid transparent;
+  }
+  .qy-bg-icon {
+    width: 16px;
+    height: 16px;
+    background-image: url("@/views/gis/map-info/qy-dom-icon1.png");
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    position: absolute;
+    z-index: 1;
+    &.qy-bg-icon-1 {
+      left: 0;
+      top: 0;
+    }
+    &.qy-bg-icon-2 {
+      right: 0;
+      top: 0;
+      transform: rotate(90deg);
+    }
+    &.qy-bg-icon-3 {
+      right: 0;
+      bottom: 0;
+      transform: rotate(180deg);
+    }
+    &.qy-bg-icon-4 {
+      left: 0;
+      bottom: 0;
+      transform: rotate(270deg);
+    }
+  }
+  .qy-main {
+    width: 100%;
+    height: auto;
+    z-index: 2;
+    padding: 12px;
+    .qy-main-head {
+      display: flex;
+      align-items: center;
+      position: relative;
+      &:after {
+        content: '';
+        position: absolute;
+        width: 100%;
+        height: 4px;
+        bottom: -9px;
+        background-image: url("@/views/gis/map-info/qy-info-icon2.png");
+        background-repeat: no-repeat;
+      }
+      .qy-main-head-tips {
+        font-size: 10px;
+        font-family: Microsoft YaHei;
+        font-weight: bold;
+        color: #8FFFFF;
+      }
+      .qy-main-head-name {
+        font-size: 14px;
+        font-family: Microsoft YaHei;
+        font-weight: bold;
+        color: #FFFFFF;
+      }
+      .svg-icon {
+        margin-left: auto;
+      }
+    }
+    .qy-main-tab {
+      margin: 20px 0 10px 0;
+      display: flex;
+      align-items: center;
+      .qy-main-tab-item {
+        font-size: 12px;
+        font-family: Microsoft YaHei;
+        font-weight: 400;
+        color: #CEE6FF;
+        height: 16px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        padding: 0 4px;
+        border-radius: 2px;
+        background-color: rgba(255, 255, 255, 0.2);
+        &.active {
+          background-color: #1280F1;
+          color: #61FFFF;
+        }
+        &.disabled {
+          cursor: not-allowed;
+          opacity: 0.7;
+        }
+        &:not(:last-child) {
+          margin-right: 2px;
+        }
+      }
+    }
+    .qy-main-content-1 {
+      font-size: 12px;
+      font-family: Microsoft YaHei;
+      font-weight: 400;
+      color: #FFFFFF;
+      >div {
+        line-height: 18px;
+      }
+    }
+    .qy-main-content-5 {
+      .qy-main-content-5-radius {
+        display: flex;
+        align-items: center;
+        font-size: 12px;
+        font-family: Microsoft YaHei;
+        font-weight: 400;
+        color: #FFFFFF;
+        .radius-min, .radius-max {
+          margin: 0 3px;
+          &:hover {
+            color: #409EFF;
+          }
+        }
+        :deep(.cus-form-column) {
+          max-width: unset;
+          width: 44px;
+          flex: unset;
+          .el-form-item {
+            margin: 0;
+            .el-form-item__content {
+              height: 18px;
+              .el-input {
+                .el-input__wrapper {
+                  padding: 0;
+                  border-radius: 5px;
+                  background-color: transparent;
+                  .el-input__inner {
+                    color: #FFFFFF;
+                    background-color: transparent;
+                    height: 100%;
+                    text-align: center;
+                    border: 1px solid #ffffff;
+                    border-radius: 5px;
+                    &::placeholder {
+                      font-size: 12px;
+                      font-family: Microsoft YaHei;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        .submit {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          width: 36px;
+          height: 18px;
+          background: #8FFFFF;
+          border-radius: 4px;
+          font-size: 12px;
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          color: #1174DB;
+          margin-left: 10px;
+        }
+        .reset {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          width: 36px;
+          height: 18px;
+          border: 1px solid #8FFFFF;
+          border-radius: 4px;
+          font-size: 12px;
+          font-family: Microsoft YaHei;
+          font-weight: 400;
+          color: #8FFFFF;
+          margin-left: 8px;
+        }
+        .tips {
+          margin-left: auto;
+          display: flex;
+          align-items: center;
+          color: #FFB878;
+          .svg-icon {
+            margin-right: 2px;
+          }
+        }
+      }
+      .qy-main-content-5-table {
+        margin-top: 10px;
+        width: 440px;
+        :deep(.__gis-overlay_table-v2) {
+          .el-table-v2__header-cell{
+            justify-content: center;
+            &:nth-child(2) {
+              color: #00C6FC;
+            }
+          }
+          .el-table-v2__header-cell, .el-table-v2__row-cell {
+            width: 60px !important;
+            $w1: 60px;
+            $w3: 60px;
+            $w4: 60px;
+            $w5: 60px;
+            &:nth-child(1) {
+              width: $w1 !important;
+            }
+            &:nth-child(2) {
+              width: calc(100% - #{$w1} - #{$w3} - #{$w4} - #{$w5} - 6px) !important;
+            }
+            &:nth-child(3) {
+              width: $w3 !important;
+            }
+            &:nth-child(4) {
+              width: $w4 !important;
+            }
+            &:nth-child(5) {
+              width: $w5 !important;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 77 - 0
src/views/gis/map-info/overlay/qy/v2-table.vue

@@ -0,0 +1,77 @@
+<template>
+  <el-table-v2
+      class="__gis-overlay_table-v2"
+      :columns="columns"
+      :data="data"
+      :width="width"
+      :height="height"
+      fixed
+      :row-height="25"
+      :header-height="25"
+  >
+    <template #empty></template>
+  </el-table-v2>
+</template>
+
+<script lang="tsx">
+import {
+  defineComponent,
+  computed,
+  onMounted,
+  ref,
+  reactive,
+  watch,
+  getCurrentInstance,
+  ComponentInternalInstance,
+  toRefs,
+  nextTick
+} from 'vue'
+import {useStore} from 'vuex'
+import {useRouter, useRoute} from 'vue-router'
+import {ElMessage, ElMessageBox} from "element-plus";
+import * as turf from "@turf/turf";
+
+export default defineComponent({
+  name: '',
+  components: {},
+  props: {
+    head: {},
+    data: {},
+    width: {},
+    height: {},
+    center: {}
+  },
+  setup(props, {emit}) {
+    const store = useStore();
+    const router = useRouter();
+    const route = useRoute();
+    const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
+    const state = reactive({
+    })
+    const columns = [
+      {width: 1, title: '序号', align: 'center', cellRenderer: ({ rowIndex }) => `${rowIndex + 1}`},
+      {width: 1, title: '名称', dataKey: 'name'},
+      {width: 1, title: '状态', align: 'center', cellRenderer: ({rowData}) => (
+          <span style={rowData.online == '1' ? "color: #4CFFFF;" : ""}>{rowData.online === '1' ? '在线' : '离线'}</span>
+        )},
+      {width: 1, title: '类型', align: 'center', dataKey: 'type'},
+      {width: 1, title: '距离', align: 'right', cellRenderer: ({rowData}) => {
+          // const start = props.feat.getGeometry().getCoordinates()
+          // const end = that.$easyMap.formatPosition.wptTcpt(rowData.wkt)
+          const end = [Number(rowData.longitude), Number(rowData.latitude)]
+          return turf.distance(props.center, end, {units: 'kilometers'}).toFixed(2) + 'km';
+        }
+      },
+    ]
+    onMounted(() => {
+    })
+    return {
+      ...toRefs(state),
+      columns
+    }
+  },
+})
+</script>
+
+<style scoped lang="scss">
+</style>