|
@@ -18,7 +18,14 @@
|
|
|
mildAcidCount: 0,
|
|
mildAcidCount: 0,
|
|
|
normalCount: 0,
|
|
normalCount: 0,
|
|
|
maxPH: 0,
|
|
maxPH: 0,
|
|
|
- minPH: 0
|
|
|
|
|
|
|
+ minPH: 0,
|
|
|
|
|
+ strongAcidArea: 0,
|
|
|
|
|
+ mildAcidArea: 0,
|
|
|
|
|
+ normalArea: 0,
|
|
|
|
|
+ totalArea: 0,
|
|
|
|
|
+ strongAcidPercent: 0,
|
|
|
|
|
+ mildAcidPercent: 0,
|
|
|
|
|
+ normalPercent: 0
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
//
|
|
//
|
|
@@ -39,10 +46,21 @@
|
|
|
workspace:'acidmap',
|
|
workspace:'acidmap',
|
|
|
layerGroup:'leshujukanbanmap',
|
|
layerGroup:'leshujukanbanmap',
|
|
|
dataLayer:'le_soil_data',
|
|
dataLayer:'le_soil_data',
|
|
|
- wmsUrl:'/geoserver/acidmap/wms'
|
|
|
|
|
|
|
+ wmsUrl:'/geoserver/acidmap/wms',
|
|
|
|
|
+ phField: 'ph_mean'
|
|
|
|
|
+ },
|
|
|
|
|
+ reboundGeoserver:{
|
|
|
|
|
+ url:'/geoserver',
|
|
|
|
|
+ workspace:'acidmap',
|
|
|
|
|
+ layerGroup:'le_reflux_map',
|
|
|
|
|
+ dataLayer:'le_data_reflux_result',
|
|
|
|
|
+ wmsUrl:'/geoserver/acidmap/wms',
|
|
|
|
|
+ phField: 'ph_value'
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const currentMapType = ref('normal')
|
|
|
|
|
+
|
|
|
|
|
|
|
|
// 获取 pH 等级对应的 CSS 类
|
|
// 获取 pH 等级对应的 CSS 类
|
|
|
function getPHLevelClass(ph) {
|
|
function getPHLevelClass(ph) {
|
|
@@ -94,6 +112,61 @@ function getPHComment(avgPH) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ async function switchMap(mapType) {
|
|
|
|
|
+ if (!map || !wmsLayer) return
|
|
|
|
|
+
|
|
|
|
|
+ currentMapType.value = mapType
|
|
|
|
|
+
|
|
|
|
|
+ const config = mapType === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
|
|
|
|
|
+
|
|
|
|
|
+ // 移除旧的 WMS 图层
|
|
|
|
|
+ map.removeLayer(wmsLayer)
|
|
|
|
|
+
|
|
|
|
|
+ // 创建新的 WMS 图层
|
|
|
|
|
+ wmsLayer = L.tileLayer.wms(config.wmsUrl, {
|
|
|
|
|
+ layers: `${config.workspace}:${config.layerGroup}`,
|
|
|
|
|
+ format: 'image/png',
|
|
|
|
|
+ transparent: true,
|
|
|
|
|
+ version: '1.1.0',
|
|
|
|
|
+ srs:'EPSG:4326',
|
|
|
|
|
+ attribution: '© GeoServer - Acidmap'
|
|
|
|
|
+ }).addTo(map)
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`地图已切换到:${mapType === 'rebound' ? '反酸一周期后' : '实施降酸措施'}`)
|
|
|
|
|
+ console.log('新图层:', `${config.workspace}:${config.layerGroup}`)
|
|
|
|
|
+
|
|
|
|
|
+ // 重新加载对应地图的数据和统计
|
|
|
|
|
+ await loadMapData()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 加载当前地图类型的数据
|
|
|
|
|
+ async function loadMapData() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
|
|
|
|
|
+
|
|
|
|
|
+ const response = await fetch(
|
|
|
|
|
+ `${config.url}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${config.workspace}:${config.dataLayer}&outputFormat=application/json`
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
|
|
|
|
+
|
|
|
|
|
+ const geoJsonData = await response.json();
|
|
|
|
|
+
|
|
|
|
|
+ console.log('✅ 获取到数据:', geoJsonData.features.length, '条记录');
|
|
|
|
|
+
|
|
|
|
|
+ // 保存数据用于统计和交互
|
|
|
|
|
+ allFeatures = geoJsonData.features;
|
|
|
|
|
+ samplePointsData.value = geoJsonData.features;
|
|
|
|
|
+
|
|
|
|
|
+ // 计算统计信息
|
|
|
|
|
+ calculatePHDistribution(allFeatures);
|
|
|
|
|
+ loadStatistics();
|
|
|
|
|
+
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ console.error('❌ 加载数据失败:', err);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
function createPointIcon(feature) {
|
|
function createPointIcon(feature) {
|
|
|
const ph = feature.properties.ph || feature.properties.value
|
|
const ph = feature.properties.ph || feature.properties.value
|
|
|
let color = '#22c55e'
|
|
let color = '#22c55e'
|
|
@@ -126,6 +199,9 @@ function getPHComment(avgPH) {
|
|
|
try {
|
|
try {
|
|
|
// 等待数据加载完成
|
|
// 等待数据加载完成
|
|
|
if (samplePointsData.value.length === 0) return;
|
|
if (samplePointsData.value.length === 0) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 根据当前地图类型选择 pH 字段
|
|
|
|
|
+ const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
|
|
|
|
|
|
|
|
let phCount = 0
|
|
let phCount = 0
|
|
|
let avgPH = 0
|
|
let avgPH = 0
|
|
@@ -134,10 +210,21 @@ function getPHComment(avgPH) {
|
|
|
let normalCount = 0
|
|
let normalCount = 0
|
|
|
let maxPH = -Infinity
|
|
let maxPH = -Infinity
|
|
|
let minPH = Infinity
|
|
let minPH = Infinity
|
|
|
|
|
+ let strongAcidArea = 0
|
|
|
|
|
+ let mildAcidArea = 0
|
|
|
|
|
+ let normalArea = 0
|
|
|
|
|
+ let totalArea = 0
|
|
|
|
|
|
|
|
samplePointsData.value.forEach(feature => {
|
|
samplePointsData.value.forEach(feature => {
|
|
|
- const numericPh = parsePHValue(feature.properties.ph || feature.properties.value)
|
|
|
|
|
|
|
+ const numericPh = parsePHValue(feature.properties[config.phField])
|
|
|
|
|
+ const area = parseFloat(feature.properties.area) || 0
|
|
|
|
|
+
|
|
|
|
|
+ // 累加总面积
|
|
|
|
|
+ if (area > 0) {
|
|
|
|
|
+ totalArea += area
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ // 过滤无效 pH 值
|
|
|
if (numericPh && numericPh > 0 && !isNaN(numericPh)) {
|
|
if (numericPh && numericPh > 0 && !isNaN(numericPh)) {
|
|
|
phCount++
|
|
phCount++
|
|
|
const delta = numericPh - avgPH;
|
|
const delta = numericPh - avgPH;
|
|
@@ -145,12 +232,26 @@ function getPHComment(avgPH) {
|
|
|
maxPH = Math.max(maxPH, numericPh)
|
|
maxPH = Math.max(maxPH, numericPh)
|
|
|
minPH = Math.min(minPH, numericPh)
|
|
minPH = Math.min(minPH, numericPh)
|
|
|
|
|
|
|
|
- if (numericPh <= 5.2) strongAcidCount++
|
|
|
|
|
- else if (numericPh < 6.0) mildAcidCount++
|
|
|
|
|
- else normalCount++
|
|
|
|
|
|
|
+ if (numericPh <= 5.2) {
|
|
|
|
|
+ strongAcidCount++
|
|
|
|
|
+ strongAcidArea += area
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (numericPh < 6.0) {
|
|
|
|
|
+ mildAcidCount++
|
|
|
|
|
+ mildAcidArea += area
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ normalCount++
|
|
|
|
|
+ normalArea += area
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ // 计算面积占比
|
|
|
|
|
+ const strongAcidPercent = totalArea > 0 ? parseFloat(((strongAcidArea / totalArea) * 100).toFixed(2)) : 0
|
|
|
|
|
+ const mildAcidPercent = totalArea > 0 ? parseFloat(((mildAcidArea / totalArea) * 100).toFixed(2)) : 0
|
|
|
|
|
+ const normalPercent = totalArea > 0 ? parseFloat(((normalArea / totalArea) * 100).toFixed(2)) : 0
|
|
|
|
|
+
|
|
|
statistics.value = {
|
|
statistics.value = {
|
|
|
totalBlocks: samplePointsData.value.length,
|
|
totalBlocks: samplePointsData.value.length,
|
|
|
avgPH: phCount > 0 ? parseFloat(avgPH.toFixed(2)) : 0, // ✅ 确保是数字
|
|
avgPH: phCount > 0 ? parseFloat(avgPH.toFixed(2)) : 0, // ✅ 确保是数字
|
|
@@ -158,7 +259,14 @@ function getPHComment(avgPH) {
|
|
|
mildAcidCount,
|
|
mildAcidCount,
|
|
|
normalCount,
|
|
normalCount,
|
|
|
maxPH: maxPH === -Infinity ? 0 : parseFloat(maxPH.toFixed(2)),
|
|
maxPH: maxPH === -Infinity ? 0 : parseFloat(maxPH.toFixed(2)),
|
|
|
- minPH: minPH === Infinity ? 0 : parseFloat(minPH.toFixed(2))
|
|
|
|
|
|
|
+ minPH: minPH === Infinity ? 0 : parseFloat(minPH.toFixed(2)),
|
|
|
|
|
+ strongAcidArea: parseFloat(strongAcidArea.toFixed(2)),
|
|
|
|
|
+ mildAcidArea: parseFloat(mildAcidArea.toFixed(2)),
|
|
|
|
|
+ normalArea: parseFloat(normalArea.toFixed(2)),
|
|
|
|
|
+ totalArea: parseFloat(totalArea.toFixed(2)),
|
|
|
|
|
+ strongAcidPercent,
|
|
|
|
|
+ mildAcidPercent,
|
|
|
|
|
+ normalPercent
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
console.log('✅ 统计数据加载完成:', statistics.value);
|
|
console.log('✅ 统计数据加载完成:', statistics.value);
|
|
@@ -202,6 +310,7 @@ function getPHComment(avgPH) {
|
|
|
|
|
|
|
|
// 计算 pH 分布
|
|
// 计算 pH 分布
|
|
|
function calculatePHDistribution(features) {
|
|
function calculatePHDistribution(features) {
|
|
|
|
|
+ const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
|
|
|
const distribution = {
|
|
const distribution = {
|
|
|
range1: 0,
|
|
range1: 0,
|
|
|
range2: 0,
|
|
range2: 0,
|
|
@@ -209,7 +318,7 @@ function getPHComment(avgPH) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
features.forEach(feature => {
|
|
features.forEach(feature => {
|
|
|
- const phValue = feature.properties.ph || feature.properties.value
|
|
|
|
|
|
|
+ const phValue = feature.properties[config.phField]
|
|
|
const numericPh = typeof phValue === 'string' ? parseFloat(phValue) : phValue
|
|
const numericPh = typeof phValue === 'string' ? parseFloat(phValue) : phValue
|
|
|
if (numericPh && numericPh > 0) {
|
|
if (numericPh && numericPh > 0) {
|
|
|
if (numericPh <= 5.2) distribution.range1++
|
|
if (numericPh <= 5.2) distribution.range1++
|
|
@@ -226,6 +335,9 @@ function getPHComment(avgPH) {
|
|
|
let nearestPoint = null;
|
|
let nearestPoint = null;
|
|
|
let minDistance = Infinity;
|
|
let minDistance = Infinity;
|
|
|
|
|
|
|
|
|
|
+ // 根据当前地图类型选择 pH 字段
|
|
|
|
|
+ const config = currentMapType.value === 'rebound' ? CONFIG.reboundGeoserver : CONFIG.geoserver
|
|
|
|
|
+
|
|
|
allFeatures.forEach(feature => {
|
|
allFeatures.forEach(feature => {
|
|
|
const coords = feature.geometry.coordinates;
|
|
const coords = feature.geometry.coordinates;
|
|
|
if (coords && coords.length >= 2) {
|
|
if (coords && coords.length >= 2) {
|
|
@@ -244,12 +356,15 @@ function getPHComment(avgPH) {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
if (nearestPoint) {
|
|
if (nearestPoint) {
|
|
|
- const ph = parsePHValue(nearestPoint.properties.ph || nearestPoint.properties.value);
|
|
|
|
|
|
|
+ const ph = parsePHValue(nearestPoint.properties[config.phField]);
|
|
|
|
|
|
|
|
selectedPoint.value = {
|
|
selectedPoint.value = {
|
|
|
ph: ph,
|
|
ph: ph,
|
|
|
properties: nearestPoint.properties
|
|
properties: nearestPoint.properties
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+ console.log('✅ 选中地块:', nearestPoint.properties);
|
|
|
|
|
+ console.log('pH 字段:', config.phField, '= ', nearestPoint.properties[config.phField]);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -290,8 +405,8 @@ onUnmounted(()=>{
|
|
|
|
|
|
|
|
<!-- 计算刷新按钮 -->
|
|
<!-- 计算刷新按钮 -->
|
|
|
<div class="compute">
|
|
<div class="compute">
|
|
|
- <button class="combtn">实施降酸措施一周期后</button>
|
|
|
|
|
- <button class="combtn">反酸一周期后</button>
|
|
|
|
|
|
|
+ <button class="combtn" @click="switchMap('normal')">实施降酸措施一周期后</button>
|
|
|
|
|
+ <button class="combtn" @click="switchMap('rebound')">反酸一周期后</button>
|
|
|
</div>
|
|
</div>
|
|
|
<!-- pH 统计 -->
|
|
<!-- pH 统计 -->
|
|
|
<div class="statistics-panel">
|
|
<div class="statistics-panel">
|
|
@@ -314,18 +429,38 @@ onUnmounted(()=>{
|
|
|
<span class="stat-value danger">{{ statistics.strongAcidCount }} 个</span>
|
|
<span class="stat-value danger">{{ statistics.strongAcidCount }} 个</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <div class="stat-row">
|
|
|
|
|
+ <span class="stat-label">强酸性面积占比:</span>
|
|
|
|
|
+ <span class="stat-value danger">{{ statistics.strongAcidPercent }}%</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<div class="stat-row">
|
|
<div class="stat-row">
|
|
|
<span class="stat-label">弱酸性 (pH 5.2~6.0): </span>
|
|
<span class="stat-label">弱酸性 (pH 5.2~6.0): </span>
|
|
|
<span class="stat-value warning">{{ statistics.mildAcidCount }} 个</span>
|
|
<span class="stat-value warning">{{ statistics.mildAcidCount }} 个</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <div class="stat-row">
|
|
|
|
|
+ <span class="stat-label">弱酸性面积占比:</span>
|
|
|
|
|
+ <span class="stat-value warning">{{ statistics.mildAcidPercent }}%</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<div class="stat-row">
|
|
<div class="stat-row">
|
|
|
<span class="stat-label">正常 (pH≥6.0):</span>
|
|
<span class="stat-label">正常 (pH≥6.0):</span>
|
|
|
<span class="stat-value success">{{ statistics.normalCount }} 个</span>
|
|
<span class="stat-value success">{{ statistics.normalCount }} 个</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <div class="stat-row">
|
|
|
|
|
+ <span class="stat-label">正常面积占比:</span>
|
|
|
|
|
+ <span class="stat-value success">{{ statistics.normalPercent }}%</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<div class="stat-divider"></div>
|
|
<div class="stat-divider"></div>
|
|
|
|
|
|
|
|
|
|
+ <div class="stat-row small">
|
|
|
|
|
+ <span class="stat-label">总面积:</span>
|
|
|
|
|
+ <span class="stat-value">{{ statistics.totalArea }} 亩</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<div class="stat-row small">
|
|
<div class="stat-row small">
|
|
|
<span class="stat-label">最高 pH:</span>
|
|
<span class="stat-label">最高 pH:</span>
|
|
|
<span class="stat-value success">{{ statistics.maxPH || '-' }}</span>
|
|
<span class="stat-value success">{{ statistics.maxPH || '-' }}</span>
|