lxf 1 день назад
Родитель
Сommit
56c9ba77d0

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


BIN
src/assets/img/home/report.png


+ 5 - 9
src/components/weatherInfo.vue

@@ -59,16 +59,12 @@
                     <div class="button-wrap" v-if="hasFarm">
                         <div class="button-item" @click="handleFarmInfo">
                             <img class="button-pre" src="@/assets/img/common/info.png" alt="">
-                            农场信息
+                            农场信息维护
                         </div>
-                        <div class="button-item">
-                            <img class="button-pre" src="@/assets/img/common/report.png" alt="">
-                            历史风险报告
-                        </div>
-                        <div class="button-item">
+                        <!-- <div class="button-item">
                             <img class="button-pre" src="@/assets/img/common/idea.png" alt="">
-                            土壤改良方案
-                        </div>
+                            种植档案管理
+                        </div> -->
                     </div>
                 </div>
             </div>
@@ -545,7 +541,7 @@ defineExpose({
         .button-item {
             border: 0.5px solid rgba(33, 153, 248, 0.5);
             display: flex;
-            border-radius: 20px;
+            border-radius: 4px;
             align-items: center;
             height: 28px;
             line-height: 28px;

+ 54 - 74
src/views/old_mini/growth_report/index.vue

@@ -38,13 +38,26 @@
                 <img class="header-img" src="@/assets/img/home/report.png" alt="" />
 
                 <div class="report-header">
+                    <div class="type-tabs report-tabs">
+                        <div class="type-item" :class="{ 'type-item-active': activeReportIndex === 0 }">作物长势</div>
+                        <div class="type-item" :class="{ 'type-item-active': activeReportIndex === 1 }">历史风险</div>
+                        <div class="type-item" :class="{ 'type-item-active': activeReportIndex === 2 }">土壤改良</div>
+                        <div class="type-item" :class="{ 'type-item-active': activeReportIndex === 3 }">种植建议</div>
+                    </div>
                     <div class="type-tabs" v-if="subjectData.length > 1">
                         <div
                             @click="handleTypeTabClick(item, index)"
                             class="type-item"
-                            v-for="(item, index) in subjectData"
+                            v-for="(item, index) in visibleSubjectData"
                             :class="{ 'type-item-active': activeSubjectIndex === index }"
                             :key="index">{{ item.speciesName }}</div>
+                    <div
+                        v-if="showSubjectToggle"
+                        class="subject-toggle"
+                        @click="typeTabsExpanded = !typeTabsExpanded"
+                    >
+                        {{ typeTabsExpanded ? "点击收起" : "点击展开更多" }}
+                    </div>
                     </div>
 
                     <div class="time-tag">{{ workItems?.[0]?.reportDate }}</div>
@@ -208,14 +221,6 @@
             </div>
         </div>
 
-        <!-- 首次进入页面的左滑查看提示遮罩 -->
-        <div class="swipe-guide-mask" v-if="showSwipeGuide" @click="closeSwipeGuide">
-            <div class="swipe-guide-content">
-                <img class="swipe-guide-icon" src="@/assets/img/home/point.png" alt="swipe" />
-                <div class="swipe-guide-text">左滑查看其它分区报告</div>
-            </div>
-        </div>
-
         <!-- 农场列表引导 -->
         <div class="mask-wrap" @click="closeTabMask" v-if="showTabMask"></div>
 
@@ -266,12 +271,8 @@ const handleAdjustPopup = () => {
 const isExpanded = ref(false);
 const weatherInfoRef = ref(null);
 
-// 首次进入页面的左滑提示遮罩
-const showSwipeGuide = ref(false);
 const showTabMask = ref(false);
-const pendingSwipeGuide = ref(false);
 const TAB_GUIDE_SHOWN_KEY = "GROWTH_REPORT_TAB_GUIDE_SHOWN";
-const SWIPE_GUIDE_KEY = "GROWTH_REPORT_SWIPE_GUIDE_SHOWN";
 const weatherExpanded = (isExpandedValue) => {
     isExpanded.value = isExpandedValue;
 };
@@ -346,20 +347,8 @@ onActivated(() => {
     // getResultReport();
 });
 
-// 关闭左滑提示遮罩
-const closeSwipeGuide = () => {
-    showSwipeGuide.value = false;
-};
-
 const closeTabMask = () => {
     showTabMask.value = false;
-    if (pendingSwipeGuide.value) {
-        setTimeout(() => {
-            showSwipeGuide.value = true;
-            pendingSwipeGuide.value = false;
-            localStorage.setItem(SWIPE_GUIDE_KEY, "1");
-        }, 500);
-    }
 };
 
 const userInfo = localStorage.getItem("localUserInfo");
@@ -451,12 +440,23 @@ const getDetail = () => {
 };
 
 const subjectData = ref([])
+const typeTabsExpanded = ref(false);
+const visibleSubjectData = computed(() => {
+    if (typeTabsExpanded.value) {
+        return subjectData.value;
+    }
+    return subjectData.value.slice(0, 4);
+});
+const showSubjectToggle = computed(() => subjectData.value.length > 4);
 
 const getSubjectData = async (id) => {
     const res = await VE_API.monitor.listFarmsBySubjectId({ subjectId: id });
-    subjectData.value = res.data || [];
+    // subjectData.value = res.data || [];
+    subjectData.value = [...res.data, ...res.data, ...res.data, ...res.data];
+    typeTabsExpanded.value = false;
 }
 
+const activeReportIndex = ref(0);
 const activeSubjectIndex = ref(0);
 const handleTypeTabClick = (item, index) => {
     activeSubjectIndex.value = index;
@@ -476,20 +476,13 @@ const getRegions = async () => {
         if (regionsData.value.length > 0) {
             hasReport.value = true;
             const hasShownTabGuide = localStorage.getItem(TAB_GUIDE_SHOWN_KEY) === "1";
-            const needSwipeGuide = !localStorage.getItem(SWIPE_GUIDE_KEY) && regionsData.value.length > 1;
 
-            // 首次进入且有分区数据:显示农场列表引导;左滑引导在其关闭后再显示
+            // 首次进入且有分区数据:显示农场列表引导
             if (!hasShownTabGuide) {
                 showTabMask.value = true;
                 localStorage.setItem(TAB_GUIDE_SHOWN_KEY, "1");
-                pendingSwipeGuide.value = needSwipeGuide;
             } else {
                 showTabMask.value = false;
-                pendingSwipeGuide.value = false;
-                if (needSwipeGuide) {
-                    showSwipeGuide.value = true;
-                    localStorage.setItem(SWIPE_GUIDE_KEY, "1");
-                }
             }
 
             // 切换农场tab回到当前农场tab
@@ -533,7 +526,6 @@ const getRegions = async () => {
             // 切换农场tab回到当前农场tab
             // weatherInfoRef.value && weatherInfoRef.value.handleGardenClick('current');
             showTabMask.value = false;
-            pendingSwipeGuide.value = false;
             hasReport.value = false;
         }
     });
@@ -733,40 +725,6 @@ onUnmounted(() => {
         }
     }
 
-    // 首次进入页面左滑提示遮罩
-    .swipe-guide-mask {
-        position: fixed;
-        left: 0;
-        top: 0;
-        width: 100%;
-        height: 100%;
-        background: rgba(0, 0, 0, 0.6);
-        z-index: 99999;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-
-        .swipe-guide-content {
-            display: flex;
-            flex-direction: column;
-            align-items: center;
-            justify-content: center;
-            color: #ffffff;
-            text-align: center;
-        }
-
-        .swipe-guide-icon {
-            width: 71px;
-            height: 79px;
-            object-fit: contain;
-            margin-bottom: 23px;
-        }
-
-        .swipe-guide-text {
-            font-size: 20px;
-        }
-    }
-
     .code-icon {
         position: absolute;
         right: 10px;
@@ -852,23 +810,35 @@ onUnmounted(() => {
         }
 
         .type-tabs {
-            background: #fff;
-            height: 38px;
+            background: rgba(255, 255, 255, 0.8);
             display: flex;
             align-items: center;
+            flex-wrap: wrap;
             gap: 8px;
             width: fit-content;
             border-radius: 5px;
-            padding: 0 5px;
+            padding: 5px;
             margin-bottom: 22px;
+            &.report-tabs {
+                padding: 0 5px;
+                height: 38px;
+                background: none;
+                margin-bottom: 6px;
+                .type-item {
+                    height: 34px;
+                    line-height: 34px;
+                    font-size: 14px;
+                    color: #858585;
+                }
+            }
             .type-item {
                 height: 28px;
                 line-height: 28px;
                 text-align: center;
                 padding: 0 6px;
                 min-width: 80px;
-                color: #858585;
-                background: #EEEEEE;
+                color: #9A9A9A;
+                background: #FFFFFF;
                 box-sizing: border-box;
                 border-radius: 2px;
                 &.type-item-active {
@@ -878,6 +848,16 @@ onUnmounted(() => {
             }
         }
 
+        .subject-toggle {
+            margin-top: 4px;
+            margin-bottom: 5px;
+            font-size: 14px;
+            color: rgba(0, 0, 0, 0.6);
+            width: 100%;
+            cursor: pointer;
+            text-align: center;
+        }
+
         .report-header {
             position: relative;
             padding-top: 148px;

+ 381 - 0
src/views/old_mini/monitor/subPages/farmInfo copy.vue

@@ -0,0 +1,381 @@
+<template>
+    <custom-header name="农场信息" bgColor="#f2f3f5"></custom-header>
+    <div class="farm-details-page">
+        <div class="map-wrap info-card">
+            <div class="map-area" ref="mapContainer"></div>
+            <div class="map-text" @click="handleEditMap">点击编辑地块</div>
+        </div>
+        <div class="info-box info-card">
+            <div class="section-header">
+                <div class="line-title">基本信息</div>
+                <div class="edit-btn-box">
+                    <div class="edit-btn" @click="handleAddVariety">新增品种</div>
+                    <div class="edit-btn" @click="handleEditFarmInfo">编辑信息</div>
+                </div>
+            </div>
+            <div class="info-list">
+                <div class="info-row">
+                    <span class="info-label">农场名称:</span>
+                    <span class="info-value">{{ farmInfo.subjectName }}</span>
+                </div>
+                <div class="info-row">
+                    <span class="info-label">联系人:</span>
+                    <span class="info-value">{{ farmInfo.contactName }}</span>
+                </div>
+                <div class="info-row center-row">
+                    <span class="info-label">联系电话:</span>
+                    <span class="info-value">{{ farmInfo.contactPhone }}</span>
+                </div>
+                <div class="info-row">
+                    <span class="info-label">种植面积:</span>
+                    <span class="info-value">{{ farmInfo.farmArea }}亩</span>
+                </div>
+                <div class="info-row">
+                    <span class="info-label">农场位置:</span>
+                    <span class="info-value">{{ farmInfo.farmAddress }}</span>
+                </div>
+                <div class="info-row">
+                    <span class="info-label">种植品种:</span>
+                    <div class="info-value crop-tags">
+                        <span v-for="crop in farmInfo.regionList" :key="crop.regionId" class="crop-tag">
+                            {{ crop.regionName }}
+                        </span>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="info-box info-card">
+            <div class="section-header">
+                <div class="line-title">农场设施</div>
+                <div class="edit-btn" @click="handleEditFarmFacility">编辑信息</div>
+            </div>
+            <div class="info-list">
+                <div class="info-row">
+                    <span class="info-label">灌溉方式:</span>
+                    <div class="info-value crop-tags">
+                        <span v-for="method in basicFarmInfo.irrigation" :key="method.code" class="crop-tag">
+                            {{ method.name }}
+                        </span>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <FarmInfoPopup ref="farmInfoPopupRef" :farmId="route.query.subjectId" @success="fetchFarmSubjectDetail" />
+</template>
+
+<script setup>
+import { ref, onMounted, nextTick } from "vue";
+import customHeader from "@/components/customHeader.vue";
+import { useRouter, useRoute } from "vue-router";
+import DrawRegionMap from "@/views/old_mini/interactionList/map/drawRegionMap.js";
+import * as util from "@/common/ol_common.js";
+import { ElMessage } from "element-plus";
+import { useStore } from "vuex";
+import FarmInfoPopup from "@/views/old_mini/home/components/farmInfoPopup.vue";
+
+const router = useRouter();
+const route = useRoute();
+const store = useStore();
+const farmInfo = ref({});
+const mapContainer = ref(null);
+const drawRegionMap = new DrawRegionMap();
+
+const initMap = () => {
+    if (!mapContainer.value) return;
+    if (drawRegionMap.kmap) return;
+
+    const info = farmInfo.value || {};
+
+    drawRegionMap.initMap(info.farmLocation, mapContainer.value, false, true, false);
+
+    // 回显农场区域,多边形 WKT 数组(有就画,没有就不画)
+    let geometryArr = [];
+
+    // 优先使用 regionList 里的 geom:有值才渲染
+    if (Array.isArray(info.regionList) && info.regionList.length > 0) {
+        info.regionList.forEach((item) => {
+            if (item?.geom) {
+                geometryArr.push(item?.geom)
+            }
+        });
+    }
+
+    if (geometryArr.length) {
+        // 农场信息页:地块用绿色展示;第三参留空表示面积仍按地块自动计算
+        drawRegionMap.setAreaGeometry(Array.from(geometryArr), true, undefined, {
+            fill: "rgba(0, 57, 44, 0.5)",
+            stroke: "#18AA8B",
+        });
+    }
+
+    // 在区域中心落一个点位(使用与勾画页相同的图标)
+    try {
+        const geom = util.wktCastGeom(info.farmLocation);
+        if (geom && typeof geom.getFirstCoordinate === "function") {
+            const coord = geom.getFirstCoordinate();
+            drawRegionMap.setMapPoint(coord);
+        }
+    } catch (e) {
+        // 解析失败则忽略点位
+    }
+};
+
+const destroyMap = () => {
+    if (drawRegionMap && drawRegionMap.kmap && drawRegionMap.destroyMap) {
+        drawRegionMap.destroyMap();
+    }
+};
+
+onMounted(() => {
+    fetchFarmSubjectDetail();
+    fetchBasicFarmFormData();
+});
+
+function fetchFarmSubjectDetail() {
+    VE_API.basic_farm.fetchFarmSubjectDetail({ subjectId: route.query.subjectId }).then(({ data }) => {
+        farmInfo.value = data || {};
+        nextTick(() => {
+            destroyMap();
+            initMap();
+        });
+    });
+}
+
+const basicFarmInfo = ref({});
+function fetchBasicFarmFormData() {
+    VE_API.basic_farm.fetchBasicFarmFormData({ subjectId: route.query.subjectId }).then(({ data, code }) => {
+        if (code === 0) {
+            basicFarmInfo.value = {
+                ...data,
+                irrigation: data.irrigationMethods.filter(item => item.selected),
+            }
+        }
+    });
+}
+
+const farmInfoPopupRef = ref(null);
+const handleEditFarmInfo = () => {
+    // // 回显地块:存到 polygonData,创建页会优先使用这里的数据
+    // if (data.geomWkt) {
+    //     const polygonData = {
+    //         geometryArr: [data.geomWkt],
+    //         mianji: data.mianji,
+    //         isConfirmed: true,
+    //     };
+    //     store.commit("home/SET_FARM_POLYGON", polygonData);
+    // } else {
+    //     store.commit("home/SET_FARM_POLYGON", null);
+    // }
+
+    // const params = {
+    //     ...farmInfo.value,
+    //     name: farmInfo.value.subjectName,
+    //     fzr: farmInfo.value.contactName,
+    //     tel: farmInfo.value.contactPhone,
+    //     mianji: farmInfo.value.farmArea,
+    //     address: farmInfo.value.farmAddress,
+    // };
+
+    // // 回显其他表单字段
+    // store.commit("home/SET_EDIT_FARM_DATA", params);
+
+    // // 带上 from=details,创建页提交/取消后能正确返回
+    // router.push(`/create_farm?type=edit&farmId=${route.query.subjectId}&from=details`);
+
+    farmInfoPopupRef.value.handleShow();
+};
+
+const handleEditFarmFacility = () => {
+    router.push(`/prescription?subjectId=${route.query.subjectId}`);
+};
+
+// 点击编辑地块
+const handleEditMap = () => {
+    const mapCenter = farmInfo.value.farmLocation || undefined;
+    if (farmInfo.value.regionList.length) {
+        // type=view 进入查看态;rangeWkt 用于回显多个地块
+        router.push({
+            path: "/draw_area",
+            query: {
+                type: "viewOnly",
+                subjectId: route.query.subjectId
+            },
+        });
+    } else {
+        ElMessage.warning("暂无种植作物,无法编辑地块");
+    }
+};
+
+const handleAddVariety = () => {
+    router.push(`/interaction?addVariety=true&subjectId=${route.query.subjectId}`);
+};
+</script>
+
+<style lang="scss" scoped>
+.farm-details-page {
+    background: #f2f3f5;
+    height: calc(100vh - 40px);
+    padding: 0 12px;
+    overflow: auto;
+
+    .line-title {
+        position: relative;
+        padding-left: 14px;
+        font-size: 16px;
+
+        &::before {
+            content: "";
+            position: absolute;
+            left: 5px;
+            top: 50%;
+            transform: translateY(-50%);
+            width: 4px;
+            height: 15px;
+            background: #2199f8;
+            border-radius: 20px;
+        }
+    }
+
+    .info-card{
+        margin-top: 12px;
+        background: #fff;
+        border-radius: 6px;
+        padding: 10px;
+    }
+
+    .map-wrap {
+        position: relative;
+
+        .map-area {
+            width: 100%;
+            height: 142px;
+            clip-path: inset(0px round 5px);
+        }
+
+        .map-text {
+            position: absolute;
+            right: 13px;
+            bottom: 16px;
+            font-size: 12px;
+            color: #ffffff;
+            background: rgba(0, 0, 0, 0.5);
+            padding: 8px 12px;
+            border-radius: 25px;
+            border: 1px solid rgba(255, 255, 255, 0.5);
+        }
+    }
+
+    .info-box {
+        margin-top: 12px;
+
+        .section-header {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+        }
+
+        .edit-btn-box {
+            display: flex;
+            align-items: center;
+            gap: 8px;
+        }
+
+        .edit-btn {
+            padding: 4px 12px;
+            font-size: 12px;
+            color: #86909c;
+            border-radius: 999px;
+            border: 0.5px solid #d0d3d8;
+            background-color: #ffffff;
+        }
+
+        .info-list {
+            margin-top: 10px;
+            margin-left: 5px;
+
+            .info-row {
+                display: flex;
+                align-items: flex-start;
+                margin-bottom: 6px;
+
+                &.center-row {
+                    align-items: center;
+                }
+
+                .info-label {
+                    min-width: 80px;
+                    color: #4E5969;
+                }
+
+                .crop-tags {
+                    display: flex;
+                    align-items: center;
+                    flex-wrap: wrap;
+                    gap: 6px;
+
+                    .crop-tag {
+                        padding: 2px 8px;
+                        background: #E8F3FF;
+                        color: #2199f8;
+                        border-radius: 2px;
+                        font-size: 12px;
+                    }
+                }
+
+                .problem-tags {
+                    display: flex;
+                    flex-wrap: wrap;
+                    gap: 6px;
+
+                    .problem-tag {
+                        padding: 2px 8px;
+                        background: rgba(58, 173, 148, 0.1);
+                        color: #3AAD94;
+                        border-radius: 2px;
+                        font-size: 13px;
+                    }
+                }
+
+                .device-value {
+                    width: 100%;
+                }
+
+                .device-box {
+                    padding: 6px;
+                    border-radius: 4px;
+                    border: 0.5px solid rgba(33, 153, 248, 0.2);
+                    display: grid;
+                    grid-template-columns: repeat(2, minmax(0, 1fr));
+                    column-gap: 12px;
+                    row-gap: 4px;
+
+                    .device-item {
+                        display: flex;
+                        align-items: center;
+                        justify-content: space-between;
+                        padding: 4px 0;
+                        min-width: 0;
+                        gap: 8px;
+                        font-size: 13px;
+                        color: #1D2129;
+
+                        .device-count {
+                            padding: 2px 8px;
+                            background: #E8F3FF;
+                            color: #2199f8;
+                            border-radius: 2px;
+                        }
+                    }
+                }
+            }
+
+            .info-row-column {
+                display: flex;
+                flex-direction: column;
+                gap: 4px;
+            }
+        }
+    }
+}
+</style>

+ 128 - 124
src/views/old_mini/monitor/subPages/farmInfo.vue

@@ -1,10 +1,6 @@
 <template>
-    <custom-header name="农场信息" bgColor="#f2f3f5"></custom-header>
+    <custom-header name="农场基本信息" bgColor="#f2f3f5"></custom-header>
     <div class="farm-details-page">
-        <div class="map-wrap info-card">
-            <div class="map-area" ref="mapContainer"></div>
-            <div class="map-text" @click="handleEditMap">点击编辑地块</div>
-        </div>
         <div class="info-box info-card">
             <div class="section-header">
                 <div class="line-title">基本信息</div>
@@ -19,113 +15,101 @@
                     <span class="info-value">{{ farmInfo.subjectName }}</span>
                 </div>
                 <div class="info-row">
-                    <span class="info-label">联系人:</span>
-                    <span class="info-value">{{ farmInfo.contactName }}</span>
-                </div>
-                <div class="info-row center-row">
-                    <span class="info-label">联系电话:</span>
-                    <span class="info-value">{{ farmInfo.contactPhone }}</span>
-                </div>
-                <div class="info-row">
-                    <span class="info-label">种植面积:</span>
+                    <span class="info-label">农场面积:</span>
                     <span class="info-value">{{ farmInfo.farmArea }}亩</span>
                 </div>
                 <div class="info-row">
                     <span class="info-label">农场位置:</span>
                     <span class="info-value">{{ farmInfo.farmAddress }}</span>
                 </div>
-                <div class="info-row">
-                    <span class="info-label">种植品种:</span>
-                    <div class="info-value crop-tags">
-                        <span v-for="crop in farmInfo.regionList" :key="crop.regionId" class="crop-tag">
-                            {{ crop.regionName }}
-                        </span>
-                    </div>
+            </div>
+        </div>
+        <div class="info-box info-card">
+            <div class="section-header">
+                <div class="line-title">土壤性质</div>
+                <div class="edit-btn" @click="handleEditSoil">编辑信息</div>
+            </div>
+            <div class="info-list grid-list">
+                <div class="grid-item">
+                    <div class="grid-value">壤土</div>
+                    <div class="grid-name">质地</div>
+                </div>
+                <div class="grid-item">
+                    <div class="grid-value">1%</div>
+                    <div class="grid-name">有机质</div>
                 </div>
+                <div class="grid-item">
+                    <div class="grid-value">5.5</div>
+                    <div class="grid-name">PH</div>
+                </div>
+            </div>
+        </div>
+        <div class="info-box info-card">
+            <div class="section-header">
+                <div class="line-title">历史高发风险</div>
+                <div class="edit-btn only-text" @click="handleEditFarmFacility">查看更多<el-icon><ArrowRight /></el-icon></div>
+            </div>
+            <div class="info-list">
+                <span class="text-label">物候风险:</span> 风险描述风险描述风险描述风险描述风险
             </div>
         </div>
         <div class="info-box info-card">
             <div class="section-header">
-                <div class="line-title">农场设施</div>
-                <div class="edit-btn" @click="handleEditFarmFacility">编辑信息</div>
+                <div class="line-title">种植类别</div>
             </div>
             <div class="info-list">
                 <div class="info-row">
-                    <span class="info-label">灌溉方式:</span>
+                    <span class="info-label">过往种植:</span>
                     <div class="info-value crop-tags">
-                        <span v-for="method in basicFarmInfo.irrigation" :key="method.code" class="crop-tag">
-                            {{ method.name }}
+                        <span v-for="crop in farmInfo.regionList" :key="crop.regionId" class="crop-tag dark-tag">
+                            {{ crop.regionName }}
                         </span>
+                        <span class="crop-tag border-tag" @click="handleAddVariety">+新增品种</span>
+                    </div>
+                </div>
+                <div class="info-row line-break">
+                    <div class="info-label">当季作物:</div>
+                    <div class="season-box">
+                        <div class="info-value crop-tags">
+                            <span class="crop-tag">
+                                桂味
+                            </span>
+                        </div>
+                        <div class="season-content">
+                            <div class="season-item">桂味-上市时间:06.08</div>
+                            <div class="season-item">桂味-上市时间:06.08</div>
+                        </div>
+                    </div>
+                    <div class="season-box">
+                        <div class="info-value crop-tags">
+                            <span class="crop-tag">
+                                桂味
+                            </span>
+                        </div>
+                        <div class="season-content">
+                            <div class="season-item">桂味-上市时间:06.08</div>
+                            <div class="season-item">桂味-上市时间:06.08</div>
+                        </div>
                     </div>
                 </div>
             </div>
         </div>
     </div>
     <FarmInfoPopup ref="farmInfoPopupRef" :farmId="route.query.subjectId" @success="fetchFarmSubjectDetail" />
+
+    <SoilPopup ref="soilPopupRef" />
 </template>
 
 <script setup>
-import { ref, onMounted, nextTick } from "vue";
+import { ref, onMounted } from "vue";
 import customHeader from "@/components/customHeader.vue";
 import { useRouter, useRoute } from "vue-router";
-import DrawRegionMap from "@/views/old_mini/interactionList/map/drawRegionMap.js";
-import * as util from "@/common/ol_common.js";
-import { ElMessage } from "element-plus";
-import { useStore } from "vuex";
 import FarmInfoPopup from "@/views/old_mini/home/components/farmInfoPopup.vue";
+import SoilPopup from "./soilPopup.vue";
 
 const router = useRouter();
 const route = useRoute();
-const store = useStore();
 const farmInfo = ref({});
-const mapContainer = ref(null);
-const drawRegionMap = new DrawRegionMap();
-
-const initMap = () => {
-    if (!mapContainer.value) return;
-    if (drawRegionMap.kmap) return;
-
-    const info = farmInfo.value || {};
-
-    drawRegionMap.initMap(info.farmLocation, mapContainer.value, false, true, false);
-
-    // 回显农场区域,多边形 WKT 数组(有就画,没有就不画)
-    let geometryArr = [];
-
-    // 优先使用 regionList 里的 geom:有值才渲染
-    if (Array.isArray(info.regionList) && info.regionList.length > 0) {
-        info.regionList.forEach((item) => {
-            if (item?.geom) {
-                geometryArr.push(item?.geom)
-            }
-        });
-    }
-
-    if (geometryArr.length) {
-        // 农场信息页:地块用绿色展示;第三参留空表示面积仍按地块自动计算
-        drawRegionMap.setAreaGeometry(Array.from(geometryArr), true, undefined, {
-            fill: "rgba(0, 57, 44, 0.5)",
-            stroke: "#18AA8B",
-        });
-    }
-
-    // 在区域中心落一个点位(使用与勾画页相同的图标)
-    try {
-        const geom = util.wktCastGeom(info.farmLocation);
-        if (geom && typeof geom.getFirstCoordinate === "function") {
-            const coord = geom.getFirstCoordinate();
-            drawRegionMap.setMapPoint(coord);
-        }
-    } catch (e) {
-        // 解析失败则忽略点位
-    }
-};
-
-const destroyMap = () => {
-    if (drawRegionMap && drawRegionMap.kmap && drawRegionMap.destroyMap) {
-        drawRegionMap.destroyMap();
-    }
-};
 
 onMounted(() => {
     fetchFarmSubjectDetail();
@@ -135,10 +119,6 @@ onMounted(() => {
 function fetchFarmSubjectDetail() {
     VE_API.basic_farm.fetchFarmSubjectDetail({ subjectId: route.query.subjectId }).then(({ data }) => {
         farmInfo.value = data || {};
-        nextTick(() => {
-            destroyMap();
-            initMap();
-        });
     });
 }
 
@@ -186,25 +166,13 @@ const handleEditFarmInfo = () => {
     farmInfoPopupRef.value.handleShow();
 };
 
-const handleEditFarmFacility = () => {
-    router.push(`/prescription?subjectId=${route.query.subjectId}`);
+const soilPopupRef = ref(null);
+const handleEditSoil = () => {
+    soilPopupRef.value.open();
 };
 
-// 点击编辑地块
-const handleEditMap = () => {
-    const mapCenter = farmInfo.value.farmLocation || undefined;
-    if (farmInfo.value.regionList.length) {
-        // type=view 进入查看态;rangeWkt 用于回显多个地块
-        router.push({
-            path: "/draw_area",
-            query: {
-                type: "viewOnly",
-                subjectId: route.query.subjectId
-            },
-        });
-    } else {
-        ElMessage.warning("暂无种植作物,无法编辑地块");
-    }
+const handleEditFarmFacility = () => {
+    router.push(`/prescription?subjectId=${route.query.subjectId}`);
 };
 
 const handleAddVariety = () => {
@@ -244,28 +212,6 @@ const handleAddVariety = () => {
         padding: 10px;
     }
 
-    .map-wrap {
-        position: relative;
-
-        .map-area {
-            width: 100%;
-            height: 142px;
-            clip-path: inset(0px round 5px);
-        }
-
-        .map-text {
-            position: absolute;
-            right: 13px;
-            bottom: 16px;
-            font-size: 12px;
-            color: #ffffff;
-            background: rgba(0, 0, 0, 0.5);
-            padding: 8px 12px;
-            border-radius: 25px;
-            border: 1px solid rgba(255, 255, 255, 0.5);
-        }
-    }
-
     .info-box {
         margin-top: 12px;
 
@@ -288,6 +234,9 @@ const handleAddVariety = () => {
             border-radius: 999px;
             border: 0.5px solid #d0d3d8;
             background-color: #ffffff;
+            &.only-text {
+                border: none;
+            }
         }
 
         .info-list {
@@ -299,12 +248,16 @@ const handleAddVariety = () => {
                 align-items: flex-start;
                 margin-bottom: 6px;
 
+                &.line-break {
+                    display: block;
+                }
+
                 &.center-row {
                     align-items: center;
                 }
 
                 .info-label {
-                    min-width: 80px;
+                    min-width: 70px;
                     color: #4E5969;
                 }
 
@@ -320,6 +273,15 @@ const handleAddVariety = () => {
                         color: #2199f8;
                         border-radius: 2px;
                         font-size: 12px;
+                        height: 22px;
+                        box-sizing: border-box;
+                        &.dark-tag {
+                            background: #F8F8F8;
+                            color: #7F7F7F;
+                        }
+                        &.border-tag {
+                            border: 0.5px solid #2199F8;
+                        }
                     }
                 }
 
@@ -376,6 +338,48 @@ const handleAddVariety = () => {
                 gap: 4px;
             }
         }
+
+        .season-box {
+            padding-top: 8px;
+            .season-content {
+                display: grid;
+                grid-template-columns: repeat(2, 1fr);
+                gap: 2px;
+                .season-item {
+                    padding-top: 6px;
+                }
+            }
+        }
+
+        .text-label {
+            color: #4E5969;
+        }
+
+        .grid-list {
+            display: grid;
+            grid-template-columns: repeat(3, 1fr);
+            gap: 6px;
+            .grid-item {
+                background: #F5F5F5;
+                border-radius: 5px;
+                padding: 3px;
+                display: flex;
+                flex-direction: column;
+                align-items: center;
+                justify-content: center;
+                height: 50px;
+                .grid-value {
+                    font-size: 16px;
+                    color: #1D2129;
+                    // line-height: 22px;
+                }
+                .grid-name {
+                    // line-height: 14px;
+                    font-size: 12px;
+                    color: rgba(78, 89, 105, 0.5);
+                }
+            }
+        }
     }
 }
 </style>

+ 251 - 0
src/views/old_mini/monitor/subPages/soilPopup.vue

@@ -0,0 +1,251 @@
+<template>
+    <Popup class="soil-popup" round v-model:show="show">
+        <div class="soil-content">
+            <div class="section-title">请选择您的土壤类型</div>
+            <div class="slider-wrap">
+                <Slider
+                    v-model="soilIndex"
+                    :min="0"
+                    :max="soilOptions.length - 1"
+                    :step="1"
+                    bar-height="2px"
+                    active-color="#D9D9D9"
+                    inactive-color="#D9D9D9"
+                >
+                    <template #button>
+                        <div class="slider-button">
+                            <span></span><span></span><span></span>
+                        </div>
+                    </template>
+                </Slider>
+                <div class="dot-row">
+                    <span
+                        v-for="(_, idx) in soilOptions"
+                        :key="'soil-dot-' + idx"
+                        class="dot"
+                        :class="{ active: idx === soilIndex }"
+                        @click="soilIndex = idx"
+                    />
+                </div>
+                <div class="label-row">
+                    <span
+                        v-for="(item, idx) in soilOptions"
+                        :key="'soil-label-' + item"
+                        class="label-item"
+                        :class="{ active: idx === soilIndex }"
+                        @click="soilIndex = idx"
+                    >
+                        {{ item }}
+                    </span>
+                </div>
+            </div>
+
+            <div class="section-title ph-title">调整pH值</div>
+            <div class="slider-wrap">
+                <Slider
+                    v-model="phIndex"
+                    :min="0"
+                    :max="phOptions.length - 1"
+                    :step="1"
+                    bar-height="2px"
+                    active-color="#D9D9D9"
+                    inactive-color="#D9D9D9"
+                >
+                    <template #button>
+                        <div class="slider-button">
+                            <span></span><span></span><span></span>
+                        </div>
+                    </template>
+                </Slider>
+                <div class="dot-row">
+                    <span
+                        v-for="(_, idx) in phOptions"
+                        :key="'ph-dot-' + idx"
+                        class="dot"
+                        :class="{ active: idx === phIndex }"
+                        @click="phIndex = idx"
+                    />
+                </div>
+                <div class="label-row ph-label-row">
+                    <span
+                        v-for="(item, idx) in phOptions"
+                        :key="'ph-label-' + item"
+                        class="label-item"
+                        :class="{ active: idx === phIndex }"
+                        @click="phIndex = idx"
+                    >
+                        {{ item }}
+                    </span>
+                </div>
+            </div>
+        </div>
+        <div class="popup-button">
+            <div class="button-item cancel" @click="close">取消</div>
+            <div class="button-item confirm" @click="handleConfirm">确认信息</div>
+        </div>
+    </Popup>
+</template>
+
+<script setup>
+import { computed, ref } from 'vue';
+import { Popup, Slider } from "vant";
+
+const show = ref(false);
+const soilOptions = ["沙土", "壤土", "粘土"];
+const phOptions = ["5", "5.5", "6", "6.5", "7", "7.5", "8"];
+const soilIndex = ref(1);
+const phIndex = ref(3);
+
+const emit = defineEmits(["confirm"]);
+
+const currentSoilType = computed(() => soilOptions[soilIndex.value] || soilOptions[0]);
+const currentPh = computed(() => Number(phOptions[phIndex.value] || phOptions[0]));
+
+const open = () => {
+    show.value = true;
+}
+
+const close = () => {
+    show.value = false;
+}
+
+const handleConfirm = () => {
+    emit("confirm", {
+        soilType: currentSoilType.value,
+        ph: currentPh.value,
+    });
+    close();
+};
+
+defineExpose({
+    open,
+    close,
+});
+</script>
+
+<style lang="scss" scoped>
+.soil-popup {
+    width: 90%;
+    padding: 20px 22px 20px 22px;
+    // background: linear-gradient(360deg, #FFFFFF 74.2%, #D1EBFF 100%);
+    background: linear-gradient(360deg, #FFFFFF 63.11%, #93CEFD 100%);
+    border-radius: 8px;
+    font-size: 16px;
+    
+    .soil-content {
+        padding: 4px 0 0;
+
+        .section-title {
+            font-size: 16px;
+            color: #000;
+            margin-bottom: 10px;
+        }
+
+        .ph-title {
+            margin-top: 18px;
+        }
+
+        .slider-wrap {
+            padding: 8px 4px 0;
+            ::v-deep {
+                .van-slider__button-wrapper {
+                    z-index: 10;
+                }
+            }
+        }
+
+        .slider-button {
+            width: 46px;
+            height: 26px;
+            border-radius: 28px;
+            background: #2199f8;
+            border: 2px solid rgba(255, 255, 255, 0.9);
+            box-shadow: 0 3px 8px rgba(0, 0, 0, 0.18);
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            gap: 4px;
+
+            span {
+                width: 2px;
+                height: 8px;
+                border-radius: 6px;
+                background: #fff;
+            }
+        }
+
+        .dot-row {
+            margin-top: -6px;
+            z-index: 2;
+            position: relative;
+            padding: 0 2px;
+            display: flex;
+            justify-content: space-between;
+
+            .dot {
+                width: 10px;
+                height: 10px;
+                box-sizing: border-box;
+                border-radius: 50%;
+                background: #CDCDCD;
+                border: 1.5px solid #fff;
+                cursor: pointer;
+                box-shadow: 0px 2px 3px 0px #00000012;
+            }
+
+            .dot.active {
+                border-color: #2199f8;
+            }
+        }
+
+        .label-row {
+            margin-top: 14px;
+            display: flex;
+            justify-content: space-between;
+
+            .label-item {
+                font-size: 14px;
+                color: #000;
+                cursor: pointer;
+            }
+
+            .label-item.active {
+                color: #2199f8;
+                font-weight: 500;
+            }
+        }
+
+        .ph-label-row {
+            .label-item {
+                min-width: 24px;
+                text-align: center;
+            }
+        }
+    }
+
+    .popup-button {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 16px;
+        gap: 12px;
+        .button-item {
+            flex: 1;
+            border-radius: 20px;
+            background: #2199F8;
+            color: #fff;
+            text-align: center;
+            height: 40px;
+            box-sizing: border-box;
+            line-height: 40px;
+        }
+
+        .cancel {
+            color: #000;
+            border: 1px solid rgba(0, 0, 0, 0.2);
+            background: #fff;
+            width: 102px;
+            flex: none;
+        }
+    }
+}
+</style>

+ 18 - 17
src/views/old_mini/work_detail/index.vue

@@ -6,23 +6,15 @@
             <!-- 顶部状态 -->
             <div class="content-status" :class="['status-' + detail?.flowStatus, 'audit-' + getAuditStatusPriority(detail?.executeEvidenceAuditStatus)]">
                 <div class="status-l">
-                    <div class="status-title">{{ handleTagType(detail?.flowStatus) }}</div>
+                    <div class="status-title">{{ detail?.farmWorkName }}</div>
                     <div class="status-sub" v-if="triggerDateText && (detail?.flowStatus == -1 || detail?.flowStatus == -2)">
                         执行时间已经过去 {{ Math.abs(daysDiff) }} 天了
                     </div>
                     <div class="status-sub" v-if="detail?.flowStatus === 3 && getAuditStatusPriority(detail?.executeEvidenceAuditStatus) !== 2">
-                        <template v-if="daysDiff > 0">
-                            距离执行时间还差 {{ Math.abs(daysDiff) }} 天
-                        </template>
-                        <template v-else-if="daysDiff === 0">
-                            执行时间为今天
-                        </template>
-                        <template v-else>
-                            执行时间已过
-                        </template>
+                        04/19 执行最佳
                     </div>
                     <div class="status-sub" v-if="!detail?.flowStatus || detail?.flowStatus === 0">
-                        预计触发时间 {{ detail?.executeDate || "--" }}
+                        预计{{ detail?.executeDate || "--" }}执行,执行时间需巡园校准
                     </div>
                 </div>
             </div>
@@ -31,8 +23,9 @@
                 <!-- 农事组信息 -->
                 <div class="box-wrap group-info group-box" v-if="(detail?.executionLimitDays || detail?.executionLimitDays === 0) && detail?.flowStatus !== 5">
                     <div class="group-name">
-                        该农事为 <span class="light-text">标准防治溯源农事</span> ,最佳执行时间为 <span class="light-text">{{detail?.executionLimitDays}}天</span>, 
-                        请及时完成溯源认证上传
+                        <!-- 该农事为 <span class="light-text">标准防治溯源农事</span> ,最佳执行时间为 <span class="light-text">{{detail?.executionLimitDays}}天</span>, 
+                        请及时完成溯源认证上传 -->
+                        农事原因农事原因农事原因农事原因农事原因农事原因农事原因
                     </div>
                 </div>
 
@@ -536,7 +529,7 @@ const changeExecutionMethod = (stageIndex, value) => {
     padding: 16px 12px 0 12px;
     color: #fff;
     z-index: 1;
-    height: 100px;
+    height: 92px;
     box-sizing: border-box;
 
     &::after {
@@ -545,7 +538,7 @@ const changeExecutionMethod = (stageIndex, value) => {
         position: absolute;
         left: 0;
         top: 0;
-        height: 100px;
+        height: 140px;
         background: #C7C7C7;
         // background: #FF953D;
         width: 100%;
@@ -592,14 +585,22 @@ const changeExecutionMethod = (stageIndex, value) => {
         }
 
         .status-sub {
-            font-size: 14px;
+            margin-top: 10px;
+            font-size: 12px;
+            padding: 0 8px;
+            background: #fff;
+            color: rgba(62, 61, 61, 0.8);
+            width: fit-content;
+            height: 26px;
+            line-height: 26px;
+            border-radius: 2px;
         }
     }
 }
 
 .work-wrap {
     position: relative;
-    top: -16px;
+    top: 0;
     padding: 0 12px 12px;
     z-index: 2;
     &.has-bottom {