Quellcode durchsuchen

feat:添加地图农场点击事件

wangsisi vor 5 Tagen
Ursprung
Commit
214bd7583a

+ 21 - 15
src/views/warningHome/components/equipment.vue

@@ -60,31 +60,37 @@
 <script setup>
 import chartBox from "@/components/chartBox.vue";
 import oneLineChart from "@/components/charts/oneLineChart.vue";
-import { onMounted, ref, onUnmounted } from "vue";
-import eventBus from "@/api/eventBus";
+import { ref, watch, nextTick } from "vue";
 
-const organId = ref(sessionStorage.getItem("farmId"));
-
-onMounted(() => {
-    getList();
-    //   eventBus.on("area:id", changeAreaId);
+const props = defineProps({
+    farmId: {
+        type: [Number, String],
+        default: null,
+    },
 });
 
-onUnmounted(() => {
-    eventBus.off("area:id", changeAreaId);
+watch(() => props.farmId, async (newVal, oldVal) => {
+    if(newVal) {
+        // 使用 nextTick 确保 DOM 更新完成后再执行
+        await nextTick();
+        getList();
+    } else {
+        // 如果 farmId 变为空,清空数据
+        temperatureData.value = [];
+        humidityData.value = [];
+        lightData.value = [];
+        chartDate.value = [];
+    }
+}, {
+    immediate: true, // 立即执行一次
 });
 
-function changeAreaId({ farmId }) {
-    organId.value = farmId;
-    getList();
-}
-
 const temperatureData = ref([]);
 const humidityData = ref([]);
 const lightData = ref([]);
 const chartDate = ref([]);
 function getList() {
-    VE_API.warning.fetchFarmDeviceRecord({ farmId: 1 }).then((res) => {
+    VE_API.warning.fetchFarmDeviceRecord({ farmId: props.farmId }).then((res) => {
         if(res.code === 0 && res.data && res.data.length > 0) { 
             temperatureData.value = res.data.map(item => item.temperature.toFixed(2));
             humidityData.value = res.data.map(item => item.humidity.toFixed(2));

+ 38 - 27
src/views/warningHome/components/farmInfoGroup.vue

@@ -25,7 +25,7 @@
                         <span class="info-label">{{ isBack ? `农场编号:${item.farmCode}` : item.farmName }}</span>
                         <div class="tags">
                             <span class="tag">{{ item.speciesName }}</span>
-                            <span class="tag">{{ item.varietyName }}</span>
+                            <span class="tag" v-show="item.varietyName">{{ item.varietyName }}</span>
                         </div>
                     </div>
                     <div class="info-item">
@@ -85,8 +85,8 @@
                             </div>
                         </div>
                         <div class="perception-wrap">
-                            <equipment v-if="perceptionActive === 'device'"></equipment>
-                            <crop v-else></crop>
+                            <equipment v-show="perceptionActive === 'device'" :farmId="currentFarmId"></equipment>
+                            <crop v-show="perceptionActive === 'crop'"></crop>
                         </div>
                     </div>
                 </div>
@@ -96,29 +96,44 @@
 </template>
 
 <script setup>
-import { ref ,onMounted} from "vue";
+import { ref, watch, onMounted, onUnmounted } from "vue";
 import equipment from "./equipment.vue";
 import crop from "./crop.vue";
+import eventBus from "@/api/eventBus";
 
-
-onMounted(() => {
-    fetchFarmList();
+const props = defineProps({
+    farmList: {
+        type: Array,
+        default: () => [],
+    },
 });
 
-//获取农场列表
 const defaultFarmList = ref([]);
-const fetchFarmList = () => {
-    VE_API.warning.fetchFarmList().then(res => {
-        if (res.code === 0 && res.data && res.data.length > 0) {
-            farmList.value = res.data;
-            defaultFarmList.value = res.data;
-        } else {
-            farmList.value = [];
-            defaultFarmList.value = [];
-        }
-    });
+watch(() => props.farmList, (newVal) => {
+    farmList.value = newVal;
+    defaultFarmList.value = newVal;
+});
+
+const handleFarmClick = (farmData) => {
+    farmList.value = [farmData];
+    currentFarmId.value = farmData.farmId;
+    isBack.value = true;
+   
+    if (currentFarmId.value) {
+        fetchFarmPhenologyRecord(currentFarmId.value);
+    }
 };
 
+onMounted(() => {
+    // 在组件挂载时注册事件监听
+    eventBus.on("distributionLayer:farmClick", handleFarmClick);
+});
+
+onUnmounted(() => {
+    // 组件卸载时移除事件监听
+    eventBus.off("distributionLayer:farmClick", handleFarmClick);
+});
+
 //查询农场物候记录
 const timelineList = ref([]);
 const fetchFarmPhenologyRecord = (farmId) => {
@@ -148,19 +163,15 @@ const handleBack = () => {
     isBack.value = false;
 };
 
-const handleCropArchive = () => {
-    // 作物档案逻辑
-};
-
-const handlePerceptionRecord = () => {
-    // 感知记录逻辑
-};
-
 const isBack = ref(false);
+const currentFarmId = ref(null);
 const handleFarmInfo = (item) => {
+    currentFarmId.value = item.farmId;
+    activeTab.value = "crop";
+    perceptionActive.value = "device";
     farmList.value = [item];
     isBack.value = true;
-    fetchFarmPhenologyRecord(item.id);
+    fetchFarmPhenologyRecord(item.farmId);
 };
 </script>
 <style lang="scss" scoped>

+ 80 - 17
src/views/warningHome/index.vue

@@ -45,11 +45,11 @@
                 <div class="warning-alarm yes-events" v-show="activeBaseTab === '预警分布'">
                     <alarm-list></alarm-list>
                 </div>
-                <div v-show="activeBaseTab !== '农服管理'" class="time-wrap yes-events">
+                <div v-show="activeBaseTab !== '农服管理' && activeBaseTab !== '农场分布'" class="time-wrap yes-events">
                     <time-line></time-line>
                 </div>
             </div>
-            <div class="action-legend" v-if="activeBaseTab !== '农场分布' && activeBaseTab !== '农服管理'">
+            <div class="action-legend" v-if="activeBaseTab !== '农服管理'">
                 <el-tree
                     ref="treeRef"
                     class="yes-events"
@@ -78,7 +78,7 @@
                 <!-- <farmInfoGroup></farmInfoGroup> -->
             </div>
             <div v-if="panelType === 1" class="warning-r right yes-events">
-                <farmInfoGroup></farmInfoGroup>
+                <farmInfoGroup :farmList="farmList"></farmInfoGroup>
             </div>
             <div v-if="panelType === 2" class="warning-r right yes-events">
                 <service-list></service-list>
@@ -173,12 +173,6 @@ const defaultProps = {
     label: "name",
 };
 
-import lz from "@/assets/images/map/type/荔枝.png";
-import ly from "@/assets/images/map/type/龙眼.png";
-import sd from "@/assets/images/map/type/水稻.png";
-import xm from "@/assets/images/map/type/小麦.png";
-import bc from "@/assets/images/map/type/小麦.png";
-import lb from "@/assets/images/map/type/小麦.png";
 // 冷链冷库、加工厂图标(与图例保持一致)
 import coldChainIcon from "@/assets/images/common/legend-icon-1.png";
 import factoryIcon from "@/assets/images/common/legend-icon-2.png";
@@ -410,6 +404,11 @@ const getCommonMapData = async (firstCategory) => {
             distributionLayer.initData(phenologyData, 'phenologyName');
             return;
         }
+        if (activeBaseTab.value === "农场分布") {
+            const lastLevelIds = lastLevelNodes.map((n) => n.originalId);
+            await fetchFarmList(lastLevelIds);
+            return;
+        }
         const lastLevelIds = lastLevelNodes.map((n) => n.id);
         // 并发请求所有数据
         const promises = lastLevelIds.map((id) => getDistributionData(id));
@@ -477,6 +476,10 @@ const handleTabClick = (item) => {
 
     switch (item) {
         case "作物分布":
+            // 禁用农场分布点击处理
+            if (distributionLayer) {
+                distributionLayer.setFarmClickEnabled(false);
+            }
             // 恢复原始数据
             if (originalTreeData.value.length > 0) {
                 treeActionData.value = JSON.parse(JSON.stringify(originalTreeData.value));
@@ -485,6 +488,10 @@ const handleTabClick = (item) => {
             handleDistributionLayer();
             break;
         case "物候期分布":
+            // 禁用农场分布点击处理
+            if (distributionLayer) {
+                distributionLayer.setFarmClickEnabled(false);
+            }
             // 先恢复原始数据,再修改第二级 children 的 items 字段为 phenologies
             if (originalTreeData.value.length > 0) {
                 treeActionData.value = JSON.parse(JSON.stringify(originalTreeData.value));
@@ -516,6 +523,10 @@ const handleTabClick = (item) => {
             handlePhenologyLayer();
             break;
         case "预警分布":
+            // 禁用农场分布点击处理
+            if (distributionLayer) {
+                distributionLayer.setFarmClickEnabled(false);
+            }
             handleAlarmTreeDefault()
             handleAlarmLayer();
             // 通知预警列表组件默认选中第一个(因子)项
@@ -523,7 +534,39 @@ const handleTabClick = (item) => {
             break;
         case "农场分布":
             panelType.value = 1;
-            fetchFarmList();
+            // 启用农场分布点击处理
+            if (distributionLayer) {
+                distributionLayer.setFarmClickEnabled(true);
+            }
+            // 先恢复原始数据,再修改第二级 children 的 items 字段为 phenologies
+            if (originalTreeData.value.length > 0) {
+                treeActionData.value = JSON.parse(JSON.stringify(originalTreeData.value));
+            }
+            // 修改第二级 children 的 items 字段为 phenologies,不修改其他项
+            treeActionData.value = treeActionData.value.map((firstLevel) => {
+                if (firstLevel.items && Array.isArray(firstLevel.items)) {
+                    return {
+                        ...firstLevel,
+                        items: firstLevel.items.map((secondLevel) => {
+                            // 如果第二级有 phenologies 字段,将其设置为 items
+                            if (secondLevel.phenologies) {
+                                secondLevel.phenologies.forEach((phenology) => {
+                                    phenology.originalId = phenology.id;
+                                    phenology.id = 'phenology_' + phenology.id;
+                                });
+                                return {
+                                    ...secondLevel,
+                                    items: secondLevel.phenologies,
+                                };
+                            }
+                            return secondLevel;
+                        }),
+                    };
+                }
+                return firstLevel;
+            });
+            handlePhenologyTreeDefault();
+            handlePhenologyLayer();
 
             // // 设施图层测试数据
             // const facilityData = [
@@ -544,6 +587,10 @@ const handleTabClick = (item) => {
             // distributionLayer.initFacilityData(facilityData);
             break;
         case "农服管理":
+            // 禁用农场分布点击处理
+            if (distributionLayer) {
+                distributionLayer.setFarmClickEnabled(false);
+            }
             panelType.value = 2;
             break;
         default:
@@ -656,8 +703,15 @@ const props1 = {
     },
 };
 
-const fetchFarmList = () => {
-    VE_API.warning.fetchFarmList().then(res => {
+const farmList = ref([]);
+const fetchFarmList = (phenologyIds) => {
+    const params = {
+        year: currentYear.value,
+        quarter: currentQuarter.value,
+        phenologyIds: phenologyIds || [],
+    };
+    return new Promise((resolve, reject) => {
+        VE_API.warning.fetchFarmList(params).then(res => {
         if (res.code === 0 && res.data && res.data.length > 0) {
             // 将接口数据转换为地图需要的格式
             const cropData = res.data.map((item) => {
@@ -676,13 +730,18 @@ const fetchFarmList = () => {
             
             // 渲染作物数据到地图
             distributionLayer.initData(cropData, 'label');
+            farmList.value = cropData;
+            resolve(cropData);
         } else {
             // 接口返回空数据时,清空地图
             distributionLayer.initData([]);
+            resolve([]);
         }
-    }).catch((error) => {
-        // 错误时也清空地图
-        distributionLayer.initData([]);
+        }).catch((error) => {
+            // 错误时也清空地图
+            distributionLayer.initData([]);
+            reject(error);
+        });
     });
 };
 
@@ -790,7 +849,7 @@ const getTreeChecks = async (nodeData, data) => {
     let finalCheckedNodes = checkedNodes;
 
     // 物候期分布:限制"二级只能选一个,三级不限个数"
-    if ((activeBaseTab.value === "物候期分布" || activeBaseTab.value === "预警分布") && treeRef.value) {
+    if ((activeBaseTab.value === "物候期分布" || activeBaseTab.value === "预警分布" || activeBaseTab.value === "农场分布") && treeRef.value) {
         const tree = treeRef.value;
         const { level, secondId } = getNodeLevelInfo(nodeData.id);
 
@@ -833,7 +892,7 @@ const getTreeChecks = async (nodeData, data) => {
 
     // 任意 tab 下,最终都用当前选中的节点驱动地图渲染
     // 提取最后一级节点的 id 到数组(没有子节点的叶子节点)
-    const field = activeBaseTab.value === "物候期分布" ? "originalId" : "id";
+    const field = (activeBaseTab.value === "物候期分布" || activeBaseTab.value === "农场分布") ? "originalId" : "id";
     const lastLevelIds = finalCheckedNodes
         .filter((n) => (!n.items || n.items.length === 0) && (!n.children || n.children.length === 0))
         .map((n) => n[field]);
@@ -846,6 +905,10 @@ const getTreeChecks = async (nodeData, data) => {
         distributionLayer.initData(phenologyData, 'phenologyName');
         return;
     }
+    if (activeBaseTab.value === "农场分布") {
+        await fetchFarmList(lastLevelIds);
+        return;
+    }
     // 并发请求所有数据,等待所有 Promise 完成
     const promises = lastLevelIds.map((id) => {
         const node = finalCheckedNodes.find((n) => n.id === id);

+ 63 - 0
src/views/warningHome/map/distributionLayer.js

@@ -7,6 +7,7 @@ import Photo from "ol-ext/style/Photo";
 import { newPoint, newPolymerFeature } from "@/utils/map.js";
 
 import pointBgImg from "@/assets/images/map/point_bg.png";
+import eventBus from "@/api/eventBus";
 
 class DistributionLayer {
     constructor(kmap) {
@@ -174,6 +175,68 @@ class DistributionLayer {
             },
         });
         this.kmap.addLayer(this.facilityPointLayer.layer)
+
+        // 标志:是否启用农场分布点击处理
+        this.enableFarmClick = false;
+
+        // 添加点击事件监听,用于处理农场分布的点击交互
+        this.clickHandler = (event) => {
+            if (this.enableFarmClick) {
+                this.handlePointClick(event);
+            }
+        };
+        this.kmap.on('singleclick', this.clickHandler);
+    }
+
+    /**
+     * 启用/禁用农场分布点击处理
+     * @param {boolean} enable - 是否启用
+     */
+    setFarmClickEnabled(enable) {
+        this.enableFarmClick = enable;
+    }
+
+    /**
+     * 处理点位点击事件
+     * 如果是聚合点,放大地图;如果是单个农场,打印提示
+     */
+    handlePointClick(event) {
+        const pixel = event.pixel;
+        const coordinate = event.coordinate;
+        
+        // 检查是否点击到了 distributionPointLayer
+        const clickedFeature = this.kmap.map.forEachFeatureAtPixel(pixel, (feature, layer) => {
+            if (layer === this.distributionPointLayer.layer) {
+                return feature;
+            }
+            return null;
+        });
+
+        if (!clickedFeature) {
+            return;
+        }
+
+        // 获取聚合点内的所有 features
+        const features = clickedFeature.get('features');
+        
+        if (features && features.length > 1) {
+            // 是聚合点,放大地图
+            const view = this.kmap.map.getView();
+            const currentZoom = view.getZoom();
+            const newZoom = Math.min(currentZoom + 2, view.getMaxZoom() || 22);
+            
+            view.animate({
+                center: coordinate,
+                zoom: newZoom,
+                duration: 300
+            });
+        } else if (features && features.length === 1) {
+            // 是单个农场,通过事件总线发送事件
+            const farmFeature = features[0];
+            const farmData = farmFeature.getProperties();
+            // 通过事件总线发送农场点击事件
+            eventBus.emit('distributionLayer:farmClick', farmData);
+        }
     }
 
     /**