|
|
|
@ -15,13 +15,13 @@ |
|
|
|
|
|
|
|
|
|
|
|
<div class="forest-grass-wet-ui ecological-protection-ui"> |
|
|
|
<div class="forest-grass-wet-ui ecological-protection-ui"> |
|
|
|
<div |
|
|
|
<div |
|
|
|
v-if="isEcologicalRedlineView && redlineDataState !== 'ready'" |
|
|
|
v-if="isEcologicalDirectView && ecologicalDirectDataState !== 'ready'" |
|
|
|
class="fgw-data-state" |
|
|
|
class="fgw-data-state" |
|
|
|
:class="{ 'is-error': redlineDataState === 'error' }" |
|
|
|
:class="{ 'is-error': ecologicalDirectDataState === 'error' }" |
|
|
|
role="status" |
|
|
|
role="status" |
|
|
|
aria-live="polite" |
|
|
|
aria-live="polite" |
|
|
|
> |
|
|
|
> |
|
|
|
{{ redlineDataStateMessage }} |
|
|
|
{{ ecologicalDirectDataStateMessage }} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div v-if="!isEngineeringAnalysis" class="fgw-left"> |
|
|
|
<div v-if="!isEngineeringAnalysis" class="fgw-left"> |
|
|
|
<div class="fgw-side-stack is-left"> |
|
|
|
<div class="fgw-side-stack is-left"> |
|
|
|
@ -197,12 +197,10 @@ import EngineeringAnalysisPanel from "./components/EngineeringAnalysisPanel.vue" |
|
|
|
import EngineeringStatisticsPanel from "./components/EngineeringStatisticsPanel.vue" |
|
|
|
import EngineeringStatisticsPanel from "./components/EngineeringStatisticsPanel.vue" |
|
|
|
import { |
|
|
|
import { |
|
|
|
buildEcologicalRedlinePanels, |
|
|
|
buildEcologicalRedlinePanels, |
|
|
|
buildEcologicalScopePanels, |
|
|
|
buildNaturalProtectedAreaPanels, |
|
|
|
buildEcologicalRestorationPanels, |
|
|
|
buildEcologicalRestorationPanels, |
|
|
|
buildNationalParkPanels, |
|
|
|
buildNationalParkPanels, |
|
|
|
ecologicalScopeViewKeys, |
|
|
|
|
|
|
|
engineeringAnalysisPanels, |
|
|
|
engineeringAnalysisPanels, |
|
|
|
getEcologicalScopeTopStats, |
|
|
|
|
|
|
|
getEcologicalMapRanking, |
|
|
|
getEcologicalMapRanking, |
|
|
|
getEcologicalRestorationTopStats, |
|
|
|
getEcologicalRestorationTopStats, |
|
|
|
getNationalParkTopStats, |
|
|
|
getNationalParkTopStats, |
|
|
|
@ -229,7 +227,8 @@ const activeLayerKey = ref("") |
|
|
|
const selectedLegendKey = ref("") |
|
|
|
const selectedLegendKey = ref("") |
|
|
|
const redlinePanels = ref(buildEcologicalRedlinePanels()) |
|
|
|
const redlinePanels = ref(buildEcologicalRedlinePanels()) |
|
|
|
const redlineDataState = ref("loading") |
|
|
|
const redlineDataState = ref("loading") |
|
|
|
const scopePanels = ref(buildEcologicalScopePanels({}, "natural-protected-area")) |
|
|
|
const naturalProtectedAreaPanels = ref(buildNaturalProtectedAreaPanels()) |
|
|
|
|
|
|
|
const naturalProtectedAreaDataState = ref("loading") |
|
|
|
const nationalParkPanels = ref(buildNationalParkPanels({})) |
|
|
|
const nationalParkPanels = ref(buildNationalParkPanels({})) |
|
|
|
const restorationPanels = ref(buildEcologicalRestorationPanels({})) |
|
|
|
const restorationPanels = ref(buildEcologicalRestorationPanels({})) |
|
|
|
const selectedFeature = ref(null) |
|
|
|
const selectedFeature = ref(null) |
|
|
|
@ -254,14 +253,14 @@ let destroyed = false |
|
|
|
let mapAssetsReady = false |
|
|
|
let mapAssetsReady = false |
|
|
|
let mapLoadStarted = false |
|
|
|
let mapLoadStarted = false |
|
|
|
let mapLoadTimer = null |
|
|
|
let mapLoadTimer = null |
|
|
|
let scopeStatsRequestId = 0 |
|
|
|
|
|
|
|
let redlineStatsRequestId = 0 |
|
|
|
let redlineStatsRequestId = 0 |
|
|
|
|
|
|
|
let naturalProtectedAreaStatsRequestId = 0 |
|
|
|
let nationalParkStatsRequestId = 0 |
|
|
|
let nationalParkStatsRequestId = 0 |
|
|
|
let restorationStatsRequestId = 0 |
|
|
|
let restorationStatsRequestId = 0 |
|
|
|
let engineeringAnalysisRequestId = 0 |
|
|
|
let engineeringAnalysisRequestId = 0 |
|
|
|
let featureQueryRequestId = 0 |
|
|
|
let featureQueryRequestId = 0 |
|
|
|
const scopeStatsCache = new Map() |
|
|
|
|
|
|
|
let redlineStatsCache = null |
|
|
|
let redlineStatsCache = null |
|
|
|
|
|
|
|
let naturalProtectedAreaStatsCache = null |
|
|
|
let nationalParkStatsCache = null |
|
|
|
let nationalParkStatsCache = null |
|
|
|
let restorationStatsCache = null |
|
|
|
let restorationStatsCache = null |
|
|
|
let engineeringAnalysisCache = null |
|
|
|
let engineeringAnalysisCache = null |
|
|
|
@ -297,11 +296,16 @@ const currentView = computed(() => |
|
|
|
const isEngineeringAnalysis = computed(() => currentView.value === "engineering-analysis") |
|
|
|
const isEngineeringAnalysis = computed(() => currentView.value === "engineering-analysis") |
|
|
|
const isProjectDetailView = computed(() => ["restoration", "engineering-analysis"].includes(currentView.value)) |
|
|
|
const isProjectDetailView = computed(() => ["restoration", "engineering-analysis"].includes(currentView.value)) |
|
|
|
const isEcologicalRedlineView = computed(() => currentView.value === "ecological-redline") |
|
|
|
const isEcologicalRedlineView = computed(() => currentView.value === "ecological-redline") |
|
|
|
const isEcologicalScopeView = computed(() => ecologicalScopeViewKeys.includes(currentView.value)) |
|
|
|
const isNaturalProtectedAreaView = computed(() => currentView.value === "natural-protected-area") |
|
|
|
const redlineDataStateMessage = computed(() => { |
|
|
|
const isEcologicalDirectView = computed(() => isEcologicalRedlineView.value || isNaturalProtectedAreaView.value) |
|
|
|
if (redlineDataState.value === "loading") return "生态保护红线数据加载中" |
|
|
|
const ecologicalDirectDataState = computed(() => ( |
|
|
|
if (redlineDataState.value === "empty") return "生态保护红线暂无数据" |
|
|
|
isEcologicalRedlineView.value ? redlineDataState.value : naturalProtectedAreaDataState.value |
|
|
|
if (redlineDataState.value === "error") return "生态保护红线数据加载失败,请稍后重试" |
|
|
|
)) |
|
|
|
|
|
|
|
const ecologicalDirectDataStateMessage = computed(() => { |
|
|
|
|
|
|
|
const featureName = isEcologicalRedlineView.value ? "生态保护红线" : "自然保护地" |
|
|
|
|
|
|
|
if (ecologicalDirectDataState.value === "loading") return `${featureName}数据加载中` |
|
|
|
|
|
|
|
if (ecologicalDirectDataState.value === "empty") return `${featureName}暂无数据` |
|
|
|
|
|
|
|
if (ecologicalDirectDataState.value === "error") return `${featureName}数据加载失败,请稍后重试` |
|
|
|
return "" |
|
|
|
return "" |
|
|
|
}) |
|
|
|
}) |
|
|
|
const baseActiveLayer = computed(() => activeLayerKey.value ? getLayerByKey(currentView.value, activeLayerKey.value) : null) |
|
|
|
const baseActiveLayer = computed(() => activeLayerKey.value ? getLayerByKey(currentView.value, activeLayerKey.value) : null) |
|
|
|
@ -337,7 +341,7 @@ const activeLayer = computed(() => { |
|
|
|
}) |
|
|
|
}) |
|
|
|
const currentPanels = computed(() => { |
|
|
|
const currentPanels = computed(() => { |
|
|
|
if (isEcologicalRedlineView.value) return redlinePanels.value |
|
|
|
if (isEcologicalRedlineView.value) return redlinePanels.value |
|
|
|
if (isEcologicalScopeView.value) return scopePanels.value |
|
|
|
if (isNaturalProtectedAreaView.value) return naturalProtectedAreaPanels.value |
|
|
|
if (currentView.value === "restoration") return restorationPanels.value |
|
|
|
if (currentView.value === "restoration") return restorationPanels.value |
|
|
|
if (currentView.value === "engineering-analysis") return engineeringAnalysisPanels |
|
|
|
if (currentView.value === "engineering-analysis") return engineeringAnalysisPanels |
|
|
|
return nationalParkPanels.value |
|
|
|
return nationalParkPanels.value |
|
|
|
@ -422,6 +426,7 @@ function syncView(viewKey) { |
|
|
|
const isRestoration = viewKey === "restoration" |
|
|
|
const isRestoration = viewKey === "restoration" |
|
|
|
const isEngineering = viewKey === "engineering-analysis" |
|
|
|
const isEngineering = viewKey === "engineering-analysis" |
|
|
|
const isRedline = viewKey === "ecological-redline" |
|
|
|
const isRedline = viewKey === "ecological-redline" |
|
|
|
|
|
|
|
const isNaturalProtectedArea = viewKey === "natural-protected-area" |
|
|
|
mapRanking.value = getEcologicalMapRanking(viewKey) |
|
|
|
mapRanking.value = getEcologicalMapRanking(viewKey) |
|
|
|
mapSceneRef.value?.setBoundaryDrawing?.(false) |
|
|
|
mapSceneRef.value?.setBoundaryDrawing?.(false) |
|
|
|
mapSceneRef.value?.clearAnalysisBoundary?.() |
|
|
|
mapSceneRef.value?.clearAnalysisBoundary?.() |
|
|
|
@ -430,8 +435,9 @@ function syncView(viewKey) { |
|
|
|
if (isRedline) { |
|
|
|
if (isRedline) { |
|
|
|
redlineDataState.value = "loading" |
|
|
|
redlineDataState.value = "loading" |
|
|
|
redlinePanels.value = buildEcologicalRedlinePanels() |
|
|
|
redlinePanels.value = buildEcologicalRedlinePanels() |
|
|
|
} else if (ecologicalScopeViewKeys.includes(viewKey)) { |
|
|
|
} else if (isNaturalProtectedArea) { |
|
|
|
scopePanels.value = buildEcologicalScopePanels({}, viewKey) |
|
|
|
naturalProtectedAreaDataState.value = "loading" |
|
|
|
|
|
|
|
naturalProtectedAreaPanels.value = buildNaturalProtectedAreaPanels() |
|
|
|
} |
|
|
|
} |
|
|
|
if (isNationalPark) { |
|
|
|
if (isNationalPark) { |
|
|
|
nationalParkPanels.value = buildNationalParkPanels({}) |
|
|
|
nationalParkPanels.value = buildNationalParkPanels({}) |
|
|
|
@ -446,10 +452,8 @@ function syncView(viewKey) { |
|
|
|
emit("module-stats", { |
|
|
|
emit("module-stats", { |
|
|
|
moduleKey: "ecological-protection", |
|
|
|
moduleKey: "ecological-protection", |
|
|
|
viewKey, |
|
|
|
viewKey, |
|
|
|
items: isRedline |
|
|
|
items: isRedline || isNaturalProtectedArea |
|
|
|
? [] |
|
|
|
? [] |
|
|
|
: ecologicalScopeViewKeys.includes(viewKey) |
|
|
|
|
|
|
|
? getEcologicalScopeTopStats({}, viewKey) |
|
|
|
|
|
|
|
: isNationalPark |
|
|
|
: isNationalPark |
|
|
|
? getNationalParkTopStats({}) |
|
|
|
? getNationalParkTopStats({}) |
|
|
|
: isRestoration |
|
|
|
: isRestoration |
|
|
|
@ -458,8 +462,8 @@ function syncView(viewKey) { |
|
|
|
}) |
|
|
|
}) |
|
|
|
if (isRedline) { |
|
|
|
if (isRedline) { |
|
|
|
loadEcologicalRedlineStats(viewKey) |
|
|
|
loadEcologicalRedlineStats(viewKey) |
|
|
|
} else if (ecologicalScopeViewKeys.includes(viewKey)) { |
|
|
|
} else if (isNaturalProtectedArea) { |
|
|
|
loadEcologicalScopeStats(viewKey) |
|
|
|
loadNaturalProtectedAreaStats(viewKey) |
|
|
|
} else if (isNationalPark) { |
|
|
|
} else if (isNationalPark) { |
|
|
|
loadNationalParkStats(viewKey) |
|
|
|
loadNationalParkStats(viewKey) |
|
|
|
} else if (isRestoration) { |
|
|
|
} else if (isRestoration) { |
|
|
|
@ -568,32 +572,35 @@ function handleViewSelect(viewKey) { |
|
|
|
emit("view-change", nextKey) |
|
|
|
emit("view-change", nextKey) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function loadEcologicalScopeStats(viewKey) { |
|
|
|
async function loadNaturalProtectedAreaStats(viewKey) { |
|
|
|
const requestId = ++scopeStatsRequestId |
|
|
|
const requestId = ++naturalProtectedAreaStatsRequestId |
|
|
|
|
|
|
|
naturalProtectedAreaDataState.value = "loading" |
|
|
|
|
|
|
|
naturalProtectedAreaPanels.value = buildNaturalProtectedAreaPanels() |
|
|
|
try { |
|
|
|
try { |
|
|
|
const cached = scopeStatsCache.get(viewKey) |
|
|
|
const stats = naturalProtectedAreaStatsCache || await getNaturalProtectedAreaStats() |
|
|
|
const stats = cached || await getNaturalProtectedAreaStats() |
|
|
|
if (requestId !== naturalProtectedAreaStatsRequestId || currentView.value !== viewKey) return |
|
|
|
if (requestId !== scopeStatsRequestId || currentView.value !== viewKey) return |
|
|
|
naturalProtectedAreaStatsCache = stats |
|
|
|
scopeStatsCache.set(viewKey, stats) |
|
|
|
naturalProtectedAreaDataState.value = stats.dataState |
|
|
|
scopePanels.value = buildEcologicalScopePanels(stats, viewKey) |
|
|
|
naturalProtectedAreaPanels.value = buildNaturalProtectedAreaPanels(stats.panels) |
|
|
|
emit("module-stats", { |
|
|
|
emit("module-stats", { |
|
|
|
moduleKey: "ecological-protection", |
|
|
|
moduleKey: "ecological-protection", |
|
|
|
viewKey, |
|
|
|
viewKey, |
|
|
|
items: getEcologicalScopeTopStats(stats, viewKey), |
|
|
|
items: stats.topRows.rows, |
|
|
|
}) |
|
|
|
}) |
|
|
|
} catch (error) { |
|
|
|
} catch (error) { |
|
|
|
if (requestId !== scopeStatsRequestId || currentView.value !== viewKey) return |
|
|
|
if (requestId !== naturalProtectedAreaStatsRequestId || currentView.value !== viewKey) return |
|
|
|
scopePanels.value = buildEcologicalScopePanels({}, viewKey) |
|
|
|
naturalProtectedAreaDataState.value = "error" |
|
|
|
|
|
|
|
naturalProtectedAreaPanels.value = buildNaturalProtectedAreaPanels() |
|
|
|
emit("module-stats", { |
|
|
|
emit("module-stats", { |
|
|
|
moduleKey: "ecological-protection", |
|
|
|
moduleKey: "ecological-protection", |
|
|
|
viewKey, |
|
|
|
viewKey, |
|
|
|
items: getEcologicalScopeTopStats({}, viewKey), |
|
|
|
items: [], |
|
|
|
}) |
|
|
|
}) |
|
|
|
layerStatus.value = { |
|
|
|
layerStatus.value = { |
|
|
|
type: "error", |
|
|
|
type: "error", |
|
|
|
text: "保护范围统计加载失败", |
|
|
|
text: "自然保护地统计加载失败", |
|
|
|
} |
|
|
|
} |
|
|
|
console.warn("Failed to load ecological scope statistics", error) |
|
|
|
console.warn("Failed to load natural-protected-area statistics", error) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|