Browse Source

视频监控

Hwf 2 tháng trước cách đây
mục cha
commit
0bd04e57df

BIN
src/assets/images/map/tag2.png


BIN
src/assets/images/videoTagEdit/box1.png


BIN
src/assets/images/videoTagEdit/btn.png


BIN
src/assets/images/videoTagEdit/close.png


BIN
src/assets/images/videoTagEdit/industry.png


BIN
src/assets/images/videoTagEdit/line1.png


BIN
src/assets/images/videoTagEdit/line2.png


BIN
src/assets/images/videoTagEdit/type.png


+ 25 - 14
src/components/Dialog/index.vue

@@ -6,12 +6,12 @@
     :style="{ width: computedWidth, height: computedHeight, zIndex: zIndex }"
   >
     <div :class="type === 'xs' || headerType === 'header2' ? 'dialog-header2' : 'dialog-header'">
-      <div v-if="!hideTitle" class="dialog-title">
+      <div v-if="!hideTitle" class="dialog-title" :title="title ? title : '弹窗'">
         {{ title ? title : '弹窗' }}
       </div>
       <div v-if="!!getTagId" class="tags">
         <div v-for="(item, index) in tags" :key="index" class="tag">{{ item.dict_label }}</div>
-        <div class="add-tag" @click="handleShowAddTag">+添加标签</div>
+        <i :class="tags && tags.length > 0 ? 'collectFill' : 'collect'" @click="handleShowAddTag" />
       </div>
       <i class="decoration" />
       <i class="dialog-close" @click="closeDialog" />
@@ -30,8 +30,8 @@
     <i class="triangle2" />
     <i class="triangle3" />
     <i class="triangle4" />
-    <VideoTagEdit v-model="showAddTag" :tags="tags" :id="getTagId" @updateVideoTag="getData" />
   </div>
+  <VideoTagEdit v-if="showAddTag" v-model="showAddTag" :tags="tags" :id="getTagId" @updateVideoTag="getData(true)" />
 </template>
 
 <script lang="ts" setup name="Dialog">
@@ -39,7 +39,8 @@ import { getVideoTagInfo } from '@/api/videoMonitor';
 import useAppStore from '@/store/modules/app';
 
 interface Tag {
-  name: string;
+  dict_label: string;
+  dict_value: string;
 }
 // type: xs、sm、md、lg、xl
 interface Props {
@@ -67,7 +68,7 @@ const props = withDefaults(defineProps<Props>(), {
   confirmText: '确定',
   hideFooter: false
 });
-const emit = defineEmits(['update:modelValue', 'close', 'confirm']);
+const emit = defineEmits(['update:modelValue', 'close', 'confirm', 'changeTagsData']);
 const computedWidth = computed(() => {
   if (!!props.width) {
     return props.width;
@@ -134,9 +135,12 @@ let showAddTag = ref(false);
 const handleShowAddTag = () => {
   showAddTag.value = true;
 };
-const getData = () => {
+const getData = (needUpdate?: boolean) => {
   getVideoTagInfo({ video_code: props.getTagId }).then((res) => {
     tags.value = res.data;
+    if (!!needUpdate) {
+      emit('changeTagsData', res.data);
+    }
   });
 };
 onMounted(() => {
@@ -180,6 +184,9 @@ onMounted(() => {
       font-family: 'YouSheBiaoTiHei';
       font-size: 24px;
       padding-left: 25px;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
     }
     .dialog-close {
       position: absolute;
@@ -248,16 +255,20 @@ onMounted(() => {
         justify-content: center;
         align-items: center;
       }
-      .add-tag {
-        width: 104px;
-        height: 29px;
-        background: url('@/assets/images/map/rightMenu/btn.png') no-repeat;
+      .collect {
+        background: url('@/assets/images/video/collect.png') no-repeat;
+      }
+      .collectFill {
+        background: url('@/assets/images/video/collectFill.png') no-repeat;
+      }
+      .collect,
+      .collectFill {
+        width: 20px;
+        height: 20px;
+        cursor: pointer;
         background-size: 100% 100%;
-        margin-left: 12px;
-        display: flex;
-        align-items: center;
-        justify-content: center;
         cursor: pointer;
+        margin-left: 6px;
       }
     }
     &::before {

+ 9 - 3
src/components/HKVideo/hikvision-h5player.vue

@@ -2,7 +2,7 @@
   <div class="player-box">
     <div :id="state.id" class="playWnd"></div>
     <div v-show="state.isLoading" class="loader"></div>
-    <img v-if="!state.isLoading" class="video-enlarge" src="@/assets/images/video/enlarge.png" alt="" @click="fullScreen" />
+    <img v-if="!state.isLoading && !hideEnlarge" class="video-enlarge" src="@/assets/images/video/enlarge.png" alt="" @click="fullScreen" />
   </div>
 </template>
 
@@ -10,6 +10,10 @@
 import { reactive, onMounted, onActivated, nextTick, onBeforeUnmount } from 'vue';
 import { parseTime } from '@/utils/ruoyi';
 
+const props = defineProps({
+  hideEnlarge: Boolean
+});
+
 const play = async (url) => {
   state.wsUrl = url;
   realplay(url);
@@ -216,6 +220,7 @@ defineExpose({
   stop,
   playback,
   handleScreenshot,
+  fullScreen,
   getPlayer
 });
 </script>
@@ -244,8 +249,9 @@ defineExpose({
   .loader {
     position: absolute;
     z-index: 10;
-    left: calc(1000% - 32px) / 2;
-    top: calc(1000% - 32px) / 2;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
     width: 32px;
     height: 32px;
     background: url('@/assets/images/video/ajax-loader.gif');

+ 9 - 7
src/components/HKVideo/index.vue

@@ -38,8 +38,11 @@ const play = () => {
 };
 
 const refresh_data = () => {
-  console.log('refresh_data');
-  play_now();
+  reload.value = true;
+  nextTick(() => {
+    reload.value = false;
+    play_now();
+  });
 };
 
 const emits = defineEmits(['propClick', 'videoPreviewClick', 'favorClick']);
@@ -98,10 +101,6 @@ watch(
 );
 const play_now = async (check?: boolean) => {
   posterVisible.value = false;
-  // if (check === true && props.dot_data.status === '离线') {
-  //   errBKVisible.value = true;
-  //   isPlaying.value = false;
-  // } else {
   errBKVisible.value = false;
   isPlaying.value = true;
   // 视频监控数据
@@ -109,7 +108,6 @@ const play_now = async (check?: boolean) => {
     wsUrl.value = res.data;
     videoPlayer.value.play(wsUrl.value);
   });
-  // }
   console.log('play_now');
 };
 
@@ -121,6 +119,9 @@ const stop_now = async () => {
   }
   posterVisible.value = true;
 };
+const handleFullScreen = (name) => {
+  videoPlayer.value.fullScreen(name);
+};
 const handleScreenshot = (name) => {
   videoPlayer.value.handleScreenshot(name);
 };
@@ -131,6 +132,7 @@ defineExpose({
   play,
   refresh_data,
   handleScreenshot,
+  handleFullScreen,
   getPlayer
 });
 onMounted(() => {

+ 1 - 1
src/components/HKVideo/index2.vue

@@ -39,7 +39,7 @@
     <!--收藏弹窗-->
     <VideoTagEdit v-if="showCollectDialog" :id="dot_data.id" v-model="showCollectDialog" :tags="tags" @update-video-tag="getData2" />
     <!--点击全屏弹窗-->
-    <video-dialog v-if="showFullScreenDialog" v-model="showFullScreenDialog" :videoMonitorData="dot_data" @changeTagsData="getData" />
+    <video-dialog v-if="showFullScreenDialog" v-model="showFullScreenDialog" height="680px" :videoMonitorData="dot_data" @changeTagsData="getData" />
   </div>
 </template>
 

+ 110 - 256
src/components/VideoTagEdit/index.vue

@@ -1,288 +1,142 @@
 <template>
-  <div v-show="modelValue" class="edit-container">
-    <div class="edit-header">
-      <div class="title">视频标签</div>
-      <i class="close" @click="handleClose" />
+  <Dialog v-model="show" title="视频标签" height="auto" @close="handleClose" @confirm="handleAdd">
+    <div class="title-box">
+      <div class="title">当前标签</div>
     </div>
-    <div class="edit-content">
-      <div class="title-box">
-        <div class="title">当前标签</div>
-      </div>
-      <div class="tags">
-        <div v-for="(item, index) in tags" :key="index" class="tag">{{ item.dict_label }}</div>
-      </div>
-      <div class="title-box">
-        <div class="title">新增标签</div>
-      </div>
-      <div class="tags">
-        <el-select
-          v-model="addTag2"
-          :teleported="false"
-          class="custom-select"
-          popper-class="custom-select-popper"
-          style="width: 300px; margin-left: 10px"
-        >
-          <el-option v-for="item in video_type" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-        <div class="common-btn-primary" @click="handleAdd3">添加</div>
-      </div>
-      <div class="title-box">
-        <div class="title">新建标签</div>
-      </div>
-      <div class="tags">
-        <div class="tag">{{ addTag }}</div>
-        <el-input v-model="addTag" class="custom-input" placeholder="不超过20个字,回车添加" @keyup.enter="handleAdd"></el-input>
-      </div>
-      <div class="title-box2">
-        <div class="title">最近标签</div>
-      </div>
-      <div class="tags">
-        <div v-for="(item, index) in recentTags" :key="index" class="tag" @click="handleAdd2(item)">{{ item.dict_label }}</div>
-      </div>
-      <div class="title-box3">
-        <i class="icon-type" />
-        <div class="title">类型</div>
-        <el-select
-          v-model="type"
-          :teleported="false"
-          class="custom-select"
-          popper-class="custom-select-popper"
-          style="width: 140px; margin-bottom: 10px"
-        >
-          <el-option label="全部" value="lx" />
-          <el-option v-for="item in video_tag_type" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-      </div>
-      <div class="tags">
-        <div v-for="(item, index) in typeTags" :key="index" class="tag" @click="handleAdd2(item)">{{ item.dict_label }}</div>
-      </div>
-      <div class="title-box3">
-        <i class="icon-industry" />
-        <div class="title">行业</div>
-        <el-select
-          v-model="industry"
-          :teleported="false"
-          class="custom-select"
-          popper-class="custom-select-popper"
-          style="width: 140px; margin-bottom: 10px"
-        >
-          <el-option label="全部" value="hy" />
-          <el-option v-for="item in video_tag_industry" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-      </div>
-      <div class="tags">
-        <div v-for="(item, index) in industryTags" :key="index" class="tag" @click="handleAdd2(item)">{{ item.dict_label }}</div>
+    <div v-if="selectTags && selectTags.length > 0" class="tags">
+      <div v-for="(item, index) in selectTags" :key="index" class="tagActive">{{ item.label }}</div>
+    </div>
+    <div v-else class="empty-text">暂无标签</div>
+    <div class="title-box" style="margin-top: 20px">
+      <div class="title">添加标签</div>
+    </div>
+    <div class="tags">
+      <div v-for="item in videoType" :key="item.value" :class="!!item.checked ? 'tagActive' : 'tag'" @click="handleSelect(item)">
+        {{ item.label }}
       </div>
     </div>
-  </div>
+  </Dialog>
 </template>
 
 <script lang="ts" setup name="VideoTagEdit">
-import { addVideoTag, addVideoTagLabel, getLxHyVideoTagInfo, getRecentlyVideoTagInfo } from '@/api/videoMonitor';
-import { showSuccessMsg } from '@/utils/notification';
+import { addVideoTag } from '@/api/videoMonitor';
+import { getDicts } from '@/api/system/dict/data';
 
-const props = defineProps({
-  modelValue: Boolean,
-  tags: [],
-  id: String
-});
-const emits = defineEmits(['update:modelValue', 'updateVideoTag']);
-const proxy = getCurrentInstance()?.proxy;
-const { video_type, video_tag_type, video_tag_industry } = toRefs<any>(proxy?.useDict('video_type', 'video_tag_type', 'video_tag_industry'));
-let addTag = ref('');
-let addTag2 = ref('');
-let recentTags = ref([]);
-let type = ref('lx');
-let typeTags = ref([]);
-let industry = ref('hy');
-let industryTags = ref([]);
+interface Tag {
+  dict_label: string;
+  dict_value: string;
+}
+interface Props {
+  modelValue: boolean;
+  tags: Tag[];
+  id: string;
+}
 
-const getTypeList = () => {
-  getLxHyVideoTagInfo({ dict_value: type.value }).then((res) => {
-    typeTags.value = res.data;
-  });
-};
-const getIndustryList = () => {
-  getLxHyVideoTagInfo({ dict_value: industry.value }).then((res) => {
-    industryTags.value = res.data;
-  });
-};
-watch(
-  () => props.id,
-  () => {
-    if (!!props.id) {
-      getRecentlyVideoTagInfo().then((res) => {
-        recentTags.value = res.data;
-      });
-      getTypeList();
-      getIndustryList();
-    } else {
-      addTag.value = '';
-      recentTags.value = [];
-      typeTags.value = [];
-      industryTags.value = [];
-    }
+const props = defineProps<Props>();
+const emits = defineEmits(['update:modelValue', 'updateVideoTag']);
+let videoType = ref([]);
+const show = computed({
+  get() {
+    return props.modelValue;
   },
-  {
-    immediate: true
+  set(newValue) {
+    emits('update:modelValue', newValue);
   }
-);
+});
+let selectTags = ref([]);
+
 //关闭
 const handleClose = () => {
   emits('update:modelValue', false);
 };
+// 选择
+const handleSelect = (item) => {
+  item.checked = !item.checked;
+  const index = selectTags.value.findIndex((item2) => item2.value === item.value);
+  if (!!item.checked) {
+    if (index === -1) {
+      selectTags.value.push(item);
+    }
+  } else {
+    if (index >= 0) {
+      selectTags.value.splice(index, 1);
+    }
+  }
+};
 const handleAdd = () => {
-  addVideoTagLabel({
-    video_code: props.id,
-    dict_label: addTag.value,
-    dict_type: 'video_type'
-  }).then(() => {
-    proxy.$modal.msgSuccess('新增成功');
-    emits('updateVideoTag');
+  const tagsId = [];
+  selectTags.value.forEach((item) => {
+    tagsId.push(item.value);
   });
-  addTag.value = '';
-};
-const handleAdd2 = (item) => {
-  addVideoTag({ video_code: props.id, dict_value: item.dict_value, dict_type: 'video_type' }).then(() => {
-    proxy.$modal.msgSuccess('新增成功');
+  addVideoTag({ video_code: props.id, dict_value: tagsId, dict_type: 'video_type' }).then(() => {
+    showSuccessMsg('新增成功');
     emits('updateVideoTag');
+    handleClose();
   });
 };
-const handleAdd3 = () => {
-  addVideoTag({ video_code: props.id, dict_value: addTag2.value, dict_type: 'video_type' }).then(() => {
-    proxy.$modal.msgSuccess('新增成功');
-    emits('updateVideoTag');
+
+const getTagList = () => {
+  getDicts('video_type').then((res) => {
+    let data = [];
+    let data2 = [];
+    res.data.forEach((item) => {
+      const checked = !!props.tags && props.tags.findIndex((item2) => item2.dict_value === item.dictValue) > -1;
+      const obj = { label: item.dictLabel, value: item.dictValue, checked: checked };
+      if (!!checked) {
+        data2.push(obj);
+      }
+      data.push(obj);
+    });
+    videoType.value = data;
+    selectTags.value = data2;
   });
 };
+onMounted(() => {
+  getTagList();
+});
 </script>
 
 <style lang="scss" scoped>
-.edit-container {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  z-index: 100;
-  width: 407px;
-  height: 602px;
-  background: url('@/assets/images/videoTagEdit/box1.png') no-repeat;
+.title-box {
+  width: 379px;
+  height: 39px;
+  background: url('@/assets/images/map/titleBox3.png') no-repeat;
   background-size: 100% 100%;
-  .edit-header {
-    height: 40px;
+  padding-left: 22px;
+  .title {
+    font-size: 16px;
+    font-weight: bold;
+    padding-top: 6px;
+    padding-left: 3px;
+  }
+}
+.tags {
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  margin-top: -5px;
+  .tag {
+    background: url('@/assets/images/map/tag2.png') no-repeat;
+  }
+  .tagActive {
+    background: url('@/assets/images/map/tag.png') no-repeat;
+  }
+  .tag,
+  .tagActive {
+    min-width: 146px;
+    height: 30px;
+    background-size: 100% 100%;
     display: flex;
-    justify-content: space-between;
     align-items: center;
-    padding: 0 20px;
-    position: relative;
-    .title {
-      color: transparent;
-      background-image: linear-gradient(to bottom, #ffffff 30%, #edf7fe 50%, #5cc4fa 70%, #40a2e7 100%);
-      -webkit-background-clip: text;
-      background-clip: text;
-      display: inline-block;
-      font-family: 'YouSheBiaoTiHei';
-      font-size: 24px;
-    }
-    .close {
-      width: 16px;
-      height: 16px;
-      background: url('@/assets/images/videoTagEdit/close.png') no-repeat;
-      background-size: 100% 100%;
-      cursor: pointer;
-    }
-    &::before {
-      content: '';
-      width: 43px;
-      height: 18px;
-      background: url('@/assets/images/videoTagEdit/line1.png') no-repeat;
-      background-size: 100% 100%;
-      position: absolute;
-      bottom: -8px;
-      left: 0;
-    }
-    &::after {
-      content: '';
-      width: calc(100% - 83px);
-      height: 2px;
-      background: url('@/assets/images/videoTagEdit/line2.png') no-repeat;
-      background-size: 100% 100%;
-      position: absolute;
-      bottom: 0;
-      left: 47px;
-    }
+    justify-content: center;
+    margin-top: 6px;
+    padding: 0 6px 0 5px;
+    cursor: pointer;
   }
-  .edit-content {
-    margin-top: 10px;
-    height: 500px;
-    overflow-y: auto;
-    .title-box {
-      width: 379px;
-      height: 39px;
-      background: url('@/assets/images/map/titleBox3.png') no-repeat;
-      background-size: 100% 100%;
-      padding-left: 30px;
-      margin-top: 10px;
-      .title {
-        font-size: 16px;
-      }
-    }
-    .title-box2 {
-      width: 135px;
-      height: 24px;
-      background: url('@/assets/images/map/rightMenu/titleBox2.png') no-repeat bottom left;
-      background-size: 135px 20px;
-      padding-left: 30px;
-      margin-top: 10px;
-      .title {
-        font-size: 16px;
-        color: #96aac1;
-      }
-    }
-    .title-box3 {
-      display: flex;
-      align-items: center;
-      margin-top: 10px;
-      .title {
-        font-size: 16px;
-        color: #96aac1;
-        margin: 0 6px;
-      }
-      .icon-type {
-        width: 28px;
-        height: 26px;
-        background: url('@/assets/images/videoTagEdit/type.png') no-repeat;
-        background-size: 100% 100%;
-      }
-      .icon-industry {
-        width: 26px;
-        height: 27px;
-        background: url('@/assets/images/videoTagEdit/industry.png') no-repeat;
-        background-size: 100% 100%;
-      }
-    }
-    .tags {
-      display: flex;
-      flex-wrap: wrap;
-      align-items: center;
-      margin-top: -5px;
-      .tag {
-        min-width: 126px;
-        height: 26px;
-        background: url('@/assets/images/map/tag.png') no-repeat;
-        background-size: 100% 100%;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        margin-top: 10px;
-        padding: 0 20px 0 15px;
-        cursor: pointer;
-      }
-      .custom-input {
-        width: 230px;
-        margin-left: 20px;
-        margin-top: 10px;
-      }
-    }
+  .custom-input {
+    width: 222px;
+    margin-left: 6px;
+    margin-top: 6px;
   }
 }
 </style>

+ 5 - 31
src/views/emergencyCommandMap/LeftSection/VideoMonitor.vue

@@ -4,10 +4,7 @@
     <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">
-        <HKVideo :dot_data="item" autoplay />
-        <div class="video-label">
-          <span class="label">{{ item.name }}</span>
-        </div>
+        <HKVideo :dot_data="item" autoplay @change="(data, index) => updateData(data, index)" />
       </div>
     </div>
   </div>
@@ -17,6 +14,7 @@
 <script lang="ts" setup name="VideoMonitor">
 import { getVideoListByUser } from '@/api/videoMonitor';
 import VideoMonitorEdit from './VideoMonitorEdit.vue';
+import HKVideo from '@/components/HKVideo/index2.vue';
 
 const props = defineProps({
   longitude: Number,
@@ -40,6 +38,9 @@ const initData = () => {
     listData.value = res.rows;
   });
 };
+const updateData = (data, index) => {
+  console.log(data, index, 'sdakfhasdkjfhskjdfhdskjh');
+}
 initData();
 
 const showVideoMonitorList = () => {
@@ -81,33 +82,6 @@ const showVideoMonitorList = () => {
       &:nth-child(4) {
         margin-right: 0;
       }
-      .video-label {
-        position: absolute;
-        bottom: 5px;
-        right: 3px;
-        z-index: 901;
-        display: flex;
-        .label {
-          width: 186px;
-          height: 22px;
-          line-height: 22px;
-          font-size: 14px;
-          white-space: nowrap;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          padding: 0 5px 0 10px;
-          color: #fff;
-          background-color: rgba(18, 107, 248, 0.4);
-          text-align: right;
-        }
-        &::before {
-          content: '';
-          width: 0;
-          height: 0;
-          border-bottom: 22px solid rgba(18, 107, 248, 0.4);
-          border-left: 22px solid transparent;
-        }
-      }
     }
     :deep(.err_box) {
       align-items: flex-start;

+ 114 - 33
src/views/emergencyCommandMap/LeftSection/VideoMonitorEdit.vue

@@ -2,27 +2,62 @@
   <Dialog custom-show type="xl" title="视频监控" class="dialog" hide-footer draggable @close="reset">
     <div class="search-box">
       <div class="box-left">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="70px" label-position="left">
-          <el-form-item prop="name">
-            <el-input v-model="queryParams.name" class="custom-input2" placeholder="请输入摄像头名称" style="width: 500px" />
+        <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-position="left">
+          <el-form-item label="区划" prop="area" label-width="30px">
+            <el-select
+              v-model="treeData.area"
+              class="custom-select"
+              popper-class="custom-select-popper"
+              :teleported="false"
+              style="width: 150px; margin-left: 10px"
+              @change="handleAreaChange"
+            >
+              <el-option v-for="item in treeData.areaList" :key="item.id" :label="item.label" :value="item.id" />
+            </el-select>
+            <el-select
+              v-model="treeData.town"
+              class="custom-select"
+              popper-class="custom-select-popper"
+              :teleported="false"
+              style="width: 150px; margin-left: 10px"
+              @change="handleTownChange"
+            >
+              <el-option v-for="item in treeData.townList" :key="item.id" :label="item.label" :value="item.id" />
+            </el-select>
+            <el-select
+              v-model="treeData.village"
+              class="custom-select"
+              popper-class="custom-select-popper"
+              :teleported="false"
+              style="width: 150px; margin-left: 10px"
+              @change="handleVillageChange"
+            >
+              <el-option v-for="item in treeData.villageList" :key="item.id" :label="item.label" :value="item.id" />
+            </el-select>
           </el-form-item>
-          <el-form-item label="实景视频" prop="dict_value">
+          <el-form-item label="实景视频" prop="dict_value" label-width="70px">
             <el-select
               v-model="queryParams.dict_value"
               class="custom-select"
               popper-class="custom-select-popper"
               :teleported="false"
+              style="width: 120px"
             >
               <el-option v-for="item in video_type" :key="item.value" :label="item.label" :value="item.value" />
             </el-select>
           </el-form-item>
-          <el-form-item>
+          <el-form-item prop="name">
+            <el-input v-model="queryParams.name" class="custom-input2" placeholder="请输入摄像头名称" style="width: 313px" />
+          </el-form-item>
+          <el-form-item style="margin-right: 0">
             <div class="common-btn-primary" @click="handleQuery">搜索</div>
             <div class="common-btn" @click="resetQuery">重置</div>
           </el-form-item>
         </el-form>
       </div>
-      <div v-show="!editVideo" class="common-btn-primary2 edit-icon" style="margin-top: -20px" @click="activeEdit">编辑首页视频</div>
+    </div>
+    <div style="display: flex; justify-content: flex-end; margin-bottom: 12px; margin-top: -20px">
+      <div v-show="!editVideo" class="common-btn-primary2 edit-icon" @click="activeEdit">编辑首页视频</div>
       <div v-show="editVideo" class="edit-box">
         <div class="flex">
           <div v-for="(item, index) in editData" :key="index" class="box-item">
@@ -33,7 +68,7 @@
           </div>
         </div>
         <div class="flex" style="flex-direction: column; align-items: center">
-          <div class="common-btn-primary3" @click="handleSave">保存</div>
+          <div class="common-btn-primary3" style="margin-top: -25px" @click="handleSave">保存</div>
           <div class="common-btn-danger2" @click="handleCancel">取消</div>
         </div>
       </div>
@@ -41,16 +76,16 @@
     <div class="border"></div>
     <div class="video-list2">
       <div v-for="(item, index) in dialogListData" :key="index" class="video-box" @click="selectItem(item)">
-        <div class="video-label">
-          <span class="label">{{ item.name }}</span>
-        </div>
         <div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
           <div v-if="editVideo">
-            <div v-if="item.sort" class="active-tag"></div>
-            <div :class="item.sort ? 'common-checked-active' : 'common-checked'"></div>
+            <div v-if="getCheckStatus(item.video_code)" class="active-tag"></div>
+            <div :class="getCheckStatus(item.video_code) ? 'common-checked-active' : 'common-checked'"></div>
             <div class="img"></div>
+            <div class="video-label">
+              <span class="label">{{ item.name }}</span>
+            </div>
           </div>
-          <HKVideo v-else :dot_data="item" autoplay />
+          <HKVideo v-else :dot_data="item" autoplay :is-index="item.sort" />
         </div>
       </div>
     </div>
@@ -63,7 +98,7 @@
         layout="total, prev, pager, next"
         @pagination="getList"
       />
-      <div v-if="total === 0" style="width: 100%; text-align: center; font-size: 18px; font-weight: bold">暂无数据</div>
+      <div v-if="total === 0" style="width: 100%; text-align: center; font-size: 38px; font-weight: bold">暂无数据</div>
     </div>
     <div id="container" style="display: none"></div>
   </Dialog>
@@ -75,6 +110,9 @@ import { getEmergencyVideoCata, getUserVideoPoints, getVideoList, updateUserVide
 import { deepClone } from '@/utils';
 import useAppStore from '@/store/modules/app';
 import useMapStore from '@/store/modules/map';
+import HKVideo from '@/components/HKVideo/index2.vue';
+import { getRegionalTree } from '@/api/PreventionResponsible';
+
 interface LngLat {
   longitude: number;
   latitude: number;
@@ -97,11 +135,20 @@ const { video_type } = toRefs<any>(proxy?.useDict('video_type'));
 
 //查看更多数据
 const queryFormRef = ref();
+const treeData = reactive({
+  area: '',
+  town: '',
+  village: '',
+  areaList: [],
+  townList: [],
+  villageList: []
+});
 const queryParams = reactive({
   current: 1,
   size: 8,
   dict_value: '',
-  name: ''
+  name: '',
+  area: ''
 });
 let total = ref(0);
 let editVideo = ref(false);
@@ -122,7 +169,7 @@ watch(
   { immediate: true }
 );
 
-const getList = () => {
+const getList = (flag?: boolean) => {
   let newParams = {
     latitude: props.lngLat.latitude,
     longitude: props.lngLat.longitude,
@@ -138,9 +185,10 @@ const getList = () => {
   getEmergencyVideoCata(newParams).then((res) => {
     dialogListData.value = res.rows;
     total.value = res.total;
-    if (editVideo.value && editData.value) {
-      filterData(editData.value);
-    }
+    getUserVideoPoints().then((res2) => {
+      filterData(res2.data.videoInfos);
+      editData.value = deepClone(res2.data.videoInfos);
+    });
   });
 };
 const getVideoInfoList = () => {
@@ -165,9 +213,6 @@ const deleteItem = (index) => {
 };
 /** 表单重置 */
 const reset = () => {
-  queryParams.current = 1;
-  queryParams.dict_value = '';
-  queryParams.name = '';
   emits('update:modelValue', false);
 };
 
@@ -181,16 +226,18 @@ const handleQuery = () => {
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
+  treeData.area = '';
+  treeData.townList = [];
+  treeData.town = '';
+  treeData.villageList = [];
+  treeData.village = '';
+  queryParams.current = 1;
   handleQuery();
 };
 
 // 开启编辑视频
 const activeEdit = () => {
-  getUserVideoPoints().then((res) => {
-    filterData(res.data.videoInfos);
-    editData.value = deepClone(res.data.videoInfos);
-    editVideo.value = true;
-  });
+  editVideo.value = true;
 };
 const filterData = (data) => {
   data.forEach((item) => {
@@ -213,13 +260,46 @@ const handleSave = () => {
     data.push(item.video_code_int);
   });
   updateUserVideoPoints(data).then(() => {
-    getList();
+    getList(true);
     handleCancel();
   });
 };
-
+// 区变化
+const handleAreaChange = () => {
+  getAreaTreeList('townList', treeData.area);
+  treeData.town = '';
+  treeData.village = '';
+  queryParams.area = treeData.area;
+};
+// 镇变化
+const handleTownChange = () => {
+  getAreaTreeList('villageList', treeData.town);
+  treeData.village = '';
+  queryParams.area = treeData.town;
+};
+// 村变化
+const handleVillageChange = () => {
+  queryParams.area = treeData.village;
+};
+// 获取区划树
+const getAreaTreeList = (datasource, id) => {
+  getRegionalTree(id).then((res) => {
+    treeData[datasource] = res.data;
+  });
+};
+const getCheckStatus = (id) => {
+  let flag = false;
+  for (let i = 0; i < editData.value.length; i++) {
+    if (editData.value[i].video_code_int === id) {
+      flag = true;
+      break;
+    }
+  }
+  return flag;
+};
 onMounted(() => {
   getList();
+  getAreaTreeList('areaList', 2);
   // getVideoInfoList();
 });
 </script>
@@ -230,6 +310,7 @@ onMounted(() => {
   width: 100%;
   justify-content: space-between;
   align-items: center;
+  margin-top: -10px;
   .el-form--inline .el-form-item {
     margin-right: 15px;
   }
@@ -312,9 +393,9 @@ onMounted(() => {
   height: 83px;
   background: url('@/assets/images/video/editBg.png') no-repeat;
   background-size: 100% 100%;
-  position: absolute;
-  right: 20px;
-  top: 27px;
+  //position: absolute;
+  //right: 20px;
+  //top: 27px;
 }
 .box-item {
   position: relative;
@@ -396,7 +477,7 @@ onMounted(() => {
   background-color: #15428d;
   width: 100%;
   height: 1px;
-  margin-bottom: 30px;
+  margin-bottom: 15px;
 }
 .edit-icon {
   display: flex;

+ 2 - 14
src/views/globalMap/LeftMenu.vue

@@ -112,20 +112,7 @@
         </div>
       </Transition>
     </div>
-    <Dialog
-      v-if="showDialog"
-      v-model="showDialog"
-      type="lg"
-      header-type="header2"
-      title="视频"
-      height="720px"
-      :get-tag-id="videoMonitorData.video_code"
-      hide-footer
-    >
-      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center">
-        <HKVideo :dot_data="videoMonitorData" />
-      </div>
-    </Dialog>
+    <video-dialog v-if="showDialog" v-model="showDialog" :videoMonitorData="videoMonitorData" height="680px" />
   </div>
 </template>
 
@@ -133,6 +120,7 @@
 import { getPointInfoComprehensiveSearch } from '@/api/globalMap';
 import { listMenu2 } from '@/api/system/menu';
 import { deepClone } from '@/utils';
+import VideoDialog from '@/components/HKVideo/video-dialog.vue';
 import { onClickOutside } from '@vueuse/core';
 import gcoord from 'gcoord';