| .env.development | ●●●●● patch | view | raw | blame | history | |
| src/api/dataCenter/dataCenter.js | ●●●●● patch | view | raw | blame | history | |
| src/assets/images/dataCenter/filePackage.png | patch | view | raw | blame | history | |
| src/hooks/components/EventPopUpBox.vue | ●●●●● patch | view | raw | blame | history | |
| src/permission.js | ●●●●● patch | view | raw | blame | history | |
| src/utils/util.js | ●●●●● patch | view | raw | blame | history | |
| src/views/dataCenter/components/dataCenterMap.vue | ●●●●● patch | view | raw | blame | history | |
| src/views/dataCenter/components/searchData.vue | ●●●●● patch | view | raw | blame | history | |
| src/views/dataCenter/dataCenter.vue | ●●●●● patch | view | raw | blame | history | |
| src/views/job/components/JobRelatedEvents.vue | ●●●●● patch | view | raw | blame | history |
.env.development
@@ -21,7 +21,7 @@ # 服务地址 VITE_APP_URL = https://wrj.shuixiongit.com/api #VITE_APP_URL= http://192.168.1.168 rjg #VITE_APP_URL= http://192.168.1.168 #VITE_APP_URL= http://192.168.1.33 #新大屏地址 VITE_APP_DASHBOARD_URL = 'https://wrj.shuixiongit.com/command-center-dashboard/' src/api/dataCenter/dataCenter.js
@@ -81,3 +81,19 @@ }, }) } // 获取机场下的文件夹 export const getJobIdsBySnApi = (params, dockSn) => { return request({ url: `/drone-device-core/wayline/api/v1/workspaces/getJobIdsBySn`, method: 'get', params, }) } // 附件下载 export const attachDownload = (data) => { return request({ url: `/blade-resource/attach/download`, method: 'post', data }) } src/assets/images/dataCenter/filePackage.png
src/hooks/components/EventPopUpBox.vue
@@ -1,11 +1,28 @@ <template> <div class="mapPopUpBox"> <div class="title"> <span>{{ info.event_name }}</span> <el-icon class="header-close" @click.stop="props.detailClick"><Warning /></el-icon> <el-tooltip v-if="infoList.resultType === 2" effect="dark" :content="infoList.eventName" placement="top" :disabled="!shouldShowTooltip" > <span ref="titleSpan" class="title-text"> {{ infoList.eventName?infoList.eventName:'--' }} </span> </el-tooltip> <el-tooltip v-else effect="dark" :content="infoList.nickName" placement="top" :disabled="!shouldShowTooltip"> <span ref="titleSpan" class="title-text" > {{ infoList.nickName }} </span> </el-tooltip> <div> <el-icon class="header-close" @click.stop="props.detailClick"><Warning /></el-icon> <el-icon class="header-close" @click.stop="props.removeLabel"> <Close /> </el-icon> </div> </div> <div class="content"> <div class="medium"> @@ -27,6 +44,12 @@ </div> <div class="details"> <div class="label" v-if="infoList.resultType === 2">事件编号:</div> <div class="value point" v-if="infoList.resultType === 2"> {{ infoList?.eventNum ? infoList?.eventNum : '--' }} </div> <div class="label">时间:</div> <div class="value point"> {{ @@ -36,8 +59,8 @@ </div> <div class="label">地点:</div> <div class="value"> {{ _.round(infoList?.metadata?.shootPosition?.lng, 3) }},{{ _.round(infoList?.metadata?.shootPosition?.lat, 3) {{ _.round(infoList?.metadata?.shootPosition?.lng, 6) }},{{ _.round(infoList?.metadata?.shootPosition?.lat, 6) }} </div> </div> @@ -63,6 +86,8 @@ create_time: '04/01 12:41', }); const infoList = props.data; console.log('infoList',infoList); const clickpanorama = val => { // 通过事件总线发送全景参数 EventBus.emit('open-panorama', { @@ -78,8 +103,8 @@ <style scoped lang="scss"> .mapPopUpBox { width: 271px; height: 153px; width: 291px; height: 183px; // background: url('@/assets/images/dataCenter/datamap/popUpBox.png') no-repeat center / 100% 100%; border-radius: 20px; background-color: #fff; @@ -92,19 +117,18 @@ font-weight: 400; font-size: 18px; line-height: 16px; background: linear-gradient(180deg, #a8e5fb 0%, #e6f8ff 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; -moz-background-clip: text; -moz-text-fill-color: transparent; background-clip: text; text-fill-color: transparent; margin-bottom: 10px; display: flex; align-items: center; justify-content: end; .header-close { justify-content: space-between; .title-text { color: black; } div{ display: flex; align-items: center; .header-close { width: 20px; height: 100%; line-height: 100%; @@ -114,17 +138,19 @@ pointer-events: all; cursor: pointer; } } } .content { height: 102px; width: 240px; height: 132px; // width: 240px; display: flex; align-items: center; .medium { height: 102px; width: 120px; height: 122px; width: 140px; margin-right: 10px; > img, @@ -152,10 +178,11 @@ color: black; line-height: 16px; margin-bottom: 2px; white-space: nowrap; } .point { margin-bottom: 14px; margin-bottom: 10px; } } } src/permission.js
@@ -126,9 +126,17 @@ } }) // router.afterEach(to => { // NProgress.done() // let title = router.$avueRouter.generateTitle(to, { label: 'name' }) // router.$avueRouter.setTitle(title) // store.commit('SET_IS_SEARCH', false) // }) router.afterEach(to => { NProgress.done() let title = router.$avueRouter.generateTitle(to, { label: 'name' }) router.$avueRouter.setTitle(title) store.commit('SET_IS_SEARCH', false) }) NProgress.done() const isLoginPage = to.path === '/login' // 根据是否登录页设置标题 const pageTitle = isLoginPage ? '中图智飞低空感知网平台' : '综合管理平台' document.title = pageTitle store.commit('SET_IS_SEARCH', false) }) src/utils/util.js
@@ -459,6 +459,16 @@ return `${url.substring(0, lastDotIndex)}_show${url.substring(lastDotIndex)}` } /** * 获取正射路径 * @param url * @returns {string} */ export const getzsShowImg = url => { if (!url) return '' const lastDotIndex = url.lastIndexOf('.') return `${url.substring(0, lastDotIndex)}_show.jpeg` } // key驼峰转换为下划线 export function camelToSnake (obj) { if (typeof obj !== 'object' || obj === null) { src/views/dataCenter/components/dataCenterMap.vue
@@ -232,7 +232,6 @@ try { const res = await getMapInfoAPI(ids); dataPointList.value = res.data.data || []; if (isMapInitialized.value && viewer) { renderDataPoint(dataPointList.value); } src/views/dataCenter/components/searchData.vue
@@ -2,8 +2,9 @@ <div class="search-box-test"> <el-form :model="searchForm" inline> <div class="search-first"> <el-form-item label="行政区划:"> <el-form-item label="行政区划:" > <el-tree-select :disabled="foldersDisabled" popper-class="custom-tree-select" v-model="searchForm.areaCode" :data="deptTreeData" @@ -16,6 +17,7 @@ </el-form-item> <el-form-item label="所属机巢:"> <el-select :disabled="foldersDisabled" :teleported="false" v-model="searchForm.deviceSn" placeholder="请选择" @@ -59,6 +61,7 @@ </el-form-item> <el-form-item label="文件格式:"> <el-select :disabled="foldersDisabled" :teleported="false" v-model="searchForm.resultType" placeholder="请选择" @@ -76,7 +79,8 @@ </el-form-item> <el-form-item label="文件类别:"> <el-select :disabled="disabled" :disabled="disabled || foldersDisabled" :teleported="false" v-model="searchForm.photoType" placeholder="请选择" @@ -95,7 +99,7 @@ </div> <div class="search-first"> <el-form-item label="文件名称:"> <el-input v-model="searchForm.name" placeholder="请输入" clearable /> <el-input :disabled="foldersDisabled" v-model="searchForm.name" placeholder="请输入" clearable /> </el-form-item> <div class="search-btn"> <el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button> @@ -107,6 +111,7 @@ <!-- <el-button type="primary" icon="el-icon-download" @click="allDownloadFun"--> <!-- >全部下载</el-button--> <!-- >--> <el-button type="primary" plain @click="handleswitchFolders" ><el-icon><FolderOpened /></el-icon></el-button> <div class="downloadBtn" @click="htsjzx === 100 && downloadFun()"> <el-progress v-if="htsjzx !== 100" :percentage="htsjzx" :show-text="false" striped striped-flow :duration="1" /> <div class="downloadBtnText"> @@ -135,13 +140,13 @@ const userAreaCode = computed(() => store.getters.userInfo.detail.areaCode); const selectedAreaCode = computed(() => store.state.user.selectedAreaCode); const htsjzx = computed(() => store.state.common.downloadProgress?.htsjzx || 100) const emit = defineEmits(['search', 'downFun', 'allDownFun']); const emit = defineEmits(['search', 'downFun', 'allDownFun','handleswitchFolders']); const startTime = dayjs().subtract(6, 'day').startOf('day'); const endTime = dayjs().endOf('day'); const timeRange = [startTime.format('YYYY-MM-DD HH:mm:ss'), endTime.format('YYYY-MM-DD HH:mm:ss')]; const dateRange = ref(timeRange); const timeFormat = 'YYYY-MM-DD HH:mm:ss'; const props = defineProps(['searchjobId','switchFolders']) const searchForm = reactive({ jobName: '', //任务名称 name: '', //文件名称 @@ -151,6 +156,7 @@ deviceSn: '', // 所属机巢 resultType: '', //文件格式 photoType: '', //文件类别 wayLineJobId:'' }); const disabled = ref(false); const treeProps = { @@ -207,6 +213,18 @@ }, { deep: true } ); watch(() => props.searchjobId, (newVal) => { searchForm.wayLineJobId = newVal; handleSearch() }); const foldersDisabled = ref(false) watch(() => props.switchFolders, (newVal) => { if(newVal === true){ foldersDisabled.value = true }else{ foldersDisabled.value = false } }); const changePhotoType =(val)=>{ if(val === undefined){ searchForm.photoType = '' @@ -322,7 +340,10 @@ ElMessage.success('取消成功') }) } // 切换文件夹 const handleswitchFolders =()=>{ emit('handleswitchFolders'); } onMounted(() => { requestDockInfo(); getDownloadStatusApi({type: 'htsjzx'}).then(res =>{ @@ -346,9 +367,12 @@ justify-content: space-between; .search-btn { display: flex; align-items: center; margin-right: 32px; .downloadBtn{ margin-left: 10px; position: relative; display: flex; align-items: center; src/views/dataCenter/dataCenter.vue
@@ -4,12 +4,30 @@ > <div class="dataCenter-table"> <searchData :searchjobId="searchjobId" :switchFolders="switchFolders" @search="searchClick" @downFun="downloadFile" @allDownFun="aLLDownloadFile" @handleswitchFolders="handleswitchFolders" ></searchData> <!-- 文件夹 --> <div class="fileshow" v-if="switchFolders" v-loading="loadings " element-loading-text="加载中"> <div class="filePackage" v-for="(folderItem, fileIndex) in folderList" :key="fileIndex" @click.stop="foldersOpen(folderItem)" > <img :src="fileimg" alt="" /> <el-checkbox v-model="folderItem.checked" @click.stop /> <div class="itemName" :title="folderItem.name"> <div>{{ folderItem.name }}</div> </div> </div> </div> <!-- 表格部分 --> <div class="dataTable"> <div class="dataTable" v-else> <el-table border stripe @@ -124,16 +142,16 @@ </div> <!-- 分页 --> <div class="pagination"> <el-pagination v-model:current-page="jobListParams.current" v-model:page-size="jobListParams.size" :page-sizes="[10, 20, 30, 40]" background layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> <el-pagination :current-page="switchFolders ? FolderListParams.page : jobListParams.current" :page-size="switchFolders ? FolderListParams.page_size : jobListParams.size" :page-sizes="[10, 20, 30, 40]" background layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> </div> <!-- 查看弹框 --> <el-dialog @@ -278,6 +296,11 @@ </template> <script setup> import fileimg from '@/assets/images/dataCenter/filePackage.png' import { getShowImg, getSmallImg, getzsSmallImg } from '@/utils/util'; import { onMounted, watch } from 'vue'; import dayjs from 'dayjs'; import ElTooltipCopy from '@/components/ElTooltipCopy.vue'; import videoplay from '@/assets/images/dataCenter/videoplay.png'; import positionicon from '@/assets/images/dataCenter/positionicon.png'; import { useStore } from 'vuex'; @@ -308,12 +331,9 @@ deleteFileMultipleApi, downloadApi, updataTitleApi, getOrthoimageInfo, getDownloadStatusApi getOrthoimageInfo, getDownloadStatusApi,getJobIdsBySnApi } from '@/api/dataCenter/dataCenter'; import { getShowImg, getSmallImg, getzsSmallImg } from '@/utils/util'; import { onMounted, watch } from 'vue'; import dayjs from 'dayjs'; import ElTooltipCopy from '@/components/ElTooltipCopy.vue'; const switchFolders = ref(false) function bytesToMB(bytes, decimalPlaces = 2) { if (typeof bytes !== 'number' || bytes < 0) return '0'; @@ -397,6 +417,14 @@ orderByCreateTime: true, searchParams: { startTime: timeRange[0], endTime: timeRange[1] }, }); const FolderListParams = reactive({ page: 1, page_size: 30, startTime: jobListParams.searchParams.startTime?.slice(0, 10), endTime: jobListParams.searchParams.endTime?.slice(0, 10), waylineName:'', }); const tableData = ref([]); // 获取列表数据 @@ -406,7 +434,6 @@ orderByCreateTime: jobListParams.orderByCreateTime, ...jobListParams.searchParams, }; getaiImagesPageAPI(params, { current: jobListParams.current, size: jobListParams.size, @@ -423,27 +450,86 @@ })); }) .catch(error => { // 可选:这里可以添加错误处理逻辑 console.error('获取数据失败:', error); }) .finally(() => { loadings.value = false; // 无论成功失败都会执行 loadings.value = false; }); }; const folderList = ref([]) // 获取文件夹数据 const getFolderList=()=>{ loadings.value = true; const apiParams = { ...FolderListParams, }; getJobIdsBySnApi(apiParams) .then(res => { folderList.value = res.data.data.records.map(i => ({ ...i, checked: false })) total.value = res.data.data.total }) .finally(() => { loadings.value = false; }) } const searchjobId = ref('') const foldersOpen = (val)=>{ loadings.value = true; tableData.value=[] searchjobId.value = val.job_id switchFolders.value = false } // 获取数据时使用各自的分页参数 const fetchData = () => { loadings.value = true; if (switchFolders.value) { getFolderList(); } else { getaiImagesPage(); } }; // 切换文件夹 const handleswitchFolders = () => { switchFolders.value = !switchFolders.value; jobListParams.current = 1; FolderListParams.page = 1; fetchData(); }; // 查询 const searchClick = params => { jobListParams.current = 1; jobListParams.size = 10; jobListParams.searchParams = params; getaiImagesPage(); if(switchFolders.value){ FolderListParams.page = 1; FolderListParams.page_size = 30; FolderListParams.startTime = params.startTime?.slice(0, 10); FolderListParams.endTime = params.endTime?.slice(0, 10); FolderListParams.waylineName=params.jobName, getFolderList() }else{ jobListParams.current = 1; jobListParams.size = 10; jobListParams.searchParams = { ...jobListParams.searchParams, ...params }; getaiImagesPage() } }; const handleSizeChange = val => { jobListParams.size = val; getaiImagesPage(); const handleSizeChange = (val) => { if (switchFolders.value) { FolderListParams.page_size = val; } else { jobListParams.size = val; } fetchData(); }; const handleCurrentChange = val => { jobListParams.current = val; getaiImagesPage(); const handleCurrentChange = (val) => { if (switchFolders.value) { FolderListParams.page = val; } else { jobListParams.current = val; } fetchData(); }; // 多选 const selectedRows = ref([]); @@ -517,9 +603,20 @@ }); } }; // 文件夹打包下载 async function folderDownload() { const jobId = folderList.value.filter(i => i.checked).map(i => i.job_id) if (!jobId?.length) return ElMessage.warning('请选择文件夹') const res = await getDownloadStatusApi({type: 'dpsjzx'}) if (!['CANCELLED','COMPLETED'].includes(res.data.data?.status || 'COMPLETED')){ return ElMessage.warning('还有正在处理的') } await downloadApi({ wayLineJobIds:jobId, withFolder: true, resultType: 0, type:'htsjzx' }) } // 下载 const downloadFile = () => { fileDownload(); switchFolders.value?folderDownload(): fileDownload(); }; const detailDownLoad = val => { const suffix = val.link?.split('.').pop(); @@ -724,7 +821,6 @@ isMapInitialized.value = false; } function handleCellClick(row, column) { console.log(row,column.no) if (column.no === 5) { navigator.clipboard.writeText(row.nickName).then(() => { ElMessage.success('复制文件名称成功') @@ -746,7 +842,6 @@ viewInstance.value?.viewerDestroy(); }); </script> <style scoped lang="scss"> .dataCenter-table { height: 0; @@ -781,7 +876,67 @@ cursor: pointer; } } .fileshow { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; overflow: auto; flex: 1; min-height: 0; /* 关键:解决 flex 容器中的最小高度问题 */ align-content: flex-start; /* 让内容从顶部开始排列 */ .filePackage { display: flex; justify-content: center; width: 260px; height: 146px; border-radius: 4px 4px 4px 4px; position: relative; background: #ddd; cursor: pointer; img { width: 111px; height: 111px; } .el-checkbox { position: absolute; top: 0; left: 6px; } .itemName { position: absolute; bottom: 0; left: 0; height: 23px; width: 100%; padding: 0 10px; box-sizing: border-box; background: rgba(22, 56, 101, 0.3); 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; display: flex; align-items: center; justify-content: space-between; div { white-space: nowrap; } img { width: 14px; height: 14px; cursor: pointer; } } } } .pagination { display: flex; justify-content: end; @@ -938,4 +1093,4 @@ } } } </style> </style> src/views/job/components/JobRelatedEvents.vue
@@ -222,7 +222,7 @@ } // 处理中 .processing { color: #ffff61; color: #FFC300; } // 已完成 .done {