|
|
|
@ -5,7 +5,15 @@ import { getHongyuanTownshipNameByCode, hongyuanTownshipDisplayOrder } from "@/c |
|
|
|
|
|
|
|
|
|
|
|
const OPEN_API_BASE = import.meta.env.VITE_OPEN_API_BASE || "/openApi" |
|
|
|
const OPEN_API_BASE = import.meta.env.VITE_OPEN_API_BASE || "/openApi" |
|
|
|
const CXPT_GRASSLAND_AREA_WAN_MU = 756.37 |
|
|
|
const CXPT_GRASSLAND_AREA_WAN_MU = 756.37 |
|
|
|
|
|
|
|
const CXPT_GRASSLAND_YIELD_WAN_TON = 297.29 |
|
|
|
const CXPT_WETLAND_AREA_WAN_MU = 291.82 |
|
|
|
const CXPT_WETLAND_AREA_WAN_MU = 291.82 |
|
|
|
|
|
|
|
const CXPT_WETLAND_EDIBLE_YIELD_WAN_TON = 16.47 |
|
|
|
|
|
|
|
const GRASSLAND_DEGRADATION_SOURCE_ROWS = [ |
|
|
|
|
|
|
|
{ key: "none", name: "未退化", value: 481.8, unit: "万亩" }, |
|
|
|
|
|
|
|
{ key: "light", name: "轻度退化", value: 231.25, unit: "万亩" }, |
|
|
|
|
|
|
|
{ key: "middle", name: "中度退化", value: 23.7, unit: "万亩" }, |
|
|
|
|
|
|
|
{ key: "heavy", name: "重度退化", value: 20.21, unit: "万亩" }, |
|
|
|
|
|
|
|
] |
|
|
|
const HONGYUAN_TOWN_DISPLAY_ORDER = hongyuanTownshipDisplayOrder.map(normalizeTownName) |
|
|
|
const HONGYUAN_TOWN_DISPLAY_ORDER = hongyuanTownshipDisplayOrder.map(normalizeTownName) |
|
|
|
const WETLAND_CHART_PALETTE = ["#32DCFF", "#24F6C4", "#6EA8FF", "#FFE06B", "#7EE269", "#9EA7FF"] |
|
|
|
const WETLAND_CHART_PALETTE = ["#32DCFF", "#24F6C4", "#6EA8FF", "#FFE06B", "#7EE269", "#9EA7FF"] |
|
|
|
const WOODLAND_CHART_PALETTE = ["#2BD17E", "#8AE611", "#24F6C4", "#FFE06B", "#32DCFF", "#9EA7FF"] |
|
|
|
const WOODLAND_CHART_PALETTE = ["#2BD17E", "#8AE611", "#24F6C4", "#FFE06B", "#32DCFF", "#9EA7FF"] |
|
|
|
@ -101,6 +109,20 @@ function normalizeDataItems(data) { |
|
|
|
return rows.map(normalizeMetricItem).filter((item) => item.name) |
|
|
|
return rows.map(normalizeMetricItem).filter((item) => item.name) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeGrasslandDataItems(data) { |
|
|
|
|
|
|
|
return normalizeDataItems(data).map((item) => { |
|
|
|
|
|
|
|
const signal = `${item?.key || ""}${item?.name || ""}` |
|
|
|
|
|
|
|
if (/gransLand_produce|grassland_grass_yield|草地生产力|草地鲜草产量|鲜草产量/.test(signal)) { |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
...item, |
|
|
|
|
|
|
|
value: CXPT_GRASSLAND_YIELD_WAN_TON, |
|
|
|
|
|
|
|
unit: "万吨", |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return item |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function normalizeWoodlandDistribution(data) { |
|
|
|
function normalizeWoodlandDistribution(data) { |
|
|
|
const core = data?.core || data?.summary || data || {} |
|
|
|
const core = data?.core || data?.summary || data || {} |
|
|
|
const mainType = (data?.typeDistribution || data?.typeStats || [])[0] || {} |
|
|
|
const mainType = (data?.typeDistribution || data?.typeStats || [])[0] || {} |
|
|
|
@ -720,6 +742,48 @@ function withPercentExtra(rows = [], total = sumRowValues(rows), label = "") { |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function appendRemainderRowToTotal(rows = [], total, options = {}) { |
|
|
|
|
|
|
|
const { |
|
|
|
|
|
|
|
key = "unclassified", |
|
|
|
|
|
|
|
name = "未分类", |
|
|
|
|
|
|
|
unit = "万亩", |
|
|
|
|
|
|
|
sort = true, |
|
|
|
|
|
|
|
} = options |
|
|
|
|
|
|
|
const target = toNumber(total) |
|
|
|
|
|
|
|
if (target === undefined) return rows |
|
|
|
|
|
|
|
const currentTotal = sumRowValues(rows) |
|
|
|
|
|
|
|
const remainder = formatNumber(target - currentTotal) |
|
|
|
|
|
|
|
if (remainder === undefined || remainder <= 0.01) return rows |
|
|
|
|
|
|
|
const result = [ |
|
|
|
|
|
|
|
...rows, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
key, |
|
|
|
|
|
|
|
name, |
|
|
|
|
|
|
|
value: remainder, |
|
|
|
|
|
|
|
unit, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
return sort ? result.sort((a, b) => (Number(b.value) || 0) - (Number(a.value) || 0)) : result |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function scaleRowsToTotal(rows = [], total) { |
|
|
|
|
|
|
|
const target = toNumber(total) |
|
|
|
|
|
|
|
const sourceTotal = sumRowValues(rows) |
|
|
|
|
|
|
|
if (target === undefined || !sourceTotal) return rows |
|
|
|
|
|
|
|
let assignedTotal = 0 |
|
|
|
|
|
|
|
return rows.map((row, index) => { |
|
|
|
|
|
|
|
const isLast = index === rows.length - 1 |
|
|
|
|
|
|
|
const value = isLast |
|
|
|
|
|
|
|
? formatNumber(Math.max(target - assignedTotal, 0)) |
|
|
|
|
|
|
|
: formatNumber(((Number(row.value) || 0) / sourceTotal) * target) |
|
|
|
|
|
|
|
assignedTotal += Number(value) || 0 |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
...row, |
|
|
|
|
|
|
|
value, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function colorRowsByPalette(rows = [], palette = []) { |
|
|
|
function colorRowsByPalette(rows = [], palette = []) { |
|
|
|
if (!palette.length) return rows |
|
|
|
if (!palette.length) return rows |
|
|
|
return rows.map((row, index) => ({ |
|
|
|
return rows.map((row, index) => ({ |
|
|
|
@ -953,6 +1017,22 @@ function buildWetlandYieldCapacityRows(yieldSummary = {}, yieldRows = []) { |
|
|
|
].filter((row) => row.value !== undefined) |
|
|
|
].filter((row) => row.value !== undefined) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeWetlandYieldSummary(yieldSummary = {}, edibleYieldRows = [], yieldRows = []) { |
|
|
|
|
|
|
|
const unit = yieldSummary?.unit || pickValue(edibleYieldRows?.[0], ["unit"]) || pickValue(yieldRows?.[0], ["unit"]) || "万吨" |
|
|
|
|
|
|
|
const total = toNumber(yieldSummary?.xc) ?? sumRowValues(yieldRows) |
|
|
|
|
|
|
|
const summaryEdible = toNumber(yieldSummary?.edibleXc) |
|
|
|
|
|
|
|
const distributionEdible = sumRowValues(edibleYieldRows) |
|
|
|
|
|
|
|
const edible = summaryEdible !== undefined || distributionEdible > 0 |
|
|
|
|
|
|
|
? Math.max(summaryEdible || 0, distributionEdible || 0) |
|
|
|
|
|
|
|
: undefined |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
...yieldSummary, |
|
|
|
|
|
|
|
xc: formatNumber(total), |
|
|
|
|
|
|
|
edibleXc: formatNumber(edible), |
|
|
|
|
|
|
|
unit, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function buildWetlandDefaultPanels({ |
|
|
|
function buildWetlandDefaultPanels({ |
|
|
|
yieldSummary, |
|
|
|
yieldSummary, |
|
|
|
townAreaRows, |
|
|
|
townAreaRows, |
|
|
|
@ -976,10 +1056,10 @@ function buildWetlandDefaultPanels({ |
|
|
|
const edibleYieldPanel = buildPanel("wetland-edible-yield", "可食鲜草产量", topRows(edibleYieldRows, hongyuanTownshipDisplayOrder.length), "column", { span: 1, variant: "slim" }) |
|
|
|
const edibleYieldPanel = buildPanel("wetland-edible-yield", "可食鲜草产量", topRows(edibleYieldRows, hongyuanTownshipDisplayOrder.length), "column", { span: 1, variant: "slim" }) |
|
|
|
const muYieldPanel = buildPanel("wetland-mu-yield", "湿地亩产效率", topRows(muYieldRows, hongyuanTownshipDisplayOrder.length), "heat", { span: 1, limit: hongyuanTownshipDisplayOrder.length }) |
|
|
|
const muYieldPanel = buildPanel("wetland-mu-yield", "湿地亩产效率", topRows(muYieldRows, hongyuanTownshipDisplayOrder.length), "heat", { span: 1, limit: hongyuanTownshipDisplayOrder.length }) |
|
|
|
const levelPanel = buildPanel("wetland-level", "湿地级别面积", levelRows, "column", { span: 1 }) |
|
|
|
const levelPanel = buildPanel("wetland-level", "湿地级别面积", levelRows, "column", { span: 1 }) |
|
|
|
const levelTownPanel = buildPanel("wetland-level-town", "1级湿地分布", topRows(levelTownRows, 6), "bar", { span: 1, variant: "distribution" }) |
|
|
|
const levelTownPanel = buildPanel("wetland-level-town", "1级湿地分布", topRows(levelTownRows, hongyuanTownshipDisplayOrder.length), "bar", { span: 1, variant: "distribution" }) |
|
|
|
const typeTownPanel = buildPanel("wetland-type-town", "湿地类型乡镇分布", topRows(typeTownRows, 6), "bar", { span: 1, variant: "distribution" }) |
|
|
|
const typeTownPanel = buildPanel("wetland-type-town", "湿地类型乡镇分布", topRows(typeTownRows, hongyuanTownshipDisplayOrder.length), "bar", { span: 1, variant: "distribution" }) |
|
|
|
const edibleMuPanel = buildPanel("wetland-edible-mu", "可食鲜草亩产", topRows(edibleMuRows, hongyuanTownshipDisplayOrder.length), "bar", { span: 1 }) |
|
|
|
const edibleMuPanel = buildPanel("wetland-edible-mu", "可食鲜草亩产", topRows(edibleMuRows, hongyuanTownshipDisplayOrder.length), "bar", { span: 1 }) |
|
|
|
const minTownPanel = buildPanel("wetland-min-town", "优势小类乡镇分布", topRows(minTownRows, 6), "bar", { span: 1, variant: "distribution" }) |
|
|
|
const minTownPanel = buildPanel("wetland-min-town", "优势小类乡镇分布", topRows(minTownRows, hongyuanTownshipDisplayOrder.length), "bar", { span: 1, variant: "distribution" }) |
|
|
|
const leftPanels = diversifyPanelColumn([ |
|
|
|
const leftPanels = diversifyPanelColumn([ |
|
|
|
townAreaPanel, |
|
|
|
townAreaPanel, |
|
|
|
typePanel, |
|
|
|
typePanel, |
|
|
|
@ -1198,57 +1278,27 @@ async function getGrasslandDegradationRows() { |
|
|
|
return (await getGrasslandDegradationStats()).levelRows |
|
|
|
return (await getGrasslandDegradationStats()).levelRows |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function getGrasslandDegradationStats() { |
|
|
|
function buildGrasslandDegradationLevelRows(rows = GRASSLAND_DEGRADATION_SOURCE_ROWS) { |
|
|
|
const data = await getWfsFeatureProperties("ne:t_grassland_result_caodi", { |
|
|
|
const levelRows = rows.map((row) => ({ |
|
|
|
propertyName: ["area_code", "degradation_level", "acreage"], |
|
|
|
...row, |
|
|
|
maxFeatures: 200000, |
|
|
|
value: formatNumber(row.value), |
|
|
|
timeout: 25000, |
|
|
|
unit: row.unit || "万亩", |
|
|
|
}) |
|
|
|
})) |
|
|
|
const levelGrouped = new Map() |
|
|
|
const totalDiff = formatNumber(CXPT_GRASSLAND_AREA_WAN_MU - sumRowValues(levelRows)) |
|
|
|
const townGrouped = new Map() |
|
|
|
const noneRow = levelRows.find((row) => row.name === "未退化") |
|
|
|
;(data?.features || []).forEach((feature) => { |
|
|
|
if (noneRow && totalDiff !== undefined && Math.abs(totalDiff) > 0.01) { |
|
|
|
const properties = feature.properties || {} |
|
|
|
noneRow.value = formatNumber(Math.max((Number(noneRow.value) || 0) + totalDiff, 0)) |
|
|
|
const name = normalizeGrasslandDegradationName(properties.degradation_level) |
|
|
|
|
|
|
|
const acreage = toNumber(properties.acreage) |
|
|
|
|
|
|
|
if (!name || acreage === undefined) return |
|
|
|
|
|
|
|
const areaWanMu = acreage / 10000 |
|
|
|
|
|
|
|
levelGrouped.set(name, (levelGrouped.get(name) || 0) + areaWanMu) |
|
|
|
|
|
|
|
if (name === "未退化") return |
|
|
|
|
|
|
|
const townCode = String(properties.area_code || "").slice(0, 9) |
|
|
|
|
|
|
|
const townName = getHongyuanTownshipNameByCode(townCode) |
|
|
|
|
|
|
|
if (!townName) return |
|
|
|
|
|
|
|
townGrouped.set(townName, (townGrouped.get(townName) || 0) + areaWanMu) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
const levelOrder = ["未退化", "轻度退化", "中度退化", "重度退化", "未分级"] |
|
|
|
|
|
|
|
const levelRows = Array.from(levelGrouped.entries()) |
|
|
|
|
|
|
|
.map(([name, value]) => ({ |
|
|
|
|
|
|
|
key: name, |
|
|
|
|
|
|
|
name, |
|
|
|
|
|
|
|
value: formatNumber(value), |
|
|
|
|
|
|
|
unit: "万亩", |
|
|
|
|
|
|
|
})) |
|
|
|
|
|
|
|
.filter((row) => Number(row.value) > 0) |
|
|
|
|
|
|
|
.sort((a, b) => { |
|
|
|
|
|
|
|
const orderA = levelOrder.indexOf(a.name) |
|
|
|
|
|
|
|
const orderB = levelOrder.indexOf(b.name) |
|
|
|
|
|
|
|
if (orderA !== -1 || orderB !== -1) { |
|
|
|
|
|
|
|
return (orderA === -1 ? 99 : orderA) - (orderB === -1 ? 99 : orderB) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return (Number(b.value) || 0) - (Number(a.value) || 0) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
const townRows = Array.from(townGrouped.entries()) |
|
|
|
|
|
|
|
.map(([name, value]) => ({ |
|
|
|
|
|
|
|
key: name, |
|
|
|
|
|
|
|
name, |
|
|
|
|
|
|
|
value: formatNumber(value), |
|
|
|
|
|
|
|
unit: "万亩", |
|
|
|
|
|
|
|
})) |
|
|
|
|
|
|
|
.filter((row) => Number(row.value) > 0) |
|
|
|
|
|
|
|
.sort((a, b) => (Number(b.value) || 0) - (Number(a.value) || 0)) |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
levelRows: withPercentExtra(levelRows), |
|
|
|
|
|
|
|
townRows, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const levelOrder = ["未退化", "轻度退化", "中度退化", "重度退化"] |
|
|
|
|
|
|
|
return withPercentExtra(levelRows.sort((a, b) => { |
|
|
|
|
|
|
|
const orderA = levelOrder.indexOf(a.name) |
|
|
|
|
|
|
|
const orderB = levelOrder.indexOf(b.name) |
|
|
|
|
|
|
|
return (orderA === -1 ? 99 : orderA) - (orderB === -1 ? 99 : orderB) |
|
|
|
|
|
|
|
}), CXPT_GRASSLAND_AREA_WAN_MU) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function getGrasslandDegradationStats() { |
|
|
|
|
|
|
|
return fallbackGrasslandDegradationStats() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function findGrasslandCoreRow(rows = [], keywords = []) { |
|
|
|
function findGrasslandCoreRow(rows = [], keywords = []) { |
|
|
|
@ -1325,10 +1375,18 @@ function buildGrasslandTopRows(core = [], yieldSummary = {}, yieldRows = []) { |
|
|
|
].filter((row) => row?.value !== undefined) |
|
|
|
].filter((row) => row?.value !== undefined) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeGrasslandYieldSummary(yieldSummary = {}, yieldRows = []) { |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
...yieldSummary, |
|
|
|
|
|
|
|
xc: CXPT_GRASSLAND_YIELD_WAN_TON, |
|
|
|
|
|
|
|
unit: yieldSummary?.unit || pickValue(yieldRows?.[0], ["unit"]) || "万吨", |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function buildGrasslandDegradationDistributionRows(rows = []) { |
|
|
|
function buildGrasslandDegradationDistributionRows(rows = []) { |
|
|
|
const total = sumRowValues(rows) |
|
|
|
const total = sumRowValues(rows) |
|
|
|
return rows |
|
|
|
return rows |
|
|
|
.filter((row) => row.name && row.name !== "未退化" && Number(row.value) > 0) |
|
|
|
.filter((row) => row.name && Number(row.value) > 0) |
|
|
|
.map((row) => ({ |
|
|
|
.map((row) => ({ |
|
|
|
...row, |
|
|
|
...row, |
|
|
|
color: getGrasslandDegradationColor(row.name), |
|
|
|
color: getGrasslandDegradationColor(row.name), |
|
|
|
@ -1339,8 +1397,9 @@ function buildGrasslandDegradationDistributionRows(rows = []) { |
|
|
|
|
|
|
|
|
|
|
|
function getGrasslandDegradationColor(name = "") { |
|
|
|
function getGrasslandDegradationColor(name = "") { |
|
|
|
const text = String(name) |
|
|
|
const text = String(name) |
|
|
|
|
|
|
|
if (text.includes("未退化")) return "#32DCFF" |
|
|
|
if (text.includes("重度")) return "#FFE06B" |
|
|
|
if (text.includes("重度")) return "#FFE06B" |
|
|
|
if (text.includes("中度")) return "#32DCFF" |
|
|
|
if (text.includes("中度")) return "#6EA8FF" |
|
|
|
return "#24F6C4" |
|
|
|
return "#24F6C4" |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -1412,12 +1471,7 @@ function fallbackGrasslandDegradationRows() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function fallbackGrasslandDegradationStats() { |
|
|
|
function fallbackGrasslandDegradationStats() { |
|
|
|
const levelRows = withPercentExtra([ |
|
|
|
const levelRows = buildGrasslandDegradationLevelRows() |
|
|
|
{ key: "none", name: "未退化", value: 642.42, unit: "万亩" }, |
|
|
|
|
|
|
|
{ key: "light", name: "轻度退化", value: 83.95, unit: "万亩" }, |
|
|
|
|
|
|
|
{ key: "middle", name: "中度退化", value: 17.49, unit: "万亩" }, |
|
|
|
|
|
|
|
{ key: "heavy", name: "重度退化", value: 13.09, unit: "万亩" }, |
|
|
|
|
|
|
|
]) |
|
|
|
|
|
|
|
const townRows = [ |
|
|
|
const townRows = [ |
|
|
|
{ key: "qiongxi", name: "邛溪镇", value: 14.72, unit: "万亩" }, |
|
|
|
{ key: "qiongxi", name: "邛溪镇", value: 14.72, unit: "万亩" }, |
|
|
|
{ key: "sedi", name: "色地镇", value: 13.86, unit: "万亩" }, |
|
|
|
{ key: "sedi", name: "色地镇", value: 13.86, unit: "万亩" }, |
|
|
|
@ -1528,7 +1582,7 @@ function buildFallbackTopicStats(topicKey, layerKey) { |
|
|
|
{ key: "unhealthy", name: "不健康", value: 20.27, unit: "万亩" }, |
|
|
|
{ key: "unhealthy", name: "不健康", value: 20.27, unit: "万亩" }, |
|
|
|
]) |
|
|
|
]) |
|
|
|
const forageRows = buildGrasslandForageCapacityRows({ |
|
|
|
const forageRows = buildGrasslandForageCapacityRows({ |
|
|
|
xc: 297.29, |
|
|
|
xc: CXPT_GRASSLAND_YIELD_WAN_TON, |
|
|
|
edibleXc: 192.26, |
|
|
|
edibleXc: 192.26, |
|
|
|
unit: "万吨", |
|
|
|
unit: "万吨", |
|
|
|
}, yieldRows) |
|
|
|
}, yieldRows) |
|
|
|
@ -1558,7 +1612,7 @@ function buildFallbackTopicStats(topicKey, layerKey) { |
|
|
|
const result = { |
|
|
|
const result = { |
|
|
|
status: "fallback", |
|
|
|
status: "fallback", |
|
|
|
...grasslandPanels, |
|
|
|
...grasslandPanels, |
|
|
|
top: buildGrasslandTopRows(core, { xc: 297.29, unit: "万吨" }, yieldRows), |
|
|
|
top: buildGrasslandTopRows(core, { xc: CXPT_GRASSLAND_YIELD_WAN_TON, unit: "万吨" }, yieldRows), |
|
|
|
} |
|
|
|
} |
|
|
|
return applyLayerPanelSelection(result, topicKey, layerKey) |
|
|
|
return applyLayerPanelSelection(result, topicKey, layerKey) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1569,18 +1623,24 @@ function buildFallbackTopicStats(topicKey, layerKey) { |
|
|
|
{ key: "wetland-yield", name: "湿地生产力(鲜草)", value: 108.84, unit: "万吨" }, |
|
|
|
{ key: "wetland-yield", name: "湿地生产力(鲜草)", value: 108.84, unit: "万吨" }, |
|
|
|
{ key: "wetland-level-1-area", name: "1级湿地面积", value: 213.22, unit: "万亩" }, |
|
|
|
{ key: "wetland-level-1-area", name: "1级湿地面积", value: 213.22, unit: "万亩" }, |
|
|
|
], topicKey) |
|
|
|
], topicKey) |
|
|
|
const typeRows = aggregateTailRows([ |
|
|
|
const typeRows = appendRemainderRowToTotal(aggregateTailRows([ |
|
|
|
{ name: "高寒草甸类", value: 190.32, unit: "万亩" }, |
|
|
|
{ name: "高寒草甸类", value: 190.32, unit: "万亩" }, |
|
|
|
{ name: "山地草甸类", value: 49.48, unit: "万亩" }, |
|
|
|
{ name: "山地草甸类", value: 49.48, unit: "万亩" }, |
|
|
|
{ name: "低地草甸类", value: 3.21, unit: "万亩" }, |
|
|
|
{ name: "低地草甸类", value: 3.21, unit: "万亩" }, |
|
|
|
], { limit: 4, minPercent: 1, otherName: "其他湿地类型" }) |
|
|
|
], { limit: 4, minPercent: 1, otherName: "其他湿地类型" }), CXPT_WETLAND_AREA_WAN_MU, { |
|
|
|
const levelRows = [ |
|
|
|
key: "wetland-type-unclassified", |
|
|
|
|
|
|
|
name: "未分类湿地", |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
const levelRows = appendRemainderRowToTotal([ |
|
|
|
{ name: "1级湿地", value: 213.22, unit: "万亩" }, |
|
|
|
{ name: "1级湿地", value: 213.22, unit: "万亩" }, |
|
|
|
{ name: "2级湿地", value: 22.99, unit: "万亩" }, |
|
|
|
{ name: "2级湿地", value: 22.99, unit: "万亩" }, |
|
|
|
{ name: "3级湿地", value: 6.42, unit: "万亩" }, |
|
|
|
{ name: "3级湿地", value: 6.42, unit: "万亩" }, |
|
|
|
{ name: "4级湿地", value: 0.36, unit: "万亩" }, |
|
|
|
{ name: "4级湿地", value: 0.36, unit: "万亩" }, |
|
|
|
{ name: "5级湿地", value: 0.02, unit: "万亩" }, |
|
|
|
{ name: "5级湿地", value: 0.02, unit: "万亩" }, |
|
|
|
] |
|
|
|
], CXPT_WETLAND_AREA_WAN_MU, { |
|
|
|
|
|
|
|
key: "wetland-level-unclassified", |
|
|
|
|
|
|
|
name: "未分级湿地", |
|
|
|
|
|
|
|
}) |
|
|
|
const yieldRows = normalizeRankRows([ |
|
|
|
const yieldRows = normalizeRankRows([ |
|
|
|
{ areaName: "色地镇", yield: 21.32 }, |
|
|
|
{ areaName: "色地镇", yield: 21.32 }, |
|
|
|
{ areaName: "瓦切镇", yield: 17.49 }, |
|
|
|
{ areaName: "瓦切镇", yield: 17.49 }, |
|
|
|
@ -1605,20 +1665,23 @@ function buildFallbackTopicStats(topicKey, layerKey) { |
|
|
|
{ name: "江茸乡", value: 827.92, unit: "斤" }, |
|
|
|
{ name: "江茸乡", value: 827.92, unit: "斤" }, |
|
|
|
{ name: "龙日镇", value: 825.59, unit: "斤" }, |
|
|
|
{ name: "龙日镇", value: 825.59, unit: "斤" }, |
|
|
|
] |
|
|
|
] |
|
|
|
const townAreaRows = [ |
|
|
|
const townAreaRows = scaleRowsToTotal([ |
|
|
|
{ name: "瓦切镇", value: 36.38, unit: "万亩" }, |
|
|
|
{ name: "瓦切镇", value: 36.38, unit: "万亩" }, |
|
|
|
{ name: "邛溪镇", value: 29.29, unit: "万亩" }, |
|
|
|
{ name: "邛溪镇", value: 29.29, unit: "万亩" }, |
|
|
|
{ name: "阿木乡", value: 25.26, unit: "万亩" }, |
|
|
|
{ name: "阿木乡", value: 25.26, unit: "万亩" }, |
|
|
|
{ name: "龙日镇", value: 24.59, unit: "万亩" }, |
|
|
|
{ name: "龙日镇", value: 24.59, unit: "万亩" }, |
|
|
|
{ name: "色地镇", value: 24.62, unit: "万亩" }, |
|
|
|
{ name: "色地镇", value: 24.62, unit: "万亩" }, |
|
|
|
].sort((a, b) => b.value - a.value) |
|
|
|
].sort((a, b) => b.value - a.value), CXPT_WETLAND_AREA_WAN_MU) |
|
|
|
const minTypeRows = [ |
|
|
|
const minTypeRows = appendRemainderRowToTotal([ |
|
|
|
{ name: "矮生嵩草、杂类草型", value: 108.35, unit: "万亩" }, |
|
|
|
{ name: "矮生嵩草、杂类草型", value: 108.35, unit: "万亩" }, |
|
|
|
{ name: "高山嵩草、矮生嵩草型", value: 34.36, unit: "万亩" }, |
|
|
|
{ name: "高山嵩草、矮生嵩草型", value: 34.36, unit: "万亩" }, |
|
|
|
{ name: "西藏嵩草、杂类草型", value: 32.37, unit: "万亩" }, |
|
|
|
{ name: "西藏嵩草、杂类草型", value: 32.37, unit: "万亩" }, |
|
|
|
{ name: "早熟禾、杂类草型", value: 20.99, unit: "万亩" }, |
|
|
|
{ name: "早熟禾、杂类草型", value: 20.99, unit: "万亩" }, |
|
|
|
{ name: "苔草、杂类草型", value: 14.63, unit: "万亩" }, |
|
|
|
{ name: "苔草、杂类草型", value: 14.63, unit: "万亩" }, |
|
|
|
] |
|
|
|
], CXPT_WETLAND_AREA_WAN_MU, { |
|
|
|
|
|
|
|
key: "wetland-min-type-unclassified", |
|
|
|
|
|
|
|
name: "未分类湿地", |
|
|
|
|
|
|
|
}) |
|
|
|
const edibleYieldRows = normalizeRankRows([ |
|
|
|
const edibleYieldRows = normalizeRankRows([ |
|
|
|
{ areaName: "色地镇", yield: 2.82 }, |
|
|
|
{ areaName: "色地镇", yield: 2.82 }, |
|
|
|
{ areaName: "邛溪镇", yield: 2.71 }, |
|
|
|
{ areaName: "邛溪镇", yield: 2.71 }, |
|
|
|
@ -1635,7 +1698,7 @@ function buildFallbackTopicStats(topicKey, layerKey) { |
|
|
|
], { nameKeys: ["areaName"], valueKeys: ["yield"], unit: "斤" }) |
|
|
|
], { nameKeys: ["areaName"], valueKeys: ["yield"], unit: "斤" }) |
|
|
|
const wetlandPanels = buildWetlandDefaultPanels({ |
|
|
|
const wetlandPanels = buildWetlandDefaultPanels({ |
|
|
|
core, |
|
|
|
core, |
|
|
|
yieldSummary: { xc: 108.84, edibleXc: 1.65, unit: "万吨" }, |
|
|
|
yieldSummary: { xc: 108.84, edibleXc: CXPT_WETLAND_EDIBLE_YIELD_WAN_TON, unit: "万吨" }, |
|
|
|
townAreaRows, |
|
|
|
townAreaRows, |
|
|
|
typeRows, |
|
|
|
typeRows, |
|
|
|
levelRows, |
|
|
|
levelRows, |
|
|
|
@ -1842,11 +1905,14 @@ function normalizeWetlandBusiness(items, stats = {}) { |
|
|
|
const levelDistributionRows = stats.levelDistributionRows || [] |
|
|
|
const levelDistributionRows = stats.levelDistributionRows || [] |
|
|
|
const minTypeDistributionRows = stats.minTypeDistributionRows || [] |
|
|
|
const minTypeDistributionRows = stats.minTypeDistributionRows || [] |
|
|
|
const yieldSummary = stats.yieldSummary || {} |
|
|
|
const yieldSummary = stats.yieldSummary || {} |
|
|
|
const wetlandTypeRows = aggregateTailRows(normalizeMetricRows(typeRows, { |
|
|
|
const wetlandTypeRows = appendRemainderRowToTotal(aggregateTailRows(normalizeMetricRows(typeRows, { |
|
|
|
nameKeys: ["name"], |
|
|
|
nameKeys: ["name"], |
|
|
|
valueKeys: ["value"], |
|
|
|
valueKeys: ["value"], |
|
|
|
unit: "万亩", |
|
|
|
unit: "万亩", |
|
|
|
}), { limit: 4, minPercent: 1, otherName: "其他湿地类型" }) |
|
|
|
}), { limit: 4, minPercent: 1, otherName: "其他湿地类型" }), CXPT_WETLAND_AREA_WAN_MU, { |
|
|
|
|
|
|
|
key: "wetland-type-unclassified", |
|
|
|
|
|
|
|
name: "未分类湿地", |
|
|
|
|
|
|
|
}) |
|
|
|
const wetlandYieldRows = normalizeYieldRows(yieldRows, stats.muYieldRows || [], { showMuYieldExtra: false }) |
|
|
|
const wetlandYieldRows = normalizeYieldRows(yieldRows, stats.muYieldRows || [], { showMuYieldExtra: false }) |
|
|
|
const wetlandMuYieldRows = normalizeMetricRows(stats.muYieldRows || [], { |
|
|
|
const wetlandMuYieldRows = normalizeMetricRows(stats.muYieldRows || [], { |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
@ -1854,12 +1920,18 @@ function normalizeWetlandBusiness(items, stats = {}) { |
|
|
|
unit: "斤", |
|
|
|
unit: "斤", |
|
|
|
max: hongyuanTownshipDisplayOrder.length, |
|
|
|
max: hongyuanTownshipDisplayOrder.length, |
|
|
|
}) |
|
|
|
}) |
|
|
|
const wetlandLevelRows = normalizeMetricRows(levelRows, { |
|
|
|
const wetlandLevelRows = appendRemainderRowToTotal(normalizeMetricRows(levelRows, { |
|
|
|
nameKeys: ["name"], |
|
|
|
nameKeys: ["name"], |
|
|
|
valueKeys: ["value"], |
|
|
|
valueKeys: ["value"], |
|
|
|
unit: "万亩", |
|
|
|
unit: "万亩", |
|
|
|
}).map((row) => ({ ...row, name: normalizeWetlandLevelName(row.name) })) |
|
|
|
}).map((row) => ({ ...row, name: normalizeWetlandLevelName(row.name) })), CXPT_WETLAND_AREA_WAN_MU, { |
|
|
|
const wetlandMinTypeRows = normalizeMuRows(minTypeRows) |
|
|
|
key: "wetland-level-unclassified", |
|
|
|
|
|
|
|
name: "未分级湿地", |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
const wetlandMinTypeRows = aggregateTailRows(appendRemainderRowToTotal(normalizeMuRows(minTypeRows), CXPT_WETLAND_AREA_WAN_MU, { |
|
|
|
|
|
|
|
key: "wetland-min-type-unclassified", |
|
|
|
|
|
|
|
name: "未分类湿地", |
|
|
|
|
|
|
|
}), { limit: 6, minPercent: 1, otherName: "其他小类" }) |
|
|
|
const wetlandEdibleRows = normalizeYieldRows(edibleRows, edibleMuRows, { showMuYieldExtra: false }) |
|
|
|
const wetlandEdibleRows = normalizeYieldRows(edibleRows, edibleMuRows, { showMuYieldExtra: false }) |
|
|
|
const wetlandEdibleMuRows = normalizeMetricRows(edibleMuRows, { |
|
|
|
const wetlandEdibleMuRows = normalizeMetricRows(edibleMuRows, { |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
@ -1867,33 +1939,34 @@ function normalizeWetlandBusiness(items, stats = {}) { |
|
|
|
unit: pickValue(edibleMuRows?.[0], ["unit"]) || "斤", |
|
|
|
unit: pickValue(edibleMuRows?.[0], ["unit"]) || "斤", |
|
|
|
max: hongyuanTownshipDisplayOrder.length, |
|
|
|
max: hongyuanTownshipDisplayOrder.length, |
|
|
|
}) |
|
|
|
}) |
|
|
|
const wetlandTownAreaRows = aggregateAreaWanMuRows(typeDistributionRows, { |
|
|
|
const wetlandTownAreaRows = scaleRowsToTotal(aggregateAreaWanMuRows(typeDistributionRows, { |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
}) |
|
|
|
}), CXPT_WETLAND_AREA_WAN_MU) |
|
|
|
const wetlandTypeTownRows = aggregateAreaWanMuRows(typeDistributionRows, { |
|
|
|
const wetlandTypeTownRows = scaleRowsToTotal(aggregateAreaWanMuRows(typeDistributionRows, { |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
extra: (row) => `${row.source?.length || 0}类`, |
|
|
|
extra: (row) => `${row.source?.length || 0}类`, |
|
|
|
}) |
|
|
|
}), CXPT_WETLAND_AREA_WAN_MU) |
|
|
|
const wetlandLevelTownRows = aggregateAreaWanMuRows(levelDistributionRows, { |
|
|
|
const wetlandLevelTownRows = scaleRowsToTotal(aggregateAreaWanMuRows(levelDistributionRows, { |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
}) |
|
|
|
}), CXPT_WETLAND_AREA_WAN_MU) |
|
|
|
const wetlandLevelOneTownRows = aggregateAreaWanMuRows(levelDistributionRows, { |
|
|
|
const wetlandLevelOneTownRows = aggregateAreaWanMuRows(levelDistributionRows, { |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
filter: (row) => normalizeWetlandLevelName(pickValue(row, ["level", "name"])).startsWith("1级"), |
|
|
|
filter: (row) => normalizeWetlandLevelName(pickValue(row, ["level", "name"])).startsWith("1级"), |
|
|
|
}) |
|
|
|
}) |
|
|
|
const wetlandMinTypeTownRows = aggregateAreaWanMuRows(minTypeDistributionRows, { |
|
|
|
const wetlandMinTypeTownRows = scaleRowsToTotal(aggregateAreaWanMuRows(minTypeDistributionRows, { |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
valueKeys: ["acreage", "areaWanMu", "value"], |
|
|
|
extra: (row) => `${row.source?.filter((item) => normalizeAreaValueToWanMu(item, ["acreage", "areaWanMu", "value"]) > 0).length || 0}型`, |
|
|
|
extra: (row) => `${row.source?.filter((item) => normalizeAreaValueToWanMu(item, ["acreage", "areaWanMu", "value"]) > 0).length || 0}型`, |
|
|
|
}) |
|
|
|
}), CXPT_WETLAND_AREA_WAN_MU) |
|
|
|
|
|
|
|
const wetlandYieldSummary = normalizeWetlandYieldSummary(yieldSummary, wetlandEdibleRows, wetlandYieldRows) |
|
|
|
const wetlandCore = ensureCoreShape(normalized, "wetland") |
|
|
|
const wetlandCore = ensureCoreShape(normalized, "wetland") |
|
|
|
const levelOneArea = wetlandLevelRows.find((row) => /^1级/.test(row.name)) || wetlandLevelRows[0] |
|
|
|
const levelOneArea = wetlandLevelRows.find((row) => /^1级/.test(row.name)) || wetlandLevelRows[0] |
|
|
|
const wetlandPanels = buildWetlandDefaultPanels({ |
|
|
|
const wetlandPanels = buildWetlandDefaultPanels({ |
|
|
|
yieldSummary, |
|
|
|
yieldSummary: wetlandYieldSummary, |
|
|
|
townAreaRows: wetlandTownAreaRows, |
|
|
|
townAreaRows: wetlandTownAreaRows, |
|
|
|
typeRows: wetlandTypeRows, |
|
|
|
typeRows: wetlandTypeRows, |
|
|
|
levelRows: wetlandLevelRows, |
|
|
|
levelRows: wetlandLevelRows, |
|
|
|
@ -2086,6 +2159,7 @@ export async function getTopicBusinessStats(topicKey, layerKey) { |
|
|
|
const degradationRows = degradationStats.levelRows || [] |
|
|
|
const degradationRows = degradationStats.levelRows || [] |
|
|
|
const core = ensureCoreShape(normalizeBasicGrassland(data), topicKey) |
|
|
|
const core = ensureCoreShape(normalizeBasicGrassland(data), topicKey) |
|
|
|
const grassYieldRows = normalizeYieldRows(yieldRows || [], muYieldRows || [], { showMuYieldExtra: false }) |
|
|
|
const grassYieldRows = normalizeYieldRows(yieldRows || [], muYieldRows || [], { showMuYieldExtra: false }) |
|
|
|
|
|
|
|
const grassYieldSummary = normalizeGrasslandYieldSummary(yieldSummary, grassYieldRows) |
|
|
|
const muYieldRankRows = normalizeRankRows(muYieldRows || [], { |
|
|
|
const muYieldRankRows = normalizeRankRows(muYieldRows || [], { |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
nameKeys: ["areaName", "name"], |
|
|
|
valueKeys: ["yield", "value"], |
|
|
|
valueKeys: ["yield", "value"], |
|
|
|
@ -2122,13 +2196,13 @@ export async function getTopicBusinessStats(topicKey, layerKey) { |
|
|
|
healthRows: normalizedHealthRows, |
|
|
|
healthRows: normalizedHealthRows, |
|
|
|
productivityRows: muYieldRankRows, |
|
|
|
productivityRows: muYieldRankRows, |
|
|
|
edibleYieldRows, |
|
|
|
edibleYieldRows, |
|
|
|
forageRows: buildGrasslandForageCapacityRows(yieldSummary, grassYieldRows), |
|
|
|
forageRows: buildGrasslandForageCapacityRows(grassYieldSummary, grassYieldRows), |
|
|
|
degradationRows, |
|
|
|
degradationRows, |
|
|
|
}) |
|
|
|
}) |
|
|
|
const result = { |
|
|
|
const result = { |
|
|
|
status: "success", |
|
|
|
status: "success", |
|
|
|
...grasslandPanels, |
|
|
|
...grasslandPanels, |
|
|
|
top: buildGrasslandTopRows(core, yieldSummary, grassYieldRows), |
|
|
|
top: buildGrasslandTopRows(core, grassYieldSummary, grassYieldRows), |
|
|
|
} |
|
|
|
} |
|
|
|
return applyLayerPanelSelection(result, topicKey, layerKey) |
|
|
|
return applyLayerPanelSelection(result, topicKey, layerKey) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2212,7 +2286,7 @@ export async function getTopicCoreStats(topicKey) { |
|
|
|
async () => normalizeResponseData(await get("/index/dataItem", { group: "grassLand" })), |
|
|
|
async () => normalizeResponseData(await get("/index/dataItem", { group: "grassLand" })), |
|
|
|
async () => normalizeResponseData(await get("/index/dataItem", { group: "grassland" })), |
|
|
|
async () => normalizeResponseData(await get("/index/dataItem", { group: "grassland" })), |
|
|
|
]) |
|
|
|
]) |
|
|
|
const items = Array.isArray(data) ? normalizeDataItems(data) : normalizeBasicGrassland(data) |
|
|
|
const items = Array.isArray(data) ? normalizeGrasslandDataItems(data) : normalizeBasicGrassland(data) |
|
|
|
return { |
|
|
|
return { |
|
|
|
status: "success", |
|
|
|
status: "success", |
|
|
|
items: ensureCoreShape(items, topicKey), |
|
|
|
items: ensureCoreShape(items, topicKey), |
|
|
|
|