Kaynağa Gözat

feat:物候期分布接口对接和添加农场列表

wangsisi 6 gün önce
ebeveyn
işleme
dac5609c62

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

@@ -49,5 +49,10 @@ export default {
         url: config.one_map_url + "agri_land_crop/stat_region_yield_ratio",
         type: "get",
     },
+    //获取农场列表
+    fetchFarmList: {
+        url: config.one_map_url + "agri_farm_crop/list",
+        type: "post",
+    },
 }
 

+ 46 - 8
src/components/chartBox.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="chart-box" :class="color">
-    <div class="chart-title" v-if="name">
+    <div class="chart-title" v-if="name" ref="titleRef">
       <div class="name">
         <img :src="`/src/assets/images/common/chart-${color || 'icon'}.png`" alt="" />
         <span>{{name}}</span>
@@ -11,7 +11,7 @@
       </div>
     </div>
     <slot v-else name="title-name"></slot>
-    <div class="chart-content">
+    <div class="chart-content" :style="{ height: contentHeight }">
         <div v-show="arrow" :class="['arrow',arrow]" @click="handleShrink">
             <el-icon class="icon" color="#141414"><DArrowLeft /></el-icon>
         </div>
@@ -21,7 +21,7 @@
 </template>
 
 <script setup>
-import {ref} from 'vue'
+import {ref, onMounted, onBeforeUnmount, nextTick, watch} from 'vue'
 const props = defineProps({
     name:{
         type:String,
@@ -37,10 +37,50 @@ const props = defineProps({
     }
 })
 
-const isShrink = ref(true)
+const titleRef = ref(null)
+const contentHeight = ref('calc(100% - 38px)')
+let resizeObserver = null
+
+const updateContentHeight = () => {
+    nextTick(() => {
+        if (titleRef.value) {
+            const titleHeight = titleRef.value.offsetHeight
+            contentHeight.value = `calc(100% - ${titleHeight}px)`
+        } else {
+            // 如果没有标题,内容占满整个高度
+            contentHeight.value = '100%'
+        }
+    })
+}
+
 const handleShrink = () =>{
 
 }
+
+onMounted(() => {
+    updateContentHeight()
+    
+    // 使用 ResizeObserver 监听头部高度变化
+    if (titleRef.value && window.ResizeObserver) {
+        resizeObserver = new ResizeObserver(() => {
+            updateContentHeight()
+        })
+        resizeObserver.observe(titleRef.value)
+    }
+})
+
+onBeforeUnmount(() => {
+    // 清理 ResizeObserver
+    if (resizeObserver) {
+        resizeObserver.disconnect()
+        resizeObserver = null
+    }
+})
+
+// 监听 name 变化,重新计算高度
+watch(() => props.name, () => {
+    updateContentHeight()
+})
 </script>
 
 <style lang="scss" scoped>
@@ -54,7 +94,7 @@ const handleShrink = () =>{
 
   .chart-title {
     width: 100%;
-    height: 38px;
+    min-height: 38px;
     display: flex;
     align-items: center;
     justify-content: space-between;
@@ -77,7 +117,6 @@ const handleShrink = () =>{
   .chart-content{
     position: relative;
     width: 100%;
-    height: calc(100% - 38px);
     padding: 4px 8px;
     box-sizing: border-box;
     .arrow{
@@ -106,7 +145,7 @@ const handleShrink = () =>{
     border-radius: 8px;
     background: #191919;
     .chart-title{
-      height: 59px;
+      min-height: 59px;
       .name{
         color: #FFD489;
         span{
@@ -116,7 +155,6 @@ const handleShrink = () =>{
     }
     .chart-content{
       padding: 0;
-      height: calc(100% - 59px);
     }
   }
 }

+ 9 - 0
src/views/warningHome/components/chart_components/barChart.vue

@@ -68,6 +68,15 @@ const initData = () => {
             // 移除 dataZoom
             delete newOption.dataZoom;
         }
+    } else {
+        // 数据为空时,清空图表
+        newOption.xAxis.data = [];
+        newOption.series[0].data = [];
+        // 恢复默认配置
+        newOption.grid.bottom = 10;
+        newOption.xAxis.axisLabel.rotate = 0;
+        // 移除 dataZoom
+        delete newOption.dataZoom;
     }
 
     // 更新 yAxis 的 formatter

+ 152 - 110
src/views/warningHome/components/chart_components/chartList.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="chart-list">
         <div class="chart-item">
-            <chart-box name="2025年广东省作物种植面积占比">
+            <chart-box :name="`${props.areaName}作物种植面积占比`">
                 <div class="box-content">
                     <div class="chart-dom">
                         <pie-chart :chartData="pieChartData" :totalArea="totalArea"></pie-chart>
@@ -70,7 +70,11 @@ const props = defineProps({
     },
     areaCode: {
         type: String,
-        default: null,
+        default: "156440000",
+    },
+    areaName: {
+        type: String,
+        default: "广东省",
     },
 });
 
@@ -123,32 +127,14 @@ const legendData = computed(() => {
     });
 });
 
-const twoTitle = ref("2025年广东省作物区域占比");
-const threeTitle = ref("2025年广东省作物预估产量对比");
-
-onMounted(() => {
-    fetchStatSpeciesAreaYield();
-    fetchStatRegionAreaRatio();
-    fetchAreaTrend();
-});
+const twoTitle = ref(`${props.areaName}作物区域占比`);
+const threeTitle = ref(`${props.areaName}作物预估产量对比`);
 
 // 监听 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();
-        }
+    () => {
+        initData();
     }
 );
 
@@ -156,75 +142,85 @@ watch(
 watch(
     () => props.areaCode,
     (newVal) => {
-        if (props.activeBaseTab === "物候期分布" && newVal) {
-            fetchStatPhenologyRatio();
-            fetchStatRegionYieldRatio();
+        if (newVal) {
+            initData();
         }
     }
 );
 
+const initData = () => {
+    if (props.activeBaseTab === "物候期分布") {
+        twoTitle.value = `${props.areaName}小麦物候进程分布`;
+        threeTitle.value = `${props.areaName}小麦预告产量统计`;
+        fetchStatPhenologyRatio();
+        fetchStatRegionYieldRatio();
+    } else {
+        twoTitle.value = `${props.areaName}作物区域占比`;
+        threeTitle.value = `${props.areaName}作物预估产量对比`;
+        fetchStatSpeciesAreaYield();
+        fetchStatRegionAreaRatio();
+        fetchAreaTrend();
+    }
+};
+
 //统计指定物种在下级区划中的预估产量占比
 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)));
+    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,
+                };
 
-            // 更新图表数据
-            yieldChartData.value = {
-                categories,
-                values,
-            };
+                // 找到最大值的区域
+                let maxValue = 0;
+                let maxRegion = "";
+                res.data.forEach((item) => {
+                    if (item.expectYield > maxValue) {
+                        maxValue = item.expectYield;
+                        maxRegion = item.adminName;
+                    }
+                });
 
-            // 找到最大值的区域
-            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 = "暂无数据";
                 }
-            });
-
-            // 更新摘要文字
-            if (maxRegion) {
-                const maxValueFormatted = maxValue.toFixed(1);
-                const unit = props.activeBaseTab === "物候期分布" ? "亩" : "吨";
-                yieldSummaryText.value = `${maxRegion}的${props.activeBaseTab === "物候期分布" ? "种植面积" : "预估产量"}最大,为${maxValueFormatted}${unit}`;
             } else {
+                yieldChartData.value = {
+                    categories: [],
+                    values: [],
+                };
                 yieldSummaryText.value = "暂无数据";
             }
-        } else {
+        })
+        .catch((error) => {
+            console.error("获取区域产量占比数据失败:", error);
             yieldChartData.value = {
                 categories: [],
                 values: [],
             };
             yieldSummaryText.value = "暂无数据";
-        }
-    }).catch((error) => {
-        console.error('获取区域产量占比数据失败:', error);
-        yieldChartData.value = {
-            categories: [],
-            values: [],
-        };
-        yieldSummaryText.value = "暂无数据";
-    });
+        });
 };
 
 //统计指定物种在不同物候期下的面积占比
@@ -235,57 +231,60 @@ const fetchStatPhenologyRatio = () => {
         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))); // 转换为百分比,保留两位小数
+    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,
+                };
 
-            // 更新图表数据
-            regionChartData.value = {
-                categories,
-                values,
-            };
+                // 找到最大占比的物候期
+                let maxRatio = 0;
+                let maxPhenology = "";
+                res.data.forEach((item) => {
+                    if (item.areaRatio > maxRatio) {
+                        maxRatio = item.areaRatio;
+                        maxPhenology = item.phenologyName;
+                    }
+                });
 
-            // 找到最大占比的物候期
-            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 = "暂无数据";
                 }
-            });
-
-            // 更新摘要文字
-            if (maxPhenology) {
-                const maxPercent = (maxRatio * 100).toFixed(1);
-                regionSummaryText.value = `${maxPhenology}的种植面积最大,占比${maxPercent}%`;
             } else {
+                regionChartData.value = {
+                    categories: [],
+                    values: [],
+                };
                 regionSummaryText.value = "暂无数据";
             }
-        } else {
+        })
+        .catch((error) => {
+            console.error("获取物候期占比数据失败:", error);
             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],
-        adminCode: "156440000",
+        adminCode: props.areaCode,
         adminLevel: "province",
     };
     VE_API.warning.fetchAreaTrend(params).then((res) => {
@@ -348,15 +347,28 @@ const fetchAreaTrend = () => {
                 xAxisData,
                 series,
             };
+        } else {
+            console.log("空数据");
+            // 接口返回空数据时,清空图表数据
+            areaTrendChartData.value = {
+                xAxisData: [],
+                series: [],
+            };
         }
+    }).catch(() => {
+        // 错误时也清空数据
+        areaTrendChartData.value = {
+            xAxisData: [],
+            series: [],
+        };
     });
 };
 
 const fetchStatRegionAreaRatio = () => {
     const params = {
-        speciesId: 222,
-        adminCode: 156441400,
-        adminLevel: "city",
+        speciesId: "1",
+        adminCode: props.areaCode,
+        adminLevel: "",
     };
     VE_API.warning.fetchStatRegionAreaRatio(params).then((res) => {
         if (res.code === 0 && res.data && res.data.length > 0) {
@@ -388,15 +400,28 @@ const fetchStatRegionAreaRatio = () => {
                 regionSummaryText.value = "暂无数据";
             }
         } else {
+            // 接口返回空数据时,清空图表数据
+            regionChartData.value = {
+                categories: [],
+                values: [],
+            };
             regionSummaryText.value = "暂无数据";
         }
+    }).catch((error) => {
+        console.error("获取区域面积占比数据失败:", error);
+        // 错误时也清空数据
+        regionChartData.value = {
+            categories: [],
+            values: [],
+        };
+        regionSummaryText.value = "暂无数据";
     });
 };
 
 const fetchStatSpeciesAreaYield = () => {
     const params = {
         year: 2025,
-        adminCode: null,
+        adminCode: props.areaCode,
         adminLevel: null,
     };
     VE_API.warning.fetchStatSpeciesAreaYield(params).then((res) => {
@@ -444,8 +469,25 @@ const fetchStatSpeciesAreaYield = () => {
                 yieldSummaryText.value = "暂无数据";
             }
         } else {
+            // 接口返回空数据时,清空图表数据
+            pieChartData.value = [];
+            totalArea.value = 0;
+            yieldChartData.value = {
+                categories: [],
+                values: [],
+            };
             yieldSummaryText.value = "暂无数据";
         }
+    }).catch((error) => {
+        console.error("获取作物面积产量数据失败:", error);
+        // 错误时也清空数据
+        pieChartData.value = [];
+        totalArea.value = 0;
+        yieldChartData.value = {
+            categories: [],
+            values: [],
+        };
+        yieldSummaryText.value = "暂无数据";
     });
 };
 </script>

+ 4 - 0
src/views/warningHome/components/chart_components/lineChart.vue

@@ -28,6 +28,10 @@ const initData = () => {
     if (props.chartData && props.chartData.xAxisData && props.chartData.xAxisData.length > 0) {
         newOption.xAxis.data = props.chartData.xAxisData;
         newOption.series = props.chartData.series;
+    } else {
+        // 数据为空时,清空图表
+        newOption.xAxis.data = [];
+        newOption.series = [];
     }
     
     myChart.setOption(newOption);

+ 11 - 0
src/views/warningHome/components/chart_components/pieChart.vue

@@ -39,6 +39,17 @@ const initData = () => {
                 return `${params.marker}${data.name}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${percent}%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${Math.round(data.value)}亩`;
             };
         }
+    } else {
+        // 数据为空时,清空图表
+        newOption.series[0].data = [];
+        newOption.title.subtext = '0';
+        // 恢复默认 tooltip
+        newOption.tooltip.formatter = function (params) {
+            const data = params.data;
+            const total = 3774;
+            const percent = (data.value / total * 100).toFixed(2);
+            return `${params.marker}${data.name}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${percent}%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${data.value}亩`;
+        };
     }
     
     myChart.setOption(newOption);

+ 108 - 77
src/views/warningHome/components/farmInfoGroup.vue

@@ -2,24 +2,23 @@
     <div class="farm-info-group">
         <!-- 顶部标题栏 -->
         <div class="info-header">
-            <div class="back-btn" @click="handleBack">返回</div>
+            <div class="back-btn" v-if="!farmList.length" @click="handleBack">返回</div>
             <div class="title">
                 <img class="title-icon" src="@/assets/images/common/chart-icon.png" alt="" />
-                <span class="title-text">荔博园</span>
+                <span class="title-text">{{ farmList.length ? "农场列表" : "荔博园" }}</span>
             </div>
         </div>
 
         <!-- 主要内容区域 -->
-        <div class="info-content">
-            <div class="farm-info">
+        <div class="info-content" :style="{ height: !farmList.length ? 'calc(100% - 168px)' : 'calc(100% - 50px)' }">
+            <div class="farm-info" v-for="item in farmList" :key="item" @click="handleFarmInfo(item)">
                 <div class="lz-icon">
                     <img src="@/assets/images/warningHome/lz-icon.png" alt="" />
                 </div>
                 <!-- 右侧信息区域 -->
                 <div class="info-right">
                     <div class="info-item farm-code">
-                        <span class="info-label">农场编号:</span>
-                        <span class="info-value">GZ86770</span>
+                        <span class="info-label">{{ !farmList.length ? '农场编号:GZ86770' : item.name }}</span>
                         <div class="tags">
                             <span class="tag">荔枝</span>
                             <span class="tag">井岗红糯</span>
@@ -39,61 +38,75 @@
                     </div>
                 </div>
             </div>
-            <div class="tabs">
-                <div
-                    v-for="tab in tabs"
-                    :key="tab.key"
-                    class="tab-item"
-                    :class="{ active: activeTab === tab.key }"
-                    @click="activeTab = tab.key"
-                >
-                    {{ tab.label }}
-                </div>
-            </div>
-            <div class="tab-content">
-                <div class="timeline" v-if="activeTab === 'crop'">
+            <template v-if="!farmList.length">
+                <div class="tabs">
                     <div
-                        class="timeline-item"
-                        v-for="item in timelineList"
-                        :key="item.id"
+                        v-for="tab in tabs"
+                        :key="tab.key"
+                        class="tab-item"
+                        :class="{ active: activeTab === tab.key }"
+                        @click="activeTab = tab.key"
                     >
-                        <div class="timeline-left">
-                            <div class="dot"></div>
-                            <div class="line"></div>
-                        </div>
-                        <div class="timeline-right">
-                            <div class="date">{{ item.date }}</div>
-                            <div class="text">{{ item.text }}</div>
-                        </div>
+                        {{ tab.label }}
                     </div>
                 </div>
-                <div v-else class="perception-content">
-                    <div class="perception-tabs">
-                        <div
-                            v-for="tab in perceptionTabs"
-                            :key="tab.key"
-                            class="perception-tab"
-                            :class="{ 'perception-tab--active': perceptionActive === tab.key }"
-                            @click="perceptionActive = tab.key"
-                        >
-                            <span class="label">{{ tab.label }}</span>
-                            <div class="underline"></div>
+                <div class="tab-content">
+                    <div class="timeline" v-if="activeTab === 'crop'">
+                        <div class="timeline-item" v-for="item in timelineList" :key="item.id">
+                            <div class="timeline-left">
+                                <div class="dot"></div>
+                                <div class="line"></div>
+                            </div>
+                            <div class="timeline-right">
+                                <div class="date">{{ item.date }}</div>
+                                <div class="text">{{ item.text }}</div>
+                            </div>
                         </div>
                     </div>
-                    <div class="perception-wrap">
-                        <equipment v-if="perceptionActive === 'device'"></equipment>
-                        <crop v-else></crop>
+                    <div v-else class="perception-content">
+                        <div class="perception-tabs">
+                            <div
+                                v-for="tab in perceptionTabs"
+                                :key="tab.key"
+                                class="perception-tab"
+                                :class="{ 'perception-tab--active': perceptionActive === tab.key }"
+                                @click="perceptionActive = tab.key"
+                            >
+                                <span class="label">{{ tab.label }}</span>
+                                <div class="underline"></div>
+                            </div>
+                        </div>
+                        <div class="perception-wrap">
+                            <equipment v-if="perceptionActive === 'device'"></equipment>
+                            <crop v-else></crop>
+                        </div>
                     </div>
                 </div>
-            </div>
+            </template>
         </div>
     </div>
 </template>
 
 <script setup>
-import { ref } from "vue";
+import { ref ,onMounted} from "vue";
 import equipment from "./equipment.vue";
 import crop from "./crop.vue";
+
+
+onMounted(() => {
+    fetchFarmList();
+});
+
+const fetchFarmList = () => {
+    VE_API.warning.fetchFarmList().then(res => {
+        if (res.code === 0 && res.data && res.data.length > 0) {
+            farmList.value = res.data;
+        } else {
+            farmList.value = [];
+        }
+    });
+};
+
 // 底部 tabs 配置
 const tabs = [
     { key: "crop", label: "作物档案" },
@@ -118,8 +131,15 @@ const timelineList = ref([
     { id: 5, date: "8/1", text: "水稻进入拔节期,水稻进入拔节期" },
 ]);
 
+const farmList = ref([]);
 const handleBack = () => {
-    // 返回逻辑
+    farmList.value = [
+        { id: 1, name: "荔博园", area: "58亩", position: "广东省广州市***", owner: "张扬" },
+        { id: 2, name: "荔博园", area: "58亩", position: "广东省广州市***", owner: "张扬" },
+        { id: 3, name: "荔博园", area: "58亩", position: "广东省广州市***", owner: "张扬" },
+        { id: 4, name: "荔博园", area: "58亩", position: "广东省广州市***", owner: "张扬" },
+        { id: 5, name: "荔博园", area: "58亩", position: "广东省广州市***", owner: "张扬" },
+    ];
 };
 
 const handleCropArchive = () => {
@@ -129,6 +149,10 @@ const handleCropArchive = () => {
 const handlePerceptionRecord = () => {
     // 感知记录逻辑
 };
+
+const handleFarmInfo = (item) => {
+    farmList.value = [item];
+};
 </script>
 <style lang="scss" scoped>
 .farm-info-group {
@@ -165,9 +189,15 @@ const handlePerceptionRecord = () => {
             }
         }
     }
+
     .info-content {
         padding: 5px 10px;
         height: calc(100% - 168px);
+        overflow-y: auto;
+
+        .farm-info + .farm-info {
+            margin-top: 12px;
+        }
         .farm-info {
             display: flex;
             align-items: flex-start;
@@ -187,8 +217,9 @@ const handlePerceptionRecord = () => {
                 .info-item {
                     display: flex;
                     align-items: center;
-                    gap: 8px;
                     line-height: 18px;
+                    gap: 6px;
+                    cursor: pointer;
                     &.farm-code {
                         font-weight: 700;
                         font-size: 16px;
@@ -202,9 +233,9 @@ const handlePerceptionRecord = () => {
 
                         .tag {
                             padding: 1px 6px;
-                            border: 1px solid #FFD489;
+                            border: 1px solid #ffd489;
                             border-radius: 2px;
-                            color: #FFD489;
+                            color: #ffd489;
                             font-size: 12px;
                             font-weight: 400;
                         }
@@ -216,7 +247,7 @@ const handlePerceptionRecord = () => {
             display: flex;
             gap: 10px;
             margin-top: 12px;
-            
+
             .tab-item {
                 padding: 6px 32px;
                 text-align: center;
@@ -225,86 +256,86 @@ const handlePerceptionRecord = () => {
                 color: #ffffff;
                 background: rgba(166, 166, 166, 0.08);
                 border: 1px solid transparent;
-                
+
                 &.active {
-                    color: #FFD489;
+                    color: #ffd489;
                     background: rgba(255, 212, 137, 0.2);
-                    border: 1px solid #FFD489;
+                    border: 1px solid #ffd489;
                 }
             }
         }
-        .tab-content{
+        .tab-content {
             margin: 12px 0;
             height: calc(100% - 24px);
             overflow-y: auto;
-            .timeline{
+            .timeline {
                 padding-right: 12px;
-                .timeline-item{
+                .timeline-item {
                     display: flex;
                     align-items: flex-start;
                     font-size: 14px;
                     color: #ffffff;
                     line-height: 22px;
-                    & + .timeline-item{
+                    & + .timeline-item {
                         margin-top: 24px;
                     }
-                    .timeline-left{
+                    .timeline-left {
                         width: 24px;
                         display: flex;
                         flex-direction: column;
                         align-items: center;
-                        .dot{
+                        .dot {
                             width: 6px;
                             height: 6px;
                             border-radius: 50%;
-                            background: #FFD489;
+                            background: #ffd489;
                             margin-top: 6px;
                         }
-                        .line{
+                        .line {
                             border-left: 1px dashed rgba(255, 212, 137, 0.6);
                             margin-top: 4px;
                             height: 40px;
                         }
                     }
-                    .timeline-right{
+                    .timeline-right {
                         padding-left: 8px;
-                        .date{
-                            color: #FFD489;
+                        .date {
+                            color: #ffd489;
                             font-weight: 500;
                             margin-bottom: 2px;
                         }
-                        .text{
-                            color: #D7D7D7;
+                        .text {
+                            color: #d7d7d7;
                         }
                     }
                 }
             }
-            .perception-content{
+            .perception-content {
                 height: 100%;
-                .perception-tabs{
+                .perception-tabs {
                     display: flex;
                     align-items: flex-end;
                     gap: 20px;
                     margin-bottom: 12px;
-                    .perception-tab{
-                        color: #FFFFFF;
+                    .perception-tab {
+                        color: #ffffff;
                         cursor: pointer;
-                        .underline{
+                        .underline {
                             margin-top: 6px;
                             width: 56px;
                             height: 2px;
                             background: transparent;
                             border-radius: 2px;
                         }
-                        &.perception-tab--active{
-                            color: #FFD489;
-                            .underline{
-                                background: #FFD489;
+                        &.perception-tab--active {
+                            color: #ffd489;
+                            .underline {
+                                background: #ffd489;
                             }
                         }
                     }
                 }
-                .perception-wrap{
+                .perception-wrap {
                     height: calc(100% - 40px);
                     overflow-y: auto;
                 }

+ 5 - 2
src/views/warningHome/components/timeLine.vue

@@ -58,7 +58,7 @@ const isCounting = ref(false);
 
 // 计算进度条百分比位置(根据数据数量动态计算)
 const numList = computed(() => {
-    return [4,16.5,29.5,43.5,56.5,69.5,82.8,95.5];
+    return [4,17,31,45,59,72,86,99];
     // const count = list.value.length;
     // if (count <= 1) return [100];
     // const step = 100 / (count - 1);
@@ -157,7 +157,7 @@ defineExpose({ restActive });
     .line {
         background: linear-gradient(30deg, #fff 0% , rgba(44, 44, 44,0.6) 100%);
         border-radius: 2px;
-        width: 90%;
+        width: 88%;
         height: 2px;
         display: flex;
         justify-content: space-between;
@@ -220,6 +220,9 @@ defineExpose({ restActive });
                 margin-left: -8px;
             }
         }
+        .mr{
+            margin-right: -35px;
+        }
     }
 }
 </style>

+ 64 - 27
src/views/warningHome/index.vue

@@ -7,6 +7,7 @@
                     <div class="top-l yes-events">
                         <div>
                             <el-cascader
+                                ref="cascaderRef"
                                 style="width: 184px"
                                 :show-all-levels="false"
                                 v-model="areaVal"
@@ -16,7 +17,7 @@
                             />
                         </div>
                     </div>
-                    <!-- <div class="top-r yes-events">
+                    <div class="top-r yes-events" v-show="activeBaseTab !== '作物分布'">
                         <div class="data-box" :class="{ active: activeBoxName === '面积' }">
                             <div class="data-value">
                                 <span>{{ regionCropData.plantArea }}</span
@@ -39,7 +40,7 @@
                             </div>
                             <div class="data-name">预估产量</div>
                         </div>
-                    </div> -->
+                    </div>
                 </div>
                 <div class="warning-alarm yes-events" v-show="activeBaseTab === '预警分布'">
                     <alarm-list></alarm-list>
@@ -72,8 +73,8 @@
                     </template>
                 </el-tree>
             </div>
-            <div v-if="!showDetail" class="warning-r right chart-wrap yes-events">
-                <chart-list :activeBaseTab="activeBaseTab" :areaCode="selectedAreaCode"></chart-list>
+            <div v-if="showDetail" class="warning-r right chart-wrap yes-events">
+                <chart-list :activeBaseTab="activeBaseTab" :areaCode="selectedAreaCode" :areaName="selectedAreaName"></chart-list>
                 <!-- <farmInfoGroup></farmInfoGroup> -->
             </div>
             <div v-else class="warning-r right yes-events">
@@ -441,11 +442,10 @@ onMounted(async () => {
     initAreaDefaultValue();
 });
 
-const getRegionCropAreaYield = async (adminCode) => {
-    const code = adminCode || (areaVal.value && areaVal.value.length > 0 ? areaVal.value[areaVal.value.length - 1] : '156440000');
-    
+const getRegionCropAreaYield = async () => {
+    if (activeBaseTab.value === '作物分布') return;
     const res = await VE_API.warning.fetchRegionCropAreaYield({
-        adminCode: code,
+        adminCode: selectedAreaCode.value,
         speciesId: 1,
         year: '',
         quarter: '',
@@ -466,10 +466,12 @@ const initAreaDefaultValue = async () => {
         if (res.code === 0 && res.data && res.data.length > 0) {
             // 设置第一个省为默认值
             const firstProvinceCode = res.data[0].provCode || res.data[0].code;
+            const firstProvinceName = res.data[0].provName || res.data[0].name;
             areaVal.value = [firstProvinceCode];
             selectedAreaCode.value = firstProvinceCode;
-            // 初始化区域作物数据
-            // getRegionCropAreaYield(firstProvinceCode);
+            selectedAreaName.value = firstProvinceName;
+            // 保存到映射中
+            areaCodeNameMap.value.set(firstProvinceCode, firstProvinceName);
         }
     } catch (error) {
         console.error('初始化区域默认值失败:', error);
@@ -592,6 +594,7 @@ const destroyPopup = () => {
 
 const handleTabClick = (item) => {
     activeBaseTab.value = item;
+    getRegionCropAreaYield();
 
     // 切换 Tab 时,先清空农场分布图层上的旧数据
     if (distributionLayer) {
@@ -704,17 +707,25 @@ const props1 = {
             // 第一级:获取省级列表
             VE_API.species.provinceList().then((res) => {
                 if (res.code === 0 && res.data) {
-                    const nodes = res.data.map((item) => ({
-                        value: item.provCode || item.code, // 使用code,不使用id
-                        label: item.provName || item.name,
-                        leaf: false, // 省级不是叶子节点
-                    }));
+                    const nodes = res.data.map((item) => {
+                        const code = item.provCode || item.code;
+                        const name = item.provName || item.name;
+                        // 保存 code 到 name 的映射
+                        areaCodeNameMap.value.set(code, name);
+                        return {
+                            value: code, // 使用code,不使用id
+                            label: name,
+                            leaf: false, // 省级不是叶子节点
+                        };
+                    });
                     if (nodes.length > 0) {
                         // 设置第一个省的code
                         const firstProvinceCode = nodes[0].value;
                         areaVal.value = [firstProvinceCode];
+                        selectedAreaCode.value = firstProvinceCode;
+                        selectedAreaName.value = nodes[0].label;
                         // 使用第一个省的code初始化数据
-                        getRegionCropAreaYield(firstProvinceCode);
+                        getRegionCropAreaYield();
                     }
                     resolve(nodes);
                 } else {
@@ -728,11 +739,17 @@ const props1 = {
             const provCode = node.value;
             VE_API.species.cityList({ provCode }).then((res) => {
                 if (res.code === 0 && res.data) {
-                    const nodes = res.data.map((item) => ({
-                        value: item.cityCode || item.code,
-                        label: item.cityName || item.name,
-                        leaf: false, // 市级不是叶子节点
-                    }));
+                    const nodes = res.data.map((item) => {
+                        const code = item.cityCode || item.code;
+                        const name = item.cityName || item.name;
+                        // 保存 code 到 name 的映射
+                        areaCodeNameMap.value.set(code, name);
+                        return {
+                            value: code,
+                            label: name,
+                            leaf: false, // 市级不是叶子节点
+                        };
+                    });
                     resolve(nodes);
                 } else {
                     resolve([]);
@@ -745,11 +762,17 @@ const props1 = {
             const cityCode = node.value;
             VE_API.species.districtList({ cityCode }).then((res) => {
                 if (res.code === 0 && res.data) {
-                    const nodes = res.data.map((item) => ({
-                        value: item.districtCode || item.code,
-                        label: item.districtName || item.name,
-                        leaf: true, // 区级是叶子节点
-                    }));
+                    const nodes = res.data.map((item) => {
+                        const code = item.districtCode || item.code;
+                        const name = item.districtName || item.name;
+                        // 保存 code 到 name 的映射
+                        areaCodeNameMap.value.set(code, name);
+                        return {
+                            value: code,
+                            label: name,
+                            leaf: true, // 区级是叶子节点
+                        };
+                    });
                     resolve(nodes);
                 } else {
                     resolve([]);
@@ -764,14 +787,28 @@ const props1 = {
 };
 
 const selectedAreaCode = ref(null);
+const selectedAreaName = ref(null);
+const cascaderRef = ref(null);
+
+// 保存 code 到 name 的映射关系
+const areaCodeNameMap = ref(new Map());
+
 const toggleArea = (v) => {
     activeBoxName.value = null;
     // 获取选中的最后一个值(即最终的code)
     const selectedCode = v && v.length > 0 ? v[v.length - 1] : null;
     selectedAreaCode.value = selectedCode;
+    
+    // 从映射中获取对应的 name
+    if (selectedCode && areaCodeNameMap.value.has(selectedCode)) {
+        selectedAreaName.value = areaCodeNameMap.value.get(selectedCode);
+    } else {
+        selectedAreaName.value = null;
+    }
+    
     if (selectedCode) {
         // 调用接口更新区域作物数据
-        getRegionCropAreaYield(selectedCode);
+        getRegionCropAreaYield();
     }
 };