浏览代码

点位信息样式、易涝点全部视频、更新时间

Hwf 7 月之前
父节点
当前提交
4906a2b377

+ 15 - 0
src/api/globalMap/potentialFloodHazard.ts

@@ -7,3 +7,18 @@ export const getWaterloggedRoadsList = (data) => {
     data: data
   });
 };
+
+export const getWaterloggedAllVideoInfo = (params) => {
+  return request({
+    url: '/api/videoResource/videoinfo/get_waterlogged_all_video_info',
+    method: 'get',
+    params: params
+  });
+};
+
+export const getWaterloggedRoadsUpdateTime = () => {
+  return request({
+    url: 'api/gateway/v1/get_waterlogged_roads_update_time',
+    method: 'get'
+  });
+};

二进制
src/assets/images/dotIcon/1_expert_hover.png


二进制
src/assets/images/map/rightMenu/triangle.png


+ 0 - 1
src/components/HKVideo/hikvision-h5player.vue

@@ -180,7 +180,6 @@ const stopPlay = () => {
 
 // 整体全屏
 const fullScreen = (type) => {
-  debugger
   state.player &&
     state.player.JS_FullScreenDisplay(type).then(
       () => {

+ 41 - 11
src/components/Map/index.vue

@@ -51,7 +51,7 @@ const props = withDefaults(defineProps<Props>(), {});
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { point_type } = toRefs<any>(proxy?.useDict('point_type'));
 
-const emits = defineEmits(['update:drawing', 'selectGraphics', 'unSelectGraphics', 'showTextEditBox', 'onDrawCompleted']);
+const emits = defineEmits(['update:drawing', 'selectGraphics', 'unSelectGraphics', 'showTextEditBox', 'onDrawCompleted', 'handleShowVideo']);
 const containerRef = ref();
 const width = ref('100%');
 const height = ref('100%');
@@ -95,7 +95,7 @@ const { getAMap, getMap, switchMap, addMarker, addSearchMarker, clearMarker, get
     drawTool.initMouseTool({ container: 'aMap', map, AMap });
     handleResize();
   },
-  onMarkerClick: (data) => {
+  onMarkerClick: (data, e) => {
     // 多点位
     if (data.type === '1') {
       let path = [];
@@ -109,6 +109,7 @@ const { getAMap, getMap, switchMap, addMarker, addSearchMarker, clearMarker, get
       }).then((res) => {
         const data2 = res.data.list;
         let content = document.createElement('div');
+        // content.style.cssText = 'transform: scale(' + containerScale().scaleX + ');';
         content.className = 'point-info';
         let content2 = '';
         content2 += '<div class="title-box"><div class="gradient-text">多点位信息</div></div>';
@@ -125,8 +126,11 @@ const { getAMap, getMap, switchMap, addMarker, addSearchMarker, clearMarker, get
           item.latitude = data.latitude;
           const div = document.createElement('div');
           div.className = 'point-item';
-          div.innerHTML = '<div class="td2">' + getDictLabel(point_type.value, item.dataType.toString()) + '</div><div class="td2">' + item.name + '</div>';
-          div.addEventListener('click', () => handlePointDetails(item));
+          div.innerHTML =
+            '<div class="td2">' + getDictLabel(point_type.value, item.dataType.toString()) + '</div><div class="td2">' + item.name + '</div>';
+          div.addEventListener('click', () => {
+            handlePointDetails(item);
+          });
           table.appendChild(div);
         });
         content.appendChild(table);
@@ -168,16 +172,41 @@ const handlePointDetails = (data) => {
   method(data.id).then((res) => {
     if (!!pointDetailTemplate[data.dataType]) {
       let div = document.createElement('div');
+      // div.style.cssText = 'transform: scale(' + containerScale().scaleX + ');';
       div.className = 'point-info';
+      let titleDom = document.createElement('div');
+      titleDom.className = 'title-box';
+      titleDom.innerHTML = '<div class="gradient-text">' + title + '</div></div>';
+      div.appendChild(titleDom);
+      if (data.dataType === 4) {
+        let btnBox = document.createElement('div');
+        let btn = document.createElement('div');
+        btnBox.className = 'flex';
+        btn.className = 'btn';
+        btn.innerHTML = '<div class="video-icon"></div><div>附近视频</div>';
+        btn.onclick = () => {
+          emits('handleShowVideo', data);
+        };
+        btnBox.appendChild(btn);
+        div.appendChild(btnBox);
+      }
+      let icon1 = document.createElement('div');
+      icon1.className = 'icon1';
+      let icon2 = document.createElement('div');
+      icon2.className = 'icon2';
+      let icon3 = document.createElement('div');
+      icon3.className = 'icon3';
+      let icon4 = document.createElement('div');
+      icon4.className = 'icon4';
+      div.appendChild(icon1);
+      div.appendChild(icon2);
+      div.appendChild(icon3);
+      div.appendChild(icon4);
+      let table = document.createElement('div');
+      table.className = 'table';
       let content = '';
-      content += '<div class="title-box"><div class="gradient-text">' + title + '</div></div>';
-      content += '<div class="icon1"></div>';
-      content += '<div class="icon2"></div>';
-      content += '<div class="icon3"></div>';
-      content += '<div class="icon4"></div>';
       content += '<div class="table">';
       const newData = filterTd(res.rows[0], data.dataType);
-
       newData.forEach((item) => {
         if (item.type === 'shortText') {
           content += '<div class="tr">';
@@ -194,7 +223,8 @@ const handlePointDetails = (data) => {
         }
       });
       content += '</div>';
-      div.innerHTML = content;
+      table.innerHTML = content;
+      div.appendChild(table);
       let closeBtn = document.createElement('div');
       closeBtn.className = 'close';
       closeBtn.onclick = hideInfo;

+ 26 - 1
src/components/Map/map.scss

@@ -84,7 +84,7 @@ $vh_base: 2520;
     background-position: bottom left;
     &::before {
       content: "";
-      width: 515px;
+      width: 500px;
       height: 2px;
       background-image: linear-gradient(to right, rgba(0, 191, 252, 0.35) 0, rgba(0, 191, 252, 0) 100%);
       display: block;
@@ -121,4 +121,29 @@ $vh_base: 2520;
     bottom: 2px;
     transform: rotate(-90deg);
   }
+  .flex {
+    width: 100%;
+    display: flex;
+    justify-content: flex-end;
+  }
+  .btn {
+    width: 125px;
+    height: 50px;
+    background: url('@/assets/images/map/rightMenu/potentialFloodHazard/btn2.png') no-repeat;
+    background-size: 100% 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    cursor: pointer;
+    margin-left: 20px;
+    color: #edfaff;
+    //font-size: 32px;
+    .video-icon {
+      width: 20.5px;
+      height: 19px;
+      background: url('@/assets/images/map/rightMenu/potentialFloodHazard/video.png') no-repeat;
+      background-size: 100% 100%;
+      display: flex;
+    }
+  }
 }

+ 106 - 12
src/components/NearbyVideos/index.vue

@@ -9,7 +9,18 @@
       </el-select>
     </div>
     <div class="video-box">
-      <video-container2 :video-data="videoMonitorData" />
+      <video-container2 v-show="!loading" :video-data="videoMonitorData" />
+    </div>
+    <div v-if="!!getDataMethod" class="footer">
+      <el-pagination
+        background
+        :hide-on-single-page="true"
+        layout="total, prev, pager, next"
+        :total="total"
+        :page-size="queryParams2.pageSize"
+        :current-page="queryParams2.page"
+        @current-change="initData2"
+      />
     </div>
   </div>
 </template>
@@ -17,19 +28,24 @@
 <script lang="ts" setup name="NearbyVideos">
 // 请求参数
 import { getVideoInfo } from '@/api/globalMap';
+import { getWaterloggedRoadsUpdateTime } from '@/api/globalMap/potentialFloodHazard';
 
 interface Props {
   modelValue: boolean;
-  location: string | number[];
+  location?: string | number[];
+  getDataMethod?: Function;
 }
 const props = withDefaults(defineProps<Props>(), {});
 const emits = defineEmits(['update:modelValue']);
+const total = ref(0);
 const queryParams = reactive({
-  current: 1,
-  size: 9,
   location: '',
   radius: '500'
 });
+const queryParams2 = reactive({
+  page: 1,
+  pageSize: 9
+});
 let videoMonitorData = ref([]);
 const radiusOption = reactive([
   { label: '500米', value: '500' },
@@ -37,19 +53,54 @@ const radiusOption = reactive([
   { label: '1500米', value: '1500' },
   { label: '2000米', value: '2000' }
 ]);
+let loading = ref(false);
 const initData = () => {
-  getVideoInfo(queryParams).then((res) => {
-    res.data?.list.forEach((item) => {
-      item.video_code = item.indexcode;
+  loading.value = true;
+  getVideoInfo(queryParams)
+    .then((res) => {
+      res.data?.list.forEach((item) => {
+        item.video_code = item.indexcode;
+      });
+      videoMonitorData.value = res.data?.list;
+    })
+    .finally(() => {
+      loading.value = false;
+    });
+};
+const initData2 = () => {
+  loading.value = true;
+  props
+    .getDataMethod({ page: queryParams2.page, pageSize: queryParams2.pageSize, radius: queryParams.radius })
+    .then((res) => {
+      total.value = res.totalPages;
+      res.data?.list.forEach((item) => {
+        item.video_code = item.indexcode;
+      });
+      videoMonitorData.value = res.data?.list;
+    })
+    .finally(() => {
+      loading.value = false;
     });
-    videoMonitorData.value = res.data?.list;
-  });
 };
 watch(
   () => props.location,
   () => {
-    queryParams.location = `POINT(${props.location[0]} ${props.location[1]})`;
-    initData();
+    if (props.location && props.location.length === 2) {
+      queryParams.location = `POINT(${props.location[0]} ${props.location[1]})`;
+      initData();
+    }
+  },
+  {
+    immediate: true,
+    deep: true
+  }
+);
+watch(
+  () => props.getDataMethod,
+  () => {
+    if (!!props.getDataMethod) {
+      initData2();
+    }
   },
   {
     immediate: true,
@@ -75,6 +126,8 @@ const handleClose = () => {
   padding: 160px 30px 20px 40px;
   font-size: 36px;
   color: #ffffff;
+  display: flex;
+  flex-direction: column;
 }
 .flex-box {
   display: flex;
@@ -88,7 +141,7 @@ const handleClose = () => {
 }
 .video-box {
   margin-top: 30px;
-  height: 1245px;
+  flex: 1;
   display: flex;
   flex-wrap: wrap;
 }
@@ -108,4 +161,45 @@ const handleClose = () => {
   background-size: 100% 100%;
   cursor: pointer;
 }
+.footer {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 30px;
+  padding-right: 40px;
+  :deep(.el-pagination__total) {
+    color: #a7ccdf;
+    font-size: 32px;
+  }
+
+  :deep(.el-pagination) {
+    .btn-next,
+    .btn-prev {
+      background-color: transparent;
+      border: none;
+      .el-icon {
+        font-size: 22px;
+        color: #a7ccdf;
+      }
+    }
+    .el-pager li {
+      width: 64px;
+      height: 64px;
+      line-height: 64px;
+      text-align: center;
+      font-size: 32px;
+      color: #a7ccdf;
+      background-color: #0e3064;
+      border: 1px solid #0c57a7;
+      margin: 0 6px;
+      &:hover {
+        background-color: #038dff;
+        border: 1px solid #038dff;
+      }
+    }
+    .el-pager li.is-active {
+      background-color: #038dff;
+      border: 1px solid #038dff;
+    }
+  }
+}
 </style>

+ 39 - 3
src/hooks/AMap/useAMap.ts

@@ -5,6 +5,8 @@ export function useAMap(options) {
   const markers = {
     point: []
   };
+  let clickMarker = null;
+  let addPoints = [];
   // 初始化事件
   const initMap = (options) => {
     AMapLoader.load({
@@ -63,6 +65,7 @@ export function useAMap(options) {
 
   const addMarker = (points, isSearchItem?: boolean) => {
     clearMarker('point');
+    addPoints = points;
     const count = points.length;
     const _renderClusterMarker = function (context) {
       console.log(context);
@@ -90,7 +93,7 @@ export function useAMap(options) {
       const content =
         '<div style="display: flex;flex-direction: column;align-items: center;justify-content: center">' +
         '<div style="background: url(' +
-        context.data[0].image +
+        context.data[0].icon +
         ') no-repeat; width: ' +
         context.data[0].size[0] +
         'px;height: ' +
@@ -103,7 +106,29 @@ export function useAMap(options) {
       context.marker.setOffset(offset);
       context.marker.setExtData(context.data[0]);
       context.marker.on('click', function (e) {
-        options.onMarkerClick(e.target.getExtData());
+        const extData = e.target.getExtData();
+        let index = 0;
+        for (let i = 0; i < addPoints.length; i++) {
+          if (addPoints[i].id === extData.id && addPoints[i].imageHover) {
+            addPoints[i].icon = addPoints[i].imageHover;
+            e.target.setContent(content);
+            index++;
+          } else if (!!clickMarker) {
+            const extData2 = clickMarker.getExtData();
+            if (addPoints[i].id === extData2.id) {
+              addPoints[i].icon = addPoints[i].image;
+              clickMarker.setContent(content);
+
+              index++;
+            }
+          }
+          if ((!!clickMarker && index === 2) || (!clickMarker && index === 1)) {
+            break;
+          }
+        }
+        addMarker(addPoints);
+        clickMarker = e.target;
+        options.onMarkerClick(extData);
       });
     };
     cluster = new AMap.MarkerCluster(
@@ -148,9 +173,20 @@ export function useAMap(options) {
     infoWindow.open(map, lnglat);
   };
 
-  const hideInfo = () => {
+  const hideInfo = (e) => {
     if (!!infoWindow) {
       infoWindow.close();
+      if (!!clickMarker && e) {
+        const extData = clickMarker.getExtData();
+        for (let i = 0; i < addPoints.length; i++) {
+          if (addPoints[i].id === extData.id) {
+            addPoints[i].icon = addPoints[i].image;
+            clickMarker = null;
+            addMarker(addPoints);
+            break;
+          }
+        }
+      }
     }
   };
 

+ 21 - 5
src/views/globalMap/RightMenu/PotentialFloodHazard.vue

@@ -6,11 +6,11 @@
       <div class="date-box">
         <div class="text1">更新</div>
         <div class="text-box">
-          <div class="text2">2024</div>
+          <div class="text2">{{ timeArr[0] }}</div>
           <div class="text1">年</div>
-          <div class="text2">09</div>
+          <div class="text2">{{ timeArr[1] }}</div>
           <div class="text1">月</div>
-          <div class="text2">18</div>
+          <div class="text2">{{ timeArr[2] }}</div>
           <div class="text1">日</div>
         </div>
       </div>
@@ -61,20 +61,28 @@
     </div>
   </div>
   <NearbyVideos v-if="showNearbyVideos" v-model="showNearbyVideos" :location="location" />
+  <NearbyVideos v-if="showNearbyVideos2" v-model="showNearbyVideos2" :getDataMethod="getDataMethod" />
 </template>
 
 <script lang="ts" setup>
 import { Search } from '@element-plus/icons-vue';
-import { getWaterloggedRoadsList } from '@/api/globalMap/potentialFloodHazard';
+import {
+  getWaterloggedAllVideoInfo,
+  getWaterloggedRoadsList,
+  getWaterloggedRoadsUpdateTime
+} from '@/api/globalMap/potentialFloodHazard';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { district_type } = toRefs<any>(proxy?.useDict('district_type'));
+const getMap = inject('getMap');
 const queryParams = reactive({
   area: '',
   keyword: ''
 });
 const dataList = ref([]);
 const showNearbyVideos = ref(false);
+const showNearbyVideos2 = ref(false);
+const getDataMethod = ref(null);
 let location = ref([]);
 const initData = () => {
   getWaterloggedRoadsList(queryParams).then((res) => {
@@ -86,14 +94,22 @@ const handleCancel = () => {
   initData();
 };
 const showMoreVideos = () => {
-  console.log('全部视频');
+  getDataMethod.value = getWaterloggedAllVideoInfo;
+  showNearbyVideos2.value = true;
 };
 const handleShowDialog = (item) => {
   location.value = [item.lng, item.lat];
+  getMap().setCenter(location.value);
   showNearbyVideos.value = true;
 };
+let timeArr = ref([]);
 onMounted(() => {
   initData();
+  getWaterloggedRoadsUpdateTime().then((res) => {
+    const dateTimeStr = res.data.list[0].update_time;
+    let parts = dateTimeStr.split(' ');
+    timeArr.value = parts[0].split('-');
+  });
 });
 </script>
 

+ 8 - 6
src/views/globalMap/data/mapData.ts

@@ -4111,9 +4111,6 @@ export const logicalData = {
     ]
   ]
 };
-import expertImg from '@/assets/images/dotIcon/1_expert.png';
-import rescueSuppliesImg from '@/assets/images/dotIcon/2_rescue_supplies.png';
-import easyFloodPointImg from '@/assets/images/dotIcon/4_easy_flood_point.png';
 import hospitalImg from '@/assets/images/dotIcon/6_hospital.png';
 import gasStationImg from '@/assets/images/dotIcon/7_gas_station.png';
 import schoolImg from '@/assets/images/dotIcon/5_school.png';
@@ -4121,13 +4118,17 @@ import nonCoalMineImg from '@/assets/images/dotIcon/8_non_coal_mine.png';
 import enterprisesImg from '@/assets/images/dotIcon/9_hazardous_chemical_enterprises.png';
 import shipDynamicsImg from '@/assets/images/dotIcon/10_ship_dynamics.png';
 import UAVImg from '@/assets/images/dotIcon/15_UAV.png';
+const getImageUrl = (name) => {
+  return new URL(`../../../assets/images/dotIcon/${name}`, import.meta.url).href;
+};
 export const iconList = {
   '1': {
-    image: expertImg,
+    image: getImageUrl('1_expert.png'),
+    imageHover: getImageUrl('1_expert_hover.png'),
     size: [40, 40]
   },
   '2': {
-    image: rescueSuppliesImg,
+    image: getImageUrl('2_rescue_supplies'),
     size: [40, 40]
   },
   '3': {
@@ -4135,11 +4136,12 @@ export const iconList = {
     size: [19, 31]
   },
   '4': {
-    image: easyFloodPointImg,
+    image: getImageUrl('4_easy_flood_point.png'),
     size: [40, 40]
   },
   'common': {
     image: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
+    imageHover: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
     size: [19, 31]
   },
   '5': {

+ 14 - 3
src/views/globalMap/index.vue

@@ -4,7 +4,7 @@
       <MapLogical v-if="activeMap === 'logical'" :map-data="mapData" />
 <!--      <YMap v-else-if="['satellite2', 'satellite3'].includes(activeMap)" :activeMap="activeMap" />-->
       <YztMap v-else-if="['satellite2', 'satellite3'].includes(activeMap)" ref="map2Ref" :active-map="activeMap" :pointType="pointType" />
-      <Map v-else ref="mapRef" :active-map="activeMap" :pointType="pointType" />
+      <Map v-else ref="mapRef" :active-map="activeMap" :pointType="pointType" @handleShowVideo="handleShowVideo" />
       <!--左侧菜单-->
       <LeftMenu style="position: absolute; top: 20px; left: 20px" @click-menu="clickMenu" @select-search-marker="selectSearchMarker" />
       <!--右侧菜单-->
@@ -13,6 +13,7 @@
       <SwitchMapTool :active-map="activeMap" class="tool-box" @switch-map="switchMap" />
       <!--时间轴-->
       <TimeAxis />
+      <NearbyVideos v-if="showNearbyVideos" v-model="showNearbyVideos" :location="location" />
     </div>
   </div>
 </template>
@@ -66,8 +67,7 @@ const addMarkers = (item) => {
         dom.clearMarker('point');
         return;
       }
-    }
-    else {
+    } else {
       // 右侧图层分析状态
       item.checked2 = true;
       pointType.value.push(item);
@@ -82,10 +82,14 @@ const addMarkers = (item) => {
       data.forEach((item2) => {
         // 获取图标
         if (iconList[item2.dataType]) {
+          item2.icon = iconList[item2.dataType].image;
           item2.image = iconList[item2.dataType].image;
+          item2.imageHover = iconList[item2.dataType].imageHover;
           item2.size = iconList[item2.dataType].size;
         } else {
+          item2.icon = iconList['common'].image;
           item2.image = iconList['common'].image;
+          item2.imageHover = iconList['common'].imageHover;
           item2.size = iconList['common'].size;
         }
         if (item2.materia_name) {
@@ -166,6 +170,13 @@ const getDrawTool = () => {
   }
   return {};
 };
+let showNearbyVideos = ref(false);
+let location = reactive([]);
+// 显示附近视频
+const handleShowVideo = (data) => {
+  location = [data.longitude, data.latitude];
+  showNearbyVideos.value = true;
+};
 provide('getMap', getMap);
 provide('getDrawTool', getDrawTool);
 </script>

+ 0 - 1
src/views/routineCommandMap/PositionMap.vue

@@ -292,7 +292,6 @@ function handleClose() {
 let queryFormRef = ref();
 let containerRef = ref();
 function handleResize() {
-  debugger
   const containerWidth = containerRef.value.clientWidth * (document.body.clientWidth / 8960);
   const containerHeight = containerRef.value.clientHeight * (document.body.clientHeight / 2520);
   width.value = containerWidth + 'px';