| | |
| | | <div class="itemBox"> |
| | | <div class="itemTitle">{{ item.name }}:</div> |
| | | <div truncated class="itemValue" v-if="item.name !== '飞行事件' && item.name !== '任务执行次数'">{{ |
| | | item.value ? item.value : '--' }}</div> |
| | | item.value ? item.value : '--' }}</div> |
| | | <div class="itemValue" v-if="item.name === '任务执行次数'">{{ item.value ? item.value : '0' |
| | | }}次</div> |
| | | <!-- 飞行事件 --> |
| | |
| | | <span>{{ total }}</span> |
| | | 个 |
| | | </p> |
| | | <p class="more" @click="jumpMore">更多</p> |
| | | <div class="rightBox"> |
| | | <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"> |
| | | <!-- 图片显示 --> |
| | | <!-- :preview-src-list="achievementList.map(i => i.url)" --> |
| | | <template v-for="(item, index) in achievementList" :key="index"> |
| | | <el-image v-if="item.result_type === 0" class="imgItem" :src="getSmallImg(item.url)" |
| | | :preview-src-list="achievementList.map(i => i.url)" show-progress preview-teleported |
| | | :initial-index="index" fit="cover" /> |
| | | <div v-if="item.result_type === 1" class="videotime"> |
| | | <video ref="videoRef" class="videoDisplay" :src="item.url"></video> |
| | | <img @click="enterFullScreen(index)" class="videobutton" |
| | | src="@/assets/images/task/videoshow.png" alt=""> |
| | | </div> |
| | | <el-dialog class="ztzf-dialog " append-to-body modal-class="detailsOfHistoricalTasks" |
| | | v-model="VideoShow" width="1600" :close-on-click-modal="false" |
| | | :destroy-on-close="true"> |
| | | <div class="fullscreen"> |
| | | |
| | | <video ref="fullscreenVideo" class="fullscreen-video" :src="currentVideoUrl" |
| | | :style="{ width: 1600, height: '80vh' }" controls autoplay></video> |
| | | <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-dialog> |
| | | <!-- 图片 --> |
| | | <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> |
| | | |
| | | </template> |
| | | |
| | | </div> |
| | | </div> |
| | | <DeviceJobDetailsMap v-if="isShow" class="contentRight" :detailsData="detailsData" /> |
| | | <DeviceJobDetailsMap v-if="isShow" :yuanImages="yuanImages" class="contentRight" :detailsData="detailsData" /> |
| | | |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 全景360 --> |
| | | <PanoramaPopup |
| | | v-if="'全景'" |
| | | v-model:panoramaParamsShow="panoramaParamsShow" |
| | | v-model:panoramaParamsUrl="panoramaParamsUrl" |
| | | /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import PanoramaPopup from '@/components/PanoramaPopup/PanoramaPopup.vue'; |
| | | import { getShowImg, getSmallImg, getzsSmallImg,getzsShowImg } from '@/utils/util'; |
| | | import { getaiImagesPageAPI,cancelDownloadApi,getDownloadStatusApi,attachDownload} from '@/api/dataCenter/dataCenter'; |
| | | import { pxToRem } from '@/utils/rem' |
| | | import JobRelatedEvents from './JobRelatedEvents.vue' |
| | | import { getEventMediaListApi, getJobDetails, getJobInfoFiles } from '@/api/job/task' |
| | | import { getEventMediaListApi, getJobDetails, getJobInfoFiles,getJobsAllFiles } from '@/api/job/task' |
| | | import DeviceJobDetailsMap from './DeviceJobDetailsMap.vue' |
| | | import { droneEventList } from '../const/drc' |
| | | import { ElMessage } from 'element-plus' |
| | | import { ElMessage,ElLoading } from 'element-plus' |
| | | import { useStore } from 'vuex'; |
| | | const store = useStore(); |
| | | const htlsrwxq = computed(() => store.state.common.downloadProgress?.htlsrwxq || 100) |
| | | const isShow = defineModel('show') |
| | | const VideoShow = ref(false) |
| | | const showAll = ref(false) // 是否展示全部 |
| | | let loadingData |
| | | // 原图 |
| | | const yuanImages = ref([]) |
| | | function convertVideoUrlToThumbnail(videoUrl) { |
| | | // 检查是否是有效的视频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' }, |
| | |
| | | // 任务成果 |
| | | const total = ref(0) |
| | | const achievementList = ref([]) |
| | | const props = defineProps(['wayLineJodInfoId', 'waylineJobId', 'batchNo']) |
| | | const props = defineProps(['wayLineJodInfoId', 'waylineJobId', 'batchNo','jobId']) |
| | | const wayLineJodInfoId = computed(() => props.wayLineJodInfoId) |
| | | provide('wayLineJodInfoId', wayLineJodInfoId) |
| | | // 可见数量 |
| | | const visibleCount = computed(() => |
| | | showAll.value ? achievementList.value.length : Math.min(5, achievementList.value.length) |
| | | ) |
| | | const getAchievement = () => { |
| | | if (!props.wayLineJodInfoId) return |
| | | const params = { |
| | | "way_line_jod_info_id": props.wayLineJodInfoId, |
| | | "batch_no": props.batchNo |
| | | if (!props.jobId) return |
| | | |
| | | const attachmentsParams = { |
| | | 'wayLineJobId': props.jobId, |
| | | 'resultTypes': [0, 1, 3, 4, 5], |
| | | 'orderByCreateTime': true, |
| | | } |
| | | getEventMediaListApi(params).then(res => { |
| | | achievementList.value = res.data.data.slice(0, 5) |
| | | total.value = res.data.data.length |
| | | const pageParams = { |
| | | current: 1, |
| | | size: 2000, |
| | | } |
| | | getaiImagesPageAPI(attachmentsParams,pageParams ).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) |
| | | }) |
| | | } |
| | | const jumpMore = () => { |
| | | ElMessage.warning('正在加急开发中...') |
| | | } |
| | | const getSmallImg = url => { |
| | | return url ? url.substring(0, url.lastIndexOf('.')) + '_small' + url.substring(url.lastIndexOf('.')) : '' |
| | | } |
| | | |
| | | const flightEvents = ref([]) |
| | | const jobTimes = ref([]) |
| | | const getDetails = () => { |
| | |
| | | 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 || {} |
| | |
| | | droneEventList.filter(({ value }) => actionActuatorFunc === value) |
| | | ) |
| | | } |
| | | 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 |
| | | console.log('ssssss',yuanImages.value); |
| | | |
| | | }) |
| | | }) |
| | | // flystatus.value = res.data.data.ai_type_str |
| | | }) |
| | |
| | | } |
| | | // 计算当前视频URL |
| | | const currentVideoUrl = computed(() => { |
| | | return achievementList.value[currentVideoIndex.value]?.url || '' |
| | | return achievementList.value[currentVideoIndex.value]?.link || '' |
| | | }) |
| | | // 关闭弹窗处理 |
| | | const handleClose = () => { |
| | |
| | | fullscreenVideo.value.currentTime = 0 |
| | | } |
| | | } |
| | | |
| | | // 下载 |
| | | const downloadFun = async () => { |
| | | const list = achievementList.value.filter(i => i.checked) |
| | | console.log('list',list); |
| | | if (!list?.length) return ElMessage.warning('请选择文件') |
| | | if (list.length === 1) { |
| | | list.forEach((item, index) => { |
| | | const suffix = item.url.split('.').pop() |
| | | aLinkDownloadUtil(item.url, item.nickName + '.' + suffix) |
| | | }) |
| | | } else { |
| | | loadingData = ElLoading.service({ background: 'rgba(0, 0, 0, 0.5)', text: '打包中,请稍等...' }) |
| | | const fileIds = list.map(i => i.id) |
| | | const res = await getDownloadStatusApi({type: 'htlsrwxq'}) |
| | | if (!['CANCELLED','COMPLETED'].includes(res.data.data?.status || 'COMPLETED')){ |
| | | return ElMessage.warning('还有正在处理的') |
| | | } |
| | | attachDownload({ attachIds: fileIds,type:'htlsrwxq' }).finally(()=>{ |
| | | loadingData.close() |
| | | }) |
| | | } |
| | | } |
| | | // 全景预览 |
| | | const panoramaParamsShow = ref(false) |
| | | const panoramaParamsUrl = ref(null) |
| | | const clickpanorama = val => { |
| | | panoramaParamsShow.value = true |
| | | panoramaParamsUrl.value = val.link |
| | | } |
| | | // 取消下载 |
| | | function cancelDownload() { |
| | | cancelDownloadApi({ type:'htlsrwxq' }).then(res =>{ |
| | | ElMessage.success('取消成功') |
| | | }) |
| | | } |
| | | onMounted(() => { |
| | | getDetails() |
| | | getAchievement() |
| | |
| | | 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; |
| | | |
| | | .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: 26px !important; |
| | | border-radius: 0 !important; |
| | | background: transparent !important; |
| | | |
| | | .el-progress-bar__inner{ |
| | | border-radius: 0 !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | p { |
| | | display: inline-block; |
| | | margin-left: 30px; |
| | |
| | | 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; |
| | | } |
| | | |
| | | .quanjing { |
| | | width: 100%; |
| | | height: 100%; |
| | | object-fit: cover; |
| | | cursor: pointer; |
| | | 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; |
| | | } |
| | | } |
| | | |
| | | .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; |
| | |
| | | .videotime { |
| | | position: relative; |
| | | } |
| | | |
| | | // .videobutton { |
| | | // position: absolute; |
| | | // top: 40%; |
| | | // left: 45%; |
| | | // transform: translate(-50%); |
| | | // cursor: pointer; |
| | | // width: 40px; |
| | | // height: 40px; |
| | | // display: inline-block; |
| | | // } |
| | | |
| | | } |
| | | .contentRight { |