Преглед изворни кода

feat:修改农事规划时间轴样式和农事详情页面逻辑

wangsisi пре 8 часа
родитељ
комит
a2487d7e01

BIN
src/assets/img/common/fq-1.png


BIN
src/assets/img/common/fq-2.png


BIN
src/assets/img/common/jf-1.png


BIN
src/assets/img/common/jf-2.png


BIN
src/assets/img/common/yz-1.png


BIN
src/assets/img/common/yz-2.png


+ 141 - 74
src/components/pageComponents/ArchivesFarmTimeLine.vue

@@ -30,8 +30,8 @@
                                             <div class="left-date">{{ formatDate(fw.createTime) }}</div>
                                             <div class="text">
                                                 <span class="van-ellipsis">{{ fw.title }}</span>
-                                                <div class="text-status">{{ farmWorkTypeObj[fw.farm_work_type] }}</div>
-                                                <el-icon>
+                                                <div class="text-status" :style="farmWorkTypeObjColor[fw.farm_work_type]">{{ farmWorkTypeObj[fw.farm_work_type] }}</div>
+                                                <el-icon color="#333333">
                                                     <ArrowRight />
                                                 </el-icon>
                                             </div>
@@ -43,10 +43,15 @@
                                             <div class="info-right">{{ fw.interaction_issue }}</div>
                                         </div>
                                         <div class="text-display" v-if="fw.zone.length">
-                                            <div class="title-text van-ellipsis" v-for="(zone,index) in fw.zone" :key="index">{{ zone }}</div>
+                                            <div class="title-text" v-for="(zone,index) in fw.zone" :key="index">
+                                                <span>{{ zone }}</span>
+                                                <div class="check-icon" v-if="fw.work_status === 6">
+                                                    <el-icon size="8" color="#fff"><Select /></el-icon>
+                                                </div>
+                                            </div>
                                         </div>
                                     </div>
-                                    <div class="status-right" :style="statusColorObj[fw.work_status]"
+                                    <div class="status-right" :style="getStatusColorObj(fw)"
                                         v-if="fw.work_status !== 3 && fw.work_status !== 5">{{
                                             workStatusObj[fw.work_status] }}</div>
                                 </div>
@@ -255,29 +260,85 @@ const workStatusObj = computed(() =>
     Object.fromEntries([0, 1, 2, 3, 4, 5, 6].map((s) => [s, t(`agriRecord.workStatus.${s}`)]))
 );
 
-const statusColorObj = {
-    2: {
-        color: "#fff",
-        background: "#2199F8",
+// 农事类型颜色
+const farmWorkTypeObjColor = {
+    3: {
+        color: "#FF943D",
+        background: "rgba(255, 148, 61, 0.1)",
+        borderColor: "rgba(255, 132, 0, 0.1)",
     },
     4: {
-        color: "#4ABF32",
-        background: "rgba(74, 191, 50, 0.2)",
+        color: "#FF943D",
+        background: "rgba(255, 148, 61, 0.1)",
+        borderColor: "rgba(255, 132, 0, 0.1)",
     },
-    6: {
-        color: "#2199F8",
-        background: "rgba(33, 153, 248, 0.2)",
+    5: {
+        color: "#FF6A6A",
+        background: "rgba(255, 106, 106, 0.1)",
+        borderColor: "rgba(255, 106, 106, 0.1)",
     },
-};
+}
+
+// 农事卡片状态样式(work_status)
+const getStatusColorObj = (fw) => {
+    let color = "#fff";
+    let background = "#2199F8";
+    const status = fw?.work_status; // 农事状态
+    const type = fw?.farm_work_type; // 农事类型
+    if (status == 2){
+        if(type === 3 || type === 4){
+            color = "#fff";
+            background = "#FF943D";
+        }else if(type == 5){
+            color = "#fff";
+            background = "#FF6A6A";
+        }else{
+            color = "#fff";
+            background = "#2199F8";
+        }
+    }
+    if (status == 4){
+        color = "#2FC510";
+        background = "#fff";
+    }
+    if (status == 6){
+        if(type === 3 || type === 4){
+            color = "#FF953D";
+            background = "#fff";
+        }else if(type == 5){
+            color = "#FF6A6A";
+            background = "#fff";
+        }else{
+            color = "#2199F8";
+            background = "#fff";
+        }
+    }
+
+    return {color, background};
+}
 
 // 农事卡片状态样式(work_status)
 const getArrangeStatusClass = (fw) => {
-    const status = fw?.work_status;
-    const type = fw?.farm_work_type;
-    if (status == 0 || status == 1) return "status-orange";
-    if (status == 2) return "status-normal";
-    if (status == 4) return "status-green-info";
-    if (status == 6) return "status-normal-farm";
+    const status = fw?.work_status; // 农事状态
+    const type = fw?.farm_work_type; // 农事类型
+    if(status === 6){
+        if(type === 3 || type === 4){
+            return "status-orange-bg";
+        }else if(type === 5){
+            return "status-danger-bg";
+        }else{
+            return "status-normal-farm";
+        }
+    }else if(status === 2){
+        if(type === 3 || type === 4){
+            return "status-orange";
+        }else if(type === 5){
+            return "status-danger";
+        }else{
+            return "status-normal";
+        }
+    }
+    if (status === 0 || status === 1) return "status-normal";
     return "future-card";
 };
 
@@ -468,28 +529,9 @@ const handleStatusDetail = (fw) => {
     router.push({
         path: "/work_detail",
         query: {
-            title: fw?.title,
             id: fw?.id,
         },
     });
-    // if (fw?.archiveType === 2) {
-    //     return;
-    // }
-    // if (fw?.archiveType === 6) {
-    //     router.push({
-    //         path: "/work_detail",
-    //         query: {
-    //             miniJson: JSON.stringify({
-    //                 paramsPage: JSON.stringify({
-    //                     farmId: 98570,
-    //                     farmWorkLibId: '832268348690534411',
-    //                     recordId: "832268363366404096",
-    //                     reproductiveId: 149,
-    //                 }),
-    //             }),
-    //         },
-    //     });
-    // } 
 };
 
 // 格式化日期为 MM-DD 格式
@@ -540,31 +582,14 @@ onBeforeRouteLeave(() => {
 </script>
 
 <style scoped lang="scss">
-@mixin arrange-card-status($color, $content-color: null, $border-color: null, $content-bg: null, $text-color: null) {
+@mixin arrange-card-status($color, $content-color: null, $border-color: null, $content-bg: null) {
     border-color: $color;
 
     @if $content-bg !=null {
         background: $content-bg;
     }
 
-    .card-content {
-        @if $text-color !=null {
-            color: $text-color;
-        }
-    }
-
     .card-left {
-        .left-info {
-            .left-date {
-                color: $text-color;
-                border-color: $text-color;
-            }
-
-            .text {
-                color: $text-color;
-            }
-        }
-
         .title-text {
             @if $color !=null {
                 color: $color;
@@ -692,7 +717,6 @@ onBeforeRouteLeave(() => {
                     margin-bottom: 10px;
 
                     .card-content {
-                        color: #242424;
                         display: flex;
                         justify-content: space-between;
                         align-items: center;
@@ -707,7 +731,6 @@ onBeforeRouteLeave(() => {
                                 gap: 6px;
 
                                 .left-date {
-                                    color: rgba(0, 0, 0, 0.4);
                                     border: 0.5px solid rgba(0, 0, 0, 0.4);
                                     border-radius: 2px;
                                     font-size: 12px;
@@ -720,22 +743,35 @@ onBeforeRouteLeave(() => {
                                     display: flex;
                                     align-items: center;
                                     gap: 2px;
-                                    color: rgba(0, 0, 0, 0.4);
                                     width: calc(100% - 90px);
                                 }
                                 .text-status {
-                                    background: rgba(144, 144, 144, 0.1);
-                                    color: #515151;
+                                    background: rgba(33, 153, 248, 0.1);
+                                    color: #2199F8;
                                     border-radius: 2px;
-                                    padding: 2px 5px;
+                                    padding: 0 5px;
                                     font-size: 10px;
                                     min-width: fit-content;
+                                    border: 0.5px solid rgba(33, 153, 248, 0.4);
                                 }
                             }
 
                             .text-display {
                                 display: flex;
-                                gap: 5px;
+                                gap: 6px;
+                                margin-top: 3px;
+                                .check-icon{
+                                    position: absolute;
+                                    right: -5px;
+                                    top: -5px;
+                                    width: 13px;
+                                    height: 13px;
+                                    background: #2199F8;
+                                    border-radius: 50%;
+                                    display: flex;
+                                    align-items: center;
+                                    justify-content: center;
+                                }
                             }
 
                             .title-text {
@@ -749,6 +785,7 @@ onBeforeRouteLeave(() => {
                                 font-size: 12px;
                                 box-sizing: border-box;
                                 border: 0.5px solid rgba(0, 0, 0, 0.4);
+                                position: relative;
                             }
 
                             .farm-info {
@@ -764,7 +801,7 @@ onBeforeRouteLeave(() => {
                                 margin-top: 6px;
 
                                 .info-right {
-                                    background: #FF953D;
+                                    background: #2199F8;
                                     border-radius: 2px;
                                     padding: 1px 5px;
                                     color: #fff;
@@ -779,7 +816,7 @@ onBeforeRouteLeave(() => {
                             font-size: 12px;
                             color: #fff;
                             background: #FF953D;
-                            border-radius: 0 4px 0 4px;
+                            border-radius: 0 8px 0 4px;
                             padding: 0 5px;
                         }
                     }
@@ -799,26 +836,56 @@ onBeforeRouteLeave(() => {
                 }
 
                 .arrange-card.status-normal {
-                    @include arrange-card-status(#2199F8, null, #2199F8, null, #000);
+                    @include arrange-card-status(#2199F8, null, #2199F8, null);
                 }
 
-                .arrange-card.status-green-info {
-                    @include arrange-card-status(#4ABF32, #ECFFE8, rgba(74, 191, 50, 0.5), rgba(28, 169, 0, 0.1), rgba(0, 0, 0, 0.4));
+                .arrange-card.status-orange {
+                    @include arrange-card-status(#FF953D, null, #FF953D, #fff);
                 }
 
-                .arrange-card.status-orange {
-                    @include arrange-card-status(#FF953D, null, #FF953D, #fff, #000);
+                .arrange-card.status-orange-bg {
+                    @include arrange-card-status(#FF953D, null, #FF953D, rgba(255, 149, 61, 0.1));
+                    .check-icon{
+                        background: #FF953D !important;
+                    }
+                }
+
+                .arrange-card.status-danger {
+                    @include arrange-card-status(#FF6A6A, null, #FF6A6A, #fff);
+                }
+
+                .arrange-card.status-danger-bg {
+                    @include arrange-card-status(#FF6A6A, null, #FF6A6A, rgba(255, 106, 106, 0.1));
+                    .check-icon{
+                        background: #FF6A6A !important;
+                    }
                 }
 
                 .arrange-card.status-normal-farm {
-                    @include arrange-card-status(#2199F8, #E9F5FF, #2199F8, rgba(33, 153, 248, 0.1), rgba(0, 0, 0, 0.4));
+                    @include arrange-card-status(#2199F8, #E9F5FF, #2199F8, rgba(33, 153, 248, 0.1));
                 }
 
                 // 未激活等:灰色描边卡片
                 .arrange-card.future-card {
-                    @include arrange-card-status(rgba(184, 182, 182, 0.9), null, rgba(184, 182, 182, 0.9), #fff, rgba(184, 182, 182, 0.9));
-                }
+                    @include arrange-card-status(rgba(184, 182, 182, 0.9), null, rgba(184, 182, 182, 0.9), #fff);
+
+                    .card-content {
+                        color: rgba(184, 182, 182, 0.9);
+                    }
 
+                    .card-left {
+                        .left-info {
+                            .left-date {
+                                color: rgba(184, 182, 182, 0.9);
+                                border-color: rgba(184, 182, 182, 0.9);
+                            }
+
+                            .text {
+                                color: rgba(184, 182, 182, 0.9);
+                            }
+                        }
+                    }
+                }
             }
         }
     }

+ 4 - 4
src/i18n/messages.js

@@ -179,8 +179,8 @@ export default {
             phenologyReason: "预计到达病虫防控关键期",
             phenologyIssue: "是否有60%的荔枝进入转色期",
             workStatus: {
-                0: "待校准",
-                1: "机动执行",
+                0: "时间待校准",
+                1: "触发待巡园",
                 2: "待执行",
                 3: "未激活",
                 4: "已认证",
@@ -379,8 +379,8 @@ export default {
             phenologyReason: "Expected critical pest control period",
             phenologyIssue: "Have 60% of lychee trees entered color-change stage?",
             workStatus: {
-                0: "Calib",
-                1: "Flex",
+                0: "Time Calib",
+                1: "Trigger Patrol",
                 2: "Pending",
                 3: "Off",
                 4: "Cert",

+ 7 - 0
src/router/globalRoutes.js

@@ -160,6 +160,13 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/work_detail/index.vue"),
     },
+    // 农事详情 - 查看区域
+    {
+        path: "/view_area",
+        name: "WorkViewArea",
+        meta: { keepAlive: true },
+        component: () => import("@/views/old_mini/work_detail/components/mapInfo.vue"),
+    },
     {
         path: "/select_crop",
         name: "SelectCrop",

+ 142 - 29
src/views/old_mini/work_detail/components/areaMap.js

@@ -11,6 +11,7 @@ import * as turf from "@turf/turf"
 import Style from "ol/style/Style";
 import Icon from "ol/style/Icon";
 import { Fill, Text, Stroke } from "ol/style";
+import Overlay from "ol/Overlay";
 import * as proj from "ol/proj";
 import { buffer as bufferExtent, getWidth, getHeight } from "ol/extent";
 import proj4 from "proj4"
@@ -23,32 +24,12 @@ register(proj4);
  */
 class AreaMap {
     constructor() {
-        let that = this;
-        let vectorStyle = new KMap.VectorStyle()
+        this.labelOverlays = [];
         this.gardenPolygonLayer = new KMap.VectorLayer("gardenPolygonLayer", 999, {
             minZoom: 8,
             maxZoom: 22,
             source: new VectorSource({}),
-            style: function (f) {
-                let style2 = vectorStyle.getPolygonStyle("#00000080", "#2199F8", 2)
-
-                const label = f.get("zone_name") || (f.get("mianji") ? `${f.get("mianji")}亩` : "");
-                const style3 = label
-                    ? new Style({
-                          text: new Text({
-                              font: "14px sans-serif",
-                              text: label,
-                              offsetY: 10,
-                              fill: new Fill({ color: "#fff" }),
-                              stroke: new Stroke({
-                                  color: "#000",
-                                  width: 0.5,
-                              }),
-                          }),
-                      })
-                    : null;
-                return style3 ? [style2, style3] : [style2];
-            }
+            style: (f) => this.getZoneStyle(f),
         });
 
         // 位置图标
@@ -79,10 +60,135 @@ class AreaMap {
     }
 
 
-    initMap(location, target) {
+    getZoneStyle(f) {
+        const flySpeed = f.get("fly_speed");
+        const labelStyle = f.get("label_style") || (flySpeed ? "card" : "legacy");
+        const fillColor = f.get("fill_color") || "#00000080";
+        const strokeColor = f.get("stroke_color") || "#2199F8";
+        const zoneName = f.get("zone_name") || (f.get("mianji") ? `${f.get("mianji")}亩` : "");
+
+        const styles = [
+            new Style({
+                fill: new Fill({ color: fillColor }),
+                stroke: new Stroke({ color: strokeColor, width: 2 }),
+            }),
+        ];
+
+        if (!zoneName) return styles;
+
+        if (labelStyle === "legacy") {
+            styles.push(
+                new Style({
+                    text: new Text({
+                        font: "14px sans-serif",
+                        text: zoneName,
+                        offsetY: 10,
+                        fill: new Fill({ color: "#fff" }),
+                        stroke: new Stroke({
+                            color: "#000",
+                            width: 0.5,
+                        }),
+                    }),
+                })
+            );
+            return styles;
+        }
+
+        if (labelStyle === "simple") {
+            styles.push(
+                new Style({
+                    text: new Text({
+                        text: zoneName,
+                        font: "13px sans-serif",
+                        fill: new Fill({ color: "#ffffff" }),
+                        backgroundFill: new Fill({ color: "rgba(80, 80, 80, 0.85)" }),
+                        padding: [4, 8, 4, 8],
+                    }),
+                })
+            );
+            return styles;
+        }
+
+        return styles;
+    }
+
+    createZoneCardLabelElement(zoneName, flySpeed) {
+        const wrap = document.createElement("div");
+        Object.assign(wrap.style, {
+            background: "#ffffff",
+            borderRadius: "4px",
+            padding: "6px 10px",
+            boxShadow: "0 1px 4px rgba(0, 0, 0, 0.08)",
+            textAlign: "center",
+            pointerEvents: "none",
+            whiteSpace: "nowrap",
+        });
+
+        const title = document.createElement("div");
+        title.textContent = zoneName;
+        Object.assign(title.style, {
+            fontSize: "13px",
+            fontWeight: "600",
+            color: "#262626",
+            lineHeight: "18px",
+        });
+        wrap.appendChild(title);
+
+        if (flySpeed) {
+            const sub = document.createElement("div");
+            sub.textContent = `飞巡速度:${flySpeed}`;
+            Object.assign(sub.style, {
+                fontSize: "11px",
+                color: "#999999",
+                lineHeight: "16px",
+                marginTop: "2px",
+            });
+            wrap.appendChild(sub);
+        }
+
+        return wrap;
+    }
+
+    clearLabelOverlays() {
+        if (!this.labelOverlays?.length || !this.kmap?.map) return;
+        this.labelOverlays.forEach((overlay) => {
+            this.kmap.map.removeOverlay(overlay);
+        });
+        this.labelOverlays = [];
+    }
+
+    syncLabelOverlays() {
+        this.clearLabelOverlays();
+        if (!this.kmap?.map || !this.gardenPolygonLayer?.source) return;
+
+        this.gardenPolygonLayer.source.getFeatures().forEach((f) => {
+            const flySpeed = f.get("fly_speed");
+            const labelStyle = f.get("label_style") || (flySpeed ? "card" : "legacy");
+            if (labelStyle !== "card") return;
+
+            const zoneName = f.get("zone_name");
+            if (!zoneName) return;
+
+            const geom = f.getGeometry();
+            if (!geom?.getInteriorPoint) return;
+
+            const coord = geom.getInteriorPoint().getCoordinates();
+            const overlay = new Overlay({
+                element: this.createZoneCardLabelElement(zoneName, flySpeed),
+                position: coord,
+                positioning: "center-center",
+                stopEvent: false,
+            });
+            this.kmap.map.addOverlay(overlay);
+            this.labelOverlays.push(overlay);
+        });
+    }
+
+    initMap(location, target, options = {}) {
+        const { interactive = false } = options;
         let level = 16;
         let coordinate = util.wktCastGeom(location).getFirstCoordinate();
-        // 详情页仅展示地块:禁用拖拽、滚轮缩放及触摸缩放
+        // dragPan / mouseWheelZoom 需在 Map 构造时传入,interactive 为 true 时才能拖拽与缩放
         this.kmap = new KMap.Map(
             target,
             level,
@@ -92,10 +198,10 @@ class AreaMap {
             8,
             22,
             undefined,
-            false,
-            false
+            interactive,
+            interactive
         );
-        if (this.kmap?.map) {
+        if (!interactive && this.kmap?.map) {
             this.kmap.map.getInteractions().forEach((i) => i.setActive(false));
         }
         let xyz2 = config.base_img_url3 + "map/lby/{z}/{x}/{y}.png";
@@ -112,8 +218,9 @@ class AreaMap {
         this.initZones([{ zone_geometry: rangeWkt }]);
     }
 
-    /** @param {{ zone_geometry?: string, zone_name?: string }[]} zones */
+    /** @param {{ zone_geometry?: string, zone_name?: string, fly_speed?: string, fill_color?: string, stroke_color?: string, label_style?: 'card'|'simple' }[]} zones */
     initZones(zones) {
+        this.clearLabelOverlays();
         if (this.gardenPolygonLayer.source) {
             this.gardenPolygonLayer.source.clear();
         }
@@ -134,12 +241,17 @@ class AreaMap {
             try {
                 const f = newAreaFeature({ geomWkt: wkt }, "geomWkt");
                 f.set("zone_name", zone.zone_name ?? "");
+                if (zone.fly_speed) f.set("fly_speed", zone.fly_speed);
+                if (zone.fill_color) f.set("fill_color", zone.fill_color);
+                if (zone.stroke_color) f.set("stroke_color", zone.stroke_color);
+                if (zone.label_style) f.set("label_style", zone.label_style);
                 this.gardenPolygonLayer.source.addFeature(f);
             } catch (e) {
                 console.warn("[AreaMap] zone_geometry parse failed", e);
             }
         });
 
+        this.syncLabelOverlays();
         this.fitView();
     }
 
@@ -193,7 +305,7 @@ class AreaMap {
         this.gardenPolygonLayer.source.forEachFeature((f) => {
             if (f.get("organId") == gardenId) {
                 const extent = f.getGeometry().getExtent()
-                this.kmap.getView().fit(extent, { padding: [160, 60, 340, 60], duration: hasMapAnimate ? 1500 : 0 });
+                this.kmap.getView().fit(extent, { padding: [60, 60, 60, 60], duration: hasMapAnimate ? 1500 : 0 });
                 const currentZoom = this.kmap.getView().getZoom();
                 if (currentZoom > 16) {
                     // this.kmap.getView().setZoom(16);
@@ -207,6 +319,7 @@ class AreaMap {
     }
 
     destroyMap() {
+        this.clearLabelOverlays();
         if (this.gardenPolygonLayer?.source) {
             this.gardenPolygonLayer.source.clear();
         }

+ 109 - 52
src/views/old_mini/work_detail/components/mapInfo.vue

@@ -1,7 +1,7 @@
 <template>
-    <div class="map-info">
-        <!-- <div class="popup-title" v-if="showTitle">{{ t('执行区域') }}</div> -->
-        <div class="map-box">
+    <div class="view-area-page">
+        <custom-header :name="t('查看区域')" isGoBack @goback="handleBack" />
+        <div class="map-wrapper">
             <div class="map" ref="mapContainer"></div>
         </div>
     </div>
@@ -9,79 +9,136 @@
 
 <script setup>
 import { useI18n } from "@/i18n";
-const { t } = useI18n();
-import { ref, nextTick, onMounted, watch } from "vue";
+import customHeader from "@/components/customHeader.vue";
+import { ref, nextTick, onMounted, onActivated, onDeactivated, onBeforeUnmount } from "vue";
+import { useRouter } from "vue-router";
+import WKT from "ol/format/WKT.js";
 import AreaMap from "./areaMap.js";
 
-const props = defineProps({
-    rangeWkt: {
-        type: [Number, String],
-        default: null,
-    },
-    showTitle: {
-        type: Boolean,
-        default: true,
-    },
-});
+const { t } = useI18n();
+const router = useRouter();
 
 const mapContainer = ref(null);
 const areaMap = new AreaMap();
+const wktFmt = new WKT();
+const MAP_CENTER_FALLBACK = "POINT(110.479 29.128)";
 
-// 加载农场地图信息
-const loadFarmMap = async () => {
-    if (!props.rangeWkt) return;
-
-    try {
-        const point = props.rangeWkt;
+/** 临时 mock 数据,后续替换为接口返回 */
+const MOCK_ZONES = [
+    {
+        zone_geometry:
+            "POLYGON((110.4735 29.1325, 110.4765 29.1340, 110.4785 29.1310, 110.4755 29.1295, 110.4735 29.1325))",
+        zone_name: "04/19-分区一",
+        fly_speed: "5.2m/s",
+        fill_color: "rgba(224, 49, 49, 0.45)",
+        stroke_color: "#E03131",
+        label_style: "card",
+    },
+    {
+        zone_geometry:
+            "POLYGON((110.4765 29.1290, 110.4795 29.1305, 110.4815 29.1275, 110.4785 29.1260, 110.4765 29.1290))",
+        zone_name: "04/20-分区二",
+        fly_speed: "4.8m/s",
+        fill_color: "rgba(224, 49, 49, 0.45)",
+        stroke_color: "#E03131",
+        label_style: "card",
+    },
+    {
+        zone_geometry:
+            "POLYGON((110.4795 29.1315, 110.4825 29.1330, 110.4845 29.1300, 110.4815 29.1285, 110.4795 29.1315))",
+        zone_name: "04/21-分区三",
+        fly_speed: "6.0m/s",
+        fill_color: "rgba(224, 49, 49, 0.45)",
+        stroke_color: "#E03131",
+        label_style: "card",
+    },
+    {
+        zone_geometry:
+            "POLYGON((110.4710 29.1280, 110.4740 29.1295, 110.4755 29.1265, 110.4725 29.1250, 110.4710 29.1280))",
+        zone_name: "妃子笑",
+        fill_color: "rgba(55, 55, 55, 0.55)",
+        stroke_color: "#FFFFFF",
+        label_style: "simple",
+    },
+    {
+        zone_geometry:
+            "POLYGON((110.4820 29.1255, 110.4850 29.1270, 110.4865 29.1240, 110.4835 29.1225, 110.4820 29.1255))",
+        zone_name: "04/22-分区四",
+        fly_speed: "5.5m/s",
+        fill_color: "rgba(120, 45, 45, 0.55)",
+        stroke_color: "#E03131",
+        label_style: "card",
+    },
+];
 
-        nextTick(() => {
-            // 如果地图已经初始化,则更新中心点和地块;否则初始化地图
-            if (areaMap.kmap) {
-                areaMap.initLayer(point);
-            } else if (point && mapContainer.value) {
-                areaMap.initMap(point, mapContainer.value);
-                areaMap.initLayer(point);
-            }
-        });
-    } catch (e) {
-        // 忽略地图加载错误,避免影响主流程
+function wktCenterPointFromZones(zones) {
+    const list = Array.isArray(zones) ? zones : [];
+    for (const zone of list) {
+        const wkt = zone?.zone_geometry;
+        if (!wkt || typeof wkt !== "string") continue;
+        try {
+            const c = wktFmt.readGeometry(wkt.trim()).getFirstCoordinate();
+            return `POINT(${c[0]} ${c[1]})`;
+        } catch {
+            /* try next zone */
+        }
     }
+    return MAP_CENTER_FALLBACK;
+}
+
+const destroyMap = () => {
+    areaMap.destroyMap();
+};
+
+const initMap = () => {
+    nextTick(() => {
+        if (!mapContainer.value) return;
+        const zones = MOCK_ZONES;
+        areaMap.destroyMap();
+        areaMap.initMap(wktCenterPointFromZones(zones), mapContainer.value, { interactive: true });
+        areaMap.initZones(zones);
+    });
+};
+
+const handleBack = () => {
+    router.back();
 };
 
 onMounted(() => {
-    loadFarmMap();
+    initMap();
 });
 
-// rangeWkt 变化时重新加载地图
-watch(
-    () => props.rangeWkt,
-    () => {
-        loadFarmMap();
-    }
-);
+onActivated(() => {
+    initMap();
+});
+
+onDeactivated(() => {
+    destroyMap();
+});
+
+onBeforeUnmount(() => {
+    destroyMap();
+});
 </script>
 
 <style lang="scss" scoped>
-.map-info {
+.view-area-page {
     width: 100%;
+    height: 100vh;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+    background: #f2f3f5;
 }
-    .popup-title {
-        text-align: center;
-        font-size: 24px;
-        font-family: "PangMenZhengDao";
-        padding-bottom: 12px;
-    }
 
-.map-box {
-    width: 100%;
-    height: 350px;
+.map-wrapper {
+    flex: 1;
+    min-height: 0;
     position: relative;
 
     .map {
         width: 100%;
         height: 100%;
-        clip-path: inset(0px round 5px);
-        pointer-events: none;
     }
 }
 </style>

+ 188 - 393
src/views/old_mini/work_detail/index.vue

@@ -1,28 +1,32 @@
 <template>
     <div class="work-detail">
-        <custom-header :name="$t('workDetail.title')" v-if="!miniJson?.hideDraw" :showClose="false" isGoBack @goback="handleBack" />
+        <custom-header :name="$t('workDetail.title')" v-if="!miniJson?.hideDraw" :showClose="false" isGoBack
+            @goback="handleBack" />
 
         <div class="work-detail-content">
             <!-- 顶部状态 -->
-            <div class="content-status" :class="['status-' + farmData?.work_status]">
+            <div class="content-status" :style="getContentStatusStyle(farmData)">
                 <div class="status-l">
-                    <div class="status-title">{{ farmData.work_name }}</div>
-                    <!-- <div class="status-sub" v-if="triggerDateText && (detail?.flowStatus == -1 || detail?.flowStatus == -2)">
-                        执行时间已经过去 {{ Math.abs(daysDiff) }} 天了
+                    <div class="status-title">
+                        <span>{{ farmData.work_name }}</span>
+                        <div class="status-tag" :style="statusTagStyle[farmData?.farm_work_type]">{{ farmWorkTypeObj[farmData?.farm_work_type] }}</div>
                     </div>
-                    <div class="status-sub" v-if="detail?.flowStatus === 3 && getAuditStatusPriority(detail?.executeEvidenceAuditStatus) !== 2">
-                        04/19 执行最佳
+                    <div class="status-hint-card" v-if="farmData?.work_status === 0">
+                        <div class="status-hint-text">{{ farmData?.best_time }}</div>
+                        <div class="status-hint-question">
+                            <el-icon class="status-hint-link-icon">
+                                <Link />
+                            </el-icon>
+                            <span class="status-hint-question-text">{{ farmData.interaction_issue }}</span>
+                        </div>
                     </div>
-                    <div class="status-sub" v-if="!detail?.flowStatus || detail?.flowStatus === 0">
-                        预计{{ detail?.executeDate || "--" }}执行,执行时间需巡园校准
-                    </div> -->
-                    <div class="status-sub">
+                    <div class="status-sub" :style="getFarmWorkTypeColorStyle(farmData)" v-else>
                         {{ farmData.best_time }}
                     </div>
                 </div>
             </div>
 
-            <div class="work-wrap has-bottom warning-info-show">
+            <div class="work-wrap has-bottom" :style="farmData.work_status === 0 ? 'margin-top: 35px;' : ''">
                 <!-- 农事组信息 -->
                 <div class="group-info group-box" v-if="farmData.interaction_reason">
                     <div class="group-name">
@@ -30,131 +34,22 @@
                     </div>
                 </div>
 
-                <!-- 每一段农事 -->
-                <!-- <div v-for="(prescription, index) in stageList" :key="index" class="box-wrap stage-card">
-                    <div class="work-info">
-                        <div class="stage-header">
-                            <div class="stage-title">{{ detail.farmWorkName }}</div>
-                        </div>
-
-                        <div class="stage-info">
-                            <div class="form-item">
-                                <div class="item-name">{{ $t('workDetail.purpose') }}</div>
-                                <div class="item-text">
-                                    {{ prescription.purpose || prescription.purposeName || "--" }}
-                                </div>
-                            </div>
-                            <div class="form-item">
-                                <div class="item-name">{{ $t('农事时间') }}</div>
-                                <div class="item-text">
-                                    {{ detail.executeDate || "--" }}
-                                </div>
-                            </div>
-                            <div class="form-item">
-                                <div class="item-name">{{ $t('执行区域') }}</div>
-                                <div class="item-text light-text area-text">
-                                    {{ detail?.executionRegion?.regionName }}种植区域
-                                    <div class="area-btn" v-if="detail?.executionRegion?.regionRange" @click="handleViewArea">{{ $t('查看区域') }}</div>
-                                    <div class="area-btn area-btn-right" @click="toDraw" v-if="!detail?.executionRegion?.regionRange && !miniJson?.hideDraw">{{ $t('建议勾选') }}<el-icon><ArrowRight /></el-icon></div>
-                                </div>
-                            </div>
-                            <div class="form-item">
-                                <div class="item-name">{{ $t('workDetail.notes') }}</div>
-                                <div class="item-text">
-                                    {{ detail.remark || "--" }}
-                                </div>
-                            </div>
-                            <div class="form-item" v-if="hasAnyAvailableExecutionMethod(prescription)">
-                                <div class="item-name">{{ $t('药肥处方') }}</div>
-                            </div>
-                        </div>
-
-                        <div class="stage-tabs" v-if="hasAnyAvailableExecutionMethod(prescription)">
-                            <div v-for="tab in getAvailableExecutionTabs(prescription)" :key="tab.value" class="tab-pill"
-                                :class="{ active: getStageExecutionMethod(index) === tab.value }"
-                                @click="changeExecutionMethod(index, tab.value)">
-                                {{ tab.label }}
-                            </div>
-                        </div>
-
-                        <div class="prescription-wrap"
-                            v-if="prescription.pesticideList && prescription.pesticideList.length && hasAnyAvailableExecutionMethod(prescription)">
-                            <div class="prescription-table">
-                                <div class="table-header">
-                                    <div class="col col-type">{{ $t('使用功效') }}</div>
-                                    <div class="col col-name">{{ $t('药肥名称') }}</div>
-                                    <div class="col col-ratio">{{ $t('药肥配比') }}</div>
-                                </div>
-
-                                <div v-for="(item, i) in prescription.pesticideList" :key="i" class="table-row">
-                                    <div class="col col-type">
-                                        {{ item.typeName || "--" }}
-                                    </div>
-                                    <div class="col col-name">
-                                        {{ item.name || item.pesticideFertilizerName || "--" }}
-                                    </div>
-                                    <div class="col col-ratio">
-                                        {{ getPesticideParam(item, index)?.ratio || "--" }}倍
-                                    </div>
-                                </div>
-                            </div>
-
-                            <div v-if="hasRemark(prescription, index)" class="prescription-remark">
-                                <span v-for="(item, idx) in [prescription.pesticideList[0]]" :key="idx">
-                                    <template v-if="getParamRemark(item, index)">
-                                        {{ getParamRemark(item, index) }}
-                                        <br />
-                                    </template>
-</span>
-</div>
-</div>
-</div>
-
-
-<div class="work-info photo-box" v-if="prescription.cropAlbum && prescription.cropAlbum.length">
-    <div class="photo-title">{{ $t('农事凭证') }}</div>
-    <div class="tips-text" v-if="detail?.imageAuditRejectReason">{{ detail?.imageAuditRejectReason }}</div>
-    <div class="photo-sub-title" v-if="info?.appType === 1">来自于 {{ detail?.executorOrganizationName || "--" }}</div>
-    <div class="photo-img-wrap">
-        <photo-provider :photo-closable="true">
-            <photo-consumer v-for="(src, index) in prescription.cropAlbum" intro="农事凭证" :key="index"
-                :src="base_img_url2 + src.filename">
-                <div class="photo-img">
-                    <img :src="base_img_url2 + src.filename" />
-                    <div class="fail-icon" v-if="failIndex(index) === 2">
-                        <el-icon size="24" color="#FF953D">
-                            <WarningFilled />
-                        </el-icon>
-                        <div class="fail-icon-text">{{ $t('审核失败') }}</div>
-                    </div>
-                </div>
-            </photo-consumer>
-        </photo-provider>
-    </div>
-</div>
-</div> -->
-
-
                 <div class="box-wrap stage-card">
                     <div class="work-info">
-                        <div class="map-box">
+                        <div class="map-box" @click="handleViewArea">
                             <div class="map-title">{{ $t('workDetail.executionArea') }}</div>
                             <div class="map-container" ref="mapContainer"></div>
                         </div>
                         <div class="area-list">
-                            <div
-                                v-for="(zone, zoneIndex) in farmZones"
-                                :key="`${zone.zone_name || 'zone'}-${zoneIndex}`"
-                                class="area-item"
-                            >
+                            <div v-for="(zone, zoneIndex) in farmZones"
+                                :key="`${zone.zone_name || 'zone'}-${zoneIndex}`" class="area-item">
                                 <div class="area-l">
                                     {{ zone.zone_name }}
                                     <span> {{ zone.execute_time }}</span>
-                                    <span
-                                        class="area-tag"
-                                        :style="backgroundFarmWorkStatus(farmData.work_status)"
-                                    >{{ workStatusObj[farmData.work_status] }}</span>
+                                    <span class="area-tag" :style="backgroundFarmWorkStatus(farmData.work_status)">{{
+                                        workStatusObj[farmData.work_status] }}</span>
                                 </div>
+                                <div class="area-r" :style="{background:farmData?.work_status === 6 ? '#37C11B' : '#2199F8'}">{{ farmData?.work_status === 6 ? '溯源认证' : '我已完成' }}</div>
                             </div>
                         </div>
                         <!-- <div class="ecological-plant-card">
@@ -181,7 +76,8 @@
                             <div class="info-value">{{ farmData.work_reason_detail }}</div>
                         </div>
                         <div class="info-item">
-                            <div class="info-title"><span class="title-block"></span>{{ $t('workDetail.purpose') }}</div>
+                            <div class="info-title"><span class="title-block"></span>{{ $t('workDetail.purpose') }}
+                            </div>
                             <div class="info-value">{{ farmData.work_purpose }}</div>
                         </div>
                         <div class="info-item">
@@ -189,11 +85,13 @@
                             <div class="info-value">{{ farmData.precautions }}</div>
                         </div>
                         <div class="info-item">
-                            <div class="info-title"><span class="title-block"></span>{{ $t('workDetail.prescription') }}</div>
+                            <div class="info-title"><span class="title-block"></span>{{ $t('workDetail.prescription') }}
+                            </div>
                             <div class="info-value">{{ farmData.drug_prescription }}</div>
                         </div>
                         <div class="info-item">
-                            <div class="info-title"><span class="title-block"></span>{{ $t('workDetail.executionMethod') }}</div>
+                            <div class="info-title"><span class="title-block"></span>{{ $t('workDetail.executionMethod')
+                                }}</div>
                             <div class="info-value">{{ farmData.execution_method }}</div>
                         </div>
                     </div>
@@ -211,26 +109,16 @@
                 </div> -->
 
                 <!-- 底部按钮 -->
-                <!-- <div class="fixed-btn-wrap center-btn" v-if="info?.appType === 2">
-                    <div class="fixed-btn" @click="handleConvert">
-                        转发农事
-                    </div>
-                </div>
-
-                <div class="fixed-btn-wrap execute-action">
+                <!-- <div class="fixed-btn-wrap execute-action">
                     <div class="action-item second" v-if="!miniJson?.hideDraw" @click="handleConvert">{{ $t('转发给执行人员') }}</div>
                 </div> -->
+
                 <!-- <div class="action-item primary" @click="handleExecute">{{ $t('溯源认证') }}</div> -->
             </div>
         </div>
         <ExecutePopup ref="executePopupRef" @executeSuccess="getDetail" />
-
         <upload-tips v-model:show="showUploadTipsPopup" />
     </div>
-    <!-- 执行区域地图弹窗 -->
-    <popup v-model:show="showMapPopup" closeable class="map-popup">
-        <map-info :rangeWkt="detail?.executionRegion?.regionRange" />
-    </popup>
 </template>
 
 <script setup>
@@ -244,23 +132,14 @@ import { formatDate } from "@/common/commonFun";
 import ExecutePopup from "./components/executePopup.vue";
 import { base_img_url2 } from "@/api/config";
 import UploadTips from "@/components/popup/uploadTips.vue";
-import { Popup } from "vant";
-import MapInfo from "./components/mapInfo.vue";
 import { useRoute } from "vue-router";
 import AreaMap from "./components/areaMap.js";
 import WKT from "ol/format/WKT.js";
 import { time } from "echarts";
-import imgFq1 from "@/assets/img/common/fq-1.png";
-import imgFq2 from "@/assets/img/common/fq-2.png";
-import imgYz1 from "@/assets/img/common/yz-1.png";
-import imgYz2 from "@/assets/img/common/yz-2.png";
-import imgJf1 from "@/assets/img/common/jf-1.png";
-import imgJf2 from "@/assets/img/common/jf-2.png";
 
 const route = useRoute();
 const { locale } = useI18n();
 const showUploadTipsPopup = ref(false);
-const headerTitle = ref('');
 const router = useRouter();
 // const info = JSON.parse(localStorage.getItem("localUserInfo") || "{}");
 const info = { appType: 1 };
@@ -318,13 +197,6 @@ onMounted(() => {
 });
 
 const miniJson = ref(null);
-/** 生态种植卡片:方式文案(可后续接接口字段) */
-const ecologicalPlantingMethodText = ref("某某方式");
-/** 与设计稿一致的四宫格示例图 */
-const ecologicalPlantThumbUrls = ref([imgFq1, imgFq2]);
-const ecologicalExecutorOrg = computed(
-    () => detail.value?.executorOrganizationName || "某某某农资机构"
-);
 const farmData = ref({});
 
 const wktFmt = new WKT();
@@ -377,26 +249,12 @@ onBeforeUnmount(() => {
 });
 
 onActivated(() => {
-    headerTitle.value = route.query?.title || '返青追肥';
-    if (headerTitle.value === '返青追肥') {
-        ecologicalPlantThumbUrls.value = [imgFq1, imgFq2]
-    } else if (headerTitle.value === '移栽防治') {
-        ecologicalPlantThumbUrls.value = [imgYz1, imgYz2]
-    } else {
-        ecologicalPlantThumbUrls.value = [imgJf1, imgJf2]
-    }
-    // if (route.query?.miniJson) {
-    //     const miniJsonObj = JSON.parse(route.query.miniJson);
-    //     miniJson.value = JSON.parse(miniJsonObj.paramsPage);
-    // } else {
-    //     miniJson.value = null;
-    // }
     getDetail();
 });
 
 const workStatusObj = {
-    0: "待校准",
-    1: "机动执行",
+    0: "时间待校准",
+    1: "触发待巡园",
     2: "待执行",
     3: "未激活",
     4: "已认证",
@@ -404,16 +262,24 @@ const workStatusObj = {
     6: "已执行",
 }
 
+const farmWorkTypeObj = {
+    1: "标准农事",
+    2: "机动农事",
+    3: "气象预警农事",
+    4: "气象恢复农事",
+    5: "异常农事",
+    6: "标准施肥类",
+    7: "标准防治类",
+    8: "标准调节类",
+}
+
 const backgroundFarmWorkStatus = (status) => {
     let background = 'rgba(33, 153, 248, 0.1)';
     let color = '#2199F8';
-    if (status === 0 || status === 1) {
-        background = 'rgba(255, 149, 61, 0.1)';
-        color = '#FF953D';
-    }else if (status === 4) {
+    if (status === 6 || status === 4) {
         background = 'rgba(55, 193, 27, 0.1)';
         color = '#37C11B';
-    }else if (status === 3 || status === 5) {
+    } else if (status === 3 || status === 5) {
         background = 'rgba(98, 98, 98, 0.1)';
         color = '#626262';
     }
@@ -431,51 +297,45 @@ const getDetail = () => {
             initWorkDetailMap();
         }
     })
-    // if (!miniJson.value) return;
-    // const { farmWorkLibId, farmId, recordId, reproductiveId } = miniJson.value;
-    // VE_API.z_farm_work_record
-    //     .getDetailById({ farmWorkLibId, farmId, farmWorkRecordId: recordId, reproductiveId })
-    //     .then(({ data }) => {
-    //         const inner =
-    //             data?.detail && typeof data.detail === "object"
-    //                 ? { ...data.detail }
-    //                 : {};
-    //         detail.value = {
-    //             ...inner,
-    //             post: data?.post ?? null,
-    //             executionRegion: data?.executionRegion ?? null,
-    //             expertNameFromFarmBasicInfo:
-    //                 data?.expertNameFromFarmBasicInfo ?? "",
-    //             rangeWkt: data?.rangeWkt ?? null,
-    //         };
-
-    //         // 地图
-    //         areaMap.initMap("POINT(113.1093017627431 22.57454083668)", mapContainer.value);
-    //     });
 };
 
-watch(locale, () => {
-    getDetail();
-});
-
-// 计算距离执行时间的天数差
-const daysDiff = computed(() => {
-    if (!detail.value?.executeDate) {
-        return '--';
-    }
-
-    const executeDate = new Date(detail.value.executeDate);
-    const today = new Date();
-
-    // 将时间设置为 00:00:00,只比较日期
-    executeDate.setHours(0, 0, 0, 0);
-    today.setHours(0, 0, 0, 0);
+const handleExecute = () => {
+    // const today = new Date();
+    // const executeDate = new Date(detail.value.executeDate);
+    // if (executeDate.getTime() > today.getTime()) {
+    //     ElMessage.warning('未到农事执行时间,无法溯源认证');
+    //     return;
+    // }
+    const evidenceList = normalizeCropAlbum(
+        detail.value?.confirmPicture?.length
+            ? detail.value.confirmPicture
+            : detail.value.executeEvidence
+    ).map((item) => item.filename);
+    const auditStatusList = Array.isArray(detail.value?.executeEvidenceAuditStatus)
+        ? detail.value.executeEvidenceAuditStatus
+        : [];
 
-    // 计算天数差(毫秒转天数)
-    const diffTime = executeDate.getTime() - today.getTime();
-    const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
+    let imgs = []
+    evidenceList.forEach((item, index) => {
+        imgs.push({
+            url: base_img_url2 + item,
+            filePath: item,
+            status: auditStatusList[index] === 2 ? 'failed' : 'success',
+            message: auditStatusList[index] === 2 ? '审核失败' : '审核成功',
+        });
+    });
+    console.log("evideimgsnceList", imgs);
+    const isEdit = evidenceList?.length > 0 ? true : false;
+    executePopupRef.value.openPopup(miniJson.value.recordId, {
+        evidenceList: imgs,
+        isEdit: isEdit,
+        executeDate: detail.value.executeDate,
+        executorOrganizationName: detail.value.executorOrganizationName,
+    });
+};
 
-    return diffDays;
+watch(locale, () => {
+    getDetail();
 });
 
 // 执行方式 Tab 配置
@@ -510,16 +370,59 @@ const getAvailableExecutionTabs = (prescription) => {
     );
 };
 
-const hasAnyAvailableExecutionMethod = (prescription) => {
-    return getAvailableExecutionTabs(prescription).length > 0;
+const statusTagStyle = {
+    3: {
+        color: '#FF953D',
+    },
+    4: {
+        color: '#FF953D',
+    },
+    5: {
+        color: '#FF6A6A',
+    },
 };
 
+const getFarmWorkTypeColorStyle = (farmData) => {
+    const type = Number(farmData?.farm_work_type);
+    const status = Number(farmData?.work_status);
+    let color = '#2199F8';
+    if (status === 2) {
+        if(type === 3 || type === 4) {
+            color = '#FF943D';
+        } else if(type === 5) {
+            color = '#FF6A6A';
+        } else {
+            color = '#2199F8';
+        }
+    }else if (status === 3) {
+        color = 'rgba(62, 61, 61, 0.8)';
+    }
+    return {
+        color,
+    };
+};
 
-const triggerDateText = computed(() => {
-    if (!detail.value.executeDate) return "";
-    const d = formatDate(detail.value.executeDate);
-    return d.replace(/-/g, ".");
-});
+/** 顶部 content-status 背景色(::after 通过 CSS 变量读取) */
+const getContentStatusStyle = (farmData) => {
+    const type = Number(farmData?.farm_work_type);// 农事类型
+    const status = Number(farmData?.work_status);// 农事状态
+    let background = '#2199F8';
+
+    if (status === 2) {
+        if(type === 3 || type === 4) {
+            background = '#FF943D';
+        } else if(type === 5) {
+            background = '#FF6A6A';
+        } else {
+            background = '#2199F8';
+        }
+    } else if (status === 3) {
+        background = '#C7C7C7';
+    }
+    return {
+        "--content-status-bg": background,
+    };
+};
 
 /**
  * 展示用「分段」列表:detail.pesticideList 或 prescriptionList 推导
@@ -546,103 +449,13 @@ const stageList = computed(() => {
 });
 
 
-const hasRemark = (prescription, stageIndex) => {
-    if (!prescription?.pesticideList || !Array.isArray(prescription.pesticideList)) return false;
-    const currentMethod = getStageExecutionMethod(stageIndex);
-    return prescription.pesticideList.some((item) => {
-        if (!item.params || !Array.isArray(item.params)) return false;
-        const p = item.params.find((param) => param.executionMethod === currentMethod);
-        return !!(p && p.remark);
-    });
-};
-
-const handleTagType = (tagType) => {
-    if (tagType == 0) return "待触发";
-    if (tagType == -1) return "已过期";
-    if (tagType == -2) return "已过期";
-    if (tagType == 3) {
-        const status = getAuditStatusPriority(detail.value?.executeEvidenceAuditStatus);
-        if (status === 2) {
-            return "审核失败";
-        }
-        return "待认证"
-    }
-    if (tagType == 5) {
-        const status = getAuditStatusPriority(detail.value?.executeEvidenceAuditStatus);
-        if (status === 2) {
-            return "审核失败";
-        }
-        if (status === 0) {
-            return "审核中";
-        }
-        return "已认证";
-    }
-    return "待触发"
-}
-
-// 审核状态优先级:2 > 0 > 1
-const getAuditStatusPriority = (auditStatusList) => {
-    if (!Array.isArray(auditStatusList) || !auditStatusList.length) return 1;
-    const normalized = auditStatusList.map((x) => Number(x)).filter((x) => [0, 1, 2].includes(x));
-    if (!normalized.length) return 1;
-    if (normalized.includes(0)) return 0;
-    if (normalized.includes(2)) return 2;
-    return 1;
-};
-
-// 审核是否失败
-const failIndex = (index) => {
-    return detail.value?.executeEvidenceAuditStatus[index]
-}
-
-const handleExecute = () => {
-    // const today = new Date();
-    // const executeDate = new Date(detail.value.executeDate);
-    // if (executeDate.getTime() > today.getTime()) {
-    //     ElMessage.warning('未到农事执行时间,无法溯源认证');
-    //     return;
-    // }
-    const evidenceList = normalizeCropAlbum(
-        detail.value?.confirmPicture?.length
-            ? detail.value.confirmPicture
-            : detail.value.executeEvidence
-    ).map((item) => item.filename);
-    const auditStatusList = Array.isArray(detail.value?.executeEvidenceAuditStatus)
-        ? detail.value.executeEvidenceAuditStatus
-        : [];
-
-    let imgs = []
-    evidenceList.forEach((item, index) => {
-        imgs.push({
-            url: base_img_url2 + item,
-            filePath: item,
-            status: auditStatusList[index] === 2 ? 'failed' : 'success',
-            message: auditStatusList[index] === 2 ? '审核失败' : '审核成功',
-        });
-    });
-    console.log("evideimgsnceList", imgs);
-    const isEdit = evidenceList?.length > 0 ? true : false;
-    executePopupRef.value.openPopup(miniJson.value.recordId, {
-        evidenceList: imgs,
-        isEdit: isEdit,
-        executeDate: detail.value.executeDate,
-        executorOrganizationName: detail.value.executorOrganizationName,
-    });
-};
-
-
-const showMapPopup = ref(false);
 
 const handleViewArea = () => {
-    showMapPopup.value = true;
-}
-
-const toDraw = () => {
     router.push({
-        path: "/draw_area",
+        path: "/view_area",
         query: {
             subjectId: localStorage.getItem('selectedFarmId'),
-            varietyId: miniJson.value.typeId,
+            varietyId: 2,
         },
     });
 }
@@ -686,27 +499,7 @@ const getPesticideParam = (item, stageIndex) => {
     );
 };
 
-const getParamRemark = (item, stageIndex) => {
-    const param = getPesticideParam(item, stageIndex);
-    return param?.remark || item.remark || "";
-};
-
-const changeExecutionMethod = (stageIndex, value) => {
-    const stage = stageList.value?.[stageIndex];
-    const availableTabs = getAvailableExecutionTabs(stage);
-    const isAllowed = availableTabs.some(
-        (tab) => Number(tab.value) === Number(value)
-    );
-    if (!isAllowed) return;
-
-    stageExecutionMethods.value = {
-        ...stageExecutionMethods.value,
-        [stageIndex]: value
-    };
-};
-
 // 地图
-
 const mapContainer = ref(null);
 const areaMap = new AreaMap();
 </script>
@@ -739,70 +532,74 @@ const areaMap = new AreaMap();
         left: 0;
         top: 0;
         height: 140px;
-        background: #C7C7C7;
+        background: var(--content-status-bg, #2199F8);
         width: 100%;
     }
 
     .status-l {
         .status-title {
-            font-size: 22px;
+            font-size: 21px;
+            display: flex;
+            align-items: center;
+            gap: 9px;
+
+            .status-tag {
+                font-size: 12px;
+                color: #2199F8;
+                background: #fff;
+                border-radius: 2px;
+                padding: 2px 5px;
+                min-width: fit-content;
+            }
         }
 
         .status-sub {
             margin-top: 10px;
-            font-size: 12px;
-            padding: 0 8px;
+            font-size: 13px;
+            padding: 2px 8px;
             background: #fff;
-            color: rgba(62, 61, 61, 0.8);
+            color: #2199F8;
             width: fit-content;
-            height: 26px;
-            line-height: 26px;
             border-radius: 2px;
         }
-    }
-
-    &.status-5 {
-        &::after {
-            background: #C7C7C7;
-        }
-    }
-
-    &.status-0, &.status-1 {
-        &::after {
-            background: #FF953D;
-        }
-    }
-
-    &.status-2 {
-        &::after {
-            background: #2199F8;
-        }
-    }
-
-    &.status-6 {
-        &::after {
-            background: #2199F8;
-        }
-    }
 
-    &.audit-2,
-    &.audit-0 {
-        &::after {
-            background: #FF953D;
-        }
-    }
-
-    &.audit-2 {
-        padding-top: 30px;
-    }
+        .status-hint-card {
+            margin-top: 10px;
+            background: #fff;
+            border-radius: 2px;
+            padding: 5px 8px;
+            box-sizing: border-box;
 
-    &.status-4 {
-        &::after {
-            background: #37C11B;
-        }
+            .status-hint-text {
+                font-size: 12px;
+                color: #626262;
+            }
 
-        .status-sub {
-            color: #37C11B;
+            .status-hint-question {
+                margin-top: 8px;
+                background: #2199f8;
+                border-radius: 4px;
+                padding: 6px 8px;
+                display: flex;
+                align-items: center;
+                gap: 6px;
+                color: #fff;
+
+                .status-hint-link-icon {
+                    flex-shrink: 0;
+                    font-size: 14px;
+                }
+
+                .status-hint-question-text {
+                    flex: 1;
+                    min-width: 0;
+                    font-size: 12px;
+                    text-decoration: underline;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                    white-space: nowrap;
+                }
+            }
         }
     }
 }
@@ -812,7 +609,6 @@ const areaMap = new AreaMap();
     top: 0;
     padding: 0 12px 12px;
     z-index: 2;
-
     // &.has-bottom {
     //     margin-bottom: 88px;
     // }
@@ -976,9 +772,10 @@ const areaMap = new AreaMap();
         border-radius: 6px;
 
         .area-l {
-            color: #000000;
+            display: flex;
+            align-items: center;
+            gap: 5px;
 
-            // font-weight: 500;
             .area-tag {
                 background: rgba(98, 98, 98, 0.1);
                 color: #626262;
@@ -991,7 +788,6 @@ const areaMap = new AreaMap();
                 display: inline-block;
             }
         }
-
         .area-r {
             background: #2199F8;
             color: #fff;
@@ -1003,13 +799,12 @@ const areaMap = new AreaMap();
             padding: 0 10px;
             border-radius: 20px;
         }
+
     }
 }
 
 .ecological-plant-card {
     margin-top: 10px;
-    // padding: 10px;
-    // background: rgba(244, 244, 244, 0.8);
     border-radius: 8px;
     text-align: left;
 }