lxf vor 4 Tagen
Ursprung
Commit
ba0814ea96

BIN
src/assets/img/common/rain.png


BIN
src/assets/img/common/water.png


BIN
src/assets/img/map/Flood_Waterlogging_Risk.png


BIN
src/assets/img/map/High_Humidity_Heat_Risk.png


+ 26 - 0
src/views/old_mini/growth_report/growthReportMap.js

@@ -1,6 +1,7 @@
 import * as KMap from "@/utils/ol-map/KMap";
 import * as util from "@/common/ol_common.js";
 import config from "@/api/config.js";
+import StaticImgLayer from "@/utils/ol-map/StaticImgLayer";
 import Style from "ol/style/Style";
 import Icon from "ol/style/Icon";
 import Fill from "ol/style/Fill";
@@ -22,6 +23,7 @@ class IndexMap {
     let that = this;
     let vectorStyle = new KMap.VectorStyle();
     this.vectorStyle = vectorStyle;
+    this.remoteImageLayer = null;
 
     // 位置图标
     this.clickPointLayer = new KMap.VectorLayer("clickPointLayer", 9999, {
@@ -36,6 +38,30 @@ class IndexMap {
     });
   }
 
+  /** 叠加静态风险底图(与 PC homeMap.showRemoteImage 一致) */
+  showRemoteImage(url, extent, options = {}) {
+    this.hideRemoteImage();
+    if (!url || !extent?.length || !this.kmap) return;
+    this.remoteImageLayer = new StaticImgLayer(
+      url,
+      {
+        extent,
+        minZoom: 6,
+        maxZoom: 22,
+        opacity: options.opacity ?? 0.5,
+      },
+      50,
+      this.kmap,
+    );
+  }
+
+  hideRemoteImage() {
+    if (this.remoteImageLayer?.layer && this.kmap?.map) {
+      this.kmap.map.removeLayer(this.remoteImageLayer.layer);
+    }
+    this.remoteImageLayer = null;
+  }
+
   initMap(location, target) {
     let level = 16;
     let coordinate = util.wktCastGeom(location).getFirstCoordinate();

+ 76 - 24
src/views/old_mini/growth_report/index.vue

@@ -12,7 +12,9 @@
                         <img class="interact-card__star" src="@/assets/img/agricultural/start.png" alt="" />
                         <span>异常互动</span>
                     </div>
-                    <el-icon class="interact-card__close" @click="showInteractCard = false"><Close /></el-icon>
+                    <el-icon class="interact-card__close" @click="showInteractCard = false">
+                        <Close />
+                    </el-icon>
                 </div>
                 <div class="interact-card__qa">
                     <div class="interact-card__question">{{ interactQuestionText }}</div>
@@ -28,6 +30,21 @@
             <span class="location-bar__action" @click="handleSwitchLocation">切换位置</span>
         </div> -->
 
+
+        <!-- 左侧:胁迫图层菜单 -->
+        <div class="side-menu side-menu--left">
+            <div v-for="item in stressMenuItems" :key="item.key" class="side-menu__item"
+                :class="{ active: activeMenuKey === item.key }" @click="handleSelectMenu(item.key)">
+                <img class="side-menu__icon" :src="item.icon" alt="" />
+                <div class="side-menu__text">
+                    <span>{{ item.line1 }}</span>
+                    <span>{{ item.line2 }}</span>
+                </div>
+            </div>
+        </div>
+
+
+
         <!-- <div class="map-legend" :style="{ bottom: `${inviteBottom}px` }">
             <div
                 v-for="item in mapLegendItems"
@@ -39,21 +56,13 @@
             </div>
         </div> -->
 
-        <crop-alert-panel
-            :crop-name="currentCropName"
-            :weather-risk="weatherRisk"
-            :weather-stress="weatherStress"
-            :weather-risk-explain="weatherRiskExplain"
-            :weather-stress-explain="weatherStressExplain"
-            :report-generating="reportGenerating"
-            @switch-category="handleSwitchCategory"
-            @view-detail="handleViewDetail"
-            @patrol-tip="handlePatrolTip"
-            @height-change="handlePanelHeightChange"
-        />
+        <crop-alert-panel :crop-name="currentCropName" :weather-risk="weatherRisk" :weather-stress="weatherStress"
+            :weather-risk-explain="weatherRiskExplain" :weather-stress-explain="weatherStressExplain"
+            :report-generating="reportGenerating" @switch-category="handleSwitchCategory"
+            @view-detail="handleViewDetail" @patrol-tip="handlePatrolTip" @height-change="handlePanelHeightChange" />
     </div>
 
-    
+
     <!-- 诊断报告弹窗 -->
     <diagnosis-report-popup ref="diagnosisReportPopupRef" />
 
@@ -83,6 +92,27 @@ const router = useRouter();
 const route = useRoute();
 const diagnosisReportPopupRef = ref(null);
 
+const menuIcon = require("@/assets/img/common/water.png");
+const menuIcon2 = require("@/assets/img/common/rain.png");
+const stressMenuItems = [
+    {
+        key: "stress",
+        line1: "暴雨",
+        line2: "涝渍",
+        icon: menuIcon,
+        mapUrl: require("@/assets/img/map/Flood_Waterlogging_Risk.png"),
+        extent: [115.7752805213905, 23.913245697921756, 116.55501818800624, 24.798086252779484],
+    },
+    {
+        key: "hot-drought-1",
+        line1: "高温",
+        line2: "高湿",
+        icon: menuIcon2,
+        mapUrl: require("@/assets/img/map/High_Humidity_Heat_Risk.png"),
+        extent: [115.77569718805717, 23.912588960529323, 116.55453653938879, 24.79742951538705],
+    },
+];
+
 /** 恢复种植确认「已到达」后,再检查是否弹出诊断报告 */
 const onPhenologyReached = () => {
     diagnosisReportPopupRef.value?.checkShouldShow?.();
@@ -104,7 +134,6 @@ function readEntryFarmData() {
 
 const entryFarmData = readEntryFarmData();
 
-const menuIcon = require("@/assets/img/common/farm-active.png");
 
 const mapLegendItems = computed(() => [
     { key: "zone", label: "胁迫", pillClass: "map-legend__pill--zone" },
@@ -120,10 +149,10 @@ const growthReportMap = new GrowthReportMap();
 const locationName = ref("");
 const currentMapPoint = ref(
     entryFarmData?.point ||
-        localStorage.getItem(MAP_POINT_STORAGE_KEY) ||
-        localStorage.getItem("selectedFarmPoint") ||
-        store.state.home.miniUserLocationPoint ||
-        DEFAULT_MAP_POINT
+    localStorage.getItem(MAP_POINT_STORAGE_KEY) ||
+    localStorage.getItem("selectedFarmPoint") ||
+    store.state.home.miniUserLocationPoint ||
+    DEFAULT_MAP_POINT
 );
 const currentCropName = ref(entryFarmData?.crop || "水稻");
 const weatherRisk = ref(entryFarmData?.weatherRisk || "具体预警");
@@ -134,7 +163,7 @@ const weatherRiskExplain = ref("");
 const weatherStressExplain = ref("");
 /** stress_report 为空时,气象报告生成中 */
 const reportGenerating = ref(false);
-const activeMenuKey = ref("hot-drought-2");
+const activeMenuKey = ref("");
 const panelHeight = ref(280);
 const inviteBottom = computed(() => panelHeight.value);
 const invitePopupRef = ref(null);
@@ -142,7 +171,7 @@ const invitePopupRef = ref(null);
 const showInteractCard = ref(false);
 const interactQuestionText = ref("");
 
-const CHECK_REPORT_INTERVAL_MS = 3000;
+const CHECK_REPORT_INTERVAL_MS = 6000;
 let checkWeatherReportTimer = null;
 
 function resolveUserTel() {
@@ -357,13 +386,25 @@ const initMap = async () => {
         if (coordinate?.length === 2) {
             growthReportMap.setMapPosition(coordinate);
         }
+        applyMenuOverlay(activeMenuKey.value);
         return;
     }
     const location = currentMapPoint.value || store.state.home.miniUserLocationPoint || DEFAULT_MAP_POINT;
     currentMapPoint.value = location;
     growthReportMap.initMap(location, mapContainer.value);
+    applyMenuOverlay(activeMenuKey.value);
 };
 
+/** 按侧边菜单叠加对应风险底图 */
+function applyMenuOverlay(key) {
+    const item = stressMenuItems.find((m) => m.key === key);
+    if (!item?.mapUrl || !item.extent || !growthReportMap.kmap) {
+        growthReportMap.hideRemoteImage();
+        return;
+    }
+    growthReportMap.showRemoteImage(item.mapUrl, item.extent);
+}
+
 function applySelectedLocation() {
     const raw = sessionStorage.getItem(LOCATION_SESSION_KEY);
     if (!raw) return false;
@@ -405,7 +446,14 @@ const handleSwitchLocation = () => {
 
 const handleSelectMenu = (key) => {
     if (!key) return;
+    // 再次点击同一项则关闭叠加
+    if (activeMenuKey.value === key) {
+        activeMenuKey.value = "";
+        growthReportMap.hideRemoteImage();
+        return;
+    }
     activeMenuKey.value = key;
+    applyMenuOverlay(key);
 };
 
 const handleInvite = (type) => {
@@ -616,12 +664,14 @@ onBeforeUnmount(() => {
             margin: 0 10px 10px;
             border-radius: 8px;
         }
+
         .interact-card__question {
             font-size: 16px;
             color: #000;
             font-weight: 500;
 
         }
+
         .interact-card__btn {
             margin: 10px auto 0;
             height: 32px;
@@ -712,8 +762,8 @@ onBeforeUnmount(() => {
         }
 
         &__icon {
-            width: 16px;
-            height: 16px;
+            width: 22px;
+            height: 22px;
             object-fit: contain;
             opacity: 0.55;
             filter: grayscale(1);
@@ -751,11 +801,13 @@ onBeforeUnmount(() => {
             color: #2199F8;
             font-weight: 500;
             font-size: 12px;
+
             .invite-icon {
                 width: 16px;
             }
         }
-        .invite-btn + .invite-btn {
+
+        .invite-btn+.invite-btn {
             margin-top: 10px;
         }
     }