|
|
|
|
@ -14,6 +14,15 @@ |
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
<div class="forest-grass-wet-ui ecological-protection-ui"> |
|
|
|
|
<div |
|
|
|
|
v-if="isEcologicalRedlineView && redlineDataState !== 'ready'" |
|
|
|
|
class="fgw-data-state" |
|
|
|
|
:class="{ 'is-error': redlineDataState === 'error' }" |
|
|
|
|
role="status" |
|
|
|
|
aria-live="polite" |
|
|
|
|
> |
|
|
|
|
{{ redlineDataStateMessage }} |
|
|
|
|
</div> |
|
|
|
|
<div v-if="!isEngineeringAnalysis" class="fgw-left"> |
|
|
|
|
<div class="fgw-side-stack is-left"> |
|
|
|
|
<m-card |
|
|
|
|
@ -170,8 +179,9 @@ import { |
|
|
|
|
} from "@/config/layers" |
|
|
|
|
import { |
|
|
|
|
getEcologicalEngineeringAnalysisStats, |
|
|
|
|
getEcologicalRedlineStats, |
|
|
|
|
getEcologicalRestorationStats, |
|
|
|
|
getEcologicalScopeStats, |
|
|
|
|
getNaturalProtectedAreaStats, |
|
|
|
|
getNationalParkStats, |
|
|
|
|
} from "@/services/ecologicalProtectionApi" |
|
|
|
|
import { getProjectClickInfoByWkt } from "@/services/pastureApi" |
|
|
|
|
@ -186,6 +196,7 @@ import TopicSwitcher from "@/views/forestGrassWet/components/TopicSwitcher.vue" |
|
|
|
|
import EngineeringAnalysisPanel from "./components/EngineeringAnalysisPanel.vue" |
|
|
|
|
import EngineeringStatisticsPanel from "./components/EngineeringStatisticsPanel.vue" |
|
|
|
|
import { |
|
|
|
|
buildEcologicalRedlinePanels, |
|
|
|
|
buildEcologicalScopePanels, |
|
|
|
|
buildEcologicalRestorationPanels, |
|
|
|
|
buildNationalParkPanels, |
|
|
|
|
@ -216,7 +227,9 @@ const emit = defineEmits(["module-stats", "view-change"]) |
|
|
|
|
const mapSceneRef = ref(null) |
|
|
|
|
const activeLayerKey = ref("") |
|
|
|
|
const selectedLegendKey = ref("") |
|
|
|
|
const scopePanels = ref(buildEcologicalScopePanels({}, "ecological-redline")) |
|
|
|
|
const redlinePanels = ref(buildEcologicalRedlinePanels()) |
|
|
|
|
const redlineDataState = ref("loading") |
|
|
|
|
const scopePanels = ref(buildEcologicalScopePanels({}, "natural-protected-area")) |
|
|
|
|
const nationalParkPanels = ref(buildNationalParkPanels({})) |
|
|
|
|
const restorationPanels = ref(buildEcologicalRestorationPanels({})) |
|
|
|
|
const selectedFeature = ref(null) |
|
|
|
|
@ -242,11 +255,13 @@ let mapAssetsReady = false |
|
|
|
|
let mapLoadStarted = false |
|
|
|
|
let mapLoadTimer = null |
|
|
|
|
let scopeStatsRequestId = 0 |
|
|
|
|
let redlineStatsRequestId = 0 |
|
|
|
|
let nationalParkStatsRequestId = 0 |
|
|
|
|
let restorationStatsRequestId = 0 |
|
|
|
|
let engineeringAnalysisRequestId = 0 |
|
|
|
|
let featureQueryRequestId = 0 |
|
|
|
|
const scopeStatsCache = new Map() |
|
|
|
|
let redlineStatsCache = null |
|
|
|
|
let nationalParkStatsCache = null |
|
|
|
|
let restorationStatsCache = null |
|
|
|
|
let engineeringAnalysisCache = null |
|
|
|
|
@ -281,7 +296,14 @@ const currentView = computed(() => |
|
|
|
|
) |
|
|
|
|
const isEngineeringAnalysis = computed(() => currentView.value === "engineering-analysis") |
|
|
|
|
const isProjectDetailView = computed(() => ["restoration", "engineering-analysis"].includes(currentView.value)) |
|
|
|
|
const isEcologicalRedlineView = computed(() => currentView.value === "ecological-redline") |
|
|
|
|
const isEcologicalScopeView = computed(() => ecologicalScopeViewKeys.includes(currentView.value)) |
|
|
|
|
const redlineDataStateMessage = computed(() => { |
|
|
|
|
if (redlineDataState.value === "loading") return "生态保护红线数据加载中" |
|
|
|
|
if (redlineDataState.value === "empty") return "生态保护红线暂无数据" |
|
|
|
|
if (redlineDataState.value === "error") return "生态保护红线数据加载失败,请稍后重试" |
|
|
|
|
return "" |
|
|
|
|
}) |
|
|
|
|
const baseActiveLayer = computed(() => activeLayerKey.value ? getLayerByKey(currentView.value, activeLayerKey.value) : null) |
|
|
|
|
const selectedLegend = computed(() => |
|
|
|
|
(baseActiveLayer.value?.legends || []).find((item) => item.key === selectedLegendKey.value) || null |
|
|
|
|
@ -314,6 +336,7 @@ const activeLayer = computed(() => { |
|
|
|
|
: layer |
|
|
|
|
}) |
|
|
|
|
const currentPanels = computed(() => { |
|
|
|
|
if (isEcologicalRedlineView.value) return redlinePanels.value |
|
|
|
|
if (isEcologicalScopeView.value) return scopePanels.value |
|
|
|
|
if (currentView.value === "restoration") return restorationPanels.value |
|
|
|
|
if (currentView.value === "engineering-analysis") return engineeringAnalysisPanels |
|
|
|
|
@ -398,12 +421,16 @@ function syncView(viewKey) { |
|
|
|
|
const isNationalPark = viewKey === "national-park" |
|
|
|
|
const isRestoration = viewKey === "restoration" |
|
|
|
|
const isEngineering = viewKey === "engineering-analysis" |
|
|
|
|
const isRedline = viewKey === "ecological-redline" |
|
|
|
|
mapRanking.value = getEcologicalMapRanking(viewKey) |
|
|
|
|
mapSceneRef.value?.setBoundaryDrawing?.(false) |
|
|
|
|
mapSceneRef.value?.clearAnalysisBoundary?.() |
|
|
|
|
if (viewKey !== "engineering-analysis") mapSceneRef.value?.clearEngineeringSuitability?.() |
|
|
|
|
closeFeaturePanel() |
|
|
|
|
if (ecologicalScopeViewKeys.includes(viewKey)) { |
|
|
|
|
if (isRedline) { |
|
|
|
|
redlineDataState.value = "loading" |
|
|
|
|
redlinePanels.value = buildEcologicalRedlinePanels() |
|
|
|
|
} else if (ecologicalScopeViewKeys.includes(viewKey)) { |
|
|
|
|
scopePanels.value = buildEcologicalScopePanels({}, viewKey) |
|
|
|
|
} |
|
|
|
|
if (isNationalPark) { |
|
|
|
|
@ -419,15 +446,19 @@ function syncView(viewKey) { |
|
|
|
|
emit("module-stats", { |
|
|
|
|
moduleKey: "ecological-protection", |
|
|
|
|
viewKey, |
|
|
|
|
items: ecologicalScopeViewKeys.includes(viewKey) |
|
|
|
|
? getEcologicalScopeTopStats({}, viewKey) |
|
|
|
|
items: isRedline |
|
|
|
|
? [] |
|
|
|
|
: ecologicalScopeViewKeys.includes(viewKey) |
|
|
|
|
? getEcologicalScopeTopStats({}, viewKey) |
|
|
|
|
: isNationalPark |
|
|
|
|
? getNationalParkTopStats({}) |
|
|
|
|
: isRestoration |
|
|
|
|
? getEcologicalRestorationTopStats({}) |
|
|
|
|
: [], |
|
|
|
|
}) |
|
|
|
|
if (ecologicalScopeViewKeys.includes(viewKey)) { |
|
|
|
|
if (isRedline) { |
|
|
|
|
loadEcologicalRedlineStats(viewKey) |
|
|
|
|
} else if (ecologicalScopeViewKeys.includes(viewKey)) { |
|
|
|
|
loadEcologicalScopeStats(viewKey) |
|
|
|
|
} else if (isNationalPark) { |
|
|
|
|
loadNationalParkStats(viewKey) |
|
|
|
|
@ -541,7 +572,7 @@ async function loadEcologicalScopeStats(viewKey) { |
|
|
|
|
const requestId = ++scopeStatsRequestId |
|
|
|
|
try { |
|
|
|
|
const cached = scopeStatsCache.get(viewKey) |
|
|
|
|
const stats = cached || await getEcologicalScopeStats(viewKey) |
|
|
|
|
const stats = cached || await getNaturalProtectedAreaStats() |
|
|
|
|
if (requestId !== scopeStatsRequestId || currentView.value !== viewKey) return |
|
|
|
|
scopeStatsCache.set(viewKey, stats) |
|
|
|
|
scopePanels.value = buildEcologicalScopePanels(stats, viewKey) |
|
|
|
|
@ -566,6 +597,38 @@ async function loadEcologicalScopeStats(viewKey) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function loadEcologicalRedlineStats(viewKey) { |
|
|
|
|
const requestId = ++redlineStatsRequestId |
|
|
|
|
redlineDataState.value = "loading" |
|
|
|
|
redlinePanels.value = buildEcologicalRedlinePanels() |
|
|
|
|
try { |
|
|
|
|
const stats = redlineStatsCache || await getEcologicalRedlineStats() |
|
|
|
|
if (requestId !== redlineStatsRequestId || currentView.value !== viewKey) return |
|
|
|
|
redlineStatsCache = stats |
|
|
|
|
redlineDataState.value = stats.dataState |
|
|
|
|
redlinePanels.value = buildEcologicalRedlinePanels(stats.panels) |
|
|
|
|
emit("module-stats", { |
|
|
|
|
moduleKey: "ecological-protection", |
|
|
|
|
viewKey, |
|
|
|
|
items: stats.topRows.rows, |
|
|
|
|
}) |
|
|
|
|
} catch (error) { |
|
|
|
|
if (requestId !== redlineStatsRequestId || currentView.value !== viewKey) return |
|
|
|
|
redlineDataState.value = "error" |
|
|
|
|
redlinePanels.value = buildEcologicalRedlinePanels() |
|
|
|
|
emit("module-stats", { |
|
|
|
|
moduleKey: "ecological-protection", |
|
|
|
|
viewKey, |
|
|
|
|
items: [], |
|
|
|
|
}) |
|
|
|
|
layerStatus.value = { |
|
|
|
|
type: "error", |
|
|
|
|
text: "生态保护红线统计加载失败", |
|
|
|
|
} |
|
|
|
|
console.warn("Failed to load ecological-redline statistics", error) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function initAssets() { |
|
|
|
|
assets = new Assets() |
|
|
|
|
const params = { progress: 0 } |
|
|
|
|
|