Sfoglia il codice sorgente

救援队伍实现,样式调整

Hwf 6 mesi fa
parent
commit
c1adbbca2d

+ 32 - 0
src/api/globalMap/rescueTeam.ts

@@ -0,0 +1,32 @@
+import request from '@/utils/request';
+
+// 救援队伍列表
+export const getRescueTeamsList = (data) => {
+  return request({
+    url: '/api/gateway/v2/get_rescue_teams_list',
+    method: 'post',
+    data: data
+  });
+};
+
+// 救援队伍信息
+export const getRescueTeamsInfo = (id) => {
+  return request({
+    url: '/api/gateway/v2/get_rescue_teams_info',
+    method: 'post',
+    data: {
+      query: {
+        id
+      }
+    }
+  });
+};
+
+// 救援队伍人员列表
+export const getRescueTeamsPersonnelList = (data) => {
+  return request({
+    url: '/api/gateway/v2/get_rescue_teams_personnel_list',
+    method: 'post',
+    data: data
+  });
+};

BIN
src/assets/images/dotIcon/41_rescue_team.png


BIN
src/assets/images/dotIcon/41_rescue_team_hover.png


+ 18 - 3
src/components/Map/index.vue

@@ -51,6 +51,7 @@ import {
 import { pointDetailTemplate } from '@/views/globalMap/data/mapData';
 import ElementResizeDetectorMaker from 'element-resize-detector';
 import useAppStore from '@/store/modules/app';
+import { getRescueTeamsInfo } from '@/api/globalMap/rescueTeam';
 interface Props {
   activeMap: string;
   pointType: PointType[];
@@ -69,7 +70,8 @@ const emits = defineEmits([
   'showTextEditBox',
   'onDrawCompleted',
   'handleShowVideo',
-  'handleShowWarehouse'
+  'handleShowWarehouse',
+  'handleShowPeople'
 ]);
 const containerRef = ref();
 const width = ref('100%');
@@ -226,7 +228,8 @@ const handlePointDetails = (data) => {
     '31': getWaterList,
     '32': getVideoDrowning,
     '33': getVideoForestFire,
-    '34': getVideoDisasterPrevention
+    '34': getVideoDisasterPrevention,
+    '41': getRescueTeamsInfo
   };
   let titleList = {
     '1': '专家信息',
@@ -262,7 +265,8 @@ const handlePointDetails = (data) => {
     '31': '江湖河库',
     '32': '防溺水',
     '33': '森林防火',
-    '34': '防灾救援'
+    '34': '防灾救援',
+    '41': '救援队伍'
   };
   let method = methodList[data.dataType];
   let title = !!titleList[data.dataType] ? titleList[data.dataType] : '信息';
@@ -298,6 +302,17 @@ const handlePointDetails = (data) => {
         };
         btnBox.appendChild(btn);
         div.appendChild(btnBox);
+      } else if (data.dataType === 41) {
+        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('handleShowPeople', data);
+        };
+        btnBox.appendChild(btn);
+        div.appendChild(btnBox);
       }
       let icon1 = document.createElement('div');
       icon1.className = 'icon1';

+ 140 - 0
src/views/globalMap/RightMenu/EmergencyCrew.vue

@@ -0,0 +1,140 @@
+<template>
+  <Dialog custom-show type="md" title="应急人员" hide-footer @close="handleClose">
+    <div class="btn-box">
+      <el-input v-model="queryParams.keyword" class="custom-input" placeholder="搜索" @keyup.enter="initData">
+        <template #prefix>
+          <el-icon class="el-input__icon"><search /></el-icon>
+        </template>
+      </el-input>
+      <div class="common-btn-primary" @click="initData">搜索</div>
+    </div>
+    <div class="common-table">
+      <div class="table-header">
+        <div class="td">姓名</div>
+        <div class="td">联系电话</div>
+        <div class="td" style="width: 80px; flex-shrink: 0">性别</div>
+        <div class="td">现在地址</div>
+        <div class="td">职务</div>
+        <div class="td" style="width: 520px; flex-shrink: 0">所属救援人员单位</div>
+      </div>
+      <div v-for="(item, index) in dataList" :key="index" class="tr">
+        <div class="td">{{ item.name }}</div>
+        <div class="td">{{ item.phone_number }}</div>
+        <div class="td" style="width: 80px; flex-shrink: 0">{{ item.gender }}</div>
+        <div class="td">{{ item.current_address }}</div>
+        <div class="td">{{ item.duty }}</div>
+        <div class="td" style="width: 520px; flex-shrink: 0">{{ item.affiliated_team }}</div>
+      </div>
+    </div>
+    <div class="footer">
+      <el-pagination
+        background
+        :hide-on-single-page="true"
+        layout="total, prev, pager, next"
+        :total="total"
+        :page-size="queryParams.pageSize"
+        :current-page="queryParams.page"
+        @current-change="initData"
+      />
+    </div>
+  </Dialog>
+</template>
+
+<script lang="ts" setup>
+import { Search } from '@element-plus/icons-vue';
+import { getRescueTeamsPersonnelList } from '@/api/globalMap/rescueTeam';
+
+const props = defineProps({
+  modelValue: Boolean,
+  id: String
+});
+const emits = defineEmits(['update:modelValue']);
+const queryParams = reactive({
+  page: 1,
+  pageSize: 10,
+  keyword: ''
+});
+let total = ref(0);
+let dataList = ref([]);
+const initData = () => {
+  getRescueTeamsPersonnelList({
+    query: {
+      id: props.id,
+      keyword: queryParams.keyword
+    }
+  }).then((res) => {
+    dataList.value = res.rows;
+  });
+};
+const handleClose = () => {
+  emits('update:modelValue', false);
+};
+initData();
+</script>
+
+<style lang="scss" scoped>
+.btn-box {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20px;
+  .custom-input {
+    width: 840px;
+  }
+  .common-btn-primary {
+    flex-shrink: 0;
+  }
+}
+.footer {
+  height: 64px;
+  display: flex;
+  justify-content: flex-end;
+  margin: 30px 0;
+  .pagination-container {
+    height: 64px;
+    margin: 0;
+  }
+  :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;
+      }
+    }
+    .btn-prev:disabled,
+    .btn-next:disabled {
+      background-color: transparent;
+      border: none;
+    }
+    .el-pager li {
+      width: 64px;
+      height: 64px;
+      line-height: 64px;
+      text-align: center;
+      font-size: 38px;
+      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;
+    }
+    .el-pagination__goto {
+      font-size: 38px;
+      color: #a7ccdf;
+    }
+  }
+}
+</style>

+ 1 - 3
src/views/globalMap/RightMenu/PotentialFloodHazard.vue

@@ -60,7 +60,6 @@
       </div>
     </div>
   </div>
-  <NearbyVideos v-if="showNearbyVideos" v-model="showNearbyVideos" :location="location" />
   <NearbyVideos v-if="showNearbyVideos2" v-model="showNearbyVideos2" :getDataMethod="getDataMethod" />
 </template>
 
@@ -84,7 +83,7 @@ const dataList = ref([]);
 const showNearbyVideos = ref(false);
 const showNearbyVideos2 = ref(false);
 const getDataMethod = ref(null);
-let location = ref([]);
+
 const initData = () => {
   getWaterloggedRoadsList(queryParams).then((res) => {
     dataList.value = res.data.list;
@@ -99,7 +98,6 @@ const showMoreVideos = () => {
   showNearbyVideos2.value = true;
 };
 const handleShowDialog = (item) => {
-  location.value = [item.lng, item.lat];
   showDetail(item, 4);
 };
 let timeArr = ref([]);

+ 173 - 0
src/views/globalMap/RightMenu/RescueTeam.vue

@@ -0,0 +1,173 @@
+<template>
+  <div class="menu-content">
+    <div class="container">
+      <div class="gradient-text title">救援队伍</div>
+      <div class="box-left">
+        <el-input v-model="queryParams.query.keyword" class="custom-input" placeholder="搜索" @input="initData">
+          <template #prefix>
+            <el-icon class="el-input__icon"><search /></el-icon>
+          </template>
+        </el-input>
+        <div class="btn" @click="handleCancel">取消</div>
+      </div>
+      <div class="custom-table">
+        <div class="th">
+          <div class="td">救援人员单位</div>
+          <div class="td">名称</div>
+          <div class="td" style="width: 280px; flex: unset">操作</div>
+        </div>
+        <div class="table-content">
+          <div v-for="(item, index) in listData" :key="index" class="tr">
+            <div class="td">{{ item.name }}</div>
+            <div class="td">{{ item.team_type }}</div>
+            <div class="td" style="width: 280px; flex: unset">
+              <div class="btn-text" @click="handleShowDetail(item)">详情</div>
+              <div class="line">|</div>
+              <div class="btn-text" @click="handleShowPeople(item)">人员</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <EmergencyCrew v-if="showDialog" :id="id" v-model="showDialog" />
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { Search } from '@element-plus/icons-vue';
+import EmergencyCrew from '@/views/globalMap/RightMenu/EmergencyCrew.vue';
+import { getRescueTeamsList } from '@/api/globalMap/rescueTeam';
+
+const queryParams = reactive({
+  query: {
+    keyword: ''
+  }
+});
+
+const showDetail = inject('showDetail');
+const listData = ref([]);
+let id = ref('');
+
+let showDialog = ref(false);
+const handleShowPeople = (item) => {
+  id.value = item.id;
+  showDialog.value = true;
+};
+const handleShowDetail = (item) => {
+  showDetail(
+    {
+      id: item.id,
+      lat: item.latitude,
+      lng: item.longitude
+    },
+    41
+  );
+};
+const initData = () => {
+  getRescueTeamsList(queryParams).then((res) => {
+    listData.value = res.rows;
+  });
+};
+const handleCancel = () => {
+  queryParams.query.keyword = '';
+  initData();
+};
+initData();
+</script>
+
+<style lang="scss" scoped>
+.menu-content {
+  width: 1579px;
+  height: 1394px;
+  background: url('@/assets/images/map/rightMenu/content.png') no-repeat;
+  padding: 130px 20px 20px 20px;
+  font-size: 36px;
+  position: relative;
+  color: #ffffff;
+}
+.title {
+  font-size: 60px;
+  position: absolute;
+  top: 30px;
+  left: 160px;
+}
+.custom-table {
+  width: 100%;
+  .table-content {
+    height: 880px;
+    overflow-y: auto;
+    overflow-x: hidden;
+  }
+  .th {
+    width: 100%;
+    height: 151px;
+    background: url('@/assets/images/map/rightMenu/th.png') no-repeat;
+    background-size: 100% 100%;
+    display: flex;
+  }
+  .tr {
+    height: 139px;
+    background: url('@/assets/images/map/rightMenu/td.png') no-repeat;
+    background-size: 100% 100%;
+    //margin-left: -23px;
+    display: flex;
+    padding-right: 20px;
+    &:hover {
+      background: url('@/assets/images/map/rightMenu/td_checked.png') no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+  .td {
+    flex: 1;
+    color: #edfaff;
+    font-size: 38px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    cursor: pointer;
+  }
+  .td-text {
+    /* 设置字体透明 */
+    color: transparent;
+    /* 使用 -webkit-background-clip 属性将背景剪裁至文本形状 */
+    -webkit-background-clip: text;
+    /* 非Webkit内核浏览器需要使用标准前缀 */
+    background-clip: text;
+    font-family: 'YouSheBiaoTiHei';
+    /* 设置线性渐变,从红色渐变到蓝色 */
+    background-image: linear-gradient(to bottom, #ffffff 50%, #3075d3 100%);
+    font-size: 48px;
+  }
+  .text-green {
+    background-image: linear-gradient(to bottom, #ffffff 50%, #40c75f 100%);
+  }
+  .text-danger {
+    background-image: linear-gradient(to bottom, #ffffff 50%, #ff2f3c 100%);
+  }
+}
+.box-left {
+  display: flex;
+  align-items: center;
+  margin-top: 20px;
+  margin-bottom: 20px;
+  .btn {
+    width: 140px;
+    min-width: 140px;
+    height: 56px;
+    background: url('@/assets/images/map/rightMenu/potentialFloodHazard/btn.png') no-repeat;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    cursor: pointer;
+    margin-left: 20px;
+  }
+}
+.btn-text {
+  color: #5983df;
+  cursor: pointer;
+}
+.line {
+  color: #5983df;
+  margin: 0 20px;
+}
+</style>

+ 6 - 3
src/views/globalMap/RightMenu/Reservoir.vue

@@ -110,27 +110,29 @@ initData();
   left: 160px;
 }
 .custom-table {
-  width: 1499px;
+  width: 100%;
   .table-content {
     height: 880px;
     overflow-y: auto;
     overflow-x: hidden;
   }
   .th {
-    width: 1499px;
+    width: 100%;
     height: 151px;
     background: url('@/assets/images/map/rightMenu/th.png') no-repeat;
+    background-size: 100% 100%;
     display: flex;
   }
   .tr {
-
     height: 139px;
     background: url('@/assets/images/map/rightMenu/td.png') no-repeat;
+    background-size: 100% 100%;
     //margin-left: -23px;
     display: flex;
     padding-right: 20px;
     &:hover {
       background: url('@/assets/images/map/rightMenu/td_checked.png') no-repeat;
+      background-size: 100% 100%;
     }
   }
   .td {
@@ -163,6 +165,7 @@ initData();
 }
 .box-left {
   display: flex;
+  align-items: center;
   margin-top: 20px;
   margin-bottom: 20px;
   .btn {

+ 6 - 2
src/views/globalMap/RightMenu/RoadNetworkVideo.vue

@@ -134,26 +134,29 @@ initData();
   left: 160px;
 }
 .custom-table {
-  width: 1499px;
+  width: 100%;
   .table-content {
     height: 570px;
     overflow-y: auto;
     overflow-x: hidden;
   }
   .th {
-    width: 1499px;
+    width: 100%;
     height: 151px;
     background: url('@/assets/images/map/rightMenu/th.png') no-repeat;
+    background-size: 100% 100%;
     display: flex;
     padding: 20px;
   }
   .tr {
     height: 139px;
     background: url('@/assets/images/map/rightMenu/td.png') no-repeat;
+    background-size: 100% 100%;
     display: flex;
     padding: 20px;
     &:hover {
       background: url('@/assets/images/map/rightMenu/td_checked.png') no-repeat;
+      background-size: 100% 100%;
     }
   }
   .td {
@@ -186,6 +189,7 @@ initData();
 }
 .box-left {
   display: flex;
+  align-items: center;
   margin-top: 20px;
   margin-bottom: 20px;
   .btn {

+ 7 - 3
src/views/globalMap/RightMenu/index.vue

@@ -7,19 +7,20 @@
             v-for="(item, index) in menuState.menuData"
             :key="index"
             :class="menuState.activeIndex === index ? 'menu-item menu-active' : 'menu-item'"
+            style="pointer-events: auto"
             @click="clickMenu(index)"
           >
             <div :class="item.meta?.icon + ' ' + item.meta?.icon + '_checked'"></div>
             <div class="gradient-text text">{{ item.name }}</div>
           </div>
         </div>
-        <div v-show="menuState.menuData.length > 0" :class="menuState.showMenu ? 'right-btn' : 'left-btn'" @click="clickContractMenu"></div>
-        <div v-show="menuState.menuData.length > 7" class="btn-box">
+        <div v-show="menuState.menuData.length > 0" :class="menuState.showMenu ? 'right-btn' : 'left-btn'" style="pointer-events: auto" @click="clickContractMenu"></div>
+        <div v-show="menuState.menuData.length > 7" class="btn-box" style="pointer-events: auto">
           <div class="up-btn" @click="clickBtn('up')"></div>
           <div class="down-btn" @click="clickBtn('down')"></div>
         </div>
       </div>
-      <div v-show="menuState.showMenu">
+      <div v-show="menuState.showMenu" style="pointer-events: auto">
         <!--图层分析-->
         <LayerAnalysis v-if="menuState.showMenu && menuState.menuData[menuState.activeIndex]?.name === '图层分析'" :point-type="pointType" />
         <!--空间分析-->
@@ -81,6 +82,7 @@
         <Helicopter v-if="menuState.showMenu && menuState.menuData[menuState.activeIndex]?.name === '直升机'" @handle-menu="handleMenu" />
         <!--台风视频-->
         <TyphoonVideo v-if="menuState.showMenu && menuState.menuData[menuState.activeIndex]?.name === '台风视频'" @handle-menu="handleMenu" />
+        <RescueTeam v-if="menuState.showMenu && menuState.menuData[menuState.activeIndex]?.name === '救援队伍'" />
       </div>
     </div>
   </div>
@@ -112,6 +114,7 @@ import MobileUnmannedVehicle from './MobileUnmannedVehicle.vue';
 import MobileCommandVehicle from './MobileCommandVehicle.vue';
 import Helicopter from './Helicopter.vue';
 import TyphoonVideo from './TyphoonVideo.vue';
+import RescueTeam from './RescueTeam.vue';
 interface Props {
   pointType: PointType[];
 }
@@ -220,6 +223,7 @@ defineExpose({ handleMenu, showIndexMenu, clickContractMenu, updateMenu, getMenu
   top: 100px;
   right: 0;
   z-index: 20;
+  pointer-events: none;
 }
 .expand-btn {
   width: 70px;

+ 24 - 0
src/views/globalMap/data/mapData.ts

@@ -4297,6 +4297,11 @@ export const iconList = {
     imageHover: getImageUrl('31_lakes_video_hover.png'),
     size: [40, 40]
   },
+  '41': {
+    image: getImageUrl('41_rescue_team.png'),
+    imageHover: getImageUrl('41_rescue_team_hover.png'),
+    size: [55, 60]
+  }
 };
 
 export const pointDetailTemplate = {
@@ -4931,6 +4936,25 @@ export const pointDetailTemplate = {
     jt_cd_operation: '增量标识',
     line_name: '线路名称'
   },
+  '41': {
+    name: '救援队伍名称',
+    team_type: '救援队伍类型',
+    professional_category: '队伍专业类别',
+    team_category: '队伍类别',
+    team_attribute: '队伍属性',
+    team_level: '队伍层级',
+    affiliated_unit: '所属单位',
+    leader_name: '负责人姓名',
+    leader_phone: '负责人联系电话',
+    city: '地市',
+    district: '区县',
+    main_equipment: '主要装备',
+    number_of_people: '人数',
+    address: '地址',
+    description: '描述',
+    longitude: '经度',
+    latitude: '纬度'
+  }
 };
 
 export const creatDetailTemplate = (data, type) => {};

+ 24 - 2
src/views/globalMap/index.vue

@@ -15,6 +15,7 @@
         :point-type="pointType"
         @handle-show-video="handleShowVideo"
         @handle-show-warehouse="handleShowWarehouse"
+        @handleShowPeople="handleShowPeople"
       />
       <!--左侧菜单-->
       <LeftMenu
@@ -34,6 +35,7 @@
       <GridPointRainfall v-if="showRainfall" v-model="showRainfall" :location="location" />
       <MaterialDetail v-if="showWarehouse" v-model="showWarehouse" :warehouse-data="warehouseData" />
       <CommunicationSupport v-if="communicationSupport.show" @close="handleHideCommunicationSupport" />
+      <EmergencyCrew v-if="showPeople" v-model="showPeople" :id="teamId" />
     </div>
   </div>
 </template>
@@ -54,7 +56,7 @@ import { PointType } from '@/api/globalMap/type';
 import DrawTools from '@/views/globalMap/RightMenu/DrawTools.vue';
 import CommunicationSupport from '@/views/globalMap/RightMenu/CommunicationSupport.vue';
 import GridPointRainfall from '@/views/globalMap/RightMenu/GridPointRainfall.vue';
-import FixedPointAnalysis from '@/views/globalMap/RightMenu/FixedPointAnalysis.vue';
+import EmergencyCrew from '@/views/globalMap/RightMenu/EmergencyCrew.vue';
 
 const rightMenuRef = ref(null);
 const mapData = reactive(logicalData);
@@ -150,7 +152,19 @@ const clickMenu = (item, dataList) => {
     addMarkers(item);
 
     if (
-      ['易涝隐患点', '无人机', '铁塔运行监测', '物资与装备', '通讯保障', '路网视频', '江湖河库', '防溺水', '森林防火', '防灾救援'].includes(item.name)
+      [
+        '易涝隐患点',
+        '无人机',
+        '铁塔运行监测',
+        '物资与装备',
+        '通讯保障',
+        '路网视频',
+        '江湖河库',
+        '防溺水',
+        '森林防火',
+        '防灾救援',
+        '救援队伍'
+      ].includes(item.name)
     ) {
       rightMenuRef.value.updateMenu(checked, item);
     } else {
@@ -318,6 +332,14 @@ const handleShowWarehouse = (data) => {
   warehouseData.value = data;
   showWarehouse.value = true;
 };
+
+// 救援队伍人员列表
+let showPeople = ref(false);
+let teamId = ref('');
+const handleShowPeople = (data) => {
+  teamId.value = data.id;
+  showPeople.value = true;
+};
 // onMounted(() => {
 //   mapRef.value.addEventListener('resize', handleResize);
 // })