Selaa lähdekoodia

feat:物候期分布页面右侧接口对接

wangsisi 6 päivää sitten
vanhempi
commit
c2ace94af6

+ 10 - 0
src/api/modules/warning.js

@@ -39,5 +39,15 @@ export default {
         url: config.one_map_url + "agri_region_crop/query_area_yield",
         type: "get",
     },
+    //统计指定物种在不同物候期下的面积占比
+    fetchStatPhenologyRatio: {
+        url: config.one_map_url + "agri_land_crop/stat_phenology_ratio",
+        type: "get",
+    },
+    //统计指定物种在下级区划中的预估产量占比
+    fetchStatRegionYieldRatio: {
+        url: config.one_map_url + "agri_land_crop/stat_region_yield_ratio",
+        type: "get",
+    },
 }
 

+ 1 - 23
src/components/fnHeader.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="header">
-        <div class="title" @click="showDatePicker = !showDatePicker">
+        <div class="title">
           <img class="logo" src="@/assets/images/common/logo.png" alt="" />
           <span>{{headerName||"飞鸟智慧巡园平台"}}</span>
           <img class="logo-icon" src="@/assets/images/common/logo-icon.png" alt="" />
@@ -32,15 +32,6 @@
         <div class="page-bg bg-bottom"></div>
         <div class="page-bg bg-left"></div>
     </div>
-    <div v-if="showDatePicker" style="position: absolute;top:50%;left: 50%;width: 50%;height: 200px;">
-      <el-date-picker
-          @change="toggleFarmPicker"
-          v-model="date"
-          type="date"
-          value-format="YYYY-MM-DD"
-          placeholder="Pick a day"
-      />
-    </div>
 </template>
 
 <script setup>
@@ -49,8 +40,6 @@ import { useRouter } from "vue-router";
 import { convertPointToArray } from "@/utils/index";
 import eventBus from "@/api/eventBus";
 
-const date = ref(null);
-const showDatePicker = ref(false);
 const router = useRouter();
 const props = defineProps({
     showDate: {
@@ -83,10 +72,6 @@ const toggleFarm = (val) => {
     eventBus.emit('garden:organId',val)
     router.push({ name: "Home" });
 };
-const toggleFarmPicker = (val) => {
-  localStorage.setItem("date", val);
-  alert("已选择日期:" + localStorage.getItem("date"))
-}
 
 function getCurrentFormattedTime(type) {
     const now = new Date();
@@ -112,13 +97,6 @@ function getCurrentDayOfWeek() {
     return daysOfWeek[dayOfWeek];
 }
 
-function formatTimeToHHmmss(date) {
-    const hours = String(date.getHours()).padStart(2, "0");
-    const minutes = String(date.getMinutes()).padStart(2, "0");
-    const seconds = String(date.getSeconds()).padStart(2, "0");
-
-    return `${hours}.${minutes}.${seconds}`;
-}
 
 const options = ref([]);
 const userInfo = JSON.parse(sessionStorage.getItem("userinfo"));

+ 40 - 5
src/views/warningHome/components/chart_components/barChart.vue

@@ -27,16 +27,52 @@ let myChart = null;
 
 const initData = () => {
     const newOption = deepClone(barOption);
-    
+
     // 如果有传入数据,使用传入的数据
     if (props.chartData && props.chartData.categories && props.chartData.categories.length > 0) {
         newOption.xAxis.data = props.chartData.categories;
         newOption.series[0].data = props.chartData.values;
+
+        // 如果数据项超过 8 个,启用滚动功能
+        const dataLength = props.chartData.categories.length;
+        if (dataLength > 8) {
+            // 调整 grid 的 bottom,为 dataZoom 留出空间
+            newOption.grid.bottom = 20;
+            // 使用滚动时,不需要旋转标签
+            newOption.xAxis.axisLabel.rotate = 0;
+
+            // 添加 dataZoom 配置,实现 x 轴滚动
+            newOption.dataZoom = [
+                {
+                    type: 'slider',
+                    show: true,
+                    xAxisIndex: [0],
+                    start: 0,
+                    end: Math.min(100, (6 / dataLength) * 100), // 初始显示前 6 个或更少
+                    height: 0,
+                    bottom: 10,
+                    showDetail: false,
+                },
+                {
+                    type: 'inside',
+                    xAxisIndex: [0],
+                    start: 0,
+                    end: Math.min(100, (6 / dataLength) * 100),
+                },
+            ];
+        } else {
+            // 数据项较少时,恢复默认的 bottom 值
+            newOption.grid.bottom = 10;
+            // 数据项少时,可以旋转标签以避免重叠
+            newOption.xAxis.axisLabel.rotate = dataLength >= 5 ? 30 : 0;
+            // 移除 dataZoom
+            delete newOption.dataZoom;
+        }
     }
-    
+
     // 更新 yAxis 的 formatter
     newOption.yAxis.axisLabel.formatter = props.yAxisFormatter;
-    
+
     myChart.setOption(newOption);
 };
 
@@ -55,7 +91,6 @@ onMounted(() => {
     myChart = echarts.init(chartDom.value);
     initData();
 });
-
 </script>
 
 <style lang="scss" scoped>
@@ -63,4 +98,4 @@ onMounted(() => {
     width: 100%;
     height: 100%;
 }
-</style>
+</style>

+ 175 - 15
src/views/warningHome/components/chart_components/chartList.vue

@@ -23,7 +23,7 @@
             </chart-box>
         </div>
         <div class="chart-item">
-            <chart-box name="2025年广东省作物区域占比">
+            <chart-box :name="twoTitle">
                 <div class="box-content">
                     <div class="chart-dom">
                         <bar-chart :key="0" :chartData="regionChartData"></bar-chart>
@@ -38,17 +38,15 @@
                     <div class="chart-dom">
                         <line-chart :chartData="areaTrendChartData"></line-chart>
                     </div>
-                    <div class="box-bg">
-                        暂无数据
-                    </div>
+                    <div class="box-bg">暂无数据</div>
                 </div>
             </chart-box>
         </div>
         <div class="chart-item">
-            <chart-box name="2025年广东省作物预估产量对比">
+            <chart-box :name="threeTitle">
                 <div class="box-content">
                     <div class="chart-dom">
-                        <bar-chart :key="1" :chartData="yieldChartData" :yAxisFormatter="'{value}吨'"></bar-chart>
+                        <bar-chart :key="1" :chartData="yieldChartData" :yAxisFormatter="yAxisFormatter"></bar-chart>
                     </div>
                     <div class="box-bg">{{ yieldSummaryText }}</div>
                 </div>
@@ -61,7 +59,7 @@
 import chartBox from "@/components/chartBox.vue";
 import pieChart from "./pieChart.vue";
 import lineChart from "./lineChart.vue";
-import { computed, onMounted, ref } from "vue";
+import { computed, onMounted, ref, watch } from "vue";
 import { pieOption } from "./chartOption.js";
 import barChart from "./barChart.vue";
 
@@ -70,6 +68,10 @@ const props = defineProps({
         type: String,
         default: "作物分布",
     },
+    areaCode: {
+        type: String,
+        default: null,
+    },
 });
 
 // 图表数据
@@ -94,6 +96,11 @@ const yieldChartData = ref({
 // 预估产量摘要文字
 const yieldSummaryText = ref("暂无数据");
 
+// 根据 activeBaseTab 动态设置 y 轴单位
+const yAxisFormatter = computed(() => {
+    return props.activeBaseTab === "物候期分布" ? "{value}亩" : "{value}吨";
+});
+
 // 种植面积趋势图表数据
 const areaTrendChartData = ref({
     xAxisData: [], // 时间轴数据
@@ -116,12 +123,165 @@ const legendData = computed(() => {
     });
 });
 
+const twoTitle = ref("2025年广东省作物区域占比");
+const threeTitle = ref("2025年广东省作物预估产量对比");
+
 onMounted(() => {
     fetchStatSpeciesAreaYield();
     fetchStatRegionAreaRatio();
     fetchAreaTrend();
 });
 
+// 监听 activeBaseTab 变化
+watch(
+    () => props.activeBaseTab,
+    (newVal) => {
+        console.log(newVal);
+        if (newVal === "物候期分布") {
+            twoTitle.value = "2025年广东省小麦物候进程分布";
+            threeTitle.value = "2025年广东省小麦物候进程分布";
+            fetchStatPhenologyRatio();
+            fetchStatRegionYieldRatio();
+        }else{
+            twoTitle.value = "2025年广东省作物区域占比";
+            threeTitle.value = "2025年广东省作物预估产量对比";
+            fetchStatSpeciesAreaYield();
+            fetchStatRegionAreaRatio();
+            fetchAreaTrend();
+        }
+    }
+);
+
+// 监听 areaCode 变化,当切换到物候期分布时重新获取数据
+watch(
+    () => props.areaCode,
+    (newVal) => {
+        if (props.activeBaseTab === "物候期分布" && newVal) {
+            fetchStatPhenologyRatio();
+            fetchStatRegionYieldRatio();
+        }
+    }
+);
+
+//统计指定物种在下级区划中的预估产量占比
+const fetchStatRegionYieldRatio = () => {
+    if (!props.areaCode) {
+        yieldChartData.value = {
+            categories: [],
+            values: [],
+        };
+        yieldSummaryText.value = "暂无数据";
+        return;
+    }
+    
+    const params = {
+        speciesId: 1,
+        adminCode: props.areaCode,
+        adminLevel: "province",
+    };
+    VE_API.warning.fetchStatRegionYieldRatio(params).then((res) => {
+        if (res.code === 0 && res.data && res.data.length > 0) {
+            // 转换接口数据为图表格式
+            const categories = res.data.map((item) => item.adminName);
+            // 如果是物候期分布,使用 expectYield(但单位显示为亩),否则使用 expectYield(单位显示为吨)
+            const values = res.data.map((item) => parseFloat(item.expectYield.toFixed(2)));
+
+            // 更新图表数据
+            yieldChartData.value = {
+                categories,
+                values,
+            };
+
+            // 找到最大值的区域
+            let maxValue = 0;
+            let maxRegion = "";
+            res.data.forEach((item) => {
+                if (item.expectYield > maxValue) {
+                    maxValue = item.expectYield;
+                    maxRegion = item.adminName;
+                }
+            });
+
+            // 更新摘要文字
+            if (maxRegion) {
+                const maxValueFormatted = maxValue.toFixed(1);
+                const unit = props.activeBaseTab === "物候期分布" ? "亩" : "吨";
+                yieldSummaryText.value = `${maxRegion}的${props.activeBaseTab === "物候期分布" ? "种植面积" : "预估产量"}最大,为${maxValueFormatted}${unit}`;
+            } else {
+                yieldSummaryText.value = "暂无数据";
+            }
+        } else {
+            yieldChartData.value = {
+                categories: [],
+                values: [],
+            };
+            yieldSummaryText.value = "暂无数据";
+        }
+    }).catch((error) => {
+        console.error('获取区域产量占比数据失败:', error);
+        yieldChartData.value = {
+            categories: [],
+            values: [],
+        };
+        yieldSummaryText.value = "暂无数据";
+    });
+};
+
+//统计指定物种在不同物候期下的面积占比
+const fetchStatPhenologyRatio = () => {
+    const params = {
+        speciesId: 1,
+        adminCode: props.areaCode,
+        adminLevel: "province",
+    };
+
+    VE_API.warning.fetchStatPhenologyRatio(params).then((res) => {
+        if (res.code === 0 && res.data && res.data.length > 0) {
+            console.log(res.data);
+            // 转换接口数据为图表格式
+            const categories = res.data.map((item) => item.phenologyName);
+            const values = res.data.map((item) => parseFloat((item.areaRatio * 100).toFixed(2))); // 转换为百分比,保留两位小数
+
+            // 更新图表数据
+            regionChartData.value = {
+                categories,
+                values,
+            };
+
+            // 找到最大占比的物候期
+            let maxRatio = 0;
+            let maxPhenology = "";
+            res.data.forEach((item) => {
+                if (item.areaRatio > maxRatio) {
+                    maxRatio = item.areaRatio;
+                    maxPhenology = item.phenologyName;
+                }
+            });
+
+            // 更新摘要文字
+            if (maxPhenology) {
+                const maxPercent = (maxRatio * 100).toFixed(1);
+                regionSummaryText.value = `${maxPhenology}的种植面积最大,占比${maxPercent}%`;
+            } else {
+                regionSummaryText.value = "暂无数据";
+            }
+        } else {
+            regionChartData.value = {
+                categories: [],
+                values: [],
+            };
+            regionSummaryText.value = "暂无数据";
+        }
+    }).catch((error) => {
+        console.error('获取物候期占比数据失败:', error);
+        regionChartData.value = {
+            categories: [],
+            values: [],
+        };
+        regionSummaryText.value = "暂无数据";
+    });
+};
+
 const fetchAreaTrend = () => {
     const params = {
         speciesIds: [1, 222, 60876],
@@ -141,17 +301,17 @@ const fetchAreaTrend = () => {
 
             // 转换为数组并排序
             const xAxisData = Array.from(timePointSet).sort((a, b) => {
-                const [yearA, quarterA] = a.split('Q').map(Number);
-                const [yearB, quarterB] = b.split('Q').map(Number);
+                const [yearA, quarterA] = a.split("Q").map(Number);
+                const [yearB, quarterB] = b.split("Q").map(Number);
                 if (yearA !== yearB) return yearA - yearB;
                 return quarterA - quarterB;
             });
 
             // 定义颜色映射(可以根据需要调整)
             const colorMap = {
-                '荔枝': '#2199F8',
-                '籼稻': '#178B00',
-                '小麦': '#FAA53D',
+                荔枝: "#2199F8",
+                籼稻: "#178B00",
+                小麦: "#FAA53D",
             };
 
             // 为每个作物创建系列数据
@@ -170,15 +330,15 @@ const fetchAreaTrend = () => {
 
                 return {
                     name: species.speciesName,
-                    type: 'line',
+                    type: "line",
                     smooth: true,
                     showSymbol: false,
                     data: data,
                     itemStyle: {
-                        color: colorMap[species.speciesName] || '#2199F8',
+                        color: colorMap[species.speciesName] || "#2199F8",
                     },
                     lineStyle: {
-                        color: colorMap[species.speciesName] || '#2199F8',
+                        color: colorMap[species.speciesName] || "#2199F8",
                     },
                 };
             });

+ 6 - 0
src/views/warningHome/components/chart_components/chartOption.js

@@ -1,6 +1,7 @@
 import * as echarts from "echarts";
 
 const commonxAxis = {
+    axisTick: { show: false },
     axisLabel: { color: '#9F9F9F' },
     axisLine: { lineStyle: { color: 'rgba(185, 185, 185, 0.12)' } },
 }
@@ -79,6 +80,11 @@ export const barOption = {
     xAxis: {
         type: 'category',
         ...commonxAxis,
+        axisLabel: {
+            ...commonxAxis.axisLabel,
+            interval: 0,
+            rotate: 0, // 使用滚动后,不需要旋转标签
+        },
         data: ['从化区', '增城区', '花都区', '番禺区', '南沙区', '从化区', '荔湾区']
     },
     yAxis: {

+ 26 - 9
src/views/warningHome/index.vue

@@ -16,7 +16,7 @@
                             />
                         </div>
                     </div>
-                    <div class="top-r yes-events">
+                    <!-- <div class="top-r yes-events">
                         <div class="data-box" :class="{ active: activeBoxName === '面积' }">
                             <div class="data-value">
                                 <span>{{ regionCropData.plantArea }}</span
@@ -39,7 +39,7 @@
                             </div>
                             <div class="data-name">预估产量</div>
                         </div>
-                    </div>
+                    </div> -->
                 </div>
                 <div class="warning-alarm yes-events" v-show="activeBaseTab === '预警分布'">
                     <alarm-list></alarm-list>
@@ -73,7 +73,7 @@
                 </el-tree>
             </div>
             <div v-if="!showDetail" class="warning-r right chart-wrap yes-events">
-                <chart-list :activeBaseTab="activeBaseTab"></chart-list>
+                <chart-list :activeBaseTab="activeBaseTab" :areaCode="selectedAreaCode"></chart-list>
                 <!-- <farmInfoGroup></farmInfoGroup> -->
             </div>
             <div v-else class="warning-r right yes-events">
@@ -437,11 +437,8 @@ onMounted(async () => {
     eventBus.off("chat:showMapLayer", handleMapLayer);
     eventBus.on("chat:showMapLayer", handleMapLayer);
 
-    // 注意:getRegionCropAreaYield 会在省级列表加载完成后自动调用(在 lazyLoad 中)
-    // 如果 areaVal 已经有值,则立即调用
-    if (areaVal.value && areaVal.value.length > 0) {
-        getRegionCropAreaYield(areaVal.value[areaVal.value.length - 1]);
-    }
+    // 初始化区域选择器的默认值
+    initAreaDefaultValue();
 });
 
 const getRegionCropAreaYield = async (adminCode) => {
@@ -449,6 +446,7 @@ const getRegionCropAreaYield = async (adminCode) => {
     
     const res = await VE_API.warning.fetchRegionCropAreaYield({
         adminCode: code,
+        speciesId: 1,
         year: '',
         quarter: '',
     });
@@ -461,6 +459,23 @@ const getRegionCropAreaYield = async (adminCode) => {
     }
 };
 
+// 初始化区域选择器的默认值
+const initAreaDefaultValue = async () => {
+    try {
+        const res = await VE_API.species.provinceList();
+        if (res.code === 0 && res.data && res.data.length > 0) {
+            // 设置第一个省为默认值
+            const firstProvinceCode = res.data[0].provCode || res.data[0].code;
+            areaVal.value = [firstProvinceCode];
+            selectedAreaCode.value = firstProvinceCode;
+            // 初始化区域作物数据
+            // getRegionCropAreaYield(firstProvinceCode);
+        }
+    } catch (error) {
+        console.error('初始化区域默认值失败:', error);
+    }
+};
+
 sessionStorage.removeItem("farmId");
 
 onUnmounted(() => {
@@ -748,10 +763,12 @@ const props1 = {
     },
 };
 
+const selectedAreaCode = ref(null);
 const toggleArea = (v) => {
     activeBoxName.value = null;
     // 获取选中的最后一个值(即最终的code)
     const selectedCode = v && v.length > 0 ? v[v.length - 1] : null;
+    selectedAreaCode.value = selectedCode;
     if (selectedCode) {
         // 调用接口更新区域作物数据
         getRegionCropAreaYield(selectedCode);
@@ -1173,7 +1190,7 @@ const getTreeChecks = async (nodeData, data) => {
             position: fixed;
             bottom: 20px;
             left: 20px;
-            width: 1080px;
+            width: 950px;
             height: 71px;
         }
     }