forked from drone/command-center-dashboard

罗广辉
2025-04-15 1894e98229bb29c92bddae1fd87d4786494531b2
Merge remote-tracking branch 'origin/master'
15 files modified
407 ■■■■ changed files
src/api/home/common.js 15 ●●●●● patch | view | raw | blame | history
src/assets/images/home/homeLeft/in‌spection-select.png patch | view | raw | blame | history
src/assets/images/home/homeLeft/‌inspection-reset.png patch | view | raw | blame | history
src/assets/images/task/reset.png patch | view | raw | blame | history
src/components/CommonDateTime.vue 19 ●●●● patch | view | raw | blame | history
src/hooks/useMapAggregation/useMapAggregation.js 57 ●●●● patch | view | raw | blame | history
src/store/modules/home.js 12 ●●●●● patch | view | raw | blame | history
src/views/Home/EventOverviewDetail/EventOverviewDetailLeft/EventOverviewDetailLeft.vue 14 ●●●● patch | view | raw | blame | history
src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue 30 ●●●●● patch | view | raw | blame | history
src/views/Home/HomeLeft/InspectionRaskDetails/InspectionRaskDetailsDialog.vue 40 ●●●●● patch | view | raw | blame | history
src/views/Home/SearchBox.vue 133 ●●●●● patch | view | raw | blame | history
src/views/SignMachineNest/MachineLeft/InspectionRaskDetails.vue 4 ●●●● patch | view | raw | blame | history
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceEvent.vue 8 ●●●●● patch | view | raw | blame | history
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJob.vue 18 ●●●● patch | view | raw | blame | history
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue 57 ●●●●● patch | view | raw | blame | history
src/api/home/common.js
@@ -25,3 +25,18 @@
        params,
    })
}
// 机巢搜索
export const searchByKeyword = params => {
    return request({
        url: `/drone-device-core/map/amap/searchByKeyword?keyword=${params}`,
        method: 'get',
    })
}
// 地址搜索
export const selectDeviceList = params => {
    return request({
        url: `/drone-device-core/manage/api/v1/devices/selectDeviceList`,
        method: 'post',
        params,
    })
}
src/assets/images/home/homeLeft/in‌spection-select.png

src/assets/images/home/homeLeft/‌inspection-reset.png

src/assets/images/task/reset.png

src/components/CommonDateTime.vue
@@ -25,8 +25,10 @@
<script setup>
import dayjs from 'dayjs';
import { useStore } from 'vuex'
import { ref, defineEmits } from 'vue';
const store = useStore()
const emit = defineEmits(['change']);
const model = defineModel();
@@ -57,9 +59,22 @@
let timeClick = (item,index) => {
  checked.value = item;
  model.value = dateRanges[item];
  emit('change', dateRanges[item],timeListEnum[index]);
  const newDateRange = dateRanges[item];
  store.commit('setEventTimeType', [checked.value, timeListEnum[index]]);
  model.value = newDateRange;
  emit('change', newDateRange, timeListEnum[index]);
};
onMounted(() => {
  // 如果父组件传入了值,就使用父组件的值 by cpz
  if (model.value && model.value.length === 2) {
    // 根据传入的日期判断是哪个时间范围
    const startDate = model.value[0];
    const endDate = model.value[1];
    if (startDate !== endDate) {
      checked.value = 'week';
    }
  }
});
</script>
<style scoped lang="scss">
src/hooks/useMapAggregation/useMapAggregation.js
@@ -13,6 +13,7 @@
import cesiumOperation from '@/utils/cesium-tsa'
import { getDeviceRegion, getDeviceRegionCount, getEventDetails, getMapEvents } from '@/api/home/aggregation'
import { PolyGradientMaterial } from '@/utils/cesium/Material'
import { start } from 'nprogress'
/**
 * 机巢聚合功能
 */
@@ -53,6 +54,20 @@
  const store = useStore()
  const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode)
  const selectedAreaCode = computed(() => store.state.user.selectedAreaCode)
  const eventTimeType = computed(() => store.state.home.eventTimeType)
  const eventTimeRang = computed(() => store.state.home.eventTimeRang)
  let needFly = true
  const combinedValues = computed(() => ({
    selectedAreaCode: selectedAreaCode.value,
    eventTimeType: eventTimeType.value,
    eventTimeRang: eventTimeRang.value,
  }))
  let saveParams = { area_code: '', date_enum: 'CURRENT_WEEK' }
  // 确定缩放比例
@@ -105,6 +120,7 @@
  // 事件散点
  let eventList = []
  function processChildren (childrens) {
    // console.log(childrens, '事件点')
    return (childrens || []).map(item => {
      const arr = processChildren(item.childrens)
      if (item.data) {
@@ -118,13 +134,15 @@
      if (arr.length !== 0) {
        returnObj.childrens = arr
      }
      console.log(returnObj, '111111')
      return returnObj
    })
  }
  // 获取事件聚合
  function getMapEventCount (area_code) {
    return getMapEvents({ area_code,date_enum:'CURRENT_WEEK' }).then(res => {
  function getMapEventCount (params) {
    console.log(5555555)
    return getMapEvents(params).then(res => {
      const resData = res?.data?.data
      if (resData?.data) {
        eventList = resData?.data
@@ -163,7 +181,9 @@
  const initMapData = async areaCode => {
    eventList = []
    if (!areaCode) return
    const list = type === 'device' ? await getDeviceCount(areaCode) : await getMapEventCount(areaCode)
    saveParams.area_code = areaCode
    console.log(type, '444')
    const list = type === 'device' ? await getDeviceCount(areaCode) : await getMapEventCount(saveParams)
    const splashedList = type === 'device'
      ? await getDeviceList(areaCode)
      : eventList.map(i => ({ eventId: i.id, latitude: Number(i.latitude), longitude: Number(i.longitude), type: 'event' }))
@@ -219,19 +239,23 @@
    }
  }
  watch(combinedValues, async (newValue, oldValue) => {
    if (newValue.eventTimeType) {
      saveParams = { area_code: newValue.selectedAreaCode, date_enum: store.state.home.eventTimeParams }
    }
  let needFly = true
    if (newValue.eventTimeRang) {
      saveParams = { area_code: newValue.selectedAreaCode, start_date: newValue.eventTimeRang[0], end_date: newValue.eventTimeRang[1] }
    }
  watch(
    selectedAreaCode,
    async (newValue, oldValue) => {
      needFly = true
      if (!viewer) return
      viewer.scene.postRender.removeEventListener(determineScaling)
      initMapData(newValue).then(() => {
        viewer.scene.postRender.addEventListener(determineScaling)
      })
    },
    needFly = true
    if (!viewer) return
    viewer.scene.postRender.removeEventListener(determineScaling)
    initMapData(newValue.selectedAreaCode).then(() => {
      viewer.scene.postRender.addEventListener(determineScaling)
    })
  },
    { deep: true }
  )
@@ -437,10 +461,15 @@
    let clickTargets = viewer.scene.drillPick(click.position).map(item => item.id)
    if (!clickTargets.length) return
    console.log(clickTargets, 11111)
    let deviceAggregationFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'deviceAggregation')
    let deviceFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'device')
    // "event"
    let eventFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'event')
    // let eventFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'eventAggregation')
    currentEntity = deviceAggregationFind || deviceFind || eventFind
    if (!currentEntity) return
    if (!currentEntity?.position?._value) return
    // 一定要移除
src/store/modules/home.js
@@ -14,6 +14,10 @@
    singleTotal: {}, // 统计单个机巢数据
    // 项目id
    selectedWorkSpaceId: window.localStorage.getItem('bs_workspace_id'),
    // 事件 日 周 月 年
    eventTimeType: 'day',
    eventTimeParams: 'CURRENT_WEEK',
    eventTimeRang: '',
    wsMessage: {},
    deviceState: {
      gatewayInfo: {},
@@ -113,6 +117,14 @@
                dock.work_osd = info.host
            }
        },
    setEventTimeType : (state, data) => {
      console.log('33333')
      state.eventTimeType = data[0]
      state.eventTimeParams = data[1]
    },
    setEventTimeRang : (state, time) => {
      state.eventTimeRang = time
    },
    },
    getters: {
        test(state) {
src/views/Home/EventOverviewDetail/EventOverviewDetailLeft/EventOverviewDetailLeft.vue
@@ -23,12 +23,18 @@
import EventTrendAnalysis from '@/views/Home/EventOverviewDetail/EventOverviewDetailLeft/EventTrendAnalysis.vue'
import EventTop5 from '@/views/Home/EventOverviewDetail/EventOverviewDetailLeft/EventTop5.vue'
const today = dayjs().format('YYYY-MM-DD')
const timeArr = ref([today, today])
// 选中机巢默认日
// const today = dayjs().format('YYYY-MM-DD')
// const timeArr = ref([today, today])
// 选中事件默认为周
const startOfWeek = dayjs().startOf('week').add(1, 'day').format('YYYY-MM-DD')
const endOfWeek = dayjs().endOf('week').add(1, 'day').format('YYYY-MM-DD')
const timeArr = ref([startOfWeek, endOfWeek])
const store = useStore()
const params = ref({
    date_enum: 'TODAY',
    date_enum: 'CURRENT_WEEK',
    end_date: undefined,
    start_date: undefined,
})
@@ -65,7 +71,7 @@
    align-items: center;
    .dateTime {
        width: 356px;
        width: 400px;
        margin: 0 0 8px 0;
    }
src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue
@@ -114,11 +114,17 @@
import cesiumOperation from '@/utils/cesium-tsa'
import CommonTitle from '@/components/CommonTitle.vue'
import { pxToRem } from '@/utils/rem'
import { useStore } from 'vuex'
const store = useStore()
// const eventTimeRange = computed(() => store.state.home.eventTimeRange)
const timeFormat = 'YYYY-MM-DD HH:mm:ss'
const today = dayjs().format(timeFormat)
const oneWeekAgo = dayjs().subtract(7, 'day').format(timeFormat)
const timeArr = ref([oneWeekAgo, today])
// const oneWeekAgo = dayjs().subtract(7, 'day').format(timeFormat)
// const timeArr = ref([oneWeekAgo, today])
const startOfWeek = dayjs().startOf('week').add(1, 'day').format(timeFormat)
const endOfWeek = dayjs().endOf('week').add(1, 'day').format(timeFormat)
const timeArr = ref([startOfWeek, endOfWeek])
const deviceList = ref([])
const total = ref(0)
@@ -211,6 +217,8 @@
    const [start_date, end_date] = timeArr.value
    params.value.start_date = start_date
    params.value.end_date = end_date
    // 提交数据,更新聚合
    store.commit('setEventTimeRang', timeArr.value);
    // 重置
    getEventStatusNumFun()
    getEventList()
@@ -237,6 +245,24 @@
    })
}
const getDateRange = unit => {
  if (unit === 'today') {
    return [dayjs().format('YYYY-MM-DD HH:mm:ss'), dayjs().format('YYYY-MM-DD HH:mm:ss')];
  }
  return [dayjs().startOf(unit).format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf(unit).format('YYYY-MM-DD HH:mm:ss')];
};
// 监听事件时间范围变化
watch(() => store.state.home.eventTimeType, (newVal) => {
    timeArr.value = getDateRange(newVal);
    const [start_date, end_date] = getDateRange(newVal);
    params.value.start_date = start_date
    params.value.end_date = end_date
    getEventStatusNumFun()
    getEventList()
    getList()
}, { immediate: false,deep: true })
onMounted(() => {
    getDeviceList()
    getDictList()
src/views/Home/HomeLeft/InspectionRaskDetails/InspectionRaskDetailsDialog.vue
@@ -54,8 +54,8 @@
                    />
                </el-form-item>
                <el-form-item>
                    <div class="reset" @click="handleReset"></div>
                    <div class="searchs" @click="handleSearch"></div>
                    <div class="reset" @click="handleReset">重置</div>
                    <div class="searchs" @click="handleSearch">搜索</div>
                </el-form-item>
            </div>
        </el-form>
@@ -86,8 +86,8 @@
                                    ? 'distributed'
                                    : scope.row.status === 3
                                    ? 'finish '
                                    : scope.row.status === 4
                                    ? 'cancel '
                                    : 'fail '
                            "
                        >
@@ -97,10 +97,9 @@
                                    : scope.row.status === 2
                                    ? '执行中'
                                    : scope.row.status === 3
                                    ? '完成'
                                    : scope.row.status === 4
                                    ? '取消'
                                    : '失败'
                                    ? '已执行'
                                    : '执行失败'
                            }}
                        </span>
                    </template>
@@ -112,11 +111,11 @@
                        <span>{{ scope.row.event_number ? scope.row.event_number : '/' }}</span>
                    </template>
                </el-table-column>
                <el-table-column label="操作" width="80"><div class="ztzf-view ">查看</div></el-table-column>
                <el-table-column label="操作" width="80"><div class="ztzf-view">查看</div></el-table-column>
            </el-table>
        </div>
        <!-- 分页 -->
        <div style="display: flex;justify-content: center">
        <div style="display: flex; justify-content: center">
            <el-pagination
                class="ztzf-pagination"
                v-model:current-page="pageParams.current"
@@ -151,8 +150,8 @@
    { label: '待执行', value: 1 },
    { label: '执行中', value: 2 },
    { label: '已完成', value: 3 },
    { label: '已取消', value: 4 },
    { label: '执行失败', value: 5 },
    { label: '执行失败', value: 4 },
]
// 设备页面参数
const devicePageParams = ref({
@@ -217,10 +216,12 @@
}
// 获取任务列表
const getJobList = () => {
// 事件状态:0 =待处理,1=待分拨,2=待处理,3=处理中,4=已完成 5=已完结
    jobList(taskDetailParams).then(res => {
        if (res.data.code !== 0) return
        taskDetailData.value = res.data.data.records
        total.value = res.data.data.total
    })
}
// 机巢列表数据
@@ -278,8 +279,6 @@
}
:deep() {
    .el-form-item__label {
        font-family: Segoe UI, Segoe UI;
        font-weight: 400;
@@ -303,6 +302,10 @@
    cursor: pointer;
    background: url('/src/assets/images/home/homeLeft/‌inspection-reset.png') no-repeat center;
    background-size: 100% 100%;
    color: #fff;
    font-weight: bold;
    font-size: 14px;
    text-align: center;
}
.searchs {
    margin-left: 23px;
@@ -311,6 +314,10 @@
    height: 32px;
    background: url('/src/assets/images/home/homeLeft/in‌spection-select.png') no-repeat center;
    background-size: 100% 100%;
    color: #fff;
    font-weight: bold;
    font-size: 14px;
    text-align: center;
}
.tabledata {
    padding: 0 16px;
@@ -338,10 +345,7 @@
</style>
<style lang="scss">
.inspection-rask-details-dialog {
     width: 1270px;
    width: 1270px;
    height: 856px;
}
</style>
src/views/Home/SearchBox.vue
@@ -1,7 +1,7 @@
<template>
  <div class="searchBox">
  <div class="searchBox" ref="searchBoxRef">
    <div class="searchInput">
      <el-select v-model="value" placeholder="请选择查询">
      <el-select v-model="optionsValue" @change="optionChange" placeholder="请选择查询">
        <el-option
          v-for="item in options"
          :key="item.value"
@@ -10,9 +10,9 @@
        />
      </el-select>
      <el-input v-model="input3" placeholder="请输入搜索关键字"></el-input>
      <el-input v-model="searchKey"  @focus="handleFocus" placeholder="请输入搜索关键字"></el-input>
    </div>
    <div class="searchBtn"></div>
    <div class="searchBtn" @click="searchClick"></div>
    <div class="region">
      <el-tree-select
        v-model="treeValue"
@@ -25,20 +25,30 @@
      />
    </div>
  </div>
  <div class="select-down-list" ref="selectDownRef" v-show="isSelectDown">
    <div class="item" v-for="item in downList" @click="selectedValue(item)">{{ item.nickname || item.name }}</div>
  </div>
</template>
<script setup>
import { getRegion } from '@/api/home';
import { searchByKeyword, selectDeviceList } from '@/api/home/common';
import { useStore } from 'vuex';
import cesiumOperation from '@/utils/cesium-tsa'
const { flyTo } = cesiumOperation()
const store = useStore();
const input3 = ref('');
const searchKey = ref('');
const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode);
const selectedAreaCode = computed(() => store.state.user.selectedAreaCode);
const value = ref('Option1');
const areaValue = ref('江西省');
const treeValue = ref(userAreaCode.value);
let first = true;
const searchBoxRef = ref(null);
const selectDownRef = ref(null);
function treeChange(value) {
function treeChange(value, node) {
  areaValue.value = node.label;
  store.commit('setSelectedAreaCode', value);
}
@@ -62,20 +72,123 @@
  });
};
const optionsValue = ref('1');
const options = [
  {
    value: 'Option1',
    value: '1',
    label: '机巢',
  },
  {
    value: 'Optio44n1',
    value: '2',
    label: '地址',
  },
];
onMounted(() => {});
const isSelectDown = ref(false);
// 下拉数据列表
const machineNestList = ref([]);
// 地址搜索结果
const downList = ref([]);
const position = ref({});
// 获取机巢搜索结果
const getDeviceList = async () => {
  const res = await selectDeviceList({
    keyword: searchKey.value,
  });
  if (res.data.code !== 0) return;
  machineNestList.value = res?.data?.data || [];
  downList.value = res?.data?.data || [];
};
// 获取地址搜索结果
const getAddressList = async () => {
  const res = await searchByKeyword(encodeURIComponent(`${areaValue.value}+${searchKey.value}`));
  if (res.data.code !== 0) return;
  downList.value = res?.data?.data.tips || [];
  if (downList.value.length > 0) {
    isSelectDown.value = true;
  }
};
// 搜索结果
const searchClick = () => {
    const longitude = Number(position.value.longitude)
    const latitude = Number(position.value.latitude)
    flyTo({ longitude, latitude }, 1, 1000)
};
// 地址和机巢的切换
const optionChange = () => {
  searchKey.value = '';
  downList.value = [];
};
// 输入框获取焦点
const handleFocus = () => {
  if (optionsValue.value === '1') {
    isSelectDown.value = true;
    downList.value = machineNestList.value;
  }
};
// 机巢下拉获取值
const selectedValue = item => {
  searchKey.value = item.nickname || item.name;
  if (optionsValue.value === '1') {
    position.value = item;
  } else {
    position.value = { longitude: item.location.split(',')[0], latitude: item.location.split(',')[1] };
  }
  isSelectDown.value = false;
};
// 监听搜索关键字变化
watch(searchKey, async (newVal) => {
  if (optionsValue.value === '2') {
    await getAddressList();
  }
}, { immediate: false });
onMounted(() => {
  getDeviceList();
  document.addEventListener('click', handleClickOutside);
});
onUnmounted(() => {
  document.removeEventListener('click', handleClickOutside);
});
const handleClickOutside = (event) => {
  if (!searchBoxRef.value?.contains(event.target) && !selectDownRef.value?.contains(event.target)) {
    isSelectDown.value = false;
  }
};
</script>
<style scoped lang="scss">
.select-down-list {
  position: absolute;
  top: 188px;
  left: 45%;
  transform: translateX(-45%);
  width: 220px;
  height: 256px;
  overflow-y: auto;
  background: linear-gradient( 180deg, #0D3556 0%, #012350 100%);
  border-radius: 0px 0px 8px 8px;
  border: 1px solid;
  border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1;
  &::-webkit-scrollbar {
    width: 0;
    display: none;
  }
  -ms-overflow-style: none;  /* IE and Edge */
  scrollbar-width: none;  /* Firefox */
  .item {
    color: #FFFFFF;
    height: 32px;
    line-height: 32px;
    text-align: center;
    cursor: pointer;
  }
}
.searchBox {
  width: 420px;
  height: 43px;
src/views/SignMachineNest/MachineLeft/InspectionRaskDetails.vue
@@ -1,6 +1,6 @@
<!-- 巡检任务数据 -->
<!-- 任务事件概况 -->
<template>
    <common-title title="巡检任务详情" :style="{ marginLeft: pxToRem(14) }"></common-title>
    <common-title title="任务事件概况" :style="{ marginLeft: pxToRem(14) }"></common-title>
    <div class="inspection-rask-details">
        <CommonDateTime :style="{ top: pxToRem(14),marginLeft: pxToRem(10) }" v-model="newTime" @change="getData"></CommonDateTime>
        <div class="chart-container" ref="chartRef"></div>
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceEvent.vue
@@ -6,7 +6,7 @@
                >件
            </p>
        </div>
        <div class="deviceevent-table ztzf-table">
        <div class="deviceevent-table ztzf-table" >
            <el-table :data="list" :row-class-name="tableRowClassName"
            style="width: 100%;"
            :row-style="{ height: '38px', fontSize: '14px', 'text-align': 'center' }"
@@ -40,10 +40,10 @@
        <el-pagination
        class="ztzf-pagination"
            background
            :page-sizes="[10, 20, 30, 50]"
            v-model:current-page="sizeParams.current"
            v-model:page-size="sizeParams.size"
            layout="prev, pager, next,sizes, jumper"
            layout="prev, pager, next, jumper"
            :total="total"
            @change="pageChange"
        />
@@ -79,6 +79,7 @@
        const resData = res?.data?.data || {}
        list.value = resData.records
        total.value = resData.total
    })
    
    
@@ -127,6 +128,7 @@
// 表格
.deviceevent-table {
padding: 0 17px;
}
// 分页
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJob.vue
@@ -2,8 +2,9 @@
    <div class="devicejob-container">
        <div class="machineTableDetailsTitle">
            <p>
                相关任务<span>{{ total }}</span
                >次
                相关任务
                <span>{{ total }}</span>
                次
            </p>
        </div>
        <div class="devicelob-table ztzf-table">
@@ -35,10 +36,10 @@
        <el-pagination
        class="ztzf-pagination"
            background
            :page-sizes="[10, 20, 30, 50]"
            v-model:current-page="sizeParams.current"
            v-model:page-size="sizeParams.size"
            layout=" prev, pager, next,sizes, jumper"
            layout=" prev, pager, next, jumper"
            :total="total"
            @change="pageChange"
        />
@@ -120,8 +121,15 @@
// 表格
.devicelob-table {
    padding: 0 17px;
    // height: 280px;
    // overflow: hidden;
    // overflow-y: scroll !important;
}
// :deep(::-webkit-scrollbar) {
//     width: 0;
//     display: none;
//     background: none !important;
// }
// 分页
:deep(.el-pagination) {
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue
@@ -18,7 +18,7 @@
                        <div v-for="(item, index) in infoList" :key="index">
                            <div class="itemBox">
                                <div class="itemTitle">{{ item.name }}:</div>
                                <div class="itemValue">{{ item.value ? item.value :''}}</div>
                                <div class="itemValue">{{ item.value ? item.value : '' }}</div>
                            </div>
                        </div>
                    </div>
@@ -37,17 +37,24 @@
                    <p class="more">更多</p>
                </div>
                <div class="imgListBox">
                    <el-image
                        class="imgItem"
                        v-for="(item, index) in achievementList"
                        :key="index"
                        :src="item.url"
                        :preview-src-list="achievementList.map(i => i.url)"
                        show-progress
                        preview-teleported
                        :initial-index="index"
                        fit="cover"
                    />
                    <!-- 图片显示 -->
                    <template v-if="mediaType === 'image'">
                        <el-image
                            class="imgItem"
                            v-for="(item, index) in achievementList"
                            :key="index"
                            :src="item.url"
                            :preview-src-list="achievementList.map(i => i.url)"
                            show-progress
                            preview-teleported
                            :initial-index="index"
                            fit="cover"
                        />
                    </template>
                    <!-- 视频显示 -->
                    <template v-else-if="mediaType === 'video'">
                        <video v-for="(item, index) in achievementList" :key="index" :src="item.url" controls></video>
                    </template>
                </div>
            </div>
            <DeviceJobDetailsMap v-if="isShow" class="contentRight" :detailsData="detailsData" />
@@ -90,34 +97,38 @@
    creator_name: null,
    way_lines: [],
})
// 任务成果
const mediaType = ref('')
const total = ref(0)
const achievementList = ref([])
const wayLineJodInfoId = inject('wayLineJodInfoId')
const getAchievement = () => {
    getJobInfoFiles({ jobInfoId: wayLineJodInfoId.value }).then(res => {
        for (let i = 0; i < res.data.data.length; i++) {
            const url = res.data.data[i].url || ''
            const ext = String(url)?.split('.')?.pop().toLowerCase() || ''
            const images = ['jpg', 'jpeg', 'png', 'gif', 'webp']
            const videos = ['mp4', 'webm', 'ogg', 'mov']
            mediaType.value = images.includes(ext) ? 'image' : videos.includes(ext) ? 'video' : ''
        }
        achievementList.value = res.data.data
        total.value = res.data.data.length
    })
}
const getDetails = () => {
    getJobDetails({ wayLineJobInfoId: wayLineJodInfoId.value }).then(res => {
    console.log('res',res);
        detailsData.value = res.data.data
        infoList.value.forEach(item => {
            if (item.name === '任务时间') {
                item.value = detailsData.value.begin_time.slice(0,10) + '-' + detailsData.value.end_time.slice(0,10)
            }
        else if (item.name === '任务频次') {
                item.value === undefined ?'': detailsData.value.rep_rule_type + '-' + detailsData.value.rep_rule_val
            }
            else {
                item.value = detailsData.value.begin_time.slice(0, 10) + '-' + detailsData.value.end_time.slice(0, 10)
            } else if (item.name === '任务频次') {
                item.value = detailsData.value.rep_rule_type + ' -- ' + detailsData.value.rep_rule_val
            } else {
                item.value = detailsData.value?.[item.field] || ''
            }
        })
        flystatus.value = res.data.data.ai_type_str
        // console.log('历史任务详情', res.data.data)
    })
}
@@ -231,7 +242,7 @@
        .imgListBox {
            display: flex;
            flex-wrap: wrap;
            gap: 0 10px;
            gap: 10px;
            .imgItem {
                width: 200px;