Browse Source

添加地图显示

xiaohaizhao 6 months ago
parent
commit
8f569fab7b

+ 268 - 210
src/operation/moduleNormal/IoTdashboard/index.vue

@@ -13,16 +13,27 @@
         </a-col>
       </a-row>
     </div>
-    <div class="content" style="--zIndex:999">
+    <div class="content" style="--zIndex: 999">
       <!--顶部搜索已经其他操作-->
       <div class="header-control">
         <div class="left">
-          <a-button style="margin:8px 22px" type="primary" size="small" round @click="model=false" v-if="model==true">切换列表</a-button>
+          <a-button
+            style="margin: 8px 22px"
+            type="primary"
+            size="small"
+            round
+            @click="model = false"
+            v-if="model == true"
+            >切换列表</a-button
+          >
           <!-- <a-input v-if="model" placeholder="区域" v-model:value="param.content.where.areaname" @keyup.enter="listData"></a-input> -->
         </div>
       </div>
       <!--地图-->
-      <div class="M-map" :style="model ? 'display:inline-block' : 'display:none'">
+      <div
+        class="M-map"
+        :style="model ? 'display:inline-block' : 'display:none'"
+      >
         <baidu-map
           class="map"
           ref="map"
@@ -31,39 +42,76 @@
           :scroll-wheel-zoom="true"
           @ready="mapReady"
           @click="mapClick"
-          :mapStyle="mapConfig">
-          <bm-marker 
-            v-for="item in list" 
-            :position="{lat:item.latitude,lng:item.longitude}" 
-            @click="devicedClick($event,item)"
-            :icon="{url:MarkerIcon,size:{width:25,height:25}}"
+          :mapStyle="mapConfig"
+        >
+          <bm-marker
+            v-for="item in list"
+            :position="{ lat: item.latitude, lng: item.longitude }"
+            @click="devicedClick($event, item)"
+            :icon="{ url: MarkerIcon, size: { width: 25, height: 25 } }"
           >
-            <bm-label :content="item.devicename" :labelStyle="{border:'none'}" :offset="{width: -35, height: 16}"/>
+            <bm-label
+              :content="item.devicename"
+              :labelStyle="{ border: 'none' }"
+              :offset="{ width: -35, height: 16 }"
+            />
           </bm-marker>
         </baidu-map>
 
         <!--设备信息面板-->
-        <div class="info-panel" :style="infoPanel.baseInfo ? 'display:inline-block' : 'display:none'">
+        <div
+          class="info-panel"
+          :style="infoPanel.baseInfo ? 'display:inline-block' : 'display:none'"
+        >
           <div class="info-header">
             <div class="left">
               <span>设备信息</span>
             </div>
             <div class="right">
-              <customBtn :btn="true" :btn-options="[{'label':'控制面板'}]" @clickBtn="router.push({path:'/' + infoPanel.baseInfo.prodnum,query:{id:infoPanel.baseInfo.w_deviceid}})"></customBtn>
+              <customBtn
+                :btn="true"
+                :btn-options="[{ label: '控制面板' }]"
+                @clickBtn="
+                  router.push({
+                    path: '/' + infoPanel.baseInfo.prodnum,
+                    query: { id: infoPanel.baseInfo.w_deviceid },
+                  })
+                "
+              ></customBtn>
             </div>
           </div>
           <div class="map-deviced-info">
-            <p>设备名称:<span>{{ infoPanel.baseInfo.devicename }}</span></p>
-            <p>设备编码:<span>{{ infoPanel.baseInfo.serialnumber }}</span></p>
-            <p>状态:<a-tag type="info">{{ infoPanel.baseInfo.status }}</a-tag></p>
-            <p>区域:<span>{{ infoPanel.baseInfo.areaname }}</span></p>
-            <p>设备地点:<span>{{ infoPanel.baseInfo.address }}</span></p>
-            <p>固件版本:<span>{{ infoPanel.baseInfo.version }}</span></p>
-            <p>上次在线时间:<span>{{ infoPanel.baseInfo.lastconnecttime }}</span></p>
+            <p>
+              设备名称:<span>{{ infoPanel.baseInfo.devicename }}</span>
+            </p>
+            <p>
+              设备编码:<span>{{ infoPanel.baseInfo.serialnumber }}</span>
+            </p>
+            <p>
+              状态:<a-tag type="info">{{ infoPanel.baseInfo.status }}</a-tag>
+            </p>
+            <p>
+              区域:<span>{{ infoPanel.baseInfo.areaname }}</span>
+            </p>
+            <p>
+              设备地点:<span>{{ infoPanel.baseInfo.address }}</span>
+            </p>
+            <p>
+              固件版本:<span>{{ infoPanel.baseInfo.version }}</span>
+            </p>
+            <p>
+              上次在线时间:<span>{{
+                infoPanel.baseInfo.lastconnecttime
+              }}</span>
+            </p>
           </div>
           <p>监测指数</p>
           <div class="data-info">
-            <p v-for="item in infoPanel.dataInfo">{{ item.paramname }}:<span>{{ item.lastvalue }}{{ item.unit }}</span></p>
+            <p v-for="item in infoPanel.dataInfo">
+              {{ item.paramname }}:<span
+                >{{ item.lastvalue }}{{ item.unit }}</span
+              >
+            </p>
           </div>
         </div>
         <!--控制点显示面板-->
@@ -96,91 +144,120 @@
           
         </div> -->
       </div>
-        <!--列表-->
-        <a-card :bordered="false" class="M-list" v-if="!model">
-          <template #title>
-            <a-button type="primary" size="small" round @click="model=true">切换地图</a-button>
-          </template>
-          <normalTable rowKey="w_deviceid" :is-select="false" ref="list2" size="small" :param="param2" :columns="utils.TBLayout('equipmentTable')">
-            <template #tb_cell="{data}">
-              <div v-if="data.column.dataIndex == 'operation'">
-                <a-button type="link" @click="router.push({path:'/' + (data.record.dashboardpath || 'baseDevice'),query:{id:data.record.w_deviceid}})">控制界面</a-button>
-              </div>
-              <template v-else-if="data.column.dataIndex === 'isused'">
-                <span :style="{color:utils.statusAndColor(data.record.isused ? '启用' : '停用')}">{{ data.record.isused ? '启用' : '停用' }}</span>
-              </template>
-              <div v-else-if="data.column.dataIndex == 'rwtype'">
-                {{ data.record.rwtype == 0 ? '读' : data.record.rwtype == 1 ? '写' : '上报' }}
-              </div>
-              <div v-else>
-                {{ data.record[data.column.dataIndex] }}
-              </div>
-            </template>
-            <template #operation>
-              
+      <!--列表-->
+      <a-card :bordered="false" class="M-list" v-if="!model">
+        <template #title>
+          <a-button type="primary" size="small" round @click="model = true"
+            >切换地图</a-button
+          >
+        </template>
+        <normalTable
+          rowKey="w_deviceid"
+          :is-select="false"
+          ref="list2"
+          size="small"
+          :param="param2"
+          :columns="utils.TBLayout('equipmentTable')"
+        >
+          <template #tb_cell="{ data }">
+            <div v-if="data.column.dataIndex == 'operation'">
+              <a-button
+                type="link"
+                @click="
+                  router.push({
+                    path: '/' + (data.record.dashboardpath || 'baseDevice'),
+                    query: { id: data.record.w_deviceid },
+                  })
+                "
+                >控制界面</a-button
+              >
+            </div>
+            <template v-else-if="data.column.dataIndex === 'isused'">
+              <span
+                :style="{
+                  color: utils.statusAndColor(
+                    data.record.isused ? '启用' : '停用'
+                  ),
+                }"
+                >{{ data.record.isused ? "启用" : "停用" }}</span
+              >
             </template>
-          </normalTable>
-        </a-card>
+            <div v-else-if="data.column.dataIndex == 'rwtype'">
+              {{
+                data.record.rwtype == 0
+                  ? "读"
+                  : data.record.rwtype == 1
+                  ? "写"
+                  : "上报"
+              }}
+            </div>
+            <div v-else>
+              {{ data.record[data.column.dataIndex] }}
+            </div>
+          </template>
+          <template #operation> </template>
+        </normalTable>
+      </a-card>
     </div>
   </div>
 </template>
 
 <script setup>
-import mapConfig from './modules/mapConfig.js'
-import MarkerIcon from '../../../assets/map/marker1.svg'
-import customBtn from '../controlPanel/modules/customBtn.vue'
-import productInfo from './modules/productInfo.vue'
-import deviceInfo from './modules/deviceInfo.vue'
-import dataInfo from './modules/dataInfo.vue'
-import normalTable from '@/template/normalTable/index.vue'
-import { useRouter } from 'vue-router'
-import {ref, defineProps, defineEmits, onMounted} from 'vue'
-import Api from '@/api/api'
-import utils from '@/utils/utils'
-let emit = defineEmits([])
-let props = defineProps({})
+import mapConfig from "./modules/mapConfig.js";
+import MarkerIcon from "../../../assets/map/marker1.svg";
+import customBtn from "../controlPanel/modules/customBtn.vue";
+import productInfo from "./modules/productInfo.vue";
+import deviceInfo from "./modules/deviceInfo.vue";
+import dataInfo from "./modules/dataInfo.vue";
+import normalTable from "@/template/normalTable/index.vue";
+import { useRouter } from "vue-router";
+import { ref, defineProps, defineEmits, onMounted } from "vue";
+import Api from "@/api/api";
+import utils from "@/utils/utils";
+let emit = defineEmits([]);
+let props = defineProps({});
 let param = ref({
-  "id": 20230711144102,
-  "content": {
-      "pageNumber": 1,
-      "pageSize": 999999,
-      "where": {
-          "condition": "",
-          "areaname": ""
-      }
+  id: 20230711144102,
+  content: {
+    pageNumber: 1,
+    pageSize: 999999,
+    where: {
+      condition: "",
+      areaname: "",
+    },
   },
-})
+});
 let param2 = ref({
-  "id": 20230711144102,
-  "content": {
-      "pageNumber": 1,
-      "pageSize": 20,
-      "where": {
-          "condition": "",
-          "areaname": ""
-      }
+  id: 20230711144102,
+  content: {
+    pageNumber: 1,
+    pageSize: 20,
+    where: {
+      condition: "",
+      areaname: "",
+    },
   },
-})
+});
 
-let list = ref([])
+let list = ref([]);
 let latlng = ref({
-  lat:0,
-  lng:0
-})
-let zoom = ref(3)
-let model = ref(true)
-let map = ref()
+  lat: 0,
+  lng: 0,
+});
+let zoom = ref(3);
+let model = ref(true);
+let map = ref();
 let infoPanel = ref({
-  baseInfo:'',
-  dataInfo:''
-})
-let dataInfoList = ref([])
+  baseInfo: "",
+  dataInfo: "",
+});
+let dataInfoList = ref([]);
 
-let router = useRouter()
+let router = useRouter();
 
 let autoRange = (map, points_arr) => {
   if (points_arr.length === 0) {
-    return
+    return;
   }
   /**
    * 先计算中心点坐标
@@ -195,170 +272,152 @@ let autoRange = (map, points_arr) => {
    * 目标点的经度需要大于左下角点的经度并且小于右上角的经度
    *
    */
-  let max_lng = points_arr[0].split(',')[0],
-      min_lat = points_arr[0].split(',')[1],
-      max_lat = points_arr[0].split(',')[1],
-      min_lng = points_arr[0].split(',')[0]
+  let max_lng = points_arr[0].split(",")[0],
+    min_lat = points_arr[0].split(",")[1],
+    max_lat = points_arr[0].split(",")[1],
+    min_lng = points_arr[0].split(",")[0];
   for (let i = 0; i < points_arr.length - 1; i++) {
-      let lng_lat = points_arr[i + 1].split(',')
-      //   max = max < arr[i+1] ? arr[i+1] : max
-      max_lng = max_lng < lng_lat[0] ? lng_lat[0] : max_lng
-      min_lng = min_lng > lng_lat[0] ? lng_lat[0] : min_lng
-      max_lat = max_lat < lng_lat[1] ? lng_lat[1] : max_lat
-      min_lat = min_lat > lng_lat[1] ? lng_lat[1] : min_lat
+    let lng_lat = points_arr[i + 1].split(",");
+    //   max = max < arr[i+1] ? arr[i+1] : max
+    max_lng = max_lng < lng_lat[0] ? lng_lat[0] : max_lng;
+    min_lng = min_lng > lng_lat[0] ? lng_lat[0] : min_lng;
+    max_lat = max_lat < lng_lat[1] ? lng_lat[1] : max_lat;
+    min_lat = min_lat > lng_lat[1] ? lng_lat[1] : min_lat;
   }
   // console.log((Number(max_lng) + Number(min_lng)) / 2,(Number(max_lat)+Number(min_lat))/2);
-  let n_lng = (Number(max_lng) + Number(min_lng)) / 2
-  let n_lat = (Number(max_lat) + Number(min_lat)) / 2
+  let n_lng = (Number(max_lng) + Number(min_lng)) / 2;
+  let n_lat = (Number(max_lat) + Number(min_lat)) / 2;
 
   /**
    * 计算层级
    *  百度地图比例尺与级别关系
    */
-  let bs = map.getBounds() //获取可视区域
-  let bssw = bs.getSouthWest() //可视区域左下角
-  let bsne = bs.getNorthEast() //可视区域右上角
-// 百度地图比例尺与级别关系,参考https://blog.csdn.net/tjj3027/article/details/81015138
+  let bs = map.getBounds(); //获取可视区域
+  let bssw = bs.getSouthWest(); //可视区域左下角
+  let bsne = bs.getNorthEast(); //可视区域右上角
+  // 百度地图比例尺与级别关系,参考https://blog.csdn.net/tjj3027/article/details/81015138
   const map_rule = [
-      500000,
-      250000,
-      100000,
-      50000,
-      25000,
-      10000,
-      5000,
-      2500,
-      1250,
-      1000,
-      500,
-      250,
-      100,
-      50,
-      25,
-      10,
-      5,
-      2.5,
-      1,
-  ]
+    500000, 250000, 100000, 50000, 25000, 10000, 5000, 2500, 1250, 1000, 500,
+    250, 100, 50, 25, 10, 5, 2.5, 1,
+  ];
 
-  let zoomA = [4, 4]
+  let zoomA = [4, 4];
   for (let j = 0; j < 2; j++) {
-      let viewSize, searchSize
-      if (j === 0) {
-          viewSize = bsne.lng - bssw.lng // 当前可视宽度右上角经度-左下角经度
-          searchSize = (max_lng - min_lng) * 1.1 // 搜索结果的最大宽度 经度最大值-经度最小值
-      } else {
-          viewSize = bsne.lat - bssw.lat // 当前可视高度右上角纬度-左下角纬度
-          searchSize = (max_lat - min_lat) * 1.1 // 搜索结果的最大宽度 纬度最大值-纬度最小值
-      }
+    let viewSize, searchSize;
+    if (j === 0) {
+      viewSize = bsne.lng - bssw.lng; // 当前可视宽度右上角经度-左下角经度
+      searchSize = (max_lng - min_lng) * 1.1; // 搜索结果的最大宽度 经度最大值-经度最小值
+    } else {
+      viewSize = bsne.lat - bssw.lat; // 当前可视高度右上角纬度-左下角纬度
+      searchSize = (max_lat - min_lat) * 1.1; // 搜索结果的最大宽度 纬度最大值-纬度最小值
+    }
 
-      let minDiff = 0
-      for (let i = 0; i < map_rule.length; i++) {
-          let diff =
-              (viewSize * map_rule[i]) / map_rule[zoom.value - 1] - searchSize
-          if (diff > 0) {
-              if (minDiff == 0 || diff < minDiff) {
-                  zoomA[j] = i + 1
-                  minDiff = diff
-              }
-          }
+    let minDiff = 0;
+    for (let i = 0; i < map_rule.length; i++) {
+      let diff =
+        (viewSize * map_rule[i]) / map_rule[zoom.value - 1] - searchSize;
+      if (diff > 0) {
+        if (minDiff == 0 || diff < minDiff) {
+          zoomA[j] = i + 1;
+          minDiff = diff;
+        }
       }
+    }
   }
-  let zoom1 = zoomA[0] > zoomA[1] ? zoomA[1] : zoomA[0]
+  let zoom1 = zoomA[0] > zoomA[1] ? zoomA[1] : zoomA[0];
   // 设定地图最大缩放层级为18,最小为4
-  zoom1 = zoom1 >= 18 ? 18 : zoom1
-  zoom1 = zoom1 <= 4 ? 4 : zoom1
-/*
-*  图移动到新的中点,调整好层级
-*  这里使用 map.centerAndZoom(new BMap.Point(n_lng, n_lat),zoom)
-*	屏幕可能会过度晃动,暂时知道原因,所以用了下面的方案
-**/
-  zoom.value = zoom1
+  zoom1 = zoom1 >= 18 ? 18 : zoom1;
+  zoom1 = zoom1 <= 4 ? 4 : zoom1;
+  /*
+   *  图移动到新的中点,调整好层级
+   *  这里使用 map.centerAndZoom(new BMap.Point(n_lng, n_lat),zoom)
+   *	屏幕可能会过度晃动,暂时知道原因,所以用了下面的方案
+   **/
+  zoom.value = zoom1;
   function setCenter() {
-      map.panTo(new BMap.Point(n_lng, n_lat), { noAnimation: false }) // 设置中心点坐标
-      console.log('触发')
-      map.removeEventListener('tilesloaded', setCenter)
+    map.panTo(new BMap.Point(n_lng, n_lat), { noAnimation: false }); // 设置中心点坐标
+    console.log("触发");
+    map.removeEventListener("tilesloaded", setCenter);
   }
   //地图加载完毕(地图稍微有改动就会触发) 当地图所有图块完成加载时触发此事件
   map.addEventListener("tilesloaded", setCenter);
-}
+};
 
 let listData = async () => {
-  let res = await Api.requested(param.value)
-  list.value = res.data.filter(item => item.latitude != '')
+  let res = await Api.requested(param.value);
+  list.value = res.data.filter((item) => item.latitude != "");
   if (!list.value.length) {
     latlng.value = {
-      lat:32.98007167711148,
-      lng:110.34538404697058
-    }
-    zoom.value = 6
+      lat: 32.98007167711148,
+      lng: 110.34538404697058,
+    };
+    zoom.value = 6;
   }
-  
-}
+};
 
 let getData = async () => {
   let res = await Api.requested({
-    "id": 20230711101902,
-    "content": {},
-  })
-  dataInfoList.value = res.data
+    id: 20230711101902,
+    content: {},
+  });
+  dataInfoList.value = res.data;
   console.log(dataInfoList.value);
-}
+};
 
-let mapReady = ({Bmap,map}) => {
-  let lngLatArr = list.value.map(item => {
-    return item.longitude + ',' + item.latitude
-  })
-  map.value = map
-  autoRange(map,lngLatArr)
-}
+let mapReady = ({ Bmap, map }) => {
+  let lngLatArr = list.value.map((item) => {
+    return item.longitude + "," + item.latitude;
+  });
+  map.value = map;
+  autoRange(map, lngLatArr);
+};
 
 let mapClick = (e) => {
   console.log(e);
-  if(infoPanel.value.baseInfo) infoPanel.value = {baseInfo:'',dataInfo:''}
-}
+  if (infoPanel.value.baseInfo)
+    infoPanel.value = { baseInfo: "", dataInfo: "" };
+};
 
-let devicedClick = async (map,data) => {
-  console.log(map,data,'触发');
+let devicedClick = async (map, data) => {
+  console.log(map, data, "触发");
   let res = await Api.requested({
-    "id": 20230711165702,
-    "content": {
-        "w_deviceid": data.w_deviceid
+    id: 20230711165702,
+    content: {
+      w_deviceid: data.w_deviceid,
     },
-  })
+  });
   infoPanel.value = {
-    baseInfo:data,
-    dataInfo:res.data
-  }
-}
+    baseInfo: data,
+    dataInfo: res.data,
+  };
+};
 
 let modelChange = () => {
   if (model.value) {
-    listData()
+    listData();
   }
-}
+};
 
-router.afterEach( route => {
-  if (route.path == '/IoTdashboard') set()
-})
+router.afterEach((route) => {
+  if (route.path == "/IoTdashboard") set();
+});
 
 /* 适配 */
-let set =  () => {
-  let baseWidth = 2133
-  document.querySelector('html').style.fontSize = `${100 / baseWidth}vw`
-}
+let set = () => {
+  let baseWidth = 2133;
+  document.querySelector("html").style.fontSize = `${100 / baseWidth}vw`;
+};
 
 onMounted(() => {
-  getData()
-  listData()
-  set()
-  console.log(utils.TBLayout('equipmentTable'));
-})
-
+  getData();
+  listData();
+  set();
+  console.log(utils.TBLayout("equipmentTable"));
+});
 </script>
 
 <style scoped>
-*{
+* {
   box-sizing: border-box;
 }
 .M-container {
@@ -392,10 +451,9 @@ onMounted(() => {
   align-items: center;
 }
 
-
 .info-panel {
   width: 350rem;
-  background: rgb(90,100,119,.8) !important;
+  background: rgb(90, 100, 119, 0.8) !important;
   position: absolute;
   top: 50%;
   left: 20%;
@@ -411,20 +469,20 @@ onMounted(() => {
   align-items: center;
 }
 .info-panel .map-deviced-info {
-  background: rgba(255, 255, 255,.2);
+  background: rgba(255, 255, 255, 0.2);
   border-radius: 5rem;
   padding: 10rem;
   margin: 10rem 0;
 }
 .info-panel .data-info {
-  background: rgba(255, 255, 255,.2);
+  background: rgba(255, 255, 255, 0.2);
   border-radius: 5rem;
   padding: 10rem;
   margin: 10rem 0;
 }
 .point-control {
   width: 166rem;
-  background: rgb(90,100,119,.8) !important;
+  background: rgb(90, 100, 119, 0.8) !important;
   padding: 0 10rem;
   position: absolute;
   right: 10rem;
@@ -456,7 +514,7 @@ onMounted(() => {
   width: 180px;
 }
 /deep/ .header-control .ant-input {
-  background: rgb(90,100,119,.5) !important;
+  background: rgb(90, 100, 119, 0.5) !important;
   border: none !important;
   padding: 0 !important;
   color: #ffffff !important;

+ 3 - 2
src/operation/moduleNormal/pressureControl/index.vue

@@ -95,7 +95,7 @@
                   </template>
                   <span>{{ item.eventname }}</span>
                 </a-tooltip>
-           <!--      <span
+                <!--      <span
                   :style="{
                     color: baseSet.styleObj(
                       eventlevelList.filter(
@@ -159,7 +159,7 @@
       <div class="control_content-center">
         <ContentBox>
           <div class="header">
-            <span>设备监控</span>
+            <span style="flex: 1">设备监控</span>
             <a-button
               type="primary"
               size="small"
@@ -311,6 +311,7 @@ import {
   onDeactivated,
   watch,
   createVNode,
+  provide
 } from "vue";
 import Api from "@/api/api";
 import utils from "@/utils/utils";

+ 299 - 4
src/operation/moduleNormal/pressureControl/modules/devices.vue

@@ -1,5 +1,99 @@
 <template>
-  <div class="device-wrapper" v-load-directive="deviceLoad">
+  <!--地图-->
+  <div
+    class="M-map"
+    :style="isShowMap ? 'display:inline-block' : 'display:none'"
+  >
+    <div class="but-box">
+      <a-button type="primary" size="small" round @click="isShowMap = false"
+        >切换列表</a-button
+      >
+    </div>
+    <baidu-map
+      class="map"
+      ref="map"
+      :center="latlng"
+      :zoom="zoom"
+      :scroll-wheel-zoom="true"
+      @ready="mapReady"
+      @click="mapClick"
+      :mapStyle="mapConfig"
+    >
+      <bm-marker
+        v-for="item in list"
+        :position="{ lat: item.latitude, lng: item.longitude }"
+        @click="devicedClick($event, item)"
+        :icon="{ url: MarkerIcon, size: { width: 25, height: 25 } }"
+      >
+        <bm-label
+          :content="item.devicename"
+          :labelStyle="{ border: 'none', color: '#000' }"
+          :offset="{ width: -35, height: 16 }"
+        />
+      </bm-marker>
+    </baidu-map>
+
+    <!--设备信息面板-->
+    <div
+      class="info-panel"
+      :style="infoPanel.baseInfo ? 'display:inline-block' : 'display:none'"
+    >
+      <div class="info-header">
+        <div class="left">
+          <span>设备信息</span>
+        </div>
+        <div class="right">
+          <customBtn
+            :btn="true"
+            :btn-options="[{ label: '控制面板' }]"
+            @clickBtn="deviceClick(infoPanel.baseInfo)"
+          ></customBtn>
+        </div>
+      </div>
+      <div class="map-deviced-info">
+        <p>
+          设备名称:<span>{{ infoPanel.baseInfo.devicename }}</span>
+        </p>
+        <p>
+          设备编码:<span>{{ infoPanel.baseInfo.serialnumber }}</span>
+        </p>
+        <p>
+          状态:<a-tag type="info">{{ infoPanel.baseInfo.status }}</a-tag>
+        </p>
+        <p>
+          区域:<span>{{ infoPanel.baseInfo.areaname }}</span>
+        </p>
+        <p>
+          设备地点:<span>{{ infoPanel.baseInfo.address }}</span>
+        </p>
+        <p>
+          固件版本:<span>{{ infoPanel.baseInfo.version }}</span>
+        </p>
+        <p>
+          上次在线时间:<span>{{ infoPanel.baseInfo.lastconnecttime }}</span>
+        </p>
+      </div>
+      <p>监测指数</p>
+      <div class="data-info">
+        <p v-for="item in infoPanel.dataInfo">
+          {{ item.paramname }}:<span>{{ item.lastvalue }}{{ item.unit }}</span>
+        </p>
+      </div>
+    </div>
+  </div>
+  <div
+    style="margin: 10rem 20rem 10rem 20rem"
+    :style="!isShowMap ? 'display:inline-block' : 'display:none'"
+  >
+    <a-button type="primary" size="small" round @click="isShowMap = true"
+      >切换地图</a-button
+    >
+  </div>
+  <div
+    class="device-wrapper"
+    :style="!isShowMap ? 'display:inline-block' : 'display:none'"
+    v-load-directive="deviceLoad"
+  >
     <div class="device-list" v-if="deviceList.length">
       <ContentBox
         v-for="(item, index) in deviceList"
@@ -42,13 +136,148 @@
 </template>
 
 <script setup>
-import { ref, defineProps, onMounted } from "vue";
+import { ref, defineProps, onMounted, inject } from "vue";
 import Api from "@/api/api";
 import { useRouter } from "vue-router";
 import ContentBox from "./Box.vue";
 import { EnvironmentOutlined } from "@ant-design/icons-vue";
-
+import { Empty } from "ant-design-vue";
+import mapConfig from "../../IoTdashboard/modules/mapConfig.js";
+import customBtn from "../../controlPanel/modules/customBtn.vue";
+import MarkerIcon from "../../../../assets/map/marker1.svg";
+const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
 const router = useRouter();
+let isShowMap = ref(true);
+
+/* 地图 */
+let infoPanel = ref({
+    baseInfo: "",
+    dataInfo: "",
+  }),
+  latlng = ref({
+    lat: 39.9,
+    lng: 116.39,
+  }),
+  zoom = ref(3),
+  list = ref([]);
+
+let mapReady = ({ Bmap, map }) => {
+  let lngLatArr = list.value.map((item) => {
+    return item.longitude + "," + item.latitude;
+  });
+  map.value = map;
+  autoRange(map, lngLatArr);
+};
+
+let mapClick = (e) => {
+  if (infoPanel.value.baseInfo)
+    infoPanel.value = { baseInfo: "", dataInfo: "" };
+};
+
+let devicedClick = async (map, data) => {
+  console.log(map, data, "触发");
+  let res = await Api.requested({
+    id: 20230711165702,
+    content: {
+      w_deviceid: data.w_deviceid,
+    },
+  });
+  infoPanel.value = {
+    baseInfo: data,
+    dataInfo: res.data,
+  };
+  console.log("infoPanel", infoPanel);
+};
+
+let autoRange = (map, points_arr) => {
+  if (points_arr.length === 0) {
+    return;
+  }
+  /**
+   * 先计算中心点坐标
+   * 1. 找出所有点中最大最小经纬度
+   * 2. 计算中心点坐标
+   *
+   *
+   * bssw 为左下角
+   * bsne 为右上角
+   *
+   * 目标点的纬度需要大于左下角点的纬度并且小于右上角的纬度
+   * 目标点的经度需要大于左下角点的经度并且小于右上角的经度
+   *
+   */
+  let max_lng = points_arr[0].split(",")[0],
+    min_lat = points_arr[0].split(",")[1],
+    max_lat = points_arr[0].split(",")[1],
+    min_lng = points_arr[0].split(",")[0];
+  for (let i = 0; i < points_arr.length - 1; i++) {
+    let lng_lat = points_arr[i + 1].split(",");
+    //   max = max < arr[i+1] ? arr[i+1] : max
+    max_lng = max_lng < lng_lat[0] ? lng_lat[0] : max_lng;
+    min_lng = min_lng > lng_lat[0] ? lng_lat[0] : min_lng;
+    max_lat = max_lat < lng_lat[1] ? lng_lat[1] : max_lat;
+    min_lat = min_lat > lng_lat[1] ? lng_lat[1] : min_lat;
+  }
+  // console.log((Number(max_lng) + Number(min_lng)) / 2,(Number(max_lat)+Number(min_lat))/2);
+  let n_lng = (Number(max_lng) + Number(min_lng)) / 2;
+  let n_lat = (Number(max_lat) + Number(min_lat)) / 2;
+
+  /**
+   * 计算层级
+   *  百度地图比例尺与级别关系
+   */
+  let bs = map.getBounds(); //获取可视区域
+  let bssw = bs.getSouthWest(); //可视区域左下角
+  let bsne = bs.getNorthEast(); //可视区域右上角
+  // 百度地图比例尺与级别关系,参考https://blog.csdn.net/tjj3027/article/details/81015138
+  const map_rule = [
+    500000, 250000, 100000, 50000, 25000, 10000, 5000, 2500, 1250, 1000, 500,
+    250, 100, 50, 25, 10, 5, 2.5, 1,
+  ];
+
+  let zoomA = [4, 4];
+  for (let j = 0; j < 2; j++) {
+    let viewSize, searchSize;
+    if (j === 0) {
+      viewSize = bsne.lng - bssw.lng; // 当前可视宽度右上角经度-左下角经度
+      searchSize = (max_lng - min_lng) * 1.1; // 搜索结果的最大宽度 经度最大值-经度最小值
+    } else {
+      viewSize = bsne.lat - bssw.lat; // 当前可视高度右上角纬度-左下角纬度
+      searchSize = (max_lat - min_lat) * 1.1; // 搜索结果的最大宽度 纬度最大值-纬度最小值
+    }
+
+    let minDiff = 0;
+    for (let i = 0; i < map_rule.length; i++) {
+      let diff =
+        (viewSize * map_rule[i]) / map_rule[zoom.value - 1] - searchSize;
+      if (diff > 0) {
+        if (minDiff == 0 || diff < minDiff) {
+          zoomA[j] = i + 1;
+          minDiff = diff;
+        }
+      }
+    }
+  }
+  let zoom1 = zoomA[0] > zoomA[1] ? zoomA[1] : zoomA[0];
+  // 设定地图最大缩放层级为18,最小为4
+  zoom1 = zoom1 >= 18 ? 18 : zoom1;
+  zoom1 = zoom1 <= 4 ? 4 : zoom1;
+  /*
+   *  图移动到新的中点,调整好层级
+   *  这里使用 map.centerAndZoom(new BMap.Point(n_lng, n_lat),zoom)
+   *	屏幕可能会过度晃动,暂时知道原因,所以用了下面的方案
+   **/
+  zoom.value = zoom1;
+  function setCenter() {
+    map.panTo(new BMap.Point(n_lng, n_lat), { noAnimation: false }); // 设置中心点坐标
+    console.log("触发");
+    map.removeEventListener("tilesloaded", setCenter);
+  }
+  //地图加载完毕(地图稍微有改动就会触发) 当地图所有图块完成加载时触发此事件
+  map.addEventListener("tilesloaded", setCenter);
+};
+
+/* 列表 */
 let DeviceTotalPage = ref(0);
 let deviceList = ref([]);
 let deviceParam = ref({
@@ -68,14 +297,26 @@ let deviceLoad = () => {
 
 let getDeviceData = async () => {
   let res = await Api.requested(deviceParam.value);
+  console.log("获取列表", res);
   deviceList.value =
     deviceParam.value.content.pageNumber == 1
       ? res.data
       : deviceList.value.concat(res.data);
+
+  list.value = res.data.filter((item) => item.latitude != "");
+  console.log("list.value", list.value);
+  if (!list.value.length) {
+    latlng.value = {
+      lat: 39.9,
+      lng: 116.39,
+    };
+    zoom.value = 6;
+  }
   DeviceTotalPage.value = res.pageTotal;
 };
 
 let deviceClick = (data) => {
+  console.log("跳转", data);
   router.push({
     path: "/" + (data.dashboardpath || "baseDevice"),
     query: {
@@ -95,16 +336,70 @@ onMounted(async () => {
   --color1: #16fff6;
   --color2: rgba(255, 164, 6);
 }
+/* 地图 */
+.M-map {
+  width: 100%;
+  height: calc(100vh - 290rem);
+  position: relative;
+  padding: 12rem;
+}
+.M-map .map {
+  width: 100%;
+  height: 100%;
+  border-radius: 8rem;
+  overflow: hidden;
+}
 
+.M-map .but-box {
+  position: absolute;
+  top: 25rem;
+  left: 25rem;
+  z-index: 9999;
+}
+
+.info-panel {
+  width: 250rem;
+  background: rgb(90, 100, 119, 0.8) !important;
+  position: absolute;
+  top: 48%;
+  left: 4%;
+  transform: translateY(-50%);
+  z-index: 9999999999999999999;
+  padding: 10rem;
+  color: #ffffff;
+  font-size: 14rem;
+}
+.info-panel .info-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+.info-panel .map-deviced-info {
+  background: rgba(255, 255, 255, 0.2);
+  border-radius: 5rem;
+  padding: 10rem;
+  margin: 10rem 0;
+}
+.info-panel .data-info {
+  background: rgba(255, 255, 255, 0.2);
+  border-radius: 5rem;
+  padding: 10rem;
+  margin: 10rem 0;
+}
+/* 列表 */
 .device-wrapper {
   display: flex;
+  justify-content: center;
   overflow-y: scroll;
   height: calc(100% - 180rem);
-  margin-top: 40rem;
+  scrollbar-width: none; /* firefox */
+  -ms-overflow-style: none; /* IE 10+ */
+  margin-top: 10rem;
 }
 .device-wrapper .device-list {
   display: flex;
   flex-wrap: wrap;
+  padding-bottom: 50rem;
 }
 
 .device-wrapper .device-list .content_box {

+ 4 - 4
vite.config.js

@@ -12,15 +12,15 @@ export default defineConfig({
   },
   define: {
     'process.env': {
-      'BASE_API':"http://60.204.153.188"
-      // 'BASE_API':"http://61.164.207.46:8100/"
+      // 'BASE_API':"http://60.204.153.188"
+      'BASE_API':"http://61.164.207.46:8100/"
     }
   },
   server: {
     proxy: {
       "/api": {
-        target: "http://60.204.153.188/",
-        // target: "http://61.164.207.46:8100/",
+        // target: "http://60.204.153.188/",
+        target: "http://61.164.207.46:8100/",
         ws: true,
         changeOrigin: true,
         rewrite: (path) => path.replace(/^\/api/, ""),