From d516e08ace187d792b99440223dcf5eaf3f6f36b Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Wed, 13 Aug 2025 15:56:29 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/feature/v5.0/5.0.3' into feature/v5.0/5.0.3
---
.env.development | 2
src/permission.js | 18 +
src/views/dataCenter/components/searchData.vue | 36 ++++
src/hooks/components/EventPopUpBox.vue | 69 ++++++---
src/utils/util.js | 10 +
src/views/dataCenter/dataCenter.vue | 221 ++++++++++++++++++++++++++----
src/views/job/components/JobRelatedEvents.vue | 2
src/views/dataCenter/components/dataCenterMap.vue | 1
src/api/dataCenter/dataCenter.js | 16 ++
src/assets/images/dataCenter/filePackage.png | 0
10 files changed, 307 insertions(+), 68 deletions(-)
diff --git a/.env.development b/.env.development
index e35d854..09780be 100644
--- a/.env.development
+++ b/.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/'
diff --git a/src/api/dataCenter/dataCenter.js b/src/api/dataCenter/dataCenter.js
index 996ac7f..0dd0dd0 100644
--- a/src/api/dataCenter/dataCenter.js
+++ b/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
+ })
+}
\ No newline at end of file
diff --git a/src/assets/images/dataCenter/filePackage.png b/src/assets/images/dataCenter/filePackage.png
new file mode 100644
index 0000000..a7daa97
--- /dev/null
+++ b/src/assets/images/dataCenter/filePackage.png
Binary files differ
diff --git a/src/hooks/components/EventPopUpBox.vue b/src/hooks/components/EventPopUpBox.vue
index a0a084f..24a4ad6 100644
--- a/src/hooks/components/EventPopUpBox.vue
+++ b/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;
}
}
}
diff --git a/src/permission.js b/src/permission.js
index 4db5ed8..36ed552 100644
--- a/src/permission.js
+++ b/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)
+})
\ No newline at end of file
diff --git a/src/utils/util.js b/src/utils/util.js
index 325dcc5..57c3536 100644
--- a/src/utils/util.js
+++ b/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) {
diff --git a/src/views/dataCenter/components/dataCenterMap.vue b/src/views/dataCenter/components/dataCenterMap.vue
index cc787c7..2715f26 100644
--- a/src/views/dataCenter/components/dataCenterMap.vue
+++ b/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);
}
diff --git a/src/views/dataCenter/components/searchData.vue b/src/views/dataCenter/components/searchData.vue
index a0c557d..fc5052f 100644
--- a/src/views/dataCenter/components/searchData.vue
+++ b/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;
diff --git a/src/views/dataCenter/dataCenter.vue b/src/views/dataCenter/dataCenter.vue
index 2ddb099..501ffe4 100644
--- a/src/views/dataCenter/dataCenter.vue
+++ b/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>
\ No newline at end of file
diff --git a/src/views/job/components/JobRelatedEvents.vue b/src/views/job/components/JobRelatedEvents.vue
index 6826bef..632db4f 100644
--- a/src/views/job/components/JobRelatedEvents.vue
+++ b/src/views/job/components/JobRelatedEvents.vue
@@ -222,7 +222,7 @@
}
// 处理中
.processing {
- color: #ffff61;
+ color: #FFC300;
}
// 已完成
.done {
--
Gitblit v1.9.3