无人机管理后台前端(已迁走)
chenyao
2025-11-28 cf55e57ac8e892c321cc9eeb79e14b39e7d80e82
src/views/job/components/DeviceJobDetails.vue
@@ -1,148 +1,150 @@
<!-- 历史任务详情 -->
<template>
   <el-dialog class="ztzf-dialog" append-to-body modal-class="detailsOfHistoricalTasks" v-model="isShow" title="历史任务详情"
      :width="pxToRem(1800)" :close-on-click-modal="false" :destroy-on-close="true">
      <div class="content">
         <div class="contentLeft">
            <div class="machineTableDetailsTitle"><img src="/src/assets/images/task/sign.svg" alt=""><span>详情</span></div>
            <div class="infoBox">
               <div class="itemBoxLeft">
                  <div v-for="(item, index) in infoList" :key="index" class="itemCon">
                     <div class="itemBox">
                        <div class="itemTitle">{{ item.name }}:</div>
                        <div truncated class="itemValue" v-if="item.name !== '飞行事件' && item.name !== '任务执行次数'">{{
                              item.value ? item.value : '--' }}</div>
                        <div class="itemValue" v-if="item.name === '任务执行次数'">{{ item.value ? item.value : '0'
                           }}次</div>
                        <!-- 飞行事件 -->
                        <div class="flightEvents" v-if="item.name === '飞行事件'">
                           <template v-if="flightEvents.length">
                              <img v-for="(item, index) in flightEvents" alt="" :src="item.img"
                                 :title="item.name" :key="index"></img>
                           </template>
                           <div class="itemValue" v-else>--</div>
                        </div>
                     </div>
                  </div>
               </div>
  <el-dialog class="ztzf-dialog" append-to-body modal-class="detailsOfHistoricalTasks" v-model="isShow" title="历史任务详情"
             :width="pxToRem(1800)" :close-on-click-modal="false" :destroy-on-close="true">
    <div class="content">
      <div class="contentLeft">
        <div class="machineTableDetailsTitle"><img src="/src/assets/images/task/sign.svg" alt=""><span>详情</span></div>
        <div class="infoBox">
          <div class="itemBoxLeft">
            <div v-for="(item, index) in infoList" :key="index" class="itemCon">
              <div class="itemBox">
                <div class="itemTitle">{{ item.name }}:</div>
                <div truncated class="itemValue" v-if="item.name !== '飞行事件' && item.name !== '任务执行次数'">{{
                    item.value ? item.value : '--' }}</div>
                <div class="itemValue" v-if="item.name === '任务执行次数'">{{ item.value ? item.value : '0'
                  }}次</div>
                <!-- 飞行事件 -->
                <div class="flightEvents" v-if="item.name === '飞行事件'">
                  <template v-if="flightEvents.length">
                    <img v-for="(item, index) in flightEvents" alt="" :src="item.img"
                         :title="item.name" :key="index"></img>
                  </template>
                  <div class="itemValue" v-else>--</div>
                </div>
              </div>
            </div>
          </div>
            </div>
            <JobRelatedEvents :jobTimes="jobTimes" :batchNo="batchNo" />
            <div class="devicetitle" v-if="isShow">
            <div>
                  <img src="/src/assets/images/task/sign.svg" alt="">
               <p>
                  成果数据
                  <span>{{ total }}</span>
                  个
               </p>
            </div>
               <div class="rightBox" v-if="total">
                  <div class="downloadBtn" @click="htlsrwxq === 100 && downloadFun()">
                     <el-progress v-if="htlsrwxq !== 100" :percentage="htlsrwxq" :show-text="false" striped striped-flow :duration="1" />
                     <div class="downloadBtnText">
                        <span v-if="htlsrwxq === 100">下载</span>
                        <template v-else>
                           处理中<el-icon @click="cancelDownload"><CircleClose /></el-icon>
                        </template>
                     </div>
                  </div>
                  <div class="downloadBtn" @click="showAll = !showAll" v-if="total > 5">
                     {{ showAll ? '收起' : '更多' }}
                  </div>
               </div>
            </div>
            <div class="imgListBox">
               <!-- 图片显示 -->
               <template v-for="(item, index) in achievementList.slice(0, visibleCount)" :key="index">
               <div class="result-item">
                  <el-checkbox v-model="item.checked" />
                  <div class="itemName">{{ item.createTime }}</div>
                  <!-- 正射 -->
                     <el-image
                        v-if="item.resultType === 4"
                        :src="item.smallUrl"
                        :preview-src-list="[item.showUrl]"
                        fit="cover"
                        preview-teleported
                     />
                     <!-- 全景 -->
                     <img
                        v-else-if="item.resultType === 5"
                        class="quanjing"
                        @click="clickpanorama(item)"
                        :src="item?.smallUrl"
                        alt=""
                     />
                  <!-- 视频 -->
                     <div v-else-if="item.resultType === 1" class="videotime">
                        <img
                           class="videoDisplay"
                           :src="convertVideoUrlToThumbnail(item.link)"
                           alt=""
                           @click="enterFullScreen(index)"
                        />
                        <img
                           @click="enterFullScreen(index)"
                           class="videobutton"
                           src="@/assets/images/task/videoshow.png"
                           alt=""
                        />
                     </div>
                        <!-- 图片 -->
                     <el-image
                        v-else
                        :src="item.smallUrl"
                        :preview-src-list="[item.showUrl]"
                        preview-teleported
                        :initial-index="index"
                        fit="cover"
                     />
        </div>
        <JobRelatedEvents :jobTimes="jobTimes" :batchNo="batchNo" />
        <div class="devicetitle" v-if="isShow">
          <div>
            <img src="/src/assets/images/task/sign.svg" alt="">
            <p>
              成果数据
              <span>{{ total }}</span>
              个
            </p>
          </div>
          <div class="rightBox" v-if="total">
            <div class="downloadBtn" @click="htlsrwxq === 100 && downloadFun()">
              <el-progress v-if="htlsrwxq !== 100" :percentage="htlsrwxq" :show-text="false" striped striped-flow :duration="1" />
              <div class="downloadBtnText">
                <span v-if="htlsrwxq === 100">下载</span>
                <template v-else>
                  处理中<el-icon @click="cancelDownload"><CircleClose /></el-icon>
                </template>
              </div>
            </div>
            <div class="downloadBtn" @click="showAll = !showAll" v-if="total > 5">
              {{ showAll ? '收起' : '更多' }}
            </div>
          </div>
        </div>
        <div class="imgListBox">
          <!-- 图片显示 -->
          <template v-for="(item, index) in achievementList.slice(0, visibleCount)" :key="index">
            <div class="result-item">
              <el-checkbox v-model="item.checked" />
              <div class="itemName">{{ item.createTime }}</div>
              <!-- 正射 -->
              <el-image
                v-if="item.resultType === 4"
                :src="item.smallUrl"
                :preview-src-list="[item.showUrl]"
                fit="cover"
                preview-teleported
              />
              <!-- 全景 -->
              <img
                v-else-if="item.resultType === 5"
                class="quanjing"
                @click="clickpanorama(item)"
                :src="item?.smallUrl"
                alt=""
              />
              <!-- 视频 -->
              <div v-else-if="item.resultType === 1" class="videotime">
                <img
                  class="videoDisplay"
                  :src="convertVideoUrlToThumbnail(item.link)"
                  alt=""
                  @click="enterFullScreen(index)"
                />
                <img
                  @click="enterFullScreen(index)"
                  class="videobutton"
                  src="@/assets/images/task/videoshow.png"
                  alt=""
                />
              </div>
              <!-- 图片 -->
              <el-image
                v-else
                :src="item.smallUrl"
                :preview-src-list="[item.showUrl]"
                preview-teleported
                :initial-index="index"
                fit="cover"
              />
                  <el-dialog
              class="ztzf-dialog"
              append-to-body
              modal-class="detailsOfHistoricalTasks"
              v-model="VideoShow"
              :width="pxToRem(1600)"
              :close-on-click-modal="false"
              :destroy-on-close="true"
         >
            <div class="fullscreen">
               <video
                  ref="fullscreenVideo"
                  class="fullscreen-video"
                  :src="currentVideoUrl"
                  :style="{ width: pxToRem(1600), height: '80vh' }"
                  controls
                  autoplay
               ></video>
            </div>
         </el-dialog>
                  </div>
              <el-dialog
                class="ztzf-dialog"
                append-to-body
                modal-class="detailsOfHistoricalTasks"
                v-model="VideoShow"
                :width="pxToRem(1600)"
                :close-on-click-modal="false"
                :destroy-on-close="true"
              >
                <div class="fullscreen">
                  <video
                    ref="fullscreenVideo"
                    class="fullscreen-video"
                    :src="currentVideoUrl"
                    :style="{ width: pxToRem(1567), height: '80vh' }"
                    controls
                    preload="auto"
                    @play="handleVideoPlay"
                    @ended="handleVideoEnded"
                  ></video>
                </div>
              </el-dialog>
            </div>
               </template>
          </template>
            </div>
            <el-image-viewer
               v-if="showViewer"
               :url-list="previewUrls"
               :initial-index="activeIndex"
               @close="showViewer = false"
            />
         </div>
        </div>
        <el-image-viewer
          v-if="showViewer"
          :url-list="previewUrls"
          :initial-index="activeIndex"
          @close="showViewer = false"
        />
      </div>
         <div class="content-right" v-if="isShow">
            <DeviceJobDetailsMap
               :detailsData="detailsData"
               :yuanImages="yuanImages"
               @showImageeclick="showImageeclick"
               :jobId="props.jobId"
            />
            <div class="content-map-popups"></div>
         </div>
      </div>
   </el-dialog>
      <div class="content-right" v-if="isShow">
        <DeviceJobDetailsMap
          :detailsData="detailsData"
          :yuanImages="yuanImages"
          @showImageeclick="showImageeclick"
          :jobId="props.jobId"
        />
        <div class="content-map-popups"></div>
      </div>
    </div>
  </el-dialog>
  <!-- 全景360 -->
  <PanoramaPopup
    v-if="'全景'"
@@ -169,46 +171,66 @@
const VideoShow = ref(false)
const showAll = ref(false) // 是否展示全部
let loadingData
const fullscreenVideo = ref(null)
// 视频播放事件处理
const handleVideoPlay = (event) => {
  if (event.target.playbackRate !== 0.75) {
    event.target.playbackRate = 0.75
  }
}
const handleVideoEnded = index => {
  // 获取当前视频
  const video = fullscreenVideo.value
  // 重置视频播放时间为 0
  video.currentTime = 0
  // 重新加载视频
  video.load()
}
// 原图
const yuanImages = ref([])
function convertVideoUrlToThumbnail(videoUrl) {
   // 检查是否是有效的视频URL
   if (!videoUrl || typeof videoUrl !== 'string') {
      return videoUrl
   }
   // 替换文件扩展名
   return videoUrl.replace(/\.mp4$/, '_small.jpg')
  // 检查是否是有效的视频URL
  if (!videoUrl || typeof videoUrl !== 'string') {
    return videoUrl
  }
  // 替换文件扩展名
  return videoUrl.replace(/\.mp4$/, '_small.jpg')
}
const infoList = ref([
   { name: '任务编号', value: '', field: 'job_info_num' },
   { name: '任务名称', value: '', field: 'name' },
   { name: '任务类型', value: '', field: 'industry_type_str' },
   { name: '飞行事件', value: '', field: 'event_number' },
   { name: '所属机巢', value: '', field: 'device_names' },
   { name: '所属部门', value: '', field: 'dept_name' },
   { name: '任务时间', value: '', field: 'cycle_time_value' },
   { name: '关联算法', value: '', field: 'ai_type_str' },
   { name: '任务描述', value: '', field: 'remark' },
  { name: '任务编号', value: '', field: 'job_info_num' },
  { name: '任务名称', value: '', field: 'name' },
  { name: '任务类型', value: '', field: 'industry_type_str' },
  { name: '飞行事件', value: '', field: 'event_number' },
  { name: '所属机巢', value: '', field: 'device_names' },
  { name: '所属部门', value: '', field: 'dept_name' },
  { name: '任务时间', value: '', field: 'cycle_time_value' },
  { name: '关联算法', value: '', field: 'ai_type_str' },
  { name: '自定义识别区', value: '', field: 'enable_custom_area' },
   // { name: '任务执行次数', value: '', field: 'job_num' },
  { name: '创建人', value: '', field: 'creator_name' },
  { name: '任务描述', value: '', field: 'remark' },
  // { name: '任务执行次数', value: '', field: 'job_num' },
])
// 机巢状态
const flystatus = ref('')
const detailsData = ref({
   id: null,
   remark: null,
   is_monitoring: null,
   industry_type_str: null,
   area_code: null,
   ai_type_str: null,
   begin_time: null,
   end_time: null,
   device_names: null,
   create_time: null,
   name: null,
   event_number: null,
   creator_name: null,
   way_lines: [],
  id: null,
  remark: null,
  is_monitoring: null,
  industry_type_str: null,
  area_code: null,
  ai_type_str: null,
  enable_custom_area:null,
  begin_time: null,
  end_time: null,
  device_names: null,
  create_time: null,
  name: null,
  event_number: null,
  creator_name: null,
  way_lines: [],
})
// 任务成果
const total = ref(0)
@@ -218,10 +240,10 @@
provide('wayLineJodInfoId', wayLineJodInfoId)
// 可见数量
const visibleCount = computed(() =>
   showAll.value ? achievementList.value.length : Math.min(5, achievementList.value.length)
  showAll.value ? achievementList.value.length : Math.min(5, achievementList.value.length)
)
const getAchievement = () => {
   if (!props.jobId) return
  if (!props.jobId) return
  const attachmentsParams = {
    'wayLineJobId': props.jobId,
@@ -230,83 +252,83 @@
    current: 1,
    size: 2000,
  }
   const pageParams = {
      current: 1,
      size: 2000,
   }
  const pageParams = {
    current: 1,
    size: 2000,
  }
  aiImagesPage(attachmentsParams ).then(res => {
      achievementList.value = res.data.data.records.map(i => ({
         ...i,
         checked: false,
         smallUrl: i.resultType === 4 ? getzsSmallImg(i.link) : getSmallImg(i.link),
         showUrl: i.resultType === 4 ? getzsShowImg(i.link) : getShowImg(i.link),
      }))
      total.value = res.data.data.total
      // console.log('成果数据', res.data.data)
   })
    achievementList.value = res.data.data.records.map(i => ({
      ...i,
      checked: false,
      smallUrl: i.resultType === 4 ? getzsSmallImg(i.link) : getSmallImg(i.link),
      showUrl: i.resultType === 4 ? getzsShowImg(i.link) : getShowImg(i.link),
    }))
    total.value = res.data.data.total
    // console.log('成果数据', res.data.data)
  })
}
const jumpMore = () => {
   ElMessage.warning('正在加急开发中...')
  ElMessage.warning('正在加急开发中...')
}
const flightEvents = ref([])
const jobTimes = ref([])
const getDetails = () => {
   const params = {
      wayLineJobInfoId: props.wayLineJodInfoId,
      waylineJobId: props.waylineJobId,
      batchNo: props.batchNo
   }
   getJobDetails(params).then(res => {
      detailsData.value = res.data.data
      jobTimes.value = res.data.data.job_times
      infoList.value.forEach(item => {
         if (item.name === '任务频次') {
            const { rep_rule_type = '', rep_rule_val = '' } = detailsData?.value || {}
            item.value = rep_rule_type + ' -- ' + rep_rule_val
         } else {
            item.value = detailsData.value?.[item.field] || '--'
         }
         if (item.name === '飞行事件') {
            const { action_modes = [] } = detailsData?.value || {}
            flightEvents.value = action_modes.flatMap(({ actionActuatorFunc }) =>
               droneEventList.filter(({ value }) => actionActuatorFunc === value)
            )
         }
  const params = {
    wayLineJobInfoId: props.wayLineJodInfoId,
    waylineJobId: props.waylineJobId,
    batchNo: props.batchNo
  }
  getJobDetails(params).then(res => {
    detailsData.value = res.data.data
    jobTimes.value = res.data.data.job_times
    infoList.value.forEach(item => {
      if (item.name === '任务频次') {
        const { rep_rule_type = '', rep_rule_val = '' } = detailsData?.value || {}
        item.value = rep_rule_type + ' -- ' + rep_rule_val
      } else {
        item.value = detailsData.value?.[item.field] || '--'
      }
      if (item.name === '飞行事件') {
        const { action_modes = [] } = detailsData?.value || {}
        flightEvents.value = action_modes.flatMap(({ actionActuatorFunc }) =>
          droneEventList.filter(({ value }) => actionActuatorFunc === value)
        )
      }
      if (item.name === '自定义识别区') {
        item.value = res.data.data.enable_custom_area ? '是': '否'
      }
            getJobsAllFiles({
         wayLineJobId: detailsData.value.way_lines.map(item => item.job_id).join(','),
         resultTypes: [0, 2, 4, 5],
      }).then(result => {
         if (result.data.code !== 200) return
         yuanImages.value = result.data.data.records
      getJobsAllFiles({
        wayLineJobId: detailsData.value.way_lines.map(item => item.job_id).join(','),
        resultTypes: [0, 2, 4, 5],
      }).then(result => {
        if (result.data.code !== 200) return
        yuanImages.value = result.data.data.records
      })
      })
      // flystatus.value = res.data.data.ai_type_str
   })
      })
    })
    // flystatus.value = res.data.data.ai_type_str
  })
}
// 播放
const videoRef = ref(null);
const currentVideoIndex = ref(-1)
const fullscreenVideo = ref(null)
const enterFullScreen = (index) => {
   currentVideoIndex.value = index
   VideoShow.value = true
  currentVideoIndex.value = index
  VideoShow.value = true
}
// 计算当前视频URL
const currentVideoUrl = computed(() => {
   return achievementList.value[currentVideoIndex.value]?.link || ''
  return achievementList.value[currentVideoIndex.value]?.link || ''
})
// 关闭弹窗处理
const handleClose = () => {
   if (fullscreenVideo.value) {
      fullscreenVideo.value.pause()
      fullscreenVideo.value.currentTime = 0
   }
  if (fullscreenVideo.value) {
    fullscreenVideo.value.pause()
    fullscreenVideo.value.currentTime = 0
  }
}
// 下载
const downloadFun = async () => {
@@ -334,353 +356,353 @@
const panoramaParamsShow = ref(false)
const panoramaParamsUrl = ref(null)
const clickpanorama = val => {
   panoramaParamsShow.value = true
   panoramaParamsUrl.value = val.link
  panoramaParamsShow.value = true
  panoramaParamsUrl.value = val.link
}
// 从地图点击图片预览
const showViewer = ref(false)
const activeIndex = ref(0)
const previewUrls = ref([])
const showImageeclick = (list, index, categoriestype) => {
   if (categoriestype === 5) {
      panoramaParamsShow.value = true
      panoramaParamsUrl.value = list[0]
   } else {
      previewUrls.value = list
      activeIndex.value = 0
      showViewer.value = true
   }
  if (categoriestype === 5) {
    panoramaParamsShow.value = true
    panoramaParamsUrl.value = list[0]
  } else {
    previewUrls.value = list
    activeIndex.value = 0
    showViewer.value = true
  }
}
// 取消下载
function cancelDownload() {
   cancelDownloadApi({ type:'htlsrwxq' }).then(res =>{
      ElMessage.success('取消成功')
   }).catch(e =>{
  cancelDownloadApi({ type:'htlsrwxq' }).then(res =>{
    ElMessage.success('取消成功')
  }).catch(e =>{
    EventBus.emit('useGlobalWS-messageHandler', {biz_code: 'DOWNLOAD_PROGRESS',data:{status: 'CANCELLED',type:'htlsrwxq'}})
  })
}
onMounted(() => {
   getDetails()
   getAchievement()
  getDetails()
  getAchievement()
})
</script>
<style lang="scss">
.detailsOfHistoricalTasks {
   .el-dialog {
      --el-dialog-margin-top: 5vh;
   }
  .el-dialog {
    --el-dialog-margin-top: 5vh;
  }
   .el-pagination {
      justify-content: center;
      padding: 20px;
   }
  .el-pagination {
    justify-content: center;
    padding: 20px;
  }
   .el-dialog__body {
      height: 80vh;
   }
  .el-dialog__body {
    height: 80vh;
  }
}
</style>
<style lang="scss" scoped>
.content {
   display: flex;
   height: 100%;
.contentLeft {
      margin-left: 35px;
      margin-right: 24px;
      width: 1150px;
      overflow: auto;
  display: flex;
  height: 100%;
  .contentLeft {
    margin-left: 35px;
    margin-right: 24px;
    width: 1150px;
    overflow: auto;
      .machineTableDetailsTitle {
         margin-bottom: 10px;
         // background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
         border-bottom: 2px solid #e4e7ed;
         background-size: 100% 100%;
         img{
         width: 15px;
         height: 15px;}
         span {
            display: inline-block;
            margin-left: 10px;
            font-size: 16px;
            // color: #0282ff;
            color: #303133;
            line-height: 20px;
            text-align: left;
            margin-bottom: 8px;
         }
      }
    .machineTableDetailsTitle {
      margin-bottom: 10px;
      // background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
      border-bottom: 2px solid #e4e7ed;
      background-size: 100% 100%;
      img{
        width: 15px;
        height: 15px;}
      span {
        display: inline-block;
        margin-left: 10px;
        font-size: 16px;
        // color: #0282ff;
        color: #303133;
        line-height: 20px;
        text-align: left;
        margin-bottom: 8px;
      }
    }
      .devicetitle {
         margin-bottom: 16px;
         // background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
         border-bottom: 2px solid #e4e7ed;
         background-size: 100% 100%;
         display: flex;
         justify-content: space-between;
         align-content: center;
         .rightBox{
            display: flex;
            align-items: center;
            padding-right: 10px;
            gap: 0 10px;
    .devicetitle {
      margin-bottom: 16px;
      // background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
      border-bottom: 2px solid #e4e7ed;
      background-size: 100% 100%;
      display: flex;
      justify-content: space-between;
      align-content: center;
      .rightBox{
        display: flex;
        align-items: center;
        padding-right: 10px;
        gap: 0 10px;
            .downloadBtn{
               position: relative;
               display: flex;
               align-items: center;
               justify-content: center;
               height: 28px;
               padding: 0 15px;
               background: rgba(28, 92, 255, 0.14);
               border-radius: 4px 4px 4px 4px;
               border: 1px solid #1c5cff;
               cursor: pointer;
                   color: #1C5CFF;
        .downloadBtn{
          position: relative;
          display: flex;
          align-items: center;
          justify-content: center;
          height: 28px;
          padding: 0 15px;
          background: rgba(28, 92, 255, 0.14);
          border-radius: 4px 4px 4px 4px;
          border: 1px solid #1c5cff;
          cursor: pointer;
          color: #1C5CFF;
               .downloadBtnText{
                  display: flex;
                  align-items: center;
                  gap: 5px;
                  z-index: 5;
               }
               .el-progress{
                  position: absolute;
                  left: 0;
                  top: 0;
                  width: 100%;
          .downloadBtnText{
            display: flex;
            align-items: center;
            gap: 5px;
            z-index: 5;
          }
          .el-progress{
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
                  :deep(){
                     .el-progress-bar__outer{
                        height: 28px !important;
                        border-radius: 0 !important;
                        background: transparent !important;
            :deep(){
              .el-progress-bar__outer{
                height: 28px !important;
                border-radius: 0 !important;
                background: transparent !important;
                        .el-progress-bar__inner{
                           border-radius: 0 !important;
                        }
                     }
                  }
               }
                .el-progress-bar__inner{
                  border-radius: 0 !important;
                }
              }
            }
          }
            }
         }
         img{
         width: 15px;
         height: 15px;}
         p {
            display: inline-block;
            margin-left: 10px;
            font-size: 16px;
            color: #363636;
            line-height: 20px;
            text-align: left;
            margin-bottom: 8px;
        }
      }
      img{
        width: 15px;
        height: 15px;}
      p {
        display: inline-block;
        margin-left: 10px;
        font-size: 16px;
        color: #363636;
        line-height: 20px;
        text-align: left;
        margin-bottom: 8px;
            span {
               font-size: 26px;
               color: #0282ff;
               font-weight: bold;
            }
         }
        span {
          font-size: 26px;
          color: #0282ff;
          font-weight: bold;
        }
      }
         .more {
            color: #2f9dff;
            font-size: 14px;
            padding-top: 5px;
            cursor: pointer;
         }
      }
      .more {
        color: #2f9dff;
        font-size: 14px;
        padding-top: 5px;
        cursor: pointer;
      }
    }
      .infoBox {
         display: flex;
         justify-content: space-between;
    .infoBox {
      display: flex;
      justify-content: space-between;
         .itemBoxLeft {
            flex: 1;
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            column-gap: 10px;
            /* 只设置列间距 */
            row-gap: 0;
            /* 取消行间距 */
            padding: 10px;
            font-size: 14px;
      .itemBoxLeft {
        flex: 1;
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        column-gap: 10px;
        /* 只设置列间距 */
        row-gap: 0;
        /* 取消行间距 */
        padding: 10px;
        font-size: 14px;
            .itemBox {
               display: flex;
               align-items: center;
               background: #fff;
               height: 43px;
               border-top: 2px solid #EFEFEF;
        .itemBox {
          display: flex;
          align-items: center;
          background: #fff;
          height: 43px;
          border-top: 2px solid #EFEFEF;
            }
        }
         }
      }
         .itemCon:nth-last-child(-n+2) {
            border-bottom: 2px solid #EFEFEF;
         }
      .itemCon:nth-last-child(-n+2) {
        border-bottom: 2px solid #EFEFEF;
      }
         .itemBox:nth-last-child(-n+2) .itemTitle {
            border-bottom: 1px solid #EFEFEF;
         }
      .itemBox:nth-last-child(-n+2) .itemTitle {
        border-bottom: 1px solid #EFEFEF;
      }
         .itemTitle {
            color: #0B1D38;
            width: 26%;
            text-align: right;
            background: #F3F6FF;
            height: 43px;
            line-height: 43px;
            padding-right: 10px;
            border-top: 1px solid #EFEFEF;
         }
      .itemTitle {
        color: #0B1D38;
        width: 26%;
        text-align: right;
        background: #F3F6FF;
        height: 43px;
        line-height: 43px;
        padding-right: 10px;
        border-top: 1px solid #EFEFEF;
      }
         .itemValue {
            font-size: 14px;
            color: #747e91;
            text-align: center;
            width: 74%;
      .itemValue {
        font-size: 14px;
        color: #747e91;
        text-align: center;
        width: 74%;
         }
      }
         .flightEvents {
            display: flex;
            flex-wrap: wrap;
            gap: 10px 10px;
            width: 74%;
            justify-content: center;
      .flightEvents {
        display: flex;
        flex-wrap: wrap;
        gap: 10px 10px;
        width: 74%;
        justify-content: center;
            img {
               width: 30px;
               height: 30px;
            }
         }
        img {
          width: 30px;
          height: 30px;
        }
      }
      }
    }
      .imgListBox {
         display: grid;
         grid-template-columns: repeat(5, 1fr);
         gap: 10px;
         margin-bottom: 49px;
    .imgListBox {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      gap: 10px;
      margin-bottom: 49px;
         > * {
            width: 100%;
            height: 200px;
            position: relative;
            border-radius: 0px 0px 4px 4px;
            overflow: hidden;
         }
         :deep(.el-checkbox__inner) {
            width: 17px !important;
            height: 17px !important;
            background: rgba(37, 36, 36, 0.63) !important;
            border-radius: 4px 4px 4px 4px;
            border: 1px solid #ffffff !important;
         }
         .el-checkbox {
            position: absolute;
            top: 0;
            left: 6px;
         }
         :deep(.el-checkbox__inner:after) {
            position: absolute;
            left: 50% !important;
            top: 40% !important;
            transform: translate(-50%, -50%) rotate(45deg) !important;
         }
         :deep(.el-checkbox.is-checked .el-checkbox__inner) {
            background-color: #09297b !important;
            border-color: #1c5cff !important;
         }
         .el-image {
            width: 100%;
            height: 100%;
            cursor: pointer;
            position: relative;
         }
      > * {
        width: 100%;
        height: 200px;
        position: relative;
        border-radius: 0px 0px 4px 4px;
        overflow: hidden;
      }
      :deep(.el-checkbox__inner) {
        width: 17px !important;
        height: 17px !important;
        background: rgba(37, 36, 36, 0.63) !important;
        border-radius: 4px 4px 4px 4px;
        border: 1px solid #ffffff !important;
      }
      .el-checkbox {
        position: absolute;
        top: 0;
        left: 6px;
      }
      :deep(.el-checkbox__inner:after) {
        position: absolute;
        left: 50% !important;
        top: 40% !important;
        transform: translate(-50%, -50%) rotate(45deg) !important;
      }
      :deep(.el-checkbox.is-checked .el-checkbox__inner) {
        background-color: #09297b !important;
        border-color: #1c5cff !important;
      }
      .el-image {
        width: 100%;
        height: 100%;
        cursor: pointer;
        position: relative;
      }
         .quanjing {
            width: 100%;
            height: 100%;
            object-fit: cover;
            cursor: pointer;
            position: relative;
         }
      .quanjing {
        width: 100%;
        height: 100%;
        object-fit: cover;
        cursor: pointer;
        position: relative;
      }
         .videotime {
            width: 100%;
            height: 100%;
            position: relative;
      .videotime {
        width: 100%;
        height: 100%;
        position: relative;
            .videoDisplay {
               width: 100%;
               height: 100%;
               object-fit: cover;
            }
         }
         .itemName {
            position: absolute;
            bottom: 0;
            left: 0;
            height: 23px;
            width: 100%;
            background: rgba(22, 22, 22, 0.68);
            border-radius: 0px 0px 4px 4px;
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: 400;
            font-size: 14px;
            color: #ffffff;
            line-height: 23px;
            z-index: 9;
            padding: 0 6px;
         }
      }
        .videoDisplay {
          width: 100%;
          height: 100%;
          object-fit: cover;
        }
      }
      .itemName {
        position: absolute;
        bottom: 0;
        left: 0;
        height: 23px;
        width: 100%;
        background: rgba(22, 22, 22, 0.68);
        border-radius: 0px 0px 4px 4px;
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 14px;
        color: #ffffff;
        line-height: 23px;
        z-index: 9;
        padding: 0 6px;
      }
    }
.videobutton {
         position: absolute;
         top: 40%;
         left: 50%;
         transform: translate(-50%);
         cursor: pointer;
         width: 40px;
         height: 40px;
         display: inline-block;
         background: #999;
         border-radius: 50%;
      }
      .videoDisplay {
         display: flex;
         flex-wrap: wrap;
         width: 200px;
         height: 200px;
    .videobutton {
      position: absolute;
      top: 40%;
      left: 50%;
      transform: translate(-50%);
      cursor: pointer;
      width: 40px;
      height: 40px;
      display: inline-block;
      background: #999;
      border-radius: 50%;
    }
    .videoDisplay {
      display: flex;
      flex-wrap: wrap;
      width: 200px;
      height: 200px;
      }
    }
      .videotime {
         position: relative;
      }
    .videotime {
      position: relative;
    }
   }
  }
      .content-right {
      position: relative;
      width: 0;
      flex-grow: 1;
      background: #19ad8d;
      margin-right: 17px;
      overflow: hidden;
  .content-right {
    position: relative;
    width: 0;
    flex-grow: 1;
    background: #19ad8d;
    margin-right: 17px;
    overflow: hidden;
      .content-map-popups {
         pointer-events: none;
    .content-map-popups {
      pointer-events: none;
         > * {
            pointer-events: auto !important;
         }
      }
   }
      > * {
        pointer-events: auto !important;
      }
    }
  }
}
</style>