|
|
@@ -1,13 +1,10 @@
|
|
|
<template>
|
|
|
<div class="chart-list">
|
|
|
<div class="chart-item">
|
|
|
- <chart-box :name="`四川省斑块占比统计`">
|
|
|
+ <chart-box :name="`平泉街道${selectedCategory.category}占比统计`">
|
|
|
<div class="box-content">
|
|
|
<div class="chart-dom">
|
|
|
- <pie-chart
|
|
|
- :chartData="pieChartData"
|
|
|
- :totalArea="totalArea"
|
|
|
- ></pie-chart>
|
|
|
+ <pie-chart :chartData="pieChartData" :totalArea="totalArea"></pie-chart>
|
|
|
</div>
|
|
|
<div class="box-bg">
|
|
|
<div class="legend-list">
|
|
|
@@ -26,21 +23,15 @@
|
|
|
</chart-box>
|
|
|
</div>
|
|
|
<div class="chart-item">
|
|
|
- <chart-box :name="`四川省物候进程分布`">
|
|
|
+ <chart-box :name="`平泉街道物候进程分布`">
|
|
|
<template #title-right>
|
|
|
<el-select
|
|
|
v-model="selectedPieItem"
|
|
|
- placeholder="全部"
|
|
|
size="small"
|
|
|
style="width: 100px"
|
|
|
- @change="fetchStatPhenologyAreaRatioByCropType"
|
|
|
+ @change="fetchStatPhenologyAreaRatioForGrain"
|
|
|
>
|
|
|
- <el-option
|
|
|
- v-for="item in options"
|
|
|
- :key="item.speciesId"
|
|
|
- :label="item.speciesName"
|
|
|
- :value="item.speciesId"
|
|
|
- />
|
|
|
+ <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
</el-select>
|
|
|
</template>
|
|
|
<div class="box-content">
|
|
|
@@ -52,7 +43,7 @@
|
|
|
</chart-box>
|
|
|
</div>
|
|
|
<div class="chart-item">
|
|
|
- <chart-box name="四川省用地面积统计">
|
|
|
+ <chart-box :name="`平泉街道非农化非量化占比统计`">
|
|
|
<div class="box-content">
|
|
|
<div class="chart-dom">
|
|
|
<bar-chart
|
|
|
@@ -71,9 +62,9 @@
|
|
|
<script setup>
|
|
|
import chartBox from "@/components/chartBox.vue";
|
|
|
import pieChart from "./pieChart.vue";
|
|
|
-import { computed, ref, watch, onMounted } from "vue";
|
|
|
-import { pieOption } from "./chartOption.js";
|
|
|
+import { computed, ref, onMounted, onUnmounted } from "vue";
|
|
|
import barChart from "./barChart.vue";
|
|
|
+import eventBus from "@/api/eventBus";
|
|
|
|
|
|
const props = defineProps({
|
|
|
activeBaseTab: {
|
|
|
@@ -94,6 +85,28 @@ const props = defineProps({
|
|
|
const pieChartData = ref([]);
|
|
|
const totalArea = ref(0);
|
|
|
|
|
|
+// 饼图颜色数组(与 chartOption.js 保持一致)
|
|
|
+const pieColors = ["#2199F8", "#14C9C9", "#FFCC4B", "#8F46F4", "#FF7878", "#9FDB1D"];
|
|
|
+
|
|
|
+// 图例数据(基于饼图数据计算)
|
|
|
+const legendData = computed(() => {
|
|
|
+ if (!pieChartData.value || pieChartData.value.length === 0 || totalArea.value === 0) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ return pieChartData.value.map((item, index) => {
|
|
|
+ const percent = ((item.value / totalArea.value) * 100).toFixed(2);
|
|
|
+ // 从饼图数据中获取颜色(优先使用 itemStyle.color,如果没有则使用默认颜色)
|
|
|
+ const color = item.itemStyle?.color || pieColors[index % pieColors.length];
|
|
|
+ return {
|
|
|
+ color: color,
|
|
|
+ name: item.name,
|
|
|
+ percent: parseFloat(percent),
|
|
|
+ value: Math.round(item.value),
|
|
|
+ };
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
// 物候进程分布标题右侧下拉框选中项(来自饼图数据)
|
|
|
const selectedPieItem = ref(null);
|
|
|
|
|
|
@@ -106,164 +119,146 @@ const regionChartData = ref({
|
|
|
// 区域占比摘要文字
|
|
|
const regionSummaryText = ref("暂无数据");
|
|
|
|
|
|
-// 预估产量图表数据
|
|
|
+// 用地面积统计图表数据
|
|
|
const yieldChartData = ref({
|
|
|
- categories: [], // 作物名称数组
|
|
|
- values: [], // 预估产量数组(单位:吨)
|
|
|
+ categories: [], // 类别名称数组
|
|
|
+ values: [], // 占比百分比数组
|
|
|
});
|
|
|
|
|
|
-// 预估产量摘要文字
|
|
|
+// 用地面积统计摘要文字
|
|
|
const yieldSummaryText = ref("暂无数据");
|
|
|
|
|
|
-// y 轴不显示单位
|
|
|
-const yAxisFormatter = computed(() => {
|
|
|
- return "{value}%";
|
|
|
+onMounted(() => {
|
|
|
+ // 监听图例组件的变化事件
|
|
|
+ eventBus.on("landUseLegend:change", handleLandUseLegendChange);
|
|
|
+ // 初始化时请求用地面积统计数据(statType=1)
|
|
|
+ fetchYieldChartData();
|
|
|
});
|
|
|
|
|
|
-// 计算图例数据
|
|
|
-const legendData = computed(() => {
|
|
|
- if (!pieChartData.value.length || totalArea.value === 0) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- return pieChartData.value.map((item, index) => {
|
|
|
- const percent = ((item.value / totalArea.value) * 100).toFixed(1);
|
|
|
- // 优先使用地图图例接口返回的颜色(与名称对应),没有匹配到再使用默认颜色
|
|
|
- const legendItem = legendArr.value.find((l) => l.name === item.name);
|
|
|
- const color = legendItem && legendItem.color ? legendItem.color : pieOption.color[index % pieOption.color.length];
|
|
|
- return {
|
|
|
- name: item.name,
|
|
|
- value: Math.round(item.value), // 显示整数
|
|
|
- percent: percent,
|
|
|
- color: color,
|
|
|
- };
|
|
|
- });
|
|
|
+onUnmounted(() => {
|
|
|
+ // 移除事件监听
|
|
|
+ eventBus.off("landUseLegend:change", handleLandUseLegendChange);
|
|
|
});
|
|
|
|
|
|
-const legendArr = ref([]);
|
|
|
-const fetchMapLegend = () => {
|
|
|
- VE_API.warning.fetchMapLegend().then((res) => {
|
|
|
- if (res.code === 0 && res.data && res.data.length > 0) {
|
|
|
- legendArr.value = res.data;
|
|
|
- }
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
-const threeTitle = ref(`${props.areaName}作物预估产量对比`);
|
|
|
-
|
|
|
-// 监听 activeBaseTab 变化
|
|
|
-watch(
|
|
|
- () => props.activeBaseTab,
|
|
|
- () => {
|
|
|
- initData();
|
|
|
+// 处理图例组件变化
|
|
|
+const handleLandUseLegendChange = (data) => {
|
|
|
+ if (data.category === "作物类型" || data.nonGrain == null) {
|
|
|
+ options.value = data.children;
|
|
|
+ selectedPieItem.value = data.children[0].id;
|
|
|
}
|
|
|
-);
|
|
|
-
|
|
|
-// 监听 areaCode 变化,当切换到物候期分布时重新获取数据
|
|
|
-watch(
|
|
|
- () => props.areaCode,
|
|
|
- (newVal) => {
|
|
|
- if (newVal) {
|
|
|
- initData();
|
|
|
- }
|
|
|
- }
|
|
|
-);
|
|
|
-
|
|
|
-// 监听 areaName 变化,更新标题
|
|
|
-watch(
|
|
|
- () => props.areaName,
|
|
|
- () => {
|
|
|
- if (props.activeBaseTab === "物候期分布") {
|
|
|
- threeTitle.value = `${props.areaName}小麦预告产量统计`;
|
|
|
- } else if (props.activeBaseTab === "作物分布") {
|
|
|
- threeTitle.value = `${props.areaName}作物预估产量对比`;
|
|
|
- }
|
|
|
- }
|
|
|
-);
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- // 初始化时调用一次
|
|
|
- initData();
|
|
|
-});
|
|
|
-
|
|
|
-const initData = () => {
|
|
|
- fetchStatRegionAreaRatio();
|
|
|
- fetchStatLandTypeAreaRatio();
|
|
|
- fetchStatPhenologyAreaRatioByCropType();
|
|
|
+ // 更新选中的类别信息
|
|
|
+ selectedCategory.value = {
|
|
|
+ category: data.category,
|
|
|
+ nonGrain: data.nonGrain,
|
|
|
+ };
|
|
|
+ // 使用新的 nonGrain 重新获取饼图数据
|
|
|
+ fetchStatRegionAreaRatio(data.nonGrain);
|
|
|
+ fetchStatPhenologyAreaRatioForGrain();
|
|
|
};
|
|
|
|
|
|
const options = ref([]);
|
|
|
+// 当前选中的类别信息
|
|
|
+const selectedCategory = ref({
|
|
|
+ category: null,
|
|
|
+ nonGrain: null,
|
|
|
+});
|
|
|
+
|
|
|
//种植面积占比
|
|
|
-const fetchStatRegionAreaRatio = () => {
|
|
|
+const fetchStatRegionAreaRatio = (nonGrain = null) => {
|
|
|
+ const params = { statType: nonGrain || 0 };
|
|
|
VE_API.warning
|
|
|
- .fetchStatRegionAreaRatio()
|
|
|
+ .fetchStatAreaRatioByType(params)
|
|
|
.then((res) => {
|
|
|
if (res.code === 0 && res.data && res.data.length > 0) {
|
|
|
// 转换接口数据为饼图格式
|
|
|
- // 饼图数据格式:{ value: 种植面积, name: 物种名称 }
|
|
|
- const chartData = res.data.map((item) => ({
|
|
|
- value: item.plantArea, // 种植面积
|
|
|
- name: item.speciesName, // 物种名称
|
|
|
+ // 饼图数据格式:{ value: 种植面积, name: 物种名称, itemStyle: { color: 颜色 } }
|
|
|
+ const chartData = res.data.map((item, index) => ({
|
|
|
+ value: item.plantArea,
|
|
|
+ name: item.name,
|
|
|
+ itemStyle: {
|
|
|
+ color: item.color || pieColors[index % pieColors.length], // 使用接口返回的 color,如果没有则使用默认颜色
|
|
|
+ },
|
|
|
}));
|
|
|
|
|
|
- // 计算总种植面积
|
|
|
- const total = chartData.reduce((sum, item) => sum + item.value, 0);
|
|
|
+ if (chartData.length > 0) {
|
|
|
+ // 计算总种植面积
|
|
|
+ const total = chartData.reduce((sum, item) => sum + (item.value || 0), 0);
|
|
|
|
|
|
- // 更新饼图数据
|
|
|
- pieChartData.value = chartData;
|
|
|
- totalArea.value = total;
|
|
|
- options.value = res.data
|
|
|
- options.value.unshift({ speciesId: null, speciesName: "全部" });
|
|
|
- fetchMapLegend();
|
|
|
+ // 更新饼图数据
|
|
|
+ pieChartData.value = chartData;
|
|
|
+ totalArea.value = total;
|
|
|
+ } else {
|
|
|
+ // 数据过滤后为空
|
|
|
+ pieChartData.value = [];
|
|
|
+ totalArea.value = 0;
|
|
|
+ }
|
|
|
} else {
|
|
|
- // 接口返回空数据时,仅清空饼图数据
|
|
|
+ // 接口返回空数据时,清空饼图数据
|
|
|
pieChartData.value = [];
|
|
|
totalArea.value = 0;
|
|
|
}
|
|
|
})
|
|
|
.catch((error) => {
|
|
|
- console.error("获取区域产量占比数据失败:", error);
|
|
|
- yieldChartData.value = {
|
|
|
- categories: [],
|
|
|
- values: [],
|
|
|
- };
|
|
|
- yieldSummaryText.value = "暂无数据";
|
|
|
+ console.error("获取种植面积占比数据失败:", error);
|
|
|
+ // 错误时清空数据
|
|
|
+ pieChartData.value = [];
|
|
|
+ totalArea.value = 0;
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-//按地块类型统计面积及面积占比
|
|
|
-const fetchStatLandTypeAreaRatio = () => {
|
|
|
+// 获取用地面积统计图表数据(statType=1)
|
|
|
+const fetchYieldChartData = () => {
|
|
|
+ const params = { statType: 1 }; // 固定为 1
|
|
|
VE_API.warning
|
|
|
- .fetchStatLandTypeAreaRatio()
|
|
|
+ .fetchStatAreaRatioByType(params)
|
|
|
.then((res) => {
|
|
|
if (res.code === 0 && res.data && res.data.length > 0) {
|
|
|
- // 转换接口数据为图表格式
|
|
|
- const categories = res.data.map((item) => item.landTypeName);
|
|
|
- const values = res.data.map((item) => parseFloat((item.areaRatio * 100).toFixed(2))); // 转换为百分比,保留两位小数
|
|
|
+ // 计算总种植面积
|
|
|
+ const total = res.data.reduce((sum, item) => sum + (item.plantArea || 0), 0);
|
|
|
+
|
|
|
+ // 转换接口数据为柱状图格式
|
|
|
+ const categories = res.data.map((item) => item.name);
|
|
|
+ const values = res.data.map((item) => {
|
|
|
+ // 计算百分比
|
|
|
+ const percent = total > 0 ? ((item.plantArea / total) * 100).toFixed(2) : 0;
|
|
|
+ return parseFloat(percent);
|
|
|
+ });
|
|
|
|
|
|
- // 更新图表数据到 yieldChartData
|
|
|
+ // 更新图表数据
|
|
|
yieldChartData.value = {
|
|
|
categories,
|
|
|
values,
|
|
|
};
|
|
|
|
|
|
- // 找到最大占比的物候期
|
|
|
- let maxRatio = 0;
|
|
|
- let maxPhenology = "";
|
|
|
+ // 找到最大和最小占比的项
|
|
|
+ let maxValue = 0;
|
|
|
+ let maxName = "";
|
|
|
+ let minValue = Infinity;
|
|
|
+ let minName = "";
|
|
|
res.data.forEach((item) => {
|
|
|
- if (item.areaRatio > maxRatio) {
|
|
|
- maxRatio = item.areaRatio;
|
|
|
- maxPhenology = item.landTypeName;
|
|
|
+ if (item.plantArea > maxValue) {
|
|
|
+ maxValue = item.plantArea;
|
|
|
+ maxName = item.name;
|
|
|
+ }
|
|
|
+ if (item.plantArea < minValue) {
|
|
|
+ minValue = item.plantArea;
|
|
|
+ minName = item.name;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 更新摘要文字
|
|
|
- if (maxPhenology) {
|
|
|
- const maxPercent = (maxRatio * 100).toFixed(1);
|
|
|
- yieldSummaryText.value = `${maxPhenology}的种植面积最大,占比${maxPercent}%`;
|
|
|
+ if (maxName && minName && total > 0) {
|
|
|
+ const maxPercent = ((maxValue / total) * 100).toFixed(1);
|
|
|
+ const minPercent = ((minValue / total) * 100).toFixed(1);
|
|
|
+ yieldSummaryText.value = `${maxName}的种植面积最大,占比${maxPercent}%;${minName}的种植面积最小,占比${minPercent}%`;
|
|
|
+ } else if (maxName && total > 0) {
|
|
|
+ const maxPercent = ((maxValue / total) * 100).toFixed(1);
|
|
|
+ yieldSummaryText.value = `${maxName}的种植面积最大,占比${maxPercent}%`;
|
|
|
} else {
|
|
|
yieldSummaryText.value = "暂无数据";
|
|
|
}
|
|
|
} else {
|
|
|
+ // 接口返回空数据时,清空图表数据
|
|
|
yieldChartData.value = {
|
|
|
categories: [],
|
|
|
values: [],
|
|
|
@@ -272,7 +267,8 @@ const fetchStatLandTypeAreaRatio = () => {
|
|
|
}
|
|
|
})
|
|
|
.catch((error) => {
|
|
|
- console.error("获取地块类型面积占比数据失败:", error);
|
|
|
+ console.error("获取用地面积统计数据失败:", error);
|
|
|
+ // 错误时清空数据
|
|
|
yieldChartData.value = {
|
|
|
categories: [],
|
|
|
values: [],
|
|
|
@@ -281,9 +277,9 @@ const fetchStatLandTypeAreaRatio = () => {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-const fetchStatPhenologyAreaRatioByCropType = () => {
|
|
|
+const fetchStatPhenologyAreaRatioForGrain = () => {
|
|
|
VE_API.warning
|
|
|
- .fetchStatPhenologyAreaRatioByCropType({ cropTypeId: selectedPieItem.value })
|
|
|
+ .fetchStatPhenologyAreaRatioForGrain({ speciesId: selectedPieItem.value })
|
|
|
.then((res) => {
|
|
|
if (res.code === 0 && res.data && res.data.length > 0) {
|
|
|
// 转换接口数据为图表格式(物候进程分布)
|
|
|
@@ -302,17 +298,19 @@ const fetchStatPhenologyAreaRatioByCropType = () => {
|
|
|
// 找到最大占比的物候期
|
|
|
let maxRatio = 0;
|
|
|
let maxPhenology = "";
|
|
|
+ let maxPhenologyName = "";
|
|
|
res.data.forEach((item) => {
|
|
|
if (item.areaRatio > maxRatio) {
|
|
|
maxRatio = item.areaRatio;
|
|
|
maxPhenology = item.speciesName;
|
|
|
+ maxPhenologyName = item.phenologyName;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 更新摘要文字
|
|
|
if (maxPhenology) {
|
|
|
const maxPercent = (maxRatio * 100).toFixed(1);
|
|
|
- regionSummaryText.value = `${maxPhenology}的种植面积最大,占比${maxPercent}%`;
|
|
|
+ regionSummaryText.value = `${maxPhenology}的种植面积最大,占比${maxPercent}%,进入${maxPhenologyName}`;
|
|
|
} else {
|
|
|
regionSummaryText.value = "暂无数据";
|
|
|
}
|