Procházet zdrojové kódy

delete:删除没有用到的文件

wangsisi před 7 hodinami
rodič
revize
9495a8c459

+ 0 - 45
src/router/globalRoutes.js

@@ -12,12 +12,6 @@ export default [
         name: "dev_login",
         component: () => import("@/views/old_mini/dev_login.vue"),
     },
-    {
-        path: "/monitor",
-        name: "Monitor",
-        meta: { showTabbar: true, keepAlive: true },
-        component: () => import("@/views/old_mini/monitor/index.vue"),
-    },
     // 创建农场
     {
         path: "/create_farm",
@@ -46,25 +40,6 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/chat_frame/index.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",
-        meta: { keepAlive: true },
-        component: () => import("@/views/old_mini/monitor/subPages/agriculturalDetail.vue"),
-    },
     // 成果报告
     {
         path: "/achievement_report",
@@ -126,26 +101,6 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/interactionList/confirmArea.vue"),
     },
-    // 农场信息
-    {
-        path: "/farm_info",
-        name: "FarmInfo",
-        component: () => import("@/views/old_mini/monitor/subPages/farmInfo.vue"),
-    },
-    // 勾画区域
-    {
-        path: "/draw_area",
-        name: "DrawArea",
-        meta: { keepAlive: true },
-        component: () => import("@/views/old_mini/monitor/subPages/darwArea.vue"),
-    },
-    // 农情互动
-    {
-        path: "/interaction",
-        name: "Interaction",
-        meta: { keepAlive: true },
-        component: () => import("@/views/old_mini/interaction/index.vue"),
-    },
     //有味溯源
     {
         path: "/youwei_trace",

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

@@ -1,785 +0,0 @@
-<template>
-    <div class="interaction-page">
-        <custom-header :name="$t('农情互动')" bgColor="#f2f4f5" />
-        <div class="interaction-content">
-            <!-- 顶部说明 -->
-            <div class="intro-card">
-                完善作物品种以及物候信息,精准匹配种植方案,实现精细化管理
-            </div>
-
-            <!-- 作物块(每个农场一块) -->
-            <div v-for="(crop, cropIndex) in farmData.farms" :key="cropIndex" class="crop-section">
-                <div class="crop-header">
-                    <div class="crop-tag">{{ crop.speciesName }}</div>
-                    <div class="add-btn" v-if="farmData.status === 'INIT' || isAddVariety" @click="addVariety(crop)">+
-                        新增品种</div>
-                </div>
-
-                <div v-for="(region, regionIndex) in crop.regions" :key="regionIndex" class="variety-card">
-                    <div class="field-row">
-                        <div class="field-value variety-select-wrap" v-if="farmData.status === 'INIT' || isAddVariety">
-                            <el-select filterable v-model="region.regionId" class="variety-input" :placeholder="$t('选择品种')">
-                                <el-option v-for="(item, index) in crop.typeIdItems" :key="index" :label="item.name"
-                                    :value="item.id"
-                                    :disabled="isVarietyOptionDisabled(crop, region, item.id) || item.selected === 1" />
-                                <!-- <template #footer>
-                                    <el-button text bg @click="onAddOption(region)">
-                                        + 增加品种
-                                    </el-button>
-                                </template> -->
-                            </el-select>
-                            <div
-                                v-if="regionIndex > 0"
-                                class="delete-variety-btn"
-                                @click="removeVariety(crop, regionIndex)"
-                            >
-                                <el-icon><Delete /></el-icon>
-                            </div>
-                        </div>
-                        <div class="tag-val" v-else>
-                            {{ region.regionName }}
-                        </div>
-                    </div>
-
-                    <div class="field-row">
-                        <div class="field-label">{{ $t('当下物候期') }}</div>
-                        <div class="field-value">
-                            <el-select
-                            v-model="region.phenologyId" @change="handlePhenologyChange(crop, region)" class="select-input" :placeholder="$t('选择物候期')">
-                                <el-option v-for="(item, index) in crop.phenologyOptions" :key="index"
-                                    :label="item.phenologyName" :value="item.phenologyId" />
-                            </el-select>
-                        </div>
-                    </div>
-
-                    <div class="field-row" v-if="region.phenologyId">
-                        <div class="field-label">{{ getPhenologyLabel(crop, region.phenologyId) }}</div>
-                        <div class="field-value">
-                            <el-date-picker
-                                :editable="false"
-                                style="width: 100%"
-                                v-model="region.phenologyStartDate"
-                                class="date-picker"
-                                type="date"
-                                :placeholder="$t('选择时间')"
-                                format="YYYY-MM-DD"
-                                value-format="YYYY-MM-DD"
-                                :disabled-date="(time) => disabledFutureDate(time, crop, region)"
-                            />
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-
-        <!-- 底部按钮 -->
-        <div class="fixed-btn-wrap">
-            <el-button class="fixed-btn" :loading="loading" @click="handleConfirm">
-                确认信息
-            </el-button>
-        </div>
-    </div>
-
-    <tip-popup v-model:show="showTipPopup" type="success" :text="$t('您的农情报告已生成')" text2="请查看" buttonText="点击查看"
-        @confirm="handleTipConfirm" />
-
-
-    <popup class="add-tag-popup" :z-index="2500" round v-model:show="showAddPopup" @update:show="handlePopupClose">
-        <div class="tag-item">
-            <div class="popup-title">{{ $t('新增品种名称') }}</div>
-            <el-input autofocus class="popup-input" v-model="newVarietyName" :placeholder="$t('请输入品种名称')" size="large" />
-        </div>
-        <div class="popup-button">
-            <div class="cancel" @click="handleCancelAdd">{{ $t('取消') }}</div>
-            <div @click="handleAddVariety">{{ $t('确认') }}</div>
-        </div>
-    </popup>
-
-    <!-- 勾选区域引导弹窗 -->
-    <select-region-popup v-model:show="showSelectRegionPopup" :image="selectRegionImage" :title="selectRegionTitle"
-        sub-:title="$t('精准匹配农情信息,高效管理分区')" @confirm="handleGoSelectRegion" @skip="handleSkipSelectRegion" />
-</template>
-
-<script setup>
-import { ref, nextTick, onActivated, onDeactivated, onBeforeUnmount } from "vue";
-import { ElMessage } from "element-plus";
-import { Popup } from "vant";
-import customHeader from "@/components/customHeader.vue";
-import { useRoute, useRouter } from "vue-router";
-import tipPopup from "@/components/popup/tipPopup.vue";
-import selectRegionPopup from "@/components/popup/selectRegionPopup.vue";
-
-const router = useRouter();
-
-const route = useRoute();
-
-const isAddVariety = ref(false);
-const loading = ref(false);
-onActivated(() => {
-    isAddVariety.value = route.query.addVariety ? true : false;
-
-    if (isAddVariety.value) {
-        getFarmTypeIdAndPhenologyList();
-        // console.log("farmData", farmData.value);
-        return;
-    }
-    const subjectId = route.query.subjectId;
-    getPhenologyInitOrConfirmStatus(subjectId);
-});
-
-const farmData = ref({
-    farms: [],
-    status: "",
-})
-const getPhenologyInitOrConfirmStatus = async (subjectId) => {
-    const { data } = await VE_API.farm_v3.phenologyInitOrConfirmStatus({ subjectId });
-    farmData.value = data;
-    if (data.status === 'INIT') {
-        data.farms.forEach(item => {
-            addVariety(item);
-        });
-    } else {
-        // 大物候期确认
-        data.farms.forEach(item => {
-            item.regions.forEach(region => {
-                region.phenologyId = region.currentPhenologyId;
-                region.phenologyStartDate = region.currentPhenologyStartDate;
-            });
-        });
-    }
-    // console.log("farmData", farmData.value);
-}
-
-const getFarmTypeIdAndPhenologyList = async () => {
-    const { data } = await VE_API.farm_v3.farmTypeIdAndPhenologyList({ subjectId: route.query.subjectId });
-    // farmData.value.farms.forEach(item => {
-    //     item.phenologyOptions = data.phenologyOptions;
-    //     item.typeIdItems = data.typeIdItems;
-    // });
-
-
-    farmData.value.farms.push({
-        phenologyOptions: data[0].phenologyOptions,
-        typeIdItems: data[0].typeIdItems,
-        speciesId: data[0].speciesId,
-        farmId: data[0].farmId,
-        speciesName: data[0].speciesName,
-        regions: [
-            {
-                regionId: null,
-                phenologyId: null,
-                phenologyStartDate: "",
-            }
-        ]
-    });
-}
-
-const addVariety = (crop) => {
-    if (!Array.isArray(crop.regions)) {
-        crop.regions = [];
-    }
-    crop.regions.push({
-        regionId: null,
-        phenologyId: null,
-        phenologyStartDate: "",
-    });
-};
-
-// 同一作物下,已被其它行选择的品种不可重复选择
-const isVarietyOptionDisabled = (crop, currentRegion, optionId) => {
-    const optionKey = String(optionId);
-    return (crop?.regions || []).some((region) => {
-        if (region === currentRegion) return false;
-        if (!region?.regionId) return false;
-        return String(region.regionId) === optionKey;
-    });
-};
-
-// 第一项保留不可删,其余项可删
-const removeVariety = (crop, regionIndex) => {
-    if (!crop?.regions || regionIndex <= 0) return;
-    crop.regions.splice(regionIndex, 1);
-};
-
-// 获取物候期对应的时间标签
-const getPhenologyLabel = (farm, phenologyId) => {
-    if (!farm?.phenologyOptions) return "选择时间";
-    const found = farm.phenologyOptions.find(
-        (item) => item.id === phenologyId || item.phenologyId === phenologyId
-    );
-    return found?.startDateLabel || "选择时间";
-};
-
-const getStartDate = (farm, phenologyId) => {
-    if (!farm?.phenologyOptions) return "";
-    const found = farm.phenologyOptions.find(
-        (item) => item.id === phenologyId || item.phenologyId === phenologyId
-    );
-    return found?.startDate || "";
-};
-
-const handlePhenologyChange = (crop, region) => {
-    region.phenologyStartDate = getStartDate(crop, region.phenologyId);
-};
-
-// 禁用今天之后的日期;最早只能选到「该物候期默认开始时间」的前 3 个月
-// 如果没有物候期开始时间,则基于今天往前 3 个月
-const disabledFutureDate = (time, crop, region) => {
-    const today = new Date();
-    today.setHours(0, 0, 0, 0);
-
-    // 基准开始时间:物候期默认开始日期
-    const baseStartStr = getStartDate(crop, region.phenologyId);
-    const baseStart = baseStartStr ? new Date(baseStartStr) : null;
-
-    // 选择基准日期:有物候期开始时间则用它,否则用今天
-    const base = !baseStart || isNaN(baseStart.getTime()) ? new Date(today) : new Date(baseStart);
-    base.setHours(0, 0, 0, 0);
-
-    // 三个月前的同一天(基于 base)
-    const threeMonthsAgo = new Date(base);
-    threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
-
-    const t = time.getTime();
-    return t > today.getTime() || t < threeMonthsAgo.getTime();
-};
-
-const showTipPopup = ref(false);
-
-// 勾选区域引导弹窗相关
-const showSelectRegionPopup = ref(false);
-const selectRegionImage = ref("");
-const selectRegionTitle = ref("勾选 区域");
-
-const varietyItemData = ref(null);
-// 获取第一个选择的品种名称用于弹窗标题
-const getFirstSelectedVariety = () => {
-    for (const farm of farmData.value.farms) {
-        const selectedRegion = (farm.regions || []).find(
-            (r) => r.regionId && r.phenologyId && r.phenologyStartDate
-        );
-        if (selectedRegion) {
-            const varietyItem = (farm.typeIdItems || []).find(
-                (t) => String(t.id) === String(selectedRegion.regionId)
-            );
-            if (varietyItem?.name) {
-                varietyItemData.value = varietyItem;
-                return {
-                    name: varietyItem.name,
-                    id: varietyItem.id,
-                };
-            }
-        }
-    }
-    return "";
-};
-
-const handleConfirm = async () => {
-    // INIT / 新增品种:initFarmData;CONFIRM_REPRODUCTIVE:confirmReproductivePhenology(regionPhenologyItems,每条一个区域)
-    const status = farmData.value.status;
-    const isInitOrAddVariety = status === "INIT" || isAddVariety.value;
-
-    let farmDataList;
-    if (isInitOrAddVariety) {
-        farmDataList = farmData.value.farms
-            .map((farm) => {
-                const typeIdItems = (farm.regions || [])
-                    .filter(
-                        (r) =>
-                            r.regionId && r.phenologyId && r.phenologyStartDate
-                    )
-                    .map((r) => {
-                        const origin =
-                            (farm.typeIdItems || []).find(
-                                (t) => String(t.id) === String(r.regionId)
-                            ) || {};
-                        return {
-                            id: r.regionId,
-                            name: origin.name || "",
-                            phenologyId: r.phenologyId,
-                            phenologyStartDate: r.phenologyStartDate,
-                        };
-                    })
-                    .filter((item) => item.id);
-
-                return {
-                    farmId: farm.farmId,
-                    speciesId: farm.speciesId,
-                    typeIdItems,
-                };
-            })
-            .filter((item) => item.typeIdItems.length > 0);
-    } else {
-        // CONFIRM_REPRODUCTIVE:每个区域单独一条,字段 regionPhenologyItems
-        farmDataList = [];
-        for (const farm of farmData.value.farms) {
-            const validRegions = (farm.regions || []).filter(
-                (r) => r.regionId && r.phenologyId && r.phenologyStartDate
-            );
-            for (const r of validRegions) {
-                farmDataList.push({
-                    farmId: farm.farmId,
-                    regionPhenologyItems: [
-                        {
-                            regionId: r.regionId,
-                            phenologyId: r.phenologyId,
-                            phenologyStartDate: r.phenologyStartDate,
-                        },
-                    ],
-                });
-            }
-        }
-    }
-
-    if (!farmDataList.length) {
-        ElMessage.warning("请完善信息");
-        return;
-    }
-
-    loading.value = true;
-    const params = {
-        expertMiniUserId: 81881,
-        farmDataList,
-    };
-
-    const { code, msg } = await VE_API.farm_v3[
-        isInitOrAddVariety ? "initFarmData" : "confirmReproductivePhenology"
-    ](params);
-    if (code === 0) {
-        loading.value = false;
-        // 从点击新增品种进来的才需要勾选区域
-        if (isAddVariety.value) {
-            // 显示勾选区域引导弹窗
-            const variety = getFirstSelectedVariety();
-            if (variety) {
-                selectRegionTitle.value = `勾选 ${variety.name} 区域`;
-            }
-            showSelectRegionPopup.value = true;
-        } else {
-            showTipPopup.value = true;
-        }
-    } else {
-        loading.value = false;
-        ElMessage.error(msg || "提交失败");
-    }
-};
-
-const handleSkipSelectRegion = () => {
-    showSelectRegionPopup.value = false;
-    showTipPopup.value = true;
-};
-
-const handleGoSelectRegion = () => {
-    showSelectRegionPopup.value = false;
-    
-    const addVarietyCount = (farmData.value.farms || []).reduce((count, farm) => {
-            return count + ((farm?.regions || []).length || 0);
-        }, 0);
-    router.push({
-        path: "/draw_area",
-        query: {
-            targetUrl: "growth_report",
-            showTipPopup: "true",
-            subjectId: route.query.subjectId,
-            varietyId: varietyItemData.value.id,
-            addVarietyCount: addVarietyCount,
-        },
-    });
-};
-
-// 大物候期转换所需参数// 组装为后端所需的 farmDataList 结构
-// const farmDataList = farmData.value
-//     .map((farm) => {
-//         const regionPhenologyItems = (farm.regions || [])
-//             .filter(
-//                 (r) => r.regionId && r.phenologyId && r.phenologyStartDate
-//             )
-//             .map((r) => ({
-//                 regionId: r.regionId,
-//                 phenologyId: r.phenologyId,
-//                 phenologyStartDate: r.phenologyStartDate,
-//             }));
-
-//         return {
-//             farmId: farm.farmId,
-//             regionPhenologyItems,
-//         };
-//     })
-//     .filter((item) => item.regionPhenologyItems.length > 0);
-
-// console.log("farmDataList", farmDataList);
-
-// const params = {
-//     farmDataList,
-//     expertMiniUserId: 81881,
-// }
-// const {code, msg} = await VE_API.farm_v3.confirmReproductivePhenology(params);
-// if(code === 0) {
-//     qrCodePopupRef.value.showPopup();
-// } else {
-//     ElMessage.error(msg);
-// }
-
-const showAddPopup = ref(false);
-const newVarietyName = ref("");
-const currentVariety = ref(null); // 记录当前正在添加品种的 variety 对象
-
-const handleAddVariety = () => {
-    if (!newVarietyName.value.trim()) {
-        return;
-    }
-
-    // 如果当前有正在添加品种的 variety,则自动选中新增的品种
-    if (currentVariety.value) {
-        currentVariety.value.variety = newVarietyName.value;
-    }
-
-    newVarietyName.value = "";
-    showAddPopup.value = false;
-    currentVariety.value = null;
-}
-
-const onAddOption = async (region) => {
-    // 先关闭下拉菜单
-    if (document.activeElement) {
-        document.activeElement.blur();
-    }
-
-    // 等待下拉菜单关闭后再显示弹窗
-    await nextTick();
-
-    // 记录当前 region
-    currentVariety.value = region;
-    showAddPopup.value = true;
-}
-
-const handleCancelAdd = () => {
-    newVarietyName.value = "";
-    showAddPopup.value = false;
-    currentVariety.value = null;
-}
-
-const handlePopupClose = (show) => {
-    if (!show) {
-        // 弹窗关闭时清空状态
-        newVarietyName.value = "";
-        currentVariety.value = null;
-    }
-}
-
-const handleTipConfirm = () => {
-    const query = {
-        hideInteraction: "true",
-    };
-    if (isAddVariety.value) {
-        const addVarietyCount = (farmData.value.farms || []).reduce((count, farm) => {
-            return count + ((farm?.regions || []).length || 0);
-        }, 0);
-        query.addVarietyCount = String(addVarietyCount);
-    }
-    router.push({ path: "/growth_report", query });
-}
-
-// 离开页面/失活时清空本页状态,避免返回后数据复用导致异常
-const clearPageState = () => {
-    loading.value = false;
-    isAddVariety.value = false;
-    farmData.value = { farms: [], status: "" };
-
-    showTipPopup.value = false;
-    showSelectRegionPopup.value = false;
-    selectRegionImage.value = "";
-    selectRegionTitle.value = "勾选 区域";
-
-    newVarietyName.value = "";
-    currentVariety.value = null;
-    // 清空当前下拉记录,避免返回后仍处在“添加品种”上下文
-    // 如果后续你给 currentVariety.variety 赋值,也会随 currentVariety 置空一起释放
-};
-
-onDeactivated(() => {
-    clearPageState();
-});
-
-onBeforeUnmount(() => {
-    clearPageState();
-});
-</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: 12px 10px 90px 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;
-}
-
-.variety-select-wrap {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    gap: 10px;
-}
-
-.delete-variety-btn {
-    color: #ff4d4f;
-    font-size: 16px;
-    cursor: pointer;
-    user-select: none;
-}
-
-.tag-val {
-    background: rgba(33, 153, 248, 0.1);
-    color: #2199F8;
-    border-radius: 2px;
-    padding: 0 10px;
-    width: fit-content;
-    height: 26px;
-    line-height: 26px;
-    box-sizing: border-box;
-}
-
-.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;
-    }
-}
-
-
-.fixed-btn-wrap {
-    display: flex;
-    justify-content: center;
-    position: fixed;
-    bottom: 0px;
-    left: 0;
-    right: 0;
-    background: #fff;
-    padding: 10px 12px 36px 12px;
-    box-sizing: border-box;
-    // box-shadow: 0 -2px 8px rgba(15, 35, 52, 0.06);
-    box-shadow: 2px 2px 4.5px 0px #00000066;
-
-    .fixed-btn {
-        min-width: 110px;
-        height: 40px;
-        padding: 0 30px;
-        line-height: 40px;
-        text-align: center;
-        border-radius: 20px;
-        background: linear-gradient(180deg, #70bffe, #2199f8);
-        color: #ffffff;
-        font-size: 14px;
-    }
-}
-
-.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;
-}
-
-.success-text {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    font-size: 24px;
-    color: #000;
-
-    .success-icon {
-        width: 28px;
-        height: 28px;
-        margin-right: 5px;
-    }
-}
-
-
-.add-tag-popup {
-    width: 90%;
-    padding: 24px 16px 20px 16px;
-    background: linear-gradient(360deg, #FFFFFF 74.2%, #D1EBFF 100%);
-
-    .popup-title {
-        font-size: 16px;
-        font-weight: 400;
-        margin-bottom: 12px;
-        color: #000000;
-
-        .name-text {
-            font-weight: 500;
-            color: #2199F8;
-            padding: 0 2px;
-        }
-    }
-
-    .ml-2 {
-        margin-left: 3px;
-    }
-
-    .popup-input {
-        margin-bottom: 24px;
-    }
-
-    .popup-button {
-        display: flex;
-
-        div {
-            flex: 1;
-            font-size: 16px;
-            padding: 9px;
-            border-radius: 20px;
-            background: #2199F8;
-            color: #fff;
-            text-align: center;
-            cursor: pointer;
-        }
-
-        .cancel {
-            margin-right: 13px;
-            color: #000;
-            background: #fff;
-            border: 1px solid #999999;
-        }
-
-        .delete {
-            margin-right: 13px;
-            color: #FF3D3D;
-            background: #fff;
-            border: 1px solid rgba(255, 61, 61, 0.4);
-        }
-    }
-}
-</style>

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

@@ -1,450 +0,0 @@
-<template>
-    <custom-header v-if="isHeaderShow" :name="$t('农场详情')"></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" from="monitor" class="weather-info" @weatherExpanded="weatherExpanded"
-            @changeGarden="changeGarden" @changeGardenTab="changeGardenTab" :isGarden="true"
-            :gardenId="defaultGardenId"></weather-info>
-        <!-- 农场列表 -->
-        <div v-show="activeGardenTab === 'list'">
-            <garden-list ref="gardenListRef" :garden-id="selectedGardenId" @loaded="handleGardenLoaded"
-                @selectGarden="handleGardenSelected" />
-        </div>
-        <!-- 作物档案 -->
-        <div class="archives-time-line" :class="{ 'no-top': !varietyTabs.length && !gardenId }" v-show="activeGardenTab === 'current'">
-            <div class="archives-time-line-header">
-                <div class="line-title">{{ $t('农情档案') }}</div>
-                <div class="header-right">
-                    <div class="add-variety-btn" v-if="varietyTabs.length > 0" @click="handleAddVariety">
-                        <span>{{ $t('分区管理') }}</span>
-                    </div>
-                    <el-date-picker
-                        style="width: 100px"
-                        :editable="false"
-                        v-model="date"
-                        type="year"
-                        :placeholder="$t('全部日期')"
-                        :disabled-date="disabledYearDate"
-                    />
-                </div>
-            </div>
-            <!-- 品种选择 -->
-            <div class="category-tabs tabs-list" v-if="farmsCategoryList.length > 0">
-                <div v-for="(v, index) in farmsCategoryList" :key="index" class="item-tab"
-                    :class="{ 'item-tab--active': activeFarmsCategory === v.speciesId }" @click="handleFarmsCategoryClick(v, index)">
-                    {{ v.speciesName }}
-                </div>
-            </div>
-            <div class="variety-tabs tabs-list" v-if="varietyTabs.length > 0">
-                <div v-for="(v, index) in varietyTabs" :key="index" class="item-tab"
-                    :class="{ 'item-tab--active': activeVariety === index }" @click="handleVarietyClick(v, index)">
-                    {{ v.regionName }}
-                </div>
-            </div>
-            <template v-if="!varietyTabs.length">
-                <div class="lock-img" @click="handleLockClick">
-                    <img src="@/assets/img/home/lock-blue.png" alt="" class="lock-img-item" />
-                    <div class="lock-text">
-                        专属数字农场,种好卖好
-                        <div>{{ $t('点击解锁一键溯源增产') }}</div>
-                    </div>
-                    <div class="lock-btn">{{ $t('点击解锁') }}</div>
-                </div>
-                <img class="example-img" src="@/assets/img/monitor/example.png" alt="">
-            </template>
-            <div class="archives-time-line-content">
-                <div class="time-line">
-                    <archives-farm-time-line :farmId="farmIdData" @card-click="handleCardClick"></archives-farm-time-line>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <!-- 勾选区域引导弹窗 -->
-    <select-region-popup v-model:show="showSelectRegionPopup" :title="titlePopup" @confirm="handleGoSelectRegion"
-        @skip="handleSkipSelectRegion" />
-
-    <!-- 农事执行弹窗(勾选区域引导弹窗显示时不展示) -->
-    <agri-execute-popup v-if="!showSelectRegionPopup" ref="agriExecutePopupRef" />
-
-    <start-interact-popup ref="startInteractPopupRef" />
-</template>
-
-<script setup>
-import { ref, computed, onActivated, onMounted } from "vue";
-import customHeader from "@/components/customHeader.vue";
-import { useStore } from "vuex";
-import wx from "weixin-js-sdk";
-import weatherInfo from "@/components/weatherInfo.vue";
-import { useRouter, useRoute } from "vue-router";
-import selectRegionPopup from "@/components/popup/selectRegionPopup.vue";
-import ArchivesFarmTimeLine from "@/components/pageComponents/ArchivesFarmTimeLine.vue";
-import agriExecutePopup from "@/components/popup/agriExecutePopup.vue";
-import startInteractPopup from "@/components/popup/startInteractPopup.vue";
-import gardenList from "@/components/gardenList.vue";
-
-const startInteractPopupRef = ref(null);
-
-const agriExecutePopupRef = ref(null);
-
-// 品种选择(作物档案内)- 根据主体ID动态获取分区列表
-const varietyTabs = ref([]);
-const activeVariety = ref(0);
-
-const getVarietyTabs = async (isShowPopup = true) => {
-    if (!gardenId.value) {
-        return;
-    }
-    try {
-        const res = await VE_API.basic_farm.fetchProblemZoneList({
-            subjectId: gardenId.value,
-        });
-        varietyTabs.value = res.data?.regionList || []
-        if (varietyTabs.value.length > 0) {
-            handleVarietyClick(varietyTabs.value[activeVariety.value || 0], activeVariety.value || 0)
-            if (isShowPopup && !showSelectRegionPopup.value && agriExecutePopupRef.value) {
-                agriExecutePopupRef.value.showPopup(varietyTabs.value[activeVariety.value || 0].farmId);
-            }
-        }
-    } catch (error) {
-        console.error("获取主体分区列表失败:", error);
-    }
-};
-
-const farmIdData = ref(null);
-const titlePopup = ref("");
-const currentVariety = ref({});
-const handleVarietyClick = (tab, index) => {
-    activeVariety.value = index;
-    if (tab.regionId) {
-        farmIdData.value = tab.farmId;
-    }
-    currentVariety.value = tab;
-    if (tab.lastViewTime == null && tab.regionId) {
-        titlePopup.value = `勾选 ${tab.regionName} 区域`;
-        showSelectRegionPopup.value = true;
-        VE_API.basic_farm.updateLastViewTime({
-            regionId: tab.regionId,
-        }).then(() => {
-            getVarietyTabs(false);
-        });
-    }
-};
-
-const date = ref(new Date());
-const disabledYearDate = (time) => {
-    const year = time.getFullYear();
-    const currentYear = new Date().getFullYear();
-    return year !== currentYear && year !== currentYear - 1;
-};
-
-const showSelectRegionPopup = ref(false);
-
-const handleAddVariety = () => {
-    router.push(`/draw_area?subjectId=${gardenId.value}&type=viewOnly`);
-};
-
-const handleSkipSelectRegion = () => {
-    showSelectRegionPopup.value = false;
-};
-
-const handleGoSelectRegion = () => {
-    showSelectRegionPopup.value = false;
-    router.push({
-        path: "/draw_area",
-        query: {
-            subjectId: gardenId.value,
-            varietyId: currentVariety.value.typeId
-        },
-    });
-};
-
-const defaultGardenId = ref(null);
-const selectedGardenId = ref(null);
-const gardenListRef = ref(null);
-const activeGardenTab = ref('current');
-const changeGardenTab = (tab) => {
-    activeGardenTab.value = tab;
-};
-
-const handleGardenLoaded = ({ hasFarm }) => {
-    weatherInfoRef.value?.setGardenLoaded?.(hasFarm);
-};
-
-const handleGardenSelected = (garden) => {
-    selectedGardenId.value = garden?.id ?? null;
-    weatherInfoRef.value?.setSelectedGarden?.(garden);
-};
-
-const isHeaderShow = ref(false);
-const weatherInfoRef = ref(null);
-onActivated(() => {
-    sessionStorage.removeItem('interactionListScrollTop');
-    // 用来接收我的农场跳转过来的农场详情逻辑
-    if (route.query.isHeaderShow) {
-        isHeaderShow.value = true;
-        defaultGardenId.value = route.query.farmId;
-    }
-    const savedFarmId = localStorage.getItem("selectedFarmId");
-    selectedGardenId.value = savedFarmId ? Number(savedFarmId) : null;
-    gardenListRef.value?.refreshFarmList?.();
-});
-
-const store = useStore();
-const tabBarHeight = computed(() => store.state.home.tabBarHeight);
-const router = useRouter();
-const route = useRoute();
-
-const userInfo = localStorage.getItem("localUserInfo");
-const userInfoObj = userInfo ? JSON.parse(userInfo) : {};
-const handleLockClick = () => {
-    if (gardenId.value) {
-        router.push("/interaction?subjectId=" + localStorage.getItem("selectedFarmId"));
-        return;
-    }
-    if (userInfoObj?.tel) {
-        router.push(`/create_farm?from=growth_report&isReload=true`);
-        return;
-    }
-    wx.miniProgram.navigateTo({
-        url: '/pages/subPages/phone_auth/index',
-    });
-}
-
-
-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);
-
-const farmsCategoryList = ref([]);
-const activeFarmsCategory = ref(null);
-const getListFarmsBySubjectId = async () => {
-    const res = await VE_API.monitor.listFarmsBySubjectId({
-        subjectId: gardenId.value,
-    });
-    farmsCategoryList.value = res.data || [];
-    if(farmsCategoryList.value.length > 0){
-        activeFarmsCategory.value = res.data[0].speciesId;
-    }
-}
-
-const handleFarmsCategoryClick = (tab, index) => {
-    activeFarmsCategory.value = tab.speciesId;
-}
-
-const changeGarden = ({ id }) => {
-    gardenId.value = id;
-    if(sessionStorage.getItem('activeVariety')){
-        activeVariety.value = Number(sessionStorage.getItem('activeVariety'));
-        sessionStorage.removeItem('activeVariety');
-    } else {
-        activeVariety.value = 0;
-    }
-    // 更新 store 中的状态
-    store.commit("home/SET_GARDEN_ID", id);
-    getVarietyTabs();
-    getListFarmsBySubjectId(); 
-
-    startInteractPopupRef.value.getPhenologyInitOrConfirmStatus();
-};
-
-const handleCardClick = () => {
-    sessionStorage.setItem('activeVariety', activeVariety.value);
-}
-
-</script>
-
-<style scoped lang="scss">
-.monitor-index {
-    width: 100%;
-    height: 100%;
-    // padding: 13px 10px;
-    box-sizing: border-box;
-    background: linear-gradient(180deg, #2199F8 6%, #F5F5F5 19%, #F5F5F5 73%, #F5F5F5 100%);
-    .weather-mask {
-        position: fixed;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        background-color: rgba(0, 0, 0, 0.52);
-        z-index: 11;
-    }
-
-    .lock-img {
-        position: fixed;
-        z-index: 10;
-        top: 50%;
-        left: 50%;
-        transform: translate(-50%, -20%);
-        width: 100%;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        flex-direction: column;
-        gap: 16px;
-
-        .lock-img-item {
-            width: 57px;
-        }
-
-        .lock-text {
-            font-size: 14px;
-            color: #000;
-            padding: 5px 64px;
-            line-height: 21px;
-            background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #FFFFFF 50%, rgba(255, 255, 255, 0) 100%);
-        }
-
-        .lock-btn {
-            width: 140px;
-            height: 40px;
-            line-height: 40px;
-            text-align: center;
-            background: linear-gradient(180deg, #76C3FF 0%, #2199F8 100%);
-            border-radius: 25px;
-            color: #fff;
-            font-size: 16px;
-        }
-    }
-
-    .example-img {
-        width: 100%;
-        height: 100%;
-        object-fit: inherit;
-    }
-
-    .weather-info {
-        width: calc(100% - 20px);
-        position: absolute;
-        top: 10px;
-        left: 10px;
-        z-index: 12;
-    }
-
-    .archives-time-line {
-        position: relative;
-        padding: 150px 12px 12px 12px;
-        height: calc(100% - 158px);
-        display: flex;
-        flex-direction: column;
-        min-height: 0;
-        &.no-top {
-            padding: 96px 12px 12px 12px;
-        }
-
-        .archives-time-line-header {
-            flex-shrink: 0;
-            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;
-                }
-            }
-
-            .header-right {
-                display: flex;
-                align-items: center;
-                gap: 12px;
-
-                .add-variety-btn {
-                    display: flex;
-                    align-items: center;
-                    gap: 3px;
-                    padding: 4px 10px;
-                    border: 1px solid #2199F8;
-                    border-radius: 2px;
-                    color: #2199F8;
-                    background: rgba(33, 153, 248, 0.1);
-                }
-            }
-        }
-
-        .category-tabs{
-            margin: 10px 0 6px 0;
-        }
-
-        .tabs-list {
-            flex-shrink: 0;
-            display: grid;
-            grid-template-columns: repeat(4, 1fr);
-            gap: 8px;
-
-            .item-tab {
-                box-sizing: border-box;
-                padding: 4px;
-                border-radius: 2px;
-                color: #767676;
-                background: #fff;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                text-align: center;
-                word-break: break-word;
-                overflow-wrap: anywhere;
-            }
-
-            .item-tab--active {
-                background: #2199F8;
-                color: #ffffff;
-            }
-
-            &.variety-tabs{
-                padding: 5px 6px;
-                background: #ffffff;
-                .item-tab{
-                    background: #F6F6F6;
-                }
-                .item-tab--active {
-                    background: rgba(33, 153, 248, 0.1);
-                    color: #2199F8;
-                }
-            }        
-        }
-
-        .archives-time-line-content {
-            margin-top: 10px;
-            flex: 1;
-            min-height: 0;
-            background: #fff;
-            border-radius: 8px;
-            padding: 10px;
-            box-sizing: border-box;
-            display: flex;
-            flex-direction: column;
-
-            .time-line {
-                flex: 1;
-                min-height: 0;
-            }
-        }
-    }
-}
-</style>

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

@@ -1,286 +0,0 @@
-<template>
-    <div class="agricultural-detail">
-        <custom-header :name="$t('农事详情')"></custom-header>
-        <div class="detail-content">
-            <div class="card-wrap" v-if="route.query.title !== '气象风险'">
-                <div class="card-box photo-card">
-                    <div class="card-title">
-                        <span>{{ t('农情照片') }}</span>
-                        <span class="date">{{ imgInfo.samplingTime }}</span>
-                    </div>
-                    <div class="ratio-tip" :class="archiveColorObj[route.query.title]">
-                        <div class="title">{{ route.query.title }}</div>
-                        <span class="content van-ellipsis">{{ route.query.content }}</span>
-                    </div>
-                    <!-- <div class="location-tip">
-                        由于系统审核,某些照片拍摄位置与农场相差超 3 公里,请在农场现场使用水印相机重新拍摄上传,谢谢配合
-                    </div> -->
-                    <div class="photo-grid">
-                        <div v-for="(photo, index) in imgInfo.imageList" :key="photo.id" class="photo-item"
-                            @click="handlePhotoClick(index)">
-                            <img :src="photo.url" alt="农情照片" />
-                        </div>
-                    </div>
-                </div>
-                <div class="card-box region-card">
-                    <div class="card-title">{{ t('区域勾选') }}</div>
-                    <div class="map-container" ref="mapContainer"></div>
-                </div>
-            </div>
-            <div class="card-wrap" v-else>
-                <div class="card-box risk-card">
-                    <div class="card-title">
-                        <span>{{ t('农情详情') }}</span>
-                        <span class="date">2025.05.06</span>
-                    </div>
-                    <img class="risk-image" src="" alt="">
-                    <div class="risk-content">
-                        <p class="risk-highlight">
-                            <span class="risk-title">{{ t('高湿风险:') }}</span>
-                            <span class="risk-text">{{ t('预计未来7天平均相对湿度≥85%,伴随间歇性小雨或雾天。') }}</span>
-                        </p>
-                        <p>{{ t('潜在危害:田间湿度过高极易诱发霜疫霉病、炭疽病等真菌病害,病菌侵染幼果后导致腐烂、脱落。影响幼果正常发育和果皮着色,可能造成裂果、烂果。') }}</p>
-                        <p>{{ t('高湿环境利于蒂蛀虫等害虫繁殖,成虫活动增加,增加后期虫果率。') }}</p>
-                        <div class="warning-tip">{{ t('预警等级:黄色预警(中等风险),建议在未来48小时内启动预防措施。') }}</div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import { useI18n } from "@/i18n";
-const { t } = useI18n();
-import { useRoute } from "vue-router";
-import { ref, onActivated, computed } from "vue";
-import customHeader from "@/components/customHeader.vue";
-import { showImagePreview } from 'vant';
-import IndexMap from "@/views/old_mini/common_map/index.js";
-const route = useRoute();
-const mapContainer = ref(null);
-const indexMap = new IndexMap();
-
-const previewImages = computed(() => {
-    const list = imgInfo.value?.imageList || [];
-    return list.map((item) => item?.url).filter(Boolean);
-});
-
-const archiveColorObj = {
-    '管理信息': "green",
-    '异常发现': "red",
-    '气象风险': "orange",
-    // '气象风险': "yellow",
-};
-
-const handlePhotoClick = (index) => {
-    const images = previewImages.value;
-    const safeIndex = Math.min(Math.max(Number(index) || 0, 0), Math.max(images.length - 1, 0));
-    showImagePreview({
-        images,
-        startPosition: safeIndex,
-        closeable: true,
-        showIndex: true,
-    });
-};
-
-onActivated(() => {
-    // getFarmImagePage();
-    if(route.query.title !== '气象风险') {
-        indexMap.initMap('POINT(113.6142086995688 23.585836479509055)', mapContainer.value);
-    } 
-});
-
-const imgInfo = ref({});
-const getFarmImagePage = () => {
-    VE_API.monitor.getFarmImagePage({
-        id: route.query.id
-    }).then((res) => {
-        if (res.code === 0) {
-            imgInfo.value = res.data;
-        }
-    });
-};
-</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 {
-            .card-box {
-                background: #fff;
-                border-radius: 8px;
-                padding: 12px 16px;
-                box-sizing: border-box;
-
-                .card-title {
-                    font-size: 16px;
-                    display: flex;
-                    align-items: center;
-                    justify-content: space-between;
-                    margin-bottom: 12px;
-
-                    .date {
-                        font-size: 12px;
-                        color: rgba(0, 0, 0, 0.2);
-                    }
-                }
-            }
-
-            .sampling-card {
-                .sampling-title {
-                    font-size: 16px;
-                    font-weight: 500;
-                    color: #333;
-                    margin-bottom: 6px;
-                }
-
-                .sampling-desc {
-                    font-size: 14px;
-                    color: rgba(0, 0, 0, 0.5);
-                }
-            }
-
-            .photo-card {
-                .ratio-tip {
-                    font-size: 14px;
-                    padding: 5px 8px;
-                    background: rgba(33, 153, 248, 0.08);
-                    border-radius: 5px;
-                    display: flex;
-                    align-items: center;
-                    
-                    .title {
-                        font-size: 12px;
-                        color: #fff;
-                        margin-right: 12px;
-                        background: #2199f8;
-                        padding: 2px 6px;
-                        border-radius: 2px;
-                    }
-
-                    .content {
-                        max-width: 210px;
-                    }
-
-                    &.green {
-                        background: rgba(71, 184, 129, 0.1);
-                        .title {
-                            background: #47B881;
-                        }
-                    }
-                    &.red {
-                        background: rgba(255, 78, 78, 0.1);
-                        .title {
-                            background: #FF4E4E;
-                        }
-                    }
-                    &.orange {
-                        background: rgba(255, 148, 61, 0.1);
-                        .title {
-                            background: #FF943D;
-                        }
-                    }
-                }
-
-                .location-tip {
-                    margin-top: 12px;
-                    padding: 5px 10px;
-                    border: 1px solid #FF953D;
-                    border-radius: 5px;
-                    color: #FA7406;
-                }
-
-                .photo-grid {
-                    margin-top: 12px;
-                    display: grid;
-                    grid-template-columns: repeat(4, 1fr);
-                    grid-gap: 6px;
-
-                    .photo-item {
-                        position: relative;
-                        width: 100%;
-                        padding-bottom: 100%;
-                        border-radius: 8px;
-                        overflow: hidden;
-                        background: #e5f5e5;
-
-                        img {
-                            position: absolute;
-                            inset: 0;
-                            width: 100%;
-                            height: 100%;
-                            object-fit: cover;
-                            display: block;
-                        }
-                    }
-                }
-            }
-
-            .risk-card {
-                .risk-image {
-                    width: 100%;
-                    height: 170px;
-                    border-radius: 5px;
-                    margin-bottom: 12px;
-                    background: #ff8a3d;
-                }
-
-                .risk-content {
-                    line-height: 22px;
-                    border-radius: 5px;
-                    padding: 5px 8px;
-                    background: rgba(190, 190, 190, 0.11);
-
-                    p {
-                        margin: 0 0 12px;
-                    }
-
-                    .risk-highlight {
-                        .risk-title {
-                            font-weight: 500;
-                            color: #FFAA14;
-                        }
-                    }
-                }
-
-                .warning-tip {
-                    border-radius: 5px;
-                    background: rgba(255, 177, 41, 0.1);
-                    color: #FFAA14;
-                    font-size: 14px;
-                    line-height: 22px;
-                    font-weight: 500;
-                    padding: 5px 8px;
-                }
-            }
-
-            .region-card {
-                margin-top: 10px;
-                .map-container {
-                    width: 100%;
-                    height: 170px;
-                    clip-path: inset(0px round 5px);
-                }
-            }
-        }
-    }
-}
-
-.image-popup {
-    width: 327px;
-    border-radius: 8px;
-
-    .popup-content {
-        width: 100%;
-    }
-}
-</style>

+ 0 - 1916
src/views/old_mini/monitor/subPages/darwArea.vue

@@ -1,1916 +0,0 @@
-<template>
-    <div class="edit-map">
-        <custom-header @goback="goBack" :isGoBack="true" :name="viewOnly ? '查看区域' : '勾选地块'"></custom-header>
-        <div class="region-type-tabs">
-            <div v-for="item in regionTypeTabs" :key="item.code" class="region-type-tab"
-                :class="{ 'region-type-tab--active': activeRegionType === item.code }"
-                @click="handleRegionTypeClick(item)">
-                {{ item.name }}
-            </div>
-        </div>
-        <div class="variety-tabs" v-if="varietyTabs.length > 0 && activeRegionType !== 'DORMANCY'">
-            <div v-for="(v, index) in varietyTabs" :key="index" class="variety-tab"
-                :class="{ 'variety-tab--active': activeVariety === index }" @click="handleVarietyClick(v, index)">
-                {{ v.regionName || v.problemZoneTypeName }}
-            </div>
-        </div>
-        <div class="edit-map-content">
-            <div class="edit-map-tip" v-if="!viewOnly">{{ $t('操作提示:拖动圆点,即可调整地块边界') }}</div>
-            <div class="map-container" ref="mapContainer"></div>
-            <div class="edit-map-footer">
-                <div v-if="viewOnly" class="footer-back" @click="deletePolygon">
-                    <img class="back-icon" src="@/assets/img/map/delete.png" alt="" />
-                </div>
-                <div class="edit-map-footer-btn" :class="{ 'confirm-btn-box': viewOnly }">
-                    <template v-if="!viewOnly">
-                        <div class="btn-reset" @click="resetPolygon">{{ $t('重置区域') }}</div>
-                        <div class="btn-confirm" @click="openConfirmDrawTypePopup">{{ $t('确认区域') }}</div>
-                    </template>
-                    <div v-else class="btn-confirm" @click="handleEditRegion">{{ $t('编辑区域') }}</div>
-                </div>
-            </div>
-        </div>
-        <tip-popup v-model:show="showTipPopup" type="success" :text="$t('您的农情报告已生成')" text2="请查看" buttonText="点击查看"
-            @confirm="handleTipConfirm" />
-
-        <confirm-draw-type-popup ref="confirmDrawTypePopupRef" @confirm="handleConfirmDrawType" />
-    </div>
-</template>
-
-<script setup>
-import customHeader from "@/components/customHeader.vue";
-import { ref, computed, watch, onActivated, onDeactivated, nextTick } from "vue";
-import DrawRegionMap from "../../interactionList/map/drawRegionMap.js";
-import { Map as KMapMap } from "@/utils/ol-map/KMap";
-import { useRouter, useRoute } from "vue-router";
-import { convertPointToArray } from "@/utils/index";
-import { ElMessage, ElMessageBox } from "element-plus";
-import TipPopup from "@/components/popup/tipPopup.vue";
-import ConfirmDrawTypePopup from "@/components/popup/confirmDrawTypePopup.vue";
-import Style from "ol/style/Style";
-import { Fill, Stroke, Circle, Text } from "ol/style.js";
-import { Point, Polygon, MultiPolygon } from "ol/geom";
-import WKT from "ol/format/WKT.js";
-import { unByKey } from "ol/Observable.js";
-import * as proj from "ol/proj";
-import { getArea } from "ol/sphere.js";
-
-const router = useRouter();
-const route = useRoute();
-const mapContainer = ref(null);
-const drawRegionMap = new DrawRegionMap();
-
-/** OpenLayers 地图在容器尺寸变化后不会自动重算 canvas,需手动 updateSize */
-const resizeMapToContainer = () => {
-    nextTick(() => {
-        requestAnimationFrame(() => {
-            drawRegionMap.kmap?.map?.updateSize?.();
-        });
-    });
-};
-
-// handleVarietyClick 内部有延迟渲染(setTimeout),切换查看/编辑或重建地图时必须取消,避免旧回调在新实例上再次 addFeature 造成叠加
-const pendingGeomRenderTimer = ref(null);
-const clearPendingGeomRenderTimer = () => {
-    if (pendingGeomRenderTimer.value) {
-        clearTimeout(pendingGeomRenderTimer.value);
-        pendingGeomRenderTimer.value = null;
-    }
-};
-
-const confirmDrawTypePopupRef = ref(null);
-const selectedDrawTypeMeta = ref({
-    type: "",
-    category: "",
-    remark: "",
-});
-// 每个品种(tab)对应的地块数据草稿:key 为 tab index,value 为 { geomArr, geom }(与当前大类 Tab 一致时同步)
-const regionsDraftByIndex = ref({});
-/** 按弹窗确认的「大类 + 小类」存几何与备注,避免与地图当前选中 Tab 不一致 */
-const regionsDraftByKey = ref({});
-const submitting = ref(false);
-// 仅在首次进入页面时根据路由 varietyId 定位一次,避免后续刷新覆盖当前流程进度
-const hasAppliedInitialVariety = ref(false);
-const selectedDeleteFeature = ref(null);
-const deleteSelectClickKey = ref(null);
-const selectedDeleteFeatureUid = ref("");
-const selectedDeleteFeatureOriginalStyle = ref(null);
-
-const type = ref(null);
-const varietyTabs = ref([]);
-const activeVariety = ref(0);
-const regionGeom = ref(null);
-
-
-/** 切换「大类」Tab 时子类列表完全替换,regionsDraftByIndex 按下标缓存会与新区块列表错位;保存成功后也应以接口为准 */
-const clearDraftIndexOnly = () => {
-    regionsDraftByIndex.value = {};
-};
-
-const clearAllRegionDrafts = () => {
-    regionsDraftByKey.value = {};
-    regionsDraftByIndex.value = {};
-};
-
-const clearDeleteSelectionState = () => {
-    if (selectedDeleteFeature.value) {
-        selectedDeleteFeature.value.setStyle(selectedDeleteFeatureOriginalStyle.value ?? undefined);
-        selectedDeleteFeature.value = null;
-    }
-    selectedDeleteFeatureUid.value = "";
-    selectedDeleteFeatureOriginalStyle.value = null;
-    if (deleteSelectClickKey.value) {
-        unByKey(deleteSelectClickKey.value);
-        deleteSelectClickKey.value = null;
-    }
-};
-
-const getDeleteHighlightStyle = () => {
-    const styleKind = getCanonicalRegionTypeForStyles();
-    if (styleKind === "variety") {
-        return {
-            fillColor: "rgba(24, 170, 139, 0.5)",
-            strokeColor: "#18AA8B",
-        };
-    }
-    if (styleKind === "ABNORMAL") {
-        if (activeVariety.value < 2) {
-            return {
-                fillColor: "rgba(224, 49, 49, 0.5)",
-                strokeColor: "#E03131",
-            }
-        } else {
-            return {
-                fillColor: "rgba(255, 115, 0, 0.5)",
-                strokeColor: "#FF7300",
-            };
-        }
-    }
-    if (styleKind === "ENVIRONMENT") {
-        return {
-            fillColor: "rgba(255, 199, 102, 0.5)",
-            strokeColor: "#FDCF7F",   
-        };
-    }
-    // 其余类型先给默认占位色,后续可按产品视觉再调整
-    return {
-        fillColor: "rgba(229, 229, 229, 0.5)",
-        strokeColor: "#A6A6A6",
-    };
-};
-
-const highlightDeleteSelectedFeature = (feature) => {
-    if (!feature) return;
-    if (selectedDeleteFeature.value === feature) return;
-    if (selectedDeleteFeature.value && selectedDeleteFeature.value !== feature) {
-        selectedDeleteFeature.value.setStyle(selectedDeleteFeatureOriginalStyle.value ?? undefined);
-    }
-    selectedDeleteFeatureOriginalStyle.value = feature.getStyle ? feature.getStyle() : null;
-    selectedDeleteFeature.value = feature;
-    selectedDeleteFeatureUid.value = String(feature?.ol_uid || feature?.getId?.() || "");
-    const { fillColor, strokeColor } = getDeleteHighlightStyle();
-    // 删除选择态:按当前类型动态高亮(单选)
-    feature.setStyle(
-        new Style({
-            fill: new Fill({ color: fillColor }),
-            stroke: new Stroke({ color: strokeColor, width: 2 }),
-        })
-    );
-};
-
-const isFeatureLockedForDelete = (feature) => {
-    if (activeRegionType.value === "variety") return false;
-    const growth = getAbnormalGrowthOverlayMeta(feature);
-    const status = String(growth?.handleStatus || "");
-    return status === "2" || status === "3";
-};
-
-const enableDeleteSelectionMode = () => {
-    const map = drawRegionMap.kmap?.map;
-    const polygonLayer = drawRegionMap.kmap?.polygonLayer?.layer;
-    if (!map || !polygonLayer || deleteSelectClickKey.value) return;
-    deleteSelectClickKey.value = map.on("singleclick", (evt) => {
-        let hitFeature = null;
-        map.forEachFeatureAtPixel(
-            evt.pixel,
-            (feature) => {
-                hitFeature = feature;
-                return true;
-            },
-            {
-                layerFilter: (layer) => layer === polygonLayer,
-            }
-        );
-        if (hitFeature) {
-            if (isFeatureLockedForDelete(hitFeature)) {
-                ElMessage.warning("该地块不可删除");
-                return;
-            }
-            highlightDeleteSelectedFeature(hitFeature);
-        }
-    });
-};
-
-const handleRegionTypeClick = (item) => {
-    clearDeleteSelectionState();
-    const prevMajor = activeRegionType.value;
-    if (item.code !== prevMajor) {
-        clearDraftIndexOnly();
-    }
-    activeRegionType.value = item.code;
-    activeVariety.value = 0;
-    if (item.code === "variety") {
-        varietyTabs.value = regionInfo.value.regionList || [];
-    } else {
-        varietyTabs.value = item.children;
-    }
-    handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
-    if (drawRegionMap.kmap) {
-        applyRegionStyles();
-    }
-};
-
-// 删除当前地块
-const deletePolygon = () => {
-    const features = drawRegionMap.kmap?.polygonLayer?.source?.getFeatures?.() || [];
-    const deletableFeatures = features.filter((f) => !isFeatureLockedForDelete(f));
-    let matchedFeature = null;
-    if (features.length === 0) {
-        clearDeleteSelectionState();
-        ElMessage.warning("当前没有可删除的地块");
-        return;
-    }
-    if (features.length === 1 && deletableFeatures.length === 0) {
-        clearDeleteSelectionState();
-        ElMessage.warning("当前地块不可删除");
-        return;
-    }
-    if (features.length > 1) {
-        if (deletableFeatures.length === 0) {
-            clearDeleteSelectionState();
-            ElMessage.warning("当前地块不可删除");
-            return;
-        }
-        if (!selectedDeleteFeature.value) {
-            enableDeleteSelectionMode();
-            ElMessage.warning("当前有多个地块,请先选择地块");
-            return;
-        }
-        matchedFeature = features.find((f) => {
-            if (f === selectedDeleteFeature.value) return true;
-            const uid = String(f?.ol_uid || f?.getId?.() || "");
-            return uid && uid === selectedDeleteFeatureUid.value;
-        });
-        if (!matchedFeature) {
-            selectedDeleteFeature.value = null;
-            selectedDeleteFeatureUid.value = "";
-            ElMessage.warning("请选择地块后再删除");
-            return;
-        }
-        if (isFeatureLockedForDelete(matchedFeature)) {
-            clearDeleteSelectionState();
-            ElMessage.warning("该地块不可删除");
-            return;
-        }
-    } else {
-        clearDeleteSelectionState();
-    }
-
-    ElMessageBox.confirm(
-        "确认删除当前地块吗?删除后可以重新勾画。",
-        "删除确认",
-        {
-            confirmButtonText: "确认删除",
-            cancelButtonText: "取消",
-            type: "warning",
-        }
-    ).then(async () => {
-        if (selectedDeleteFeature.value && features.length > 1) {
-            drawRegionMap.kmap?.polygonLayer?.source?.removeFeature?.(matchedFeature || selectedDeleteFeature.value);
-            clearDeleteSelectionState();
-        } else {
-            drawRegionMap.deleteCurrentPolygon();
-        }
-
-        const polygonData = drawRegionMap.getAreaGeometry?.();
-        const geometryArr = polygonData?.geometryArr || [];
-        try {
-            const ok = await submitCurrentTabGeometryChange(geometryArr);
-            if (!ok) {
-                ElMessage.error("删除后保存失败");
-                return;
-            }
-            await fetchRegionInfo();
-            clearAllRegionDrafts();
-            if (activeRegionType.value === "variety") {
-                varietyTabs.value = regionInfo.value?.regionList || [];
-            } else {
-                const group = (regionTypeTabs.value || []).find(
-                    (x) => String(x?.code) === String(activeRegionType.value)
-                );
-                varietyTabs.value = group?.children || [];
-            }
-            const nextIndex = Math.min(activeVariety.value, Math.max(varietyTabs.value.length - 1, 0));
-            activeVariety.value = nextIndex;
-            if (varietyTabs.value.length > 0 && varietyTabs.value[nextIndex]) {
-                handleVarietyClick(varietyTabs.value[nextIndex], nextIndex);
-            } else {
-                drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
-                drawRegionMap.fitAllRegions?.();
-            }
-            ElMessage.success("地块已删除");
-        } catch (_) {
-            ElMessage.error("删除后保存失败");
-        }
-    });
-};
-
-/** 取 Polygon / MultiPolygon 的外环坐标(地图投影),用于顶点样式 */
-const getOuterRingCoordinates = (geometry) => {
-    if (!geometry || typeof geometry.getType !== "function") return [];
-    const type = geometry.getType();
-    const c = geometry.getCoordinates();
-    if (!c || !c.length) return [];
-    if (type === "Polygon") return c[0] || [];
-    if (type === "MultiPolygon") return c[0]?.[0] || [];
-    return [];
-};
-
-const createPolygonStyleFunc = (fillColor, strokeColor) => {
-    return (feature) => {
-        const growth = getAbnormalGrowthOverlayMeta(feature);
-        const isTreatingDisease =
-            String(growth?.handleStatus || "") === "2" && !String(growth?.badgeText || "").includes("长势");
-        const isTreatingGrowth =
-            String(growth?.handleStatus || "") === "2" && String(growth?.badgeText || "").includes("长势");
-        const isControlledDisease = String(growth?.handleStatus || "") === "3";
-        const currentFillColor = isControlledDisease
-            ? SLEEP_ZONE_FILL_COLOR
-            : isTreatingGrowth
-                ? "rgba(255, 159, 102, 0.3)"
-            : isTreatingDisease
-                ? DISEASE_TREATING_FILL_COLOR
-                : fillColor;
-        const currentStrokeColor = isControlledDisease
-            ? SLEEP_ZONE_STROKE_COLOR
-            : isTreatingGrowth
-                ? "rgba(255, 94, 0, 0.3)"
-            : isTreatingDisease
-                ? DISEASE_TREATING_STROKE_COLOR
-                : strokeColor;
-        const styles = [];
-        const ring = getOuterRingCoordinates(feature.getGeometry());
-        const ringLen = ring.length;
-        const vertexCount = ringLen > 1 ? ringLen - 1 : ringLen;
-        for (let i = 0; i < vertexCount; i++) {
-            if (i % 2) {
-                styles.push(
-                    new Style({
-                        geometry: new Point(ring[i]),
-                        image: new Circle({
-                            radius: 4,
-                            fill: new Fill({
-                                color: currentStrokeColor,
-                            }),
-                            stroke: new Stroke({
-                                color: "#fff",
-                                width: 1,
-                            }),
-                        }),
-                    })
-                );
-            } else {
-                styles.push(
-                    new Style({
-                        geometry: new Point(ring[i]),
-                        image: new Circle({
-                            radius: 6,
-                            fill: new Fill({
-                                color: "#fff",
-                            }),
-                        }),
-                    })
-                );
-            }
-        }
-        const fillStyle = new Style({
-            fill: new Fill({
-                color: currentFillColor,
-            }),
-            stroke: new Stroke({
-                color: currentStrokeColor,
-                width: 2,
-            }),
-        });
-        let geom = feature.getGeometry().clone();
-        geom.transform(proj.get("EPSG:4326"), proj.get("EPSG:38572"));
-        let area = getArea(geom);
-        area = (area + area / 2) / 1000;
-        if (growth) {
-            styles.push(
-                new Style({
-                    text: new Text({
-                        text: growth.badgeText,
-                        font: "bold 13px sans-serif",
-                        fill: new Fill({ color: growth.badgeTextColor || "#ffffff" }),
-                        backgroundFill: new Fill({ color: growth.badgeBackground || ABNORMAL_BADGE_BG_GROWTH }),
-                        backgroundStroke: growth.badgeBorderColor
-                            ? new Stroke({ color: growth.badgeBorderColor, width: 1 })
-                            : undefined,
-                        padding: [4, 10, 4, 10],
-                        offsetY: -40,
-                    }),
-                }),
-                new Style({
-                    text: new Text({
-                        text: `发现时间:${growth.discoveryDate}`,
-                        font: "12px sans-serif",
-                        fill: new Fill({ color: "#ffffff" }),
-                        offsetY: -16,
-                    }),
-                })
-            );
-        }
-        const areaValStyle = new Style({
-            text: new Text({
-                font: "16px sans-serif",
-                text: area.toFixed(2) + "亩",
-                fill: new Fill({ color: "#fff" }),
-                offsetY: growth ? 14 : 0,
-            }),
-        });
-        styles.push(fillStyle, areaValStyle);
-        return styles;
-    };
-};
-
-const applyRegionStyles = () => {
-    const kmap = drawRegionMap.kmap;
-    if (!kmap) return;
-
-    let lineColor = "#2199F8";
-    let vertexColor = "#2199F8";
-    let fillColor = [0, 0, 0, 0.5];
-    let strokeColor = "#2199F8";
-
-    const styleKind = getCanonicalRegionTypeForStyles();
-    if (styleKind === "variety") {
-        lineColor = "#18AA8B";
-        vertexColor = "#18AA8B";
-        fillColor = [0, 57, 44, 0.5];
-        strokeColor = "#18AA8B";
-    } else if (styleKind === "ABNORMAL") {
-        if (activeVariety.value < 2) {
-            lineColor = "#E03131";
-            vertexColor = "#E03131";
-            fillColor = [100, 0, 0, 0.5];
-            strokeColor = "#E03131";
-        } else {
-            lineColor = "#FF7300";
-            vertexColor = "#FF7300";
-            fillColor = [124, 46, 0, 0.5];
-            strokeColor = "#FF7300";
-        }
-    } else if (styleKind === "ENVIRONMENT") {
-        lineColor = "#FDCF7F";
-        vertexColor = "#FDCF7F";
-        fillColor = [151, 96, 0, 0.5];
-        strokeColor = "#FDCF7F";
-    } else {
-        lineColor = "#A6A6A6";
-        vertexColor = "#A6A6A6";
-        fillColor = [166, 166, 166, 0.25];
-        strokeColor = "#A6A6A6";
-    }
-
-
-    // 勾画进行中:通过 Map.drawStyleColors 影响底层 drawStyleFunc 颜色
-    KMapMap.drawStyleColors = {
-        line: lineColor,
-        vertex: vertexColor,
-        // 只读回显时也复用当前大类颜色(避免查看态全部变绿)
-        fill: fillColor,
-        stroke: strokeColor,
-    };
-
-    kmap.polygonStyle = createPolygonStyleFunc(fillColor, strokeColor);
-    if (kmap.polygonLayer?.layer && typeof kmap.polygonLayer.layer.setStyle === "function") {
-        kmap.polygonLayer.layer.setStyle(kmap.polygonStyle);
-    }
-};
-
-const isValidGeom = (geom) => {
-    if (typeof geom !== "string") return false;
-    const normalized = geom.trim();
-    if (!normalized) return false;
-    if (["[]", "{}", "null", "undefined", '""'].includes(normalized)) return false;
-    return true;
-};
-
-/** 与 drawRegionMap / setAreaGeometry 一致:WKT 按 WGS84 解析 */
-const WGS84_WKT_OPTS = Object.freeze({
-    dataProjection: "EPSG:4326",
-    featureProjection: "EPSG:4326",
-});
-
-const wktGeomFormat = new WKT();
-
-/** Polygon / MultiPolygon 各自对应一组环坐标(MultiPolygon 为多块) */
-const polygonCoordSetsFromGeometry = (geometry) => {
-    if (!geometry || typeof geometry.getType !== "function") return [];
-    const type = geometry.getType();
-    if (type === "Polygon") return [geometry.getCoordinates()];
-    if (type === "MultiPolygon") return geometry.getCoordinates();
-    return [];
-};
-
-const mergePolygonWktsForApi = (wktArr) => {
-    if (!Array.isArray(wktArr) || wktArr.length === 0) return "";
-    const trimmed = wktArr.map((x) => String(x).trim()).filter(isValidGeom);
-    if (trimmed.length === 0) return "";
-    if (trimmed.length === 1) return trimmed[0];
-
-    const coordSets = [];
-    for (const w of trimmed) {
-        try {
-            const g = wktGeomFormat.readGeometry(w, WGS84_WKT_OPTS);
-            coordSets.push(...polygonCoordSetsFromGeometry(g));
-        } catch (_) {
-            /* 单条解析失败则跳过 */
-        }
-    }
-    if (coordSets.length === 0) return trimmed[0];
-    if (coordSets.length === 1) {
-        try {
-            return wktGeomFormat.writeGeometry(new Polygon(coordSets[0]), WGS84_WKT_OPTS);
-        } catch (_) {
-            return trimmed[0];
-        }
-    }
-    return wktGeomFormat.writeGeometry(new MultiPolygon(coordSets), WGS84_WKT_OPTS);
-};
-
-const flattenWktToPolygonWktArray = (wkt) => {
-    if (!isValidGeom(wkt)) return [];
-    const s = String(wkt).trim();
-    try {
-        const g = wktGeomFormat.readGeometry(s, WGS84_WKT_OPTS);
-        const sets = polygonCoordSetsFromGeometry(g);
-        if (sets.length === 0) return [s];
-        return sets.map((rings) => wktGeomFormat.writeGeometry(new Polygon(rings), WGS84_WKT_OPTS));
-    } catch (_) {
-        return [s];
-    }
-};
-
-const flattenGeomWktList = (arr) => {
-    if (!Array.isArray(arr)) return [];
-    const out = [];
-    for (const item of arr) {
-        if (!isValidGeom(item)) continue;
-        out.push(...flattenWktToPolygonWktArray(String(item).trim()));
-    }
-    return out;
-};
-
-/** 地图回显:展开 MULTIPOLYGON 为多个 POLYGON WKT,并去掉无效项 */
-const flattenGeomWktListForMap = (arr) => flattenGeomWktList(arr).filter(isValidGeom);
-
-const formatAreaTextFromGeomArr = (geomWktArr) => {
-    if (!Array.isArray(geomWktArr) || geomWktArr.length === 0) return "";
-    let totalArea = 0;
-    for (const wkt of geomWktArr) {
-        if (!isValidGeom(wkt)) continue;
-        try {
-            const geometry = wktGeomFormat.readGeometry(String(wkt).trim(), WGS84_WKT_OPTS);
-            geometry.transform(proj.get("EPSG:4326"), proj.get("EPSG:38572"));
-            let area = getArea(geometry);
-            area = (area + area / 2) / 1000;
-            totalArea += Number(area) || 0;
-        } catch (_) {
-            /* 单条解析失败则跳过 */
-        }
-    }
-    return totalArea > 0 ? `${totalArea.toFixed(2)}亩` : "";
-};
-
-// 从 tab.geomItems[{geomWkt}] 中提取 WKT 数组(兼容单块/多块)
-const getGeomArrFromGeomItems = (tab) => {
-    const items = tab?.geomItems;
-    if (!Array.isArray(items) || items.length === 0) return [];
-    return items
-        .map((x) => x?.geomWkt)
-        .filter((x) => x !== undefined && x !== null)
-        .map((x) => String(x).trim())
-        .filter((x) => isValidGeom(x));
-};
-
-const isDiseaseAbnormalTab = (tab) => {
-    const name = (tab?.problemZoneTypeName || tab?.regionName || "").toString();
-    return name.includes("病害") || name.includes("虫害");
-};
-
-const isGrowthAbnormalTab = (tab) => {
-    const name = (tab?.problemZoneTypeName || tab?.regionName || "").toString();
-    return name.includes("过慢") || name.includes("过快");
-};
-
-const hasLockedStatusItems = (tab) => {
-    const items = Array.isArray(tab?.geomItems) ? tab.geomItems : [];
-    return items.some((item) => {
-        const status = String(item?.handleStatus ?? "");
-        return status === "2" || status === "3";
-    });
-};
-
-const isLockedAbnormalTab = (tab) =>
-    isDiseaseAbnormalTab(tab) || isGrowthAbnormalTab(tab) || hasLockedStatusItems(tab);
-
-const isLockedAbnormalItem = (tab, item) => {
-    const status = String(item?.handleStatus ?? "");
-    if (!isLockedAbnormalTab(tab)) return false;
-    return status === "2" || status === "3";
-};
-
-const formatDateToYmdDot = (raw) => {
-    const sourceDate = raw ? new Date(raw) : new Date();
-    const resolvedDate = Number.isNaN(sourceDate.getTime()) ? new Date() : sourceDate;
-    const y = resolvedDate.getFullYear();
-    const m = String(resolvedDate.getMonth() + 1).padStart(2, "0");
-    const d = String(resolvedDate.getDate()).padStart(2, "0");
-    return `${y}.${m}.${d}`;
-};
-
-const formatDateToYmdDash = (raw) => {
-    const sourceDate = raw ? new Date(raw) : new Date();
-    const resolvedDate = Number.isNaN(sourceDate.getTime()) ? new Date() : sourceDate;
-    const y = resolvedDate.getFullYear();
-    const m = String(resolvedDate.getMonth() + 1).padStart(2, "0");
-    const d = String(resolvedDate.getDate()).padStart(2, "0");
-    return `${y}-${m}-${d}`;
-};
-
-const getLockedDiseaseRegions = (tab) => {
-    if (!isLockedAbnormalTab(tab)) return [];
-    const items = Array.isArray(tab?.geomItems) ? tab.geomItems : [];
-    const out = [];
-    items.forEach((item) => {
-        if (!isLockedAbnormalItem(tab, item)) return;
-        const status = String(item?.handleStatus ?? "");
-        const polygons = flattenWktToPolygonWktArray(item?.geomWkt).filter(isValidGeom);
-        polygons.forEach((geometry) => {
-            const name = (tab?.problemZoneTypeName || tab?.regionName || "").toString();
-            const isGrowth = name.includes("过慢") || name.includes("过快");
-            const prefix = name.includes("虫害")
-                ? "虫害"
-                : name.includes("病害")
-                    ? "病害"
-                    : name.includes("过快")
-                        ? "长势过快"
-                        : "长势过慢";
-            out.push({
-                geometry,
-                displayMode: "lockedDisease",
-                handleStatus: status,
-                lockStyleType: isGrowth ? "growthTreating" : status === "3" ? "controlled" : "diseaseTreating",
-                label: status === "3" ? `${prefix}已控制` : `${prefix}治疗中`,
-                updatedTime: formatDateToYmdDot(item?.createTime),
-            });
-        });
-    });
-    return out;
-};
-
-const getEditableGeomArrForCurrentTab = (tab, rawGeomArr) => {
-    if (
-        !tab ||
-        !isLockedAbnormalTab(tab) ||
-        viewOnly.value ||
-        activeRegionType.value === "variety"
-    ) {
-        return flattenGeomWktListForMap(rawGeomArr);
-    }
-    const key = draftKeyFromParts(activeRegionType.value, tab);
-    const draft = key ? regionsDraftByKey.value[key] : null;
-    const draftItems = Array.isArray(draft?.geomItems) ? draft.geomItems : [];
-    const items = draftItems.length > 0 ? draftItems : Array.isArray(tab?.geomItems) ? tab.geomItems : [];
-    const editable = [];
-    items.forEach((item) => {
-        if (isLockedAbnormalItem(tab, item)) return;
-        editable.push(...flattenWktToPolygonWktArray(item?.geomWkt));
-    });
-    const editableGeomArr = flattenGeomWktListForMap(editable);
-    if (editableGeomArr.length > 0) return editableGeomArr;
-    // 当前小类存在 2/3 锁定地块时,编辑图层保持空,避免把锁定地块误加到可编辑层
-    const hasLockedItems = items.some((item) => isLockedAbnormalItem(tab, item));
-    if (hasLockedItems) return [];
-    // 仅当无锁定地块且没有 geomItems 时,兜底使用纯几何草稿(例如新勾画未落库)
-    const draftGeom = getDraftGeomForTab(activeRegionType.value, tab, activeVariety.value);
-    if (isValidGeom(draftGeom)) {
-        return flattenGeomWktListForMap([String(draftGeom).trim()]);
-    }
-    return editableGeomArr;
-};
-
-// 兜底防线:若锁定地块意外进入可编辑图层,按 handleStatus(2/3) 强制移除,避免只读层与可编辑层叠加
-const purgeLockedFeaturesFromEditableLayer = (tab) => {
-    if (!isLockedAbnormalTab(tab)) return;
-    const source = drawRegionMap.kmap?.polygonLayer?.source;
-    if (!source) return;
-    const features = source.getFeatures?.() || [];
-    features.forEach((feature) => {
-        const geomItem = getGeomItemByFeature(tab, feature);
-        const status = String(geomItem?.handleStatus ?? "");
-        if (status === "2" || status === "3") {
-            source.removeFeature?.(feature);
-        }
-    });
-};
-
-/** 非品种区提交:按当前地块顺序生成 geomItems(已有项更新,新项追加) */
-const buildGeomItemsFromGeometryArr = (tab, geometryArr, remarkOverride) => {
-    const geomArr = flattenGeomWktListForMap(geometryArr || []);
-    const existingItems = Array.isArray(tab?.geomItems) ? tab.geomItems : [];
-    const nowDate = new Date();
-    const y = nowDate.getFullYear();
-    const m = String(nowDate.getMonth() + 1).padStart(2, "0");
-    const d = String(nowDate.getDate()).padStart(2, "0");
-    const defaultCreateTime = `${y}-${m}-${d}`;
-    return geomArr.map((geomWkt, idx) => {
-        const base = existingItems[idx] && typeof existingItems[idx] === "object" ? existingItems[idx] : {};
-        const baseRemark = base?.remark != null ? String(base.remark) : "";
-        const finalRemark = remarkOverride != null ? String(remarkOverride) : baseRemark;
-        const createTime =
-            base?.createTime != null && String(base.createTime).trim() !== ""
-                ? String(base.createTime)
-                : defaultCreateTime;
-        const handleStatus =
-            base?.handleStatus != null && String(base.handleStatus).trim() !== ""
-                ? base.handleStatus
-                : 1;
-        return {
-            ...base,
-            geomWkt,
-            remark: finalRemark,
-            createTime,
-            handleStatus,
-        };
-    });
-};
-
-/** 病害编辑态提交:2/3 保持只读原样,1 与新勾画项按当前可编辑地块更新/追加 */
-const buildDiseaseGeomItemsForSubmit = (tab, editableGeometryArr, remarkOverride) => {
-    const items = Array.isArray(tab?.geomItems) ? tab.geomItems : [];
-    const lockedItems = items
-        .filter((item) => {
-            const status = String(item?.handleStatus ?? "");
-            return status === "2" || status === "3";
-        })
-        .map((item) => ({
-            ...item,
-            geomWkt: isValidGeom(item?.geomWkt) ? String(item.geomWkt).trim() : "",
-            remark: item?.remark != null ? String(item.remark) : "",
-        }))
-        .filter((item) => isValidGeom(item.geomWkt));
-    const editableBaseItems = items.filter((item) => {
-        const status = String(item?.handleStatus ?? "");
-        return status === "1" || status === "";
-    });
-    const geomArr = flattenGeomWktListForMap(editableGeometryArr || []);
-    const editableItems = geomArr.map((geomWkt, idx) => {
-        const base =
-            editableBaseItems[idx] && typeof editableBaseItems[idx] === "object"
-                ? editableBaseItems[idx]
-                : {};
-        const baseRemark = base?.remark != null ? String(base.remark) : "";
-        const finalRemark = remarkOverride != null ? String(remarkOverride) : baseRemark;
-        const createTime =
-            base?.createTime != null && String(base.createTime).trim() !== ""
-                ? String(base.createTime)
-                : formatDateToYmdDot();
-        const handleStatus =
-            base?.handleStatus != null && String(base.handleStatus).trim() !== ""
-                ? String(base.handleStatus)
-                : 1;
-        return {
-            ...base,
-            geomWkt,
-            remark: finalRemark,
-            createTime: formatDateToYmdDash(createTime),
-            handleStatus,
-        };
-    });
-    return [...lockedItems, ...editableItems];
-};
-
-const draftKeyFromParts = (majorType, tabLike) => {
-    if (!majorType || !tabLike || typeof tabLike !== "object") return "";
-    const t = tabLike;
-    const id = t.regionId ?? t.problemZoneTypeId ?? t.typeId ?? t.id;
-    if (id != null && String(id).trim() !== "") {
-        return `${majorType}:${String(id).trim()}`;
-    }
-    const nm = (t.regionName || t.problemZoneTypeName || "").toString().trim();
-    return nm ? `${majorType}:name:${nm}` : "";
-};
-
-const getDraftGeomForTab = (majorType, tab, index) => {
-    const k = draftKeyFromParts(majorType, tab);
-    const byKey = k ? regionsDraftByKey.value[k] : null;
-    if (byKey?.geom) return byKey.geom;
-    return regionsDraftByIndex.value[index]?.geom;
-};
-
-const resolveInitialVarietyIndex = (regionList) => {
-    const queryVarietyId = route.query?.varietyId;
-    if (!queryVarietyId || !Array.isArray(regionList) || regionList.length === 0) return 0;
-    const queryId = String(queryVarietyId).trim();
-    const matchedIndex = regionList.findIndex((item) => {
-        const candidateIds = [item?.typeId, item?.varietyId, item?.id]
-            .filter((v) => v !== undefined && v !== null)
-            .map((v) => String(v).trim());
-        return candidateIds.includes(queryId);
-    });
-    return matchedIndex >= 0 ? matchedIndex : 0;
-};
-
-const getReadonlyVarietyRegions = (activeIndex) => {
-    if (!Array.isArray(varietyTabs.value) || varietyTabs.value.length === 0) return [];
-    const readonlyRegions = [];
-    for (let i = 0; i < varietyTabs.value.length; i++) {
-        if (i === activeIndex) continue;
-        const tab = varietyTabs.value[i];
-        if (!tab) continue;
-        const draftGeom = getDraftGeomForTab(activeRegionType.value, tab, i);
-        const geometry = draftGeom || tab.geom;
-        if (!isValidGeom(geometry)) continue;
-        readonlyRegions.push({
-            geometry,
-            label: tab.regionName || "",
-            displayMode: "readonlyVariety",
-        });
-    }
-    return readonlyRegions;
-};
-
-const getAllVarietyReadonlyRegions = () => {
-    const list = regionInfo.value?.regionList || [];
-    if (!Array.isArray(list) || list.length === 0) return [];
-    const regions = [];
-    for (let i = 0; i < list.length; i++) {
-        const tab = list[i];
-        if (!tab) continue;
-        const draftGeom = getDraftGeomForTab("variety", tab, i);
-        const geometry = draftGeom || tab.geom;
-        if (!isValidGeom(geometry)) continue;
-        regions.push({
-            geometry,
-            label: tab.regionName || "",
-            displayMode: "readonlyVariety",
-        });
-    }
-    return regions;
-};
-
-const renderReadonlyVarietyRegions = (activeIndex) => {
-    if (drawRegionMap && typeof drawRegionMap.setStatusRegions === "function") {
-        drawRegionMap.setStatusRegions(getReadonlyVarietyRegions(activeIndex));
-    }
-};
-
-/**
- * 仅渲染「品种区」所有已有地块(只读),用于在其它问题区查看/编辑时作为底图参考。
- * 需求:只显示品种区地块,其它问题区地块不显示,且不可编辑。
- */
-const renderAllVarietyRegionsReadonlyOnly = () => {
-    if (!drawRegionMap || typeof drawRegionMap.setStatusRegions !== "function") return;
-    const regions = getAllVarietyReadonlyRegions();
-    if (regions.length === 0) {
-        drawRegionMap.setStatusRegions([]);
-        return;
-    }
-    drawRegionMap.setStatusRegions(regions);
-};
-
-/**
- * 用户“闭环(drawend)”后,把当前绘制结果自动写入草稿,避免切换 tab 时被清掉。
- * 注意:getAreaGeometry 可能包含多块,这里以“最新一块”为准(最后一个 feature)
- */
-const syncClosedDrawToDraft = () => {
-    const tab = varietyTabs.value?.[activeVariety.value];
-    if (!tab) return;
-    const polygonData = drawRegionMap.getAreaGeometry?.();
-    const geometryArr = polygonData?.geometryArr;
-    if (!Array.isArray(geometryArr) || geometryArr.length === 0) return;
-    const geom = String(geometryArr[geometryArr.length - 1] || "").trim();
-    if (!isValidGeom(geom)) return;
-
-    const key = draftKeyFromParts(activeRegionType.value, tab);
-    if (key) {
-        const prev = regionsDraftByKey.value[key] || {};
-        regionsDraftByKey.value[key] = {
-            ...prev,
-            geomArr: [geom],
-            geom,
-        };
-    }
-    regionsDraftByIndex.value[activeVariety.value] = { geomArr: [geom], geom };
-    regionGeom.value = geom;
-};
-
-const handleVarietyClick = (tab, index) => {
-    clearDeleteSelectionState();
-    // 取消上一次延迟渲染,避免快速切换 tab / 切换编辑态时重复追加要素
-    clearPendingGeomRenderTimer();
-
-    // 若存在“未闭环”的绘制草图(Draw 的 sketch 在 overlay 上),切换时需要清掉;已闭环的要素会走 drawend 写入草稿
-    const draw = drawRegionMap.kmap?.draw;
-    const hasUnclosedSketch = !!(draw && (draw.sketchFeature_ || draw.sketchCoords_ || draw.sketchLine_));
-    if (hasUnclosedSketch) {
-        drawRegionMap.abortOngoingDrawSketch?.();
-    }
-
-    activeVariety.value = index;
-    // 取值优先级:
-    // 1) 草稿(regionsDraftByKey / regionsDraftByIndex)
-    // 2) 接口返回的 tab.geomItems[].geomWkt(你给的结构)
-    // 3) 兜底 tab.geom(兼容旧结构)
-    const draftGeom = getDraftGeomForTab(activeRegionType.value, tab, index);
-    const rawGeomArr =
-        isValidGeom(draftGeom)
-            ? [String(draftGeom).trim()]
-            : (() => {
-                const fromItems = getGeomArrFromGeomItems(tab);
-                if (fromItems.length) return fromItems;
-                return isValidGeom(tab?.geom) ? [String(tab.geom).trim()] : [];
-            })();
-    const geomArr = getEditableGeomArrForCurrentTab(tab, rawGeomArr);
-    // 保留一份“当前选中地块”的原始字符串形态给其它逻辑使用
-    regionGeom.value = geomArr.length > 1 ? JSON.stringify(geomArr) : geomArr[0] || "";
-    // 地图尚未初始化时,仅更新状态,不做图层绘制,避免首次进入重复叠加
-    if (!drawRegionMap.kmap) return;
-
-    // 确保当前大类颜色样式生效(非品种区:黄色/红色/灰色;品种区:绿色)
-    applyRegionStyles();
-
-    // 非品种区:底图显示品种区(只读绿色)+ 当前小类(按当前大类颜色渲染)
-    // 品种区:显示其他品种只读 + 当前品种可编辑
-    if (activeRegionType.value !== "variety") {
-        if (isLockedAbnormalTab(tab)) {
-            drawRegionMap.setStatusRegions([
-                ...getAllVarietyReadonlyRegions(),
-                ...getLockedDiseaseRegions(tab),
-            ]);
-            // 查看态也需要继续渲染当前小类地块(handleStatus=1),
-            // 2/3 锁定地块仍由 setStatusRegions 只读层承载,避免被遗漏
-        } else {
-            renderAllVarietyRegionsReadonlyOnly();
-        }
-    } else {
-        renderReadonlyVarietyRegions(index);
-    }
-
-    // 切换时先清空当前可编辑图层,避免叠加
-    drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
-    if (geomArr.length > 0) {
-        pendingGeomRenderTimer.value = setTimeout(() => {
-            // 再兜底清一次,避免异步回调在 destroy/init 后仍执行导致重复追加
-            drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
-            const viewOnlySubCategoryLabel =
-                route.query.type === "viewOnly" && getCanonicalRegionTypeForStyles() !== "ABNORMAL"
-                    ? (tab.regionName || tab.problemZoneTypeName || "").toString().trim()
-                    : "";
-            const currentAreaText = formatAreaTextFromGeomArr(geomArr);
-            const viewOnlySubCategoryLabelWithArea =
-                viewOnlySubCategoryLabel && currentAreaText
-                    ? `${viewOnlySubCategoryLabel}\n${currentAreaText}`
-                    : viewOnlySubCategoryLabel;
-            drawRegionMap.setAreaGeometry(
-                geomArr,
-                false,
-                undefined,
-                undefined,
-                getAbnormalGrowthOverlayMeta,
-                viewOnlySubCategoryLabelWithArea || undefined
-            );
-            if (!viewOnly.value && activeRegionType.value !== "variety") {
-                purgeLockedFeaturesFromEditableLayer(tab);
-            }
-            // 有当前小类地块:仅 fit 当前可编辑层,避免被其它只读参考地块拉远
-            drawRegionMap.fitView?.();
-        }, 50);
-    } else {
-        // 当前小类无地块:视野包含品种区只读底图(与其它参考地块联合范围)
-        pendingGeomRenderTimer.value = setTimeout(() => {
-            drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
-            drawRegionMap.fitAllRegions?.();
-        }, 50);
-    }
-};
-
-const viewOnly = computed(() => route.query.type === "viewOnly");
-
-const point = ref(null);
-
-const regionTypeTabs = ref([]);
-const activeRegionType = ref("variety");
-const regionInfo = ref([]);
-async function fetchRegionInfo() {
-    const { data } = await VE_API.basic_farm.fetchRegionInfo({ subjectId: route.query.subjectId });
-    if (data && data.length > 0) {
-        regionInfo.value = data[0] || [];
-        regionTypeTabs.value = regionInfo.value.problemZoneList || [];
-        regionTypeTabs.value.unshift({ name: "品种区", code: "variety" });
-        if (data[0]?.regionList?.length) {
-            if (!hasAppliedInitialVariety.value && route.query?.varietyId) {
-                activeVariety.value = resolveInitialVarietyIndex(data[0]?.regionList);
-                hasAppliedInitialVariety.value = true;
-            }
-
-            point.value = data[0].point;
-
-            varietyTabs.value = regionInfo.value.regionList || [];
-        }
-    }
-}
-
-/** 样式用的大类:与接口 tab.code 解耦(避免 ABNORMAL / 数字 code 等导致勾画色落到默认灰) */
-const getCanonicalRegionTypeForStyles = () => {
-    const raw = activeRegionType.value;
-    if (raw === "variety") return "variety";
-    const tabs = regionTypeTabs.value || [];
-    const item = tabs.find((t) => String(t?.code) === String(raw));
-    if (item) {
-        const kind = item.code;
-        if (kind) return kind;
-    }
-    return "SLEEP";
-};
-
-const ABNORMAL_BADGE_BG_DISEASE_PEST = "#E32A28";
-const ABNORMAL_BADGE_BG_GROWTH = "#F76F00";
-const DISEASE_TREATING_FILL_COLOR = "rgba(191, 91, 91, 0.36)";
-const DISEASE_TREATING_STROKE_COLOR = "rgba(224, 49, 49, 0.3)";
-const SLEEP_ZONE_STROKE_COLOR = "#A6A6A6";
-const SLEEP_ZONE_FILL_COLOR = [166, 166, 166, 0.25];
-
-const getGeomItemByFeature = (tab, feature) => {
-    if (!tab || !feature) return null;
-    const items = Array.isArray(tab.geomItems) ? tab.geomItems : [];
-    if (!items.length) return null;
-    let featureWkt = "";
-    try {
-        featureWkt = wktGeomFormat.writeGeometry(feature.getGeometry(), WGS84_WKT_OPTS);
-    } catch (_) {
-        featureWkt = "";
-    }
-    if (!isValidGeom(featureWkt)) return null;
-    const normalizeWktKey = (wkt) => String(wkt || "").replace(/\s+/g, "").trim();
-    const normalizedFeatureWkt = normalizeWktKey(featureWkt);
-    for (const item of items) {
-        const polygons = flattenWktToPolygonWktArray(item?.geomWkt);
-        if (polygons.some((w) => normalizeWktKey(w) === normalizedFeatureWkt)) {
-            return item;
-        }
-    }
-    // 兜底:仅在要素数量与 geomItems 数量一致时按索引映射,避免病害锁定态错位
-    const features = drawRegionMap.kmap?.polygonLayer?.source?.getFeatures?.() || [];
-    if (features.length === items.length) {
-        const featureIndex = features.findIndex((f) => f === feature);
-        if (featureIndex >= 0 && featureIndex < items.length) {
-            return items[featureIndex];
-        }
-    }
-    return null;
-};
-
-/** 异常区小类(长势/病害/虫害等)闭合地块后在多边形内展示标签与发现日期(查看态 setAreaGeometry 同步使用) */
-const getAbnormalGrowthOverlayMeta = (feature) => {
-    if (getCanonicalRegionTypeForStyles() !== "ABNORMAL") return null;
-    const tab = varietyTabs.value?.[activeVariety.value];
-    if (!tab) return null;
-    const geomItem = getGeomItemByFeature(tab, feature);
-    const name = (tab.problemZoneTypeName || tab.regionName || "").toString();
-    const handleStatus = String(geomItem?.handleStatus || "");
-    let badgeText = "";
-    let badgeBackground = ABNORMAL_BADGE_BG_GROWTH;
-    let badgeTextColor = "#ffffff";
-    let badgeBorderColor = "";
-    if (name.includes("病害") || name.includes("虫害")) {
-        // 病害/虫害:严格按当前地块对应 geomItem;未命中(新勾画)按“新增”展示,避免误用旧地块状态
-        const currentGeomItem = geomItem || null;
-        const currentHandleStatus = String(currentGeomItem?.handleStatus || "");
-        const currentCreateTime = currentGeomItem?.createTime;
-        const prefix = name.includes("虫害") ? "虫害" : "病害";
-        if (!currentGeomItem) {
-            badgeText = `新增${prefix}`;
-            badgeBackground = ABNORMAL_BADGE_BG_DISEASE_PEST;
-        } else if (currentHandleStatus === "2") {
-            badgeText = `${prefix}治疗中`;
-            badgeTextColor = ABNORMAL_BADGE_BG_DISEASE_PEST;
-            badgeBackground = "#fff";
-            badgeBorderColor = ABNORMAL_BADGE_BG_DISEASE_PEST;
-        } else if (currentHandleStatus == "3") {
-            badgeText = `${prefix}已控制`;
-            // 已控制态与休眠区视觉保持一致
-            badgeBackground = SLEEP_ZONE_STROKE_COLOR;
-        } else {
-            badgeText = `新增${prefix}`;
-            badgeBackground = ABNORMAL_BADGE_BG_DISEASE_PEST;
-        }
-        const rawCreateTime = currentCreateTime || tab?.createTime;
-        const sourceDate = rawCreateTime ? new Date(rawCreateTime) : new Date();
-        const resolvedDate = Number.isNaN(sourceDate.getTime()) ? new Date() : sourceDate;
-        const y = resolvedDate.getFullYear();
-        const m = String(resolvedDate.getMonth() + 1).padStart(2, "0");
-        const d = String(resolvedDate.getDate()).padStart(2, "0");
-        return {
-            badgeText,
-            discoveryDate: `${y}.${m}.${d}`,
-            badgeBackground,
-            badgeTextColor,
-            badgeBorderColor,
-            handleStatus: currentHandleStatus,
-        };
-    } else if (name.includes("过慢")) {
-        if (handleStatus === "2") {
-            badgeText = "长势过慢治疗中";
-            badgeTextColor = ABNORMAL_BADGE_BG_GROWTH;
-            badgeBackground = "#fff";
-            badgeBorderColor = ABNORMAL_BADGE_BG_GROWTH;
-        } else {
-            badgeText = "新增长势过慢";
-        }
-    } else if (name.includes("过快")) {
-        if (handleStatus === "2") {
-            badgeText = "长势过快治疗中";
-            badgeTextColor = ABNORMAL_BADGE_BG_GROWTH;
-            badgeBackground = "#fff";
-            badgeBorderColor = ABNORMAL_BADGE_BG_GROWTH;
-        } else {
-            badgeText = "新增长势过快";
-        }
-    } else {
-        return null;
-    }
-    const rawCreateTime = geomItem?.createTime || tab?.createTime;
-    const sourceDate = rawCreateTime ? new Date(rawCreateTime) : new Date();
-    const resolvedDate = Number.isNaN(sourceDate.getTime()) ? new Date() : sourceDate;
-    const y = resolvedDate.getFullYear();
-    const m = String(resolvedDate.getMonth() + 1).padStart(2, "0");
-    const d = String(resolvedDate.getDate()).padStart(2, "0");
-    return {
-        badgeText,
-        discoveryDate: `${y}.${m}.${d}`,
-        badgeBackground,
-        badgeTextColor,
-        badgeBorderColor,
-        handleStatus,
-    };
-};
-
-const findProblemZoneGroupByDrawType = (majorType) => {
-    if (!majorType || majorType === "variety") return null;
-    const list = regionInfo.value?.problemZoneList || [];
-    return (
-        list.find((x) => x.code === majorType) ||
-        list.find((x) => String(x?.code) === String(majorType))
-    );
-};
-
-const getTabsForMajorType = (majorType) => {
-    if (majorType === "variety") {
-        return regionInfo.value?.regionList || [];
-    }
-    const g = findProblemZoneGroupByDrawType(majorType);
-    return g?.children || [];
-};
-
-const findTabIndexForCategory = (tabs, category) => {
-    if (!Array.isArray(tabs) || !category || typeof category !== "object") return -1;
-    const fields = ["regionId", "problemZoneTypeId", "typeId", "id"];
-    for (let i = 0; i < tabs.length; i++) {
-        const t = tabs[i];
-        for (const f of fields) {
-            const cv = category[f];
-            const tv = t[f];
-            if (cv != null && cv !== "" && tv != null && String(cv) === String(tv)) return i;
-        }
-    }
-    const cname = (category.regionName || category.problemZoneTypeName || "").toString().trim();
-    if (cname) {
-        const idx = tabs.findIndex((t) => {
-            const tn = (t.regionName || t.problemZoneTypeName || "").toString().trim();
-            return tn === cname;
-        });
-        if (idx >= 0) return idx;
-    }
-    return -1;
-};
-
-/** 仅提交本次有勾画草稿(regionsDraftByKey)的品种区,不带未勾画项 */
-const buildRegionListForSubmit = () => {
-    const list = regionInfo.value?.regionList || [];
-    const out = [];
-    list.forEach((tab) => {
-        const k = draftKeyFromParts("variety", tab);
-        const d = k ? regionsDraftByKey.value[k] : null;
-        const geom = d?.geom != null ? String(d.geom).trim() : "";
-        if (!isValidGeom(geom)) return;
-        out.push({
-            regionId: tab.regionId,
-            typeId: tab.typeId,
-            regionName: tab.regionName,
-            geom,
-        });
-    });
-    return out;
-};
-
-/** 仅包含有勾画草稿的问题分区子项;无任何子项勾画的分组整组不传 */
-const buildProblemZoneListForSubmit = () => {
-    const raw = regionInfo.value?.problemZoneList || [];
-    const subjectId = route.query.subjectId;
-    const groups = [];
-    raw.forEach((group) => {
-        const canonical = group.code;
-        const children = (group.children || [])
-            .map((child) => {
-                if (!canonical) return null;
-                const k = draftKeyFromParts(canonical, child);
-                const d = k ? regionsDraftByKey.value[k] : null;
-                let geomItems = Array.isArray(d?.geomItems)
-                    ? d.geomItems
-                    : [];
-                geomItems = geomItems
-                    .map((x) => {
-                        const geomWkt = x?.geomWkt != null ? String(x.geomWkt).trim() : "";
-                        if (!isValidGeom(geomWkt)) return null;
-                        return {
-                            ...x,
-                            geomWkt,
-                            remark: x?.remark != null ? String(x.remark) : "",
-                        };
-                    })
-                    .filter(Boolean);
-                if (geomItems.length === 0) {
-                    const geomWkt = d?.geom != null ? String(d.geom).trim() : "";
-                    if (!isValidGeom(geomWkt)) return null;
-                    const remark =
-                        d && "remark" in d && d.remark != null ? String(d.remark) : "";
-                    geomItems = [{ geomWkt, remark }];
-                }
-                return {
-                    farmSubjectId: subjectId,
-                    problemZoneTypeId: child.problemZoneTypeId ?? child.typeId ?? "",
-                    problemZoneTypeName: child.problemZoneTypeName ?? child.regionName ?? "",
-                    parentName: group.name ?? "",
-                    parentCode: group.code ?? "",
-                    geomItems,
-                };
-            })
-            .filter(Boolean);
-        if (children.length === 0) return;
-        groups.push({
-            name: group.name,
-            code: group.code,
-            children,
-        });
-    });
-    return groups;
-};
-
-onActivated(async () => {
-    activeVariety.value = 0;
-    hasAppliedInitialVariety.value = false;
-    clearPendingGeomRenderTimer();
-    // keep-alive 场景下再次进入前先销毁旧地图实例,避免重复 init 导致图层状态错位
-    if (drawRegionMap.kmap) {
-        drawRegionMap.abortOngoingDrawSketch?.();
-        drawRegionMap.destroyMap?.();
-    }
-
-    type.value = route.query.type;
-    const editable = !viewOnly.value;
-    await fetchRegionInfo();
-    drawRegionMap.initMap(point.value, mapContainer.value, editable, true, true, syncClosedDrawToDraft);
-    applyRegionStyles();
-
-    // 首次进入时,fetch 阶段可能先于地图初始化触发了 tab 渲染;
-    // 这里在地图可用后再补渲一次,确保“其他品种只读地块”能显示出来
-    if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
-        handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
-    }
-
-
-    // 从编辑态进入仅查看时,需重新初始化为不可编辑
-    if (viewOnly.value && drawRegionMap.kmap && drawRegionMap.editable) {
-        drawRegionMap.destroyMap();
-        drawRegionMap.initMap(point.value, mapContainer.value, false, true, false, syncClosedDrawToDraft);
-        applyRegionStyles();
-        if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
-            handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
-        }
-    }
-
-    // 从仅查看进入勾画(编辑)时,需重新初始化为可编辑
-    if (!viewOnly.value && drawRegionMap.kmap && !drawRegionMap.editable) {
-        drawRegionMap.destroyMap();
-        drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
-        applyRegionStyles();
-        if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
-            handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
-        }
-    }
-
-    // 查看模式下已通过 fitAllRegions 适配;编辑模式再设置地图中心
-    if (!viewOnly.value) {
-        drawRegionMap.setMapPosition(convertPointToArray(point.value));
-    }
-
-    resizeMapToContainer();
-});
-
-watch(
-    () => [varietyTabs.value.length, activeRegionType.value, activeVariety.value],
-    () => {
-        if (drawRegionMap.kmap?.map) resizeMapToContainer();
-    }
-);
-
-onDeactivated(() => {
-    clearDeleteSelectionState();
-    activeVariety.value = 0;
-    activeRegionType.value = "variety";
-    clearPendingGeomRenderTimer();
-    // 离开页面时中止未完成绘制并销毁地图,确保下次进入是干净实例
-    drawRegionMap.abortOngoingDrawSketch?.();
-    drawRegionMap.destroyMap?.();
-})
-const goBack = () => {
-    if (route.query.targetUrl) {
-        router.replace(route.query.targetUrl);
-        return;
-    }
-    router.go(-1);
-};
-
-const resetPolygon = () => {
-    clearDeleteSelectionState();
-    ElMessageBox.confirm(
-        "确认重置当前地块吗?重置后将恢复为初始状态",
-        "重置确认",
-        {
-            confirmButtonText: "确认重置",
-            cancelButtonText: "取消",
-            type: "warning",
-        }
-    )
-        .then(() => {
-            // 先取消进行中的勾画草图(未完成时线条在 Draw 的 overlay 上,清 source 去不掉)
-            drawRegionMap.abortOngoingDrawSketch();
-            // 只清空当前可编辑多边形,不影响只读状态图层
-            if (drawRegionMap.kmap && drawRegionMap.kmap.polygonLayer && drawRegionMap.kmap.polygonLayer.source) {
-                drawRegionMap.kmap.polygonLayer.source.clear();
-            }
-
-            // 清空当前 tab 草稿,重置应回到“进入时初始化值”
-            const currentTab = varietyTabs.value?.[activeVariety.value];
-            const currentKey = draftKeyFromParts(activeRegionType.value, currentTab);
-            if (currentKey && regionsDraftByKey.value[currentKey]) {
-                delete regionsDraftByKey.value[currentKey];
-            }
-            if (regionsDraftByIndex.value[activeVariety.value]) {
-                delete regionsDraftByIndex.value[activeVariety.value];
-            }
-
-            // 当前品类有初始化地块则回显;没有则保持空地图
-            const initialGeomArrRaw = (() => {
-                const fromItems = getGeomArrFromGeomItems(currentTab);
-                if (fromItems.length) return fromItems;
-                return isValidGeom(currentTab?.geom) ? [String(currentTab.geom).trim()] : [];
-            })();
-            const initialGeomArr = getEditableGeomArrForCurrentTab(currentTab, initialGeomArrRaw);
-            if (
-                !viewOnly.value &&
-                activeRegionType.value !== "variety" &&
-                isLockedAbnormalTab(currentTab)
-            ) {
-                drawRegionMap.setStatusRegions([
-                    ...getAllVarietyReadonlyRegions(),
-                    ...getLockedDiseaseRegions(currentTab),
-                ]);
-            }
-            if (initialGeomArr.length > 0) {
-                drawRegionMap.setAreaGeometry(
-                    initialGeomArr,
-                    false,
-                    undefined,
-                    undefined,
-                    getAbnormalGrowthOverlayMeta
-                );
-                regionGeom.value =
-                    initialGeomArr.length > 1 ? JSON.stringify(initialGeomArr) : initialGeomArr[0];
-            } else {
-                regionGeom.value = "";
-                drawRegionMap.fitAllRegions?.();
-            }
-            ElMessage.success("地块已重置");
-        })
-        .catch(() => {
-            // 用户取消重置,不做任何操作
-        });
-};
-
-const submitRegions = async () => {
-    if (submitting.value) return;
-    const regionList = buildRegionListForSubmit();
-    const problemZoneList = buildProblemZoneListForSubmit();
-    if (regionList.length === 0 && problemZoneList.length === 0) {
-        ElMessage.warning("请先勾画地块后再确认");
-        return false;
-    }
-    submitting.value = true;
-    try {
-        const params = {
-            subjectId: route.query.subjectId,
-            regionList,
-            problemZoneList,
-        };
-        const res = await VE_API.basic_farm.ediRegionZone(params);
-        if (res?.code === 0) {
-            if (selectedDrawTypeMeta.value.type === 'ABNORMAL') {
-                let problemZoneId = null;
-                if (params.problemZoneList.length) {
-                    res.data[0].problemZoneList.forEach(element => {
-                        if (element.code === selectedDrawTypeMeta.value.type) {
-                            element.children.forEach(item => {
-                                if (item.problemZoneTypeName === selectedDrawTypeMeta.value.category.problemZoneTypeName) {
-                                    problemZoneId = item.id;
-                                }
-                            });
-                        }
-                    });
-                }
-                VE_API.basic_farm.saveProblemZoneImage({
-                    problemZoneId,
-                    imagePathList: selectedDrawTypeMeta.value.images,
-                })
-            }
-            return true;
-        }
-        ElMessage.error(res?.msg || "保存失败");
-        return false;
-    } catch (e) {
-        ElMessage.error("保存失败");
-        return false;
-    } finally {
-        submitting.value = false;
-    }
-};
-
-const submitCurrentTabGeometryChange = async (geomWktOrArr) => {
-    const tab = varietyTabs.value?.[activeVariety.value];
-    if (!tab) return false;
-    const geometryArr = Array.isArray(geomWktOrArr)
-        ? geomWktOrArr
-        : isValidGeom(geomWktOrArr)
-            ? [String(geomWktOrArr).trim()]
-            : [];
-    const normalizedGeom = mergePolygonWktsForApi(geometryArr);
-    const params = {
-        subjectId: route.query.subjectId,
-        regionList: [],
-        problemZoneList: [],
-    };
-
-    if (activeRegionType.value === "variety") {
-        params.regionList = [
-            {
-                regionId: tab.regionId,
-                typeId: tab.typeId,
-                regionName: tab.regionName,
-                geom: normalizedGeom,
-            },
-        ];
-    } else {
-        const group = findProblemZoneGroupByDrawType(activeRegionType.value);
-        if (!group) return false;
-        const geomItems = isLockedAbnormalTab(tab)
-            ? buildDiseaseGeomItemsForSubmit(tab, geometryArr)
-            : buildGeomItemsFromGeometryArr(tab, geometryArr);
-        params.problemZoneList = [
-            {
-                name: group.name,
-                code: group.code,
-                children: [
-                    {
-                        farmSubjectId: route.query.subjectId,
-                        problemZoneTypeId: tab.problemZoneTypeId ?? tab.typeId ?? "",
-                        problemZoneTypeName: tab.problemZoneTypeName ?? tab.regionName ?? "",
-                        parentName: group.name ?? "",
-                        parentCode: group.code ?? "",
-                        geomItems,
-                    },
-                ],
-            },
-        ];
-    }
-
-    const res = await VE_API.basic_farm.ediRegionZone(params);
-    return res?.code === 0;
-};
-
-/** 以弹窗 confirm 传入的 drawMeta(大类 type + 小类 category + remark)为准写入草稿并提交 */
-const confirmArea = async (drawMeta) => {
-    const meta =
-        drawMeta && drawMeta.type != null
-            ? drawMeta
-            : selectedDrawTypeMeta.value;
-    if (!meta?.type || meta.category == null) {
-        ElMessage.warning("请先在弹窗中选择勾画类型与类别");
-        return;
-    }
-    const polygonData = drawRegionMap.getAreaGeometry?.();
-    const geometryArr = polygonData?.geometryArr;
-    if (!Array.isArray(geometryArr) || geometryArr.length === 0) {
-        ElMessage.warning("请先勾画地块后再确认");
-        return;
-    }
-    const normalizedGeomArr = flattenGeomWktListForMap(geometryArr);
-    if (!Array.isArray(normalizedGeomArr) || normalizedGeomArr.length === 0) {
-        ElMessage.warning("地块几何无效,请重新勾画");
-        return;
-    }
-    const key = draftKeyFromParts(meta.type, meta.category);
-    if (!key) {
-        ElMessage.warning("无法识别勾画类别,请重新选择");
-        return;
-    }
-    const geom = mergePolygonWktsForApi(normalizedGeomArr);
-    const currentTab = varietyTabs.value?.[activeVariety.value];
-    const nextDraft = {
-        geomArr: normalizedGeomArr,
-        geom,
-        remark: meta.remark != null ? String(meta.remark) : "",
-    };
-    if (meta.type !== "variety") {
-        nextDraft.geomItems = isLockedAbnormalTab(currentTab)
-            ? buildDiseaseGeomItemsForSubmit(currentTab, normalizedGeomArr, meta.remark)
-            : buildGeomItemsFromGeometryArr(currentTab, normalizedGeomArr, meta.remark);
-    }
-    regionsDraftByKey.value[key] = nextDraft;
-    const tabList = getTabsForMajorType(meta.type);
-    const idx = findTabIndexForCategory(tabList, meta.category);
-    if (activeRegionType.value === meta.type && idx >= 0) {
-        regionsDraftByIndex.value[idx] = { geomArr: normalizedGeomArr, geom };
-    }
-
-    const ok = await submitRegions();
-    const rid = meta.category?.regionId;
-    if (rid != null && rid !== "") {
-        try {
-            await VE_API.basic_farm.updateLastViewTime({ regionId: rid });
-        } catch (_) {
-            /* 非品种区可能无 regionId,忽略 */
-        }
-    }
-    if (!ok) return;
-
-    // 保存成功后:不跳走,刷新当前页并回显最新数据,并切换为查看态
-    try {
-        await fetchRegionInfo();
-        // 接口已是最新几何与 id,清空草稿避免旧 key/下标回退遮挡 geomItems
-        clearAllRegionDrafts();
-
-        // 恢复当前大类下的子类 tab(fetchRegionInfo 默认会填充品种区)
-        if (activeRegionType.value === "variety") {
-            varietyTabs.value = regionInfo.value?.regionList || [];
-        } else {
-            const group = (regionTypeTabs.value || []).find(
-                (x) => x?.code === activeRegionType.value
-            );
-            varietyTabs.value = group?.children || [];
-        }
-
-        // 更新路由为查看态,确保按钮/头部状态同步
-        try {
-            router.replace({ query: { ...route.query, type: "viewOnly" } });
-        } catch (_) {
-            // 路由更新失败不影响回显
-        }
-
-        // 重新初始化地图(非编辑/查看模式),确保回显形状正确
-        if (drawRegionMap.kmap) {
-            drawRegionMap.destroyMap?.();
-        }
-        drawRegionMap.initMap(point.value, mapContainer.value, false, true, false);
-        applyRegionStyles();
-        if (varietyTabs.value.length > 0 && varietyTabs.value[activeVariety.value]) {
-            handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
-        }
-        drawRegionMap.fitAllRegions?.();
-    } catch (_) {
-        // 刷新失败不阻断用户继续操作,保持当前页面状态
-    }
-
-    if (route.query.showTipPopup) {
-        showTipPopup.value = true;
-        return;
-    }
-};
-
-const openConfirmDrawTypePopup = () => {
-    const polygonData = drawRegionMap.getAreaGeometry?.();
-    const geometryArr = polygonData?.geometryArr;
-    if (!Array.isArray(geometryArr) || geometryArr.length === 0) {
-        ElMessage.warning("请先勾画地块后再确认");
-        return;
-    }
-
-    const remark = varietyTabs?.value?.[activeVariety.value]?.geomItems?.[0]?.remark;
-    confirmDrawTypePopupRef.value.openPopup({
-        regionInfo: regionInfo.value,
-        activeRegionType: activeRegionType.value,
-        activeVarietyIndex: activeVariety.value,
-        remark: activeRegionType.value === 'variety' ? '' : remark,
-    });
-};
-
-const handleConfirmDrawType = async (payload) => {
-    selectedDrawTypeMeta.value = payload;
-    await confirmArea(payload);
-};
-
-const handleEditRegion = async () => {
-    clearDeleteSelectionState();
-    // 从查看态切换到可勾画编辑态:移除查看标记(所有大类共用)
-    const nextQuery = { ...route.query };
-    delete nextQuery.type;
-    delete nextQuery.viewOnly;
-    clearPendingGeomRenderTimer();
-    await router.replace({ query: nextQuery });
-
-    nextTick(() => {
-        if (drawRegionMap.kmap) {
-            drawRegionMap.abortOngoingDrawSketch?.();
-            drawRegionMap.destroyMap();
-        }
-
-        // 若当前不在品种区(如环境/异常/休眠),点击“编辑”进入当前问题区的编辑态:
-        // - 地图可编辑(仅编辑当前选中的问题区子项)
-        // - 只显示「品种区」地块作为底图参考(只读)
-        // - 不显示其它问题区地块
-        if (activeRegionType.value !== "variety") {
-            drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
-            applyRegionStyles();
-            // 清空当前可编辑图层,避免残留
-            drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
-            const tab = varietyTabs.value?.[activeVariety.value];
-            if (isLockedAbnormalTab(tab)) {
-                drawRegionMap.setStatusRegions([
-                    ...getAllVarietyReadonlyRegions(),
-                    ...getLockedDiseaseRegions(tab),
-                ]);
-            } else {
-                renderAllVarietyRegionsReadonlyOnly();
-            }
-
-            // 进入编辑时:缩放到当前要编辑的地块
-            // 异常锁定小类(2/3)进入编辑态时,禁止从 tab.geom / draftGeom 回填到可编辑层,避免与只读层重叠
-            const currentGeomArrRaw = isLockedAbnormalTab(tab)
-                ? getGeomArrFromGeomItems(tab)
-                : (() => {
-                    const currentGeomStr = tab
-                        ? (getDraftGeomForTab(activeRegionType.value, tab, activeVariety.value) || tab.geom)
-                        : "";
-                    return isValidGeom(currentGeomStr)
-                        ? [String(currentGeomStr).trim()]
-                        : getGeomArrFromGeomItems(tab);
-                })();
-            const currentGeomArr = getEditableGeomArrForCurrentTab(tab, currentGeomArrRaw);
-            regionGeom.value =
-                currentGeomArr.length > 1 ? JSON.stringify(currentGeomArr) : currentGeomArr[0] || "";
-            if (currentGeomArr.length > 0) {
-                drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
-                drawRegionMap.setAreaGeometry(
-                    currentGeomArr,
-                    true,
-                    undefined,
-                    undefined,
-                    getAbnormalGrowthOverlayMeta
-                );
-                purgeLockedFeaturesFromEditableLayer(tab);
-            } else {
-                // 仍自适应到品种区底图
-                drawRegionMap.fitAllRegions?.();
-            }
-            return;
-        }
-
-        drawRegionMap.initMap(point.value, mapContainer.value, true, true, true, syncClosedDrawToDraft);
-        applyRegionStyles();
-
-        // 切到编辑态后:统一走一遍当前 tab 的点击逻辑,确保所有有地块的品种都能显示
-        if (varietyTabs.value.length && varietyTabs.value[activeVariety.value]) {
-            // 进入编辑时:让当前品种地块显示且缩放到当前编辑地块
-            handleVarietyClick(varietyTabs.value[activeVariety.value], activeVariety.value);
-            const tab = varietyTabs.value[activeVariety.value];
-            const draftGeom = getDraftGeomForTab(activeRegionType.value, tab, activeVariety.value);
-            const rawGeomArr =
-                isValidGeom(draftGeom)
-                    ? [String(draftGeom).trim()]
-                    : (() => {
-                        const fromItems = getGeomArrFromGeomItems(tab);
-                        if (fromItems.length) return fromItems;
-                        return isValidGeom(tab?.geom) ? [String(tab.geom).trim()] : [];
-                    })();
-            const geomArr = flattenGeomWktListForMap(rawGeomArr);
-            drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
-            if (geomArr.length > 0) {
-                drawRegionMap.setAreaGeometry(
-                    geomArr,
-                    true,
-                    undefined,
-                    undefined,
-                    getAbnormalGrowthOverlayMeta
-                );
-            }
-        } else {
-            renderReadonlyVarietyRegions(activeVariety.value);
-            const fallbackGeom = regionGeom.value;
-            if (isValidGeom(fallbackGeom)) {
-                drawRegionMap.kmap?.polygonLayer?.source?.clear?.();
-                drawRegionMap.setAreaGeometry(
-                    [fallbackGeom],
-                    true,
-                    undefined,
-                    undefined,
-                    getAbnormalGrowthOverlayMeta
-                );
-            }
-        }
-        // 编辑态下:保持缩放在当前要编辑地块,不再强制 fitAllRegions 覆盖
-    });
-};
-
-const showTipPopup = ref(false);
-const handleTipConfirm = () => {
-    const query = {
-        hideInteraction: "true",
-    };
-    if (route.query.addVarietyCount) {
-        query.addVarietyCount = String(route.query.addVarietyCount);
-    }
-    router.push({ path: "/growth_report", query });
-}
-</script>
-
-<style lang="scss" scoped>
-.edit-map {
-    width: 100%;
-    height: 100vh;
-    overflow: hidden;
-    display: flex;
-    flex-direction: column;
-    box-sizing: border-box;
-
-    &> :first-child {
-        flex-shrink: 0;
-    }
-
-    .region-type-tabs {
-        flex-shrink: 0;
-        display: flex;
-        align-items: center;
-        background: #f4f4f4;
-        margin: 10px 10px 0;
-        padding: 3px;
-        border-radius: 4px;
-        box-sizing: border-box;
-
-        .region-type-tab {
-            flex: 1;
-            text-align: center;
-            padding: 5px 0;
-            color: #767676;
-        }
-
-        .region-type-tab--active {
-            background: #ffffff;
-            border-radius: 4px;
-            color: #0D0D0D;
-        }
-    }
-
-    .variety-tabs {
-        flex-shrink: 0;
-        display: flex;
-        align-items: center;
-        gap: 8px;
-        padding: 10px 12px 0;
-        overflow-x: auto;
-        overflow-y: hidden;
-        flex-wrap: nowrap;
-        -webkit-overflow-scrolling: touch;
-
-        .variety-tab {
-            padding: 4px 12px;
-            border-radius: 2px;
-            color: #575757;
-            background: #F4F4F4;
-            border: 1px solid transparent;
-            white-space: nowrap;
-        }
-
-        .variety-tab--active {
-            background: rgba(33, 153, 248, 0.1);
-            color: #2199F8;
-            border: 1px solid #2199F8;
-        }
-    }
-
-    .edit-map-content {
-        width: 100%;
-        margin-top: 10px;
-        flex: 1;
-        min-height: 0;
-        position: relative;
-        box-sizing: border-box;
-        /* 底部「重置 / 确认」等为 position:fixed,占高约 68px,地图区域需预留避免被盖住 */
-        padding-bottom: 68px;
-
-        .edit-map-tip {
-            position: absolute;
-            top: 23px;
-            left: calc(50% - 256px / 2);
-            z-index: 1;
-            font-size: 12px;
-            color: #fff;
-            padding: 9px 20px;
-            background: rgba(0, 0, 0, 0.5);
-            border-radius: 20px;
-        }
-
-        .map-container {
-            width: 100%;
-            height: 100%;
-        }
-
-        .edit-map-footer {
-            position: absolute;
-            bottom: 85px;
-            left: 12px;
-            width: calc(100% - 24px);
-            display: flex;
-            flex-direction: column;
-            align-items: flex-end;
-
-            .footer-back {
-                padding: 4px 5px 7px;
-                background: #fff;
-                border-radius: 8px;
-                margin-bottom: 12px;
-
-                .back-icon {
-                    width: 23px;
-                    height: 23px;
-                }
-            }
-
-            .edit-map-footer-btn {
-                display: flex;
-                justify-content: space-between;
-                align-items: center;
-                width: 100%;
-                position: fixed;
-                bottom: 0;
-                left: 0;
-                background: #fff;
-                padding: 10px 12px 20px 12px;
-                box-sizing: border-box;
-
-                &.confirm-btn-box {
-                    justify-content: center;
-                }
-
-                div {
-                    width: 100px;
-                    text-align: center;
-                    color: #666666;
-                    font-size: 14px;
-                    padding: 8px 0;
-                    border-radius: 25px;
-                    border: 0.5px solid rgba(153, 153, 153, 0.5);
-                }
-
-                .btn-confirm {
-                    background: #2199F8;
-                    color: #fff;
-                    border: 1px solid #2199F8;
-                }
-            }
-        }
-    }
-}
-</style>

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

@@ -1,387 +0,0 @@
-<template>
-    <custom-header :name="$t('农场基本信息')" bgColor="#f2f3f5"></custom-header>
-    <div class="farm-details-page">
-        <div class="info-box info-card">
-            <div class="section-header">
-                <div class="line-title">{{ t('基本信息') }}</div>
-                <div class="edit-btn-box">
-                    <div class="edit-btn" @click="handleAddVariety">{{ t('新增品种') }}</div>
-                    <div class="edit-btn" @click="handleEditFarmInfo">{{ t('编辑信息') }}</div>
-                </div>
-            </div>
-            <div class="info-list">
-                <div class="info-row">
-                    <span class="info-label">{{ t('农场名称:') }}</span>
-                    <span class="info-value">{{ farmInfo.subjectName }}</span>
-                </div>
-                <div class="info-row">
-                    <span class="info-label">{{ t('农场面积:') }}</span>
-                    <span class="info-value">{{ farmInfo.farmArea }}亩</span>
-                </div>
-                <div class="info-row">
-                    <span class="info-label">{{ t('农场位置:') }}</span>
-                    <span class="info-value">{{ farmInfo.farmAddress }}</span>
-                </div>
-            </div>
-        </div>
-        <div class="info-box info-card">
-            <div class="section-header">
-                <div class="line-title">{{ t('土壤性质') }}</div>
-                <div class="edit-btn" @click="handleEditSoil">{{ t('编辑信息') }}</div>
-            </div>
-            <div class="info-list grid-list">
-                <div class="grid-item">
-                    <div class="grid-value">{{ t('壤土') }}</div>
-                    <div class="grid-name">{{ t('质地') }}</div>
-                </div>
-                <div class="grid-item">
-                    <div class="grid-value">1%</div>
-                    <div class="grid-name">{{ t('有机质') }}</div>
-                </div>
-                <div class="grid-item">
-                    <div class="grid-value">5.5</div>
-                    <div class="grid-name">PH</div>
-                </div>
-            </div>
-        </div>
-        <div class="info-box info-card">
-            <div class="section-header">
-                <div class="line-title">{{ t('历史高发风险') }}</div>
-                <div class="edit-btn only-text" @click="handleEditFarmFacility">{{ t('查看更多') }}<el-icon><ArrowRight /></el-icon></div>
-            </div>
-            <div class="info-list">
-                <span class="text-label">{{ t('物候风险:') }}</span> 风险描述风险描述风险描述风险描述风险
-            </div>
-        </div>
-        <div class="info-box info-card">
-            <div class="section-header">
-                <div class="line-title">{{ t('种植类别') }}</div>
-            </div>
-            <div class="info-list">
-                <div class="info-row">
-                    <span class="info-label">{{ t('过往种植:') }}</span>
-                    <div class="info-value crop-tags">
-                        <span v-for="crop in farmInfo.regionList" :key="crop.regionId" class="crop-tag dark-tag">
-                            {{ crop.regionName }}
-                        </span>
-                        <span class="crop-tag border-tag" @click="handleAddVariety">{{ t('+新增品种') }}</span>
-                    </div>
-                </div>
-                <div class="info-row line-break">
-                    <div class="info-label">{{ t('当季作物:') }}</div>
-                    <div class="season-box">
-                        <div class="info-value crop-tags">
-                            <span class="crop-tag">
-                                桂味
-                            </span>
-                        </div>
-                        <div class="season-content">
-                            <div class="season-item">{{ t('桂味-上市时间:06.08') }}</div>
-                            <div class="season-item">{{ t('桂味-上市时间:06.08') }}</div>
-                        </div>
-                    </div>
-                    <div class="season-box">
-                        <div class="info-value crop-tags">
-                            <span class="crop-tag">
-                                桂味
-                            </span>
-                        </div>
-                        <div class="season-content">
-                            <div class="season-item">{{ t('桂味-上市时间:06.08') }}</div>
-                            <div class="season-item">{{ t('桂味-上市时间:06.08') }}</div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <FarmInfoPopup ref="farmInfoPopupRef" :farmId="route.query.subjectId" @success="fetchFarmSubjectDetail" />
-
-    <SoilPopup ref="soilPopupRef" />
-</template>
-
-<script setup>
-import { useI18n } from "@/i18n";
-const { t } = useI18n();
-import { ref, onMounted } from "vue";
-import customHeader from "@/components/customHeader.vue";
-import { useRouter, useRoute } from "vue-router";
-import FarmInfoPopup from "@/views/old_mini/home/components/farmInfoPopup.vue";
-import SoilPopup from "./soilPopup.vue";
-
-const router = useRouter();
-const route = useRoute();
-const farmInfo = ref({});
-
-onMounted(() => {
-    fetchFarmSubjectDetail();
-    fetchBasicFarmFormData();
-});
-
-function fetchFarmSubjectDetail() {
-    VE_API.basic_farm.fetchFarmSubjectDetail({ subjectId: route.query.subjectId }).then(({ data }) => {
-        farmInfo.value = data || {};
-    });
-}
-
-const basicFarmInfo = ref({});
-function fetchBasicFarmFormData() {
-    VE_API.basic_farm.fetchBasicFarmFormData({ subjectId: route.query.subjectId }).then(({ data, code }) => {
-        if (code === 0) {
-            basicFarmInfo.value = {
-                ...data,
-                irrigation: data.irrigationMethods.filter(item => item.selected),
-            }
-        }
-    });
-}
-
-const farmInfoPopupRef = ref(null);
-const handleEditFarmInfo = () => {
-    // // 回显地块:存到 polygonData,创建页会优先使用这里的数据
-    // if (data.geomWkt) {
-    //     const polygonData = {
-    //         geometryArr: [data.geomWkt],
-    //         mianji: data.mianji,
-    //         isConfirmed: true,
-    //     };
-    //     store.commit("home/SET_FARM_POLYGON", polygonData);
-    // } else {
-    //     store.commit("home/SET_FARM_POLYGON", null);
-    // }
-
-    // const params = {
-    //     ...farmInfo.value,
-    //     name: farmInfo.value.subjectName,
-    //     fzr: farmInfo.value.contactName,
-    //     tel: farmInfo.value.contactPhone,
-    //     mianji: farmInfo.value.farmArea,
-    //     address: farmInfo.value.farmAddress,
-    // };
-
-    // // 回显其他表单字段
-    // store.commit("home/SET_EDIT_FARM_DATA", params);
-
-    // // 带上 from=details,创建页提交/取消后能正确返回
-    // router.push(`/create_farm?type=edit&farmId=${route.query.subjectId}&from=details`);
-
-    farmInfoPopupRef.value.handleShow();
-};
-
-const soilPopupRef = ref(null);
-const handleEditSoil = () => {
-    soilPopupRef.value.open();
-};
-
-const handleEditFarmFacility = () => {
-    router.push(`/prescription?subjectId=${route.query.subjectId}`);
-};
-
-const handleAddVariety = () => {
-    router.push(`/interaction?addVariety=true&subjectId=${route.query.subjectId}`);
-};
-</script>
-
-<style lang="scss" scoped>
-.farm-details-page {
-    background: #f2f3f5;
-    height: calc(100vh - 40px);
-    padding: 0 12px;
-    overflow: auto;
-
-    .line-title {
-        position: relative;
-        padding-left: 14px;
-        font-size: 16px;
-
-        &::before {
-            content: "";
-            position: absolute;
-            left: 5px;
-            top: 50%;
-            transform: translateY(-50%);
-            width: 4px;
-            height: 15px;
-            background: #2199f8;
-            border-radius: 20px;
-        }
-    }
-
-    .info-card{
-        margin-top: 12px;
-        background: #fff;
-        border-radius: 6px;
-        padding: 10px;
-    }
-
-    .info-box {
-        margin-top: 12px;
-
-        .section-header {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-        }
-
-        .edit-btn-box {
-            display: flex;
-            align-items: center;
-            gap: 8px;
-        }
-
-        .edit-btn {
-            padding: 4px 12px;
-            font-size: 12px;
-            color: #86909c;
-            border-radius: 999px;
-            border: 0.5px solid #d0d3d8;
-            background-color: #ffffff;
-            &.only-text {
-                border: none;
-            }
-        }
-
-        .info-list {
-            margin-top: 10px;
-            margin-left: 5px;
-
-            .info-row {
-                display: flex;
-                align-items: flex-start;
-                margin-bottom: 6px;
-
-                &.line-break {
-                    display: block;
-                }
-
-                &.center-row {
-                    align-items: center;
-                }
-
-                .info-label {
-                    min-width: 70px;
-                    color: #4E5969;
-                }
-
-                .crop-tags {
-                    display: flex;
-                    align-items: center;
-                    flex-wrap: wrap;
-                    gap: 6px;
-
-                    .crop-tag {
-                        padding: 2px 8px;
-                        background: #E8F3FF;
-                        color: #2199f8;
-                        border-radius: 2px;
-                        font-size: 12px;
-                        height: 22px;
-                        box-sizing: border-box;
-                        &.dark-tag {
-                            background: #F8F8F8;
-                            color: #7F7F7F;
-                        }
-                        &.border-tag {
-                            border: 0.5px solid #2199F8;
-                        }
-                    }
-                }
-
-                .problem-tags {
-                    display: flex;
-                    flex-wrap: wrap;
-                    gap: 6px;
-
-                    .problem-tag {
-                        padding: 2px 8px;
-                        background: rgba(58, 173, 148, 0.1);
-                        color: #3AAD94;
-                        border-radius: 2px;
-                        font-size: 13px;
-                    }
-                }
-
-                .device-value {
-                    width: 100%;
-                }
-
-                .device-box {
-                    padding: 6px;
-                    border-radius: 4px;
-                    border: 0.5px solid rgba(33, 153, 248, 0.2);
-                    display: grid;
-                    grid-template-columns: repeat(2, minmax(0, 1fr));
-                    column-gap: 12px;
-                    row-gap: 4px;
-
-                    .device-item {
-                        display: flex;
-                        align-items: center;
-                        justify-content: space-between;
-                        padding: 4px 0;
-                        min-width: 0;
-                        gap: 8px;
-                        font-size: 13px;
-                        color: #1D2129;
-
-                        .device-count {
-                            padding: 2px 8px;
-                            background: #E8F3FF;
-                            color: #2199f8;
-                            border-radius: 2px;
-                        }
-                    }
-                }
-            }
-
-            .info-row-column {
-                display: flex;
-                flex-direction: column;
-                gap: 4px;
-            }
-        }
-
-        .season-box {
-            padding-top: 8px;
-            .season-content {
-                display: grid;
-                grid-template-columns: repeat(2, 1fr);
-                gap: 2px;
-                .season-item {
-                    padding-top: 6px;
-                }
-            }
-        }
-
-        .text-label {
-            color: #4E5969;
-        }
-
-        .grid-list {
-            display: grid;
-            grid-template-columns: repeat(3, 1fr);
-            gap: 6px;
-            .grid-item {
-                background: #F5F5F5;
-                border-radius: 5px;
-                padding: 3px;
-                display: flex;
-                flex-direction: column;
-                align-items: center;
-                justify-content: center;
-                height: 50px;
-                .grid-value {
-                    font-size: 16px;
-                    color: #1D2129;
-                    // line-height: 22px;
-                }
-                .grid-name {
-                    // line-height: 14px;
-                    font-size: 12px;
-                    color: rgba(78, 89, 105, 0.5);
-                }
-            }
-        }
-    }
-}
-</style>

+ 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="$t('选择品类')"
-                    @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">{{ $t('新增农事') }}</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">{{ $t('提交方案') }}</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="$t('请输入方案名称')" 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">{{ $t('物候期时间设置') }}</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>{{ $t('起始时间') }}</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="$t('选择日期')"
-                        @change="(date) => handleStartDateChange(date, index)"
-                    />
-                </div>
-            </div>
-            <div class="phenology-footer-tip">
-                <span>{{ $t('注:') }}</span>
-                <span class="text">{{ $t('请从上往下按照时间顺序填写日期') }}</span>
-            </div>
-        </div>
-        <div class="phenology-footer" @click="handleConfirmPhenologySetting">{{ $t('确认设置') }}</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="$t('复核成效')"></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="$t('加载中...')"
-                        finished-:text="$t('没有更多了')"
-                        @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">{{ $t('查看详情') }}</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">{{ $t('需求发送成功') }}</div>
-        <div class="apply-btn" @click="showApplyPopup = false">{{ $t('我知道了') }}</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 - 251
src/views/old_mini/monitor/subPages/soilPopup.vue

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