CaiYuanYiTiHua/src/views/demo/system/achievement/GeoTiffManager/index.vue

522 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div>
<a-row ::gutter="0">
<a-col :span="12">
<BasicTable @register="registerTable" @row-click="handRowClick">
<template #toolbar>
<a-button type="primary" @click="updateGeoTiff"></a-button>
<a-button type="success" @click="updateYearWeekThumbnail"></a-button>
<a-button type="error" @click="deleteGeoTiff"></a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'layerName'">
<span class="content-full">{{ record.layerName }}</span>
</template>
<template v-if="column.key === 'dataTable'">
<span class="content-full">{{ record.dataTable }}</span>
</template>
<template v-if="column.key === 'shpPath'">
<span class="content-full">{{ record.shpPath }}</span>
</template>
<template v-if="column.key === 'tiffPath'">
<span class="content-full">{{ record.tiffPath }}</span>
</template>
<template v-if="column.key === 'createTime'">
<span class="content-full">{{ record.createTime }}</span>
</template>
<template v-if="column.key === 'updateTime'">
<span class="content-full">{{ record.updateTime }}</span>
</template>
<template v-if="column.key === 'accessUrl'">
<a-image
:src="'/geoserver/group/1/' + record.layerName + '/' + record.layerName + '.png'"
:fallback="getUrl(record.accessUrl, record.layerName)"
:style="{ marginRight: '10px' }"
:width="100"
:height="100"
:preview="{
visible,
onVisibleChange: setVisible,
}"
/>
</template>
</template>
</BasicTable>
</a-col>
<a-col :span="12">
<div>
<MapComponent
ref="mapboxComponentRef"
style="
position: absolute;
top: 16px;
left: 0px;
height: calc(100vh - 112px);
width: calc(85vh);
z-index: 0;
"
/>
</div>
</a-col>
</a-row>
<a-modal
title="更新失败的影像"
:open="failOpen"
:maskClosable="false"
:footer="null"
:width="1000"
@cancel="failOpenClose"
>
<FailYingxiang :failYingxiangData="failYingxiangData" />
</a-modal>
<a-modal
title="选择更新的影像"
style="top: 50px"
:open="chooseUpdateOpen"
:maskClosable="false"
:width="600"
:footer="null"
@cancel="chooseUpdateClose"
>
<ChooseUpdate
ref="chooseUpdateRef"
:chooseUpdateData_yearweeks="chooseUpdateData_yearweeks"
:chooseUpdateData_layernames="chooseUpdateData_layernames"
@generateThumbnail="generateThumbnail"
/>
</a-modal>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, onMounted, createVNode } from 'vue';
// vben
import { useMessage } from '@/hooks/web/useMessage';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Modal } from 'ant-design-vue';
import proj4 from 'proj4';
import dayjs from 'dayjs';
import { getAppEnvConfig } from '@/utils/env';
import { BasicTable, useTable } from '@/components/Table';
import { columns, searchFormSchema, data } from './util';
import MapComponent from '@/views/demo/system/geoservermanagement/clound/mapComponent.vue';
import FailYingxiang from './failYingxiang.vue';
import ChooseUpdate from './chooseUpdate.vue';
// api
import {
GeoTiffManagerUpdateGeoTiff,
GeoTiffManagerLoadPage,
GeoTiffManagerGet,
GeoTiffManagerDeleteTifStore,
GeoTiffManagerUpdateLayerGroupThumb,
} from '@/api/demo/system';
import { RecordList } from '../../geoservermanagement/page';
// 图片路径拼接
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const VITE_GLOB_API_URL_VAR = ref<String>(VITE_GLOB_API_URL + '/');
const { createMessage } = useMessage();
proj4.defs(
'EPSG:4548',
'+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs',
);
// 影像管理-----------------------------------------------------------------------------------------------
const [registerTable, { reload, getSelectRows }] = useTable({
title: '影像管理',
api: GeoTiffManagerLoadPage,
// dataSource: data,
columns: columns,
useSearchForm: true,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
showIndexColumn: true,
rowSelection: {
type: 'radio',
},
bordered: true,
showTableSetting: true,
handleSearchInfoFn(info) {
return info;
},
immediate: false,
});
// 更新失败的影像-----------------------------------------------------------------------------------------
const failOpen = ref(false);
const failYingxiangData: any = ref();
// 更新失败的影像弹窗关闭
function failOpenClose() {
failOpen.value = false;
}
// 更新tiff影像
const updateGeoTiff = () => {
GeoTiffManagerUpdateGeoTiff()
.then((res) => {
if (res.length == 0) {
createMessage.success('影像更新成功');
reload();
} else {
failYingxiangData.value = getFailYingxiangData(res);
failOpen.value = true;
reload();
}
})
.catch((error) => {
console.log(error);
});
};
// 切割路径
function getFailYingxiangData(table) {
let result: any = [];
table.forEach((fullPath) => {
const lastSlashIndex = fullPath.lastIndexOf('/');
if (lastSlashIndex != -1) {
result.push({
fileName: fullPath.substring(lastSlashIndex + 1),
filePath: fullPath.substring(0, lastSlashIndex + 1),
});
}
});
return result;
}
// 删除tiff影像---------------------------------------------------------------------------------------
const deleteGeoTiff = () => {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请勾选一条数据进行删除');
}
const record = rows[0];
isPngImageUrl(getUrl(record.accessUrl, record.layerName))
.then((isPng) => {
if (isPng) {
createMessage.warn('所选影像完好,不能删除!');
} else {
Modal.confirm({
title: '是否确认删除此影像?',
icon: createVNode(ExclamationCircleOutlined),
onCancel() {},
onOk() {
// 删除有问题的影像
let params = { stores: record.storeName };
GeoTiffManagerDeleteTifStore(params).then((res) => {
if (res) {
createMessage.success('所选影像删除成功!');
reload();
} else {
createMessage.error('所选影像删除失败!');
reload();
}
});
},
});
}
})
.catch(console.error);
};
// 判断链接获取到的图片是否是png
async function isPngImageUrl(url) {
try {
const response = await fetch(url, { method: 'HEAD' });
if (!response.ok) {
throw new Error('请求失败');
}
const contentType = response.headers.get('content-type');
return contentType && contentType.startsWith('image/png');
} catch (error) {
return false;
}
}
// 在本地路径生成缩略图-------------------------------------------------------------------------------
// 选择生成缩略图的影像ref、open、数据
const chooseUpdateRef = ref();
const chooseUpdateOpen = ref(false);
const chooseUpdateData_yearweeks: any = ref([]);
const chooseUpdateData_layernames: any = ref([]);
// 选择更新的周数影像弹窗关闭
function chooseUpdateClose() {
chooseUpdateOpen.value = false;
chooseUpdateRef.value.clearSelect_layernames();
chooseUpdateRef.value.clearSelect_yearweeks();
}
// 在本地路径生成缩略图
async function updateYearWeekThumbnail() {
// allDataForClearMap = data;
// 按照时间分类
allDataForClearMap = allDataForClearMap.sort((a, b) => dayjs(b.dateDir) - dayjs(a.dateDir));
let uniqueKeysArray = [...new Set(allDataForClearMap.map((item) => item.dateDir))];
// 转换时间数组(年份-周数)
uniqueKeysArray = [...new Set(uniqueKeysArray.map(convertToYearWeek))];
// 生成对应年份-周数的缩略图
chooseUpdateData_yearweeks.value = [];
uniqueKeysArray.forEach((item, index) => {
chooseUpdateData_yearweeks.value.push({
rowname: item,
});
});
// 影像名称更换全部影像的缩略图
chooseUpdateData_layernames.value = [];
allDataForClearMap.forEach((item, index) => {
chooseUpdateData_layernames.value.push({
rowname: item.layerName,
bbox: getBboxFromUrl(item.accessUrl),
});
});
chooseUpdateOpen.value = true;
}
// 生成缩略图
async function generateThumbnail(
layerNames,
bbox,
length,
index,
widthAndHeightValue = 1024,
numValue = 1,
) {
if (bbox) {
// 检查bbox是否是ESG:4326不是的话转换成
let bboxSplit = bbox.split(',');
const result1 = isProjectedCoordinates(parseFloat(bboxSplit[0]), parseFloat(bboxSplit[1]));
if (result1) {
const result2 = isProjectedCoordinates(parseFloat(bboxSplit[2]), parseFloat(bboxSplit[3]));
bbox = result1.concat(result2).toString();
}
GeoTiffManagerUpdateLayerGroupThumb({
layerGroups: layerNames,
bbox: bbox,
num: 1,
width: widthAndHeightValue,
height: widthAndHeightValue,
})
.then((res) => {
if (res && length == index) {
createMessage.success('生成新的缩略图成功!');
chooseUpdateRef.value.clearSelect_layernames();
chooseUpdateRef.value.loading_layernames = false;
} else if (length == index) {
createMessage.error('生成新的缩略图失败!');
chooseUpdateRef.value.loading_layernames = false;
}
})
.catch((error) => {
if (length == index) {
createMessage.error('生成新的缩略图失败!');
chooseUpdateRef.value.loading_layernames = false;
}
});
} else {
// 分割的生成缩略图
GeoTiffManagerUpdateLayerGroupThumb({
layerGroups: layerNames,
num: numValue,
width: widthAndHeightValue,
height: widthAndHeightValue,
})
.then((res) => {
if (res) {
createMessage.success('生成新的缩略图成功!');
chooseUpdateRef.value.loading_yearweeks = false;
chooseUpdateRef.value.clearSelect_yearweeks();
if (numValue != 1) {
// 生成总的缩略图
GeoTiffManagerUpdateLayerGroupThumb({
layerGroups: layerNames,
num: 1,
width: widthAndHeightValue,
height: widthAndHeightValue,
});
}
} else {
createMessage.error('生成新的缩略图失败!');
chooseUpdateRef.value.loading_yearweeks = false;
}
})
.catch((error) => {
createMessage.error('生成新的缩略图失败!');
chooseUpdateRef.value.loading_yearweeks = false;
});
}
}
// 获取年份-周数
function convertToYearWeek(dateStr) {
const date = dayjs(dateStr, 'YYYYMMDD');
// 返回格式化的字符串
return `${date.year()}-${getWeekOfYear(date)}`;
}
// 每周从周一开始
function getWeekOfYear(date) {
const firstDayOfYear = dayjs(date).startOf('year');
const firstMondayOfYear =
firstDayOfYear.day() === 1
? firstDayOfYear
: firstDayOfYear.add(1 - firstDayOfYear.day(), 'day');
const diffInDays = date.diff(firstMondayOfYear, 'days');
const weekNumber = Math.floor(diffInDays / 7) + 1;
return weekNumber;
}
// 行选中-----------------------------------------------------------------------------------------
const mapboxComponentRef = ref();
function handRowClick(record) {
allDataForClearMap.forEach((data) => {
mapboxComponentRef.value.clearTaskLayer(data.layerName);
});
let lngLat = getlngLatByAccessUrl(record.accessUrl);
let chooseRows: any = [];
record.bbox = getBboxFromUrl(record.accessUrl);
chooseRows.push(record);
mapboxComponentRef.value.GeoTiffManagerRaster(chooseRows, lngLat, 11, true);
}
// 获取中心点的坐标
function getlngLatByAccessUrl(accessUrl) {
let bbox = getBboxFromUrl(accessUrl);
let lngLat = getCenterPoint(bbox);
// 检测坐标系
const result = isProjectedCoordinates(parseFloat(lngLat[0]), parseFloat(lngLat[1]));
if (result) {
lngLat[0] = result[0];
lngLat[1] = result[1];
}
return lngLat;
}
function isProjectedCoordinates(x, y) {
// 检查是否在地理坐标系的范围内
const isGeoXInRange = -180 <= x && x <= 180;
const isGeoYInRange = -90 <= y && y <= 90;
// 定义坐标系
const fromCrs1 = 'EPSG:3857'; // 假设输入坐标是 Web Mercator
const fromCrs2 = 'EPSG:4548';
const toCrs = 'EPSG:4326'; // 目标坐标系是地理坐标系
// 如果不在地理坐标系范围内,则认为是投影坐标系
if (!isGeoXInRange || !isGeoYInRange) {
// 转换坐标
// 根据输入坐标的范围来判断是哪个坐标系
const fromCrs = isProjectedCoordinate(x, y) ? fromCrs2 : fromCrs1;
return proj4(fromCrs, toCrs, [x, y]);
} else {
return false;
}
}
const isProjectedCoordinate = (x, y) => {
// 检查坐标是否符合 EPSG:4548 的大致范围
const is4548XInRange = 0 <= x && x <= 1000000;
const is4548YInRange = 0 <= y && y <= 6000000;
return is4548XInRange && is4548YInRange;
};
// 从参数中获取 bbox 的值
function getBboxFromUrl(url) {
const urlObj = new URL(url);
const params = new URLSearchParams(urlObj.search);
const bbox = params.get('bbox');
return bbox;
}
// 计算中心点
function getCenterPoint(bbox) {
const coords = bbox.split(',').map((coord) => parseFloat(coord));
const [minLon, minLat, maxLon, maxLat] = coords;
const centerLon = (minLon + maxLon) / 2;
const centerLat = (minLat + maxLat) / 2;
return [centerLon, centerLat];
}
// 缩略图的预览不使用----------------------------------------------------------------------------
const visible = ref<boolean>(false);
const setVisible = (value): void => {
visible.value = false;
};
// 从geoserver获取缩略图
function getUrl(accessUrl, name) {
let r1 = [117.34046403513817, 34.331716698906675];
let r2 = [119.27763051149853, 36.263686454243626];
let size = 4096;
if (accessUrl) {
let bbox: any = getBboxFromUrl(accessUrl);
// 检查bbox是否是ESG:4326不是的话转换成
let bboxSplit = bbox.split(',');
const result1 = isProjectedCoordinates(parseFloat(bboxSplit[0]), parseFloat(bboxSplit[1]));
if (result1) {
const result2 = isProjectedCoordinates(parseFloat(bboxSplit[2]), parseFloat(bboxSplit[3]));
bbox = result1.concat(result2).toString();
}
const coords = bbox.split(',').map((coord) => parseFloat(coord));
r1 = [coords[0], coords[1]];
r2 = [coords[2], coords[3]];
size = 256;
}
let titeUrl: any = null;
if (new URL(VITE_GLOB_API_URL).hostname == 'localhost') {
titeUrl =
'http://localhost:8080/geoserver/my_workspace/wms?service=WMS&version=1.1.0&request=GetMap&layers=my_workspace:';
} else {
titeUrl =
'http://192.168.10.141:8080/geoserver/my_workspace/wms?service=WMS&version=1.1.0&request=GetMap&layers=my_workspace:';
}
let url =
titeUrl +
name +
'&styles=&bbox=' +
r1[0] +
',' +
r1[1] +
',' +
r2[0] +
',' +
r2[1] +
'&width=' +
size +
'&height=' +
size +
'&srs=EPSG:4326&format=image/png&TRANSPARENT=TRUE';
return url;
}
// 用于去除分页后地图还有前一页的图层--------------------------------------------------------------
let allDataForClearMap: any = [];
function forClearMap() {
GeoTiffManagerLoadPage({
page: 1,
limit: 100000,
}).then((res) => {
allDataForClearMap = res.items;
});
}
onMounted(() => {
reload();
// 用于去除分页后地图还有前一页的图层
forClearMap();
});
</script>
<style lang="less" scoped>
.content-full {
white-space: pre-wrap;
word-break: break-all;
overflow-wrap: break-word;
max-width: 100%;
display: block;
}
::v-deep .ant-image-mask {
display: none !important;
}
</style>