288 lines
8.6 KiB
Vue
288 lines
8.6 KiB
Vue
<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>
|
|
</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="getUrl(record)"
|
|
: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>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, watch, onMounted } from 'vue';
|
|
// vben
|
|
import { useMessage } from '@/hooks/web/useMessage';
|
|
import proj4 from 'proj4';
|
|
import { getAppEnvConfig } from '@/utils/env';
|
|
import { BasicTable, useTable } from '@/components/Table';
|
|
import { columns, searchFormSchema } from './util';
|
|
import MapComponent from '@/views/demo/system/geoservermanagement/clound/mapComponent.vue';
|
|
import FailYingxiang from './failYingxiang.vue';
|
|
// api
|
|
import {
|
|
GeoTiffManagerUpdateGeoTiff,
|
|
GeoTiffManagerLoadPage,
|
|
GeoTiffManagerGet,
|
|
} from '@/api/demo/system';
|
|
|
|
// 图片路径拼接
|
|
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=37.56666666666666 +lon_0=126.93333333333333 +k=1 +x_0=200000 +y_0=500000 +ellps=bessel +towgs84=-119.819,-78.445,-112.283,0,0,0,0 +units=m +no_defs',
|
|
);
|
|
|
|
// 影像管理
|
|
const [registerTable, { reload, getSelectRows }] = useTable({
|
|
title: '影像管理',
|
|
api: GeoTiffManagerLoadPage,
|
|
columns: columns,
|
|
useSearchForm: true,
|
|
formConfig: {
|
|
labelWidth: 120,
|
|
schemas: searchFormSchema,
|
|
},
|
|
showIndexColumn: true,
|
|
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) => {
|
|
// console.log(res);
|
|
if (res.lenght == 0) {
|
|
reload();
|
|
} else {
|
|
failYingxiangData.value = getFailYingxiangData(res);
|
|
console.log(failYingxiangData.value);
|
|
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;
|
|
}
|
|
|
|
// 行选中
|
|
const mapboxComponentRef = ref();
|
|
function handRowClick(record) {
|
|
allDataForClearMap.forEach((data) => {
|
|
mapboxComponentRef.value.clearTaskLayer(data.layerName);
|
|
});
|
|
let bbox = getBboxFromUrl(record.accessUrl);
|
|
let lngLat = getCenterPoint(bbox);
|
|
// 检测坐标系
|
|
const result = isProjectedCoordinates(parseFloat(lngLat[0]), parseFloat(lngLat[1]));
|
|
if (result) {
|
|
lngLat[0] = result[0];
|
|
lngLat[1] = result[1];
|
|
}
|
|
let chooseRows: any = [];
|
|
chooseRows.push(record);
|
|
mapboxComponentRef.value.GeoTiffManagerRaster(chooseRows, lngLat, 11, true);
|
|
}
|
|
|
|
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];
|
|
}
|
|
|
|
// 用于去除分页后地图还有前一页的图层
|
|
let allDataForClearMap: any = [];
|
|
function forClearMap() {
|
|
GeoTiffManagerLoadPage({
|
|
page: 1,
|
|
limit: 10000,
|
|
}).then((res) => {
|
|
allDataForClearMap = res.items;
|
|
});
|
|
}
|
|
|
|
// 缩略图的预览不使用
|
|
const visible = ref<boolean>(false);
|
|
const setVisible = (value): void => {
|
|
visible.value = false;
|
|
};
|
|
|
|
// 从geoserver获取缩略图
|
|
function getUrl(record) {
|
|
let bbox: any = getBboxFromUrl(record.accessUrl);
|
|
const coords = bbox.split(',').map((coord) => parseFloat(coord));
|
|
let r1 = proj4('EPSG:4326', 'EPSG:3857', [coords[0], coords[1]]);
|
|
let r2 = proj4('EPSG:4326', 'EPSG:3857', [coords[2], coords[3]]);
|
|
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 +
|
|
record.layerName +
|
|
'&styles=&bbox=' +
|
|
r1[0] +
|
|
',' +
|
|
r1[1] +
|
|
',' +
|
|
r2[0] +
|
|
',' +
|
|
r2[1] +
|
|
'&width=256&height=256&srs=EPSG:3857&format=image/png&TRANSPARENT=TRUE';
|
|
return url;
|
|
}
|
|
|
|
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>
|