| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- <template>
- <div class="chart-list">
- <div class="chart-item">
- <chart-box :name="`平泉街道${selectedCategory.category}占比统计`">
- <div class="box-content">
- <div class="chart-dom">
- <pie-chart :chartData="pieChartData" :totalArea="totalArea"></pie-chart>
- </div>
- <div class="box-bg">
- <div class="legend-list">
- <div class="legend-item" v-for="(item, index) in legendData" :key="index">
- <span class="dot" :style="{ background: item.color }"></span>
- <span class="text">
- {{ item.name }}
- <span class="percent">{{ item.percent }}%</span>
- <span class="line">|</span>
- <span class="value">{{ item.value }}亩</span>
- </span>
- </div>
- </div>
- </div>
- </div>
- </chart-box>
- </div>
- <div class="chart-item">
- <chart-box :name="`平泉街道物候进程分布`">
- <template #title-right>
- <el-select
- v-model="selectedPieItem"
- size="small"
- style="width: 100px"
- @change="fetchStatPhenologyAreaRatioForGrain"
- >
- <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
- </el-select>
- </template>
- <div class="box-content">
- <div class="chart-dom">
- <bar-chart :key="`region-${activeBaseTab}`" :chartData="regionChartData"></bar-chart>
- </div>
- <div class="box-bg">{{ regionSummaryText }}</div>
- </div>
- </chart-box>
- </div>
- <div class="chart-item">
- <chart-box :name="`平泉街道非农化非量化占比统计`">
- <div class="box-content">
- <div class="chart-dom">
- <bar-chart
- :key="`yield-${activeBaseTab}`"
- :chartData="yieldChartData"
- :yAxisFormatter="yAxisFormatter"
- ></bar-chart>
- </div>
- <div class="box-bg">{{ yieldSummaryText }}</div>
- </div>
- </chart-box>
- </div>
- </div>
- </template>
- <script setup>
- import chartBox from "@/components/chartBox.vue";
- import pieChart from "./pieChart.vue";
- import { computed, ref, onMounted, onUnmounted } from "vue";
- import barChart from "./barChart.vue";
- import eventBus from "@/api/eventBus";
- const props = defineProps({
- activeBaseTab: {
- type: String,
- default: "作物分布",
- },
- areaCode: {
- type: String,
- default: "156440000",
- },
- areaName: {
- type: String,
- default: "广东省",
- },
- });
- // 图表数据
- 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);
- // 区域占比图表数据
- const regionChartData = ref({
- categories: [], // 区域名称数组
- values: [], // 占比百分比数组
- });
- // 区域占比摘要文字
- const regionSummaryText = ref("暂无数据");
- // 用地面积统计图表数据
- const yieldChartData = ref({
- categories: [], // 类别名称数组
- values: [], // 占比百分比数组
- });
- // 用地面积统计摘要文字
- const yieldSummaryText = ref("暂无数据");
- onMounted(() => {
- // 监听图例组件的变化事件
- eventBus.on("landUseLegend:change", handleLandUseLegendChange);
- // 初始化时请求用地面积统计数据(statType=1)
- fetchYieldChartData();
- });
- onUnmounted(() => {
- // 移除事件监听
- eventBus.off("landUseLegend:change", handleLandUseLegendChange);
- });
- // 处理图例组件变化
- const handleLandUseLegendChange = (data) => {
- if (data.category === "作物类型" || data.nonGrain == null) {
- options.value = data.children;
- selectedPieItem.value = data.children[0].id;
- }
- // 更新选中的类别信息
- 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 = (nonGrain = null) => {
- const params = { statType: nonGrain || 0 };
- VE_API.warning
- .fetchStatAreaRatioByType(params)
- .then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- // 转换接口数据为饼图格式
- // 饼图数据格式:{ 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,如果没有则使用默认颜色
- },
- }));
- if (chartData.length > 0) {
- // 计算总种植面积
- const total = chartData.reduce((sum, item) => sum + (item.value || 0), 0);
- // 更新饼图数据
- pieChartData.value = chartData;
- totalArea.value = total;
- } else {
- // 数据过滤后为空
- pieChartData.value = [];
- totalArea.value = 0;
- }
- } else {
- // 接口返回空数据时,清空饼图数据
- pieChartData.value = [];
- totalArea.value = 0;
- }
- })
- .catch((error) => {
- console.error("获取种植面积占比数据失败:", error);
- // 错误时清空数据
- pieChartData.value = [];
- totalArea.value = 0;
- });
- };
- // 获取用地面积统计图表数据(statType=1)
- const fetchYieldChartData = () => {
- const params = { statType: 1 }; // 固定为 1
- VE_API.warning
- .fetchStatAreaRatioByType(params)
- .then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- // 计算总种植面积
- 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.value = {
- categories,
- values,
- };
- // 找到最大和最小占比的项
- let maxValue = 0;
- let maxName = "";
- let minValue = Infinity;
- let minName = "";
- res.data.forEach((item) => {
- if (item.plantArea > maxValue) {
- maxValue = item.plantArea;
- maxName = item.name;
- }
- if (item.plantArea < minValue) {
- minValue = item.plantArea;
- minName = item.name;
- }
- });
- // 更新摘要文字
- 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: [],
- };
- yieldSummaryText.value = "暂无数据";
- }
- })
- .catch((error) => {
- console.error("获取用地面积统计数据失败:", error);
- // 错误时清空数据
- yieldChartData.value = {
- categories: [],
- values: [],
- };
- yieldSummaryText.value = "暂无数据";
- });
- };
- const fetchStatPhenologyAreaRatioForGrain = () => {
- VE_API.warning
- .fetchStatPhenologyAreaRatioForGrain({ speciesId: selectedPieItem.value })
- .then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- // 转换接口数据为图表格式(物候进程分布)
- // 横轴:作物名称(有物候期则为“作物名(物候期)”),纵轴:面积占比(百分比)
- const categories = res.data.map((item) =>
- item.phenologyName ? `${item.speciesName}(${item.phenologyName})` : item.speciesName
- );
- const values = res.data.map((item) => parseFloat((item.areaRatio * 100).toFixed(2)));
- // 更新区域图表数据
- regionChartData.value = {
- categories,
- values,
- };
- // 找到最大占比的物候期
- 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}%,进入${maxPhenologyName}`;
- } else {
- regionSummaryText.value = "暂无数据";
- }
- } else {
- // 接口返回空数据时,清空区域图表数据
- regionChartData.value = {
- categories: [],
- values: [],
- };
- regionSummaryText.value = "暂无数据";
- }
- })
- .catch(() => {
- // 错误时也清空数据
- regionChartData.value = {
- categories: [],
- values: [],
- };
- regionSummaryText.value = "暂无数据";
- });
- };
- </script>
- <style lang="scss" scoped>
- .chart-list {
- width: 100%;
- height: 100%;
- .chart-item {
- width: 100%;
- height: 285px;
- box-sizing: border-box;
- margin-bottom: 10px;
- background: rgba(35, 35, 35, 1);
- border: 1px solid #444444;
- border-radius: 4px;
- .box-content {
- width: 100%;
- height: 100%;
- }
- .chart-dom {
- height: calc(100% - 61px);
- width: 100%;
- }
- .box-bg {
- border-radius: 2px 2px 0 0;
- font-size: 12px;
- padding: 6px 8px;
- box-sizing: border-box;
- height: 61px;
- overflow-y: auto;
- background: linear-gradient(180deg, rgb(85, 85, 85, 0.4) 0%, rgb(35, 35, 35, 1) 100%);
- .legend-list {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 8px 12px;
- height: 100%;
- font-size: 12px;
- .legend-item {
- display: flex;
- align-items: center;
- gap: 6px;
- line-height: 12px;
- .dot {
- width: 5px;
- height: 5px;
- border-radius: 50%;
- flex-shrink: 0;
- }
- .text {
- color: rgba(255, 255, 255, 1);
- font-size: 12px;
- white-space: nowrap;
- .percent {
- padding: 0 10px;
- }
- .line {
- color: rgba(255, 255, 255, 0.2);
- padding-right: 10px;
- }
- }
- }
- }
- }
- }
- }
- </style>
|