|
@@ -1,5 +1,10 @@
|
|
|
<template>
|
|
|
<div class="map-page">
|
|
|
+ <!-- 新增加载提示 -->
|
|
|
+ <div v-if="isLoading" class="loading-overlay">
|
|
|
+ <div class="loading-spinner"></div>
|
|
|
+ <p>地图数据加载中...</p>
|
|
|
+ </div>
|
|
|
<!-- 新增工具栏容器 -->
|
|
|
<div class="map-toolbar">
|
|
|
<RegionSelector
|
|
@@ -75,13 +80,16 @@ const surveyDataLayer = ref(null); // 保持响应式引用
|
|
|
let multiPolygon;
|
|
|
const districtLayers = ref(new Map()) // 存储区县图层
|
|
|
const combinedSurveyFeatures = ref([]); // 存储原始数据
|
|
|
-const currentSurveyFilter = ref([]); // 当前选中区域
|
|
|
+const currentSurveyFilter = ref([]); // 当前选中区域
|
|
|
+const isLoading = ref(false)
|
|
|
|
|
|
const categoryColors = { // 分类颜色配置
|
|
|
'优先保护类': '#00C853', // 绿色
|
|
|
'安全利用类': '#FFD600', // 黄色
|
|
|
'严格管控类': '#D50000', // 红色
|
|
|
- '其他': '#CCCCCC' // 灰色
|
|
|
+ '其他': '#CCCCCC', // 灰色
|
|
|
+ '农产品样品': '#4CAF50', // 绿色
|
|
|
+ '土壤样品': '#2196F3' // 蓝色
|
|
|
};
|
|
|
|
|
|
const tMapConfig = reactive({
|
|
@@ -107,6 +115,7 @@ const geoLayers = reactive({
|
|
|
const initBaseLayers = async () => {
|
|
|
try {
|
|
|
// 按层级加载GeoJSON(需替换实际路径)
|
|
|
+ isLoading.value = true;
|
|
|
geoLayers.province = await loadAndCreateLayer('/data/省.geojson', 'province')
|
|
|
geoLayers.city = await loadAndCreateLayer('/data/市.geojson', 'city')
|
|
|
geoLayers.county = await loadAndCreateLayer('/data/县.geojson', 'county')
|
|
@@ -116,6 +125,8 @@ const initBaseLayers = async () => {
|
|
|
} catch (error) {
|
|
|
console.error('加载地理数据失败:', error)
|
|
|
error.value = '地理数据加载失败'
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -175,14 +186,7 @@ const updateLayerVisibility = () => {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-const getLayerColor = (type) => {
|
|
|
- const colors = {
|
|
|
- province: 'rgba(255, 170, 0, 1)',
|
|
|
- city: 'rgba(0, 168, 255, 1)',
|
|
|
- county: 'rgba(76, 175, 80, 1)'
|
|
|
- };
|
|
|
- return colors[type]
|
|
|
-}
|
|
|
+
|
|
|
|
|
|
// 清理方法
|
|
|
const hideAllLayers = () => {
|
|
@@ -299,6 +303,7 @@ const initData = () => {
|
|
|
// 初始化地图
|
|
|
const initMap = async () => {
|
|
|
try {
|
|
|
+ isLoading.value = true
|
|
|
await loadSDK()
|
|
|
|
|
|
map = new TMap.value.Map(mapContainer.value, {
|
|
@@ -337,6 +342,8 @@ const initMap = async () => {
|
|
|
updateMarkers()
|
|
|
} catch (err) {
|
|
|
error.value = err.message
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -608,6 +615,7 @@ async function loadGeoJSON(url) {
|
|
|
}
|
|
|
|
|
|
const handleRegionChange = async (districtNames) => {
|
|
|
+ isLoading.value = true;
|
|
|
console.log('收到区域变更:', districtNames)
|
|
|
currentSurveyFilter.value = districtNames;
|
|
|
|
|
@@ -649,6 +657,7 @@ const handleRegionChange = async (districtNames) => {
|
|
|
// }
|
|
|
// }))
|
|
|
filterSurveyDataLayer(districtNames);
|
|
|
+ isLoading.value = false;
|
|
|
}
|
|
|
|
|
|
const filterSurveyDataLayer = (selectedRegions) => {
|
|
@@ -689,6 +698,7 @@ const filterSurveyDataLayer = (selectedRegions) => {
|
|
|
console.groupCollapsed("[区域过滤] 调试信息");
|
|
|
console.log("🔄 收到过滤请求,当前选中区域:", selectedRegions);
|
|
|
console.log("📦 原始数据总量:", combinedSurveyFeatures.value.length);
|
|
|
+ console.log(combinedSurveyFeatures.value);
|
|
|
|
|
|
const filtered = selectedRegions.length === 0
|
|
|
? combinedSurveyFeatures.value
|
|
@@ -698,16 +708,17 @@ const filterSurveyDataLayer = (selectedRegions) => {
|
|
|
});
|
|
|
console.log("✅ 过滤后数据量:", filtered.length);
|
|
|
console.log("🔍 示例过滤后数据:", filtered.slice(0,3).map(f => ({
|
|
|
- id: f.properties.ID,
|
|
|
+ id: f.properties.ID || f.properties.OBJECTID,
|
|
|
XMC: f.properties.XMC,
|
|
|
- CMC: f.properties.CMC
|
|
|
+ CMC: f.properties.CMC,
|
|
|
+ H_XTFX: f.properties.H_XTFX,
|
|
|
})));
|
|
|
console.groupEnd();
|
|
|
|
|
|
try {
|
|
|
surveyDataLayer.value.setGeometries(filtered.map(feature => ({
|
|
|
id: feature.properties.ID || feature.properties.OBJECTID,
|
|
|
- styleId: feature.properties.H_XTFX || '其他',
|
|
|
+ styleId: feature.properties.H_XTFX || feature.properties.h_xtfx || '其他',
|
|
|
position: new TMap.value.LatLng(
|
|
|
feature.geometry.coordinates[1],
|
|
|
feature.geometry.coordinates[0]
|
|
@@ -726,14 +737,6 @@ const filterSurveyDataLayer = (selectedRegions) => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-// 生成随机颜色
|
|
|
-const randomRGBA = (alpha = 1) => {
|
|
|
- const r = Math.floor(Math.random() * 256)
|
|
|
- const g = Math.floor(Math.random() * 256)
|
|
|
- const b = Math.floor(Math.random() * 256)
|
|
|
- return `rgba(${r},${g},${b},${alpha})`
|
|
|
-}
|
|
|
-
|
|
|
function initMapWithGeoJSON(geojsonData, map) {
|
|
|
// 销毁旧图层
|
|
|
if (geoJSONLayer) {
|
|
@@ -792,10 +795,11 @@ function initMapWithGeoJSON(geojsonData, map) {
|
|
|
// 加载调查数据并初始化图层
|
|
|
const initSurveyDataLayer = async (map) => {
|
|
|
try {
|
|
|
+ isLoading.value = true
|
|
|
const geoJsonFiles = [
|
|
|
- '/data/调查数据.geojson',
|
|
|
- '/data/河池1.geojson',
|
|
|
- '/data/河池2.geojson'
|
|
|
+ 'https://soilgd.com:8000/api/vector/export/surveydata',
|
|
|
+ '/data/河池土壤样品.geojson',
|
|
|
+ '/data/河池农产品样品.geojson',
|
|
|
];
|
|
|
|
|
|
const surveyDataArray = await Promise.all(geoJsonFiles.map(loadGeoJSON));
|
|
@@ -826,7 +830,7 @@ const initSurveyDataLayer = async (map) => {
|
|
|
styles: Object.assign({}, ...pointStyles.map(s => ({ [s.id]: s.style }))),
|
|
|
geometries: combinedSurveyFeatures.value.map(feature => ({
|
|
|
id: feature.properties.ID || feature.properties.OBJECTID,
|
|
|
- styleId: feature.properties.H_XTFX || '其他', // 设置默认值
|
|
|
+ styleId: feature.properties.H_XTFX || feature.properties.h_xtfx || '其他', // 设置默认值
|
|
|
position: new TMap.value.LatLng(
|
|
|
feature.geometry.coordinates[1],
|
|
|
feature.geometry.coordinates[0]
|
|
@@ -834,7 +838,7 @@ const initSurveyDataLayer = async (map) => {
|
|
|
properties: {
|
|
|
...feature.properties,
|
|
|
// 强制添加H_XTFX字段保证数据一致性
|
|
|
- H_XTFX: feature.properties.H_XTFX || '其他'
|
|
|
+ H_XTFX: feature.properties.H_XTFX|| '其他'
|
|
|
}
|
|
|
}))
|
|
|
});
|
|
@@ -861,6 +865,8 @@ const initSurveyDataLayer = async (map) => {
|
|
|
console.error("错误对象:", error);
|
|
|
console.trace("调用堆栈");
|
|
|
console.groupEnd();
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -1118,19 +1124,34 @@ onBeforeUnmount(() => {
|
|
|
box-shadow: 0 4px 12px rgba(56, 118, 255, 0.3);
|
|
|
}
|
|
|
|
|
|
-/* 新增加载动画 */
|
|
|
-@keyframes spin {
|
|
|
- 0% { transform: rotate(0deg); }
|
|
|
- 100% { transform: rotate(360deg); }
|
|
|
+/* 新增加载提示样式 */
|
|
|
+.loading-overlay {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: rgba(255, 255, 255, 0.8);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ z-index: 9999;
|
|
|
}
|
|
|
|
|
|
.loading-spinner {
|
|
|
- width: 18px;
|
|
|
- height: 18px;
|
|
|
- border: 2px solid rgba(255, 255, 255, 0.3);
|
|
|
- border-top-color: white;
|
|
|
+ width: 50px;
|
|
|
+ height: 50px;
|
|
|
+ border: 5px solid #f3f3f3;
|
|
|
+ border-top: 5px solid #3876ff;
|
|
|
border-radius: 50%;
|
|
|
- animation: spin 0.8s linear infinite;
|
|
|
+ animation: spin 1s linear infinite;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes spin {
|
|
|
+ 0% { transform: rotate(0deg); }
|
|
|
+ 100% { transform: rotate(360deg); }
|
|
|
}
|
|
|
|
|
|
/* 响应式调整 */
|
|
@@ -1235,6 +1256,8 @@ onBeforeUnmount(() => {
|
|
|
.point-info h3[data-category="安全利用类"] { --category-color: #FFD600; }
|
|
|
.point-info h3[data-category="严格管控类"] { --category-color: #D50000; }
|
|
|
.point-info h3[data-category="其他"] { --category-color: #CCCCCC; }
|
|
|
+.point-info h3[data-category="土壤样品"] { --category-color: #2196F3; }
|
|
|
+.point-info h3[data-category="农产品样品"] { --category-color: #4CAF50; }
|
|
|
.highlight-status {
|
|
|
padding: 8px;
|
|
|
background: rgba(0, 255, 0, 0.1);
|