소스 검색

实时标绘 调整、应急态

Hwf 8 달 전
부모
커밋
588ef66bc0

+ 43 - 0
src/api/globalMap/onlinePlotting.ts

@@ -0,0 +1,43 @@
+
+import request from '@/utils/request';
+
+// 获取预案列表
+export const getPatternList = (params) => {
+  return request({
+    url: '/api/pattern/list',
+    method: 'get',
+    params: params
+  });
+};
+// 删除预案
+export const deletePatternById = (id) => {
+  return request({
+    url: '/api/pattern/delete/' + id,
+    method: 'delete'
+  });
+};
+
+// 获取预案信息
+export const getPatternInfo = (id) => {
+  return request({
+    url: '/api/pattern/info/' + id,
+    method: 'get'
+  });
+};
+// 预案更新
+export const updatePatternInfo = (id, data) => {
+  return request({
+    url: '/api/pattern/update/' + id,
+    method: 'put',
+    data: data
+  });
+};
+
+// 预案更新
+export const createPattern = (data) => {
+  return request({
+    url: '/api/pattern/create',
+    method: 'put',
+    data: data
+  });
+};

BIN
src/assets/images/video/fullscreen.png


+ 25 - 1
src/components/HKVideo/index.vue

@@ -10,6 +10,7 @@
       ></HikvisionPlayer>
       <img v-if="posterVisible" class="video-play" src="@/assets/images/video/play.png" alt="" />
       <img v-if="posterVisible && dot_data.poster" class="video-poster" :src="dot_data.poster" />
+      <img v-if="isPlaying" class="fullscreen" src="@/assets/images/video/fullscreen.png" @click.stop="handleFullScreen" />
       <div v-if="errBKVisible" class="err_bk">
         <div class="err_box">
           <div class="err_inner_box">
@@ -103,6 +104,20 @@ const stop_now = async () => {
   }
   posterVisible.value = true;
 };
+
+const videoElement = ref();
+const isFullscreen = ref(false);
+const handleFullScreen = () => {
+  if (!document.fullscreenElement && !isFullscreen.value) {
+    videoElement.value.requestFullscreen();
+    isFullscreen.value = true;
+  } else {
+    if (document.exitFullscreen) {
+      document.exitFullscreen();
+    }
+    isFullscreen.value = false;
+  }
+};
 </script>
 
 <style lang="scss" scoped>
@@ -136,7 +151,16 @@ const stop_now = async () => {
     transform: translate(-50%, -50%);
     cursor: pointer;
   }
-
+  .fullscreen {
+    width: 28px;
+    height: 28px;
+    background: url('@/assets/images/video/fullscreen.png');
+    cursor: pointer;
+    position: absolute;
+    top: 20px;
+    right: 20px;
+    z-index: 10;
+  }
   .err_bk {
     z-index: 999;
     left: 0;

+ 1 - 1
src/components/Map/MapLogical.vue

@@ -4,7 +4,7 @@
 
     </div>
     <div class="chassis"></div>
-    <div :style="{ width: mapState[mapState.active].width + 'px', height: mapState[mapState.active].height + 'px', position: 'relative' }">
+    <div :style="{ width: mapState[mapState.active].width + 'px', height: mapState[mapState.active].height + 'px', position: 'relative', pointerEvents: none }">
       <img :src="mapState[mapState.active].img" alt="" />
       <div v-show="mapState.active === 'layersData'">
         <div

+ 2 - 0
src/types/components.d.ts

@@ -48,6 +48,8 @@ declare module 'vue' {
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
+    ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
+    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElSlider: typeof import('element-plus/es')['ElSlider']
     ElStep: typeof import('element-plus/es')['ElStep']
     ElSteps: typeof import('element-plus/es')['ElSteps']

+ 6 - 5
src/utils/olMap/olMap.ts

@@ -113,12 +113,13 @@ export class olMap {
     //   '<wfs:QuerytypeName="GDSMMSZJGZDTJX_2023"userecent="true"/>\n' +
     //   '</wfs:GetFeature>');
     return this.getCapabilities(code).then((lists) => {
-      const mapData = xml.read(lists.data);
+      const geojson = xml.read(lists.data);
+      const data = geojson.Contents.Layer[0];
       const layerParam = {
-        layerName: mapData.Contents.Layer[0].Title,
-        styleName: mapData.Contents.Layer[0].Style[0].Identifier,
-        tilematrixset: mapData.Contents.TileMatrixSet[0].Identifier,
-        format: mapData.Contents.Layer[0].Format[0]
+        layerName: data.Abstract,
+        styleName: data.Identifier,
+        tilematrixset: data.TileMatrixSetLink[0].TileMatrixSet,
+        format: data.Format[0]
       };
       this.createWmsLayer(code, layerParam, minZoom, maxZoom, zIndex, visible);
     });

+ 11 - 0
src/views/emergencyCommandMap/LeftSection/Communication.vue

@@ -0,0 +1,11 @@
+<template>
+  前方通信
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 15 - 30
src/views/emergencyCommandMap/LeftSection/VideoMonitor.vue

@@ -4,13 +4,9 @@
     <div class="more-btn" @click="showVideoMonitorList">查看更多</div>
     <div class="card-content video-list">
       <div v-for="(item, index) in listData" :key="index" class="video-box">
-        <div class="video-content">
-          <div style="width: 733px; height: 300px; position: relative">
-            <HKVideo :dot_data="item" :width="733" :height="300" />
-            <div class="video-label">
-              <span class="label">{{ item.name }}</span>
-            </div>
-          </div>
+        <HKVideo :dot_data="item" :width="560" :height="256" />
+        <div class="video-label">
+          <span class="label">{{ item.name }}</span>
         </div>
       </div>
     </div>
@@ -76,12 +72,7 @@
 </template>
 
 <script lang="ts" setup name="VideoMonitor">
-import {
-  getEmergencyVideoCata,
-  getUserVideoPoints,
-  getVideoListByUser,
-  updateUserVideoPoints
-} from '@/api/videoMonitor';
+import { getEmergencyVideoCata, getUserVideoPoints, getVideoListByUser, updateUserVideoPoints } from '@/api/videoMonitor';
 import { deepClone } from '@/utils';
 
 const proxy = getCurrentInstance()?.proxy;
@@ -208,6 +199,10 @@ const handleSave = () => {
       background: url('@/assets/images/video/videoBg.png') no-repeat;
       background-size: 100% 100%;
       padding: 14.5px 9px;
+      position: relative;
+      display: flex;
+      align-items: center;
+      justify-content: center;
       &:nth-child(1),
       &:nth-child(2),
       &:nth-child(3) {
@@ -217,26 +212,16 @@ const handleSave = () => {
       &:nth-child(6) {
         margin-right: 0;
       }
-      .video-content {
-        width: 100%;
-        height: 100%;
-        background: url('@/assets/images/emergencyCommandMap/videoBox2.png') no-repeat;
-        background-size: 100% 100%;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        position: relative;
-      }
       .video-label {
         position: absolute;
-        bottom: 0;
-        right: 0;
+        bottom: 17px;
+        right: 8px;
 
         display: flex;
         .label {
-          width: 546px;
-          height: 50px;
-          line-height: 50px;
+          width: 411px;
+          height: 56px;
+          line-height: 56px;
           font-size: 32px;
           white-space: nowrap;
           overflow: hidden;
@@ -249,8 +234,8 @@ const handleSave = () => {
           content: '';
           width: 0;
           height: 0;
-          border-bottom: 50px solid rgba(0, 0, 0, 0.4);
-          border-left: 50px solid transparent;
+          border-bottom: 56px solid rgba(0, 0, 0, 0.4);
+          border-left: 56px solid transparent;
         }
       }
     }

+ 2 - 0
src/views/emergencyCommandMap/LeftSection/index.vue

@@ -94,12 +94,14 @@
       :event-id="eventId"
       @update:model-value="fetchEventDetail"
     />
+    <Communication />
   </div>
 </template>
 <script lang="ts" setup name="LeftSection">
 import { getEventDetail, getWeather } from '@/api/duty/eventing';
 import VideoMonitor from '@/views/emergencyCommandMap/LeftSection/VideoMonitor.vue';
 import { ref, onMounted, onUnmounted, computed } from 'vue';
+import Communication from './Communication.vue';
 import CloseCommand from './CloseCommand.vue';
 
 const route = useRoute();

+ 147 - 4
src/views/globalMap/RightMenu/OnlinePlotting.vue

@@ -8,14 +8,15 @@
   <el-color-picker v-model="mouseToolState.color" popper-class="custom-color-picker" show-alpha size="large" />
   <el-button size="large" @click="changeDrawing">{{ drawing ? '关闭' : '开启' }}</el-button>
   <div class="flex">
-    <div class="draw-item" @click="handleUndo">撤销</div>
+    <div class="draw-item" @click="handleUndo">撤回</div>
+    <div class="draw-item" @click="handleShowDialog">保存</div>
   </div>
   <div class="tabs1">
     <div v-for="(item, index) in menu" :key="index" :class="menuActive1 === index ? 'tab tab_active' : 'tab'" @click="clickTab(index)">
       {{ item.name }}
     </div>
   </div>
-  <div v-show="menuActive1 === 0" class="tab-content">
+  <div v-if="menuActive1 === 0" class="tab-content">
     <div class="tabs2">
       <div
         v-for="(item, index) in menu[menuActive1].children"
@@ -37,7 +38,30 @@
       </div>
     </div>
   </div>
-  <div v-show="menuActive1 === 1" class="tab-content">历史预案</div>
+  <div v-else-if="menuActive1 === 1" class="tab-content3">
+    <div>
+      <div>合并</div>
+    </div>
+    <div>
+      <el-input v-model="queryParams.pattern_name" placeholder="请输入标题关键字" size="large" @keydown.enter="handleQuery" />
+    </div>
+    <div class="custom-table">
+      <div class="tr">
+        <div class="th">预案名称</div>
+        <div class="th">操作</div>
+      </div>
+      <div v-for="(item, index) in patternList" :key="index" class="tr">
+        <div class="td">
+          <div>{{ item.pattern_name }}</div>
+        </div>
+        <div class="td td2">
+          <el-icon class="icon" @click="handleDelete(item.id)"><Delete /></el-icon>
+          <el-icon class="icon" @click="handleEdit(item.id)"><EditPen /></el-icon>
+        </div>
+      </div>
+    </div>
+  </div>
+  <!--添加文字-->
   <div v-show="textEditState.showTextEdit" class="text-edit-container">
     <el-input v-model="textEditState.text" :rows="8" type="textarea" />
     <div class="edit-box">
@@ -57,13 +81,23 @@
   </div>
   <!--绘制提示信息-->
   <div v-show="tipTitle !== ''" class="tipTitle">{{ tipTitle }}</div>
+
+  <Dialog v-model="showEdit" title="编辑" width="450px" height="200px" style="position: fixed; top: 1280px">
+    <el-input v-model="editData.pattern_name" />
+    <div class="footer">
+      <el-button :loading="buttonLoading" type="primary" @click="submitForm">确定</el-button>
+      <el-button @click="cancel">取消</el-button>
+    </div>
+  </Dialog>
 </template>
 
 <script lang="ts" setup>
 import { nanoid } from 'nanoid';
 import { deepClone } from '@/utils';
 import { useHistory } from '@/hooks/useHistory';
+import { deletePatternById, getPatternInfo, getPatternList, updatePatternInfo } from '@/api/globalMap/onlinePlotting';
 
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const getDrawTool = inject('getDrawTool');
 const getMap = inject('getMap');
 const { currentState, commit, undo, history, future } = useHistory();
@@ -193,7 +227,6 @@ const clickTab = (value: number) => {
 const clickTab2 = (value: number) => {
   menuActive2.value = value;
 };
-let drawOptions = {};
 // 点击三级菜单
 const clickTab3 = (item, index) => {
   const type = item.value;
@@ -433,6 +466,72 @@ const removeOverlayByIndex = (index: number) => {
   overlays.splice(index, 1);
   overlaysData.splice(index, 1);
 };
+
+// 历史预案
+const queryParams = reactive({
+  page: 1,
+  pageSize: 10,
+  pattern_name: ''
+});
+const patternList = ref([]);
+let total = ref(0);
+let editData = ref({
+  id: '',
+  pattern_name: ''
+});
+let showEdit = ref(false);
+let buttonLoading = ref(false);
+const handleQuery = () => {
+  queryParams.page = 1;
+  getList();
+};
+const getList = () => {
+  // if (menuActive1.value === 1 && menu.value[menuActive1.value].name == '历史预案') {
+  getPatternList(queryParams).then((res) => {
+    patternList.value = res.data;
+    total.value = res.total;
+  });
+  // }
+};
+const handleDelete = (id: number) => {
+  proxy?.$modal.confirm('是否确认删除选择的数据项?').then(() => {
+    deletePatternById(id).then(() => {
+      getList();
+    });
+  });
+};
+const handleEdit = (id) => {
+  getPatternInfo(id).then((res) => {
+    editData.value = res.data;
+    editData.value.id = id;
+  });
+  showEdit.value = true;
+};
+const submitForm = () => {
+  buttonLoading.value = true;
+  updatePatternInfo(editData.value.id, editData.value)
+    .then((res) => {
+      proxy.$modal.msgSuccess('更新成功');
+      showEdit.value = false;
+      getList();
+    })
+    .finally(() => {
+      buttonLoading.value = false;
+      editData.value = {
+        id: '',
+        pattern_name: ''
+      };
+    });
+};
+
+const cancel = () => {
+  buttonLoading.value = false;
+  showEdit.value = false;
+};
+const handleShowDialog = () => {};
+onMounted(() => {
+  getList();
+});
 </script>
 
 <style lang="scss" scoped>
@@ -518,4 +617,48 @@ const removeOverlayByIndex = (index: number) => {
   background-color: rgba(0, 0, 0, 0.4);
   border-radius: 10px;
 }
+.tab-content3 {
+  .custom-table {
+    width: 100%;
+    .tr {
+      display: flex;
+      font-size: 32px;
+      .th {
+        background-color: #edf2fb;
+        padding: 9px 20px;
+        flex: 1;
+        border-left: 1px solid #dce0e7;
+        border-top: 1px solid #dce0e7;
+        border-bottom: 1px solid #dce0e7;
+        &:last-child {
+          flex: unset;
+          width: 150px;
+          border-right: 1px solid #dce0e7;
+        }
+      }
+      .td {
+        background-color: #ffffff;
+        padding: 9px 20px;
+        flex: 1;
+        border-left: 1px solid #dce0e7;
+        border-top: 1px solid #dce0e7;
+        border-bottom: 1px solid #dce0e7;
+        &:last-child {
+          flex: unset;
+          width: 150px;
+          border-right: 1px solid #dce0e7;
+        }
+        .icon {
+          margin: 0 10px;
+          cursor: pointer;
+        }
+      }
+    }
+  }
+}
+.footer {
+  margin-top: 20px;
+  display: flex;
+  justify-content: flex-end;
+}
 </style>