Bläddra i källkod

Merge branch 'supplies' of http://www.sysuimars.cn:3000/feiniao/feiniao-farm-h5 into supplies

wangsisi 5 dagar sedan
förälder
incheckning
017191a31b

+ 7 - 75
src/router/globalRoutes.js

@@ -29,12 +29,6 @@ export default [
         name: "FarmDetails",
         component: () => import("@/views/old_mini/farmDetails/index.vue"),
     },
-    {
-        path: "/monitor",
-        name: "Monitor",
-        meta: { showTabbar: true, keepAlive: true },
-        component: () => import("@/views/old_mini/monitor/index.vue"),
-    },
     //个人中心
     {
         path: "/mine",
@@ -82,18 +76,6 @@ export default [
         name: "FarmPhoto",
         component: () => import("@/views/old_mini/home/patrolPhoto.vue"),
     },
-    // 聊天
-    {
-        path: "/chat_frame",
-        name: "ChatFrame",
-        meta: { keepAlive: true },
-        component: () => import("@/views/old_mini/chat_frame/index.vue"),
-    },// 咨询专家
-    {
-        path: "/expert_list",
-        name: "ExpertList",
-        component: () => import("@/views/old_mini/home/subPages/expertList.vue"),
-    },
     // 我的农场
     {
         path: "/my_farm",
@@ -285,24 +267,6 @@ export default [
         name: "UserInfo",
         component: () => import("@/views/old_mini/mine/pages/userInfo.vue"),
     },
-    // 农事规划
-    {
-        path: "/plan",
-        name: "Plan",
-        component: () => import("@/views/old_mini/monitor/subPages/plan.vue"),
-    },
-    // 农事复核
-    {
-        path: "/review-results",
-        name: "ReviewResults",
-        component: () => import("@/views/old_mini/monitor/subPages/reviewResults.vue"),
-    },
-    // 农情采样详情
-    {
-        path: "/agricultural_detail",
-        name: "AgriculturalDetail",
-        component: () => import("@/views/old_mini/monitor/subPages/agriculturalDetail.vue"),
-    },
     // 农事方案
     {
         path: "/agricultural_plan",
@@ -341,31 +305,12 @@ export default [
         name: "ServiceDetail",
         component: () => import("@/views/old_mini/mine/pages/serviceDetail.vue"),
     },
-    // 作物档案
-    {
-        path: "/crop_record",
-        name: "CropRecord",
-        component: () => import("@/views/old_mini/user/subPages/cropRecord.vue"),
-    },
     // 编辑农事方案
     {
         path: "/edit_plan",
         name: "EditPlan",
         component: () => import("@/views/old_mini/plan/editPlan.vue"),
     },
-    // 编辑农事方案
-    {
-        path: "/modify_plan",
-        name: "ModifyPlan",
-        component: () => import("@/views/old_mini/plan/components/modifyPlan.vue"),
-    },
-    // 编辑农事方案
-    {
-        path: "/modify",
-        name: "Modify",
-        meta: { keepAlive: true },
-        component: () => import("@/views/old_mini/modify_work/modify.vue"),
-    },
     // 农场列表
     {
         path: "/farm_list",
@@ -385,20 +330,6 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/home/subPages/prescriptionPage.vue"),
     },
-    // 知识库
-    {
-        path: "/knowledge_list",
-        name: "KnowledgeList",
-        meta: { keepAlive: true },
-        component: () => import("@/views/old_mini/home/subPages/knowledgeList.vue"),
-    },
-    // 成果报告
-    {
-        path: "/achievement_report",
-        name: "AchievementReport",
-        meta: { keepAlive: true },
-        component: () => import("@/views/old_mini/achievement_report/index.vue"),
-    },
     // 长势报告
     {
         path: "/growth_report",
@@ -406,12 +337,6 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/growth_report/index.vue"),
     },
-    // 咨询专家
-    {
-        path: "/consult",
-        name: "Consult",
-        component: () => import("@/views/old_mini/chat_frame/consult.vue"),
-    },
     // 农事记录详情
     {
         path: "/status_detail",
@@ -461,4 +386,11 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/work_detail/index.vue"),
     },
+    // 农情互动
+    {
+        path: "/interaction",
+        name: "Interaction",
+        meta: { keepAlive: true },
+        component: () => import("@/views/old_mini/interaction/index.vue"),
+    },
 ];

+ 0 - 782
src/views/old_mini/achievement_report/index.vue

@@ -1,782 +0,0 @@
-<template>
-    <div class="achievement-report-page">
-        <custom-header name="生成成果报告"></custom-header>
-        <div class="report-content-wrap" v-loading="loading">
-            <div class="report-content" ref="reportDom">
-                <img src="@/assets/img/home/qrcode.png" alt="" class="code-icon" />
-                <div class="report-header">
-                    <img class="header-book" src="@/assets/img/home/book.png" alt="" />
-                    <div class="time-tag">{{ workItem?.executeDate }}</div>
-                    <div class="report-title">成果报告</div>
-                    <div class="report-info">
-                        <div class="info-item">
-                            <img class="info-icon" :src="workItem?.executorIcon || 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'" alt="" />
-                            <span class="info-text">执行组织:{{ workItem?.executeMain }}</span>
-                        </div>
-                        <div class="info-item">
-                            <img class="info-icon" src="@/assets/img/home/farm.png" alt="" />
-                            <span class="info-text">服务农场:{{ workItem?.farmName }}</span>
-                        </div>
-                    </div>
-                </div>
-
-                <div class="report-box">
-                    <div class="report-box-item">
-                        <div class="item-content">{{ workItem?.farmWorkName || "--" }}</div>
-                        <div class="item-title">作业农事</div>
-                    </div>
-                    <div class="report-box-item">
-                        <div class="item-content">{{ formatArea(workItem?.area) || "--" }}</div>
-                        <div class="item-title">作业面积</div>
-                    </div>
-                    <div class="report-box-item">
-                        <div class="item-content">{{ reportData?.workCycle ? (reportData?.workCycle + '天') : "--" }}</div>
-                        <div class="item-title">作业周期</div>
-                    </div>
-                    <div class="report-box-item">
-                        <div class="item-content">{{ reportData?.deviceName || "--" }}</div>
-                        <div class="item-title">使用设备</div>
-                    </div>
-                </div>
-
-                <!-- <div class="report-box">
-                    <div class="box-title">精准施治,智慧护航</div>
-                    <div class="box-text">
-                        {{ reportData?.resultInfo || "--" }}
-                    </div>
-                </div> -->
-
-                <div class="report-excute" v-for="(item, index) in workItem?.executeEvidence" :key="index">
-                    <div class="tag-label">执行照片</div>
-                    <album-draw-box :key="paramsPage.id" :isShowNum="0" :imgData="workItem" :photo="item" :current="index" :index="index" :length="workItem?.executeEvidence?.length"></album-draw-box>
-                </div>
-                <div class="report-excute" v-for="(item, index) in workItem?.reviewImage" :key="index">
-                    <div class="tag-label">复核照片</div>
-                    <album-draw-box :key="paramsPage.id+'复核'" :isShowNum="0" :isAchievementImgs="true" :imgData="workItem" :photo="item" :current="index" :index="index" :length="workItem?.reviewImage?.length"></album-draw-box>
-                </div>
-                <!-- <div class="report-excute" v-for="(item, index) in workItem?.reviewImage" :key="index">
-                    <div class="tag-label">复核照片</div>
-                    <album-draw-box :isShowNum="0" :photo="item" :current="index" :index="'review'+index" :length="workItem?.reviewImage?.length"></album-draw-box>
-                </div> -->
-                <!-- <div class="report-excute">
-                    <album-carousel
-                        :key="93"
-                        :isAchievementImgs="true"
-                        :images="combinedReviewImages"
-                    ></album-carousel>
-                </div> -->
-            </div>
-
-            <div class="bottom-btn">
-                <div class="btn-item second" @click="handleDownload">保存图片</div>
-                <div class="btn-item primay" @click="handleDownload">转发</div>
-            </div>
-        </div>
-
-        <!-- 组合照片(用于生成合成图片) -->
-        <div class="review-hide-box">
-            <div class="review-image" ref="reviewComboRef">
-                <div class="review-mask">
-                    <div class="review-text">复核成效</div>
-                    <div class="review-content">
-                        {{ workItem?.reCheckText }}
-                    </div>
-                </div>
-                <div class="vs-wrap" v-if="workItem?.reviewImage && workItem?.reviewImage?.length">
-                    <img src="@/assets/img/home/vs.png" alt="" />
-                </div>
-                <div class="review-image-item" v-if="workItem?.executeEvidence?.length">
-                    <div class="review-image-item-title">复核照片</div>
-                    <img
-                        class="review-image-item-img left-img"
-                        :src="leftCoverImg"
-                        style="width: 100%; height: 255px; display: block; image-rendering: auto"
-                    />
-                </div>
-                <div class="review-image-item" v-if="workItem?.reviewImage?.length">
-                    <img
-                        class="review-image-item-img right-img"
-                        :src="rightCoverImg"
-                        style="width: 100%; height: 255px; display: block; image-rendering: auto"
-                    />
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <popup class="cavans-popup" v-model:show="showPopup">
-        <div class="cavans-content">
-            <img class="current-img" :src="pageImg" alt="" />
-        </div>
-        <!-- 底部操作按钮 -->
-        <div class="bottom-actions" @click.stop="showPopup = false">
-            <div class="action-buttons">
-                
-                <div class="action-btn text-btn">
-                    &lt;&lt;长按图片保存或转发&gt;&gt;
-                </div>
-            </div>
-            <div class="cancel-btn" @click="handleCancel">取消</div>
-        </div>
-    </popup>
-</template>
-
-<script setup>
-import CustomHeader from "@/components/customHeader.vue";
-import AlbumCarousel from "@/components/album_compoents/albumCarousel";
-import { ref, onActivated, onDeactivated, onUnmounted, nextTick, watch } from "vue";
-import html2canvas from "html2canvas";
-import { uploadBase64 } from "@/common/uploadImg";
-import { detectRuntimeEnvironment } from "@/common/commonFun";
-import { useRoute } from "vue-router";
-import { Popup } from "vant";
-import { base_img_url2 } from "@/api/config";
-import wx from "weixin-js-sdk";
-import AlbumDrawBox from "@/components/album_compoents/albumDrawBox.vue";
-
-const route = useRoute();
-const loading = ref(false);
-const workItem = ref({});
-const showPopup = ref(false);
-function formatArea(val) {
-    const num = typeof val === "number" ? val : parseFloat(val);
-    if (Number.isNaN(num)) return val;
-    return Number.isInteger(num) ? num : num.toFixed(2) + "亩";
-}
-const paramsPage = ref({});
-onActivated(() => {
-    window.scrollTo(0, 0);
-    paramsPage.value = route.query.miniJson ? JSON.parse(route.query.miniJson) : {};
-    getDetail();
-    getResultReport();
-});
-
-const reportData = ref({});
-const getResultReport = () => {
-    VE_API.z_farm_work_record.resultReport({ recordId: paramsPage.value.id }).then((res) => {
-        if (res.code === 0) {
-            reportData.value = res.data;
-        }
-    });
-};
-
-const getDetail = () => {
-    if (!paramsPage.value.id) return;
-    loading.value = true;
-    VE_API.z_farm_work_record
-        .getDetail({ id: paramsPage.value.id })
-        .then(({ data }) => {
-            workItem.value = data[0];
-        })
-        .finally(() => {
-            loading.value = false;
-        });
-};
-
-const isDowload = ref(true);
-const reportDom = ref(null);
-const pageImg = ref(null);
-
-async function handleDownload() {
-    isDowload.value = false;
-    setTimeout(async () => {
-        // 获取要截图的DOM元素
-        const element = reportDom.value;
-
-        try {
-            const canvas = await html2canvas(element, {
-                scrollY: -window.scrollY, // 处理滚动条位置
-                allowTaint: true, // 允许跨域图片
-                useCORS: true, // 使用CORS
-                scale: 2, // 提高分辨率(2倍)
-                height: element.scrollHeight, // 设置完整高度
-                width: element.scrollWidth, // 设置完整宽度
-                logging: true, // 开启日志(调试用)
-            });
-
-            // 转换为图片并下载
-            const image = canvas.toDataURL("image/png");
-            pageImg.value = image;
-            nextTick(() => {
-                showPopup.value = true;
-            })
-        } catch (error) {
-            isDowload.value = true;
-        }
-    });
-}
-
-const handleCancel = () => {
-    showPopup.value = false;
-};
-
-function downloadImage(dataUrl, filename) {
-    const link = document.createElement("a");
-    link.href = dataUrl;
-    link.download = filename;
-    document.body.appendChild(link);
-    link.click();
-    document.body.removeChild(link);
-}
-
-const reviewComboRef = ref(null);
-const combinedReviewImages = ref([]);
-// 生成组合照片,传给相册组件
-const generateCombinedReviewImage = async () => {
-    try {
-        await prepareCoverImages();
-        await nextTick();
-
-        const canvas = await html2canvas(reviewComboRef.value, {
-            backgroundColor: null,
-            useCORS: true,
-            allowTaint: true,
-            scale: window.devicePixelRatio || 2,
-        });
-
-        combinedReviewImages.value = [canvas.toDataURL("image/png")];
-    } catch (e) {
-        console.error("生成组合照片失败", e);
-    }
-};
-
-const prepareCoverImages = async () => {
-    await nextTick();
-
-    const itemEl = reviewComboRef.value.querySelector(".review-image-item");
-
-    const cssWidth = itemEl.offsetWidth;
-    const cssHeight = 255;
-
-    if (workItem.value?.executeEvidence?.length) {
-        leftCoverImg.value = await coverImageToBase64HD(
-            base_img_url2 + workItem.value.executeEvidence.at(-1),
-            cssWidth,
-            cssHeight
-        );
-    }
-
-    if (workItem.value?.reviewImage?.length) {
-        rightCoverImg.value = await coverImageToBase64HD(
-            base_img_url2 + workItem.value.reviewImage.at(-1),
-            cssWidth,
-            cssHeight
-        );
-    }
-};
-
-const leftCoverImg = ref("");
-const rightCoverImg = ref("");
-
-function coverImageToBase64HD(imgUrl, cssWidth, cssHeight) {
-    return new Promise((resolve, reject) => {
-        const dpr = window.devicePixelRatio || 2;
-
-        const img = new Image();
-        img.crossOrigin = "anonymous";
-        img.src = imgUrl;
-
-        img.onload = () => {
-            // ⚠️ 用“物理像素”创建 canvas
-            const canvas = document.createElement("canvas");
-            canvas.width = cssWidth * dpr;
-            canvas.height = cssHeight * dpr;
-
-            const ctx = canvas.getContext("2d");
-            ctx.scale(dpr, dpr);
-
-            const imgRatio = img.width / img.height;
-            const targetRatio = cssWidth / cssHeight;
-
-            let sx = 0,
-                sy = 0,
-                sw = img.width,
-                sh = img.height;
-
-            if (imgRatio > targetRatio) {
-                sw = img.height * targetRatio;
-                sx = (img.width - sw) / 2;
-            } else {
-                sh = img.width / targetRatio;
-                sy = (img.height - sh) / 2;
-            }
-
-            ctx.drawImage(img, sx, sy, sw, sh, 0, 0, cssWidth, cssHeight);
-
-            resolve(canvas.toDataURL("image/png"));
-        };
-
-        img.onerror = reject;
-    });
-}
-
-
-const userInfoStr = localStorage.getItem("localUserInfo");
-const userInfo = userInfoStr ? JSON.parse(userInfoStr) : {};
-
-async function handleForward() {
-    setTimeout(async () => {
-        // 获取要截图的DOM元素
-        const element = reportDom.value;
-
-        try {
-            const canvas = await html2canvas(element, {
-                scrollY: -window.scrollY, // 处理滚动条位置
-                allowTaint: true, // 允许跨域图片
-                useCORS: true, // 使用CORS
-                scale: 2, // 提高分辨率(2倍)
-                height: element.scrollHeight, // 设置完整高度
-                width: element.scrollWidth, // 设置完整宽度
-                logging: true, // 开启日志(调试用)
-            });
-
-            // 转换为图片并下载
-            const image = canvas.toDataURL("image/png");
-            const process = detectRuntimeEnvironment();
-            // if (process === "wechat-webview") {
-                const imgUrl = await uploadBase64(image, false);
-                const params = {
-                    val: 'share',
-                    key: "report",
-                };
-                VE_API.mine.saveSessionStore({ ...params, text: imgUrl }).then((res) => {
-                    if (res.success) {
-                        wx.miniProgram.navigateTo({
-                            url: `/pages/subPages/report_page/index`,
-                        });
-                    }
-                });
-            // }
-            isDowload.value = true;
-        } catch (error) {
-            isDowload.value = true;
-        }
-    });
-
-
-    // const image = await handleDownload(true);
-    // const imgUrl = await uploadBase64(image, false);
-    // const params = {
-    //     miniUserId: 766,
-    //     key: "report",
-    // };
-    // VE_API.mine.saveSessionStore({ ...params, text: imgUrl }).then((res) => {
-    //     if (res.success) {
-    //         wx.miniProgram.navigateTo({
-    //             url: `/pages/subPages/report_page/index`,
-    //         });
-    //     }
-    // });
-}
-
-watch(
-    () => [workItem.value.executeEvidence, workItem.value.reviewImage],
-    ([preImgs, reviewImgs]) => {
-        if (preImgs && preImgs.length && reviewImgs && reviewImgs.length) {
-            generateCombinedReviewImage();
-        }
-    },
-    { deep: true }
-);
-
-// 清理数据的函数
-const clearData = () => {
-    workItem.value = {};
-    reportData.value = {};
-    paramsPage.value = {};
-    loading.value = false;
-    isDowload.value = true;
-    combinedReviewImages.value = [];
-    leftCoverImg.value = "";
-    rightCoverImg.value = "";
-};
-
-onDeactivated(() => {
-    clearData();
-});
-
-onUnmounted(() => {
-    clearData();
-});
-</script>
-
-<style lang="scss" scoped>
-.achievement-report-page {
-    width: 100%;
-    height: 100vh;
-    background: linear-gradient(195.35deg, #d4e4ff 16.34%, rgba(93, 189, 255, 0) 50.3%),
-        linear-gradient(156.64deg, rgba(255, 255, 255, 0.16) 27.7%, rgba(255, 255, 255, 0) 72.82%);
-
-    .report-content-wrap {
-        height: calc(100% - 40px);
-        padding-bottom: 60px;
-        overflow: auto;
-        box-sizing: border-box;
-        position: relative;
-        .bottom-btn {
-            z-index: 2;
-            position: fixed;
-            bottom: 0;
-            left: 0;
-            width: 100%;
-            background: #fff;
-            height: 60px;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            padding: 0 12px;
-            box-sizing: border-box;
-            box-shadow: 2px 2px 4.5px 0px rgba(0, 0, 0, 0.4);
-            .btn-item {
-                height: 40px;
-                line-height: 40px;
-                padding: 0 24px;
-                border-radius: 20px;
-                font-size: 14px;
-                &.second {
-                    color: #666666;
-                    border: 1px solid rgba(153, 153, 153, 0.5);
-                }
-                &.primay {
-                    padding: 0 34px;
-                    background: linear-gradient(180deg, #76c3ff, #2199f8);
-                    color: #fff;
-                }
-            }
-        }
-    }
-    
-    .code-icon {
-        position: absolute;
-        right: 10px;
-        top: 12px;
-        width: 48px;
-    }
-    .report-content {
-        background: url("@/assets/img/home/report_bg.png") no-repeat center center;
-        background-size: 100% auto;
-        background-position: top center;
-        padding: 24px 16px 16px;
-        box-sizing: border-box;
-        position: relative;
-        .report-header {
-            position: relative;
-            .header-book {
-                position: absolute;
-                right: 0;
-                bottom: -6px;
-                height: 88px;
-                z-index: 10;
-            }
-            .time-tag {
-                background: linear-gradient(137.86deg, #9fd5ff 5.87%, #2199f8 82.98%);
-                border-radius: 5px 0 5px 0;
-                height: 23px;
-                line-height: 23px;
-                font-size: 13px;
-                font-weight: 500;
-                color: #fff;
-                padding: 0 9px;
-                width: fit-content;
-            }
-            .report-title {
-                font-family: "PangMenZhengDao";
-                font-size: 34px;
-                line-height: 38px;
-                color: #000000;
-            }
-            .report-info {
-                padding: 10px 0 16px 0;
-                .info-item {
-                    width: fit-content;
-                    display: flex;
-                    height: 33px;
-                    align-items: center;
-                    padding: 0 6px 0 3px;
-                    background: linear-gradient(90deg, rgba(255, 255, 255, 0.58) 0%, rgba(255, 255, 255, 0.0696) 100%);
-                    border-radius: 20px;
-                    border: 0.5px solid rgba(33, 153, 248, 0.35);
-                    gap: 3px;
-                    .info-icon {
-                        width: 26px;
-                        height: 26px;
-                        object-fit: cover;
-                        border-radius: 50%;
-                    }
-                    .info-text {
-                        font-size: 14px;
-                        color: #2199f8;
-                    }
-                }
-                .info-item + .info-item {
-                    margin-top: 5px;
-                }
-            }
-        }
-
-        .report-box {
-            display: flex;
-            align-items: center;
-            padding: 8px;
-            background: linear-gradient(0deg, #ffffff 86.32%, #2199f8 136.87%);
-            border: 1px solid #ffffff;
-            border-radius: 8px;
-            gap: 5px;
-            position: relative;
-            .report-box-item {
-                flex: 1;
-                background: rgba(33, 153, 248, 0.1);
-                border-radius: 8px;
-                min-height: 62px;
-                box-sizing: border-box;
-                padding: 2px 4px;
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-                .item-content {
-                    color: #2199f8;
-                    font-size: 14px;
-                    text-align: center;
-                }
-                .item-title {
-                    color: #000000;
-                    font-size: 10px;
-                    text-align: center;
-                    padding-top: 5px;
-                }
-            }
-
-            .box-title {
-                position: absolute;
-                top: -8px;
-                left: 0;
-                height: 32px;
-                line-height: 26px;
-                padding: 0 10px;
-                color: #ffffff;
-                background: url("@/assets/img/home/title-bg.png") no-repeat center center / 100% 100%;
-            }
-            .box-text {
-                padding: 22px 0 12px 0;
-            }
-        }
-        .report-box + .report-box {
-            margin-top: 20px;
-        }
-        .report-excute {
-            position: relative;
-            margin-top: 12px;
-            .tag-label {
-                position: absolute;
-                top: 0;
-                left: 0;
-                padding: 4px 10px;
-                background: rgba(54, 52, 52, 0.8);
-                color: #fff;
-                font-size: 12px;
-                border-radius: 8px 0 8px 0;
-                z-index: 1;
-            }
-            ::v-deep {
-                .carousel-container .carousel-wrapper .carousel-img {
-                    min-width: calc(100vw - 32px);
-                    width: calc(100vw - 32px);
-                }
-            }
-        }
-    }
-    .download-btn {
-        position: fixed;
-        bottom: 20px;
-        left: 50%;
-        // background: #fff;
-        // box-shadow: 2px 2px 4.5px 0px #00000066;
-        // width: 100%;
-        transform: translateX(-50%);
-    }
-
-    .review-hide-box {
-        position: absolute;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        z-index: -1;
-        bottom: 0;
-    }
-
-    .review-image {
-        position: relative;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        gap: 8px;
-        margin: 12px;
-        background: #fff;
-        border-radius: 8px;
-        .review-mask {
-            z-index: 1;
-            pointer-events: none;
-            position: absolute;
-            left: 0;
-            top: 0;
-            width: 100%;
-            height: 100%;
-            border-radius: 8px;
-            background: linear-gradient(
-                360deg,
-                rgba(0, 0, 0, 0.78) 0%,
-                rgba(0, 0, 0, 0.437208) 19.87%,
-                rgba(0, 0, 0, 0) 33.99%
-            );
-            display: flex;
-            flex-direction: column;
-            align-items: baseline;
-            justify-content: end;
-            padding: 12px;
-            box-sizing: border-box;
-            color: #fff;
-            .review-text {
-                font-family: "PangMenZhengDao";
-                font-size: 16px;
-                margin-bottom: 1px;
-            }
-            .review-content {
-                font-size: 10px;
-                line-height: 15px;
-            }
-        }
-        .vs-wrap {
-            position: absolute;
-            left: 50%;
-            top: 50%;
-            transform: translate(-50%, -50%);
-            width: 40px;
-            height: 40px;
-            z-index: 10;
-            img {
-                width: 100%;
-                height: 100%;
-                object-fit: cover;
-            }
-        }
-        .review-image-item {
-            position: relative;
-            flex: 1;
-            .review-image-item-title {
-                position: absolute;
-                top: 0;
-                left: 0;
-                background: rgba(54, 52, 52, 0.6);
-                padding: 4px 10px;
-                border-radius: 8px 0 8px 0;
-                backdrop-filter: 4px;
-                font-size: 12px;
-                color: #fff;
-            }
-            // .review-image-item-img {
-            //     width: 100%;
-            //     height: 250px;
-            //     object-fit: cover;
-            // }
-            .review-image-item-img {
-                width: 100%;
-                height: 100%;
-                object-fit: cover;
-                object-position: center;
-            }
-            .left-img {
-                border-radius: 8px 0 0 8px;
-            }
-            .right-img {
-                border-radius: 0 8px 8px 0;
-            }
-        }
-    }
-}
-
-
-.cavans-popup {
-    width: 100%;
-    max-width: 100%;
-    max-height: 92vh;
-    background: none;
-    border-radius: 12px;
-    overflow: auto;
-    display: flex;
-    flex-direction: column;
-    backdrop-filter: 4px;
-    .cavans-content {
-        text-align: center;
-        padding: 0 12px;
-        height: fit-content;
-        overflow: auto;
-        .current-img {
-            width: 100%;
-        }
-    }
-
-    // 底部操作按钮
-    .bottom-actions {
-        flex-shrink: 0;
-
-        .action-buttons {
-            padding: 12px 0 4px 0;
-            display: flex;
-            justify-content: space-around;
-
-            .action-btn {
-                display: flex;
-                flex-direction: column;
-                align-items: center;
-                cursor: pointer;
-                &.text-btn {
-                    font-size: 12px;
-                    color: rgba(255, 255, 255, 0.7);
-                }
-
-                .icon-circle {
-                    width: 48px;
-                    height: 48px;
-                    border-radius: 50%;
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    color: #fff;
-                    margin-bottom: 4px;
-
-                    .el-icon {
-                        color: #fff;
-                    }
-                    img {
-                        width: 50px;
-                    }
-                }
-
-                &.blue-btn .icon-circle {
-                    background: #2199f8;
-                }
-
-                &.green-btn .icon-circle {
-                    background: #07c160;
-                }
-
-                &.orange-btn .icon-circle {
-                    background: #ff790b;
-                }
-
-                .btn-label {
-                    font-size: 12px;
-                    color: #fff;
-                }
-            }
-        }
-
-        .cancel-btn {
-            text-align: center;
-            font-size: 18px;
-            color: #fff;
-            cursor: pointer;
-        }
-    }
-}
-</style>

+ 0 - 690
src/views/old_mini/chat_frame/consult.vue

@@ -1,690 +0,0 @@
-<template>
-    <div class="consult">
-        <custom-header name="咨询专家"></custom-header>
-        <div class="consult-content">
-            <!-- 聊天消息区域 -->
-            <div class="chat-messages" ref="messagesContainer">
-                <div v-for="(msg, index) in messages" :key="index" class="message" :class="msg.sender">
-                    <!-- 对方消息 -->
-                    <template v-if="msg.sender === 'received'">
-                        <!-- <div class="avatar">{{ msg.receiverName.charAt(0) }}</div> -->
-                        <el-avatar class="avatar" :size="40" :src="msg.receiverIcon ||
-                            'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'
-                            " />
-                        <div class="bubble"
-                            :class="{ 'no-bubble': msg.messageType === 'image', 'card-bubble': msg.messageType === 'card' }">
-                            <!-- 文本消息 -->
-                            <div v-if="msg.messageType === 'text'" class="content">{{ msg.content }}</div>
-
-                            <!-- 图片消息 -->
-                            <div v-if="msg.messageType === 'image'" class="image-message">
-                                <img :src="msg.content + resize" @click="showImagePreview(msg.content)"
-                                    @load="handleImageLoad" alt="图片" />
-                            </div>
-
-                            <!-- 对话样式消息 -->
-                            <div v-if="msg.messageType === 'report'" class="dialog-message"
-                                @click="handleReportClick(msg)">
-                                <template v-if="(msg.reportType || msg.content.reportType) === 'farm_report'">
-                                    <div class="report-title">{{ msg.title || msg.content.title }}</div>
-                                    <div class="dialog-title">这是{{ curRole == 2 ? '该农场' : '我' }}的果园情况,请查看~</div>
-                                    <img src="https://birdseye-img.sysuimars.com/birdseye-look-mini/share-report-bg.png"
-                                        alt="" class="monitor-image" />
-                                </template>
-                                <template v-else>
-                                    <div class="dialog-title">{{ msg.title || msg.content.title }}</div>
-                                    <img src="@/assets/img/monitor/image.png" alt="" class="monitor-image" />
-                                </template>
-                            </div>
-
-                            <!-- 对话样式消息 -->
-                            <div v-if="msg.messageType === 'card'" class="question-message">
-                                <div class="question-title">{{ msg.title || msg.content.title }}</div>
-                                <div class="image-wrap">
-                                    <!-- coverUrl 为 JSON 字符串的数组时,解析后遍历 -->
-                                    <template
-                                        v-if="msg.content && msg.content.coverUrl && Array.isArray(msg.content.coverUrl)">
-                                        <img v-for="item in msg.content.coverUrl" :key="item" :src="handleImgUrl(item)"
-                                            alt="" />
-                                    </template>
-                                    <!-- 否则当作普通字符串 URL 使用 -->
-                                    <img v-else :src="handleImgUrl(msg.content.coverUrl)" alt="">
-                                </div>
-                                <div class="btn-detail" @click="handleDetailClick">查看详情</div>
-                            </div>
-                        </div>
-                    </template>
-
-                    <!-- 我方消息 -->
-                    <template v-else>
-                        <div class="bubble"
-                            :class="{ 'no-bubble': msg.messageType === 'image', 'card-bubble': msg.messageType === 'card' || msg.messageType === 'report' }">
-                            <!-- 文本消息 -->
-                            <div v-if="msg.messageType === 'text'" class="content">{{ msg.content }}</div>
-
-                            <!-- 图片消息 -->
-                            <div v-if="msg.messageType === 'image'" class="image-message">
-                                <img :src="msg.content + resize" @click="showImagePreview(msg.content)"
-                                    @load="handleImageLoad" alt="图片" />
-                            </div>
-
-                            <!-- 对话样式消息 -->
-                            <div v-if="msg.messageType === 'report'" class="dialog-message"
-                                @click="handleReportClick(msg)">
-                                <template v-if="(msg.reportType || msg.content.reportType) === 'farm_report'">
-                                    <div class="report-title">{{ msg.title || msg.content.title }}</div>
-                                    <div class="dialog-title">这是{{ curRole == 2 ? '该农场' : '我' }}果园情况,请查看~</div>
-                                    <img src="https://birdseye-img.sysuimars.com/birdseye-look-mini/share-report-bg.png"
-                                        alt="" class="monitor-image" />
-                                </template>
-                                <template v-else>
-                                    <div class="dialog-title">{{ msg.title || msg.content.title }}</div>
-                                    <img src="@/assets/img/monitor/image.png" alt="" class="monitor-image" />
-                                </template>
-                            </div>
-
-                            <!-- 对话样式消息 -->
-                            <div v-if="msg.messageType === 'card'" class="question-message">
-                                <div class="question-title">{{ msg.title || msg.content.title }}</div>
-                                <div class="image-wrap">
-                                    <!-- coverUrl 为 JSON 字符串的数组时,解析后遍历 -->
-                                    <template
-                                        v-if="msg.content && msg.content.coverUrl && Array.isArray(msg.content.coverUrl)">
-                                        <img v-for="item in msg.content.coverUrl" :key="item" :src="handleImgUrl(item)"
-                                            alt="" />
-                                    </template>
-                                    <!-- 否则当作普通字符串 URL 使用 -->
-                                    <img v-else :src="handleImgUrl(msg.content.coverUrl)" alt="">
-                                </div>
-                                <div class="btn-detail" @click="handleDetailClick">查看详情</div>
-                            </div>
-                        </div>
-                        <!-- <div class="avatar avatar-r">{{ msg.senderName.charAt(0) }}</div> -->
-                        <el-avatar class="avatar avatar-r" :size="40" :src="msg.senderIcon ||
-                            'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'
-                            " />
-                    </template>
-                </div>
-            </div>
-
-            <!-- 输入框区域 -->
-            <div class="input-area">
-                <!-- <div class="toolbar">
-                    <el-icon class="link" @click="startImageUpload"><Link /></el-icon>
-                    <input type="file" ref="fileInput" accept="image/*" style="display: none" @change="handleImageUpload" />
-                </div> -->
-
-                <input type="text" v-model="inputMessage" placeholder="请输入你想说的话~" @keyup.enter="sendTextMessage" />
-                <div class="send" @click="sendTextMessage">发送</div>
-            </div>
-
-            <!-- 图片预览模态框 -->
-            <div v-if="previewImage" class="image-preview" @click="previewImage = null">
-                <img :src="previewImage" alt="预览" />
-            </div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import { ref, nextTick, onDeactivated, onMounted } from "vue";
-import { useRouter, useRoute } from "vue-router";
-import { base_img_url2 } from "@/api/config";
-import { getFileExt } from "@/utils/util";
-import UploadFile from "@/utils/upliadFile";
-import MqttClient from "@/plugins/MqttClient";
-import customHeader from "@/components/customHeader.vue";
-import { useStore } from "vuex";
-const store = useStore();
-const resize = "?x-oss-process=image/resize,p_120/format,webp/quality,q_100";
-const router = useRouter();
-const route = useRoute();
-
-
-const curUserId = Number(localStorage.getItem("MINI_USER_ID"));
-const storeFarmId = ref(store.state.home.gardenId)
-const senderIcon = ref("");
-const receiverIcon = ref("");
-
-// 本地用户头像
-const localUserInfoIcon = (() => {
-    try {
-        const info = JSON.parse(localStorage.getItem("localUserInfo") || "{}");
-        return info?.icon || "";
-    } catch (e) {
-        return "";
-    }
-})();
-
-// mqtt 连接
-const mqttClient = ref(null);
-const messagesContainer = ref(null);
-
-// 初始化 mqtt
-const initMqtt = () => {
-    const topics = [`user/chat/message/${storeFarmId.value}/${curUserId}`]; // 订阅的主题数组
-    mqttClient.value = new MqttClient(topics, (topic, message) => {
-        if (message && message.length > 10) {
-            const obj = JSON.parse(message);
-            console.log("message有值", obj);
-            if (obj.senderId === curUserId) {
-                return;
-            }
-            if (obj.senderId === Number(route.query.userId)) {
-                // 检查是否已存在相同 id 的消息,避免重复添加
-                if (obj.id && messages.value.some(msg => msg.id === obj.id)) {
-                    return;
-                }
-                if (obj.messageType === "image") {
-                    if (obj.image && (obj.image.url || obj.image.originUrl)) {
-                        obj.content = obj.image.url || obj.image.originUrl;
-                    } else if (obj.content) {
-                        try {
-                            const img = JSON.parse(obj.content);
-                            obj.content = img.url || img.originUrl;
-                        } catch (e) {
-                            console.error(e, "e");
-                        }
-                    }
-                } else if (obj.messageType !== 'text') {
-                    obj.content = JSON.parse(obj.content);
-                    // card 类型的 content 中,如果 coverUrl 是数组,则转成字符串(兼容旧格式)
-                    if (obj.messageType === 'card' && obj.content && Array.isArray(obj.content.coverUrl)) {
-                        obj.content.coverUrl = JSON.stringify(obj.content.coverUrl);
-                    }
-                }
-                obj.receiverId = curUserId;
-                (obj.sender = obj.senderId === curUserId ? "sent" : "received"), (obj.senderIcon = senderIcon.value);
-                obj.receiverIcon = receiverIcon.value;
-                messages.value.push(obj);
-
-                scrollToBottom();
-            }
-        }
-    });
-
-    mqttClient.value.connect();
-};
-
-// 消息数据
-const messages = ref([]);
-
-// 输入相关
-const inputMessage = ref("");
-const fileInput = ref(null);
-
-function handleImageLoad() {
-    scrollToBottom();
-}
-
-const handleDetailClick = () => {
-    router.push(`/interaction_list?expertMiniUserId=${route.query.userId}`);
-}
-
-// 图片预览
-const previewImage = ref(null);
-
-const handleCardClick = (msg) => {
-    router.push(msg.linkUrl || msg.content.linkUrl);
-}
-
-const handleImgUrl = (url) => {
-    if (url && url.includes('https://')) {
-        return url;
-    } else {
-        return base_img_url2 + url + resize;
-    }
-}
-
-// 图片处理
-const startImageUpload = () => {
-    fileInput.value.click();
-};
-
-const uploadFileObj = new UploadFile();
-
-const handleImageUpload = (event) => {
-    const file = event.target.files[0];
-    if (file) {
-        // 实际项目中应该上传到服务器,这里使用本地URL模拟
-        const miniUserId = localStorage.getItem("MINI_USER_ID");
-        let ext = getFileExt(file.name);
-        let key = `birdseye-look-mini/${miniUserId}/${new Date().getTime()}.${ext}`;
-        let imageUrl = "";
-        uploadFileObj.put(key, file).then((resFilename) => {
-            imageUrl = base_img_url2 + resFilename;
-            sendImageMessage(imageUrl);
-        });
-    }
-};
-
-const showImagePreview = (imageUrl) => {
-    previewImage.value = imageUrl;
-};
-
-// 发送图片消息
-const sendImageMessage = (thumbnailUrl) => {
-    const message = {
-        sender: "sent",
-        messageType: "image",
-        senderIcon: senderIcon.value,
-        content: thumbnailUrl,
-    };
-    sendMessage(message);
-};
-
-//发送消息接口
-//类型 text ,file,image
-const sendMsg = (messageType = "text", content = "", obj = {}) => {
-    const params = {
-        farmId: storeFarmId.value,
-        receiverId: route.query.userId,
-        content,
-        [messageType]: obj,
-        messageType,
-    };
-    VE_API.bbs.sendMsg(params);
-};
-
-// 发送消息
-const sendMessage = (message) => {
-    if (message.messageType === "text") {
-        sendMsg("text", message.content);
-    } else if (message.messageType === "image") {
-        // 按新协议:不传 content,传 image 对象
-        sendMsg("image", "", { url: message.content, thumbnailUrl: message.content + resize });
-    } else if (message.messageType === "report") {
-        // 对话样式消息不发送到服务器,只显示在本地
-        console.log("发送对话样式消息:", message);
-        if (message.reportType === 'farm_report') {
-            sendMsg('report', '', {
-                title: message.title,
-                reportId: message.reportId,
-                reportType: message.reportType,
-            });
-        } else {
-            sendMsg('report', '', {
-                title: message.title,
-                reportId: message.reportId,
-                reportType: message.reportType,
-            });
-            console.log('其他文件1');
-        }
-    } else {
-        sendMsg('card', '', {
-            title: message.title,
-            coverUrl: message.coverUrl,
-            cardType: message.cardType,
-            linkUrl: message.linkUrl
-        });
-    }
-    messages.value.push(message);
-    scrollToBottom();
-};
-
-// 发送文本消息
-const sendTextMessage = () => {
-    if (inputMessage.value.trim()) {
-        const message = {
-            sender: "sent",
-            messageType: "text",
-            senderIcon: senderIcon.value,
-            content: inputMessage.value,
-        };
-        sendMessage(message);
-        inputMessage.value = "";
-    }
-};
-
-const scrollToBottom = () => {
-    nextTick(() => {
-        setTimeout(() => {
-            if (messagesContainer.value) {
-                messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
-            }
-        }, 300);
-    });
-};
-
-const curRole = ref(null);
-
-// 点击农场报告对话框
-const handleReportClick = (msg) => {
-    if (msg.reportType === 'farm_report' || msg.messageType === 'report') {
-        const params = {
-            farmId: msg.reportId || msg.content?.reportId,
-            showFilter: true,
-        }
-        router.push(`/farm_report?miniJson=${JSON.stringify(params)}`);
-    } else {
-        console.log('其他文件');
-    }
-}
-
-// 页面加载时自动添加欢迎消息
-onMounted(() => {
-    createSession(route.query.userId);
-    scrollToBottom();
-});
-
-//聊天会话
-const createSession = (targetUserId, callback) => {
-    VE_API.bbs.createSession({ farmId: storeFarmId.value, targetUserId }).then(({ data, code }) => {
-        if (code === 0) {
-            senderIcon.value = localUserInfoIcon;
-            receiverIcon.value = data.session.targetUserAvatar;
-            messages.value = data.messages.map((item) => {
-                let content = item.content;
-                if (item.messageType === "image") {
-                    // 优先读取后端的 image 字段,其次兼容旧的 content(JSON)
-                    if (item.image && (item.image.url || item.image.originUrl)) {
-                        content = item.image.url || item.image.originUrl;
-                    } else if (item.content) {
-                        try {
-                            const imgObj = JSON.parse(item.content);
-                            content = imgObj.url || imgObj.originUrl;
-                        } catch (e) {
-                            console.error(e, "e");
-                        }
-                    }
-                } else if (item.messageType !== 'text') {
-                    content = JSON.parse(item.content);
-                }
-                return {
-                    ...item,
-                    content,
-                    sender: item.senderId === curUserId ? "sent" : "received",
-                    senderIcon: item.senderId === curUserId ? localUserInfoIcon : data.session.targetUserAvatar,
-                    receiverIcon: data.session.targetUserAvatar,
-                };
-            });
-
-            setTimeout(() => {
-                scrollToBottom();
-            }, 300);
-            callback && callback();
-
-            // 初始化mqtt
-            initMqtt();
-        }
-    });
-};
-
-onDeactivated(() => {
-    mqttClient.value && mqttClient.value.client.end(true);
-});
-</script>
-
-<style scoped lang="scss">
-.consult {
-    width: 100%;
-    height: calc(100vh - 40px);
-    box-sizing: border-box;
-
-    .consult-content {
-        width: 100%;
-        height: 100%;
-        display: flex;
-        flex-direction: column;
-        position: relative;
-    }
-}
-
-/* 聊天消息区域样式 */
-.chat-messages {
-    flex: 1;
-    padding: 12px;
-    overflow-y: auto;
-    background-color: #fff;
-    box-sizing: border-box;
-
-    .message {
-        display: flex;
-        margin-bottom: 15px;
-    }
-
-    .received {
-        justify-content: flex-start;
-
-        .bubble {
-            background-color: #F4F5F8;
-            border-radius: 0 10px 10px 10px;
-            padding: 10px 12px;
-            box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
-
-            .content {
-                font-size: 16px;
-                color: #666666;
-            }
-        }
-    }
-
-    .sent {
-        justify-content: flex-end;
-
-        .bubble {
-            background-color: #07c160;
-            border-radius: 10px 0 10px 10px;
-            padding: 10px 15px;
-            box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
-
-            .content {
-                font-size: 16px;
-                color: #000;
-            }
-        }
-        .question-message {
-            .question-title{
-                color: #000;
-            }
-        }
-    }
-
-    .avatar {
-        width: 40px;
-        height: 40px;
-        border-radius: 50%;
-        background-color: #07c160;
-        color: white;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        margin-right: 10px;
-        font-weight: bold;
-    }
-
-    .avatar-r {
-        margin: 0 0 0 10px;
-    }
-
-    .bubble {
-        max-width: 70%;
-    }
-}
-
-
-
-.input-area {
-    display: flex;
-    align-items: center;
-    padding: 15px 10px;
-    border-top: 1px solid #e6e6e6;
-    background-color: white;
-    position: relative;
-    width: 100%;
-    box-sizing: border-box;
-
-    input {
-        flex: 1;
-        padding: 10px;
-        border: 1px solid #e6e6e6;
-        border-radius: 20px;
-        outline: none;
-    }
-
-    .send {
-        margin-left: 10px;
-        padding: 8px 20px;
-        background-color: #07c160;
-        color: white;
-        border: none;
-        border-radius: 20px;
-        cursor: pointer;
-    }
-}
-
-/* 新增的多媒体消息样式 */
-.image-message {
-    img {
-        max-width: 200px;
-        max-height: 200px;
-        border-radius: 8px;
-    }
-}
-
-/* 图片消息不使用对话气泡样式 */
-.no-bubble {
-    background: transparent !important;
-    border-radius: 0 !important;
-    padding: 0 !important;
-    box-shadow: none !important;
-    color: inherit !important;
-}
-
-/* 工具栏样式 */
-.toolbar {
-    display: flex;
-    align-items: center;
-
-    button {
-        background: none;
-        border: none;
-        font-size: 20px;
-        margin-right: 10px;
-        cursor: pointer;
-        padding: 5px;
-    }
-
-    .link {
-        font-size: 24px;
-        margin-right: 10px;
-    }
-}
-
-/* 图片预览 */
-.image-preview {
-    position: fixed;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    background: rgba(0, 0, 0, 0.8);
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    z-index: 1000;
-}
-
-.image-preview img {
-    max-width: 90%;
-    max-height: 90%;
-    object-fit: contain;
-}
-
-/* 对话样式消息 */
-.dialog-message {
-    max-width: 100%;
-    background: #fff !important;
-    border-radius: 10px;
-
-    .report-title {
-        font-size: 16px;
-        font-weight: 600;
-        color: #000;
-        margin-bottom: 5px;
-    }
-
-    .dialog-title {
-        font-size: 12px;
-        color: rgba(0, 0, 0, 0.6);
-        margin-bottom: 10px;
-    }
-
-    .monitor-image {
-        width: 222px;
-        height: 180px;
-        object-fit: cover;
-    }
-
-    .farm-report-content,
-    .farm-work-content {
-
-        .report-details,
-        .work-details {
-            background: #f8f9fa;
-            border-radius: 8px;
-            padding: 12px;
-            margin-top: 10px;
-
-            .detail-item {
-                display: flex;
-                margin-bottom: 6px;
-                font-size: 13px;
-
-                &:last-child {
-                    margin-bottom: 0;
-                }
-
-                .detail-label {
-                    color: #666;
-                    min-width: 80px;
-                }
-
-                .detail-value {
-                    color: #333;
-                    flex: 1;
-                }
-            }
-        }
-    }
-}
-
-.question-message {
-    .question-title {
-        font-size: 16px;
-        color: #666666;
-        margin-bottom: 6px;
-    }
-
-    .image-wrap {
-        display: flex;
-        // flex-wrap: wrap;
-        gap: 10px;
-
-        img {
-            width: 75px;
-            height: 70px;
-            border-radius: 8px;
-            object-fit: cover;
-        }
-    }
-
-    .btn-detail {
-        font-size: 14px;
-        margin-top: 8px;
-        background: #FFFFFF;
-        border-radius: 6px;
-        text-align: center;
-        padding: 6px;
-    }
-}
-
-/* 我方消息中的对话样式 */
-.message.sent .dialog-message {
-    background: #e3f2fd;
-
-    .work-details {
-        background: #f0f8ff;
-    }
-}
-</style>

+ 0 - 66
src/views/old_mini/chat_frame/index.vue

@@ -1,66 +0,0 @@
-<template>
-    <div class="dialogue">
-        <custom-header :name="nameVal || '飞鸟种植助手'" bgColor="#f2f3f5" isGoBack @goback="headerCallBack"></custom-header>
-        <chat-window :text="desc" :userId="userIdVal" :img="imgVal" @update:name="nameVal = $event"></chat-window>
-    </div>
-</template>
-
-<script setup>
-import customHeader from "@/components/customHeader.vue";
-import { onActivated, ref } from "vue";
-import chatWindow from "@/components/chatWindow";
-import { useRoute, useRouter } from "vue-router";
-
-const route = useRoute();
-const router = useRouter();
-const desc = ref("");
-const nameVal = ref("");
-const userIdVal = ref(null);
-const imgVal = ref("");
-const formPageVal = ref("");
-onActivated(() => {
-    userIdVal.value = null;
-    setTimeout(() => {
-        const { text, formPage, userId, img } = route.query;
-        desc.value = text;
-        userIdVal.value = userId;
-        imgVal.value = img;
-        formPageVal.value = formPage;
-        if(formPage) {
-            sessionStorage.setItem('chat_frame_page', formPage);
-        }
-    }, 100);
-});
-
-function headerCallBack() {
-    const page = sessionStorage.getItem('chat_frame_page');
-    if(page === 'messageList' || page === 'monitor') {
-        VE_API.bbs.readUpdate({ targetUserId: userIdVal.value, farmId: route.query.farmId }).then((res) => {
-            if (res.code === 0) {
-                sessionStorage.removeItem('chat_frame_page');
-                router.replace({ path: '/message_list', query: { farmId: route.query.farmId, from: 'monitor' } });
-            }
-        });
-    } else {
-        router.go(-1);
-    }
-}
-</script>
-
-<style lang="scss" scoped>
-.dialogue {
-    width: 100%;
-    height: calc(100vh - 40px);
-    background: #f2f3f5;
-    box-sizing: border-box;
-    .chat-container {
-        display: flex;
-        flex-direction: column;
-        height: 100%;
-        width: 100%;
-        margin: 0 auto;
-        border: 1px solid #e6e6e6;
-        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
-    }
-}
-</style>

+ 0 - 483
src/views/old_mini/home/subPages/expertList.vue

@@ -1,483 +0,0 @@
-<template>
-    <div class="prescription-list">
-        <custom-header v-if="!isShowHeader" :name="isToSelect ? '选择专家' : '咨询专家'"></custom-header>
-        <div class="prescription-filter">
-            <div class="filter-search">
-                <el-input v-model="keyword" style="width: 100%" placeholder="搜索位置" :prefix-icon="Search" />
-            </div>
-            <div class="select-box">
-                <div class="select-item width-30">
-                    <el-select v-model="typeVal" placeholder="品种" @change="getList">
-                        <el-option v-for="item in typeOptions" :key="item.id" :label="item.name" :value="item.id" />
-                    </el-select>
-                </div>
-                <div class="select-item width-20">
-                    <el-select v-model="regionVal" placeholder="城市">
-                        <el-option
-                            v-for="item in regionOptions"
-                            :key="item.value"
-                            :label="item.label"
-                            :value="item.value"
-                        />
-                    </el-select>
-                </div>
-                <div class="select-item width-30">
-                    <el-select v-model="levelVal" placeholder="专家擅长">
-                        <el-option
-                            v-for="item in levelOptions"
-                            :key="item.value"
-                            :label="item.label"
-                            :value="item.value"
-                        />
-                    </el-select>
-                </div>
-                <div class="select-item width-20">
-                    <el-select v-model="levelVal" placeholder="筛选">
-                        <el-option
-                            v-for="item in levelOptions"
-                            :key="item.value"
-                            :label="item.label"
-                            :value="item.value"
-                        />
-                    </el-select>
-                </div>
-            </div>
-        </div>
-        <div class="prescription-content">
-            <div class="list">
-                <div class="list-item" v-for="(item, index) in list" :key="index">
-                    <div class="list-top">
-                        <div class="user">
-                            <!-- <img :src="item.pic" alt="" /> -->
-                            <img v-show="index === 0" :src="require(`@/assets/img/home/zj-1.png`)" alt="" />
-                            <img v-show="index === 1" :src="require(`@/assets/img/home/zj-2.png`)" alt="" />
-                            <img v-show="index === 2" :src="require(`@/assets/img/home/zj-3.png`)" alt="" />
-                            <!-- <div class="checkbox" @click.stop="handleCheck(item)">
-                                <el-icon class="icon" v-if="item.isDefault"><Select /></el-icon>
-                                <el-icon class="icon rotate" v-else><CloseBold /></el-icon>
-                            </div> -->
-                        </div>
-                        <div class="info">
-                            <div class="text">
-                                <div class="info-flex">
-                                    <span class="name">{{ item.name }}</span>
-                                    <!-- <span class="expert-tag">
-                                        <img class="expert-img" src="@/assets/img/home/expert-icon.png" alt="">
-                                        专家
-                                    </span> -->
-                                    <div class="fruit-tag" v-for="(ele, eleIndex) in item.tagList" :key="eleIndex">
-                                        {{ ele.name }}
-                                    </div>
-                                </div>
-                                <div class="add-btn">
-                                    <el-icon size="16" color="#fff"><Plus /></el-icon>
-                                </div>
-                            </div>
-                            <div class="van-multi-ellipsis--l2 ellipsis">擅长:{{ item.strongPoint }}</div>
-
-                            <div class="list-btn">
-                                <div class="btn-primary" @click.stop="toPage(item)">
-                                    <span>免费咨询</span>
-                                </div>
-                                <div class="btn-plain" @click.stop="handlePage(item)">查看处方</div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-                <empty
-                    v-show="list.length < 1"
-                    image="https://fastly.jsdelivr.net/npm/@vant/assets/custom-empty-image.png"
-                    image-size="80"
-                    description="暂无数据"
-                />
-            </div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import customHeader from "@/components/customHeader.vue";
-import { Empty } from "vant";
-import { onMounted, ref } from "vue";
-import { useRouter, useRoute } from "vue-router";
-import { useStore } from "vuex";
-import { ElMessage } from "element-plus";
-import { Search } from "@element-plus/icons-vue";
-const store = useStore();
-const router = useRouter();
-const route = useRoute();
-
-const props = defineProps({
-    isShowHeader: {
-        type: Boolean,
-        default: false,
-    },
-});
-
-const isToSelect = route.query.isToSelect ? true : false;
-
-const handlePage = ({ isDefault, userId }) => {
-    if (isDefault == null) {
-        console.log("isDefault", isDefault);
-        // router.push(`/expert_prescription?userId=${userId}&disabled=true`)
-    } else {
-        router.push("/expert_prescription");
-    }
-};
-
-const typeOptions = ref([]);
-
-function getSpecieList() {
-    VE_API.farm.fetchSpecieList().then(({ data }) => {
-        typeOptions.value = data;
-
-        // getList(data[0].id);
-    });
-}
-
-const list = ref([
-    {
-        containerId: "9",
-        expertId: "739294587868155904",
-        name: "冼继东",
-        strongPoint: "擅长:长期从事农业昆虫与害虫防治教学与研究工作。取得成果和奖励10项,发表学术论文50余篇。多年来一直致力于果树、蔬菜以及水稻主要病虫害非化学防控技术的推广工作,为有机荔枝龙眼、稻米、蔬菜以及多种水果的高效、安全生产提供技术指导。",
-        tagList: [
-            {
-                id: 825,
-                name: "荔枝",
-                remark: "花穗生长速度过慢",
-            },
-            {
-                id: 829,
-                name: "病虫害",
-                remark: "防止落果",
-            },
-        ],
-        userId: 81881,
-    },
-    {
-        containerId: "9",
-        expertId: "739294587868155904",
-        name: "韦帮稳",
-        pic: "https://birdseye-img-ali-cdn.sysuimars.com//expert/1757473957076.png",
-        strongPoint: "擅长:深耕果树栽培领域达30年,在荔枝、龙眼、柑橘、番茄、木瓜等多个品类果树具有非常丰富的种植栽培经验;自管荔枝果园超2000亩,每年指导海南、湛江、茂名、广州、汕尾、惠州、广西等多地的种植户超百户,面积超1万亩!",
-        tagList: [
-            {
-                id: 825,
-                name: "荔枝",
-                remark: "花穗生长速度过慢",
-            },
-            {
-                id: 829,
-                name: "龙眼",
-                remark: "防止落果",
-            },
-        ],
-        userId: 81881,
-    },
-    {
-        containerId: "9",
-        expertId: "739294587868155904",
-        name: "黄旭明",
-        pic: "https://birdseye-img-ali-cdn.sysuimars.com//expert/1757473957076.png",
-        strongPoint: "擅长:长期从事南方果树生理学研究,研究领域包括常绿果树枝梢生长节奏及调控、具假种皮果实果皮发育、细胞壁代谢和钙营养与生理病害发生关系、果实膨大生长与水分关系等。研究方向为果树生态生理学。1998年获华南农业大学植物生理学博士学位,现任南方果树研究室主任。",
-        tagList: [
-            {
-                id: 825,
-                name: "荔枝",
-                remark: "花穗生长速度过慢",
-            },
-            {
-                id: 829,
-                name: "龙眼",
-                remark: "防止落果",
-            },
-        ],
-        userId: 81881,
-    },
-]);
-
-const getList = (speciesId) => {
-    VE_API.home.fetchExpertList({ speciesId }).then(({ data }) => {
-        list.value = data || [];
-    });
-};
-
-onMounted(() => {
-    getSpecieList();
-});
-
-function toPage({ containerId, userId, name }) {
-    if (isToSelect) {
-        router.push(`/expert_homepage?containerId=${containerId}`);
-        // router.replace(`/expert_homepage?containerId=${containerId}`)
-    } else {
-        router.push(`/chat_frame?userId=${userId}`);
-    }
-}
-
-// 搜索
-const keyword = ref(null);
-const typeVal = ref(null);
-const regionVal = ref(null);
-const levelVal = ref(null);
-
-const regionOptions = ref([
-    {
-        label: "全部",
-        value: "all",
-    },
-    {
-        label: "区域1",
-        value: "1",
-    },
-    {
-        label: "区域2",
-        value: "2",
-    },
-    {
-        label: "区域3",
-        value: "3",
-    },
-]);
-
-const levelOptions = ref([
-    { label: "全部", value: "all" },
-    { label: "荔枝", value: "1" },
-    { label: "龙眼", value: "2" },
-    { label: "枇杷", value: "3" },
-]);
-</script>
-
-<style lang="scss" scoped>
-.prescription-list {
-    position: relative;
-    width: 100%;
-    height: 100vh;
-    background-color: #f5f7fb;
-    .prescription-filter {
-        padding: 12px 12px 0 12px;
-        .filter-search {
-            padding-bottom: 6px;
-            ::v-deep {
-                .el-input__wrapper {
-                    box-shadow: 0 0 0 1px #fff inset;
-                    border-radius: 20px;
-                }
-            }
-        }
-        .select-box {
-            width: 100%;
-            display: flex;
-            justify-content: space-around;
-            .select-item {
-                width: fit-content;
-                ::v-deep {
-                    .el-input__wrapper {
-                        background: none;
-                        box-shadow: none;
-                    }
-                    .el-input__inner {
-                        font-size: 14px;
-                        color: rgba(0, 0, 0, 0.5);
-                    }
-                    .el-select__wrapper {
-                        background: none;
-                        box-shadow: none;
-                        gap: 2px;
-                        padding: 4px 2px;
-                        justify-content: center;
-                    }
-                    .el-select__selection {
-                        flex: none;
-                        width: fit-content;
-                    }
-                    .el-select__placeholder {
-                        color: rgba(0, 0, 0, 0.5);
-                        position: static;
-                        transform: none;
-                        width: fit-content;
-                    }
-                }
-            }
-            .width-30 {
-                width: 30%;
-            }
-            .width-20 {
-                width: 20%;
-            }
-        }
-    }
-    .prescription-content {
-        overflow-y: auto;
-        height: calc(100% - 40px);
-        padding: 6px 12px 12px;
-        box-sizing: border-box;
-        width: 100%;
-        .list {
-            position: relative;
-            .list-item {
-                background: #fff;
-                padding: 16px 12px 12px;
-                border-radius: 8px;
-                .user {
-                    width: 68px;
-                    height: 68px;
-                    margin-right: 12px;
-                    position: relative;
-                    img {
-                        width: 100%;
-                        height: 100%;
-                        border-radius: 8px;
-                        object-fit: scale-down;
-                    }
-                    .checkbox {
-                        position: absolute;
-                        bottom: -2px;
-                        right: -1px;
-                        width: 25px;
-                        height: 25px;
-                        background: #2199f8;
-                        border-radius: 50%;
-                        display: flex;
-                        align-items: center;
-                        justify-content: center;
-                        .icon {
-                            color: #fff;
-                            font-size: 16px;
-                        }
-                        .rotate {
-                            transform: rotate(45deg);
-                        }
-                    }
-                }
-                .list-top {
-                    display: flex;
-                    img{
-                        border-radius: 50%;
-                        object-fit: cover;
-                    }
-                }
-                .list-btn {
-                    display: flex;
-                    // justify-content: center;
-                    font-size: 12px;
-                    margin-top: 8px;
-                    .btn-primary {
-                        background: rgba(33, 153, 248, 0.12);
-                        padding: 0 12px;
-                        color: #2199f8;
-                        border-radius: 20px;
-                        height: 32px;
-                        line-height: 32px;
-                        display: flex;
-                        span {
-                            margin-left: 3px;
-                        }
-                    }
-                    .btn-plain {
-                        background: rgba(162, 162, 162, 0.12);
-                        color: rgba(0, 0, 0, 0.5);
-                        padding: 0px 12px;
-                        border-radius: 20px;
-                        height: 32px;
-                        line-height: 32px;
-                        margin-left: 8px;
-                    }
-                }
-                .info {
-                    width: calc(100% - 78px);
-                    line-height: 1.6;
-                    .ellipsis {
-                        max-width: 255px;
-                        color: #666666;
-                    }
-                    .text {
-                        display: flex;
-                        color: #666666;
-                        align-items: center;
-                        justify-content: space-between;
-                        .info-flex {
-                            display: flex;
-                            align-items: center;
-                        }
-                        .add-btn {
-                            width: 26px;
-                            height: 26px;
-                            border-radius: 50%;
-                            background: #2199f8;
-                            text-align: center;
-                            display: flex;
-                            align-items: center;
-                            justify-content: center;
-                        }
-                        .name {
-                            color: #000;
-                            font-size: 16px;
-                            font-weight: bold;
-                        }
-                        .expert-tag {
-                            height: 20px;
-                            width: 48px;
-                            display: flex;
-                            align-items: center;
-                            justify-content: center;
-                            color: #c77d05;
-                            background: #ffecad;
-                            border-radius: 4px;
-                            font-size: 12px;
-                            margin-left: 8px;
-                            line-height: 20px;
-                            .expert-img {
-                                width: 12px;
-                                padding-right: 2px;
-                            }
-                        }
-                        .btn-text {
-                            font-size: 12px;
-                            color: #a8a8a8;
-                            padding: 2px 12px;
-                            border-radius: 20px;
-                            border: 1px solid #a8a8a8;
-                            background: rgba(220, 220, 220, 0.1);
-                            &.actice {
-                                color: #f3c11d;
-                                border-color: #f3c11d;
-                                background: rgba(243, 193, 29, 0.1);
-                            }
-                        }
-                    }
-                    .fruit-tag {
-                        margin-left: 5px;
-                        padding: 0 8px;
-                        height: 20px;
-                        line-height: 20px;
-                        background: #cae7ff;
-                        border-radius: 2px;
-                        font-size: 12px;
-                        color: #2199f8;
-                        // &.pest {
-                        //     background: #eedaff;
-                        //     color: #ac4dff;
-                        // }
-                        &:nth-child(3) {
-                            background: #eedaff;
-                            color: #ac4dff;
-                        }
-                    }
-                    .ellipsis {
-                        font-size: 12px;
-                        color: #999;
-                        margin-top: 4px;
-                    }
-                }
-            }
-            .list-item + .list-item {
-                margin-top: 16px;
-                padding-top: 16px;
-                border-top: 1px solid #f5f5f5;
-            }
-        }
-    }
-}
-</style>

+ 0 - 205
src/views/old_mini/home/subPages/knowledgeList.vue

@@ -1,205 +0,0 @@
-<template>
-    <div class="service-records-page">
-        <custom-header name="知识库"></custom-header>
-        <div class="record-list">
-            <list v-model:loading="listLoading" :finished="listFinished" finished-text="" @load="getKnowledgeList">
-                <div v-for="(item, index) in knowledgeList" :key="index" class="record-card">
-                    <img class="thumb" :src="item.media && item.media[0]" alt="暂无图片" />
-                    <div class="card-body" @click="handleItemClick(item)">
-                        <div class="card-body-left">
-                            <div class="title van-multi-ellipsis--l2">{{ item.title }}</div>
-                            <div class="date">{{ formatDate(item.createTime) }}</div>
-                        </div>
-                    </div>
-                </div>
-
-                <!-- 加载完成且无数据时的空状态 -->
-                <div v-if="!knowledgeList.length && listFinished" class="empty-wrap">
-                    <div class="empty-text">暂无数据</div>
-                </div>
-            </list>
-        </div>
-    </div>
-</template>
-<script setup>
-import { ref, onMounted, watch, onActivated } from "vue";
-import customHeader from "@/components/customHeader.vue";
-import { List } from "vant";
-import { useRouter, useRoute } from "vue-router";
-import { useStore } from "vuex";
-
-const router = useRouter();
-const route = useRoute();
-const store = useStore();
-
-// 服务记录列表数据
-const knowledgeList = ref([]);
-const topicId = ref(6);
-
-// 分页与滚动加载状态
-const page = ref(1);
-const pageSize = ref(10);
-const listLoading = ref(false);
-const listFinished = ref(false);
-// 存储全部数据(用于 topicId === 6 时的前端分页)
-const allDataCache = ref([]);
-
-// 重置列表状态
-const resetListState = () => {
-    knowledgeList.value = [];
-    page.value = 1;
-    listFinished.value = false;
-    allDataCache.value = [];
-};
-
-// 初始化或重置时加载数据
-const initList = () => {
-    resetListState();
-    // 重置后触发首次加载
-    getKnowledgeList();
-};
-
-onMounted(() => {
-    // 从路由获取当前知识库类型
-    topicId.value = Number(route.query.topicId) || 6;
-    // 不主动请求,交给 vant List 的 @load 触发首次加载
-});
-
-// 监听路由参数变化
-watch(
-    () => route.query.topicId,
-    (newTopicId) => {
-        const newId = Number(newTopicId) || 6;
-        if (newId !== topicId.value) {
-            topicId.value = newId;
-            initList();
-        }
-    }
-);
-
-// 页面激活时也检查参数变化
-onActivated(() => {
-    const newId = Number(route.query.topicId) || 6;
-    if (newId !== topicId.value) {
-        topicId.value = newId;
-        initList();
-    }
-});
-
-const getKnowledgeList = async () => {
-    if (listFinished.value) return;
-
-    listLoading.value = true;
-
-    try {
-        let list = [];
-        // 实战知识库:使用原接口(支持分页)
-        const params = {
-            page: page.value,
-            limit: pageSize.value,
-            topicId: topicId.value,
-        };
-        const { data } = await VE_API.home.warningPageList(params);
-        list = data || [];
-
-        if (page.value === 1) {
-            knowledgeList.value = list;
-        } else {
-            knowledgeList.value = [...knowledgeList.value, ...list];
-        }
-
-        // 如果返回数量小于页大小,认为没有更多数据了
-        if (list.length < pageSize.value) {
-            listFinished.value = true;
-        } else {
-            page.value += 1;
-        }
-    } catch (error) {
-        console.error("获取知识列表失败:", error);
-        listFinished.value = true;
-    } finally {
-        listLoading.value = false;
-    }
-};
-
-const formatDate = (dateStr) => {
-    if (!dateStr) return "";
-    // 将 2026-01-06T00:00:00 格式转换为 2026-01-06
-    return dateStr.split("T")[0];
-};
-
-const handleItemClick = (item) => {
-    router.push(`/warning_detail?id=${item.id}&showImage=true`);
-};
-</script>
-<style lang="scss" scoped>
-.service-records-page {
-    width: 100%;
-    background: #f5f5f5;
-    height: 100vh;
-
-    .record-list {
-        padding: 10px 12px;
-        display: flex;
-        flex-direction: column;
-        gap: 10px;
-        height: calc(100% - 60px);
-        overflow-y: auto;
-    }
-
-    .record-card {
-        display: flex;
-        gap: 12px;
-        padding: 12px 10px;
-        background: #ffffff;
-        border-radius: 12px;
-        align-items: center;
-        height: 98px;
-        box-sizing: border-box;
-
-        .thumb {
-            width: 112px;
-            height: 74px;
-            border-radius: 8px;
-            object-fit: cover;
-            flex: none;
-        }
-
-        .card-body {
-            flex: 1;
-            height: 100%;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-
-            .card-body-left {
-                width: 100%;
-                height: 95%;
-                display: flex;
-                flex-direction: column;
-                justify-content: space-between;
-
-                .date {
-                    font-size: 13px;
-                    color: #86909c;
-                    margin-top: 4px;
-                }
-            }
-        }
-    }
-
-    .record-card+.record-card {
-        margin-top: 10px;
-    }
-
-    .empty-wrap {
-        padding-top: 40px;
-        text-align: center;
-
-        .empty-text {
-            font-size: 14px;
-            color: #86909c;
-        }
-    }
-}
-</style>

+ 260 - 0
src/views/old_mini/interaction/index.vue

@@ -0,0 +1,260 @@
+<template>
+    <div class="interaction-page">
+        <custom-header name="农情互动" :showClose="false" :isGoBack="false" />
+        <div class="interaction-content">
+            <!-- 顶部说明 -->
+            <div class="intro-card">
+                完善作物品种以及物候信息,精准匹配种植方案,实现精细化管理
+            </div>
+
+            <!-- 作物块 -->
+            <div v-for="crop in crops" :key="crop.id" class="crop-section">
+                <div class="crop-header">
+                    <div class="crop-tag">{{ crop.name }}</div>
+                    <div class="add-btn" @click="addVariety(crop)">+ 新增品种</div>
+                </div>
+
+                <div v-for="variety in crop.varieties" :key="variety.id" class="variety-card">
+                    <div class="field-row">
+                        <div class="field-value">
+                            <el-select v-model="variety.variety" class="variety-input" placeholder="选择品种">
+                                <el-option v-for="item in varietyOptions" :key="item.value" :label="item.label"
+                                    :value="item.value" />
+                            </el-select>
+                        </div>
+                    </div>
+
+                    <div class="field-row">
+                        <div class="field-label">当下物候期</div>
+                        <div class="field-value">
+                            <el-select v-model="variety.currentStage" class="select-input" placeholder="选择物候期"
+                                >
+                                <el-option v-for="item in stageOptions" :key="item.value" :label="item.label"
+                                    :value="item.value" />
+                            </el-select>
+                        </div>
+                    </div>
+
+                    <div class="field-row">
+                        <div class="field-label">第一批花穗时间</div>
+                        <div class="field-value">
+                            <el-date-picker style="width: 100%" v-model="variety.firstFlowerDate" class="date-picker" type="date"
+                                placeholder="选择时间" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref } from "vue";
+import customHeader from "@/components/customHeader.vue";
+
+// 简单示例数据,后续可替换为接口返回
+const crops = ref([
+    {
+        id: 1,
+        name: "荔枝",
+        varieties: [
+            {
+                id: 1,
+                variety: "",
+                currentStage: "花穗期",
+                firstFlowerDate: "",
+            },
+        ],
+    },
+    {
+        id: 2,
+        name: "水稻",
+        varieties: [
+            {
+                id: 1,
+                variety: "",
+                currentStage: "花穗期",
+                firstFlowerDate: "",
+            },
+        ],
+    },
+]);
+
+const addVariety = (crop) => {
+    const nextId = crop.varieties.length + 1;
+    crop.varieties.push({
+        id: nextId,
+        variety: "",
+        currentStage: "花穗期",
+        firstFlowerDate: "",
+    });
+};
+
+// 品种下拉选项(示例)
+const varietyOptions = ref([
+    { label: "桂味", value: "桂味" },
+    { label: "糯米糍", value: "糯米糍" },
+    { label: "妃子笑", value: "妃子笑" },
+    { label: "井岗红糯", value: "井岗红糯" },
+]);
+
+// 物候期选项(示例)
+const stageOptions = ref([
+    { label: "花穗期", value: "花穗期" },
+    { label: "萌芽期", value: "萌芽期" },
+    { label: "抽梢期", value: "抽梢期" },
+    { label: "坐果期", value: "坐果期" },
+]);
+</script>
+
+<style lang="scss" scoped>
+.interaction-page {
+    height: 100vh;
+    box-sizing: border-box;
+    background: #F2F4F5;
+    font-size: 14px;
+    color: #1d2129;
+}
+
+.interaction-content {
+    height: calc(100% - 40px);
+    overflow: auto;
+    padding: 10px;
+    box-sizing: border-box;
+}
+
+.intro-card {
+    padding: 10px;
+    border-radius: 6px;
+    background: #ffffff;
+    color: #666666;
+    box-shadow: 0 2px 8px rgba(15, 35, 52, 0.06);
+    margin-bottom: 12px;
+    line-height: 17px;
+}
+
+.crop-section {
+    background: #ffffff;
+    border-radius: 6px;
+    padding: 10px;
+    box-shadow: 0 2px 8px rgba(15, 35, 52, 0.04);
+    margin-bottom: 10px;
+}
+
+.crop-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 10px;
+
+    .crop-tag {
+        padding: 0 16px;
+        border-radius: 2px;
+        background: #2199F8;
+        color: #ffffff;
+        font-size: 14px;
+        height: 26px;
+        line-height: 26px;
+    }
+
+    .add-btn {
+        padding: 0 12px;
+        border-radius: 4px;
+        height: 26px;
+        line-height: 26px;
+        box-sizing: border-box;
+        border: 0.5px solid rgba(33, 153, 248, 0.5);
+        color: #0B84E4;
+    }
+}
+
+.variety-card {
+    margin-top: 8px;
+    padding: 10px;
+    border-radius: 5px;
+    background: rgba(33, 153, 248, 0.05);
+    border: 1px solid rgba(33, 153, 248, 0.2);
+}
+
+.field-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 10px;
+
+    &:last-child {
+        margin-bottom: 0;
+    }
+}
+
+.field-label {
+    width: 118px;
+    flex: none;
+    font-size: 14px;
+    color: #1D2129;
+}
+
+.field-value {
+    flex: 1;
+}
+
+.select-input,
+.date-picker {
+    width: 100%;
+}
+
+.variety-input {
+    width: 110px;
+    ::v-deep {
+        .el-select__wrapper {
+            box-shadow: none;
+            background-color: rgba(33, 153, 248, 0.1);
+            // box-shadow: 0 0 0 1px var(--el-border-color) inset;
+        }
+        .el-select__placeholder {
+            color: #2199F8;
+        }
+        .el-select__caret {
+            color: #2199F8;
+        }
+    }
+}
+
+.fake-select {
+    height: 32px;
+    border-radius: 4px;
+    border: 1px solid rgba(0, 0, 0, 0.08);
+    background: #ffffff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 8px;
+    box-sizing: border-box;
+
+    .text {
+        color: #1d2129;
+        font-size: 14px;
+    }
+
+    .arrow {
+        font-size: 10px;
+        color: #c0c4cc;
+    }
+
+    &.fake-select--plain {
+        background: #ffffff;
+    }
+}
+
+.date-input {
+    height: 32px;
+    border-radius: 4px;
+    border: 1px dashed rgba(33, 153, 248, 0.6);
+    background: #ffffff;
+    display: flex;
+    align-items: center;
+    padding: 0 8px;
+    box-sizing: border-box;
+    color: #c0c4cc;
+    font-size: 14px;
+}
+</style>

+ 0 - 2476
src/views/old_mini/modify_work/modify.vue

@@ -1,2476 +0,0 @@
-<template>
-    <div class="new-farming-page" ref="pageRef">
-        <custom-header :name="isEdit ? (onlyPrice ? '编辑报价' : '编辑方案') : '查看详情'"></custom-header>
-        <div class="new-farming-content" :class="{ 'no-permission': !hasPlanPermission }">
-            <el-form
-                ref="formRef"
-                style="max-width: 600px"
-                label-position="left"
-                :rules="rules"
-                :model="dynamicValidateForm"
-                class="demo-dynamic"
-            >
-                <div class="farm-card">
-                    <div class="card-title between common-inputs">
-                        <div>{{ detailData?.name }}<span class="type-tag">标准农事</span></div>
-                        <el-select v-if="isEdit" size="small" v-model="tagName" placeholder="标记为" style="width: 94px">
-                            <el-option
-                                v-for="item in tagList"
-                                :key="item.value"
-                                :label="item.label"
-                                :value="item.value"
-                            />
-                        </el-select>
-                        <div class="edit-tag tag-text" v-else>{{ statusMap[tagName] }}</div>
-                        <!-- <el-tooltip
-                            effect="dark"
-                            placement="left"
-                        >
-                            <template #content>
-                                <div class="tag-item">全托管</div>
-                                <div class="tag-item">飞防托管</div>
-                                <div class="tag-item">营养托管</div>
-                            </template>
-                            <div class="title-tag add-tag">托管用户</div>
-                        </el-tooltip> -->
-                    </div>
-                    <div class="info-content">
-                        <el-form-item label-width="70px" class="form-item text-item" label="农事编号">
-                            <div class="info-text">
-                                {{ detailData?.code }}
-                            </div>
-                        </el-form-item>
-                        <el-form-item v-if="!noPrice" label-width="70px" class="form-item text-item" label="服务亩数">
-                            <div class="info-text">
-                                {{ detailData?.farm?.mianji ? formatArea(detailData?.farm?.mianji) + "亩" : "--" }}
-                            </div>
-                        </el-form-item>
-                        <el-form-item v-if="!noPrice" label-width="70px" class="form-item text-item" label="服务区域">
-                            <div class="info-text">
-                                {{ detailData?.farm?.address || "--" }}
-                            </div>
-                        </el-form-item>
-                        <el-form-item
-                            v-if="isEdit"
-                            label-width="70px"
-                            class="form-item"
-                            prop="executeDate"
-                            label="执行时间"
-                        >
-                            <el-date-picker
-                                class="item-input"
-                                style="width: 100%"
-                                value-format="YYYY-MM-DD"
-                                v-model="dynamicValidateForm.executeDate"
-                                type="date"
-                                :clearable="false"
-                                placeholder="选择日期"
-                                :editable="false"
-                            />
-                        </el-form-item>
-                        <el-form-item v-else label-width="70px" class="form-item text-item" label="执行时间">
-                            <div class="info-text">
-                                {{ detailData?.executeDate }}
-                            </div>
-                        </el-form-item>
-                    </div>
-                </div>
-
-                <div class="farm-card" v-if="!onlyPrice">
-                    <!-- 农情互动 -->
-                    <div class="card-title border-bottom between">
-                        <div>农情互动</div>
-                        <!-- <span class="del-tag">删除互动</span> -->
-                    </div>
-                    <div v-if="isEdit" class="interact-form">
-                        <div class="interact-form-item" data-interact-field="phenologyId">
-                            <div class="form-label">
-                                互动阶段
-                            </div>
-                            <div class="form-input-wrapper two-select">
-                                <div class="select-item">
-                                    <el-select
-                                        style="width: 100%"
-                                        v-model="interactFormData.phenologyId"
-                                        placeholder="请选择物候期"
-                                        @change="handlePhenologyChange"
-                                        :editable="false">
-                                        <el-option
-                                            v-for="item in phenologyList"
-                                            :key="item.id"
-                                            :label="item.name"
-                                            :value="item.id"
-                                        ></el-option>
-                                    </el-select>
-                                </div>
-                                <div class="select-item">
-                                    <el-select style="width: 100%" v-model="interactFormData.reproductiveId" placeholder="请选择物候期" :editable="false">
-                                        <el-option
-                                            v-for="item in reproductiveList"
-                                            :key="item.id"
-                                            :label="item.name"
-                                            :value="item.id"
-                                        ></el-option>
-                                    </el-select>
-                                </div>
-                            </div>
-                        </div>
-                        <div class="interact-form-item" data-interact-field="interactionTime">
-                            <div class="form-label">
-                                互动日期
-                            </div>
-                            <div class="form-input-wrapper">
-                                <el-date-picker
-                                    v-model="interactFormData.interactionTime"
-                                    disabled
-                                    style="width: 100%"
-                                    type="date"
-                                    placeholder="请选择日期"
-                                    :editable="false"
-                                />
-                            </div>
-                        </div>
-                        <div class="interact-form-item" data-interact-field="interactionQuestion">
-                            <div class="form-label">
-                                互动问题
-                            </div>
-                            <el-input
-                                v-model="interactFormData.interactionQuestion"
-                                type="textarea"
-                                :rows="3"
-                                show-word-limit
-                                maxlength="35"
-                                placeholder="请设置互动问题"
-                                class="question-textarea"
-                            />
-                        </div>
-                    </div>
-                    <div v-else class="interact-content">
-                        {{ interactFormData?.interactionQuestion }}
-                        <!-- <span class="edit-tag" @click="handleEditInteract(detailData)">点击编辑</span> -->
-                    </div>
-                </div>
-
-                <template v-if="isEdit">
-                    <div class="farm-card prescription-content common-inputs">
-                        <div class="card-title pb-12 between">
-                            药物处方
-                            <div class="add-tag" @click="addDomain()">
-                                <el-icon color="#2199F8"><Plus /></el-icon>新增药物
-                            </div>
-                        </div>
-                        <el-form-item label-width="82px" class="form-item" prop="usageMode" label="施用方式">
-                            <el-select
-                                v-model="dynamicValidateForm.prescription.usageMode"
-                                placeholder="请选择施用方式"
-                                style="width: 100%"
-                            >
-                                <el-option
-                                    v-for="(usage, uId) in allUsageModeList"
-                                    :key="uId"
-                                    :label="usage"
-                                    :value="usage"
-                                />
-                            </el-select>
-                        </el-form-item>
-                        <el-form-item label-width="82px" class="form-item" prop="executeStyle" label="执行方式">
-                            <el-select
-                                    class="select-item"
-                                    v-model="dynamicValidateForm.executeStyle"
-                                    placeholder="执行方式"
-                                    @change="handleExecutionMethodChange"
-                                >
-                                    <el-option
-                                        v-for="(item, index) in modeList"
-                                        :key="index"
-                                        :label="item.name"
-                                        :value="item.value"
-                                    />
-                                </el-select>
-                        </el-form-item>
-                        
-                        <div v-if="dynamicValidateForm.prescription.usageMode !== '人工'">
-                            <el-form-item
-                                v-for="(domain, index) in dynamicValidateForm.prescription.pesticideFertilizerList"
-                                :key="index"
-                                :prop="'prescription.pesticideFertilizerList.' + index + '.value'"
-                                class="prescription-item"
-                            >
-                                <div class="recipe-item">
-                                    <div class="recipe-form">
-                                            <div class="form-box">
-                                                <div class="form-index">药肥{{ index + 1 }}</div>
-                                                <div class="box-item" v-if="domain.typeName">
-                                                    <div class="form-l">药肥类型</div>
-                                                    <div class="form-r r-text">
-                                                        {{ domain.typeName }}
-                                                    </div>
-                                                </div>
-                                                <div class="box-item">
-                                                    <div class="form-l">药肥名称</div>
-                                                    <div class="form-r">
-                                                        <el-select
-                                                            filterable
-                                                            @change="
-                                                                handlePesticideFertilizerChange(index)
-                                                            "
-                                                            v-model="domain.code"
-                                                            placeholder="请选择"
-                                                            style="width: 150px"
-                                                        >
-                                                            <el-option
-                                                                v-for="item in pesticideFertilizersOptions"
-                                                                :key="item.pesticideFertilizerCode"
-                                                                :label="item.defaultName || item.name"
-                                                                :value="item.pesticideFertilizerCode"
-                                                            />
-                                                        </el-select>
-                                                    </div>
-                                                </div>
-
-                                                <div class="mt-8">
-                                                    <div class="box-item sub-item" :data-ratio-index="index">
-                                                        <div class="form-l has-sub">
-                                                            <div class="main-name">药肥配比</div>
-                                                        </div>
-                                                        <div class="form-r input-box text-center input-unit">
-                                                            <el-input
-                                                                v-model="domain.ratio"
-                                                                type="number"
-                                                                step="0.01"
-                                                                style="width: 150px"
-                                                                :placeholder="domain.placeholderRatio || '请输入'"
-                                                            >
-                                                                <template #append>倍</template>
-                                                            </el-input>
-                                                        </div>
-                                                    </div>
-                                                    <div class="box-item sub-item" :data-dosage-index="index">
-                                                        <div class="form-l has-sub">
-                                                            <div class="main-name">单亩用量</div>
-                                                        </div>
-                                                        <div class="form-r input-box text-center">
-                                                            <el-input
-                                                                v-model="domain.dosage"
-                                                                type="number"
-                                                                step="0.01"
-                                                                style="width: 150px"
-                                                                :placeholder="domain.placeholderDosage || '请输入'"
-                                                            >
-                                                                <template #append>{{ domain.unit }}</template>
-                                                            </el-input>
-                                                        </div>
-                                                    </div>
-
-                                                    
-                                                    <div class="box-item">
-                                                        <div class="form-l">药肥品牌</div>
-                                                        <div class="form-r">
-                                                            <el-input
-                                                                v-model="domain.brand"
-                                                                placeholder="药肥品牌"
-                                                                style="width: 150px"
-                                                            />
-                                                        </div>
-                                                    </div>
-                                                    <div class="box-item">
-                                                        <div class="form-l">药肥单价</div>
-                                                        <div class="form-r">
-                                                            <el-input
-                                                                style="width: 150px"
-                                                                v-model="domain.price"
-                                                                type="number"
-                                                                step="0.01"
-                                                                placeholder="单价"
-                                                            >
-                                                                <template #append>元/{{ domain.unit }}</template>
-                                                            </el-input>
-                                                        </div>
-                                                    </div>
-
-                                                    
-
-                                                    <div v-if="!noPrice" class="medicine-item">
-                                                        <div class="item-total">总计:</div>
-                                                        <div class="item-price">
-                                                            {{ getPesticideTotal(domain) }}<span class="item-unit">元</span>
-                                                        </div>
-                                                    </div>
-                                                </div>
-                                                <!-- <div class="input-box mark-box">
-                                                    <el-input
-                                                        v-model="domain.remark"
-                                                        style="width: 100%"
-                                                        type="textarea"
-                                                        :rows="2"
-                                                        placeholder="备注:用药注意事项"
-                                                    />
-                                                </div> -->
-                                                <div class="action-btn">
-                                                    <el-button
-                                                        class="btn delete-btn"
-                                                        @click.prevent="removeDomain(prescriptionI, domain)"
-                                                    >
-                                                        删除
-                                                    </el-button>
-                                                    <el-button
-                                                        type="default"
-                                                        class="btn"
-                                                        @click.prevent="resetItemForm(prescriptionI, index)"
-                                                    >
-                                                        重置
-                                                    </el-button>
-                                                </div>
-                                            </div>
-                                        <!-- </el-form-item> -->
-                                    </div>
-                                </div>
-                            </el-form-item>
-                        </div>
-                    </div>
-
-                    <div class="farm-card prescription-content">
-                        <div class="medicine-box">
-                                <div class="form-index">服务报价</div>
-                                <div class="box-wrap">
-                                    <div class="medicine-item mt-8">
-                                        <div class="item-name">单亩价格</div>
-                                        <div class="item-val common-inputs">
-                                            <el-input
-                                                style="width: 150px"
-                                                v-model="servicePricePerMu"
-                                                type="number"
-                                                step="0.01"
-                                                placeholder="服务单价"
-                                            >
-                                                <template #append>元/亩</template>
-                                            </el-input>
-                                        </div>
-                                    </div>
-                                    <div v-if="!noPrice" class="medicine-item">
-                                        <div class="item-total">总计:</div>
-                                        <div class="item-price">
-                                            {{ getServiceTotal() }}<span class="item-unit">元</span>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                    </div>
-
-                    <div class="submit-btn" :class="{ 'center-btn': onlyPrice || defaultTagName === 0 }">
-                        <!-- <div v-if="!onlyPrice" class="btn second" @click.prevent="cancelEdit">取消编辑</div> -->
-                        <div v-if="!onlyPrice && defaultTagName !== 0" class="btn second" @click.prevent="handleCancelAttention">取消关注</div>
-                        <div class="btn" :style="{ opacity: isSaving ? 0.8 : 1 }" @click.prevent="submitForm(formRef)">{{ isSaving ? '保存中...' : '保存' }}</div>
-                    </div>
-                </template>
-
-                <template v-else>
-                    <div class="farm-card prescription-content">
-                        <div class="card-title">药物处方</div>
-                        <div class="table-item">
-                            <div class="form-item">
-                                <div class="item-name">施用方式</div>
-                                <div class="item-text">{{ dynamicValidateForm?.prescription?.usageMode }}</div>
-                            </div>
-                            <div class="form-item">
-                                <div class="item-name">执行方式</div>
-                                <div class="item-text">
-                                    {{ dynamicValidateForm?.prescription?.pesticideFertilizerList[0]?.executeStyle === 1 ? '无人机' : dynamicValidateForm?.prescription?.pesticideFertilizerList[0]?.executeStyle === 3 ? '无人机+人工' : '人工' }}
-                                </div>
-                            </div>
-                        </div>
-                        <div class="new-wrap" v-if="detailData?.prescription?.pesticideFertilizerList?.length">
-                            <div class="new-title">
-                                <div class="title-1"><div class="table-name">使用功效</div></div>
-                                <div class="title-2"><div class="table-name">药肥名称</div></div>
-                                <div class="title-4"><div class="table-name">药肥配比</div></div>
-                                <div class="title-5"><div class="table-name">单亩用量</div></div>
-                            </div>
-                            <div
-                                class="new-table-wrap"
-                                v-for="(subP, prescriptionI) in detailData?.prescription?.pesticideFertilizerList || []"
-                                :key="prescriptionI"
-                            >
-                                <!-- <div
-                                    class="new-prescription"
-                                    v-for="(subP, subI) in prescriptionItem.pesticideFertilizerList"
-                                    :key="subI"
-                                > -->
-                                    <div class="new-table">
-                                        <div class="line-l">
-                                            <div class="line-1 title-1">{{ subP.typeName || '--' }}</div>
-                                            <div class="line-2">
-                                                {{ subP.name || subP.pesticideFertilizerName }}
-                                            </div>
-                                        </div>
-                                        <div class="line-r">
-                                            <div class="line-3">
-                                                <div class="sub-line title-4">{{ subP.ratio ? (subP.ratio + '倍') : '--' }}</div>
-                                                <div class="sub-line title-5">{{ subP.dosage ? (subP.dosage + subP.unit) : '--' }}</div>
-                                            </div>
-                                        </div>
-                                    </div>
-                                    <div class="note-text" v-if="subP.remark">{{ subP.remark }}</div>
-                                <!-- </div> -->
-                            </div>
-                        </div>
-                    </div>
-
-                    <div class="farm-card prescription-content">
-                        <div class="card-title">处方报价</div>
-
-                        <div class="price-bottom" v-if="!noPrice">
-                            <div class="info-title-wrap">
-                                <div class="sub-title font-bold">药肥费用</div>
-                                <div class="info-more">
-                                    {{ pesticideCostTotal ? formatArea(pesticideCostTotal) : "--" }}<span class="unit-text">元</span>
-                                </div>
-                            </div>
-                        </div>
-                        <div class="info-content-wrap pt-8">
-                            <price-table :prescriptionData="dynamicValidateForm.prescription" :area="detailData?.farm?.mianji">
-                                <template #bottomContent>
-                                    <div class="price-bottom">
-                                        <div class="info-title-wrap">
-                                            <div class="sub-title font-bold">服务费用</div>
-                                            <div class="info-more" v-if="!noPrice">
-                                                {{ detailData?.serviceMuPrice ? serviceCostTotal : '--' }}
-                                                <span class="unit-text">元</span>
-                                            </div>
-                                        </div>
-                                        <div class="price-info">
-                                            <div class="info-l">
-                                                单亩价格<span class="main-text">{{
-                                                    detailData?.serviceMuPrice
-                                                        ? detailData?.serviceMuPrice + "元/亩"
-                                                        : "--"
-                                                }}</span>
-                                            </div>
-                                        </div>
-                                        <div class="price-total" v-if="!noPrice">
-                                            报价合计:<span class="main-val">{{
-                                                totalCost ? formatArea(totalCost) : "--"
-                                            }}</span
-                                            >元
-                                        </div>
-                                    </div>
-                                </template>
-                            </price-table>
-                        </div>
-                    </div>
-                    <template v-if="!isDefault">
-                        <div class="submit-btn" :class="{ 'center-btn': defaultTagName === 0 }" v-has-permission="'农事规划'">
-                            <div v-if="defaultTagName !== 0" class="btn second" @click.prevent="handleCancelAttention">取消关注</div>
-                            <div class="btn" @click.prevent="toEditPrescription">编辑处方</div>
-                        </div>
-                    </template>
-                </template>
-            </el-form>
-        </div>
-    </div>
-
-    <!-- 服务报价单 -->
-    <price-sheet-popup ref="priceSheetPopupRef"></price-sheet-popup>
-
-    <!-- 互动设置弹窗 -->
-    <interact-popup
-        ref="interactPopupRef"
-        @handleSaveSuccess="handleSaveInteractSuccess"
-        @handleDeleteInteract="handleDeleteInteract"
-    ></interact-popup>
-
-    <!-- 取消关注提示 -->
-    <tip-popup
-        v-model:show="showTipPopup"
-        type="warning"
-        text="您确定要取消关注"
-        text2="农事吗?系统将不再为您推送该农事"
-        :highlightText="detailData.name"
-        :overlayStyle="{ 'z-index': 9999 }"
-        buttonText="确认取消关注"
-        @confirm="handleBtn"
-        :hasClose="true"
-        :closeOnClickOverlay="false"
-    />
-    <!-- 完善信息弹窗 -->
-    <popup 
-        v-model:show="showCompletePopup" 
-        round 
-        class="complete-tip-popup"
-        closeable
-    >
-    <img class="tip-icon success-icon" src="@/assets/img/home/right.png" alt="" />
-    <div class="tip-text success-text">
-        农事信息已完善
-    </div>
-        <div class="complete-content">
-        </div>
-        <div class="btn-wrap">
-            <div class="btn-item second" @click="handleViewDetail">查看详情</div>
-            <div class="btn-item primary" v-if="!allDone" @click="handleCompleteNext">完善下一个农事</div>
-            <div class="btn-item primary" v-else @click="handleBackToPlan">回到种植方案</div>
-        </div>
-    </popup>
-</template>
-
-<script setup>
-import { onActivated, ref, reactive, onDeactivated, onBeforeUnmount, computed, onMounted, nextTick } from "vue";
-import { useRouter, useRoute } from "vue-router";
-import { ElMessage, ElMessageBox } from "element-plus";
-import customHeader from "@/components/customHeader.vue";
-import { useStore } from "vuex";
-import { Popup } from "vant";
-import { formatArea } from "@/common/commonFun";
-import priceSheetPopup from "@/components/popup/priceSheetPopup.vue";
-import interactPopup from "@/components/popup/interactPopup.vue";
-import priceTable from "../agri_work/components/priceTable.vue";
-import tipPopup from "@/components/popup/tipPopup.vue";
-import dayjs from "dayjs";
-const store = useStore();
-const pageRef = ref(null);
-const router = useRouter();
-const route = useRoute();
-
-// 检查是否有"农事规划"权限
-const hasPlanPermission = computed(() => {
-    try {
-        const userInfoStr = localStorage.getItem("localUserInfo");
-        if (!userInfoStr) return false;
-        const userInfo = JSON.parse(userInfoStr);
-        const permissions = userInfo.agriculturalPermissions || [];
-        return permissions.includes("农事规划");
-    } catch (error) {
-        console.error("解析用户信息失败:", error);
-        return false;
-    }
-});
-
-const tagList = ref([
-    { label: "托管农事", value: 2 },
-    { label: "特别关注", value: 1 },
-    // { label: "取消关注", value: 0 },
-]);
-
-const tagName = ref("");
-const defaultTagName = ref("");
-
-// 互动表单数据
-const interactFormData = ref({
-    phenologyId: "",
-    reproductiveId: "",
-    interactionTime: "",
-    interactionQuestion: "",
-});
-const phenologyList = ref([]);
-const reproductiveList = ref([]);
-// 是否编辑
-const isEdit = ref(false);
-// 是否只显示价格,不需要农情互动
-const onlyPrice = ref(false);
-// 是否不显示价格,种植方案没有价格
-const noPrice = ref(false);
-// 是否标注方案
-const isDefault = ref(false);
-// 是否在完善信息弹窗中
-const isDoingComplete = ref(false);
-// 是否正在保存
-const isSaving = ref(false);
-
-const showCompletePopup = ref(false);
-onActivated(() => {
-    isDefault.value = route.query.isDefault == 'true' ? true : false;
-    isEdit.value = route.query.isEdit == 'true' ? true : false;
-    onlyPrice.value = route.query.onlyPrice == 'true' ? true : false;
-    noPrice.value = route.query.noPrice == 'true' ? true : false;
-    // enabled为0时,方案不可用,需要完善
-    isDoingComplete.value = route.query.enabled == 0 ? true : false;
-    // 方案列表中的ids数组
-    if (route.query.farmWorkId) {
-        getDetail();
-    }
-    if (isDoingComplete.value) {
-        let farmWorkAndArrangeIdIdsArray = (() => {
-                const stored = sessionStorage.getItem("farmWorkAndArrangeIds");
-                return stored ? JSON.parse(stored) : [];
-            })();
-        ids.value = farmWorkAndArrangeIdIdsArray;
-        if (ids.value.length === 0 || ids.value.length === 1) {
-            allDone.value = true;
-        }
-    }
-    nextTick(() => {
-        if (pageRef.value) {
-            pageRef.value.scrollTop = 0;
-        } else {
-            window.scrollTo(0, 0);
-        }
-    });
-    // 初始化 prescription 对象
-    if (!route.query.farmWorkId) {
-        dynamicValidateForm.prescription = {
-            usageMode: "",
-            pesticideFertilizerList: [
-                {
-                    code: "",
-                    name: "",
-                    dosage: "",
-                    ratio: "",
-                    typeName: "",
-                    muPrice: 0,
-                    executeStyle: 1,
-                    unit: "",
-                },
-            ],
-        };
-    }
-});
-
-const priceSheetPopupRef = ref(null);
-const showPriceSheetPopup = () => {
-    priceSheetPopupRef.value.handleShowPopup(detailData.value);
-};
-
-const handlePhenologyChange = async (val) => {
-    interactFormData.value.reproductiveId = "";
-    const { data } = await VE_API.farm.listByPhenologyId({ phenologyId: val });
-    if (!data || !Array.isArray(data)) return;
-    reproductiveList.value = data;
-};
-
-const statusMap = ref({
-    0: "",
-    1: "特别关注",
-    2: "托管农事",
-});
-const detailData = ref({});
-const userInfo = localStorage.getItem('localUserInfo');
-const userInfoObj = userInfo ? JSON.parse(userInfo) : {};
-const getDetail = async () => {
-    const { data, code } = await VE_API.farm.getFarmWorkLib({ id: route.query.farmWorkId, farmId: route.query.farmId, agriculturalId: userInfoObj?.agriculturalId });
-    if(code === 0) {
-        detailData.value = data;
-        dynamicValidateForm.executeDate = data.executeDate;
-        dynamicValidateForm.prescription.usageMode = data?.prescription?.usageMode === '其他' ? '根部施' : data?.prescription?.usageMode;
-        // 从 prescription 获取数据
-        dynamicValidateForm.prescription = data.prescription || {
-            usageMode: "",
-            pesticideFertilizerList: [],
-        };
-        dynamicValidateForm.executeStyle = data?.prescription?.pesticideFertilizerList[0]?.executeStyle;
-        servicePricePerMu.value = detailData.value.serviceMuPrice || null;
-        if (!isDefault.value) {
-            data?.prescription?.pesticideFertilizerList.forEach(item => {
-                item.placeholderRatio = item.ratio || '';
-                item.placeholderDosage = item.dosage || '';
-                if (isNaN(item.ratio)) {
-                    item.ratio = null;
-                }
-                if (isNaN(item.dosage)) {
-                    item.dosage = null;
-                }
-            });
-        }
-        const pesticideFertilizerCodes = data?.prescription?.pesticideFertilizerList.map(item => item.code);
-        getPriceList(data.schemeId, pesticideFertilizerCodes);
-        
-        // 加载互动表单数据
-        if (data.id) {
-            // 重置互动表单数据
-            interactFormData.value = {
-                phenologyId: "",
-                reproductiveId: "",
-                interactionTime: "",
-                interactionQuestion: "",
-            };
-            // 按照 interactPopup.vue 的方式获取数据
-            await getPhenologyList(data.containerSpaceTimeId || route.query.containerSpaceTimeId);
-            await getFarmWorkArrangeDetail(route.query.id || route.query.arrangeId);
-        }
-    }
-};
-
-const getPriceList = async (schemeId, pesticideFertilizerCodes) => {
-    const { data } = await VE_API.farm.getPriceList({ schemeId, pesticideFertilizerCodes });
-    if (!data || !Array.isArray(data)) return;
-
-    dynamicValidateForm.prescription.pesticideFertilizerList.forEach((item) => {
-        const priceInfo = data.find((p) => p.pesticideFertilizerCode === item.code);
-        if (!priceInfo) return;
-        item.price = priceInfo.price ?? item.price;
-        item.brand = priceInfo.brand ?? item.brand;
-    });
-
-    quotationData.value = {...detailData.value, ...dynamicValidateForm};
-};
-
-const showTipPopup = ref(false);
-// 取消关注弹窗
-const handleCancelAttention = () => {
-    showTipPopup.value = true;
-};
-
-const handleBtn = () => {
-    showTipPopup.value = false;
-    // 切换标记
-    VE_API.container_farm_work_arrange.toggleFollow({ id: route.query.id, isFollow: 0 }).then((res) => {
-        if (res.code === 0) {
-            ElMessage.success("操作成功");
-            router.back();
-        }
-    });
-};
-
-const toEditPrescription = () => {
-    isEdit.value = true;
-    if (tagName.value === 0) {
-        tagName.value = 1;
-    }
-    nextTick(() => {
-        if (pageRef.value) {
-            pageRef.value.scrollTo({ top: 0, behavior: "auto" });
-        } else {
-            window.scrollTo(0, 0);
-        }
-    });
-};
-
-const quotationData = ref({});
-
-
-// 计算单个药肥的总计:单价 * 单亩用量 * 亩数
-const getPesticideTotal = (pesticide) => {
-    const price = Number(pesticide.price || 0);
-    const dosage = Number(pesticide.dosage || 0); // 单亩用量
-    const area = Number(detailData.value.farm?.mianji || 0); // 农场面积
-    if (!price || !dosage || !area) return "--";
-    const total = (price * dosage * area).toFixed(2);
-    return total;
-};
-
-function getServiceCost(cost, area) {
-    if (!cost || !area) return "--";
-    return (parseFloat(cost) * parseFloat(area)).toFixed(2);
-}
-
-const handleViewDetail = () => {
-    showCompletePopup.value = false;
-    isEdit.value = false;
-    nextTick(() => {
-        if (pageRef.value) {
-            pageRef.value.scrollTo({ top: 0, behavior: "auto" });
-        } else {
-            window.scrollTo(0, 0);
-        }
-    });
-};
-const allDone = ref(false);
-const handleBackToPlan = () => {
-    router.back();
-};
-
-const ids = ref([]);
-const handleCompleteNext = () => {
-    showCompletePopup.value = false;
-    
-    // 如果数组为空,说明已经全部完成
-    if (!ids.value || ids.value.length === 0) {
-        allDone.value = true;
-        return;
-    }
-    
-    // 找到当前 farmWorkId 在数组中的索引
-    const currentFarmWorkId = route.query.farmWorkId;
-    const currentIndex = ids.value.findIndex(item => String(item.farmWorkId) === String(currentFarmWorkId));
-    
-    if (currentIndex === -1) {
-        // 如果找不到当前项,说明可能已经被删除或不存在
-        allDone.value = true;
-        console.log('未找到当前farmWorkId');
-        return;
-    }
-    
-    // 如果数组只剩一个(最后一个),标记为全部完成
-    if (ids.value.length === 1) {
-        // 从数组中删除当前项(已经完成的)
-        ids.value.splice(currentIndex, 1);
-        // 更新 sessionStorage
-        sessionStorage.setItem("farmWorkAndArrangeIds", JSON.stringify(ids.value));
-        allDone.value = true;
-        return;
-    }
-    
-    // 判断是否是最后一个
-    const isLast = currentIndex === ids.value.length - 1;
-    
-    // 如果是最后一个
-    if (isLast) {
-        // 从数组中删除当前项(已经完成的)
-        ids.value.splice(currentIndex, 1);
-        // 更新 sessionStorage
-        sessionStorage.setItem("farmWorkAndArrangeIds", JSON.stringify(ids.value));
-        
-        // 如果删除后数组为空,标记为全部完成
-        if (ids.value.length === 0) {
-            allDone.value = true;
-            return;
-        }
-        
-        // 如果删除后数组不为空,从第一个开始获取
-        const firstItem = ids.value[0];
-        if (firstItem && firstItem.farmWorkId && firstItem.arrangeId) {
-            router.replace({
-                path: "/modify",
-                query: {
-                    id: firstItem.arrangeId,
-                    farmWorkId: firstItem.farmWorkId,
-                    farmId: route.query.farmId,
-                    containerSpaceTimeId: route.query.containerSpaceTimeId,
-                    schemeId: route.query.schemeId,
-                    isEdit: route.query.isEdit,
-                    onlyPrice: route.query.onlyPrice,
-                },
-            });
-            return;
-        }
-        
-        // 如果第一个项无效,标记为全部完成
-        allDone.value = true;
-        return;
-    }
-    
-    // 获取下一个农事:取当前索引+1位置的值
-    const nextItem = ids.value[currentIndex + 1];
-    
-    if (nextItem && nextItem.farmWorkId && nextItem.arrangeId) {
-        // 从数组中删除当前项(已经完成的)
-        ids.value.splice(currentIndex, 1);
-        // 更新 sessionStorage
-        sessionStorage.setItem("farmWorkAndArrangeIds", JSON.stringify(ids.value));
-        
-        router.replace({
-            path: "/modify",
-            query: {
-                id: nextItem.arrangeId,
-                farmWorkId: nextItem.farmWorkId,
-                farmId: route.query.farmId,
-                containerSpaceTimeId: route.query.containerSpaceTimeId,
-                schemeId: route.query.schemeId,
-                enabled: 0,
-                isEdit: true,
-                onlyPrice: false,
-                noPrice: true,
-                isDefault: false,
-            },
-        });
-        setTimeout(() => {
-            window.location.reload();
-        }, 500);
-    } else {
-        // 从数组中删除当前项(已经完成的)
-        ids.value.splice(currentIndex, 1);
-        // 更新 sessionStorage
-        sessionStorage.setItem("farmWorkAndArrangeIds", JSON.stringify(ids.value));
-        allDone.value = true;
-        console.log('没有下一个农事需要完善');
-    }
-};
-const resetForm = (formEl) => {
-    if (!formEl) return;
-    formEl.resetFields();
-};
-
-// 清空所有数据
-const clearData = () => {
-    // 清空表单
-    resetForm(formRef.value);
-
-    // 清空详情数据
-    detailData.value = {};
-
-    // 清空表单数据
-    dynamicValidateForm.farmWorkName = "";
-    dynamicValidateForm.conditionRate = "";
-    dynamicValidateForm.purpose = "";
-    dynamicValidateForm.executeDate = dayjs().format("YYYY-MM-DD");
-    dynamicValidateForm.prescription = {
-        id: "",
-        usageMode: "",
-        farmWorkLibCode: "",
-        expertId: "",
-        phenology: "",
-        soil: "",
-        speed: null,
-        pesticideFertilizerList: [
-            {
-                code: "",
-                name: "",
-                dosage: "",
-                ratio: "",
-                typeName: "",
-                muPrice: 0,
-                executeStyle: 1,
-                unit: "",
-            },
-        ],
-    };
-};
-
-onDeactivated(() => {
-    clearData();
-});
-
-onBeforeUnmount(() => {
-    clearData();
-});
-
-const cancelEdit = () => {
-    ElMessageBox.confirm("确认要取消编辑吗?", "提示", {
-        confirmButtonText: "确认",
-        cancelButtonText: "取消",
-        type: "warning",
-    })
-        .then(() => {
-            isEdit.value = false;
-            nextTick(() => {
-                if (pageRef.value) {
-                    pageRef.value.scrollTop = 0;
-                } else {
-                    window.scrollTo(0, 0);
-                }
-            });
-        })
-        .catch(() => {
-            console.log("取消编辑");
-        });
-};
-
-const modeList = ref([
-    { name: "无人机", value: 1 },
-    { name: "人工", value: 2 },
-    { name: "无人机+人工", value: 3 },
-]);
-
-const handleExecutionMethodChange = (index, val) => {
-    // if (val == 1) {
-    //     servicePricePerMu.value = detailData.value.uavServicePrice;
-    // } else {
-    //     servicePricePerMu.value = detailData.value.manualServicePrice;
-    // }
-};
-
-// 表单
-const formRef = ref();
-const dynamicValidateForm = reactive({
-    farmWorkName: "",
-    conditionRate: "",
-    purpose: "",
-    executeDate: dayjs().format("YYYY-MM-DD"),
-    usageMode: "",
-    executeStyle: 2,
-    executionMethod: 2,
-    prescription: {
-        id: "",
-        usageMode: "",
-        farmWorkLibCode: "",
-        expertId: "",
-        phenology: "",
-        soil: "",
-        speed: null,
-        pesticideFertilizerList: [
-            {
-                code: "",
-                id: "",
-                name: "",
-                dosage: "",
-                ratio: "",
-                brand: "",
-                price: "",
-                typeName: "",
-                muPrice: 0,
-                executeStyle: 1,
-                unit: "",
-            },
-        ],
-    },
-});
-
-const rules = {
-    farmWorkName: [
-        {
-            required: true,
-            message: "请输入农事名称",
-            trigger: "blur",
-        },
-    ],
-    conditionRate: [
-        {
-            required: false,
-            message: "请输入触发条件",
-            trigger: "blur",
-        },
-    ],
-    executeDate: [
-        {
-            required: false,
-            message: "请选择执行时间",
-            trigger: "blur",
-        },
-    ],
-};
-
-const addDomain = () => {
-    if (!dynamicValidateForm.prescription.pesticideFertilizerList) {
-        dynamicValidateForm.prescription.pesticideFertilizerList = [];
-    }
-    dynamicValidateForm.prescription.pesticideFertilizerList.unshift({
-        code: "",
-        name: "",
-        dosage: "",
-        ratio: "",
-        brand: "",
-        price: "",
-        typeName: "",
-        muPrice: 0,
-        id: "",
-        executeStyle: 2,
-        unit: "",
-    });
-};
-
-let pesticideFertilizersOptions = ref([]);
-VE_API.z_farm_work_order.pesticideFertilizersList().then(({ data }) => {
-    pesticideFertilizersOptions.value = data;
-});
-
-const allUsageModeList = ["树冠+内膛", "地面喷施", "树冠喷施", "根部施", "叶面施", "内膛喷施", "其他"];
-
-/**
- * 选择药肥的时候修改订单中药肥pesticideFertilizerId 以外其他数据
- * @param index
- */
-const handlePesticideFertilizerChange = (index) => {
-    const currentItem = dynamicValidateForm.prescription.pesticideFertilizerList[index];
-    let obj = pesticideFertilizersOptions.value.filter(
-        (item) => currentItem.code === item.pesticideFertilizerCode
-    )[0];
-    if (obj) {
-        dynamicValidateForm.prescription.pesticideFertilizerList[index] = {
-            ...currentItem,
-            code: obj.pesticideFertilizerCode,
-            id: obj.id,
-            name: obj.name || obj.defaultName,
-            typeName: obj.typeName,
-            unit: obj.unit,
-            ratio: "", // 清空亩兑水量
-            dosage: "", // 清空单亩用量
-            executeStyle: obj.executionMethod || 1,
-        };
-    }
-};
-
-const removeDomain = (index) => {
-    if (index !== -1 && dynamicValidateForm.prescription.pesticideFertilizerList) {
-        dynamicValidateForm.prescription.pesticideFertilizerList.splice(index, 1);
-    }
-};
-
-const resetItemForm = (index) => {
-    if (dynamicValidateForm.prescription.pesticideFertilizerList) {
-        dynamicValidateForm.prescription.pesticideFertilizerList[index] = {
-            code: "",
-            id: "",
-            name: "",
-            dosage: "",
-            ratio: "",
-            brand: "",
-            price: "",
-            typeName: "",
-            muPrice: 0,
-            executeStyle: 1,
-            unit: "",
-        };
-    }
-};
-
-const servicePricePerMu = ref(null);
-
-// 服务费用总计(数值):亩单价 * 亩数
-const serviceCostTotal = computed(() => {
-    const price = Number(servicePricePerMu.value || 0);
-    const area = Number(detailData.value?.farm?.mianji || detailData.value?.area || 0);
-    if (!price || !area) return 0;
-    return Number((price * area).toFixed(2));
-});
-
-// 显示用的服务费用(字符串或 "--")
-const getServiceTotal = () => {
-    const total = serviceCostTotal.value;
-    return total ? total.toFixed(2) : "--";
-};
-
-// 药肥费用总计:∑(单价 * 单亩用量 * 亩数)
-const pesticideCostTotal = computed(() => {
-    const list = dynamicValidateForm.prescription?.pesticideFertilizerList || [];
-    const area = Number(detailData.value?.farm?.mianji || detailData.value?.area || 0);
-    if (!list.length || !area) return 0;
-
-    const sum = list.reduce((acc, item) => {
-        const price = Number(item?.price || 0);
-        const dosage = Number(item?.dosage || 0);
-        if (!price || !dosage) return acc;
-        return acc + price * dosage * area;
-    }, 0);
-
-    return Number(sum.toFixed(2));
-});
-
-// 报价合计 = 药肥费用 + 服务费用
-const totalCost = computed(() => {
-    const pesticide = Number(pesticideCostTotal.value || 0);
-    const service = Number(serviceCostTotal.value || 0);
-    if (!pesticide && !service) return '--';
-    return Number((pesticide + service).toFixed(2));
-});
-
-const submitForm = (formEl) => {
-    if (!formEl) return;
-    formEl.validate(async (valid) => {
-        if (valid) {
-            // 校验标记是否已选择
-            if (!validateTagName()) return;
-
-            // 校验施用方式是否已选择
-            if (!validateUsageMode()) return;
-
-            // 校验农情互动,不通过,直接返回失败
-            if (!onlyPrice.value && !validateInteractForm()) return false;
-
-            // 校验药肥的亩兑水量和单亩用量是否填写
-            if (!validatePesticideDosage()) return;
-
-            // 保存报价信息前先校验是否填写完整
-            if (!validatePriceInfos()) return;
-
-            // 检验服务报价是否填写
-            if (!validateServicePrice()) return;
-            submit();
-        } else {
-            console.log("error submit!");
-        }
-    });
-};
-
-// 校验标记是否已选择
-const validateTagName = () => {
-    if (tagName.value !== 1 && tagName.value !== 2) {
-        ElMessage.warning("请选择标记类型");
-        return false;
-    }
-    return true;
-};
-
-// 校验施用方式是否已选择
-const validateUsageMode = () => {
-    if (!dynamicValidateForm.prescription?.usageMode || dynamicValidateForm.prescription.usageMode === "") {
-        ElMessage.warning("请选择施用方式");
-        return false;
-    }
-    return true;
-};
-
-// 检验服务报价是否填写
-const validateServicePrice = () => {
-    if (!servicePricePerMu.value) {
-        ElMessage.warning("请完善服务报价信息");
-        return false;
-    }
-    return true;
-};
-
-// 校验药肥的亩兑水量和单亩用量是否填写
-const validatePesticideDosage = () => {
-    const list = dynamicValidateForm.prescription?.pesticideFertilizerList || [];
-    if (!list.length) return true; // 没有药肥就不校验
-
-    // 找到第一个未填写完整的药肥
-    for (let i = 0; i < list.length; i++) {
-        const item = list[i];
-        // 如果选择了药肥(有 code),就必须填写亩兑水量和单亩用量
-        if (item.code) {
-            const hasRatio = item.ratio !== undefined && item.ratio !== null && item.ratio !== "";
-            const hasDosage = item.dosage !== undefined && item.dosage !== null && item.dosage !== "";
-            
-            if (!hasRatio || !hasDosage) {
-                ElMessage.warning("请完善药物处方信息");
-                return false;
-            }
-        }
-    }
-    return true;
-};
-
-// 校验报价信息是否填写完整
-const validatePriceInfos = () => {
-    const list = dynamicValidateForm.prescription?.pesticideFertilizerList || [];
-    if (!list.length) return true; // 没有药肥就不校验
-
-    // 找到第一个未填写完整的药肥
-    const invalidIndex = list.findIndex((item) => {
-        // 只要选择了药肥(有 id),就必须填写单价和品牌
-        if (!item.id) return false; // 没选择药肥不校验
-        const hasPrice = item.price !== undefined && item.price !== null && item.price !== "";
-        const hasBrand = !!item.brand;
-        return !hasPrice || !hasBrand;
-    });
-
-    if (invalidIndex !== -1) {
-        ElMessage.warning("请先完善报价信息");
-        return false;
-    }
-    return true;
-};
-
-const submit = async () => {
-    // 设置保存状态
-    isSaving.value = true;
-    
-    try {
-        const data = {
-            id: route.query.farmWorkId,
-            ...dynamicValidateForm,
-            serviceMuPrice: servicePricePerMu.value,
-            prescription: dynamicValidateForm.prescription
-        };
-        await VE_API.monitor.saveFarmWorkLib(data);
-        
-        if (!onlyPrice.value) {
-            await handleSaveInteract();
-        }
-
-        // 保存报价信息
-        const priceList = {
-            schemeId: detailData.value.schemeId,
-            pesticideFertilizerInfos: dynamicValidateForm.prescription.pesticideFertilizerList.map(item => {
-                return {
-                    pesticideFertilizerId: item.id,
-                    price: item.price,
-                    brand: item.brand,
-                }
-            }),
-        }
-        const res = await VE_API.farm.updateBatchByScheme(priceList);
-        
-        // 切换标记
-        await VE_API.container_farm_work_arrange.toggleFollow({ id: route.query.id, isFollow: tagName.value });
-        
-        if (res.code === 0) {
-            await getDetail();
-            if (isDoingComplete.value) {
-                // 更新 sessionStorage(不删除当前项,保持数组完整)
-                sessionStorage.setItem("farmWorkAndArrangeIds", JSON.stringify(ids.value));
-                
-                showCompletePopup.value = true;
-                return;
-            }
-            ElMessage.success("保存成功");
-            if (onlyPrice.value) {
-                // router.push(`/task_condition?noReload=true`);
-                router.back();
-                return;
-            }
-            isEdit.value = false;
-            nextTick(() => {
-                if (pageRef.value) {
-                    pageRef.value.scrollTop = 0;
-                } else {
-                    window.scrollTo(0, 0);
-                }
-            });
-        } else {
-            // 不需要处方报价信息的农事
-            if (priceList.pesticideFertilizerInfos.length === 0) {
-                if (onlyPrice.value) {
-                    // router.push(`/task_condition?noReload=true`);
-                    router.back();
-                    return;
-                }
-                isEdit.value = false;
-                getDetail();
-                nextTick(() => {
-                    if (pageRef.value) {
-                        pageRef.value.scrollTop = 0;
-                    } else {
-                        window.scrollTo(0, 0);
-                    }
-                });
-            }
-        }
-    } catch (error) {
-        console.error("保存失败:", error);
-        ElMessage.error("保存失败,请重试");
-    } finally {
-        // 无论成功或失败,都要关闭保存状态
-        isSaving.value = false;
-    }
-};
-
-const handleSaveInteractSuccess = () => {
-    getDetail();
-};
-
-const interactPopupRef = ref(null);
-const handleEditInteract = (item) => {
-    if (interactPopupRef.value) {
-        interactPopupRef.value.showPopup({...item, containerSpaceTimeId: route.query.containerSpaceTimeId,id:route.query.id});
-    }
-};
-
-// 获取物候期列表
-const getPhenologyList = async (containerSpaceTimeId) => {
-    if (!containerSpaceTimeId) {
-        phenologyList.value = [];
-        return;
-    }
-    const res = await VE_API.monitor.listPhenology({ containerSpaceTimeId });
-    if (res.code === 0) {
-        phenologyList.value = res.data || [];
-    }
-};
-
-// 获取互动设置详情
-const getFarmWorkArrangeDetail = async (id) => {
-    if (!id) return;
-    const { data, code } = await VE_API.farm.getFarmWorkArrangeDetail({ id });
-    if(code === 0) {
-        tagName.value = data.isFollow;
-        defaultTagName.value = data.isFollow;
-        await handlePhenologyChange(data.phenologyId);
-        interactFormData.value = {
-            phenologyId: data.phenologyId || "",
-            reproductiveId: data.reproductiveId || "",
-            interactionTime: data.interactionTime || "",
-            interactionQuestion: data.interactionQuestion || "",
-        };
-    }
-};
-
-// 格式化日期
-const formatInteractDate = (date) => {
-    // 如果已经是字符串格式 YYYY-MM-DD,直接返回
-    if (typeof date === "string" && /^\d{4}-\d{2}-\d{2}$/.test(date)) {
-        return date;
-    }
-    // 如果是 Date 对象,进行转换
-    if (date instanceof Date) {
-        let year = date.getFullYear();
-        let month = String(date.getMonth() + 1).padStart(2, "0");
-        let day = String(date.getDate()).padStart(2, "0");
-        return `${year}-${month}-${day}`;
-    }
-    // 其他情况返回原值
-    return date;
-};
-
-// 验证互动表单
-const validateInteractForm = () => {
-    if (!interactFormData.value.phenologyId) {
-        ElMessage.warning("请选择互动阶段");
-        return false;
-    }
-    if (!interactFormData.value.reproductiveId) {
-        ElMessage.warning("请选择互动阶段");
-        return false;
-    }
-    if (!interactFormData.value.interactionTime) {
-        ElMessage.warning("请选择互动时间");
-        return false;
-    }
-    if (!interactFormData.value.interactionQuestion?.trim()) {
-        ElMessage.warning("请设置互动问题");
-        return false;
-    }
-    return true;
-};
-
-// 保存互动设置
-const handleSaveInteract = async () => {
-
-    const paramsObj = {
-        id: route.query.id,
-        ...interactFormData.value,
-        interactionTime: formatInteractDate(interactFormData.value.interactionTime),
-    };
-
-    try {
-        const res = await VE_API.monitor.updateFarmWorkArrange(paramsObj);
-        if (res.code !== 0) {
-            ElMessage.error(res.message || "保存农情互动信息失败");
-            return false;
-        }
-        return true;
-    } catch (error) {
-        console.error("保存互动设置失败:", error);
-        ElMessage.error("保存失败,请重试");
-        return false;
-    }
-};
-
-// 删除互动设置
-const handleDeleteInteract = () => {
-    ElMessageBox.confirm("确定要删除该互动设置吗?", "提示", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning",
-    })
-        .then(async () => {
-            if (!detailData.value.id) return;
-            const res = await VE_API.monitor.deleteFarmWorkArrange({ id: detailData.value.id });
-            if (res.code === 0) {
-                ElMessage.success("删除成功");
-                // 清空表单数据
-                interactFormData.value = {
-                    phenologyId: "",
-                    interactionTime: "",
-                    interactionQuestion: "",
-                };
-                await getDetail(); // 重新获取详情
-            } else {
-                ElMessage.error(res.message || "删除失败");
-            }
-        })
-        .catch(() => {
-            // 用户取消,不做任何操作
-        });
-};
-</script>
-
-<style lang="scss" scoped>
-.new-farming-page {
-    height: 100vh;
-    position: relative;
-    overflow: auto;
-    font-size: 14px;
-    background: #f2f3f5;
-    ::v-deep {
-        .custom-header {
-            position: fixed;
-            top: 0;
-            padding-bottom: 1px;
-        }
-    }
-    .step-wrap {
-        padding: 12px 0;
-    }
-    .box-wrap {
-        background: #fff;
-        padding: 20px 10px 10px;
-        border-radius: 6px;
-    }
-    .new-farming-content {
-        margin: 41px 0 62px 0;
-        padding: 4px 12px 8px 12px;
-        width: 100%;
-        box-sizing: border-box;
-        &.no-permission{
-            margin-bottom: 12px;
-        }
-
-        // ::v-deep {
-        //     .el-select__input {
-        //         color: #2199F8;
-        //     }
-        //     .el-select__wrapper {
-        //         color: #2199F8;
-        //         min-height: 30px;
-        //         line-height: 28px;
-        //         box-shadow: 0 0 0 1px rgba(33, 153, 248, 0.3) inset;
-        //     }
-        //     .el-select__caret {
-        //         color: #2199F8;
-        //     }
-        //     .el-select__placeholder {
-        //         color: #2199F8;
-        //     }
-        //     .el-radio {
-        //         margin-right: 16px;
-        //     }
-        //     .el-input__wrapper {
-        //         box-shadow: 0 0 0 1px rgba(33, 153, 248, 0.3) inset;
-        //     }
-        //     .el-input__prefix {
-        //         color: #2199F8;
-        //     }
-        //     .el-input__inner {
-        //         color: #2199F8;
-        //         --el-input-placeholder-color: rgba(33, 153, 248, 0.43);
-        //     }
-        //     .el-tag.el-tag--info {
-        //         --el-tag-text-color: #2199F8;
-        //         --el-tag-bg-color: rgba(33, 153, 248, 0.1);
-        //     }
-        // }
-        .farm-info {
-            color: rgba(0, 0, 0, 0.6);
-            font-size: 14px;
-            margin-top: 14px;
-            .info-title {
-                display: flex;
-                align-items: center;
-                justify-content: space-between;
-                color: rgba(41, 41, 41, 0.3);
-                .info-more {
-                    display: flex;
-                    align-items: center;
-                }
-            }
-        }
-        .farm-photo {
-            margin-top: 10px;
-            .photo-list {
-                display: flex;
-                align-items: center;
-                width: 100%;
-                overflow: auto;
-                padding-bottom: 10px;
-                .photo-item {
-                    width: 92px;
-                    height: 92px;
-                    border-radius: 8px;
-                    object-fit: cover;
-                }
-                .img-item {
-                    img {
-                        width: 92px;
-                        height: 92px;
-                        border-radius: 8px;
-                        object-fit: cover;
-                        margin-right: 12px;
-                    }
-                }
-            }
-            .list-text {
-                text-align: center;
-                color: rgba(0, 0, 0, 0.5);
-                padding-top: 2px;
-            }
-        }
-        .submit-btn {
-            z-index: 10;
-            position: fixed;
-            bottom: 0px;
-            left: 0;
-            width: 100%;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            padding: 12px;
-            background: #fff;
-            box-sizing: border-box;
-            box-shadow: 0 4px 4px rgba(0, 0, 0, 0.4);
-            border-top: 1px solid rgba(0, 0, 0, 0.1);
-            &.center-btn {
-                justify-content: center;
-            }
-            .btn {
-                height: 40px;
-                border-radius: 25px;
-                line-height: 40px;
-                width: 110px;
-                text-align: center;
-                background: linear-gradient(180deg, #70bffe, #2199f8);
-                color: #ffffff;
-                font-size: 14px;
-                &.second {
-                    background: #ffffff;
-                    border: 1px solid rgba(153, 153, 153, 0.5);
-                    color: #666666;
-                }
-            }
-            .btn + .btn {
-                margin-left: 12px;
-            }
-        }
-    }
-    .card-title {
-        font-size: 16px;
-        font-weight: bold;
-        color: #000;
-        display: flex;
-        align-items: center;
-        &.between {
-            justify-content: space-between;
-            .del-tag {
-                color: #e04c4c;
-                border: 1px solid #e04c4c;
-                border-radius: 5px;
-                padding: 4px 14px;
-                font-size: 12px;
-                font-weight: normal;
-            }
-            .title-tag {
-                padding: 2px 10px;
-                height: 26px;
-                line-height: 26px;
-            }
-        }
-        // justify-content: space-between;
-        .add-tag {
-            font-size: 12px;
-            color: #2199f8;
-            padding: 0px 11px;
-            border: 1px solid #2199F8;
-            border-radius: 5px;
-            font-weight: normal;
-            height: 28px;
-            line-height: 28px;
-        }
-        .type-tag {
-            margin-left: 5px;
-            font-size: 12px;
-            color: #000000;
-            padding: 0 10px;
-            background: rgba(119, 119, 119, 0.1);
-            border-radius: 20px;
-            font-weight: normal;
-            height: 26px;
-            line-height: 26px;
-            display: inline-block;
-        }
-    }
-    .pb-12 {
-        padding-bottom: 12px;
-    }
-    .farm-card {
-        background: #ffffff;
-        border-radius: 8px;
-        padding: 12px 12px 0 12px;
-        width: 100%;
-        box-sizing: border-box;
-        margin-top: 10px;
-        color: rgba(0, 0, 0, 0.4);
-        &.progress {
-            display: flex;
-            align-items: center;
-            padding: 12px;
-            .progress-title {
-                margin-right: 12px;
-            }
-            ::v-deep {
-                .el-radio {
-                    margin-right: 10px;
-                }
-            }
-        }
-        &.map-content {
-            margin-top: 12px;
-        }
-        &.prescription-content {
-            padding: 12px;
-        }
-        .border-bottom {
-            padding-bottom: 7px;
-            border-bottom: 1px solid rgba(245, 245, 245, 0.99);
-        }
-    }
-
-    .table-item {
-        padding: 6px 0 10px 0;
-        .form-item {
-            display: flex;
-            align-items: center;
-            font-size: 14px;
-            color: #767676;
-            height: 24px;
-            .item-name {
-                width: 80px;
-                color: rgba(0, 0, 0, 0.2);
-            }
-        }
-    }
-
-    .new-wrap {
-        border-radius: 5px;
-        text-align: center;
-        border: 1px solid rgba(225, 225, 225, 0.5);
-        .new-title {
-            background: rgba(241, 241, 241, 0.4);
-            border-radius: 5px 5px 0 0;
-            border-bottom: 1px solid rgba(225, 225, 225, 0.5);
-            display: flex;
-            color: #767676;
-            // justify-content: space-around;
-            padding: 3px 0px;
-            font-size: 12px;
-            .table-name {
-                width: 24px;
-                font-size: 12px;
-                margin: 0 auto;
-            }
-        }
-
-        .title-1 {
-            width: 46px;
-        }
-        .title-2 {
-            flex: 1;
-        }
-        .title-3 {
-            width: 52px;
-        }
-        .title-4 {
-            width: 56px;
-        }
-        .title-5 {
-            width: 52px;
-        }
-        .new-table-wrap {
-            padding: 5px 0;
-            .new-prescription + .new-prescription {
-                border-top: 1px solid rgba(225, 225, 225, 0.8);
-            }
-            // .new-prescription {
-                .new-table {
-                    display: flex;
-                    align-items: center;
-                    // border: 1px solid rgba(225, 225, 225, 0.8);
-                    background: #fff;
-                    border-radius: 5px;
-                    color: rgba(0, 0, 0, 0.6);
-                    font-size: 11px;
-                    .line-l {
-                        display: flex;
-                        flex: 1;
-                        .line-2 {
-                            flex: 1;
-                            padding: 0 2px;
-                        }
-                    }
-                    .line-r {
-                        &.has-border {
-                            border-left: 1px solid rgba(225, 225, 225, 0.8);
-                        }
-                        .line-3 {
-                            display: flex;
-                            align-items: center;
-                        }
-                        .sub-line {
-                            padding: 10px 0;
-                        }
-                        .line-4 {
-                            display: flex;
-                            align-items: center;
-                            border-top: 1px solid rgba(225, 225, 225, 0.8);
-                        }
-                        .execute-line {
-                            border-right: 1px solid rgba(225, 225, 225, 0.8);
-                        }
-                    }
-                }
-                .note-text {
-                    margin: 8px 0 4px 0;
-                    color: rgba(0, 0, 0, 0.4);
-                    background: #fff;
-                    padding: 6px 8px;
-                    border-radius: 5px;
-                    text-align: left;
-                    font-size: 11px;
-                }
-            // }
-            // .new-prescription + .new-prescription {
-            //     padding-top: 8px;
-            // }
-        }
-    }
-
-    .info-content-wrap {
-        ::v-deep {
-            .new-table-wrap {
-                padding: 5px 0;
-                .new-prescription + .new-prescription {
-                    border-top: 1px solid rgba(225, 225, 225, 0.8);
-                }
-            }
-        }
-    }
-    .price-bottom {
-        padding-top: 8px;
-
-        .info-title-wrap {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            color: #000;
-            .info-more {
-                font-size: 18px;
-            }
-            .unit-text {
-                font-size: 12px;
-            }
-        }
-        .price-info {
-            padding: 8px 0;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            color: rgba(0, 0, 0, 0.2);
-            .main-text {
-                padding-left: 20px;
-                color: rgba(0, 0, 0, 0.8);
-            }
-            .info-c {
-                flex: 1;
-                text-align: center;
-            }
-        }
-        .price-total {
-            height: 38px;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            border: 1px solid rgba(33, 153, 248, 0.5);
-            background: rgba(33, 153, 248, 0.1);
-            color: #000000;
-            border-radius: 4px;
-            .main-val {
-                font-size: 20px;
-                font-weight: bold;
-                color: #2199f8;
-                padding-right: 2px;
-            }
-        }
-    }
-    .pt-8 {
-        padding-top: 8px;
-    }
-    .pb-8 {
-        padding-bottom: 8px;
-    }
-
-    .common-inputs {
-        ::v-deep {
-            .el-input__wrapper {
-                box-shadow: none;
-            }
-            .el-input-group__append {
-                padding: 0 10px;
-                background: none;
-                box-shadow: none;
-            }
-            .el-input-group__append {
-                color: rgba(33, 153, 248, 0.5);
-            }
-            .el-input {
-                border: 1px solid rgba(33, 153, 248, 0.3);
-                border-radius: 5px;
-                height: 30px;
-                box-sizing: border-box;
-            }
-            .el-input__wrapper {
-                padding: 0 2px 0 10px;
-                height: 28px;
-                line-height: 28px;
-                min-height: 28px;
-            }
-            .el-input__inner {
-                --el-input-inner-height: 28px;
-                height: 28px;
-                line-height: 28px;
-                min-height: 28px;
-                color: #2199f8;
-                --el-input-placeholder-color: rgba(33, 153, 248, 0.43);
-            }
-
-            .el-select__wrapper {
-                box-shadow: 0 0 0 1px rgba(33, 153, 248, 0.3) inset;
-            }
-            .el-select__placeholder,
-            .el-select__caret {
-                color: #2199f8;
-            }
-        }
-    }
-
-    .medicine-item {
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        height: 32px;
-        .item-name {
-            color: rgba(0, 0, 0, 0.4);
-        }
-        .item-val {
-            min-width: 142px;
-            text-align: center;
-            color: #302f2f;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            gap: 4px;
-            .price-unit {
-                font-size: 12px;
-                color: rgba(0, 0, 0, 0.4);
-                white-space: nowrap;
-            }
-        }
-        .item-total {
-            font-size: 16px;
-            color: #000;
-        }
-        .item-price {
-            color: #2199f8;
-            font-size: 20px;
-            font-weight: bold;
-            .item-unit {
-                font-size: 14px;
-                font-weight: normal;
-                padding-left: 2px;
-                color: #474747;
-            }
-        }
-    }
-    .medicine-box {
-        // padding-top: 10px;
-        border: 1px solid rgba(33, 153, 248, 0.8);
-        position: relative;
-        border-radius: 6px;
-        .item-title {
-            padding-left: 5px;
-            font-size: 16px;
-            color: #000000;
-            font-weight: 500;
-            padding-bottom: 10px;
-        }
-        .medicine-item + .medicine-item {
-            padding-top: 2px;
-        }
-        .mt-8 {
-            margin-top: 8px;
-        }
-    }
-
-    .usage-mode-wrap {
-        padding: 0 12px;
-        margin-top: 12px;
-        .info-content {
-            padding-top: 14px;
-            padding-bottom: 1px;
-        }
-
-        .el-form-item--default {
-            margin-bottom: 0;
-        }
-    }
-
-    ::v-deep {
-        .el-form-item__label {
-            height: 30px;
-            line-height: 30px;
-            color: rgba(0, 0, 0, 0.4);
-        }
-        .el-form-item.is-required:not(.is-no-asterisk).asterisk-left > .el-form-item__label:before {
-            display: none;
-        }
-    }
-    .interact-content {
-        padding: 10px 0;
-        line-height: 20px;
-        color: #919191;
-        font-size: 14px;
-    }
-    .interact-form {
-        padding: 8px 0 20px 0px;
-
-        .interact-form-item {
-            display: flex;
-            align-items: baseline;
-            margin-bottom: 12px;
-
-            &:last-child {
-                margin-bottom: 0;
-            }
-
-            .form-label {
-                width: 70px;
-                color: rgba(0, 0, 0, 0.4);
-                font-weight: normal;
-                margin-right: 10px;
-                font-size: 14px;
-                flex: none;
-            }
-
-            .form-input-wrapper {
-                position: relative;
-                width: calc(100% - 70px);
-                &.two-select {
-                    display: flex;
-                    gap: 10px;
-                    .select-item {
-                        flex: 1;
-                    }
-                }
-                ::v-deep {
-                    .el-input__inner {
-                        caret-color: transparent;
-                        padding-right: 40px;
-                    }
-
-                    .el-input__suffix {
-                        display: none;
-                    }
-                }
-            }
-
-            .question-textarea {
-                ::v-deep {
-                    .el-textarea__inner {
-                        resize: none;
-                        line-height: 1.5;
-                        min-height: 80px;
-                    }
-                }
-            }
-        }
-
-        .interact-buttons {
-            display: flex;
-            gap: 12px;
-            padding-top: 16px;
-
-            .btn-delete,
-            .btn-save {
-                flex: 1;
-                padding: 8px;
-                border-radius: 25px;
-                font-size: 16px;
-                text-align: center;
-                cursor: pointer;
-                transition: all 0.3s;
-                user-select: none;
-            }
-
-            .btn-delete {
-                background: #ffffff;
-                border: 1px solid #ff4d4f;
-                color: #ff4d4f;
-
-                &:hover {
-                    background: #fff5f5;
-                }
-
-                &:active {
-                    opacity: 0.8;
-                    transform: scale(0.98);
-                }
-            }
-
-            .btn-save {
-                background: #2199f8;
-                color: #fff;
-                border: none;
-
-                &:hover:not(.disabled) {
-                    background: #1a8ae6;
-                }
-
-                &:active:not(.disabled) {
-                    opacity: 0.9;
-                    transform: scale(0.98);
-                }
-
-                &.disabled {
-                    opacity: 0.6;
-                    cursor: not-allowed;
-                    pointer-events: none;
-                }
-            }
-        }
-    }
-    .edit-tag {
-        padding-left: 4px;
-        color: #2199f8;
-    }
-    .tag-text {
-        font-size: 12px;
-        font-weight: normal;
-    }
-    .info-content {
-        padding: 10px 0;
-        position: relative;
-
-        .condition-wrap {
-            display: flex;
-            align-items: center;
-            width: 100%;
-            .symbol {
-                width: 10px;
-                // text-align: center;
-                // padding: 0 4px;
-            }
-        }
-        .item-input {
-            // width: 60%;
-            min-width: 140px;
-            max-width: 240px;
-        }
-        .recheck-text {
-            padding-left: 6px;
-        }
-        .info-item {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            width: 100%;
-        }
-        .info-item + .info-item {
-            margin-top: 12px;
-        }
-
-        .bottom-map {
-            width: 100%;
-            height: 250px;
-            clip-path: inset(0px round 8px);
-        }
-        .check-btn {
-            position: absolute;
-            bottom: 16px;
-            right: 6px;
-            background: rgba(0, 0, 0, 0.6);
-            padding: 0 8px;
-            border-radius: 8px;
-
-            ::v-deep {
-                .el-checkbox {
-                    color: #fff;
-                }
-            }
-        }
-        .area-select {
-            padding-bottom: 12px;
-            .block {
-                width: 12px;
-                display: inline-block;
-            }
-        }
-    }
-
-    ::v-deep {
-        .el-form-item--default {
-            margin-bottom: 8px;
-            &.text-item {
-                margin-bottom: 2px;
-                .el-form-item__content {
-                    line-height: 24px;
-                }
-                .el-form-item__label {
-                    height: 24px;
-                    line-height: 24px;
-                }
-            }
-        }
-    }
-    .sub-title {
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        color: rgba(0, 0, 0, 0.6);
-        font-size: 14px;
-        .add-tag {
-            font-size: 12px;
-            color: #2199f8;
-            padding: 0 8px;
-            border: 1px solid #2199f8;
-            border-radius: 5px;
-            font-weight: normal;
-            height: 28px;
-            line-height: 28px;
-        }
-    }
-    .font-bold {
-        font-weight: 500;
-        color: #000000;
-    }
-    .form-index {
-        position: absolute;
-        left: 0;
-        top: 0;
-        padding: 0 6px;
-        background: #2199f8;
-        border-radius: 5px 0 4px 0;
-        height: 18px;
-        line-height: 18px;
-        font-size: 12px;
-        color: #fff;
-    }
-    .recipe-item {
-        width: 100%;
-        .recipe-form {
-            padding-top: 8px;
-            ::v-deep {
-                .el-form-item {
-                    &:last-child {
-                        margin-bottom: 0;
-                    }
-                }
-            }
-        }
-
-        .mt-8 {
-            margin-top: 8px;
-        }
-
-        .box-item {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            color: rgba(0, 0, 0, 0.4);
-            .r-text {
-                color: #302f2f;
-                width: 150px;
-                text-align: center;
-            }
-            .form-r {
-                width: 150px;
-                min-width: 140px;
-                max-width: 240px;
-            }
-        }
-        .form-box {
-            border: 1px solid rgba(33, 153, 248, 0.8);
-            border-radius: 6px;
-            padding: 20px 10px;
-            width: 100%;
-            box-sizing: border-box;
-            position: relative;
-            // background: rgb(209, 235, 255, 0.3);
-            // margin-bottom: 12px;
-            .input-box {
-                &.mark-box {
-                    padding: 8px 0 12px 0;
-                }
-            }
-
-            // .input-unit {
-            //     ::v-deep {
-            //         .el-input {
-            //             border: 1px solid #dcdfe6;
-            //             border-radius: 5px;
-            //             height: 32px;
-            //             box-sizing: border-box;
-            //         }
-            //         .el-input__wrapper {
-            //             padding: 0 2px 0 10px;
-            //             height: 30px;
-            //             line-height: 30px;
-            //             min-height: 30px;
-            //             box-shadow: none;
-            //         }
-            //         .el-input__inner {
-            //             --el-input-inner-height: 30px;
-            //             height: 30px;
-            //             line-height: 30px;
-            //             min-height: 30px;
-            //             color: #606266;
-            //             --el-input-placeholder-color: #a8abb2;
-            //         }
-            //         .el-input-group__append {
-            //             box-shadow: none;
-            //             border: none;
-            //             background: none;
-            //         }
-            //     }
-            // }
-            // .text-center {
-            //     ::v-deep {
-            //         .el-input__inner {
-            //             text-align: center;
-            //         }
-            //     }
-            // }
-            .action-btn {
-                margin-top: 12px;
-                display: flex;
-                justify-content: flex-end;
-                .btn {
-                    color: #8f8f8f;
-                    border-radius: 25px;
-                    padding: 5px 30px;
-                }
-                .delete-btn {
-                    color: rgba(255, 89, 89, 0.9);
-                    background: #fff;
-                    border: 1px solid rgba(255, 89, 89, 0.9);
-                }
-            }
-            .btn-group {
-                padding-top: 12px;
-            }
-            .sub-item {
-                // padding-left: 10px;
-                .has-sub {
-                    display: flex;
-                    flex-direction: column;
-                    align-items: center;
-                    .main-name {
-                        line-height: 20px;
-                    }
-                    .sub-name {
-                        font-size: 10px;
-                        color: rgba(129, 129, 129, 0.5);
-                        line-height: 14px;
-                    }
-                }
-                .colunm-sub {
-                    display: flex;
-                    align-items: center;
-                    .sub-name {
-                        font-size: 10px;
-                        color: rgba(129, 129, 129, 0.5);
-                    }
-                }
-                .r-text {
-                    width: 132px;
-                    text-align: center;
-                    font-size: 14px;
-                    color: #474747;
-                }
-                .price {
-                    ::v-deep {
-                        .el-input__wrapper {
-                            box-shadow: 0 0 0 1px rgba(33, 153, 248, 0.3) inset;
-                        }
-                        .el-input__inner {
-                            color: #2199f8;
-                        }
-                    }
-                }
-            }
-            .form-title {
-                font-size: 14px;
-                padding-top: 6px;
-                color: #000;
-                font-weight: 600;
-            }
-            .box-item + .box-item {
-                margin-top: 8px;
-            }
-        }
-        .form-box + .form-box {
-            margin-top: 8px;
-        }
-        .usageMode-wrap {
-            padding-top: 8px;
-        }
-    }
-
-    // 状况描述样式
-    .situation-description {
-        width: 100%;
-        .description-title {
-            font-size: 16px;
-            font-weight: bold;
-            color: #000;
-            margin-bottom: 12px;
-        }
-
-        .description-content {
-            .description-textarea {
-                margin-bottom: 10px;
-                width: 100%;
-            }
-
-            .upload-section {
-                .upload-btn {
-                    width: 112px;
-                    height: 32px;
-                    border-radius: 3px;
-                    border: 1px solid #e0e0e0;
-                    background: #fff;
-                    color: #000;
-                    font-size: 14px;
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    margin-bottom: 8px;
-
-                    .el-icon {
-                        margin-right: 6px;
-                    }
-                }
-
-                .upload-tip {
-                    font-size: 12px;
-                    color: #999;
-                    line-height: 1.4;
-                }
-            }
-        }
-    }
-
-    // 专家诊断按钮样式
-    .expert-diagnosis-btn {
-        width: 180px;
-        height: 40px;
-        border-radius: 24px;
-        background: linear-gradient(180deg, #70bffe 0%, #2199f8 100%);
-        color: #ffffff;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        margin: 30px auto 0;
-    }
-}
-
-.complete-tip-popup {
-    width: 80%;
-    min-width: 294px;
-    padding: 28px 20px 20px;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    .tip-icon {
-        margin-bottom: 12px;
-        &.create-icon {
-            width: 40px;
-            height: 40px;
-        }
-        &.success-icon {
-            width: 68px;
-            height: 68px;
-        }
-    }
-    .tip-text {
-        margin-bottom: 32px;
-        text-align: center;
-        &.success-text {
-            font-size: 24px;
-            font-weight: 400;
-        }
-    }
-    .btn-wrap {
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        gap: 10px;
-        width: 100%;
-        .btn-item {
-            height: 40px;
-            line-height: 40px;
-            border-radius: 20px;
-            font-size: 16px;
-            color: #2199F8;
-            text-align: center;
-            &.second {
-                flex: none;
-                width: 92px;
-                border: 1px solid #2199F8;
-            }
-            &.primary {
-                flex: 1;
-                background: #2199f8;
-                color: #fff;
-            }
-        }
-    }
-}
-</style>

+ 0 - 484
src/views/old_mini/monitor/index.vue

@@ -1,484 +0,0 @@
-<template>
-    <custom-header v-if="isHeaderShow" name="农场详情"></custom-header>
-    <div class="monitor-index" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
-        <!-- 天气遮罩 -->
-        <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
-        <!-- 天气 -->
-        <weather-info ref="weatherInfoRef" class="weather-info" @weatherExpanded="weatherExpanded"
-            @changeGarden="changeGarden" :isGarden="true" :gardenId="defaultGardenId"></weather-info>
-        <!-- 作物档案 -->
-        <div class="archives-time-line">
-            <div class="archives-time-line-header" @click="handleJump">
-                <div class="line-title">作物档案</div>
-                <!-- <el-date-picker style="width: 110px" v-model="date" type="year" placeholder="全部日期" /> -->
-            </div>
-            <div class="archives-time-line-content">
-                <div class="report-box" v-if="hasReport">
-                    <div class="box-content">
-                        <div class="box-title" @click="handleReportClick">
-                            <span>农情互动报告</span>
-                            <el-icon>
-                                <CaretRight />
-                            </el-icon>
-                        </div>
-                        <span class="box-text">点击查看您的长势报告</span>
-                    </div>
-                    <img src="@/assets/img/monitor/report-icon.png" alt="" class="report-icon" />
-                </div>
-                <div class="time-line" :class="{ 'no-report': !hasReport }">
-                    <archives-farm-time-line :farmId="gardenId"></archives-farm-time-line>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <tip-popup v-model:show="showFarmPopup" type="success" text="农场领取成功"
-        :overlay-style="{ 'backdrop-filter': 'blur(4px)' }" :closeOnClickOverlay="false" :zIndex="9999" />
-
-    <!-- 农事执行弹窗 -->
-    <agri-execute-popup v-model:show="showAgriExecutePopup" :popupData="agriExecuteData"
-        @executed="handleAgriExecuted" @close="handleClosePopup" />
-</template>
-
-<script setup>
-import customHeader from "@/components/customHeader.vue";
-import { ref, computed, onActivated, onDeactivated, onMounted } from "vue";
-import { useStore } from "vuex";
-import { Badge, List } from "vant";
-import weatherInfo from "@/components/weatherInfo.vue";
-import { useRouter, useRoute } from "vue-router";
-import farmInfoPopup from "../home/components/farmInfoPopup.vue";
-import tipPopup from "@/components/popup/tipPopup.vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-import ArchivesFarmTimeLine from "@/components/pageComponents/ArchivesFarmTimeLine.vue";
-import agriExecutePopup from "@/components/popup/agriExecutePopup.vue";
-
-const handleJump = () =>{
-    router.push('/create_farm?type=farmer&expertMiniUserId=81881&isReload=true')
-}
-
-const showAgriExecutePopup = ref(false); // 农事执行弹窗
-const agriExecuteData = ref({});
-const handleAgriExecuted = () => {
-    showAgriExecutePopup.value = false;
-    // router.push("/interaction_list?expertMiniUserId=81881&oldUser=true");
-    handleClosePopup();
-    router.push("/interaction_list?expertMiniUserId=81881");
-};
-
-const expertInfo = ref({});
-const checkHasUnrepliedTriggeredInteraction = async () => {
-    const { data } = await VE_API.home.hasUnrepliedTriggeredInteraction({ farmId: localStorage.getItem("selectedFarmId") });
-    if (data && data.id != null) {
-        expertInfo.value = data;
-        agriExecuteData.value = {
-            expertAvatar: data.expertAvatar,
-            expertName: data.expertName,
-            title: data.subjectName,
-            abnormalText: data.subjectRemark,
-            exampleImg: JSON.parse(data.exampleImagesJson)[0],
-            executedButtonText: '开始采集',
-        };
-        showAgriExecutePopup.value = true;
-    }
-};
-
-const showFarmPopup = ref(false); // 农场领取成功弹窗
-const date = ref(new Date());
-
-const defaultGardenId = ref(null);
-const isHeaderShow = ref(false);
-const isDefaultFarm = ref(false);
-const weatherInfoRef = ref(null);
-const hasReport = ref(false);
-onActivated(() => {
-    sessionStorage.removeItem('interactionListScrollTop');
-    // 用来接收我的农场跳转过来的农场详情逻辑
-    if (route.query.isHeaderShow) {
-        isHeaderShow.value = true;
-        defaultGardenId.value = route.query.farmId;
-        // 统一转换为布尔值
-        isDefaultFarm.value = route.query.defaultFarm === "true" || route.query.defaultFarm === true;
-    }
-    
-    getReport();
-});
-
-const receiveFarm = (json) => {
-    VE_API.monitor
-        .receiveFarm({
-            agriculturalStoreId: json.agriculturalStoreId,
-            farmId: json.farmId,
-        })
-        .then((res) => {
-            if (res.code === 0) {
-                showFarmPopup.value = true;
-                defaultGardenId.value = json.farmId;
-            } else {
-                ElMessage.warning(res.msg);
-            }
-            // 清空路由参数
-            router.replace({ path: route.path });
-        });
-};
-
-const store = useStore();
-const tabBarHeight = computed(() => store.state.home.tabBarHeight);
-const router = useRouter();
-const route = useRoute();
-
-const farmInfoRef = ref(null);
-
-function toFarmInfo() {
-    farmInfoRef.value.handleShow();
-}
-
-// 功能卡片数据
-const functionCards = ref([
-    {
-        title: "农事规划",
-        route: "/plan",
-    },
-    {
-        title: "农场报告",
-        status: "最新",
-        route: "/farm_report",
-        className: "blue",
-    },
-    {
-        title: "农事方案",
-        route: "/agricultural_plan",
-    },
-    {
-        title: "复核成效",
-        status: "最新",
-        route: "/review-results",
-        className: "yellow",
-    },
-]);
-
-const getStayCount = () => {
-    VE_API.monitor
-        .getCountByStatusAndFarmId({
-            farmId: gardenId.value,
-            startStatus: 1,
-            endStatus: 3,
-        })
-        .then((res) => {
-            functionCards.value[0].status = null;
-            if (res.data && res.data != 0) {
-                functionCards.value[0].status = res.data + " 待完成";
-            }
-        });
-};
-
-// 实时播报数据
-const broadcastList = ref([]);
-const loading = ref(false);
-const finished = ref(false);
-const currentPage = ref(1);
-const pageSize = ref(10);
-
-const getBroadcastList = async (page = 1, isLoadMore = false) => {
-    if (!gardenId.value) {
-        loading.value = false;
-        return;
-    }
-
-    // 如果正在加载,直接返回(避免重复请求)
-    if (loading.value) {
-        return;
-    }
-
-    loading.value = true;
-    try {
-        const res = await VE_API.monitor.broadcastPage({
-            farmId: gardenId.value,
-            limit: pageSize.value,
-            page: page,
-        });
-
-        const newData = res.data || [];
-        if (isLoadMore) {
-            broadcastList.value = [...broadcastList.value, ...newData];
-        } else {
-            broadcastList.value = newData;
-        }
-
-        // 判断是否还有更多数据
-        if (newData.length < pageSize.value) {
-            finished.value = true;
-        } else {
-            finished.value = false;
-            // 如果未完成,页码+1,为下次加载做准备
-            currentPage.value = page + 1;
-        }
-    } catch (error) {
-        console.error("获取播报列表失败:", error);
-        finished.value = true;
-    } finally {
-        // 确保 loading 状态被正确设置为 false
-        loading.value = false;
-    }
-};
-
-// 滚动加载更多
-const onLoad = async () => {
-    if (finished.value || loading.value) return;
-
-    // 判断是否是首次加载(页码为1)
-    const isLoadMore = currentPage.value > 1;
-    const pageToLoad = currentPage.value;
-
-    // 加载数据(页码会在 getBroadcastList 成功后自动更新)
-    await getBroadcastList(pageToLoad, isLoadMore);
-};
-
-// 卡片点击事件
-const handleCardClick = (card) => {
-    const params = {
-        farmId: gardenId.value,
-    };
-    router.push({
-        path: card.route,
-        query: { ...params, miniJson: JSON.stringify(params) },
-    });
-};
-
-// 播报相关事件
-const isSpeaking = ref(false);
-const speechSynthesis = window.speechSynthesis;
-
-const handleBroadcast = () => {
-    if (isSpeaking.value) {
-        // 如果正在播放,则停止
-        speechSynthesis.cancel();
-        isSpeaking.value = false;
-        return;
-    }
-
-    // 构建播报文本
-    let broadcastText = "实时播报:";
-
-    if (broadcastList.value.length === 0) {
-        broadcastText += "暂无更多播报";
-    } else {
-        broadcastList.value.forEach((item, index) => {
-            broadcastText += `${index + 1}、${item.title}。${item.content}。`;
-        });
-    }
-
-    // 创建语音合成对象
-    const utterance = new SpeechSynthesisUtterance(broadcastText);
-
-    // 设置语音参数
-    utterance.lang = "zh-CN";
-    utterance.rate = 0.8; // 语速
-    utterance.pitch = 1; // 音调
-    utterance.volume = 1; // 音量
-
-    // 播放开始事件
-    utterance.onstart = () => {
-        isSpeaking.value = true;
-    };
-
-    // 播放结束事件
-    utterance.onend = () => {
-        isSpeaking.value = false;
-    };
-
-    // 播放错误事件
-    utterance.onerror = (event) => {
-        isSpeaking.value = false;
-        console.error("播报错误:", event.error);
-    };
-
-    // 开始播报
-    speechSynthesis.speak(utterance);
-};
-
-// 组件卸载时停止语音播放
-onDeactivated(() => {
-    showFarmPopup.value = false;
-    isDefaultFarm.value = false;
-    if (isSpeaking.value) {
-        speechSynthesis.cancel();
-        isSpeaking.value = false;
-    }
-});
-
-const isExpanded = ref(false);
-const weatherExpanded = (isExpandedValue) => {
-    isExpanded.value = isExpandedValue;
-};
-
-// 点击遮罩时收起天气
-const handleMaskClick = () => {
-    if (weatherInfoRef.value && weatherInfoRef.value.toggleExpand) {
-        weatherInfoRef.value.toggleExpand();
-    }
-};
-
-const gardenId = ref(store.state.home.gardenId);
-
-// 初始化加载数据
-onMounted(() => {
-    if (gardenId.value) {
-        currentPage.value = 1;
-        finished.value = false;
-        broadcastList.value = [];
-    }
-});
-
-const changeGarden = ({ id }) => {
-    gardenId.value = id;
-    // 更新 store 中的状态
-    store.commit("home/SET_GARDEN_ID", id);
-    // 重置分页状态
-    currentPage.value = 1;
-    finished.value = false;
-    broadcastList.value = [];
-    getStayCount();
-    getBroadcastList(1, false);
-    checkHasUnrepliedTriggeredInteraction();
-    getReport();
-};
-
-function handlePage(url) {
-    const query = {
-        farmId: gardenId.value,
-    };
-    if (url === "/message_list") {
-        query.from = "monitor";
-    }
-    router.push({
-        path: url,
-        query: query,
-    });
-}
-
-function handleReportClick() {
-    router.push({
-        path: "/growth_report",
-        query: { farmId: gardenId.value },
-    });
-}
-
-const handleClosePopup = () => {
-    VE_API.monitor.closeTodayPopup({
-        interactionId: expertInfo.value.id,
-    });
-}
-
-const getReport = () => {
-    VE_API.farm.growthReportByFarm({farmId: gardenId.value, limit: 20}).then(({ data }) => {
-        if (data && data.length > 0) {
-            hasReport.value = true;
-        } else {
-            hasReport.value = false;
-        }
-    });
-}
-</script>
-
-<style scoped lang="scss">
-.monitor-index {
-    width: 100%;
-    height: 100%;
-    padding: 13px 10px;
-    box-sizing: border-box;
-    background: linear-gradient(180deg, #f9f9f9 0%, #f0f8ff 31.47%, #f9f9f9 46.81%, #f9f9f9 69.38%, #f9f9f9 100%);
-
-    .weather-mask {
-        position: fixed;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        background-color: rgba(0, 0, 0, 0.52);
-        z-index: 11;
-    }
-
-    .weather-info {
-        width: calc(100% - 20px);
-        position: absolute;
-        z-index: 12;
-    }
-
-    .archives-time-line {
-        position: relative;
-        margin-top: 96px;
-        height: calc(100% - 90px);
-
-        .archives-time-line-header {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-
-            .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;
-                }
-            }
-        }
-
-        .archives-time-line-content {
-            margin-top: 10px;
-            height: calc(100% - 32px);
-            background: #fff;
-            border-radius: 8px;
-            padding: 10px;
-            box-sizing: border-box;
-
-            .report-box {
-                background: linear-gradient(120deg, #eef8ff, #bbe3ff);
-                border-radius: 4px;
-                padding: 6px 0 0 16px;
-                display: flex;
-                align-items: center;
-                justify-content: space-between;
-                margin-bottom: 12px;
-
-                .box-content {
-                    .box-title {
-                        font-size: 16px;
-                        color: #2199f8;
-                        font-weight: 500;
-                        margin-bottom: 4px;
-                        display: flex;
-                        align-items: center;
-                    }
-
-                    .box-text {
-                        color: #4e5969;
-                    }
-                }
-
-                .report-icon {
-                    width: 120px;
-                    height: 85px;
-                }
-            }
-
-            .time-line {
-                height: calc(100% - 100px);
-                &.no-report {
-                    height: 100%;
-                }
-            }
-        }
-    }
-}
-</style>

+ 0 - 149
src/views/old_mini/monitor/subPages/agriculturalDetail.vue

@@ -1,149 +0,0 @@
-<template>
-    <div class="agricultural-detail">
-        <custom-header name="农事详情"></custom-header>
-
-        <div class="detail-content">
-            <!-- 采样信息卡片 -->
-            <div class="card-wrap">
-                <div class="card-box sampling-card">
-                    <div class="sampling-title">采样时间: {{ samplingTime }}</div>
-                    <div class="sampling-desc">{{ samplingDesc }}</div>
-                </div>
-            </div>
-
-            <!-- 农情照片卡片 -->
-            <div class="card-wrap">
-                <div class="card-box photo-card">
-                    <div class="card-title">农情照片</div>
-                    <div class="area-btns">
-                        <div v-for="(area, idx) in areaList" :key="idx" class="area-btn"
-                            :class="{ active: activeAreaIndex === idx }" @click="activeAreaIndex = idx">
-                            {{ area }}区
-                        </div>
-                    </div>
-                    <div class="ratio-tip">出现新梢的果树占比为{{ currentRatio }}%</div>
-                </div>
-            </div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import { useRouter, useRoute } from "vue-router";
-import { ref, computed } from "vue";
-import customHeader from "@/components/customHeader.vue";
-
-const router = useRouter();
-const route = useRoute();
-
-// 从路由 miniJson 解析 id
-const detailId = ref(null);
-if (route.query.miniJson) {
-    try {
-        const mini = JSON.parse(route.query.miniJson);
-        detailId.value = mini.id ?? null;
-    } catch (_) {
-        console.error("解析 miniJson 失败", _);
-    }
-}
-
-// 采样时间、描述(后续可接接口)
-const samplingTime = ref("2025.05.06");
-const samplingDesc = ref("本次飞巡采样了1区、2区和5区,拍摄了120棵树");
-
-// 区域列表与当前选中
-const areaList = ref(["1", "2", "3", "3"]);
-const activeAreaIndex = ref(0);
-
-// 当前选中区的占比(示例数据,可按区区分)
-const ratioByArea = ["5", "8", "12", "12"];
-const currentRatio = computed(() => ratioByArea[activeAreaIndex.value] ?? "5");
-
-</script>
-
-<style lang="scss" scoped>
-.agricultural-detail {
-    min-height: 100vh;
-    width: 100%;
-    background: #f2f3f5;
-
-    .detail-content {
-        padding: 12px;
-        padding-bottom: 24px;
-        box-sizing: border-box;
-    }
-}
-
-.card-wrap {
-    margin-bottom: 12px;
-}
-
-.card-box {
-    background: #fff;
-    border-radius: 8px;
-    padding: 12px 16px;
-    box-sizing: border-box;
-}
-
-.sampling-card {
-    .sampling-title {
-        font-size: 16px;
-        font-weight: 500;
-        color: #333;
-        margin-bottom: 6px;
-    }
-
-    .sampling-desc {
-        font-size: 14px;
-        color: #767676;
-        line-height: 1.5;
-    }
-}
-
-.photo-card {
-    .card-title {
-        font-size: 16px;
-        font-weight: bold;
-        color: #333;
-        margin-bottom: 12px;
-    }
-
-    .area-btns {
-        display: flex;
-        flex-wrap: nowrap;
-        gap: 8px;
-        margin-bottom: 12px;
-        overflow-x: auto;
-        padding-bottom: 4px;
-        -webkit-overflow-scrolling: touch;
-
-        &::-webkit-scrollbar {
-            display: none;
-        }
-
-        .area-btn {
-            padding: 0 14px;
-            height: 32px;
-            line-height: 32px;
-            font-size: 14px;
-            color: #333;
-            background: #f2f3f5;
-            border-radius: 16px;
-            white-space: nowrap;
-
-            &.active {
-                background: #2199f8;
-                color: #fff;
-            }
-        }
-    }
-
-    .ratio-tip {
-        font-size: 14px;
-        color: #2199f8;
-        padding: 10px 12px;
-        background: rgba(33, 153, 248, 0.08);
-        border-radius: 8px;
-    }
-}
-</style>

+ 0 - 728
src/views/old_mini/monitor/subPages/plan copy 2.vue

@@ -1,728 +0,0 @@
-<template>
-    <div class="plan-page">
-        <custom-header name="农事规划"></custom-header>
-        <div class="plan-content">
-            <div class="filter-wrap">
-                <div class="season-tabs">
-                    <div
-                        v-for="s in seasons"
-                        :key="s.value"
-                        class="season-tab"
-                        :class="{ active: s.value === activeSeason }"
-                        @click="handleSeasonClick(s.value)"
-                    >
-                        {{ s.label }}
-                    </div>
-                </div>
-                <div class="status-filter">
-                    <div v-for="status in statusList" :key="status.value" class="status-item" :class="status.color">
-                        <div class="status-dot"></div>
-                        <span class="status-text">{{ status.label }}</span>
-                    </div>
-                </div>
-            </div>
-            <div class="timeline-container" ref="timelineContainerRef">
-                <div class="timeline-list" :style="getListStyle">
-                    <div class="timeline-middle-line"></div>
-                    <!-- 物候期覆盖条(progress 为起点,progress2 为终点,单位 %) -->
-                    <div
-                        v-for="(p, idx) in phenologyList"
-                        :key="p.id ?? idx"
-                        class="phenology-bar"
-                        :style="getPhenologyBarStyle(p)"
-                    >
-                        <div class="reproductive-list">
-                            <div
-                                v-for="(r, rIdx) in Array.isArray(p.reproductiveList) ? p.reproductiveList : []"
-                                :key="r.id ?? rIdx"
-                                class="reproductive-item"
-                                :class="{
-                                    'horizontal-text': getReproductiveItemHeight(p) < 30,
-                                    'vertical-lr-text': getReproductiveItemHeight(p) >= 30
-                                }"
-                                :style="getReproductiveItemHeight(p) < 30 ? { '--item-height': `${getReproductiveItemHeight(p)}px` } : {}"
-                            >
-                                {{ r.name }}
-                                <div class="arranges" :class="{ 'no-wrap': getReproductiveItemHeight(p) <= 35 }">
-                                    <div
-                                        v-for="(fw, aIdx) in Array.isArray(r.farmWorkArrangeList)
-                                            ? r.farmWorkArrangeList
-                                            : []"
-                                        :key="fw.id ?? aIdx"
-                                        class="arrange-box"
-                                        :class="[
-                                            getArrangeStatusClass(fw),
-                                            {
-                                                'small-height': getReproductiveItemHeight(p) <= 35,
-                                                'two-chars': fw.farmWorkName && fw.farmWorkName.trim().length === 2,
-                                                'text-4-6': fw.farmWorkName && getTextLengthClass(fw.farmWorkName) === 'text-4-6',
-                                                'text-7-8': fw.farmWorkName && getTextLengthClass(fw.farmWorkName) === 'text-7-8'
-                                            }
-                                        ]"
-                                        @click="handleRowClick(fw)"
-                                    >
-                                        <span class="arrange-text">{{ formatTextWithLineBreak(fw.farmWorkName) }}</span>
-                                        <div
-                                            v-if="
-                                                getArrangeStatusClass(fw) === 'status-complete' ||
-                                                getArrangeStatusClass(fw) === 'status-warning'
-                                            "
-                                            class="status-icon"
-                                            :class="getArrangeStatusClass(fw)"
-                                        >
-                                            <el-icon
-                                                v-if="getArrangeStatusClass(fw) === 'status-complete'"
-                                                size="16"
-                                                color="#1CA900"
-                                            >
-                                                <SuccessFilled />
-                                            </el-icon>
-                                            <el-icon v-else size="18" color="#FF953D">
-                                                <WarnTriangleFilled />
-                                            </el-icon>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                    <div v-for="t in solarTerms" :key="t.id" class="timeline-term" :style="getTermStyle(t)">
-                        <span class="term-name">{{ t.displayName }}</span>
-                    </div>
-                </div>
-            </div>
-            <div class="control-section">
-                <div class="toggle-group">
-                    <el-switch v-model="isDefaultEnabled" />
-                    <span class="toggle-label">{{ isDefaultEnabled ? "默认" : "" }}发起农情需求</span>
-                </div>
-                <div class="add-button-group">
-                    <div class="add-button button" @click="addNewTask">新增农事</div>
-                    <div class="button" @click="manageTask">农事管理</div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!-- 农事信息弹窗 -->
-    <detail-dialog ref="detailDialogRef" @triggerFarmWork="triggerFarmWork"></detail-dialog>
-    <!-- 新增:激活上传弹窗 -->
-    <active-upload-popup @handleUploadSuccess="getFarmWorkPlan"></active-upload-popup>
-</template>
-
-<script setup>
-import { reactive, ref, onMounted, computed, nextTick } from "vue";
-import customHeader from "@/components/customHeader.vue";
-import { useRouter, useRoute } from "vue-router";
-import detailDialog from "@/components/detailDialog.vue";
-import eventBus from "@/api/eventBus";
-import activeUploadPopup from "@/components/popup/activeUploadPopup.vue";
-import { ElMessage } from "element-plus";
-import { SuccessFilled, WarningFilled } from "@element-plus/icons-vue";
-const router = useRouter();
-const route = useRoute();
-
-// 状态列表数据
-const seasons = reactive([
-    { value: "spring", label: "春季" },
-    { value: "summer", label: "夏季" },
-    { value: "autumn", label: "秋季" },
-    { value: "winter", label: "冬季" },
-]);
-const activeSeason = ref("");
-
-const statusList = reactive([
-    { value: "pending", label: "待触发", color: "gray" },
-    { value: "executing", label: "待完成", color: "blue" },
-    { value: "completed", label: "已完成", color: "green" },
-    { value: "expired", label: "已过期", color: "orange" },
-]);
-
-const solarTerms = ref([]);
-const phenologyList = ref([]);
-
-// 获取当前季节
-const getCurrentSeason = () => {
-    const month = new Date().getMonth() + 1; // 1-12
-    if (month >= 3 && month <= 5) {
-        return "spring"; // 春季:3-5月
-    } else if (month >= 6 && month <= 8) {
-        return "summer"; // 夏季:6-8月
-    } else if (month >= 9 && month <= 10) {
-        return "autumn"; // 秋季:9-10月
-    } else {
-        return "winter"; // 冬季:12-2月
-    }
-};
-
-onMounted(() => {
-    getFarmWorkPlan();
-});
-
-const getFarmWorkPlan = () => {
-    // 如果不是首次加载,保存当前滚动位置
-    let savedScrollTop = 0;
-    if (!isInitialLoad.value && timelineContainerRef.value) {
-        savedScrollTop = timelineContainerRef.value.scrollTop || 0;
-    }
-    
-    VE_API.monitor
-        .farmWorkPlan({ farmId: route.query.farmId })
-        .then(({ data, code }) => {
-            if (code === 0) {
-                const list = Array.isArray(data?.solarTermsList) ? data.solarTermsList : [];
-                const filtered = list
-                    .filter((t) => t && t.type === 1)
-                    .map((t) => ({
-                        id:
-                            t.id ??
-                            t.solarTermsId ??
-                            t.termId ??
-                            `${t.name || t.solarTermsName || t.termName || "term"}-${t.createDate || ""}`,
-                        displayName: t.name || t.solarTermsName || t.termName || "节气",
-                        createDate: t.createDate || null,
-                        progress: Number(t.progress) || 0,
-                    }));
-                solarTerms.value = filtered;
-                // 物候期数据
-                phenologyList.value = Array.isArray(data?.phenologyList)
-                    ? data.phenologyList.map((it) => ({
-                          id: it.id ?? it.phenologyId ?? it.name ?? `${it.progress}-${it.progress2}`,
-                          progress: Number(it.progress) || 0, // 起点 %
-                          progress2: Number(it.progress2) || 0, // 终点 %
-                          // 兼容多种可能的开始时间字段
-                          startTimeMs: safeParseDate(
-                              it.startDate || it.beginDate || it.startTime || it.start || it.start_at
-                          ),
-                          reproductiveList: Array.isArray(it.reproductiveList) ? it.reproductiveList : [],
-                      }))
-                    : [];
-                
-                // 等待 DOM 更新后处理滚动
-                nextTick(() => {
-                    if (isInitialLoad.value) {
-                        // 首次加载:设置默认季节为当前季节,并自动滚动到对应位置
-                        const currentSeason = getCurrentSeason();
-                        handleSeasonClick(currentSeason);
-                        isInitialLoad.value = false;
-                    } else {
-                        // 非首次加载:恢复之前的滚动位置
-                        if (timelineContainerRef.value && savedScrollTop > 0) {
-                            timelineContainerRef.value.scrollTop = savedScrollTop;
-                        }
-                    }
-                });
-            }
-        })
-        .catch((error) => {
-            console.error("获取农事规划数据失败:", error);
-        });
-};
-
-// 切换开关状态
-const isDefaultEnabled = ref(true);
-// 新增农事
-const addNewTask = () => {
-    ElMessage.warning("该功能正在升级中,敬请期待");
-    // router.push({
-    //     path: "/modify_work",
-    //     query: { data: JSON.stringify(["生长异常"]), gardenId: 766, isAdd: true },
-    // });
-};
-
-const triggerFarmWork = () => {
-    eventBus.emit("activeUpload:show", {
-        gardenIdVal: route.query.farmId,
-        problemTitleVal: '请选择您出现' + curFarmObj.value.farmWorkName + '的时间',
-        arrangeIdVal: curFarmObj.value.id,
-    });
-};
-
-const curFarmObj = ref({});
-const handleRowClick = (item) => {
-    curFarmObj.value = item;
-    // 0:默认,1-4:正常,5:完成,6:预警
-    if (item.flowStatus === 5) {
-        router.push({
-            path: "/review_work",
-            query: {
-                miniJson: JSON.stringify({ id: item.farmWorkRecordId,goBack: true }),
-            },
-        });
-    } else if (item.flowStatus === null) {
-        detailDialogRef.value.showDialog(item.farmWorkId);
-    } else if (item.flowStatus === 6 || (item.flowStatus < 5 && item.flowStatus >= 0)) {
-        router.push({
-            path: "/completed_work",
-            query: {
-                miniJson: JSON.stringify({ id: item.farmWorkRecordId }),
-            },
-        });
-    }
-};
-
-const manageTask = () => {
-    router.push({
-        path: "/agri_services_manage",
-        query: {
-            type: "manage",
-        },
-    });
-};
-
-const detailDialogRef = ref(null);
-const timelineContainerRef = ref(null);
-// 标记是否为首次加载
-const isInitialLoad = ref(true);
-
-// 安全解析时间到时间戳(ms)
-const safeParseDate = (val) => {
-    if (!val) return NaN;
-    if (val instanceof Date) return val.getTime();
-    if (typeof val === "number") return val;
-    if (typeof val === "string") {
-        // 兼容 "YYYY-MM-DD HH:mm:ss" -> Safari
-        const s = val.replace(/-/g, "/").replace("T", " ");
-        const d = new Date(s);
-        return isNaN(d.getTime()) ? NaN : d.getTime();
-    }
-    return NaN;
-};
-
-// 计算节气列表容器高度与项位置
-const getListStyle = computed(() => {
-    const total = (solarTerms.value?.length || 0) * 100;
-    const minH = 50 + total + 50; // 上下各 50
-    return { minHeight: `${minH}px` };
-});
-
-const getTermStyle = (t) => {
-    const p = Math.max(0, Math.min(100, Number(t?.progress) || 0));
-    const total = (solarTerms.value?.length || 0) * 100;
-    const top = 50 + (p / 100) * total;
-    return {
-        position: "absolute",
-        top: `${top}px`,
-        left: 0,
-        transform: "translateY(-50%)",
-        width: "30px",
-        height: "20px",
-        display: "flex",
-        alignItems: "center",
-    };
-};
-
-// 点击季节 → 滚动到对应节气(立春/立夏/立秋/立冬)
-const handleSeasonClick = (seasonValue) => {
-    activeSeason.value = seasonValue;
-    const mapping = {
-        spring: "立春",
-        summer: "立夏",
-        autumn: "立秋",
-        winter: "立冬",
-    };
-    const targetName = mapping[seasonValue];
-    if (!targetName) return;
-    const target = (solarTerms.value || []).find((t) => (t?.displayName || "") === targetName);
-    if (!target) return;
-    const p = Math.max(0, Math.min(100, Number(target.progress) || 0));
-    const total = (solarTerms.value?.length || 0) * 100;
-    const targetTop = 50 + (p / 100) * total; // 内容内的像素位置
-    const wrap = timelineContainerRef.value;
-    if (!wrap) return;
-    const viewH = wrap.clientHeight || 0;
-    const maxScroll = Math.max(0, wrap.scrollHeight - viewH);
-    // 将目标位置稍微靠上(使用 0.35 视口高度做偏移)
-    let scrollTop = Math.max(0, targetTop - viewH * 0.1);
-    if (scrollTop > maxScroll) scrollTop = maxScroll;
-    wrap.scrollTo({ top: scrollTop, behavior: "smooth" });
-};
-
-// 物候期覆盖条样式(使用像素计算,避免 100% 高度为 0 的问题)
-const getPhenologyBarStyle = (item) => {
-    const p1 = Math.max(0, Math.min(100, Number(item?.progress) || 0));
-    const p2 = Math.max(0, Math.min(100, Number(item?.progress2) || 0));
-    const start = Math.min(p1, p2);
-    const end = Math.max(p1, p2);
-    const total = (solarTerms.value?.length || 0) * 100; // 有效绘制区高度(px)
-    const topPx = 50 + (start / 100) * total;
-    const heightPx = Math.max(2, ((end - start) / 100) * total);
-    const now = Date.now();
-    const isFuture = Number.isFinite(item?.startTimeMs) ? item.startTimeMs > now : start > 0; // 无开始时间时按起点>0近似
-    // 反转:大于当前时间用灰色,小于等于当前时间用蓝色
-    const barColor = isFuture ? "rgba(145, 145, 145, 0.1)" : "#2199F8";
-    const beforeBg = isFuture ? "rgba(145, 145, 145, 0.1)" : "rgba(33, 153, 248, 0.1)";
-    return {
-        position: "absolute",
-        left: "46px",
-        width: "25px",
-        top: `${topPx}px`,
-        height: `${heightPx}px`,
-        background: barColor,
-        color: isFuture ? "#747778" : "#fff",
-        "--bar-before-bg": beforeBg,
-        zIndex: 2,
-    };
-};
-
-// 农事状态样式映射(0:默认,1-4:正常,5:完成,6:预警)
-const getArrangeStatusClass = (fw) => {
-    const t = fw?.flowStatus;
-    if (t == null) return "status-default";
-    if (t >= 0 && t <= 4) return "status-normal";
-    if (t === 5) return "status-complete";
-    if (t === 6) return "status-warning";
-    return "status-default";
-};
-
-// 计算 phenology-bar 的高度(px)
-const getPhenologyBarHeight = (item) => {
-    const p1 = Math.max(0, Math.min(100, Number(item?.progress) || 0));
-    const p2 = Math.max(0, Math.min(100, Number(item?.progress2) || 0));
-    const start = Math.min(p1, p2);
-    const end = Math.max(p1, p2);
-    const total = (solarTerms.value?.length || 0) * 100;
-    const heightPx = Math.max(2, ((end - start) / 100) * total);
-    return heightPx;
-};
-
-// 计算 reproductive-item 的高度(px)
-// 由于 reproductive-list 使用 grid-auto-rows: 1fr,每个 item 会等分 phenology-bar 的高度
-const getReproductiveItemHeight = (phenologyItem) => {
-    const barHeight = getPhenologyBarHeight(phenologyItem);
-    const listLength = Array.isArray(phenologyItem?.reproductiveList) ? phenologyItem.reproductiveList.length : 1;
-    // 如果列表为空,返回 barHeight;否则等分
-    return listLength > 0 ? barHeight / listLength : barHeight;
-};
-
-// 根据文字长度返回对应的 class
-const getTextLengthClass = (text) => {
-    if (!text || typeof text !== "string") return "";
-    const len = text.trim().length;
-    if (len > 4 && len <= 6) return "text-4-6";
-    if (len > 6 && len <= 8) return "text-7-8";
-    return "";
-};
-
-// 处理文本,在括号前换行
-const formatTextWithLineBreak = (text) => {
-    if (!text || typeof text !== "string") return text;
-    // 在左括号前添加换行符
-    return text.replace(/([((])/g, "\n$1");
-};
-
-</script>
-
-<style scoped lang="scss">
-.plan-page {
-    width: 100%;
-    height: 100vh;
-    background: #fff;
-    .plan-content {
-        .filter-wrap {
-            background: #fff;
-            padding: 13px 12px;
-            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-            border-radius: 0 0 20px 20px;
-            .status-filter {
-                background: #fff;
-                padding: 3px 17px;
-                display: flex;
-                align-items: center;
-                gap: 16px;
-                font-size: 12px;
-
-                .status-item {
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    gap: 6px;
-                    flex: 1;
-                    &.gray {
-                        color: #c4c6c9;
-                        .status-dot {
-                            background-color: #c4c6c9;
-                        }
-                    }
-
-                    &.blue {
-                        color: #2199f8;
-                        .status-dot {
-                            background-color: #2199f8;
-                        }
-                    }
-
-                    &.green {
-                        color: #1ca900;
-                        .status-dot {
-                            background-color: #1ca900;
-                        }
-                    }
-
-                    &.orange {
-                        color: #ff953d;
-                        .status-dot {
-                            background-color: #ff953d;
-                        }
-                    }
-                    .status-dot {
-                        width: 6px;
-                        height: 6px;
-                        border-radius: 50%;
-                    }
-                }
-            }
-
-            .season-tabs {
-                display: flex;
-                gap: 8px;
-                margin-bottom: 12px;
-                .season-tab {
-                    flex: 1;
-                    padding: 7px;
-                    text-align: center;
-                    background: #f3f3f3;
-                    color: #898a8a;
-                    border-radius: 3px;
-                    border: 1px solid transparent;
-                    font-size: 12px;
-                }
-                .season-tab.active {
-                    background: #ffffff;
-                    color: #2199f8;
-                    border-color: #2199f8;
-                }
-            }
-        }
-        .timeline-container {
-            height: calc(100vh - 93px - 40px - 73px);
-            overflow: auto;
-            position: relative;
-            box-sizing: border-box;
-            padding: 0 12px;
-            .timeline-list {
-                position: relative;
-            }
-            .timeline-middle-line {
-                position: absolute;
-                left: 15px; /* 位于节气文字列中间(列宽约30px) */
-                top: 50px;
-                bottom: 50px;
-                width: 2px;
-                background: #e8e8e8;
-                z-index: 1;
-            }
-            .phenology-bar {
-                display: flex;
-                align-items: stretch;
-                justify-content: center;
-                box-sizing: border-box;
-                &::before {
-                    content: "";
-                    position: absolute;
-                    top: 0;
-                    left: 25px;
-                    width: calc(100vw - 100px);
-                    height: 100%;
-                    background: var(--bar-before-bg, rgba(201, 201, 201, 0.1));
-                    z-index: 1;
-                }
-                .reproductive-list {
-                    display: grid;
-                    grid-auto-rows: 1fr; /* 子项等高,整体等分父高度 */
-                    align-items: stretch;
-                    justify-items: center; /* 子项居中 */
-                    width: 100%;
-                    height: 100%;
-                    box-sizing: border-box;
-                }
-                .reproductive-item {
-                    font-size: 12px;
-                    text-align: center;
-                    word-break: break-all;
-                    writing-mode: vertical-rl;
-                    text-orientation: upright;
-                    letter-spacing: 3px;
-                    width: 100%;
-                    line-height: 23px;
-                    color: inherit;
-                    position: relative;
-                    &.horizontal-text {
-                        writing-mode: horizontal-tb;
-                        text-orientation: mixed;
-                        letter-spacing: normal;
-                        line-height: calc(var(--item-height, 15px) - 3px);
-                    }
-                    &.vertical-lr-text {
-                        writing-mode: vertical-lr;
-                        text-orientation: upright;
-                        letter-spacing: 3px;
-                        line-height: 26px;
-                    }
-                    .arranges {
-                        position: absolute;
-                        left: 48px; /* 列与中线右侧一段距离 */
-                        top: 50%;
-                        transform: translateY(-50%);
-                        z-index: 3;
-                        display: flex;
-                        flex-wrap: wrap;
-                        flex-direction: row;
-                        align-items: center;
-                        max-width: calc(100vw - 100px);
-                        gap: 16px;
-                        &.no-wrap {
-                            flex-wrap: nowrap;
-                        }
-                        .arrange-box {
-                            width: 36px;
-                            height: 36px;
-                            border: 1px solid rgba(199, 199, 199, 0.6);
-                            border-radius: 2px;
-                            background: #fff;
-                            color: #a5a7a9;
-                            display: flex;
-                            align-items: center;
-                            justify-content: center;
-                            box-sizing: border-box;
-                            position: relative;
-                            font-size: 12px;
-                            flex-shrink: 0;
-                            &.small-height {
-                                height: 20px;
-                                width: 70px;
-                                &.two-chars {
-                                    width: 35px;
-                                }
-                                &.text-4-6 {
-                                    width: 65px;
-                                }
-                                &.text-7-8 {
-                                    width: 66px;
-                                }
-                                .arrange-text {
-                                    writing-mode: vertical-lr;
-                                    white-space: pre-line;
-                                }
-                            }
-                            &.text-4-6 {
-                                width: 65px;
-                            }
-                            &.text-7-8 {
-                                width: 66px;
-                            }
-                            .arrange-text {
-                                writing-mode: horizontal-tb;
-                                line-height: 14px;
-                                text-align: center;
-                                padding-left: 3px;
-                                white-space: pre-line;
-                            }
-                            .status-icon {
-                                position: absolute;
-                                right: -10px;
-                                bottom: -10px;
-                                z-index: 3;
-                            }
-                            &::before {
-                                content: "";
-                                position: absolute;
-                                left: -4px;
-                                top: 50%;
-                                transform: translateY(-50%);
-                                width: 0;
-                                height: 0;
-                                border-top: 4px solid transparent;
-                                border-bottom: 4px solid transparent;
-                                border-right: 4px solid currentColor; /* 与文字/边框颜色一致 */
-                            }
-                        }
-                        .arrange-box.status-warning {
-                            border-color: #ff953d;
-                            color: #ff953d;
-                        }
-                        .arrange-box.status-complete {
-                            border-color: #1ca900;
-                            color: #1ca900;
-                        }
-                        .arrange-box.status-normal {
-                            border-color: #2199f8;
-                            color: #2199f8;
-                        }
-                    }
-                }
-            }
-            .reproductive-item + .reproductive-item {
-                border-top: 2px solid #fff;
-            }
-            .phenology-bar + .phenology-bar {
-                border-top: 2px solid #fff;
-            }
-            .timeline-term {
-                position: absolute;
-                width: 30px;
-                padding-right: 16px;
-                display: flex;
-                align-items: center;
-                z-index: 2; /* 置于中线之上 */
-                .term-name {
-                    display: inline-block;
-                    width: 100%;
-                    height: 46px;
-                    line-height: 30px;
-                    background: #fff;
-                    font-size: 13px;
-                    word-break: break-all;
-                    writing-mode: vertical-rl;
-                    text-orientation: upright;
-                    color: rgba(174, 174, 174, 0.6);
-                    letter-spacing: 2px;
-                    text-align: center;
-                }
-            }
-        }
-
-        // 控制区域样式
-        .control-section {
-            position: fixed;
-            width: 100%;
-            left: 0;
-            box-sizing: border-box;
-            bottom: 0px;
-            background: #fff;
-            padding: 16px 12px;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            border-top: 1px solid #f0f0f0;
-
-            .toggle-group {
-                display: flex;
-                align-items: center;
-                gap: 8px;
-
-                .toggle-label {
-                    font-size: 13px;
-                    color: #141414;
-                }
-            }
-
-            .add-button-group {
-                display: flex;
-                align-items: center;
-                gap: 8px;
-                .button {
-                    color: #2199f8;
-                    border-radius: 25px;
-                    padding: 9px 15px;
-                    border: 1px solid #2199f8;
-                }
-                .add-button {
-                    background: linear-gradient(120deg, #76c3ff 0%, #2199f8 100%);
-                    color: white;
-                    border: 1px solid transparent;
-                }
-            }
-        }
-    }
-}
-</style>

+ 0 - 1006
src/views/old_mini/monitor/subPages/plan copy.vue

@@ -1,1006 +0,0 @@
-<template>
-    <div class="plan-page">
-        <custom-header name="农事规划"></custom-header>
-        <div class="plan-content">
-            <div class="filter-wrap">
-                <div class="season-tabs">
-                    <div
-                        v-for="s in seasons"
-                        :key="s.value"
-                        class="season-tab"
-                        :class="{ active: s.value === activeSeason }"
-                        @click="activeSeason = s.value"
-                    >
-                        {{ s.label }}
-                    </div>
-                </div>
-                <div class="status-filter">
-                    <div v-for="status in statusList" :key="status.value" class="status-item" :class="status.color">
-                        <div class="status-dot"></div>
-                        <span class="status-text">{{ status.label }}</span>
-                    </div>
-                </div>
-            </div>
-
-            <!-- 三行循环时间线 -->
-            <div class="cycle-timeline-container">
-                <div class="cycle-timeline">
-                    <div
-                        v-for="(row, rowIndex) in timelineRows"
-                        :key="rowIndex"
-                        class="cycle-row"
-                        :class="{ 'odd-index': rowIndex % 2 === 1 }"
-                    >
-                        <div
-                            v-for="(item, itemIndex) in row.items"
-                            :key="itemIndex"
-                            class="cycle-item"
-                            @click="handleRowClick(item)"
-                            :class="[item.type + '-item']"
-                        >
-                            <!-- 节气节点 -->
-                            <template v-if="item.type === 'term'">
-                                <!-- <div class="cycle-term-dot"></div> -->
-                                <div class="cycle-term-label">{{ item.name || item.id }}</div>
-                            </template>
-                        </div>
-
-                        <!-- 生育期名称(根据时间范围显示在对应行) -->
-                        <div class="cycle-phenology-wrap" v-if="getPhenologyBarsForRow(rowIndex).length > 0">
-                            <div
-                                v-for="p in getPhenologyBarsForRow(rowIndex)"
-                                :key="p.id"
-                                class="cycle-label"
-                                :class="p.color"
-                                :style="
-                                    isOddVisualRow(rowIndex)
-                                        ? { right: p.left, width: p.width }
-                                        : { left: p.left, width: p.width }
-                                "
-                            >
-                                {{ p.name }}
-                                <div v-if="p.arranges && p.arranges.length" class="arranges">
-                                    <div v-for="a in p.arranges" :key="a.id" :class="['cycle-task-box', a.status]">
-                                        <div class="cycle-task-text">{{ a.farmWorkName || a.name }}</div>
-                                        <!-- 任务连接器 -->
-                                        <div class="cycle-task-connector"></div>
-                                        <div
-                                            v-if="a.status === 'complete' || a.status === 'warning'"
-                                            class="status-icon"
-                                            :class="a.status"
-                                        >
-                                            <el-icon v-if="a.status === 'complete'" size="16" color="#1CA900"
-                                                ><SuccessFilled
-                                            /></el-icon>
-                                            <el-icon v-else size="18" color="#FF953D"><WarnTriangleFilled /></el-icon>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                        <!-- 行连接器 -->
-                        <div
-                            v-if="rowIndex < timelineRows.length - 1"
-                            class="cycle-connector"
-                            :class="[
-                                rowIndex % 2 === 1 ? 'middle-connector' : 'top-connector',
-                                getConnectorColorClass(rowIndex),
-                            ]"
-                        >
-                            <img v-if="isConnectorGray(rowIndex)" src="@/assets/img/monitor/defalut-arrow.png" alt="" />
-                            <img v-else src="@/assets/img/monitor/arrow.png" alt="" />
-                        </div>
-                    </div>
-                </div>
-            </div>
-
-            <div class="control-section">
-                <div class="toggle-group">
-                    <el-switch v-model="isDefaultEnabled" />
-                    <span class="toggle-label">{{ isDefaultEnabled ? "默认" : "" }}发起农情需求</span>
-                </div>
-                <div class="add-button-group">
-                    <div class="add-button button" @click="addNewTask">新增农事</div>
-                    <div class="button" @click="manageTask">农事管理</div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!-- 农事信息弹窗 -->
-    <detail-dialog ref="detailDialogRef"></detail-dialog>
-    <!-- 新增:激活上传弹窗 -->
-    <active-upload-popup></active-upload-popup>
-</template>
-
-<script setup>
-import { reactive, ref, onMounted, nextTick, onBeforeUnmount } from "vue";
-import customHeader from "@/components/customHeader.vue";
-import { useRouter, useRoute } from "vue-router";
-import detailDialog from "@/components/detailDialog.vue";
-import activeUploadPopup from "@/components/popup/activeUploadPopup.vue";
-const router = useRouter();
-const route = useRoute();
-
-// 状态列表数据
-const seasons = reactive([
-    { value: "spring", label: "春季" },
-    { value: "summer", label: "夏季" },
-    { value: "autumn", label: "秋季" },
-    { value: "winter", label: "冬季" },
-]);
-const activeSeason = ref("spring");
-
-const statusList = reactive([
-    { value: "pending", label: "待触发", color: "gray" },
-    { value: "executing", label: "待完成", color: "blue" },
-    { value: "completed", label: "已完成", color: "green" },
-    { value: "expired", label: "已过期", color: "orange" },
-]);
-
-// 切换开关状态
-const isDefaultEnabled = ref(true);
-
-// 时间线行数据(由接口节气生成)
-const timelineRows = reactive([]);
-
-// 目标定位日期(当前生育期参考点)
-const targetDate = new Date("2025-04-04T00:00:00");
-// 每行“当前生育期”标记的位置样式(按行索引)
-const phenologyPositions = ref({});
-
-// 生育期条(按行分组)
-const phenologyBarsByRow = ref([]);
-// 每一行可视区域的实际像素宽度(用于将最小像素宽度换算为百分比)
-const rowWidths = ref([]);
-// 节气 id 到对象的索引,便于通过 id 查找节气日期
-let solarTermIdToTerm = {};
-// 接口返回的生育期数据
-const phenologyList = ref([]);
-
-// 安全日期解析(兼容 'YYYY-MM-DD HH:mm:ss' / 'YYYY/MM/DD HH:mm:ss')
-const parseDate = (val) => {
-    if (!val) return null;
-    if (val instanceof Date) return isNaN(val.getTime()) ? null : val;
-    if (typeof val === "number") return new Date(val);
-    if (typeof val === "string") {
-        // 统一到可被 Safari 解析的格式
-        const s = val.replace(/-/g, "/").replace("T", " ");
-        const d = new Date(s);
-        return isNaN(d.getTime()) ? null : d;
-    }
-    return null;
-};
-
-onMounted(() => {
-    getFarmWorkPlan();
-    window.addEventListener("resize", handleResize, { passive: true });
-});
-onBeforeUnmount(() => {
-    window.removeEventListener("resize", handleResize);
-});
-
-const handleResize = () => {
-    // 重新测量并基于最新宽度重算条目
-    nextTick(() => {
-        measureRowWidths();
-        // 需要基于最新数据重算
-        if (phenologyList.value && phenologyList.value.length && cachedValidSolarTerms.value) {
-            groupPhenologyBarsByRow(phenologyList.value, cachedValidSolarTerms.value);
-        }
-    });
-};
-
-// 缓存已过滤/排序后的节气用于重复计算
-const cachedValidSolarTerms = ref(null);
-
-const getFarmWorkPlan = () => {
-    const paramFarmId = Number(route.query.farmId) || undefined;
-    VE_API.monitor
-        .farmWorkPlan({ farmId: paramFarmId ?? 92844 }) // 优先使用路由传入的 farmId
-        .then(({ data, code }) => {
-            if (code === 0) {
-                const solarTermsList = data.solarTermsList;
-                // 仅保留 type === 1 的节气,按需要的顺序(示例:反转)
-                // 取 type===1 的节气,并按日期降序排序(晚到早)
-                const validSolarTerms = Array.isArray(solarTermsList)
-                    ? solarTermsList
-                          .filter((t) => t && t.type === 1 && t.createDate)
-                          .sort((a, b) => {
-                              const da = parseDate(a.createDate)?.getTime() ?? 0;
-                              const db = parseDate(b.createDate)?.getTime() ?? 0;
-                              return db - da;
-                          })
-                    : [];
-                cachedValidSolarTerms.value = validSolarTerms;
-                generateTimelineData(validSolarTerms);
-                computeCurrentPhenologyPositions(validSolarTerms, targetDate);
-                // 保存生育期数据并生成各行生育期条
-                phenologyList.value = Array.isArray(data.phenologyList) ? data.phenologyList : [];
-                // 生成 id->term 的索引
-                solarTermIdToTerm = {};
-                validSolarTerms.forEach((t) => {
-                    if (t && (t.id || t.solarTermsId)) solarTermIdToTerm[t.id ?? t.solarTermsId] = t;
-                });
-                // 先等待 DOM 渲染完成后测量每行宽度,再据此计算最小可显示宽度
-                nextTick(() => {
-                    measureRowWidths();
-                    groupPhenologyBarsByRow(phenologyList.value, validSolarTerms);
-                });
-            }
-        })
-        .catch((error) => {
-            console.error("获取农事规划数据失败:", error);
-        });
-};
-
-// 测量每一行生育期容器的实际宽度
-const measureRowWidths = () => {
-    const rows = document.querySelectorAll(".cycle-timeline .cycle-row");
-    const widths = [];
-    rows.forEach((rowEl, idx) => {
-        const wrap = rowEl.querySelector(".cycle-phenology-wrap");
-        widths[idx] = wrap ? wrap.offsetWidth : 0;
-    });
-    rowWidths.value = widths;
-};
-
-// 生成时间轴数据
-const generateTimelineData = (solarTerms) => {
-    // 清空
-    timelineRows.splice(0, timelineRows.length);
-
-    // 无数据则给一行示例
-    if (!solarTerms || solarTerms.length === 0) {
-        timelineRows.push({
-            items: [
-                { type: "task", status: "default", taskName: "梢期", taskDesc: "杀虫" },
-                { type: "term", name: "节气" },
-                { type: "task", status: "default", taskName: "梢期", taskDesc: "杀虫" },
-                { type: "term", name: "节气" },
-                { type: "task", status: "default", taskName: "梢期", taskDesc: "杀虫" },
-                { type: "term", name: "节气" },
-            ],
-        });
-        return;
-    }
-
-    const itemsPerRow = 6; // 任务/节气交替
-    const termsPerRow = 3; // 每行3个节气
-    const totalRows = Math.ceil(solarTerms.length / termsPerRow);
-
-    for (let rowIndex = 0; rowIndex < totalRows; rowIndex++) {
-        const rowItems = [];
-        const startTermIndex = rowIndex * termsPerRow;
-
-        for (let i = 0; i < itemsPerRow; i++) {
-            if (i % 2 === 0) {
-                // 任务位
-                const taskData = getTaskDataForIndex(Math.floor(i / 2));
-                rowItems.push({
-                    type: "task",
-                    status: taskData.status,
-                    taskName: taskData.taskName,
-                    taskDesc: taskData.taskDesc,
-                    icon: taskData.icon,
-                });
-            } else {
-                // 节气位
-                const termIndex = startTermIndex + Math.floor(i / 2);
-                if (termIndex < solarTerms.length) {
-                    const term = solarTerms[termIndex] || {};
-                    rowItems.push({
-                        type: "term",
-                        status: "default",
-                        name: term.name || term.solarTermsName || term.termName || "节气",
-                        id: term.id,
-                        createDate: term.createDate,
-                    });
-                } else {
-                    // 不足时补任务
-                    rowItems.push({
-                        type: "task",
-                        status: "default",
-                        taskName: "梢期",
-                        taskDesc: "杀虫",
-                    });
-                }
-            }
-        }
-
-        timelineRows.push({ items: rowItems });
-    }
-};
-
-// 任务占位数据(可按需接后端)
-const getTaskDataForIndex = (index) => {
-    const defaultTasks = [
-        { status: "default", taskName: "梢期", taskDesc: "杀虫" },
-        { status: "active", taskName: "梢期", taskDesc: "营养" },
-        { status: "complete", taskName: "梢期", taskDesc: "修剪", icon: { type: "complete" } },
-        { status: "warning", taskName: "梢期", taskDesc: "施肥", icon: { type: "warning" } },
-        { status: "normal", taskName: "梢期", taskDesc: "灌溉", icon: { type: "normal" } },
-    ];
-    return defaultTasks[index % defaultTasks.length];
-};
-
-// 计算“当前生育期”在各行的定位(只在包含目标日期的那一行显示)
-const computeCurrentPhenologyPositions = (solarTerms, date) => {
-    phenologyPositions.value = {};
-    if (!Array.isArray(solarTerms) || solarTerms.length === 0 || !(date instanceof Date)) return;
-
-    const termsPerRow = 3;
-    const totalRows = Math.ceil(solarTerms.length / termsPerRow);
-
-    // 1) 找到最接近目标日期的节气(按时间升序)
-    const termsAsc = solarTerms
-        .filter((t) => t && t.createDate)
-        .slice()
-        .sort((a, b) => (parseDate(a.createDate)?.getTime() ?? 0) - (parseDate(b.createDate)?.getTime() ?? 0));
-    if (termsAsc.length === 0) return;
-
-    const targetMs = date.getTime();
-    let nearest = termsAsc[0];
-    let bestDiff = Math.abs((parseDate(nearest.createDate)?.getTime() ?? 0) - targetMs);
-    for (let i = 1; i < termsAsc.length; i++) {
-        const ms = parseDate(termsAsc[i].createDate)?.getTime() ?? 0;
-        const diff = Math.abs(ms - targetMs);
-        if (diff < bestDiff) {
-            bestDiff = diff;
-            nearest = termsAsc[i];
-        }
-    }
-
-    // 2) 将该节气映射回当前(降序)数组中的索引与行
-    const nearestIdxDesc = solarTerms.findIndex((t) => t && nearest && t.id === nearest.id);
-    const rowIndex = Math.max(0, Math.floor(nearestIdxDesc / termsPerRow));
-
-    const startIdx = rowIndex * termsPerRow;
-    const endIdx = Math.min(startIdx + termsPerRow - 1, solarTerms.length - 1);
-    if (startIdx > endIdx) return;
-
-    const rowTerms = solarTerms.slice(startIdx, endIdx + 1);
-    // 视觉顺序用于方向(偶数行正向,奇数行反向),但时间范围应取该行真实最早/最晚
-    const rowDates = rowTerms
-        .map((t) => parseDate(t?.createDate))
-        .filter((d) => d && !isNaN(d.getTime()))
-        .map((d) => d.getTime());
-    if (rowDates.length === 0) return;
-    const minMs = Math.min(...rowDates);
-    const maxMs = Math.max(...rowDates);
-    const rowStart = new Date(minMs);
-    const rowEnd = new Date(maxMs);
-
-    // 3) 若目标日期不在该行范围内,则就近夹到边界(避免跨行导致丢失)
-    let anchorMs = targetMs;
-    if (anchorMs < minMs) anchorMs = minMs;
-    if (anchorMs > maxMs) anchorMs = maxMs;
-
-    // 4) 计算在该行范围内的比例
-    const total = Math.max(1, maxMs - minMs);
-    const ratio = Math.max(0, Math.min(1, (anchorMs - minMs) / total));
-    const percent = `${(ratio * 100).toFixed(2)}%`;
-
-    // 5) 偶数行用 left,奇数行用 right,与 Z 字方向一致
-    if (rowIndex % 2 === 1) {
-        phenologyPositions.value[rowIndex] = { right: percent };
-    } else {
-        phenologyPositions.value[rowIndex] = { left: percent };
-    }
-};
-// moved above with other refs
-
-// 将生育期条按行计算定位与宽度
-const groupPhenologyBarsByRow = (phenologyList, solarTerms) => {
-    phenologyBarsByRow.value = [];
-    if (
-        !Array.isArray(phenologyList) ||
-        phenologyList.length === 0 ||
-        !Array.isArray(solarTerms) ||
-        solarTerms.length === 0
-    ) {
-        return;
-    }
-
-    const termsPerRow = 3;
-    const totalRows = Math.ceil(solarTerms.length / termsPerRow);
-
-    // 行范围:使用该行包含的节气最早/最晚时间(按真实时间线性映射)
-    const rowRanges = [];
-    for (let rowIndex = 0; rowIndex < totalRows; rowIndex++) {
-        const startIdx = rowIndex * termsPerRow;
-        const endIdx = Math.min(startIdx + termsPerRow - 1, solarTerms.length - 1);
-        const rowTerms = solarTerms.slice(startIdx, endIdx + 1);
-        const rowDates = rowTerms
-            .map((t) => parseDate(t?.createDate))
-            .filter((d) => d && !isNaN(d.getTime()))
-            .map((d) => d.getTime());
-        if (rowDates.length === 0) continue;
-        const minMs = Math.min(...rowDates);
-        const maxMs = Math.max(...rowDates);
-        const rowStart = new Date(minMs);
-        const rowEnd = new Date(maxMs);
-        const totalMs = Math.max(1, rowEnd.getTime() - rowStart.getTime());
-        rowRanges.push({ rowIndex, rowStart, rowEnd, totalMs });
-        phenologyBarsByRow.value[rowIndex] = [];
-    }
-
-    // 中点归属法:每条生育期归属到中点所在的行;在行内按 Z 字方向计算 left/right 与 width
-    phenologyList.forEach((p, pIndex) => {
-        const list = Array.isArray(p?.reproductiveList) ? p.reproductiveList : [];
-        const baseColorClass = pIndex % 2 === 0 ? "blue" : "orange";
-        list.forEach((r) => {
-            // 优先使用节气 id 对应的节气日期
-            let sTermDate = null;
-            let eTermDate = null;
-            if (r?.startSolarTermId && solarTermIdToTerm[r.startSolarTermId]?.createDate) {
-                sTermDate = parseDate(solarTermIdToTerm[r.startSolarTermId].createDate);
-            }
-            if (r?.endSolarTermId && solarTermIdToTerm[r.endSolarTermId]?.createDate) {
-                eTermDate = parseDate(solarTermIdToTerm[r.endSolarTermId].createDate);
-            }
-
-            const s = sTermDate || parseDate(r?.startDate);
-            const e = eTermDate || parseDate(r?.endDate);
-            if (!s || !e) return;
-            const start = new Date(Math.min(s.getTime(), e.getTime()));
-            const end = new Date(Math.max(s.getTime(), e.getTime()));
-            if (end < start) return;
-            const mid = new Date(start.getTime() + (end.getTime() - start.getTime()) / 2);
-
-            // 找到中点所在行;若不在任何行,则归最近行
-            let target = rowRanges.find(({ rowStart, rowEnd }) => mid >= rowStart && mid <= rowEnd);
-            if (!target) {
-                target = rowRanges.reduce((best, curr) => {
-                    const dist =
-                        mid < curr.rowStart
-                            ? curr.rowStart.getTime() - mid.getTime()
-                            : mid.getTime() - curr.rowEnd.getTime();
-                    if (!best || dist < best.dist) return { dist, curr };
-                    return best;
-                }, null)?.curr;
-            }
-            if (!target) return;
-
-            // 位置:基于真实的 startDate(不截断),确保相邻条的间距 = (后一个startDate - 前一个endDate) 的时间差映射
-            const startRatio = (start.getTime() - target.rowStart.getTime()) / target.totalMs;
-
-            // 宽度:基于真实的 endDate - startDate 的时间差
-            const actualDuration = end.getTime() - start.getTime();
-            const widthRatio = actualDuration / target.totalMs;
-
-            // 限制到行范围内
-            const leftRatio = Math.max(0, Math.min(1, startRatio));
-            const rightRatio = Math.max(0, Math.min(1, (end.getTime() - target.rowStart.getTime()) / target.totalMs));
-            let clampedWidthRatio = Math.max(0.001, Math.min(widthRatio, rightRatio - leftRatio));
-
-            // 强制最小显示宽度:若换算到像素后小于 CSS 中的 min-width:22px,则使用最小可见宽度
-            const MIN_LABEL_PX = 22; // 与样式 .cycle-label 的最小宽度保持一致
-            const rowWidthPx = rowWidths.value?.[target.rowIndex] || 0;
-            let leftPercent = leftRatio * 100;
-            let widthPercent = clampedWidthRatio * 100;
-            if (rowWidthPx > 0) {
-                const minPercent = (MIN_LABEL_PX / rowWidthPx) * 100;
-                if (widthPercent < minPercent) {
-                    widthPercent = minPercent;
-                }
-                // 若越界则左移以保证完全可见
-                if (leftPercent + widthPercent > 100) {
-                    leftPercent = Math.max(0, 100 - widthPercent);
-                }
-                // 回填为比例供后续使用
-                clampedWidthRatio = widthPercent / 100;
-            } else {
-                // 无法测量时,保底给一个不至于 0 的最小显示比例(以 360px 近似,22px/360≈6.1%)
-                if (widthPercent < 6.2) {
-                    widthPercent = 6.2;
-                    if (leftPercent + widthPercent > 100) leftPercent = Math.max(0, 100 - widthPercent);
-                    clampedWidthRatio = widthPercent / 100;
-                }
-            }
-
-            const isFuture = start.getTime() > Date.now();
-            const colorToUse = isFuture ? "" : baseColorClass;
-            // 组装农事安排:按 reproductiveId 归属到当前生育期
-            const arrangeList = Array.isArray(r.farmWorkArrangeList)
-                ? r.farmWorkArrangeList.filter((fw) => !fw.reproductiveId || fw.reproductiveId === r.id)
-                : [];
-            const arrangeItems = arrangeList.map((fw) => {
-                let status = "default";
-                const t = fw.farmWorkType;
-                if (t == null || t === 0) {
-                    status = "default";
-                } else if (t >= 1 && t <= 4) {
-                    status = "normal";
-                } else if (t === 5) {
-                    status = "complete";
-                } else if (t === 6) {
-                    status = "warning";
-                }
-                return {
-                    id: fw.id,
-                    name: fw.farmWorkName,
-                    status,
-                };
-            });
-
-            // // 附加两条测试数据:已完成、已过期
-            // arrangeItems.push(
-            //     { id: `${r.id}-test-complete`, name: "测试完成", status: "complete" },
-            //     { id: `${r.id}-test-warning`, name: "测试过期", status: "warning" }
-            // );
-
-            phenologyBarsByRow.value[target.rowIndex].push({
-                id: r.id || `${p.id || "p"}-${start.getTime()}-${end.getTime()}`,
-                name: r.name && r.name.trim() ? r.name.trim() : r.phenologyName || "生育期",
-                left: `${leftPercent.toFixed(4)}%`,
-                width: `${(clampedWidthRatio * 100).toFixed(4)}%`,
-                startTime: start.getTime(), // 用于排序,确保相邻条的顺序正确
-                color: colorToUse,
-                arranges: arrangeItems,
-            });
-        });
-    });
-
-    // 每行内部按 startTime 排序,确保相邻条的间距正确反映时间差
-    phenologyBarsByRow.value.forEach((rowBars) => {
-        rowBars.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
-    });
-};
-
-// 获取指定行的生育期条
-const getPhenologyBarsForRow = (rowIndex) => {
-    return phenologyBarsByRow.value[rowIndex] || [];
-};
-
-// 视觉奇偶:自下而上计算奇偶(与 UI Z 字一致)
-const isOddVisualRow = (rowIndex) => {
-    const total = timelineRows.length;
-    if (total <= 0) return rowIndex % 2 === 1;
-    const visualIndex = total - 1 - rowIndex;
-    return visualIndex % 2 === 1;
-};
-
-// 新增农事
-const addNewTask = () => {
-    router.push({
-        path: "/modify_work",
-        query: { data: JSON.stringify(["生长异常"]), gardenId: 766, isAdd: true },
-    });
-};
-
-const manageTask = () => {
-    router.push({
-        path: "/agri_services_manage",
-        query: {
-            type: "manage",
-        },
-    });
-};
-
-const detailDialogRef = ref(null);
-
-const handleRowClick = (item) => {
-    if (item.status === "complete") {
-        router.push({
-            path: "/review_work",
-            query: {
-                miniJson: JSON.stringify({ id: item.id,goBack: true })
-            },
-        });
-    } else if (item.type !== "term" && item.status === "default") {
-        detailDialogRef.value.showDialog();
-    } else if (item.status === "warning" || item.status === "normal") {
-        router.push({
-            path: "/completed_work",
-            query: {
-                miniJson: JSON.stringify({ id: item.id })
-            },
-        });
-        // router.push({
-        //     path: "/services_agri",
-        //     query: {
-        //         id: item.id,
-        //         status: item.status,
-        //     },
-        // });
-    }
-};
-
-// 行连接器颜色:若后续生育期未开始则灰色,否则保持其颜色(蓝/橙)
-const getConnectorColorClass = (rowIndex) => {
-    const nextIndex = rowIndex + 1;
-    const bars = getPhenologyBarsForRow(nextIndex);
-    if (!bars || bars.length === 0) return "";
-
-    const nextIsOddIndex = nextIndex % 2 === 1; // 奇数行为左侧连接器
-
-    const parsePercent = (val) => {
-        if (typeof val !== "string") return 0;
-        const n = parseFloat(val.replace("%", ""));
-        return isNaN(n) ? 0 : n;
-    };
-
-    let target = bars[0];
-    if (nextIsOddIndex) {
-        // 左侧:选最靠左的条
-        target = bars.reduce((best, cur) => (parsePercent(cur.left) < parsePercent(best.left) ? cur : best), bars[0]);
-    } else {
-        // 右侧:选最靠右的条(left + width 最大)
-        const score = (b) => parsePercent(b.left) + parsePercent(b.width);
-        target = bars.reduce((best, cur) => (score(cur) > score(best) ? cur : best), bars[0]);
-    }
-
-    // 未来(未开始)时,color 为空串;过去/当前一律显示蓝色
-    const hasStarted = !!target?.color;
-    return hasStarted ? "" : "connector-gray";
-};
-
-// 行连接器是否为灰色(用于切换箭头图片)
-const isConnectorGray = (rowIndex) => getConnectorColorClass(rowIndex) === "connector-gray";
-</script>
-
-<style scoped lang="scss">
-.plan-page {
-    width: 100%;
-    height: 100vh;
-    background: #fff;
-    .plan-content {
-        .filter-wrap {
-            background: #fff;
-            padding: 13px 12px;
-            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-            border-radius: 0 0 20px 20px;
-            .status-filter {
-                background: #fff;
-                padding: 3px 17px;
-                display: flex;
-                align-items: center;
-                gap: 16px;
-                font-size: 12px;
-
-                .status-item {
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    gap: 6px;
-                    flex: 1;
-                    &.gray {
-                        color: #c4c6c9;
-                        .status-dot {
-                            background-color: #c4c6c9;
-                        }
-                    }
-
-                    &.blue {
-                        color: #2199f8;
-                        .status-dot {
-                            background-color: #2199f8;
-                        }
-                    }
-
-                    &.green {
-                        color: #1ca900;
-                        .status-dot {
-                            background-color: #1ca900;
-                        }
-                    }
-
-                    &.orange {
-                        color: #ff953d;
-                        .status-dot {
-                            background-color: #ff953d;
-                        }
-                    }
-                    .status-dot {
-                        width: 6px;
-                        height: 6px;
-                        border-radius: 50%;
-                    }
-                }
-            }
-
-            .season-tabs {
-                display: flex;
-                gap: 8px;
-                margin-bottom: 12px;
-                .season-tab {
-                    flex: 1;
-                    padding: 7px;
-                    text-align: center;
-                    background: #f3f3f3;
-                    color: #898a8a;
-                    border-radius: 3px;
-                    border: 1px solid transparent;
-                    font-size: 12px;
-                }
-                .season-tab.active {
-                    background: #ffffff;
-                    color: #2199f8;
-                    border-color: #2199f8;
-                }
-            }
-        }
-
-        // 循环时间线样式
-        .cycle-timeline-container {
-            padding: 35px 15px 25px;
-            height: calc(100vh - 135px - 69px - 60px);
-            overflow-y: auto;
-            overflow-x: hidden;
-            .cycle-timeline {
-                position: relative;
-                .cycle-row {
-                    position: relative;
-                    display: flex;
-                    justify-content: space-between;
-                    align-items: center;
-                    margin-bottom: 60px;
-                    padding-right: 30px;
-                    &.odd-index {
-                        padding: 0;
-                        padding-left: 30px;
-                        flex-direction: row-reverse;
-                        .cycle-phenology-wrap {
-                            left: 6px;
-                            width: calc(100% - 13px);
-                        }
-                    }
-
-                    &:last-child {
-                        margin-bottom: 0;
-                        .cycle-phenology-wrap {
-                            left: 20px;
-                            width: calc(100% - 10px);
-                        }
-                    }
-
-                    // 水平时间线
-                    &::before {
-                        content: "";
-                        position: absolute;
-                        top: 0;
-                        left: 6px;
-                        right: 6px;
-                        height: 5px;
-                        border-left: 2px solid #fff;
-                        border-right: 2px solid #fff;
-                        background: #e8e8e8;
-                        transform: translateY(-50%);
-                        z-index: 1;
-                    }
-
-                    .cycle-item {
-                        position: relative;
-                        z-index: 2;
-                        top: 12px;
-
-                        &.term-item {
-                            display: flex;
-                            flex-direction: column;
-                            align-items: center;
-                            top: -11px;
-
-                            .cycle-term-dot {
-                                width: 6px;
-                                height: 6px;
-                                background: #c7c7c7;
-                                border-radius: 50%;
-                                margin-bottom: 4px;
-                            }
-
-                            .cycle-term-label {
-                                font-size: 11px;
-                                color: #c7c7c7;
-                                margin-top: 16px;
-                            }
-
-                            &.active {
-                                .cycle-term-dot {
-                                    background: #858383;
-                                }
-                                .cycle-term-label {
-                                    color: #858383;
-                                }
-                            }
-                        }
-                    }
-
-                    .cycle-phenology-wrap {
-                        position: absolute;
-                        top: -23px;
-                        left: 6px;
-                        width: calc(100% - 10px);
-                        z-index: 3;
-                        height: 100px;
-                        overflow: hidden;
-                        .cycle-label {
-                            position: absolute;
-                            color: #4e4e4e;
-                            font-size: 12px;
-                            min-width: 24px;
-                            height: 20px;
-                            line-height: 20px;
-                            text-align: center;
-                            background: rgba(180, 182, 183, 0.1);
-                            border-bottom: 6px solid #e8e8e8;
-                        }
-                        .cycle-label + .cycle-label {
-                            border-right: 1px solid #fff;
-                        }
-                        .cycle-label.blue {
-                            color: #2199f8;
-                            background: rgba(33, 153, 248, 0.1);
-                            border-bottom-color: #2199f8;
-                        }
-                        .cycle-label.orange {
-                            color: #ff953d;
-                            background: #fff2e7;
-                            border-bottom-color: #ff953d;
-                        }
-                        .arranges {
-                            display: flex;
-                            gap: 8px;
-                            padding-top: 26px;
-                            justify-content: center;
-                            flex-wrap: nowrap;
-                            // 使用与任务框一致的视觉风格
-                            .cycle-task-box {
-                                border: 1px solid rgba(199, 199, 199, 0.5);
-                                border-radius: 2px;
-                                width: 36px;
-                                height: 36px;
-                                min-width: 36px;
-                                line-height: 15px;
-                                font-size: 12px;
-                                box-sizing: border-box;
-                                padding: 2px 0;
-                                text-align: center;
-                                position: relative;
-                                color: #c7c7c7;
-                                .status-icon {
-                                    position: absolute;
-                                    bottom: -10px;
-                                    right: -10px;
-                                }
-                            }
-
-                            .cycle-task-connector {
-                                position: absolute;
-                                top: -4px;
-                                left: 50%;
-                                transform: translateX(-50%);
-                                width: 0;
-                                height: 0;
-                                border-left: 4px solid transparent;
-                                border-right: 4px solid transparent;
-                                border-bottom: 4px solid #dde1e7;
-                            }
-
-                            .cycle-task-box.warning {
-                                border-color: #ff953d;
-                            }
-                            .cycle-task-box.warning .cycle-task-text {
-                                color: #ff953d;
-                            }
-                            .cycle-task-box.warning + .cycle-task-connector,
-                            .cycle-task-box.warning .cycle-task-connector {
-                                border-bottom-color: #ff953d;
-                            }
-
-                            .cycle-task-box.complete {
-                                border-color: #1ca900;
-                            }
-                            .cycle-task-box.complete .cycle-task-text {
-                                color: #1ca900;
-                            }
-                            .cycle-task-box.complete + .cycle-task-connector,
-                            .cycle-task-box.complete .cycle-task-connector {
-                                border-bottom-color: #1ca900;
-                            }
-
-                            .cycle-task-box.normal {
-                                border-color: #2199f8;
-                            }
-                            .cycle-task-box.normal .cycle-task-text {
-                                color: #2199f8;
-                            }
-                            .cycle-task-box.normal + .cycle-task-connector,
-                            .cycle-task-box.normal .cycle-task-connector {
-                                border-bottom-color: #2199f8;
-                            }
-                        }
-                    }
-
-                    .cycle-connector {
-                        position: absolute;
-                        right: 0;
-                        top: 45.5px;
-                        transform: translateY(-50%);
-                        width: 2px;
-                        height: 87px;
-                        border: 5px solid #9dcaf7;
-                        border-left: none;
-                        background: transparent;
-                        img{
-                            width: 13px;
-                            height: 13px;
-                            position: absolute;
-                            top: 50%;
-                            transform: translateY(-50%);
-                            left: -8px;
-                            z-index: 1;
-                        }
-
-                        &.top-connector {
-                            border-top-right-radius: 5px;
-                            border-bottom-right-radius: 5px;
-                            img{
-                                left: -2px;
-                            }
-                        }
-
-                        &.middle-connector {
-                            border-top-left-radius: 5px;
-                            border-bottom-left-radius: 5px;
-                            left: 0;
-                            border-right: none;
-                            border-left: 5px solid #9dcaf7;
-                        }
-
-                        // 动态颜色
-                        &.connector-gray {
-                            border-color: #c4c6c9;
-                        }
-                        &.connector-gray.middle-connector {
-                            border-left-color: #c4c6c9;
-                        }
-                    }
-                }
-            }
-        }
-
-        // 控制区域样式
-        .control-section {
-            position: fixed;
-            width: 100%;
-            left: 0;
-            box-sizing: border-box;
-            bottom: 0px;
-            background: #fff;
-            padding: 16px 12px;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            border-top: 1px solid #f0f0f0;
-
-            .toggle-group {
-                display: flex;
-                align-items: center;
-                gap: 8px;
-
-                .toggle-label {
-                    font-size: 13px;
-                    color: #141414;
-                }
-            }
-
-            .add-button-group {
-                display: flex;
-                align-items: center;
-                gap: 8px;
-                .button {
-                    color: #2199f8;
-                    border-radius: 25px;
-                    padding: 9px 15px;
-                    border: 1px solid #2199f8;
-                }
-                .add-button {
-                    background: linear-gradient(120deg, #76c3ff 0%, #2199f8 100%);
-                    color: white;
-                    border: 1px solid transparent;
-                }
-            }
-        }
-    }
-}
-</style>

+ 0 - 779
src/views/old_mini/monitor/subPages/plan.vue

@@ -1,779 +0,0 @@
-<template>
-    <div class="plan-page">
-        <custom-header
-            :name="headerTitle"
-            isGoBack
-            @goback="goback"
-            :isClose="route.query.headerTitle ? true : false"
-        ></custom-header>
-        <div class="plan-content">
-            <div class="plan-content-header" v-if="pageType === 'plant'">
-                <el-select
-                    class="select-item"
-                    v-model="specieValue"
-                    placeholder="选择品类"
-                    @change="() => getListMySchemes('left')"
-                >
-                    <el-option
-                        v-for="item in options"
-                        :key="item.id"
-                        :label="item.name"
-                        :value="item.defaultContainerId"
-                    />
-                </el-select>
-                <tab-list
-                    class="tabs-list"
-                    type="light"
-                    v-model="active"
-                    :tabs="tabs"
-                    :scrollType="scrollType"
-                    @change="handleTabChange"
-                />
-            </div>
-            <div class="tip-box">
-                <Highlight
-                    :keywords="['关注农事/托管农事', '取消关注']"
-                    source-string="提示:关注农事/托管农事 会触发农情互动,并且为您推送农事,取消关注 则不会为您推送任何与该农事相关的内容"
-                />
-            </div>
-            <div
-                class="timeline-wrap"
-                :class="{
-                    'timeline-container-plant-wrap': pageType == 'plant',
-                    'timeline-container-no-permission-wrap': !hasPlanPermission,
-                    'no-default-plan-wrap':
-                        active !== tabs[0]?.id && pageType == 'plant' && tabs[currentTabIndex]?.enabled == 0,
-                }"
-            >
-                <farm-work-plan-timeline
-                    :pageType="pageType"
-                    :farmId="route.query.farmId"
-                    :containerId="containerIdData"
-                    @row-click="handleRowClick"
-                    :disableClick="!hasPlanPermission || active === tabs[0]?.id"
-                    :isStandard="active === tabs[0]?.id"
-                    :schemeId="route.query.schemeId || active"
-                    ref="farmWorkPlanTimelineRef"
-                />
-            </div>
-        </div>
-        <div
-            class="custom-bottom-fixed-btns"
-            :class="{ center: active === tabs[0]?.id && pageType == 'plant' }"
-            v-has-permission="'农事规划'"
-        >
-            <div class="bottom-btn-group-wrap">
-                <div
-                    class="bottom-btn-group"
-                    :class="{ 'justify-center': active === tabs[0]?.id && pageType == 'plant' }"
-                >
-                    <div
-                        class="bottom-btn secondary-btn"
-                        @click="handlePhenologySetting"
-                        v-show="active !== tabs[0]?.id"
-                    >
-                        物候期设置
-                    </div>
-                    <div class="bottom-btn secondary-btn" v-if="pageType === 'plant'" @click="openCopyPlanPopup">
-                        {{ active === tabs[0]?.id ? "复制方案" : "方案设置" }}
-                    </div>
-                </div>
-                <div class="bottom-btn primary-btn" @click="addNewTask" v-show="active !== tabs[0]?.id">新增农事</div>
-            </div>
-            <template v-if="active !== tabs[0]?.id && pageType == 'plant' && tabs[currentTabIndex]?.enabled == 0">
-                <div class="bottom-btn-divider"></div>
-                <div class="bottom-btn primary-btn submit-btn" @click="handleSubmitPlan">提交方案</div>
-            </template>
-        </div>
-    </div>
-    <!-- 农事信息弹窗 -->
-    <detail-dialog ref="detailDialogRef" @triggerFarmWork="triggerFarmWork"></detail-dialog>
-    <!-- 复制方案弹窗 -->
-    <Popup v-model:show="showCopyPlan" class="copy-plan-popup" round closeable :close-on-click-overlay="false">
-        <div class="copy-plan-content">
-            <div class="label">{{ active === tabs[0]?.id ? "复制为" : "方案名称" }}</div>
-            <el-input v-model="copyPlanName" size="large" placeholder="请输入方案名称" class="copy-plan-input" />
-        </div>
-        <div class="copy-plan-footer">
-            <div class="btn btn-cancel" @click="handleCancelCopyPlan">
-                {{ active === tabs[0]?.id ? "取消复制" : "删除方案" }}
-            </div>
-            <div class="btn btn-confirm" @click="handleConfirmCopyPlan">
-                {{ active === tabs[0]?.id ? "确定复制" : "确定设置" }}
-            </div>
-        </div>
-    </Popup>
-
-    <!-- 物候期设置弹窗 -->
-    <Popup
-        v-model:show="showPhenologySetting"
-        class="copy-plan-popup phenology-popup"
-        round
-        closeable
-        :close-on-click-overlay="false"
-    >
-        <div class="phenology-header">物候期时间设置</div>
-        <div class="phenology-list">
-            <div class="phenology-item" v-for="(item, index) in mergedReproductiveList" :key="item.id || index">
-                <div class="item-label">
-                    <span class="label-text">{{ item.name }}</span>
-                    <span>起始时间</span>
-                </div>
-                <div class="item-value">
-                    <el-date-picker
-                        style="width: 100%"
-                        size="large"
-                        value-format="YYYY-MM-DD"
-                        v-model="item.startDate"
-                        :clearable="false"
-                        :editable="false"
-                        type="date"
-                        placeholder="选择日期"
-                        @change="(date) => handleStartDateChange(date, index)"
-                    />
-                </div>
-            </div>
-            <div class="phenology-footer-tip">
-                <span>注:</span>
-                <span class="text">请从上往下按照时间顺序填写日期</span>
-            </div>
-        </div>
-        <div class="phenology-footer" @click="handleConfirmPhenologySetting">确认设置</div>
-    </Popup>
-
-    <tip-popup
-        v-model:show="showTipPopup"
-        type="warning"
-        text2="还未完善此方案不可用"
-        :highlightText="highlightText"
-        buttonText="我知道了"
-        @confirm="handleBtn"
-    />
-</template>
-
-<script setup>
-import { ref, onMounted, computed, watch } from "vue";
-import { Popup, Highlight } from "vant";
-import customHeader from "@/components/customHeader.vue";
-import tabList from "@/components/pageComponents/TabList.vue";
-import FarmWorkPlanTimeline from "@/components/pageComponents/FarmWorkPlanTimeline.vue";
-import { useRouter, useRoute } from "vue-router";
-import detailDialog from "@/components/detailDialog.vue";
-import eventBus from "@/api/eventBus";
-import tipPopup from "@/components/popup/tipPopup.vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-const router = useRouter();
-const route = useRoute();
-
-const showTipPopup = ref(false);
-const highlightText = ref("");
-const handleBtn = () => {
-    showTipPopup.value = false;
-    setTimeout(() => {
-        router.go(-1);
-    }, 10);
-};
-
-const goback = () => {
-    if (
-        tabs.value[currentTabIndex.value]?.enabled == 0 &&
-        pageType.value === "plant" &&
-        active.value !== tabs.value[0]?.id
-    ) {
-        highlightText.value = tabs.value[currentTabIndex.value]?.name;
-        showTipPopup.value = true;
-    } else {
-        router.go(-1);
-    }
-};
-
-const userInfoStr = localStorage.getItem("localUserInfo");
-const userInfo = userInfoStr ? JSON.parse(userInfoStr) : {};
-// 检查是否有"农事规划"权限
-const hasPlanPermission = computed(() => {
-    try {
-        const permissions = userInfo?.agriculturalPermissions || [];
-        return permissions.includes("农事规划");
-    } catch (error) {
-        console.error("解析用户信息失败:", error);
-        return false;
-    }
-});
-
-const pageType = ref("");
-const headerTitle = ref("");
-
-onMounted(() => {
-    pageType.value = route.query.pageType || "";
-    headerTitle.value = route.query.headerTitle || (pageType.value === "plant" ? "种植方案" : "农事规划");
-    if (!pageType.value) {
-        getFarmWorkPlanForPhenology();
-    } else {
-        getSpecieList();
-    }
-});
-
-// 获取品类列表
-const specieValue = ref(null);
-const options = ref([]);
-const getSpecieList = () => {
-    VE_API.farm.fetchSpecieList({ agriculturalId: userInfo?.agriculturalId }).then(({ data }) => {
-        if (data && data.length) {
-            options.value = data || [];
-            let schemeType = "left"; // 默认使用left
-            
-            if (sessionStorage.getItem("specieValue")) {
-                specieValue.value = sessionStorage.getItem("specieValue");
-                currentTabIndex.value = sessionStorage.getItem("currentTabIndex");
-                sessionStorage.removeItem("specieValue");
-                sessionStorage.removeItem("currentTabIndex");
-                
-                // 判断恢复的specieValue是否是最后一项
-                const currentIndex = data.findIndex(item => item.defaultContainerId === specieValue.value);
-                if (currentIndex === data.length - 1) {
-                    schemeType = "right";
-                }
-            } else {
-                specieValue.value = data[0]?.defaultContainerId;
-            }
-            getListMySchemes(schemeType);
-        }
-    });
-};
-
-// 获取方案列表
-const active = ref(null);
-const tabs = ref([]);
-// 控制标签滚动方向:'left' | 'right' | 'auto' | ''
-const scrollType = ref("auto");
-const containerIdData = ref(null);
-const getListMySchemes = (type = "auto") => {
-    VE_API.home.listMySchemes({ containerId: specieValue.value }).then(({ data }) => {
-        tabs.value = data || [];
-        containerIdData.value = tabs.value[0]?.containerId;
-        if (sessionStorage.getItem("active")) {
-            active.value = sessionStorage.getItem("active");
-            sessionStorage.removeItem("active");
-            currentTab.value = data[currentTabIndex.value];
-
-        } else {
-            if (type === "right") {
-                active.value = data[data.length - 1].id;
-            } else if (type === "left") {
-                active.value = data[0]?.id;
-            } else {
-                if(currentTab.value) {
-                    currentTab.value = data.filter((item) => item.id === currentTab.value?.id)?.[0];
-                } else {
-                    currentTab.value = data[0];
-                }
-                copyPlanName.value = currentTab.value.name;
-            }
-        }
-        scrollType.value = type;
-        getFarmWorkPlanForPhenology();
-    });
-};
-
-const currentTab = ref(null);
-const currentTabIndex = ref(0);
-const handleTabChange = (id, item, index) => {
-    active.value = id;
-    currentTab.value = item;
-    currentTabIndex.value = index;
-    getFarmWorkPlanForPhenology();
-};
-
-const mergedReproductiveList = ref([]);
-const containerSpaceTimeId = ref(null);
-const schemeId = ref(null);
-
-const getPhenologyList = async () => {
-    const params = {
-        containerSpaceTimeId: containerSpaceTimeId.value,
-        agriculturalId: userInfo?.agriculturalId,
-        farmId: route.query.farmId,
-    };
-    const res = await VE_API.monitor.listPhenology(params);
-    if (res.code === 0) {
-        // 将intervalDaysArr合并到mergedReproductiveList中
-        if (intervalDaysArr.value.length > 0 && res.data.length > 0) {
-            mergedReproductiveList.value = res.data.map((item, index) => {
-                return {
-                    ...item,
-                    intervalDays: intervalDaysArr.value[index],
-                };
-            });
-        }
-    }
-};
-
-const farmWorkIds = ref([]);
-const intervalDaysArr = ref([]);
-// 获取农事规划数据以获取 containerSpaceTimeId
-const getFarmWorkPlanForPhenology = async () => {
-    try {
-        const { data, code } = await VE_API.monitor.farmWorkPlan({
-            containerId: specieValue.value,
-            farmId: route.query.farmId,
-            schemeId: active.value,
-        });
-        if (code === 0 && data?.phenologyList?.[0]?.containerSpaceTimeId) {
-            containerSpaceTimeId.value = data.phenologyList[0].containerSpaceTimeId;
-            schemeId.value = data.schemeId;
-
-            // 收集所有farmWorkId
-            farmWorkIds.value = [];
-            intervalDaysArr.value = [];
-            data.phenologyList.forEach((phenology) => {
-                intervalDaysArr.value.push(phenology.intervalDays);
-                if (Array.isArray(phenology.reproductiveList)) {
-                    phenology.reproductiveList.forEach((reproductive) => {
-                        if (Array.isArray(reproductive.farmWorkArrangeList)) {
-                            reproductive.farmWorkArrangeList.forEach((farmWork) => {
-                                if (farmWork.farmWorkId && farmWork.isFollow !== 0) {
-                                    farmWorkIds.value.push(farmWork.farmWorkId);
-                                }
-                            });
-                        }
-                    });
-                }
-            });
-        }
-    } catch (error) {
-        console.error("获取农事规划数据失败:", error);
-    }
-};
-
-// 复制方案弹窗相关
-const showCopyPlan = ref(false);
-const showPhenologySetting = ref(false);
-const copyPlanName = ref("");
-const openCopyPlanPopup = async () => {
-    copyPlanName.value = "";
-    showCopyPlan.value = true;
-    if (active.value !== tabs.value[0]?.id) {
-        copyPlanName.value = currentTab.value.name;
-    }
-};
-
-// 物候期设置弹窗
-const handlePhenologySetting = async () => {
-    await getPhenologyList();
-    showPhenologySetting.value = true;
-};
-
-/**
- * 处理物候期开始时间变化
- * 当修改某个物候期的开始时间时,自动更新后续所有物候期的开始时间
- */
-const handleStartDateChange = (date, currentIndex) => {
-    if (!date || !mergedReproductiveList.value || mergedReproductiveList.value.length === 0) {
-        return;
-    }
-    
-    // 从当前修改的物候期开始,更新后续所有物候期的开始时间
-    for (let i = currentIndex; i < mergedReproductiveList.value.length - 1; i++) {
-        const currentItem = mergedReproductiveList.value[i];
-        const nextItem = mergedReproductiveList.value[i + 1];
-        
-        // 获取当前物候期的间隔天数
-        const intervalDays = currentItem.intervalDays || 0;
-        
-        if (intervalDays > 0 && currentItem.startDate) {
-            // 将日期字符串转换为时间戳(毫秒)
-            const currentStartDateTimestamp = new Date(currentItem.startDate).getTime();
-            
-            // 在时间戳基础上加上间隔天数(转换为毫秒:天数 * 24小时 * 60分钟 * 60秒 * 1000毫秒)
-            const nextStartDateTimestamp = currentStartDateTimestamp + (intervalDays * 24 * 60 * 60 * 1000);
-            
-            // 将时间戳转换回日期对象,然后格式化为 YYYY-MM-DD 格式
-            const nextStartDate = new Date(nextStartDateTimestamp);
-            const year = nextStartDate.getFullYear();
-            const month = String(nextStartDate.getMonth() + 1).padStart(2, '0');
-            const day = String(nextStartDate.getDate()).padStart(2, '0');
-            const nextStartDateStr = `${year}-${month}-${day}`;
-            
-            // 更新下一个物候期的开始时间
-            nextItem.startDate = nextStartDateStr;
-        }
-    }
-};
-
-/**
- * 确认物候期设置
- */
-const farmWorkPlanTimelineRef = ref(null);
-const handleConfirmPhenologySetting = async () => {
-    const params = {
-        farmId: route.query.farmId,
-        agriculturalId: userInfo?.agriculturalId,
-        items: mergedReproductiveList.value.map((item) => ({
-            phenologyId: item.id,
-            startDate: item.startDate,
-        })),
-    };
-    const res = await VE_API.monitor.batchSaveFarmPhenologyTime(params);
-    if (res.code === 0) {
-        ElMessage.success("设置成功");
-        showPhenologySetting.value = false;
-        getFarmWorkPlanForPhenology();
-        farmWorkPlanTimelineRef.value.updateFarmWorkPlan();
-    }
-};
-// 取消复制方案
-const handleCancelCopyPlan = () => {
-    if (active.value === tabs.value[0]?.id) {
-        showCopyPlan.value = false;
-    } else {
-        ElMessageBox.confirm("确定要删除该方案吗?", "提示", {
-            confirmButtonText: "确定",
-            cancelButtonText: "取消",
-            type: "warning",
-        }).then(() => {
-            VE_API.monitor
-                .deleteScheme({
-                    schemeId: active.value,
-                })
-                .then(({ code }) => {
-                    if (code === 0) {
-                        showCopyPlan.value = false;
-                        ElMessage.success("删除成功");
-                        getListMySchemes("left");
-                    }
-                });
-        });
-    }
-};
-
-// 确定复制方案
-const handleConfirmCopyPlan = () => {
-    if (!copyPlanName.value.trim()) {
-        ElMessage.warning("请输入方案名称");
-        return;
-    }
-    if (active.value === tabs.value[0]?.id) {
-        VE_API.monitor
-            .copyScheme({
-                containerId: specieValue.value,
-                sourceSchemeId: active.value,
-                schemeName: copyPlanName.value,
-            })
-            .then(({ code, data }) => {
-                if (code === 0) {
-                    showCopyPlan.value = false;
-                    ElMessage.success("复制成功");
-                    getListMySchemes("right");
-                    currentTab.value = data;
-                    currentTabIndex.value = (tabs.value.length - 1) + 1;
-                }
-            });
-    } else {
-        VE_API.monitor
-            .renameScheme({
-                schemeId: active.value,
-                name: copyPlanName.value,
-            })
-            .then(({ code }) => {
-                if (code === 0) {
-                    showCopyPlan.value = false;
-                    ElMessage.success("修改成功");
-                    getListMySchemes("auto");
-                }
-            });
-    }
-};
-
-// 验证药肥报价信息并返回结果
-// 返回: { allTrue: boolean, invalidIds: string[] }
-const validatePesticideFertilizerQuotes = async () => {
-    const { data, code } = await VE_API.monitor.batchValidatePesticideFertilizerQuotes({
-        ids: farmWorkIds.value,
-        schemeId: active.value,
-    });
-
-    if (code !== 0 || !data) {
-        return { allTrue: false, invalidIds: [] };
-    }
-
-    // 判断所有值是否都为true
-    const allTrue = Object.values(data).every((value) => value === true);
-
-    // 收集所有不为true的ID
-    const invalidIds = Object.keys(data).filter((key) => data[key] !== true);
-
-    return { allTrue, invalidIds };
-};
-
-// 提交方案
-const handleSubmitPlan = async () => {
-    // 调用验证方法,传入所有ids
-    if (farmWorkIds.value.length > 0) {
-        // 自动化完善农事处方中的药肥数据   用于本地测试代码  不要删除
-        // const res = await VE_API.monitor.completeMedicationData({
-        //     schemeId: active.value,
-        //     containerId: specieValue.value,
-        // });
-        // if (res.code === 0) {
-        //     ElMessage.success("自动化完善成功");
-        //     await getFarmWorkPlanForPhenology()
-        // }
-        const { allTrue } = await validatePesticideFertilizerQuotes();
-        if (allTrue) {
-            VE_API.monitor
-                .enableScheme({
-                    schemeId: active.value,
-                })
-                .then(({ code }) => {
-                    if (code === 0) {
-                        ElMessage.success("提交成功");
-                        if(route.query.headerTitle) {
-                            router.replace({
-                                path: "/home",
-                            });
-                        }else{
-                            getListMySchemes("auto");
-                        }
-                    }
-                });
-        } else {
-            ElMessage.warning("当前方案有未完善报价信息的农事,请先完善报价信息");
-        }
-    }
-};
-
-const savePlanPageInfo = () => {
-    if(route.query.pageType !== 'plant') {
-        return;
-    }
-    sessionStorage.setItem("specieValue", specieValue.value);
-    sessionStorage.setItem("active", active.value);
-    sessionStorage.setItem("currentTabIndex", currentTabIndex.value);
-};
-
-// 新增农事
-const addNewTask = () => {
-    savePlanPageInfo();
-    router.push({
-        path: "/add_work",
-        query: {
-            containerSpaceTimeId: containerSpaceTimeId.value,
-            schemeId: route.query.schemeId || schemeId.value,
-        },
-    });
-};
-
-const triggerFarmWork = () => {
-    eventBus.emit("activeUpload:show", {
-        gardenIdVal: route.query.farmId,
-        problemTitleVal: "请选择您出现" + curFarmObj.value.farmWorkName + "的时间",
-        arrangeIdVal: curFarmObj.value.id,
-        needExecutorVal: true,
-    });
-};
-
-const curFarmObj = ref({});
-const handleRowClick = (item) => {
-    curFarmObj.value = item;
-    savePlanPageInfo();
-    sessionStorage.setItem("farmWorkAndArrangeIds", JSON.stringify(item.invalidArr));
-    const enabled = tabs.value[currentTabIndex.value]?.enabled;
-    router.push({
-        path: "/modify",
-        query: {
-            id: item.id,
-            noPrice: pageType.value === "plant" ? true : false,
-            farmId: route.query.farmId,
-            farmWorkId: item.farmWorkId,
-            containerSpaceTimeId: item.containerSpaceTimeId,
-            isDefault: active.value === tabs.value[0]?.id,
-            enabled: enabled,
-            isEdit: item.isEdit,
-        },
-    });
-};
-</script>
-
-<style scoped lang="scss">
-.plan-page {
-    width: 100%;
-    height: 100vh;
-    background: #f5f7fb;
-    .plan-content {
-        .plan-content-header {
-            display: flex;
-            align-items: center;
-            gap: 12px;
-            margin: 10px 0 10px 12px;
-            .select-item {
-                width: 82px;
-                ::v-deep {
-                    .el-select__wrapper {
-                        box-shadow: none;
-                        border-radius: 25px;
-                        border: 0.5px solid rgba(153, 153, 153, 0.5);
-                    }
-                }
-            }
-            .tabs-list {
-                width: calc(100% - 94px);
-                margin-right: 8px;
-            }
-        }
-        .tip-box {
-            padding: 5px 10px;
-            background: rgba(33, 153, 248, 0.1);
-            border-radius: 5px;
-            font-size: 12px;
-            margin: 8px 10px;
-            color: #444;
-        }
-        .timeline-wrap {
-            height: calc(100vh - 90px - 80px);
-            padding: 0 10px 0 4px;
-            &.timeline-container-plant-wrap {
-                height: calc(100vh - 90px - 85px - 38px);
-            }
-            &.no-default-plan-wrap {
-                height: calc(100vh - 90px - 85px - 100px);
-            }
-            // 没有权限时,底部按钮不显示,高度增加 73px
-            &.timeline-container-no-permission-wrap {
-                height: calc(100vh - 90px - 60px);
-            }
-        }
-    }
-    // 控制区域样式
-    .custom-bottom-fixed-btns {
-        flex-direction: column;
-        .bottom-btn-group-wrap {
-            display: flex;
-            gap: 12px;
-            width: 100%;
-            justify-content: space-between;
-            .bottom-btn-group {
-                display: flex;
-                gap: 12px;
-                &.justify-center {
-                    justify-content: center;
-                    width: 100%;
-                }
-            }
-        }
-        &.center {
-            justify-content: center;
-            .bottom-btn {
-                padding: 10px 45px;
-            }
-        }
-        .bottom-btn-divider {
-            width: calc(100% + 24px);
-            height: 1px;
-            background: #f0f0f0;
-            margin: 10px -12px;
-        }
-        .submit-btn {
-            padding: 10px 83px;
-        }
-    }
-}
-.copy-plan-popup {
-    width: 100%;
-    padding: 50px 12px 20px 12px;
-    &::before {
-        content: "";
-        position: absolute;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 136px;
-        pointer-events: none;
-        background: url("@/assets/img/monitor/popup-header-bg.png") no-repeat center center / 100% 100%;
-    }
-    .copy-plan-content {
-        display: flex;
-        align-items: center;
-        gap: 12px;
-        .label {
-            font-size: 16px;
-            font-weight: 500;
-        }
-        .copy-plan-input {
-            width: calc(100% - 80px);
-        }
-    }
-    .copy-plan-footer {
-        display: flex;
-        gap: 12px;
-        margin-top: 20px;
-        .btn {
-            flex: 1;
-            color: #666666;
-            border: 1px solid #999999;
-            border-radius: 25px;
-            padding: 10px 0;
-            font-size: 16px;
-            text-align: center;
-            &.btn-confirm {
-                color: #fff;
-                border: 1px solid #2199f8;
-                background: #2199f8;
-            }
-        }
-    }
-}
-
-.phenology-popup {
-    padding: 28px 20px 20px;
-    .phenology-header {
-        font-size: 24px;
-        text-align: center;
-        margin-bottom: 20px;
-        font-family: "PangMenZhengDao";
-    }
-    .phenology-list {
-        width: 100%;
-        .phenology-item {
-            width: 100%;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            .item-label {
-                display: flex;
-                align-items: center;
-                gap: 4px;
-                font-size: 15px;
-                color: rgba(0, 0, 0, 0.4);
-                .label-text {
-                    color: #000;
-                    font-size: 16px;
-                    font-weight: 500;
-                }
-            }
-            .item-value {
-                width: calc(100% - 156px);
-            }
-        }
-        .phenology-item + .phenology-item {
-            margin-top: 10px;
-        }
-    }
-    .phenology-footer-tip {
-        margin-top: 20px;
-        text-align: center;
-        .text{
-            color: rgba(0, 0, 0, 0.4);
-        }
-    }
-    .phenology-footer {
-        width: 100%;
-        text-align: center;
-        font-size: 16px;
-        margin-top: 10px;
-        color: #fff;
-        background: #2199f8;
-        border-radius: 25px;
-        padding: 10px 0;
-    }
-}
-</style>

+ 0 - 269
src/views/old_mini/monitor/subPages/reviewResults.vue

@@ -1,269 +0,0 @@
-<template>
-    <custom-header name="复核成效"></custom-header>
-    <div class="farm-dynamics">
-        <div class="task-content">
-            <div class="expert-content">
-                <template v-if="contentData.length > 0">
-                    <List
-                        v-model:loading="loading"
-                        :finished="finished"
-                        :offset="100"
-                        loading-text="加载中..."
-                        finished-text="没有更多了"
-                        @load="onLoad"
-                    >
-                        <div v-for="(section, index) in contentData" :key="index" class="content-section">
-                            <div class="section-id" :id="section.targetId"></div>
-                            <record-item
-                                :record-item-data="section"
-                                content-mode="serviceDetail"
-                                title-mode="default"
-                                class="recipe-item"
-                                titleRightDotText="全区"
-                                titleRightType="dot"
-                                showFarmImage
-                                @click="handleClick(section, index)"
-                            >
-                                <template #footer>
-                                    <div class="action-group" v-if="!section.reviewImage.length">
-                                        <div class="action-l">查看详情</div>
-                                        <div class="action-r">
-                                            <div
-                                                class="action-item warning-item"
-                                                :class="{ 'has-applied': section.hasApplied }"
-                                                @click.stop="handleApply(section, index)"
-                                            >
-                                                {{ section.hasApplied ? "已发起需求" : "发起需求" }}
-                                            </div>
-                                            <div class="action-item primary-item" @click.stop="handleUploadPhoto(section)">
-                                                上传照片
-                                            </div>
-                                        </div>
-                                    </div>
-                                </template>
-                            </record-item>
-                        </div>
-                    </List>
-                </template>
-                <empty
-                    v-else
-                    image="https://birdseye-img.sysuimars.com/birdseye-look-mini/custom-empty-image.png"
-                    image-size="80"
-                    description="暂无数据"
-                />
-            </div>
-        </div>
-    </div>
-    <!-- 需求发送成功弹窗 -->
-    <popup v-model:show="showApplyPopup" round class="apply-popup">
-        <img class="check-icon" src="@/assets/img/home/right.png" alt="" />
-        <div class="apply-text">需求发送成功</div>
-        <div class="apply-btn" @click="showApplyPopup = false">我知道了</div>
-    </popup>
-
-    <!-- 上传照片弹窗 -->
-    <review-upload-popup v-model="showUpload" :record-id="sectionId" @success="resetAndLoad" />
-</template>
-<script setup>
-import { ref, onMounted } from "vue";
-import recordItem from "@/components/recordItem.vue";
-import { Popup } from "vant";
-import customHeader from "@/components/customHeader.vue";
-import { useRouter, useRoute } from "vue-router";
-import { Empty,List } from "vant";
-import reviewUploadPopup from "@/components/popup/reviewUploadPopup.vue";
-
-const showApplyPopup = ref(false);
-const showUpload = ref(false);
-const router = useRouter();
-const route = useRoute();
-const sectionId = ref(null);
-// 上传照片处理函数
-const handleUploadPhoto = ({id}) => {
-    showUpload.value = true;
-    sectionId.value = id;
-};
-
-const handleApply = (section, index) => {
-    // // 更新当前项的发起需求状态
-    // showApplyPopup.value = true;
-    // section.hasApplied = true;
-};
-
-const contentData = ref([]);
-const loading = ref(false);
-const finished = ref(false);
-const page = ref(1);
-const limit = ref(10);
-
-const onLoad = () => {
-    if (finished.value) return;
-    loading.value = true;
-    const params = {
-        farmId: route.query.farmId,
-        flowStatus: 5,
-        page: page.value,
-        limit: limit.value,
-    };
-    VE_API.user.getDetailList(params)
-        .then((res) => {
-            const list = res?.data || [];
-            if (Array.isArray(list) && list.length > 0) {
-                contentData.value = contentData.value.concat(list);
-                page.value += 1;
-                if (list.length < limit.value) {
-                    finished.value = true;
-                }
-            } else {
-                finished.value = true;
-            }
-        })
-        .finally(() => {
-            loading.value = false;
-        });
-};
-
-const resetAndLoad = () => {
-    page.value = 1;
-    finished.value = false;
-    contentData.value = [];
-    onLoad();
-};
-
-onMounted(() => {
-    resetAndLoad();
-});
-
-const handleClick = (section) => {
-    router.push({
-        path: "/review_work",
-        query: {
-            miniJson: JSON.stringify({ id: section.id,goBack: true }),
-        },
-    });
-};
-</script>
-<style lang="scss" scoped>
-.farm-dynamics {
-    width: 100%;
-    height: 100vh;
-    background: #f5f7fb;
-    .task-content {
-        display: flex;
-        padding-top: 10px;
-        height: calc(100% - 40px);
-        .expert-content {
-            width: 100%;
-            height: 100%;
-            overflow: auto;
-            padding: 0 10px 10px;
-            box-sizing: border-box;
-            .content-section {
-                position: relative;
-                .section-id {
-                    position: absolute;
-                    top: 0;
-                    width: 100%;
-                    height: 1px;
-                }
-            }
-            // 空状态样式
-            :deep(.van-empty) {
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                padding: 60px 0;
-                min-height: 200px;
-            }
-            .action-r {
-                color: #1d2129;
-            }
-            .action-group {
-                display: flex;
-                align-items: center;
-                justify-content: space-between;
-                padding-top: 8px;
-                margin-top: 8px;
-                border-top: 1px solid #f5f5f5;
-                .action-l {
-                    font-size: 12px;
-                }
-            }
-            .action-group {
-                .action-r {
-                    display: flex;
-                    align-items: center;
-                    .action-item {
-                        padding: 0 11px;
-                        height: 30px;
-                        line-height: 30px;
-                        border-radius: 20px;
-                        font-size: 12px;
-                        &.second-item {
-                            border: 1px solid #2199f8;
-                            color: #2199f8;
-                        }
-                        &.primary-item {
-                            background: #2199f8;
-                            color: #fff;
-                        }
-                        &.warning-item {
-                            background: rgba(255, 131, 29, 0.1);
-                            color: #ff831d;
-                            &.has-applied {
-                                background: transparent;
-                                color: #afafaf;
-                                pointer-events: none;
-                            }
-                        }
-                        &.cancel-item {
-                            color: #676767;
-                            border: 1px solid rgba(103, 103, 103, 0.2);
-                        }
-                    }
-                    .action-item + .action-item {
-                        margin-left: 5px;
-                    }
-                }
-                .apply-action {
-                    justify-content: flex-end;
-                    .default-item {
-                        border: 1px solid rgba(0, 0, 0, 0.4);
-                        color: rgba(0, 0, 0, 0.4);
-                    }
-                }
-            }
-        }
-    }
-}
-.apply-popup {
-    width: 75%;
-    padding: 28px 28px 20px;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    .check-icon {
-        width: 68px;
-        height: 68px;
-        margin-bottom: 12px;
-    }
-    .apply-text {
-        font-size: 24px;
-        font-weight: 500;
-        margin-bottom: 32px;
-        text-align: center;
-    }
-    .apply-btn {
-        width: 100%;
-        box-sizing: border-box;
-        padding: 8px;
-        border-radius: 25px;
-        font-size: 16px;
-        background: #2199f8;
-        color: #fff;
-        text-align: center;
-    }
-}
-
-</style>

+ 0 - 1302
src/views/old_mini/plan/components/modifyPlan.vue

@@ -1,1302 +0,0 @@
-<template>
-    <div class="new-farming-page">
-        <custom-header name="编辑方案"></custom-header>
-        <div class="new-farming-content" v-loading="loading">
-            <el-form
-                ref="formRef"
-                style="max-width: 600px"
-                label-position="left"
-                :rules="rules"
-                :model="dynamicValidateForm"
-                class="demo-dynamic"
-            >
-                <div class="farm-card" v-if="!isAdd">
-                    <div class="card-title">{{ detailData?.farmWorkLib?.farmWorkName || detailData?.farmWorkLib?.name }}<span class="type-tag">标准农事</span></div>
-                    <div class="info-content">
-                        <el-form-item label-width="70px" class="form-item text-item" label="农事编号">
-                            <div class="info-text">
-                                {{ detailData?.farmWorkLib?.code }}
-                            </div>
-                        </el-form-item>
-                        <el-form-item label-width="70px" class="form-item" prop="condition" label="触发条件">
-                            <div class="condition-wrap">
-                                {{ detailData?.farmWorkLib?.condition }}
-                                <!-- <el-select v-model="dynamicValidateForm.condition" placeholder="请选择触发条件" style="width: 58%">
-                                    <el-option v-for="(item, index) in farmWorkIndexNameList" :key="index" :value="item" :label="item" />
-                                </el-select>
-                                <span class="symbol"></span>
-                                <el-select v-model="dynamicValidateForm.conditionRate" placeholder="" style="width: 38%">
-                                    <el-option :value="0" label="0%" />
-                                    <el-option :value="5" label="5%" />
-                                    <el-option :value="10" label="10%" />
-                                    <el-option :value="20" label="20%" />
-                                    <el-option :value="40" label="40%" />
-                                    <el-option :value="60" label="60%" />
-                                    <el-option :value="80" label="80%" />
-                                </el-select> -->
-                            </div>
-                        </el-form-item>
-                        <el-form-item label-width="70px" class="form-item" prop="executeDate" label="执行时间">
-                            <el-date-picker
-                                class="item-input"
-                                style="width: 100%"
-                                value-format="YYYY-MM-DD"
-                                v-model="dynamicValidateForm.executeDate"
-                                type="date"
-                                :clearable="false"
-                                placeholder="选择日期"
-                            />
-                        </el-form-item>
-                    </div>
-                </div>
-                <div class="farm-card prescription-content">
-                    <div class="card-title pb-12">药物处方</div>
-                    <el-form-item label-width="82px" class="form-item" prop="usageMode" label="施用方式">
-                        <el-select v-model="dynamicValidateForm.usageMode" placeholder="请选择施用方式" style="width: 100%">
-                            <el-option
-                                v-for="(usage, uId) in allUsageModeList"
-                                :key="uId"
-                                :label="usage"
-                                :value="usage"
-                            />
-                        </el-select>
-                    </el-form-item>
-                    <div v-if="dynamicValidateForm.usageMode !== '人工农事'">
-                        <el-form-item
-                            v-for="(prescriptionItem, prescriptionI) in dynamicValidateForm.prescriptionList"
-                            :key="prescriptionI"
-                            :prop="'prescriptions.' + prescriptionI + '.value'"
-                            class="prescription-item"
-                        >
-                            <div class="recipe-item">
-                                <div class="sub-title">
-                                    <div>{{ prescriptionItem.name }}处方</div>
-                                    <div class="add-tag" @click="addDomain(prescriptionI)">
-                                        <el-icon color="#2199F8"><Plus /></el-icon>新增药物
-                                    </div>
-                                </div>
-                                <div class="recipe-form">
-                                    <el-form-item
-                                        v-for="(domain, index) in prescriptionItem.pesticideFertilizerList"
-                                        :key="domain.key"
-                                        :prop="'pesticideFertilizerList.' + index + '.value'"
-                                    >
-                                        <div class="form-box">
-                                            <div class="form-index">{{ formatIndex(index) }}</div>
-                                            <div class="box-item" v-if="domain.typeName">
-                                                <div class="form-l">药肥类型</div>
-                                                <div class="form-r r-text">
-                                                    {{ domain.typeName }}
-                                                    <!-- <el-select
-                                                    v-model="domain.typeName"
-                                                    placeholder="请选择"
-                                                    style="width: 100%"
-                                                    >
-                                                        <el-option :label="domain.typeName" :value="domain.typeName" />
-                                                </el-select> -->
-                                                </div>
-                                            </div>
-                                            <div class="box-item">
-                                                <div class="form-l">药肥名称</div>
-                                                <div class="form-r">
-                                                    <el-select
-                                                        filterable
-                                                        @change="handlePesticideFertilizerChange(prescriptionI, index)"
-                                                        v-model="domain.pesticideFertilizerCode"
-                                                        placeholder="请选择"
-                                                        style="width: 100%"
-                                                    >
-                                                        <el-option
-                                                            v-for="item in pesticideFertilizersOptions"
-                                                            :key="item.pesticideFertilizerCode"
-                                                            :label="item.defaultName || item.name"
-                                                            :value="item.pesticideFertilizerCode"
-                                                        />
-                                                    </el-select>
-                                                </div>
-                                            </div>
-                                            <div class="form-title">人工方式</div>
-                                            <div class="box-item sub-item">
-                                                <div class="form-l has-sub">
-                                                    <div class="main-name">药肥配比</div>
-                                                </div>
-                                                <div class="form-r input-box text-center input-unit">
-                                                    <!-- <el-input
-                                                        v-model="domain.ratio"
-                                                        style="width: 100%"
-                                                        placeholder="请输入"
-                                                    /> -->
-
-                                                    <el-input v-model="domain.ratio" type="number" step="0.01" placeholder="请输入">
-                                                        <template #append>倍</template>
-                                                    </el-input>
-                                                </div>
-                                            </div>
-                                            <!-- <div class="box-item sub-item">
-                                                <div class="form-l">施用方式</div>
-                                                <div class="form-r">
-                                                    <el-select
-                                                        v-model="domain.usageMode"
-                                                        placeholder="请选择"
-                                                        style="width: 100%"
-                                                    >
-                                                        <el-option
-                                                            v-for="(usage, uId) in domain.usageModeList"
-                                                            :key="uId"
-                                                            :label="usage"
-                                                            :value="usage"
-                                                        />
-                                                    </el-select>
-                                                </div>
-                                            </div> -->
-                                            <div class="box-item sub-item">
-                                                <div class="form-l has-sub">
-                                                    <div class="main-name">单亩用量</div>
-                                                </div>
-                                                <div class="form-r input-box text-center">
-                                                    <!-- <el-input
-                                                        v-model="domain.muUsage"
-                                                        style="width: 100%"
-                                                        placeholder="请输入"
-                                                    /> -->
-                                                    <el-input v-model="domain.dosage" type="number" step="0.01" placeholder="请输入">
-                                                        <template #append>{{ domain.unit }}</template>
-                                                    </el-input>
-                                                </div>
-                                            </div>
-                                            <div v-if="dynamicValidateForm.usageMode === '叶面施'">
-                                                <div class="form-title">无人机</div>
-                                                <div class="box-item sub-item">
-                                                    <div class="form-l has-sub">
-                                                        <div class="main-name">药肥配比</div>
-                                                    </div>
-                                                    <div class="form-r input-box text-center">
-                                                        <!-- <el-input
-                                                            v-model="domain.ratio2"
-                                                            style="width: 100%"
-                                                            placeholder="请输入"
-                                                        /> -->
-                                                        <el-input v-model="domain.ratio2" type="number" step="0.01" placeholder="请输入">
-                                                            <template #append>倍</template>
-                                                        </el-input>
-                                                    </div>
-                                                </div>
-                                                <div class="box-item sub-item">
-                                                    <div class="form-l has-sub">
-                                                        <div class="main-name">单亩用量</div>
-                                                    </div>
-                                                    <div class="form-r input-box text-center">
-                                                        <!-- <el-input
-                                                            v-model="domain.muUsage2"
-                                                            style="width: 100%"
-                                                            placeholder="请输入"
-                                                        /> -->
-                                                        <el-input v-model="domain.dosage2" type="number" step="0.01" placeholder="请输入">
-                                                            <template #append>{{ domain.unit }}</template>
-                                                        </el-input>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                            <div class="input-box mark-box">
-                                                <el-input
-                                                    v-model="domain.remark"
-                                                    style="width: 100%"
-                                                    placeholder="备注:用药注意事项"
-                                                />
-                                            </div>
-                                            <div class="action-btn">
-                                                <el-button
-                                                    class="btn delete-btn"
-                                                    @click.prevent="removeDomain(prescriptionI, domain)"
-                                                >
-                                                    删除
-                                                </el-button>
-                                                <el-button
-                                                    type="default"
-                                                    class="btn"
-                                                    @click.prevent="resetItemForm(prescriptionI, index)"
-                                                >
-                                                    重置
-                                                </el-button>
-                                            </div>
-                                        </div>
-                                    </el-form-item>
-                                </div>
-                            </div>
-                        </el-form-item>
-                    </div>
-                </div>
-
-                <div class="submit-btn" v-if="isEdit">
-                    <div class="btn second" @click.prevent="cancelEdit">取消编辑</div>
-                    <div class="btn" @click.prevent="submitForm(formRef)">保存方案</div>
-                </div>
-            </el-form>
-        </div>
-    </div>
-
-    <popup v-model:show="showTaskPopup" round class="task-tips-popup">
-        <img class="farm-check-icon" src="@/assets/img/home/right.png" alt="">
-        <div class="create-farm-text success-text">方案已保存成功</div>
-        <div class="create-farm-btn" @click="handlePopupBtn">我知道了</div>
-    </popup>
-</template>
-
-<script setup>
-import { onActivated, ref, reactive, onDeactivated, onBeforeUnmount, computed, onMounted } from "vue";
-import { useRouter, useRoute } from "vue-router";
-import { ElMessage ,ElMessageBox} from "element-plus";
-import customHeader from "@/components/customHeader.vue";
-import { useStore } from "vuex";
-import { Popup } from "vant";
-import dayjs from "dayjs";
-const store = useStore();
-const router = useRouter();
-const route = useRoute();
-
-// 角色
-// const curRole = store.state.app.curRole
-const curRole = 0
-
-const gardenId = ref(null);
-const actionType = ref([]);
-const isAdd = ref(false)
-
-const showTaskPopup = ref(false);
-const loading = ref(false);
-
-const isEdit = ref(false)
-isAdd.value = route.query.isAdd ? true : false
-isEdit.value = route.query.isEdit ? true : false
-onMounted(() => {
-    window.scrollTo(0, 0);
-    console.log('route.query', route.query);
-    const arrangeId = route.query.arrangeId;
-    if (arrangeId) {
-        getArrangeDetail(arrangeId);
-    }
-    
-    // if (route.query.data) {
-    //     actionType.value = JSON.parse(route.query.data);
-    // } else {
-    //     actionType.value = ["生长异常"];
-    // }
-    // const planData = JSON.parse(route.query.planData);
-    // detailData.value = planData;
-    // console.log('planData', planData);
-    // dynamicValidateForm.farmWorkName = planData.name;
-    // dynamicValidateForm.executeDate = planData.executeDate;
-    // dynamicValidateForm.usageMode = planData.prescription.usageMode;
-    // planData.prescription.pesticideFertilizerList.forEach(item => {
-    //     item.defaultName = item.name;
-    //     item.pesticideFertilizerCode = item.code;
-    // });
-    // dynamicValidateForm.prescriptionList = [planData.prescription];
-    // console.log('dynamicValidateForm.prescriptionList', dynamicValidateForm.prescriptionList);
-    // dynamicValidateForm.prescriptionList = actionType.value.map((name) => ({
-    //     name,
-    //     pesticideFertilizerList: [
-    //         {
-    //             key: 1,
-    //             typeName: "",
-    //             muUsage: "",
-    //             muUsage2: "",
-    //             ratio: "",
-    //             ratio2: "",
-    //             remark: "",
-    //         },
-    //     ],
-    // }));
-});
-
-const getArrangeDetail = (arrangeId) => {
-    loading.value = true;
-    VE_API.container_farm_work_arrange.getComposite({ arrangeId }).then(({ data }) => {
-        detailData.value = data;
-        
-        // 赋值表单数据
-        if (data.farmWorkLib) {
-            // 执行时间
-            if (data.farmWorkLib.executeDate) {
-                dynamicValidateForm.executeDate = data.farmWorkLib.executeDate;
-            }
-        }
-        
-        // 施用方式
-        if (data.prescription && data.prescription.usageMode) {
-            dynamicValidateForm.usageMode = data.prescription.usageMode;
-        }
-        
-        // 处理处方数据
-        if (data.prescription && data.prescription.pesticideFertilizerList) {
-            // 将 prescription 对象转换为 prescriptionList 数组格式
-            // 根据 typeName 分组,创建不同的处方项
-            const prescriptionMap = new Map();
-            
-            data.prescription.pesticideFertilizerList.forEach((item, index) => {
-                const typeName = item.typeName || '其他';
-                
-                if (!prescriptionMap.has(typeName)) {
-                    prescriptionMap.set(typeName, {
-                        name: typeName,
-                        pesticideFertilizerList: []
-                    });
-                }
-                
-                // 查找对应的药肥选项,获取完整信息
-                const pesticideOption = pesticideFertilizersOptions.value.find(
-                    opt => opt.pesticideFertilizerCode === item.code || opt.code === item.code
-                );
-                
-                // 映射字段到表单需要的格式
-                const prescriptionItem = {
-                    key: Date.now() + index,
-                    pesticideFertilizerCode: item.code,
-                    pesticideFertilizerName: item.name,
-                    pesticideFertilizerId: pesticideOption?.id || null, // 用于 handlePesticideFertilizerChange 函数
-                    typeName: item.typeName || '',
-                    ratio: item.ratio || '',
-                    dosage: item.dosage || '',
-                    ratio2: item.ratio2 || '', // 无人机方式的亩兑水量
-                    dosage2: item.dosage2 || '', // 无人机方式的单亩用量
-                    remark: item.remark || '',
-                    unit: pesticideOption?.unit || 'kg',
-                    defaultRatio: pesticideOption?.defaultRatio || item.ratio || '',
-                    usageModeList: pesticideOption?.usageModeList || [],
-                    defaultName: pesticideOption?.defaultName || pesticideOption?.name || item.name,
-                };
-                
-                prescriptionMap.get(typeName).pesticideFertilizerList.push(prescriptionItem);
-            });
-            
-            // 转换为数组
-            dynamicValidateForm.prescriptionList = Array.from(prescriptionMap.values());
-            
-            // 如果没有数据,至少保留一个空项
-            if (dynamicValidateForm.prescriptionList.length === 0) {
-                dynamicValidateForm.prescriptionList = [{
-                    name: "",
-                    pesticideFertilizerList: [{
-                        key: Date.now(),
-                        typeName: "",
-                        muUsage: "",
-                        muUsage2: "",
-                        ratio: "",
-                        ratio2: "",
-                        remark: "",
-                    }],
-                }];
-            }
-        }
-    }).finally(() => {
-        loading.value = false;
-    });
-};
-
-const detailData = ref({});
-
-function handlePopupBtn() {
-    showTaskPopup.value = false;
-    router.back();
-}
-
-const resetForm = (formEl) => {
-    if (!formEl) return;
-    formEl.resetFields();
-    serveArea.value = null;
-    regionId.value = null;
-};
-
-// 清空所有数据
-const clearData = () => {
-    // 清空表单
-    resetForm(formRef.value);
-    
-    // 清空详情数据
-    detailData.value = {};
-    
-    // 清空表单数据
-    dynamicValidateForm.farmWorkName = "";
-    dynamicValidateForm.conditionRate = "";
-    dynamicValidateForm.purpose = "";
-    dynamicValidateForm.executeDate = dayjs().format("YYYY-MM-DD");
-    dynamicValidateForm.checkDay = "";
-    dynamicValidateForm.usageMode = "";
-    dynamicValidateForm.prescriptionList = [{
-        name: "",
-        pesticideFertilizerList: [{
-            key: 1,
-            typeName: "",
-            muUsage: "",
-            muUsage2: "",
-            ratio: "",
-            ratio2: "",
-            remark: "",
-        }],
-    }];
-    
-    // 清空其他数据
-    serveArea.value = null;
-    regionId.value = null;
-    areaList.value = [];
-    situationDescription.value = '';
-    checkedArea.value = false;
-    actionType.value = [];
-    gardenId.value = null;
-    showTaskPopup.value = false;
-};
-
-onDeactivated(() => {
-    // areaRef.value && newFarmMap.destroyMap();
-    clearData();
-});
-
-onBeforeUnmount(() => {
-    clearData();
-});
-
-const cancelEdit = () => {
-    ElMessageBox.confirm("确认要取消编辑吗?", "提示", {
-        confirmButtonText: "确认",
-        cancelButtonText: "取消",
-        type: "warning",
-    })
-        .then(() => {
-            router.back();
-        })
-        .catch(() => {
-            console.log("取消编辑");
-        });
-};
-
-// 表单
-const formRef = ref();
-const dynamicValidateForm = reactive({
-    farmWorkName: "",
-    conditionRate: "",
-    purpose: "",
-    executeDate: dayjs().format("YYYY-MM-DD"),
-    checkDay: "",
-    usageMode: "",
-    prescriptionList: [
-        {
-            name: "",
-            pesticideFertilizerList: [
-                {
-                    key: 1,
-                    typeName: "",
-                    muUsage: "",
-                    muUsage2: "",
-                    ratio: "",
-                    ratio2: "",
-                    remark: "",
-                },
-            ],
-        },
-    ],
-});
-
-const rules = {
-    farmWorkName: [
-        {
-            required: true,
-            message: "请输入农事名称",
-            trigger: "blur",
-        },
-    ],
-    conditionRate: [
-        {
-            required: false,
-            message: "请输入触发条件",
-            trigger: "blur",
-        },
-    ],
-    executeDate: [
-        {
-            required: false,
-            message: "请选择执行时间",
-            trigger: "blur",
-        },
-    ],
-    checkDay: [
-        {
-            required: true,
-            message: "请选择复核时间",
-            trigger: "blur",
-        },
-    ],
-};
-
-const formatIndex = (index) => {
-    return String(index + 1).padStart(2, "0");
-};
-
-const addDomain = (parentIndex) => {
-    dynamicValidateForm.prescriptionList[parentIndex].pesticideFertilizerList.unshift({
-        key: Date.now(),
-        muUsage: "",
-        muUsage2: "",
-        ratio: "",
-        ratio2: "",
-        remark: "",
-    });
-};
-
-let pesticideFertilizersOptions = ref([]);
-VE_API.z_farm_work_order.pesticideFertilizersList().then(({ data }) => {
-    pesticideFertilizersOptions.value = data;
-});
-
-const allUsageModeList = ["叶面施", "根部施", "人工农事"];
-
-
-/**
- * 选择药肥的时候修改订单中药肥pesticideFertilizerCode 以外其他数据
- * @param parentIndex 处方索引
- * @param index 药物索引
- */
-const handlePesticideFertilizerChange = (parentIndex, index) => {
-    const currentItem = dynamicValidateForm.prescriptionList[parentIndex].pesticideFertilizerList[index];
-    const pesticideFertilizerCode = currentItem.pesticideFertilizerCode;
-    
-    // 根据 pesticideFertilizerCode 查找对应的药肥选项
-    const obj = pesticideFertilizersOptions.value.find(
-        (item) => item.pesticideFertilizerCode === pesticideFertilizerCode || item.code === pesticideFertilizerCode
-    );
-    
-    if (!obj) {
-        ElMessage({
-            message: "未找到对应的药肥信息",
-            type: "warning",
-        });
-        return;
-    }
-    
-    // 更新当前项的数据,保留原有数据并更新新字段
-    dynamicValidateForm.prescriptionList[parentIndex].pesticideFertilizerList[index] = {
-        ...currentItem,
-        pesticideFertilizerId: obj.id || null,
-        typeName: obj.typeName || currentItem.typeName || '',
-        unit: obj.unit || currentItem.unit || 'kg',
-        defaultRatio: obj.defaultRatio || currentItem.defaultRatio || '',
-        usageModeList: obj.usageModeList || currentItem.usageModeList || [],
-        // 如果 ratio 为空,则使用默认值
-        ratio: currentItem.ratio || obj.defaultRatio || '',
-        ratio2: currentItem.ratio2 || obj.defaultDroneRatio || '',
-        defaultName: obj.defaultName || obj.name || currentItem.defaultName || '',
-        pesticideFertilizerName: obj.name || currentItem.pesticideFertilizerName || '',
-        pesticideFertilizerCode: obj.pesticideFertilizerCode || pesticideFertilizerCode,
-    };
-};
-
-const removeDomain = (parentIndex, item) => {
-    const index = dynamicValidateForm.prescriptionList[parentIndex].pesticideFertilizerList.indexOf(item);
-    if (index !== -1) {
-        dynamicValidateForm.prescriptionList[parentIndex].pesticideFertilizerList.splice(index, 1);
-    }
-};
-
-const resetItemForm = (parentIndex, index) => {
-    dynamicValidateForm.prescriptionList[parentIndex].pesticideFertilizerList[index] = {
-        typeName: "",
-        muUsage: "",
-        muUsage2: "",
-        ratio: "",
-        ratio2: "",
-        remark: "",
-    };
-};
-
-const submitForm = (formEl) => {
-    if (!formEl) return;
-    formEl.validate((valid) => {
-        if (valid) {
-
-            // router.push({
-            //     path: "/completed_work",
-            //     query: {
-            //         id: 1,
-            //         status: 1,
-            //     },
-            // });
-
-            // showTaskPopup.value = true;
-            submit();
-        } else {
-            console.log("error submit!");
-        }
-    });
-};
-
-const submit = () => {
-    // 构造保存数据,格式与 getComposite 返回的一致
-    const saveData = {
-        arrange: {
-            ...detailData.value.arrange,
-        },
-        farmWorkLib: {
-            ...detailData.value.farmWorkLib,
-            // 更新执行时间
-            executeDate: dynamicValidateForm.executeDate || detailData.value.farmWorkLib?.executeDate,
-        },
-        prescription: {
-            id: detailData.value.prescription?.id || null,
-            usageMode: dynamicValidateForm.usageMode || detailData.value.prescription?.usageMode || '',
-            farmWorkLibCode: detailData.value.prescription?.farmWorkLibCode || detailData.value.farmWorkLib?.code || '',
-            expertId: detailData.value.prescription?.expertId || detailData.value.farmWorkLib?.expertId || '',
-            phenology: detailData.value.prescription?.phenology || '',
-            soil: detailData.value.prescription?.soil || '',
-            speed: detailData.value.prescription?.speed || null,
-            // 将 prescriptionList 扁平化为 pesticideFertilizerList
-            pesticideFertilizerList: dynamicValidateForm.prescriptionList.reduce((acc, prescriptionItem) => {
-                const items = prescriptionItem.pesticideFertilizerList.map(item => ({
-                    code: item.pesticideFertilizerCode || item.code || '',
-                    name: item.pesticideFertilizerName || item.name || '',
-                    dosage: item.dosage || '',
-                    ratio: item.ratio || '',
-                    ratio2: item.ratio2 || '', // 无人机方式的亩兑水量
-                    dosage2: item.dosage2 || '', // 无人机方式的单亩用量
-                    muPrice: item.muPrice || null,
-                    typeName: item.typeName || '',
-                    remark: item.remark || '',
-                }));
-                return acc.concat(items);
-            }, []),
-        },
-        triggers: detailData.value.triggers || [],
-    };
-console.log('saveData', saveData);
-    // 调用保存接口
-    VE_API.container_farm_work_arrange.saveComposite(saveData).then(({ code, message }) => {
-        if (code === 0) {
-            showTaskPopup.value = true;
-        }
-    });
-};
-
-const farmWorkTypeVal = computed(() => {
-    const valueMap = {
-        生长异常: 1,
-        病虫异常: 3,
-        营养农事: 2,
-    };
-
-    if (actionType.value.length === 1) {
-        return valueMap[actionType.value[0]] || null; // 如果只有一个元素,返回对应的值,否则返回 null
-    } else {
-        return 1;
-    }
-});
-
-function flattenDomains(data) {
-    return data.reduce((acc, item) => {
-        return acc.concat(item.pesticideFertilizerList);
-    }, []);
-}
-
-const serveArea = ref(null);
-// 农场分区列表
-const areaList = ref([]);
-const regionId = ref(null);
-
-
-// 状况描述相关数据
-const situationDescription = ref('')
-const checkedArea = ref(false);
-// 处理上传图片
-const handleUploadImage = () => {
-    // 这里可以添加上传图片的逻辑
-    console.log('上传图片');
-};
-
-// 处理邀请专家诊断
-const handleExpertDiagnosis = () => {
-    // 这里可以添加邀请专家诊断的逻辑
-    console.log('邀请专家诊断');
-};
-</script>
-
-<style lang="scss" scoped>
-.new-farming-page {
-    height: 100vh;
-    position: relative;
-    overflow: auto;
-    font-size: 14px;
-    background: #f2f3f5;
-    ::v-deep {
-        .custom-header {
-            position: fixed;
-            top: 0;
-            padding-bottom: 1px;
-        }
-    }
-    .step-wrap {
-        padding: 12px 0;
-    }
-    .box-wrap {
-        background: #fff;
-        padding: 10px;
-        border-radius: 8px;
-    }
-    .new-farming-content {
-        margin: 41px 0 62px 0;
-        padding: 4px 12px 8px 12px;
-        width: 100%;
-        box-sizing: border-box;
-        
-        // ::v-deep {
-        //     .el-select__input {
-        //         color: #2199F8;
-        //     }
-        //     .el-select__wrapper {
-        //         color: #2199F8;
-        //         min-height: 30px;
-        //         line-height: 28px;
-        //         box-shadow: 0 0 0 1px rgba(33, 153, 248, 0.3) inset;
-        //     }
-        //     .el-select__caret {
-        //         color: #2199F8;
-        //     }
-        //     .el-select__placeholder {
-        //         color: #2199F8;
-        //     }
-        //     .el-radio {
-        //         margin-right: 16px;
-        //     }
-        //     .el-input__wrapper {
-        //         box-shadow: 0 0 0 1px rgba(33, 153, 248, 0.3) inset;
-        //     }
-        //     .el-input__prefix {
-        //         color: #2199F8;
-        //     }
-        //     .el-input__inner {
-        //         color: #2199F8;
-        //         --el-input-placeholder-color: rgba(33, 153, 248, 0.43);
-        //     }
-        //     .el-tag.el-tag--info {
-        //         --el-tag-text-color: #2199F8;
-        //         --el-tag-bg-color: rgba(33, 153, 248, 0.1);
-        //     }
-        // }
-        .farm-info {
-            color: rgba(0, 0, 0, 0.6);
-            font-size: 14px;
-            margin-top: 14px;
-            .info-title {
-                display: flex;
-                align-items: center;
-                justify-content: space-between;
-                color: rgba(41, 41, 41, 0.3);
-                .info-more {
-                    display: flex;
-                    align-items: center;
-                }
-            }
-        }
-        .farm-photo {
-            margin-top: 10px;
-            .photo-list {
-                display: flex;
-                align-items: center;
-                width: 100%;
-                overflow: auto;
-                padding-bottom: 10px;
-                .photo-item {
-                    width: 92px;
-                    height: 92px;
-                    border-radius: 8px;
-                    object-fit: cover;
-                }
-                .img-item {
-                    img {
-                        width: 92px;
-                        height: 92px;
-                        border-radius: 8px;
-                        object-fit: cover;
-                        margin-right: 12px;
-                    }
-                }
-            }
-            .list-text {
-                text-align: center;
-                color: rgba(0, 0, 0, 0.5);
-                padding-top: 2px;
-            }
-        }
-        .submit-btn {
-            z-index: 10;
-            position: fixed;
-            bottom: 0px;
-            left: 0;
-            width: 100%;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            padding: 12px;
-            background: #fff;
-            box-sizing: border-box;
-            box-shadow: 0 4px 4px rgba(0, 0, 0, 0.4);
-            border-top: 1px solid rgba(0, 0, 0, 0.1);
-            .btn {
-                height: 40px;
-                border-radius: 25px;
-                line-height: 40px;
-                width: 110px;
-                text-align: center;
-                background: linear-gradient(180deg, #70BFFE, #2199F8);
-                color: #FFFFFF;
-                font-size: 14px;
-                &.second {
-                    background: #FFFFFF;
-                    border: 1px solid rgba(153, 153, 153, 0.5);
-                    color: #666666;
-                }
-            }
-            .btn + .btn {
-                margin-left: 12px;
-            }
-        }
-    }
-    .card-title {
-        font-size: 16px;
-        font-weight: bold;
-        color: #000;
-        display: flex;
-        align-items: center;
-        // justify-content: space-between;
-        .add-tag {
-            font-size: 12px;
-            color: #2199f8;
-            padding: 4px 8px;
-            background: rgba(33, 153, 248, 0.16);
-            border-radius: 20px;
-            font-weight: normal;
-            height: 25px;
-            line-height: 25px;
-        }
-        .type-tag {
-            margin-left: 5px;
-            font-size: 12px;
-            color: #000000;
-            padding: 0 10px;
-            background: rgba(119, 119, 119, 0.1);
-            border-radius: 20px;
-            font-weight: normal;
-            height: 26px;
-            line-height: 26px;
-        }
-    }
-    .pb-12 {
-        padding-bottom: 12px;
-    }
-    .farm-card {
-        background: #ffffff;
-        border-radius: 8px;
-        padding: 12px 12px 0 12px;
-        width: 100%;
-        box-sizing: border-box;
-        margin-top: 10px;
-        color: rgba(0, 0, 0, 0.4);
-        &.progress{
-            display: flex;
-            align-items: center;
-            padding: 12px;
-            .progress-title{
-                margin-right: 12px;
-            }
-            ::v-deep{
-                .el-radio{
-                    margin-right: 10px;
-                }
-            }
-        }
-        &.map-content {
-            margin-top: 12px;
-        }
-        &.prescription-content {
-            padding: 12px;
-        }
-    }
-
-    .usage-mode-wrap {
-        padding: 0 12px;
-        margin-top: 12px;
-        .info-content {
-            padding-top: 14px;
-            padding-bottom: 1px;
-        }
-
-        .el-form-item--default {
-            margin-bottom: 0;
-        }
-    }
-
-    ::v-deep {
-        .el-form-item__label {
-            height: 30px;
-            line-height: 30px;
-            color: rgba(0, 0, 0, 0.4);
-        }
-        .el-form-item.is-required:not(.is-no-asterisk).asterisk-left>.el-form-item__label:before {
-            display: none;
-        }
-    }
-    .info-content {
-        padding: 10px 0;
-        position: relative;
-
-        .condition-wrap {
-            display: flex;
-            align-items: center;
-            width: 100%;
-            .symbol {
-                width: 10px;
-                // text-align: center;
-                // padding: 0 4px;
-            }
-        }
-        .item-input {
-            // width: 60%;
-            min-width: 140px;
-            max-width: 240px;
-        }
-        .recheck-text {
-            padding-left: 6px;
-        }
-        .info-item {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            width: 100%;
-        }
-        .info-item + .info-item {
-            margin-top: 12px;
-        }
-
-        .bottom-map {
-            width: 100%;
-            height: 250px;
-            clip-path: inset(0px round 8px);
-        }
-        .check-btn {
-            position: absolute;
-            bottom: 16px;
-            right: 6px;
-            background: rgba(0, 0, 0, 0.6);
-            padding: 0 8px;
-            border-radius: 8px;
-
-            ::v-deep {
-                .el-checkbox {
-                    color: #fff;
-                }
-            }
-        }
-        .area-select {
-            padding-bottom: 12px;
-            .block {
-                width: 12px;
-                display: inline-block;
-            }
-        }
-    }
-
-    ::v-deep {
-        .el-form-item--default {
-            margin-bottom: 8px;
-            &.text-item {
-                margin-bottom: 2px;
-                .el-form-item__content {
-                    line-height: 24px;
-                }
-                .el-form-item__label {
-                    height: 24px;
-                    line-height: 24px;
-                }
-            }
-        }
-    }
-    .sub-title {
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        color: rgba(0, 0, 0, 0.6);
-        font-size: 14px;
-        .add-tag {
-            font-size: 12px;
-            color: #2199f8;
-            padding: 0 8px;
-            border: 1px solid #2199F8;
-            border-radius: 5px;
-            font-weight: normal;
-            height: 28px;
-            line-height: 28px;
-        }
-    }
-    .recipe-item {
-        width: 100%;
-        .recipe-form {
-            padding-top: 8px;
-            ::v-deep {
-                .el-form-item {
-                    &:last-child {
-                        margin-bottom: 0;
-                    }
-                }
-            }
-        }
-
-        .box-item {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            color: rgba(0, 0, 0, 0.4);
-            .r-text {
-                width: 140px;
-                text-align: center;
-            }
-            .form-r {
-                width: 60%;
-                min-width: 140px;
-                max-width: 240px;
-            }
-        }
-        .form-box {
-            border: 1px solid rgba(33, 153, 248, 0.8);
-            border-radius: 8px;
-            padding: 20px 10px;
-            width: 100%;
-            position: relative;
-            // background: rgb(209, 235, 255, 0.3);
-            // margin-bottom: 12px;
-            .form-index {
-                position: absolute;
-                left: 0;
-                top: 0;
-                padding: 0 6px;
-                background: #2199F8;
-                border-radius: 4px 0 4px 0;
-                height: 18px;
-                line-height: 18px;
-                font-size: 12px;
-                color: #fff;
-            }
-            .input-box {
-                &.mark-box {
-                    padding: 8px 0 12px 0;
-                }
-            }
-
-            
-            // .input-unit {
-            //     ::v-deep {
-            //         .el-input {
-            //             border: 1px solid #dcdfe6;
-            //             border-radius: 5px;
-            //             height: 32px;
-            //             box-sizing: border-box;
-            //         }
-            //         .el-input__wrapper {
-            //             padding: 0 2px 0 10px;
-            //             height: 30px;
-            //             line-height: 30px;
-            //             min-height: 30px;
-            //             box-shadow: none;
-            //         }
-            //         .el-input__inner {
-            //             --el-input-inner-height: 30px;
-            //             height: 30px;
-            //             line-height: 30px;
-            //             min-height: 30px;
-            //             color: #606266;
-            //             --el-input-placeholder-color: #a8abb2;
-            //         }
-            //         .el-input-group__append {
-            //             box-shadow: none;
-            //             border: none;
-            //             background: none;
-            //         }
-            //     }
-            // }
-            .text-center {
-                ::v-deep {
-                    .el-input__inner {
-                        text-align: center;
-                    }
-                }
-            }
-            .action-btn {
-                display: flex;
-                justify-content: flex-end;
-                .btn {
-                    color: #8F8F8F;
-                    border-radius: 25px;
-                    padding: 5px 30px;
-                }
-                .delete-btn {
-                    color: rgba(255, 89, 89, 0.9);
-                    background: #fff;
-                    border: 1px solid rgba(255, 89, 89, 0.9);
-                }
-            }
-            .btn-group {
-                padding-top: 12px;
-            }
-            .sub-item {
-                padding-left: 10px;
-                .has-sub {
-                    display: flex;
-                    flex-direction: column;
-                    align-items: center;
-                    .main-name {
-                        line-height: 20px;
-                    }
-                    .sub-name {
-                        font-size: 10px;
-                        color: rgba(129, 129, 129, 0.5);
-                        line-height: 14px;
-                    }
-                }
-                .colunm-sub {
-                    display: flex;
-                    align-items: center;
-                    .sub-name {
-                        font-size: 10px;
-                        color: rgba(129, 129, 129, 0.5);
-                    }
-                }
-                .r-text {
-                    width: 132px;
-                    text-align: center;
-                    font-size: 14px;
-                    color: #474747;
-                }
-                .price {
-                    ::v-deep {
-                        .el-input__wrapper {
-                            box-shadow: 0 0 0 1px rgba(33, 153, 248, 0.3) inset;
-                        }
-                        .el-input__inner {
-                            color: #2199f8;
-                        }
-                    }
-                }
-            }
-            .form-title {
-                font-size: 14px;
-                padding-top: 6px;
-                color: #000;
-                font-weight: 600;
-            }
-            .box-item + .box-item {
-                margin-top: 8px;
-            }
-        }
-        .form-box + .form-box {
-            margin-top: 8px;
-        }
-        .usageMode-wrap {
-            padding-top: 8px;
-        }
-    }
-    
-    // 状况描述样式
-    .situation-description {
-        width: 100%;
-        .description-title {
-            font-size: 16px;
-            font-weight: bold;
-            color: #000;
-            margin-bottom: 12px;
-        }
-        
-        .description-content {
-            .description-textarea {
-                margin-bottom: 10px;
-                width: 100%;
-            }
-            
-            .upload-section {
-                .upload-btn {
-                    width: 112px;
-                    height: 32px;
-                    border-radius: 3px;
-                    border: 1px solid #e0e0e0;
-                    background: #fff;
-                    color: #000;
-                    font-size: 14px;
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    margin-bottom: 8px;
-                    
-                    .el-icon {
-                        margin-right: 6px;
-                    }
-                }
-                
-                .upload-tip {
-                    font-size: 12px;
-                    color: #999;
-                    line-height: 1.4;
-                }
-            }
-        }
-    }
-    
-    // 专家诊断按钮样式
-    .expert-diagnosis-btn {
-        width: 180px;
-        height: 40px;
-        border-radius: 24px;
-        background: linear-gradient(180deg, #70BFFE 0%, #2199F8 100%);
-        color: #FFFFFF;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        margin: 30px auto 0;
-    }
-}
-.task-tips-popup {
-    width: 75%;
-    padding: 28px 28px 20px;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    .create-farm-icon{
-        width: 40px;
-        height: 40px;
-        margin-bottom: 12px;
-    }
-    .farm-check-icon{
-        width: 68px;
-        height: 68px;
-        margin-bottom: 12px;
-    }
-    .create-farm-text{
-        font-size: 20px;
-        font-weight: 500;
-        line-height: 40px;
-        margin-bottom: 32px;
-        text-align: center;
-        &.success-text{
-            font-size: 24px;
-            font-weight: 500;
-        }
-    }
-    .main-text {
-        color: #2199F8;
-    }
-    .create-farm-btn{
-        width: 100%;
-        box-sizing: border-box;
-        padding: 8px;
-        border-radius: 25px;
-        font-size: 16px;
-        background: #2199F8;
-        color: #fff;
-        text-align: center;
-    }
-}
-</style>

+ 0 - 197
src/views/old_mini/user/subPages/cropRecord.vue

@@ -1,197 +0,0 @@
-<template>
-    <div class="crop-record-page">
-        <custom-header name="作物档案"></custom-header>
-        <div class="farm-work-timeline">
-            <div class="farm-work-item" v-for="(item, index) in farmWorkData" :key="index">
-                <div class="timeline-left">
-                    <div class="timeline-dot"></div>
-                    <div class="timeline-line"></div>
-                </div>
-                <div class="timeline-right">
-                    <div class="farm-work-card" :class="['card-' + getRecordTypeText(item.speakTitleName), {'is-future': item.isFuture}]">
-                        <div class="type-box">{{ item.speakTitleName }}</div>
-                        <div class="farm-work-date" v-html="item.content.renderedContent"></div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import CustomHeader from "@/components/customHeader.vue";
-import { ref, onMounted } from "vue";
-import { useRoute } from "vue-router";
-
-const route = useRoute();
-const cropRecordList = ref([]);
-
-onMounted(() => {
-    getFarmWorkList();
-});
-
-const farmWorkData = ref([]);
-const typeObj = {
-    物候: "1",
-    异常: "2",
-    病虫: "3",
-    农事: "4",
-};
-
-const getRecordTypeText = (recordType) => {
-    return typeObj[recordType];
-};
-const getFarmWorkList = () => {
-    VE_API.container_phenology.getFarmSpeakInfo({ farmId: route.query.farmId }).then(({ data }) => {
-        const res = data.filter((item) => item.content.hasException !== 0);
-        farmWorkData.value = res || [];
-        getPhenologyBroadcast();
-    });
-};
-
-const getPhenologyBroadcast = () => {
-    VE_API.container_phenology.phenologyBroadcast({ farmId: 93954 }).then(({ data }) => {
-        farmWorkData.value.push({
-            speakTitleName: "物候",
-            isFuture: true,
-            content: {
-                renderedContent: data.content,
-            },
-        });
-    });
-};
-</script>
-
-<style lang="scss" scoped>
-.crop-record-page {
-    width: 100%;
-    min-height: 100vh;
-    background: #f5f7fb;
-
-    .farm-work-timeline {
-        padding: 12px;
-        height: calc(100% - 40px);
-        .farm-work-item {
-            display: flex;
-            align-items: flex-start;
-            position: relative;
-            &:not(:last-child) {
-                margin-bottom: 20px;
-            }
-            .timeline-left {
-                display: flex;
-                flex-direction: column;
-                align-items: center;
-                margin-right: 12px;
-                position: relative;
-                .timeline-dot {
-                    width: 6px;
-                    height: 6px;
-                    border-radius: 50%;
-                    border: 1px solid #2199f8;
-                    flex-shrink: 0;
-                    z-index: 1;
-                }
-                .timeline-line {
-                    width: 1px;
-                    height: 48px;
-                    background: #e5e6eb;
-                    position: absolute;
-                    top: 8px;
-                }
-            }
-            .timeline-right {
-                flex: 1;
-                .farm-work-card {
-                    border: 1px solid #8bccff;
-                    border-radius: 4px;
-                    background: #f8fcff;
-                    padding: 12px;
-                    display: flex;
-                    align-items: center;
-                    color: #1d2129;
-                    font-size: 14px;
-                    line-height: 22px;
-                    display: flex;
-                    align-items: center;
-                    &.card-1 {
-                        border: 1px solid #8bccff;
-                        .type-box {
-                            background: #2199f8;
-                        }
-                        .farm-work-content {
-                            color: #2199f8;
-                        }
-                    }
-                    &.card-4 {
-                        border: 1px solid #ffbb83;
-                        .type-box {
-                            background: #ff953d;
-                        }
-                        .farm-work-content {
-                            color: #ff953d;
-                        }
-                    }
-                    &.card-2,
-                    &.card-3 {
-                        border: 1px solid #ff9c9c;
-                        .type-box {
-                            background: #fd7676;
-                        }
-                        .farm-work-content {
-                            color: #fd7676;
-                        }
-                    }
-                    &.is-future {
-                        padding: 0 12px;
-                        // opacity: 0.5;
-                        background: rgba(246, 250, 255, 0.5);
-                        .type-box {
-                            background: rgba(33, 153, 248, 0.5);
-                        }
-                        .farm-work-content {
-                            color: rgba(29, 33, 41, 0.5);
-                        }
-                    }
-                    .type-box {
-                        margin-right: 12px;
-                        padding: 0 5px;
-                        height: 20px;
-                        line-height: 20px;
-                        flex: none;
-                        font-size: 12px;
-                        color: #fff;
-                        border-radius: 0 4px 0 4px;
-                    }
-                    .farm-work-date {
-                        padding-right: 4px;
-                        &.is-future {
-                            // color: rgba(29, 33, 41, 0.5);
-                        }
-                    }
-                    .farm-work-desc {
-                        .farm-work-action {
-                            padding-right: 4px;
-                        }
-                        .farm-work-content {
-                            padding-right: 4px;
-                        }
-                    }
-                }
-            }
-            &.is-estimated {
-                .timeline-right {
-                    .farm-work-card {
-                        background: rgba(246, 250, 255, 0.5);
-                        border: 1px solid rgba(190, 218, 255, 0.5);
-                        .farm-work-date,
-                        .farm-work-desc {
-                            color: rgba(29, 33, 41, 0.5);
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-</style>

+ 15 - 15
src/views/old_mini/weather_detail/index.vue

@@ -19,6 +19,19 @@
       </div>
     </div>
 
+    <!-- 指标 Tab -->
+    <div class="tab-row">
+    <div
+        v-for="tab in tabs"
+        :key="tab.key"
+        class="tab-item"
+        :class="{ active: currentTab === tab.key }"
+        @click="currentTab = tab.key"
+    >
+        {{ tab.label }}
+    </div>
+    </div>
+
     <div class="weather-chart-container">
         <div class="weather-chart-wrapper">
             <div 
@@ -53,19 +66,6 @@
         </div>
     </div>
 
-    <!-- 指标 Tab -->
-    <div class="tab-row">
-      <div
-        v-for="tab in tabs"
-        :key="tab.key"
-        class="tab-item"
-        :class="{ active: currentTab === tab.key }"
-        @click="currentTab = tab.key"
-      >
-        {{ tab.label }}
-      </div>
-    </div>
-
     <!-- 风险列表 -->
     <div class="risk-list">
       <div
@@ -198,7 +198,6 @@ function getWeatherData() {
   background: #ffffff;
   border-radius: 8px;
   box-shadow: 0 2px 8px rgba(15, 35, 52, 0.06);
-  margin-bottom: 10px;
 
   .farm-left {
     flex: 1;
@@ -213,7 +212,7 @@ function getWeatherData() {
 
     .farm-name {
       font-size: 16px;
-      font-weight: 600;
+      font-weight: 500;
       color: #1d2129;
     }
 
@@ -249,6 +248,7 @@ function getWeatherData() {
   padding: 10px;
   box-shadow: 0 2px 8px rgba(15, 35, 52, 0.06);
   overflow: hidden;
+  margin-bottom: 10px;
 
   .weather-chart-wrapper {
     width: 100%;