瀏覽代碼

feat:添加诊断报告页面

wangsisi 2 小時之前
父節點
當前提交
8e26ec7594

+ 9 - 9
src/App.vue

@@ -45,30 +45,30 @@
                     />
                 </template>
             </tabbar-item>
-            <tabbar-item replace to="/agri_file">
-                <span>{{ t("tabbar.agriFile") }}</span>
+            <tabbar-item replace to="/diagnosis_report">
+                <span>诊断报告</span>
                 <template #icon="props">
                     <img
                         :src="
                             props.active
-                                ? require('@/assets/img/tab_bar/tree-active.png')
-                                : require('@/assets/img/tab_bar/tree.png')
+                                ? require('@/assets/img/tab_bar/report-active.png')
+                                : require('@/assets/img/tab_bar/report.png')
                         "
                     />
                 </template>
             </tabbar-item>
-            <!-- <tabbar-item replace to="/agri_record">
-                <span>{{ t("tabbar.agriRecord") }}</span>
+            <tabbar-item replace to="/agri_file">
+                <span>{{ t("tabbar.agriFile") }}</span>
                 <template #icon="props">
                     <img
                         :src="
                             props.active
-                                ? require('@/assets/img/tab_bar/task-active.png')
-                                : require('@/assets/img/tab_bar/task.png')
+                                ? require('@/assets/img/tab_bar/tree-active.png')
+                                : require('@/assets/img/tab_bar/tree.png')
                         "
                     />
                 </template>
-            </tabbar-item> -->
+            </tabbar-item>
             <tabbar-item replace to="/work_execute">
                 <span>{{ t("tabbar.schedule") }}</span>
                 <template #icon="props">

二進制
src/assets/img/report/base-bg.png


二進制
src/assets/img/report/base-icon.png


二進制
src/assets/img/report/star.png


二進制
src/assets/img/report/tab-1.png


二進制
src/assets/img/report/tab-2.png


二進制
src/assets/img/report/tab-3.png


二進制
src/assets/img/report/tab-4.png


二進制
src/assets/img/report/tab-5.png


二進制
src/assets/img/report/tab-act-bg.png


二進制
src/assets/img/report/tab-bg.png


二進制
src/assets/img/report/title-bg.png


二進制
src/assets/img/tab_bar/report-active.png


二進制
src/assets/img/tab_bar/report.png


+ 1 - 1
src/router/globalRoutes.js

@@ -196,7 +196,7 @@ export default [
     {
         path: "/diagnosis_report",
         name: "DiagnosisReport",
-        meta: { keepAlive: true },
+        meta: { showTabbar: true, keepAlive: true },
         component: () => import("@/views/old_mini/agri_file/pages/diagnosisReport.vue"),
     },
 ];

+ 203 - 0
src/views/old_mini/agri_file/components/adjustPhenologyPopup.vue

@@ -0,0 +1,203 @@
+<template>
+    <Popup
+        class="adjust-phenology-popup"
+        teleport="body"
+        :z-index="9999"
+        round
+        closeable
+        v-model:show="visible"
+    >
+        <div class="popup-section">
+            <div class="popup-section__title">请选择作物状态</div>
+            <div class="option-row">
+                <div
+                    v-for="item in cropStatusList"
+                    :key="item.key"
+                    class="option-tag"
+                    :class="{ selected: cropStatus === item.key }"
+                    @click="cropStatus = item.key"
+                >
+                    {{ item.label }}
+                </div>
+            </div>
+        </div>
+
+        <template v-if="cropStatus === 'growing'">
+            <div class="popup-section">
+                <div class="popup-section__title">请选择物候期</div>
+                <div class="option-scroll">
+                    <div
+                        v-for="item in phenologyList"
+                        :key="item.id"
+                        class="option-tag option-tag--scroll"
+                        :class="{ selected: phenologyId === item.id }"
+                        @click="phenologyId = item.id"
+                    >
+                        {{ item.name }}
+                    </div>
+                </div>
+            </div>
+
+            <div class="popup-section">
+                <div class="popup-section__title">请选择生育期</div>
+                <div class="option-grid">
+                    <div
+                        v-for="item in growthList"
+                        :key="item.id"
+                        class="option-tag"
+                        :class="{ selected: growthId === item.id }"
+                        @click="growthId = item.id"
+                    >
+                        {{ item.name }}
+                    </div>
+                </div>
+            </div>
+        </template>
+
+        <div class="popup-confirm" @click="handleConfirm">确认信息</div>
+    </Popup>
+</template>
+
+<script setup>
+import { ref } from "vue";
+import { Popup, showToast } from "vant";
+
+const emit = defineEmits(["confirm"]);
+
+const visible = ref(false);
+
+/** 作物状态 */
+const cropStatusList = [
+    { key: "growing", label: "生长阶段" },
+    { key: "resting", label: "休养状态" }
+];
+const cropStatus = ref("growing");
+
+/** 物候期 / 生育期:后续可替换为接口 */
+const phenologyList = ref([
+    { id: 1, name: "物候期1" },
+    { id: 2, name: "物候期2" },
+    { id: 3, name: "物候期1" },
+    { id: 4, name: "物候期3" }
+]);
+const growthList = ref([
+    { id: 1, name: "生育期1" },
+    { id: 2, name: "生育期2" },
+    { id: 3, name: "生育期3" },
+    { id: 4, name: "生育期1" },
+    { id: 5, name: "生育期1" },
+    { id: 6, name: "生育期3" }
+]);
+const phenologyId = ref(2);
+const growthId = ref(2);
+
+const open = () => {
+    visible.value = true;
+};
+
+const close = () => {
+    visible.value = false;
+};
+
+const handleConfirm = () => {
+    if (cropStatus.value === "growing") {
+        if (!phenologyId.value) {
+            showToast("请选择物候期");
+            return;
+        }
+        if (!growthId.value) {
+            showToast("请选择生育期");
+            return;
+        }
+    }
+    emit("confirm", {
+        cropStatus: cropStatus.value,
+        phenologyId: phenologyId.value,
+        growthId: growthId.value
+    });
+    close();
+};
+
+defineExpose({ open, close });
+</script>
+
+<style lang="scss" scoped>
+.adjust-phenology-popup {
+    width: 90%;
+    padding: 20px 16px;
+    box-sizing: border-box;
+    background: linear-gradient(360deg, #ffffff 74.2%, #d1ebff 100%);
+    border-radius: 8px;
+
+    .popup-section {
+        & + .popup-section {
+            margin-top: 18px;
+        }
+
+        &__title {
+            margin-bottom: 12px;
+            font-size: 16px;
+            color: #000;
+        }
+    }
+
+    .option-row {
+        display: flex;
+        gap: 10px;
+
+        .option-tag {
+            flex: 0 0 calc((100% - 20px) / 3);
+        }
+    }
+
+    .option-scroll {
+        display: flex;
+        gap: 10px;
+        overflow-x: auto;
+        -webkit-overflow-scrolling: touch;
+        scrollbar-width: none;
+
+        &::-webkit-scrollbar {
+            display: none;
+        }
+    }
+
+    .option-grid {
+        display: grid;
+        grid-template-columns: repeat(3, 1fr);
+        gap: 10px;
+    }
+
+    .option-tag {
+        height: 40px;
+        line-height: 40px;
+        text-align: center;
+        border-radius: 4px;
+        font-size: 15px;
+        background: #F7F7F7;
+        border: 1px solid transparent;
+        box-sizing: border-box;
+
+        &--scroll {
+            flex: 0 0 calc((100% - 20px) / 3);
+        }
+
+        &.selected {
+            color: #2199f8;
+            background: rgba(33, 153, 248, 0.1);
+            border-color: #2199f8;
+        }
+    }
+
+    .popup-confirm {
+        margin-top: 24px;
+        height: 44px;
+        line-height: 44px;
+        text-align: center;
+        border-radius: 22px;
+        background: #2199f8;
+        color: #fff;
+        font-size: 16px;
+    }
+}
+</style>

+ 196 - 0
src/views/old_mini/agri_file/components/restingDatePopup.vue

@@ -0,0 +1,196 @@
+<template>
+    <Popup
+        class="resting-date-popup"
+        teleport="body"
+        :z-index="10000"
+        round
+        closeable
+        v-model:show="visible"
+    >
+        <div class="popup-section">
+            <div class="popup-section__title">请选择作物状态</div>
+            <div class="option-row">
+                <div
+                    v-for="item in cropStatusList"
+                    :key="item.key"
+                    class="option-tag"
+                    :class="{ selected: cropStatus === item.key }"
+                    @click="handleStatusChange(item.key)"
+                >
+                    {{ item.label }}
+                </div>
+            </div>
+        </div>
+
+        <div v-if="cropStatus === 'resting'" class="popup-section">
+            <div class="popup-section__title">请选择历史开花/播种时间</div>
+            <div class="form-date-wrap">
+                <el-date-picker
+                    v-model="historyDate"
+                    class="form-date"
+                    type="date"
+                    placeholder="请选择日期"
+                    format="YYYY.MM.DD"
+                    value-format="YYYY.MM.DD"
+                    :editable="false"
+                    size="large"
+                    :clearable="false"
+                    :prefix-icon="null"
+                    popper-class="resting-date-picker-popper"
+                    style="width: 100%"
+                />
+                <el-icon class="form-date-wrap__icon"><Clock /></el-icon>
+            </div>
+        </div>
+
+        <div class="popup-confirm" @click="handleConfirm">确认信息</div>
+    </Popup>
+</template>
+
+<script setup>
+import { ref } from "vue";
+import { Popup, showToast } from "vant";
+import { Clock } from "@element-plus/icons-vue";
+
+const emit = defineEmits(["confirm", "switchGrowing"]);
+
+const visible = ref(false);
+
+const cropStatusList = [
+    { key: "growing", label: "生长阶段" },
+    { key: "resting", label: "休养状态" }
+];
+const cropStatus = ref("resting");
+/** 历史开花/播种时间 */
+const historyDate = ref("2025.05.06");
+/** 上一步物候弹窗带回的数据 */
+const prevPayload = ref(null);
+
+const open = (payload = {}) => {
+    prevPayload.value = payload;
+    cropStatus.value = "resting";
+    if (!historyDate.value) {
+        historyDate.value = "2025.05.06";
+    }
+    visible.value = true;
+};
+
+const close = () => {
+    visible.value = false;
+};
+
+const handleStatusChange = (key) => {
+    if (key === "growing") {
+        close();
+        emit("switchGrowing");
+        return;
+    }
+    cropStatus.value = key;
+};
+
+const handleConfirm = () => {
+    if (cropStatus.value === "resting" && !historyDate.value) {
+        showToast("请选择历史开花/播种时间");
+        return;
+    }
+    emit("confirm", {
+        ...(prevPayload.value || {}),
+        cropStatus: cropStatus.value,
+        historyDate: historyDate.value
+    });
+    close();
+};
+
+defineExpose({ open, close });
+</script>
+
+<style lang="scss" scoped>
+.resting-date-popup {
+    width: 90%;
+    padding: 20px 16px;
+    box-sizing: border-box;
+    background: linear-gradient(360deg, #ffffff 74.2%, #d1ebff 100%);
+    border-radius: 8px;
+
+    .popup-section {
+        & + .popup-section {
+            margin-top: 18px;
+        }
+
+        &__title {
+            margin-bottom: 12px;
+            font-size: 16px;
+            color: #000;
+        }
+    }
+
+    .option-row {
+        display: flex;
+        gap: 10px;
+
+        .option-tag {
+            flex: 0 0 calc((100% - 20px) / 3);
+            height: 40px;
+            line-height: 40px;
+            text-align: center;
+            border-radius: 4px;
+            font-size: 15px;
+            background: #f7f7f7;
+            border: 1px solid transparent;
+            box-sizing: border-box;
+
+            &.selected {
+                color: #2199f8;
+                background: rgba(33, 153, 248, 0.1);
+                border-color: #2199f8;
+            }
+        }
+    }
+
+    .form-date-wrap {
+        position: relative;
+
+        &__icon {
+            position: absolute;
+            right: 12px;
+            top: 50%;
+            transform: translateY(-50%);
+            color: rgba(0, 0, 0, 0.35);
+            font-size: 16px;
+            pointer-events: none;
+            z-index: 1;
+        }
+
+        :deep(.form-date) {
+            width: 100%;
+
+            .el-input__wrapper {
+                box-shadow: none;
+                border: 1px solid #ebebeb;
+            }
+
+            .el-input__inner {
+                color: rgba(0, 0, 0, 0.4);
+            }
+        }
+    }
+
+    .popup-confirm {
+        margin-top: 24px;
+        height: 44px;
+        line-height: 44px;
+        text-align: center;
+        border-radius: 22px;
+        background: #2199f8;
+        color: #fff;
+        font-size: 16px;
+    }
+}
+</style>
+
+<!-- 日期面板 teleport 到 body,需高于弹窗 z-index: 10000 -->
+<style lang="scss">
+.resting-date-picker-popper {
+    z-index: 30000 !important;
+}
+</style>

+ 0 - 452
src/views/old_mini/agri_file/index copy.vue

@@ -1,452 +0,0 @@
-<template>
-    <div class="agri-file-page" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
-        <!-- 天气遮罩 -->
-        <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
-        <!-- 头部 -->
-        <div class="agri-file-header" :style="activeGardenTab === 'current' ? headerMotionStyle : undefined">
-            <weather-info ref="weatherInfoRef" :hasWeather="false" from="agri_file" class="weather-info"
-                @weatherExpanded="weatherExpanded" @changeGarden="changeGarden" @changeGardenTab="changeGardenTab"
-                @reportTabClick="handleReportTabClick" :isGarden="true"
-                :gardenId="defaultGardenId" />
-        </div>
-        <!-- 农场列表 -->
-        <div v-show="activeGardenTab === 'list'">
-            <garden-list ref="gardenListRef" :garden-id="selectedGardenId" @loaded="handleGardenLoaded"
-                @selectGarden="handleGardenSelected" />
-        </div>
-
-        <div v-show="activeGardenTab === 'current'" class="tracking-list">
-            <div v-for="item in trackingList" :key="item.id" class="tracking-item"
-                :class="`tracking-item--${item.theme}`" @click="handleTrackingItemClick(item)">
-                <div class="tracking-item__header">
-                    <div class="tracking-item__header-row">
-                        <div class="tracking-item__header-left">
-                            <span class="tracking-item__level" v-show="item.risk_level">{{
-                                formatRiskLevel(item.risk_level) }}</span>
-                            <span class="tracking-item__title">{{ item.first_work?.work_name }}</span>
-                        </div>
-                        <div class="tracking-item__tags">
-                            <span v-for="(tag, tagIndex) in item.list" :key="tagIndex" class="tracking-item__tag">{{
-                                tag?.category_name || tag }}</span>
-                        </div>
-                    </div>
-                </div>
-                <div class="tracking-item__body">
-                    <div class="tracking-item__action">
-                        <div class="tracking-item__action-main">
-                            <div class="tracking-item__icon">
-                                <img :src="item.icon" alt="" />
-                                <div class="tracking-item__reason">{{ item.first_work?.work_reason_short }}</div>
-                            </div>
-                            <div class="tracking-item__info">
-                                <div class="tracking-item__issue">{{ item.first_work?.interaction_issue }}</div>
-                            </div>
-                        </div>
-                        <div class="tracking-item__btn">{{ $t('agriFile.recordNow') }}</div>
-                    </div>
-                    <div class="tracking-item__history" v-show="false">
-                        <div class="tracking-item__history-text">{{ item.historyText }}</div>
-                        <div class="tracking-item__images">
-                            <img v-for="(image, imageIndex) in item.images" :key="imageIndex"
-                                class="tracking-item__thumb" :src="image" alt="" />
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import { computed, onActivated, ref } from "vue";
-import { useRoute, useRouter } from "vue-router";
-import { useStore } from "vuex";
-import { useI18n } from "@/i18n";
-import weatherInfo from "@/components/weatherInfo.vue";
-import gardenList from "@/components/gardenList.vue";
-
-const { t } = useI18n();
-
-const store = useStore();
-const route = useRoute();
-const router = useRouter();
-const tabBarHeight = computed(() => store.state.home.tabBarHeight);
-
-const isExpanded = ref(false);
-const weatherInfoRef = ref(null);
-const defaultGardenId = ref(null);
-const selectedGardenId = ref(null);
-const gardenListRef = ref(null);
-const activeGardenTab = ref("current");
-const panelExpandProgress = ref(0);
-const panelViewType = ref("risk");
-
-const HEADER_FADE_START = 0.68;
-
-const headerMotionStyle = computed(() => {
-    const progress = panelExpandProgress.value;
-    const fade = progress <= HEADER_FADE_START
-        ? 0
-        : (progress - HEADER_FADE_START) / (1 - HEADER_FADE_START);
-    const opacity = 1 - fade;
-    return {
-        opacity,
-        transform: `translateY(${-14 * fade}px) scale(${1 - fade * 0.04})`,
-        pointerEvents: opacity < 0.15 ? "none" : "auto",
-    };
-});
-
-const currentFarmName = ref("");
-const currentFarmVariety = ref(null);
-
-const defaultThumb = require("@/assets/img/home/banner.png");
-const trackingList = ref([]);
-// const trackingList = ref([
-//     {
-//         id: "phenology",
-//         theme: "blue",
-//         level: "二级",
-//         title: "物候跟踪记录",
-//         tags: ["物候", "物候", "物候"],
-//         icon: require("@/assets/img/report/wh-icon.png"),
-//         reason: "某某原因",
-//         issue: "互动问题互动问题互动问题互动问题互",
-//         recordText: "立即记录",
-//         historyText: "2026.06.07 某某区发生的事情",
-//         images: Array.from({ length: 5 }, () => defaultThumb),
-//     },
-//     {
-//         id: "pest",
-//         theme: "red",
-//         level: "二级",
-//         title: "病虫害态势监控",
-//         tags: ["真菌类", "真菌类", "真菌类"],
-//         icon: require("@/assets/img/report/bh-icon.png"),
-//         reason: "某某原因",
-//         issue: "互动问题互动问题互动问题互动问题互",
-//         recordText: "立即记录",
-//         historyText: "2026.06.07 某某区发生的事情",
-//         images: Array.from({ length: 5 }, () => defaultThumb),
-//     },
-//     {
-//         id: "growth",
-//         theme: "orange",
-//         level: "二级",
-//         title: "长势异常态势跟踪",
-//         tags: ["真菌类", "真菌类", "真菌类"],
-//         icon: require("@/assets/img/report/yc-icon.png"),
-//         reason: "某某原因",
-//         issue: "互动问题互动问题互动问题互动问题互",
-//         recordText: "立即记录",
-//         historyText: "2026.06.07 某某区发生的事情",
-//         images: Array.from({ length: 5 }, () => defaultThumb),
-//     },
-// ]);
-
-const handleReportTabClick = (item) => {
-    panelViewType.value = "plot";
-};
-
-const weatherExpanded = (isExpandedValue) => {
-    isExpanded.value = isExpandedValue;
-};
-
-const handleMaskClick = () => {
-    if (weatherInfoRef.value?.toggleExpand) {
-        weatherInfoRef.value.toggleExpand();
-    }
-};
-
-const changeGardenTab = (tab) => {
-    activeGardenTab.value = tab;
-    if (tab !== "current") {
-        panelExpandProgress.value = 0;
-        panelViewType.value = "risk";
-    }
-};
-
-const handleGardenLoaded = ({ hasFarm }) => {
-    weatherInfoRef.value?.setGardenLoaded?.(hasFarm);
-};
-
-const handleGardenSelected = (garden) => {
-    selectedGardenId.value = garden?.id ?? null;
-    weatherInfoRef.value?.setSelectedGarden?.(garden);
-};
-
-const changeGarden = (data) => {
-    if (!data?.id) return;
-    store.commit("home/SET_GARDEN_ID", data.id);
-    selectedGardenId.value = data.id;
-    currentFarmName.value = data.name ?? "";
-    currentFarmVariety.value = data.farm_variety ?? null;
-    getFarmRiskAndTracking();
-};
-
-onActivated(() => {
-    if (route.query?.farmId) {
-        defaultGardenId.value = route.query.farmId;
-    }
-    const savedFarmId = localStorage.getItem("selectedFarmId");
-    selectedGardenId.value = savedFarmId ? Number(savedFarmId) : null;
-    gardenListRef.value?.refreshFarmList?.();
-});
-
-const RISK_LEVEL_KEYS = { 1: "agriFile.riskLevel1", 2: "agriFile.riskLevel2", 3: "agriFile.riskLevel3" };
-const formatRiskLevel = (level) => {
-    const key = RISK_LEVEL_KEYS[Number(level)];
-    return key ? t(key) : "";
-};
-
-const currentPheCode = ref('');
-let fetchRequestId = 0;
-const getFarmRiskAndTracking = async () => {
-    const requestId = ++fetchRequestId;
-    trackingList.value = [];
-    const selectedFarmData = JSON.parse(localStorage.getItem("selectedFarmData") || "{}");
-    const res = await VE_API.monitor.getFarmRiskAndTracking({
-        farm_id: selectedGardenId.value,
-        crop_type: selectedFarmData.farm_variety,
-        category_code: selectedFarmData.farm_category
-    });
-    if (requestId !== fetchRequestId) return;
-    if (res.code === 200) {
-        currentPheCode.value = res.data.current_phe_code;
-        trackingList.value = [
-            { ...res.data.phenology_tracking, theme: "blue", icon: require("@/assets/img/report/wh-icon.png"), workType: 'phenology' },
-            { ...res.data.growth_abnormal_tracking, theme: "orange", icon: require("@/assets/img/report/yc-icon.png"), workType: 'growth' },
-            { ...res.data.pest_risk_assessment, theme: "red", icon: require("@/assets/img/report/bh-icon.png"), workType: 'pest' },
-        ];
-    }
-};
-
-const handleTrackingItemClick = (item) => {
-    router.push({
-        path: "/record_details",
-        query: { workId: item?.first_work?.work_id, type: item?.workType, curCode: currentPheCode.value },
-    });
-};
-</script>
-
-<style lang="scss" scoped>
-.agri-file-page {
-    width: 100%;
-    height: 100%;
-    background: #D0E6FC;
-
-    .weather-mask {
-        position: fixed;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        background-color: rgba(0, 0, 0, 0.52);
-        z-index: 11;
-    }
-
-    .agri-file-header {
-        position: absolute;
-        z-index: 12;
-        left: 10px;
-        top: 12px;
-        width: calc(100% - 20px);
-        will-change: transform, opacity;
-        transform-origin: center top;
-
-        .weather-info {
-            width: 100%;
-            position: relative;
-            left: auto;
-            top: auto;
-
-            :deep(.garden-tabs) {
-                .garden-item.left-item.active .current-name {
-                    color: #2199F8;
-                    font-weight: 600;
-                }
-            }
-        }
-    }
-
-    .tracking-list {
-        height: 100%;
-        padding: 65px 10px 12px;
-        // padding: 105px 10px 12px;
-        box-sizing: border-box;
-        overflow-y: auto;
-        display: flex;
-        flex-direction: column;
-        gap: 12px;
-
-        &::-webkit-scrollbar {
-            display: none;
-        }
-    }
-
-    .tracking-item {
-        width: 100%;
-        box-shadow: 0px 4px 4px 0px var(--tracking-shadow);
-        border: 1px solid #fff;
-        border-radius: 10px;
-
-        &--blue {
-            --tracking-header-bg: linear-gradient(0deg, #A6D8FF 0%, #39A7FF 100%);
-            --tracking-primary: #2199f8;
-            --tracking-action-border: rgba(33, 153, 248, 0.2);
-            --tracking-shadow: #2199f81a;
-        }
-
-        &--red {
-            --tracking-header-bg: linear-gradient(0deg, #FD9D9D 0%, #FF6A6A 100%);
-            --tracking-primary: #FF6A6A;
-            --tracking-action-border: rgba(255, 173, 173, 0.2);
-            --tracking-shadow: #ff6b6b1a;
-        }
-
-        &--orange {
-            --tracking-header-bg: linear-gradient(0deg, #FCB981 0%, #FF953D 100%);
-            --tracking-primary: #FA8D39;
-            --tracking-action-border: rgba(255, 173, 173, 0.2);
-            --tracking-shadow: #f593421a;
-        }
-
-        &__header {
-            position: relative;
-            padding: 10px 10px 20px;
-            border-radius: 10px 10px 0 0;
-            background: var(--tracking-header-bg);
-        }
-
-        &__header-row {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-        }
-
-        &__header-left {
-            display: flex;
-            align-items: center;
-            gap: 6px;
-        }
-
-        &__level {
-            padding: 1px 6px;
-            border-radius: 2px;
-            background: #fff;
-            color: #FF6A6A;
-            font-size: 12px;
-            min-width: fit-content;
-        }
-
-        &__title {
-            color: #fff;
-            font-size: 16px;
-            font-weight: 500;
-        }
-
-        &__tags {
-            display: flex;
-            align-items: center;
-            gap: 4px;
-        }
-
-        &__tag {
-            padding: 1px 5px;
-            border-radius: 2px;
-            background: #fff;
-            color: var(--tracking-primary);
-            font-size: 12px;
-            border: .5px solid var(--tracking-primary);
-            min-width: max-content;
-        }
-
-        &__body {
-            position: relative;
-            padding: 10px;
-            background: #fff;
-            border-radius: 10px;
-            margin-top: -8px;
-
-            &::before {
-                content: "";
-                position: absolute;
-                top: -7px;
-                left: 60px;
-                width: 0;
-                height: 0;
-                border-left: 7px solid transparent;
-                border-right: 7px solid transparent;
-                border-bottom: 7px solid #fff;
-            }
-        }
-
-        &__action {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            gap: 8px;
-            padding: 10px 8px;
-            border: 1px solid var(--tracking-action-border);
-            border-radius: 6px;
-            box-sizing: border-box;
-        }
-
-        &__icon {
-            display: flex;
-            align-items: center;
-            gap: 4px;
-
-            img {
-                width: 18px;
-                height: 16px;
-            }
-        }
-
-        &__reason {
-            color: var(--tracking-primary);
-            font-weight: 500;
-        }
-
-        &__issue {
-            margin-top: 3px;
-            color: var(--tracking-primary);
-            font-size: 12px;
-        }
-
-        &__btn {
-            padding: 5px 7px;
-            border-radius: 5px;
-            background: var(--tracking-primary);
-            color: #fff;
-            font-size: 12px;
-            min-width: fit-content;
-        }
-
-        &__history {
-            margin-top: 10px;
-            padding: 6px 8px;
-            border-radius: 6px;
-            background: rgba(168, 168, 168, 0.1);
-        }
-
-        &__history-text {
-            color: rgba(31, 31, 31, 0.5);
-            font-size: 12px;
-        }
-
-        &__images {
-            display: grid;
-            grid-template-columns: repeat(5, 1fr);
-            gap: 6px;
-            margin-top: 6px;
-        }
-
-        &__thumb {
-            width: 100%;
-            aspect-ratio: 1;
-            border-radius: 8px;
-            object-fit: cover;
-        }
-    }
-}
-</style>

+ 403 - 0
src/views/old_mini/agri_file/pages/diagnosisReport copy.vue

@@ -0,0 +1,403 @@
+<template>
+    <div class="diagnosis-report-page">
+        <custom-header :name="t('agriFile.initialReport')" :isGoBack="true" @goback="handleBack" />
+
+        <div class="diagnosis-report-body">
+            <div class="report-hero">
+                <div class="report-hero__title">{{ reportData.title }}</div>
+                <div class="report-hero__desc">{{ reportData.intro }}</div>
+            </div>
+
+            <!-- 基本情况与种植价值 -->
+            <div class="report-section">
+                <div class="report-section__title">{{ reportData.basic.title }}</div>
+                <div v-for="card in reportData.basic.cards" :key="card.title" class="info-card">
+                    <div class="info-card__title">{{ card.title }}</div>
+                    <div v-for="(para, idx) in card.paragraphs" :key="idx" class="info-card__text">
+                        {{ para }}
+                    </div>
+                </div>
+            </div>
+
+            <!-- 决定产量的气象风险 -->
+            <div class="report-section">
+                <div class="report-section__title">{{ reportData.weatherRisk.title }}</div>
+                <div class="info-card__text mb-10">{{ reportData.weatherRisk.intro }}</div>
+                <div class="section-divider">
+                    <span>{{ reportData.weatherRisk.groupTitle }}</span>
+                </div>
+                <div class="info-card fertilizer-card">
+                    <div v-for="item in reportData.weatherRisk.items" :key="item.tag" class="tag-block">
+                        <span class="tag-block__tag">{{ item.tag }}</span>
+                        <div class="tag-block__text">{{ item.content }}</div>
+                    </div>
+                    <div class="suggest-card">
+                        <div class="suggest-card__title">{{ reportData.weatherRisk.suggest.title }}</div>
+                        <div v-for="row in reportData.weatherRisk.suggest.rows" :key="row.label"
+                            class="suggest-card__row">
+                            <span class="suggest-card__label">{{ row.label }}</span>
+                            <span>{{ row.content }}</span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- 肥料供给效率分析 -->
+            <div class="report-section">
+                <div class="report-section__title">{{ reportData.fertilizer.title }}</div>
+                <div class="info-card fertilizer-card">
+                    <div class="info-card__text">{{ reportData.fertilizer.intro }}</div>
+                    <div class="section-divider">
+                        <span>{{ reportData.fertilizer.groupTitle }}</span>
+                    </div>
+                    <div v-for="item in reportData.fertilizer.items" :key="item.tag" class="tag-block">
+                        <span class="tag-block__tag">{{ item.tag }}</span>
+                        <div class="tag-block__text">{{ item.content }}</div>
+                    </div>
+                    <div class="suggest-card">
+                        <div class="suggest-card__title">{{ reportData.fertilizer.suggest.title }}</div>
+                        <div v-for="row in reportData.fertilizer.suggest.rows" :key="row.label"
+                            class="suggest-card__row">
+                            <span class="suggest-card__label">{{ row.label }}</span>
+                            <span>{{ row.content }}</span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="share-btn" @click="handleShare">{{ t("agriFile.forwardReport") }}</div>
+    </div>
+</template>
+
+<script setup>
+import { ref } from "vue";
+import { useRouter, useRoute } from "vue-router";
+import customHeader from "@/components/customHeader.vue";
+import { useI18n } from "@/i18n";
+import wx from "weixin-js-sdk";
+
+const { t } = useI18n();
+const router = useRouter();
+const route = useRoute();
+
+/** 假数据:后续可替换为接口 */
+const reportData = ref({
+    title: "《广州市从化区妃子笑荔枝初始种植诊断报告》",
+    intro: "针对您的果园坐标、妃子笑荔枝和种植类型,飞鸟结合从化区长期种植条件,为您生成专属初始种植诊断报告",
+    basic: {
+        title: "基本情况与种植价值",
+        cards: [
+            {
+                title: "种植基础",
+                paragraphs: [
+                    "从化地处北回归线附近低纬度地带,属南亚热带季风气候,年均气温约20℃上下,雨量充足、光照充沛,森林覆盖率高的低山丘陵为荔枝提供了较理想的生长环境。",
+                ],
+            },
+            {
+                title: "品种价值",
+                paragraphs: [
+                    "妃子笑为当地率先登场的早熟品种,早结、丰产稳产性好,果果大核小、肉厚清甜,商品性较好,且抗逆性和成花着果能力在同产区中表现突出。",
+                    "产期价值:本地妃子笑多在5月下旬至6月中旬成熟采收,比当地桂味、糯米糍、槐枝等中晚熟品种提早约一个月上市,能在荔枝上市初期先供应市场、填补尝鲜空档。",
+                ],
+            },
+            {
+                title: "商品定位",
+                paragraphs: [
+                    "依托从化自然环境与当季鲜采优势,妃子笑宜以「本地早熟、果大肉厚清甜、新摘即卖」为卖点,面向本地及周边短途鲜食市场,强调产地直供与口感新鲜度。",
+                ],
+            }
+        ],
+    },
+    weatherRisk: {
+        title: "决定产量的气象风险",
+        intro: "飞鸟系统基于当地多年气象与物候窗口,梳理对产量形成影响最大的关键风险,帮助提前布局应对。",
+        groupTitle: "开花坐果期",
+        items: [
+            {
+                tag: "风险判断",
+                content:
+                    "开花坐果期阴雨涝渍年发生概率55.0%,历史强度等级4级,是制约坐果稳定的重要风险,需重点对待。",
+            },
+            {
+                tag: "主要影响",
+                content:
+                    "本物候期尚无花、果器官,研判重点放在叶和梢。高温、强光叠加缺水后,嫩叶失水速度超过根系补水速度,首先表现萎蔫与灼伤。",
+            },
+            {
+                tag: "重点准备",
+                content:
+                    "围绕排水防涝、保温防寒和抗旱灌水提前备好物资与预案,把灾害应对前移到敏感窗口来临之前。",
+            },
+        ],
+        suggest: {
+            title: "飞鸟建议",
+            rows: [
+                {
+                    label: "优先能力:",
+                    content:
+                        "重点提升防灾保果与应急稳产的成套管理能力,尤其是排水防涝、保温防寒和抗旱灌水的机动响应。",
+                },
+                {
+                    label: "管理方向:",
+                    content:
+                        "围绕开花坐果和果实膨大两大敏感窗口,把灾害应对前移到物候来临之前,守住产量形成的稳定期。",
+                },
+            ],
+        },
+    },
+    fertilizer: {
+        title: "肥料供给效率分析",
+        intro: "飞鸟系统结合历史土壤、地形水文和遥感长势数据,进一步分析发现,当地肥料利用效率的主要限制在于酸性黏重土壤的通气缓冲和湿热旱交替下的根系活力波动。",
+        groupTitle: "土壤长期供肥",
+        items: [
+            {
+                tag: "主要问题",
+                content:
+                    "当地为赤红壤黏壤土,pH约5.4偏酸,有机质水平中等,养分缓冲与保蓄能力总体偏弱。",
+            },
+            {
+                tag: "形成原因",
+                content:
+                    "暴雨涝渍年发生概率65.0%,长期强降雨易促使可移动养分淋失,进一步削弱酸性土壤的养分缓冲能力。",
+            },
+            {
+                tag: "生产影响",
+                content:
+                    "养分流失加快、供应节奏不稳,可能影响花芽分化、开花坐果和幼果稳定所需的营养基础。",
+            },
+        ],
+        suggest: {
+            title: "飞鸟建议",
+            rows: [
+                {
+                    label: "优先能力:",
+                    content:
+                        "重点提升排水防涝、土壤改良与分期稳肥的成套管理能力,尤其是酸性黏重土壤的通气缓冲与根系养护。",
+                },
+                {
+                    label: "管理方向:",
+                    content:
+                        "围绕开花坐果和果实膨大两大敏感窗口,把灾害应对前移到物候来临之前,守住产量形成的稳定期。",
+                },
+            ],
+        },
+    },
+});
+
+const handleBack = () => {
+    router.back();
+};
+
+const handleShare = () => {
+    const query = {
+        askInfo: { title: "转发报告", content: "是否分享给好友" },
+        shareText: reportData.value.title,
+        targetUrl: "diagnosis_report",
+        paramsPage: JSON.stringify({
+            id: route.query.id,
+            fromShare: 1,
+        }),
+        imageUrl: "https://birdseye-img.sysuimars.com/temp/field.png",
+    };
+    wx.miniProgram.navigateTo({
+        url: `/pages/subPages/share_page/index?pageParams=${JSON.stringify(query)}&type=sharePage`,
+    });
+};
+</script>
+
+<style lang="scss" scoped>
+.diagnosis-report-page {
+    min-height: 100vh;
+    background: #f5f6f8;
+    box-sizing: border-box;
+    padding-bottom: 90px;
+}
+
+.diagnosis-report-body {
+    padding: 10px 10px 60px;
+    max-height: calc(100vh - 40px);
+    overflow: auto;
+    box-sizing: border-box;
+}
+
+.report-hero {
+    padding: 0px 0px 10px;
+    text-align: center;
+
+    &__title {
+        font-size: 16px;
+        font-weight: bold;
+        line-height: 24px;
+        color: #000000;
+    }
+
+    &__desc {
+        margin-top: 10px;
+        font-size: 16px;
+        font-weight: 350;
+        line-height: 24px;
+        color: rgba(6, 6, 6, 0.5);
+        text-align: left;
+    }
+}
+
+.report-section {
+    background: #fff;
+    padding: 10px;
+    border-radius: 10px;
+
+    &+& {
+        margin-top: 18px;
+    }
+
+    &__title {
+        margin-bottom: 10px;
+        font-size: 16px;
+        font-weight: 600;
+        line-height: 24px;
+        color: #000000;
+    }
+}
+
+.mb-10 {
+        margin-bottom: 10px;
+    }
+
+.info-card {
+    padding: 10px;
+    border-radius: 4px;
+    background: #F7F8FA;
+    box-sizing: border-box;
+
+    &.fertilizer-card {
+        background: transparent;
+        padding: 0;
+
+        .info-card__text {
+            margin-bottom: 10px;
+        }
+    }
+
+    &+& {
+        margin-top: 10px;
+    }
+
+    &__title {
+        margin-bottom: 4px;
+        font-size: 14px;
+        font-weight: 500;
+        line-height: 22px;
+        color: #1D2129;
+    }
+
+    &__text {
+        // margin-bottom: 10px;
+        font-size: 12px;
+        line-height: 20px;
+        color: #4E5969;
+
+        &+& {
+            margin-top: 2px;
+        }
+    }
+}
+
+.section-divider {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    margin-bottom: 10px;
+    color: #1D2129;
+    font-size: 14px;
+    font-weight: 500;
+    line-height: 20px;
+
+    &::before,
+    &::after {
+        content: "";
+        flex: 1;
+        height: 1px;
+        background: linear-gradient(90deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0) 100%);
+    }
+
+    &::before {
+        background: linear-gradient(270deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0) 100%);
+    }
+}
+
+.tag-block {
+    padding: 12px;
+    border-radius: 8px;
+    background: #f7f8fa;
+
+    &+& {
+        margin-top: 10px;
+    }
+
+    &__tag {
+        display: inline-block;
+        padding: 0 10px;
+        border-radius: 2px;
+        background: #2199f8;
+        color: #fff;
+        font-size: 12px;
+        line-height: 22px;
+    }
+
+    &__text {
+        margin-top: 4px;
+        font-size: 12px;
+        line-height: 20px;
+        color: #4E5969;
+    }
+}
+
+.suggest-card {
+    margin-top: 10px;
+    padding: 12px;
+    border-radius: 8px;
+    background: rgba(33, 153, 248, 0.08);
+
+    &__title {
+        margin-bottom: 8px;
+        font-size: 14px;
+        font-weight: 500;
+        line-height: 20px;
+        color: #2199f8;
+    }
+
+    &__row {
+        font-size: 12px;
+        line-height: 20px;
+        color: #4E5969;
+
+        &+& {
+            margin-top: 8px;
+        }
+    }
+
+    &__label {
+        color: #000000;
+    }
+}
+
+.share-btn {
+    position: fixed;
+    left: 50%;
+    bottom: 64px;
+    z-index: 10;
+    transform: translateX(-50%);
+    min-width: 120px;
+    height: 40px;
+    box-sizing: border-box;
+    padding: 0 30px;
+    border-radius: 22px;
+    background: linear-gradient(180deg, #72C1FF 0%, #2199F8 100%);
+    color: #fff;
+    font-size: 14px;
+    line-height: 40px;
+    text-align: center;
+    box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1);
+}
+</style>

+ 331 - 344
src/views/old_mini/agri_file/pages/diagnosisReport.vue

@@ -1,403 +1,390 @@
 <template>
     <div class="diagnosis-report-page">
-        <custom-header :name="t('agriFile.initialReport')" :isGoBack="true" @goback="handleBack" />
-
-        <div class="diagnosis-report-body">
-            <div class="report-hero">
-                <div class="report-hero__title">{{ reportData.title }}</div>
-                <div class="report-hero__desc">{{ reportData.intro }}</div>
+        <div class="diagnosis-header">
+            <div class="diagnosis-header__title-row">
+                <span class="diagnosis-header__title">种植报告</span>
+                <img class="diagnosis-header__icon" src="@/assets/img/report/star.png" alt="" />
             </div>
-
-            <!-- 基本情况与种植价值 -->
-            <div class="report-section">
-                <div class="report-section__title">{{ reportData.basic.title }}</div>
-                <div v-for="card in reportData.basic.cards" :key="card.title" class="info-card">
-                    <div class="info-card__title">{{ card.title }}</div>
-                    <div v-for="(para, idx) in card.paragraphs" :key="idx" class="info-card__text">
-                        {{ para }}
+            <div class="diagnosis-header__desc">梅县区雁洋镇南福村的飞鸟智慧农业</div>
+            <div class="diagnosis-header__base">梅州柚子基地</div>
+        </div>
+        <div class="diagnosis-content">
+            <div class="variety-bar">
+                <div class="variety-bar__tags">
+                    <div v-for="item in varietyList" :key="item.id" class="variety-bar__tag"
+                        :class="{ active: item.id === activeVarietyId }" @click="activeVarietyId = item.id">
+                        {{ item.name }}
                     </div>
                 </div>
+                <div class="variety-bar__add">
+                    <el-icon>
+                        <Plus />
+                    </el-icon>
+                    <span>新增品种</span>
+                </div>
             </div>
-
-            <!-- 决定产量的气象风险 -->
-            <div class="report-section">
-                <div class="report-section__title">{{ reportData.weatherRisk.title }}</div>
-                <div class="info-card__text mb-10">{{ reportData.weatherRisk.intro }}</div>
-                <div class="section-divider">
-                    <span>{{ reportData.weatherRisk.groupTitle }}</span>
+            <div class="base-data">
+                <div class="base-data__title">
+                    <img class="base-data__icon" src="@/assets/img/report/base-icon.png" alt="" />
+                    <span>基本信息</span>
                 </div>
-                <div class="info-card fertilizer-card">
-                    <div v-for="item in reportData.weatherRisk.items" :key="item.tag" class="tag-block">
-                        <span class="tag-block__tag">{{ item.tag }}</span>
-                        <div class="tag-block__text">{{ item.content }}</div>
-                    </div>
-                    <div class="suggest-card">
-                        <div class="suggest-card__title">{{ reportData.weatherRisk.suggest.title }}</div>
-                        <div v-for="row in reportData.weatherRisk.suggest.rows" :key="row.label"
-                            class="suggest-card__row">
-                            <span class="suggest-card__label">{{ row.label }}</span>
-                            <span>{{ row.content }}</span>
+                <div class="base-data__body">
+                    <div v-for="item in baseInfoList" :key="item.key" class="base-info-item">
+                        <div class="base-info-item__row">
+                            <span class="base-info-item__label">{{ item.label }}</span>
+                            <span class="base-info-item__value">{{ item.value }}</span>
+                            <span v-if="item.actionInline" class="base-info-action"
+                                @click="handleBaseAction(item.actionInline.key)">
+                                {{ item.actionInline.text }}
+                                <el-icon><Edit /></el-icon>
+                            </span>
+                        </div>
+                        <div v-if="item.actionBlock" class="base-info-action base-info-action--block"
+                            @click="handleBaseAction(item.actionBlock.key)">
+                            {{ item.actionBlock.text }}
+                            <el-icon><Edit /></el-icon>
                         </div>
                     </div>
                 </div>
             </div>
-
-            <!-- 肥料供给效率分析 -->
-            <div class="report-section">
-                <div class="report-section__title">{{ reportData.fertilizer.title }}</div>
-                <div class="info-card fertilizer-card">
-                    <div class="info-card__text">{{ reportData.fertilizer.intro }}</div>
-                    <div class="section-divider">
-                        <span>{{ reportData.fertilizer.groupTitle }}</span>
-                    </div>
-                    <div v-for="item in reportData.fertilizer.items" :key="item.tag" class="tag-block">
-                        <span class="tag-block__tag">{{ item.tag }}</span>
-                        <div class="tag-block__text">{{ item.content }}</div>
-                    </div>
-                    <div class="suggest-card">
-                        <div class="suggest-card__title">{{ reportData.fertilizer.suggest.title }}</div>
-                        <div v-for="row in reportData.fertilizer.suggest.rows" :key="row.label"
-                            class="suggest-card__row">
-                            <span class="suggest-card__label">{{ row.label }}</span>
-                            <span>{{ row.content }}</span>
-                        </div>
+            <div class="report-module">
+                <div class="report-tabs">
+                    <div
+                        v-for="tab in reportTabs"
+                        :key="tab.key"
+                        class="report-tabs__item"
+                        :class="{ active: tab.key === activeReportTab }"
+                        @click="activeReportTab = tab.key"
+                    >
+                        <img class="report-tabs__icon" :src="tab.icon" alt="" />
+                        <span class="report-tabs__label">{{ tab.label }}</span>
                     </div>
                 </div>
+                <div class="report-panel">
+                    <div class="report-panel__title">{{ activeReportTabMeta.label }}</div>
+                </div>
             </div>
         </div>
 
-        <div class="share-btn" @click="handleShare">{{ t("agriFile.forwardReport") }}</div>
+        <adjustPhenologyPopup ref="adjustPhenologyPopupRef" @confirm="handlePhenologyConfirm" />
+        <restingDatePopup
+            ref="restingDatePopupRef"
+            @confirm="handleRestingDateConfirm"
+            @switchGrowing="handleSwitchGrowing"
+        />
     </div>
 </template>
 
 <script setup>
-import { ref } from "vue";
-import { useRouter, useRoute } from "vue-router";
-import customHeader from "@/components/customHeader.vue";
-import { useI18n } from "@/i18n";
-import wx from "weixin-js-sdk";
-
-const { t } = useI18n();
-const router = useRouter();
-const route = useRoute();
-
-/** 假数据:后续可替换为接口 */
-const reportData = ref({
-    title: "《广州市从化区妃子笑荔枝初始种植诊断报告》",
-    intro: "针对您的果园坐标、妃子笑荔枝和种植类型,飞鸟结合从化区长期种植条件,为您生成专属初始种植诊断报告",
-    basic: {
-        title: "基本情况与种植价值",
-        cards: [
-            {
-                title: "种植基础",
-                paragraphs: [
-                    "从化地处北回归线附近低纬度地带,属南亚热带季风气候,年均气温约20℃上下,雨量充足、光照充沛,森林覆盖率高的低山丘陵为荔枝提供了较理想的生长环境。",
-                ],
-            },
-            {
-                title: "品种价值",
-                paragraphs: [
-                    "妃子笑为当地率先登场的早熟品种,早结、丰产稳产性好,果果大核小、肉厚清甜,商品性较好,且抗逆性和成花着果能力在同产区中表现突出。",
-                    "产期价值:本地妃子笑多在5月下旬至6月中旬成熟采收,比当地桂味、糯米糍、槐枝等中晚熟品种提早约一个月上市,能在荔枝上市初期先供应市场、填补尝鲜空档。",
-                ],
-            },
-            {
-                title: "商品定位",
-                paragraphs: [
-                    "依托从化自然环境与当季鲜采优势,妃子笑宜以「本地早熟、果大肉厚清甜、新摘即卖」为卖点,面向本地及周边短途鲜食市场,强调产地直供与口感新鲜度。",
-                ],
-            }
-        ],
+import { computed, ref } from "vue";
+import { Plus, Edit } from "@element-plus/icons-vue";
+import adjustPhenologyPopup from "../components/adjustPhenologyPopup.vue";
+import restingDatePopup from "../components/restingDatePopup.vue";
+import tab1Icon from "@/assets/img/report/tab-1.png";
+import tab2Icon from "@/assets/img/report/tab-2.png";
+import tab3Icon from "@/assets/img/report/tab-3.png";
+import tab4Icon from "@/assets/img/report/tab-4.png";
+import tab5Icon from "@/assets/img/report/tab-5.png";
+
+const varietyList = ref([
+    { id: 1, name: "金柚" }
+]);
+const activeVarietyId = ref(1);
+const adjustPhenologyPopupRef = ref(null);
+const restingDatePopupRef = ref(null);
+
+/** 基本信息展示数据:后续可替换为接口 */
+const baseInfoList = ref([
+    {
+        key: "crop",
+        label: "种植作物:",
+        value: "柚子 — 金柚",
+        actionInline: { key: "changeVariety", text: "更改品种" }
+    },
+    {
+        key: "trait",
+        label: "品种特质:",
+        value: "金柚果大皮薄,果肉晶莹剔透,酸甜适中,富含维生素C和膳食纤维,具有清热解渴、健脾开胃的功效。其果皮可用于提取精油,果肉适合鲜食及加工成果汁、果酱等产品。"
     },
-    weatherRisk: {
-        title: "决定产量的气象风险",
-        intro: "飞鸟系统基于当地多年气象与物候窗口,梳理对产量形成影响最大的关键风险,帮助提前布局应对。",
-        groupTitle: "开花坐果期",
-        items: [
-            {
-                tag: "风险判断",
-                content:
-                    "开花坐果期阴雨涝渍年发生概率55.0%,历史强度等级4级,是制约坐果稳定的重要风险,需重点对待。",
-            },
-            {
-                tag: "主要影响",
-                content:
-                    "本物候期尚无花、果器官,研判重点放在叶和梢。高温、强光叠加缺水后,嫩叶失水速度超过根系补水速度,首先表现萎蔫与灼伤。",
-            },
-            {
-                tag: "重点准备",
-                content:
-                    "围绕排水防涝、保温防寒和抗旱灌水提前备好物资与预案,把灾害应对前移到敏感窗口来临之前。",
-            },
-        ],
-        suggest: {
-            title: "飞鸟建议",
-            rows: [
-                {
-                    label: "优先能力:",
-                    content:
-                        "重点提升防灾保果与应急稳产的成套管理能力,尤其是排水防涝、保温防寒和抗旱灌水的机动响应。",
-                },
-                {
-                    label: "管理方向:",
-                    content:
-                        "围绕开花坐果和果实膨大两大敏感窗口,把灾害应对前移到物候来临之前,守住产量形成的稳定期。",
-                },
-            ],
-        },
+    {
+        key: "phenology",
+        label: "物候信息:",
+        value: "当前为果实膨大期,预计采收时间为2024年10月中旬。",
+        actionInline: { key: "adjustPhenology", text: "调整物候" }
     },
-    fertilizer: {
-        title: "肥料供给效率分析",
-        intro: "飞鸟系统结合历史土壤、地形水文和遥感长势数据,进一步分析发现,当地肥料利用效率的主要限制在于酸性黏重土壤的通气缓冲和湿热旱交替下的根系活力波动。",
-        groupTitle: "土壤长期供肥",
-        items: [
-            {
-                tag: "主要问题",
-                content:
-                    "当地为赤红壤黏壤土,pH约5.4偏酸,有机质水平中等,养分缓冲与保蓄能力总体偏弱。",
-            },
-            {
-                tag: "形成原因",
-                content:
-                    "暴雨涝渍年发生概率65.0%,长期强降雨易促使可移动养分淋失,进一步削弱酸性土壤的养分缓冲能力。",
-            },
-            {
-                tag: "生产影响",
-                content:
-                    "养分流失加快、供应节奏不稳,可能影响花芽分化、开花坐果和幼果稳定所需的营养基础。",
-            },
-        ],
-        suggest: {
-            title: "飞鸟建议",
-            rows: [
-                {
-                    label: "优先能力:",
-                    content:
-                        "重点提升排水防涝、土壤改良与分期稳肥的成套管理能力,尤其是酸性黏重土壤的通气缓冲与根系养护。",
-                },
-                {
-                    label: "管理方向:",
-                    content:
-                        "围绕开花坐果和果实膨大两大敏感窗口,把灾害应对前移到物候来临之前,守住产量形成的稳定期。",
-                },
-            ],
-        },
+    {
+        key: "soil",
+        label: "土壤条件:",
+        value: "土壤pH值6.2,有机质含量2.8%,氮磷钾含量适中,土壤通气性和保水性良好,适合柚子生长。建议定期检测土壤养分,适时补充有机肥。",
+        actionBlock: { key: "soilSense", text: "土壤感知" }
     },
-});
+    {
+        key: "terrain",
+        label: "地形条件:",
+        value: "坡度8°,海拔185米,南向坡面,排水良好。",
+        actionInline: { key: "editLocation", text: "修改定位" }
+    }
+]);
+
+/** 报告模块 Tab */
+const reportTabs = [
+    { key: "weather", label: "气象风险", icon: tab1Icon },
+    { key: "pest", label: "病虫风险", icon: tab2Icon },
+    { key: "quality", label: "品质潜力", icon: tab3Icon },
+    { key: "input", label: "必要投入", icon: tab4Icon },
+    { key: "manage", label: "农事管理", icon: tab5Icon }
+];
+const activeReportTab = ref("weather");
+const activeReportTabMeta = computed(
+    () => reportTabs.find((tab) => tab.key === activeReportTab.value) || reportTabs[0]
+);
+
+const handleBaseAction = (key) => {
+    if (key === "adjustPhenology") {
+        adjustPhenologyPopupRef.value?.open();
+        return;
+    }
+    // 后续接入对应弹窗 / 跳转
+    console.log("base action:", key);
+};
+
+const handlePhenologyConfirm = (payload) => {
+    // 物候弹窗确认后,接着弹出历史开花/播种时间弹窗
+    restingDatePopupRef.value?.open(payload);
+};
 
-const handleBack = () => {
-    router.back();
+const handleSwitchGrowing = () => {
+    adjustPhenologyPopupRef.value?.open();
 };
 
-const handleShare = () => {
-    const query = {
-        askInfo: { title: "转发报告", content: "是否分享给好友" },
-        shareText: reportData.value.title,
-        targetUrl: "diagnosis_report",
-        paramsPage: JSON.stringify({
-            id: route.query.id,
-            fromShare: 1,
-        }),
-        imageUrl: "https://birdseye-img.sysuimars.com/temp/field.png",
-    };
-    wx.miniProgram.navigateTo({
-        url: `/pages/subPages/share_page/index?pageParams=${JSON.stringify(query)}&type=sharePage`,
-    });
+const handleRestingDateConfirm = (payload) => {
+    // 后续接入接口保存
+    console.log("resting date confirm:", payload);
 };
 </script>
 
 <style lang="scss" scoped>
 .diagnosis-report-page {
-    min-height: 100vh;
-    background: #f5f6f8;
-    box-sizing: border-box;
-    padding-bottom: 90px;
-}
-
-.diagnosis-report-body {
-    padding: 10px 10px 60px;
-    max-height: calc(100vh - 40px);
+    width: 100%;
+    height: calc(100vh - 50px);
     overflow: auto;
+    -webkit-overflow-scrolling: touch;
+    background: #f5f6fe;
     box-sizing: border-box;
-}
+    padding-bottom: 20px;
 
-.report-hero {
-    padding: 0px 0px 10px;
-    text-align: center;
-
-    &__title {
-        font-size: 16px;
-        font-weight: bold;
-        line-height: 24px;
-        color: #000000;
-    }
+    .diagnosis-header {
+        height: 148px;
+        padding: 26px 0 0 14px;
+        box-sizing: border-box;
+        background: url("@/assets/img/report/title-bg.png") no-repeat center center / 100% 100%;
+        color: #fff;
 
-    &__desc {
-        margin-top: 10px;
-        font-size: 16px;
-        font-weight: 350;
-        line-height: 24px;
-        color: rgba(6, 6, 6, 0.5);
-        text-align: left;
-    }
-}
+        &__title-row {
+            display: flex;
+            align-items: center;
+            gap: 6px;
+        }
 
-.report-section {
-    background: #fff;
-    padding: 10px;
-    border-radius: 10px;
+        &__title {
+            font-size: 35px;
+            font-family: "pangmenzhengdao";
+        }
 
-    &+& {
-        margin-top: 18px;
+        &__icon {
+            width: 24px;
+            height: 24px;
+        }
     }
 
-    &__title {
-        margin-bottom: 10px;
-        font-size: 16px;
-        font-weight: 600;
-        line-height: 24px;
-        color: #000000;
-    }
-}
+    .diagnosis-content {
+        padding: 0 10px;
 
-.mb-10 {
-        margin-bottom: 10px;
-    }
+        .variety-bar {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            padding: 10px 6px;
+            background: #fff;
+            border-radius: 8px;
+            margin-top: -20px;
+
+            &__tags {
+                display: flex;
+                align-items: center;
+                flex-wrap: wrap;
+                gap: 6px;
+            }
 
-.info-card {
-    padding: 10px;
-    border-radius: 4px;
-    background: #F7F8FA;
-    box-sizing: border-box;
+            &__tag {
+                padding: 5px 16px;
+                border-radius: 4px;
+                background: #f2f3f5;
+                color: #4e5969;
 
-    &.fertilizer-card {
-        background: transparent;
-        padding: 0;
+                &.active {
+                    background: #2199f8;
+                    color: #fff;
+                }
+            }
 
-        .info-card__text {
-            margin-bottom: 10px;
+            &__add {
+                display: flex;
+                align-items: center;
+                gap: 2px;
+                padding: 5px 10px;
+                border-radius: 4px;
+                border: 1px solid #2199f8;
+                background: rgba(33, 153, 248, 0.1);
+                color: #2199f8;
+            }
         }
-    }
 
-    &+& {
-        margin-top: 10px;
-    }
+        .base-data {
+            margin: 10px 0;
+            padding: 5px;
+            min-height: 382px;
+            background: url("@/assets/img/report/base-bg.png") no-repeat center top / 100% 100%;
+            box-sizing: border-box;
+
+            &__title {
+                display: flex;
+                align-items: center;
+                gap: 5px;
+                font-size: 17px;
+                color: #fff;
+                margin: -3px 0 0 -3px;
+            }
 
-    &__title {
-        margin-bottom: 4px;
-        font-size: 14px;
-        font-weight: 500;
-        line-height: 22px;
-        color: #1D2129;
-    }
+            &__icon {
+                width: 44px;
+                height: 44px;
+            }
 
-    &__text {
-        // margin-bottom: 10px;
-        font-size: 12px;
-        line-height: 20px;
-        color: #4E5969;
+            &__title>span {
+                margin-top: -4px;
+            }
 
-        &+& {
-            margin-top: 2px;
+            &__body {
+                margin-top: -8px;
+                padding: 10px;
+                background: #fff;
+                border-radius: 8px;
+
+                .base-info-item {
+                    margin-bottom: 8px;
+                    &__row {
+                        color: #333;
+                    }
+
+                    &__label {
+                        color: #999;
+                    }
+
+                    &__value {
+                        color: #333;
+                    }
+                }
+
+                .base-info-action {
+                    display: inline-flex;
+                    align-items: center;
+                    gap: 2px;
+                    margin-left: 6px;
+                    padding: 2px 8px;
+                    border-radius: 20px;
+                    background: rgba(33, 153, 248, 0.1);
+                    color: #2199f8;
+                    font-size: 12px;
+
+                    .el-icon {
+                        font-size: 12px;
+                    }
+
+                    &--block {
+                        display: inline-flex;
+                        margin: 8px 0 0;
+                    }
+                }
+            }
         }
-    }
-}
-
-.section-divider {
-    display: flex;
-    align-items: center;
-    gap: 10px;
-    margin-bottom: 10px;
-    color: #1D2129;
-    font-size: 14px;
-    font-weight: 500;
-    line-height: 20px;
-
-    &::before,
-    &::after {
-        content: "";
-        flex: 1;
-        height: 1px;
-        background: linear-gradient(90deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0) 100%);
-    }
-
-    &::before {
-        background: linear-gradient(270deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0) 100%);
-    }
-}
-
-.tag-block {
-    padding: 12px;
-    border-radius: 8px;
-    background: #f7f8fa;
 
-    &+& {
-        margin-top: 10px;
-    }
-
-    &__tag {
-        display: inline-block;
-        padding: 0 10px;
-        border-radius: 2px;
-        background: #2199f8;
-        color: #fff;
-        font-size: 12px;
-        line-height: 22px;
-    }
+        .report-module {
+            margin-top: 4px;
+        }
 
-    &__text {
-        margin-top: 4px;
-        font-size: 12px;
-        line-height: 20px;
-        color: #4E5969;
-    }
-}
+        .report-tabs {
+            display: flex;
+            align-items: stretch;
+            gap: 8px;
+            overflow-x: auto;
+            -webkit-overflow-scrolling: touch;
+            scrollbar-width: none;
 
-.suggest-card {
-    margin-top: 10px;
-    padding: 12px;
-    border-radius: 8px;
-    background: rgba(33, 153, 248, 0.08);
-
-    &__title {
-        margin-bottom: 8px;
-        font-size: 14px;
-        font-weight: 500;
-        line-height: 20px;
-        color: #2199f8;
-    }
+            &::-webkit-scrollbar {
+                display: none;
+            }
 
-    &__row {
-        font-size: 12px;
-        line-height: 20px;
-        color: #4E5969;
+            &__item {
+                flex: 0 0 calc((100% - 24px) / 4);
+                display: flex;
+                flex-direction: column;
+                align-items: center;
+                justify-content: center;
+                padding: 5px 5px 14px;
+                box-sizing: border-box;
+                color: #ADADAD;
+                background: url("@/assets/img/report/tab-bg.png") no-repeat center center / 100% 100%;
+
+                &.active {
+                    background: url("@/assets/img/report/tab-act-bg.png") no-repeat center center / 100% 100%;
+                    &::after {
+                        opacity: 1;
+                    }
+
+                    .report-tabs__icon {
+                        filter: none;
+                        opacity: 1;
+                    }
+                }
+            }
 
-        &+& {
-            margin-top: 8px;
+            &__icon {
+                width: 22px;
+                height: 22px;
+                filter: grayscale(1);
+                opacity: 0.45;
+            }
         }
-    }
 
-    &__label {
-        color: #000000;
+        .report-panel {
+            margin-top: 10px;
+            padding: 16px 14px 18px;
+            background: #fff;
+            border-radius: 10px;
+
+            &__title {
+                position: relative;
+                display: inline-block;
+                font-size: 18px;
+                font-weight: 600;
+                color: #1d2129;
+                line-height: 1.3;
+                z-index: 1;
+
+                &::after {
+                    content: "";
+                    position: absolute;
+                    left: 0;
+                    bottom: 2px;
+                    width: 36px;
+                    height: 8px;
+                    border-radius: 8px;
+                    background: linear-gradient(90deg, #8ed0ff 0%, rgba(142, 208, 255, 0.35) 100%);
+                    z-index: -1;
+                }
+            }
+        }
     }
 }
-
-.share-btn {
-    position: fixed;
-    left: 50%;
-    bottom: 64px;
-    z-index: 10;
-    transform: translateX(-50%);
-    min-width: 120px;
-    height: 40px;
-    box-sizing: border-box;
-    padding: 0 30px;
-    border-radius: 22px;
-    background: linear-gradient(180deg, #72C1FF 0%, #2199F8 100%);
-    color: #fff;
-    font-size: 14px;
-    line-height: 40px;
-    text-align: center;
-    box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1);
-}
 </style>

+ 2 - 2
src/views/old_mini/entry_information/components/selectEquipment.vue

@@ -529,8 +529,8 @@ function buildFarmPayload(includeEquipment = true) {
     const payload = {
         user_name: baForm.name,
         tel: baForm.phone,
-        admin_id: 94494,
-        // admin_id: getAdminId(),
+        // admin_id: 94494,
+        admin_id: getAdminId(),
         user_id: getUserId(),
         machine_id: equipmentList
             .map((item) => Number(item.id))

+ 0 - 1595
src/views/old_mini/growth_report/index copy.vue

@@ -1,1595 +0,0 @@
-<template>
-    <div class="achievement-report-page" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
-        <!-- 天气遮罩 -->
-        <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
-        <!-- 组件:天气 -->
-        <div class="weather-info-wrap">
-            <weather-info ref="weatherInfoRef" from="growth_report" class="weather-info" :showTabMask="showTabMask"
-                @weatherExpanded="weatherExpanded" @changeGarden="changeGarden" @changeGardenTab="changeGardenTab"
-                @closeTabMask="closeTabMask">
-            </weather-info>
-
-            <!-- 邀请关注 -->
-            <!-- <div class="invite-follow" v-if="currentFarmName && activeGardenTab === 'current'">
-                <div class="invite-content">
-                    <icon name="share" />
-                    <span>{{ t('邀请关注') }}</span>
-                </div>
-            </div> -->
-        </div>
-
-        <!-- 农场列表 -->
-        <div v-show="activeGardenTab === 'list'">
-            <garden-list ref="gardenListRef" :garden-id="selectedGardenId" @loaded="handleGardenLoaded"
-                @selectGarden="handleGardenSelected" />
-        </div>
-
-        <div class="report-content-wrap" v-if="hasReport && activeGardenTab === 'current'" v-loading="loading"
-            element-loading-background="rgba(0, 0, 0, 0.1)">
-            <div class="report-content has-report" :style="{ minHeight: `calc(100vh - ${tabBarHeight}px)` }">
-                <!-- <img src="@/assets/img/home/qrcode.png" alt="" class="code-icon" /> -->
-                <img class="header-img" src="@/assets/img/home/report.png" alt="" />
-
-                <div class="report-header">
-                    <!-- <div class="type-tabs report-tabs">
-                        <div class="type-item" :class="{ 'type-item-active': activeReportIndex === 0 }">{{ t('作物长势') }}</div>
-                        <div class="type-item" :class="{ 'type-item-active': activeReportIndex === 1 }">{{ t('历史风险') }}</div>
-                        <div class="type-item" :class="{ 'type-item-active': activeReportIndex === 2 }">{{ t('土壤改良') }}</div>
-                        <div class="type-item" :class="{ 'type-item-active': activeReportIndex === 3 }">{{ t('种植建议') }}</div>
-                    </div> -->
-                    <div class="type-tabs" v-if="subjectData.length > 1">
-                        <div
-                            @click="handleTypeTabClick(item, index)"
-                            class="type-item"
-                            v-for="(item, index) in visibleSubjectData"
-                            :class="{ 'type-item-active': activeSubjectIndex === index }"
-                            :key="index">{{ item.speciesName }}</div>
-                    <div
-                        v-if="showSubjectToggle"
-                        class="subject-toggle"
-                        @click="typeTabsExpanded = !typeTabsExpanded"
-                    >
-                        {{ typeTabsExpanded ? t("common.collapse") : t("common.expandMore") }}
-                    </div>
-                    </div>
-
-                    <div class="time-tag">{{ workItems?.[0]?.reportDate || new Date().toISOString().split('T')[0] }}</div>
-                    <div
-                        class="report-title"
-                        :class="{ 'report-title-toggle': localeToggleEnabled }"
-                        @click="onReportTitleClick"
-                    >{{ varietyName }}{{ t("growthReport.title") }}</div>
-                    <div class="report-info">
-                        <div class="info-item">
-                            <img class="info-icon" src="@/assets/img/home/farm.png" alt="" />
-                            <span class="info-text">{{ currentFarmName }}</span>
-                        </div>
-                    </div>
-                </div>
-
-                <div class="report-box">
-                    <div class="box-title">{{ t("growthReport.weatherRisk") }}</div>
-                    <div class="box-text">
-                        <div class="box-bg">
-                            <!-- <div class="types-info">
-                                当前 <span class="text-bold">{{ t('水稻') }}</span>{{ t('处于为  分蘖初期') }}<span class="text-link" @click="handleAdjustPopup">{{ t('(校准物候期)') }}</span>
-                            </div> -->
-                            <div class="types-info">
-                                {{ t("common.current") }}
-                                <span class="text-bold">{{ varietyName }}</span>
-                                {{ t("growthReport.inStage", { stage: currentPhenologyStage }) }}
-                            </div>
-                            <div class="tp-img" v-if="currentFarmVariety === 1">
-                                <img src="@/assets/img/common/tp-1.png" alt="">
-                                <img src="@/assets/img/common/tp-2.png" alt="">
-                                <img src="@/assets/img/common/tp-3.png" alt="">
-                                <img src="@/assets/img/common/tp-4.png" alt="">
-                                <img src="@/assets/img/common/tp-5.png" alt="">
-                                <img src="@/assets/img/common/tp-6.png" alt="">
-                            </div>
-                            <div class="tp-img" v-else>
-                                <img src="@/assets/img/common/sd-1.jpg" alt="">
-                                <img src="@/assets/img/common/sd-2.jpg" alt="">
-                                <img src="@/assets/img/common/sd-3.jpg" alt="">
-                                <img src="@/assets/img/common/sd-4.jpg" alt="">
-                                <img src="@/assets/img/common/sd-5.jpg" alt="">
-                                <img src="@/assets/img/common/sd-6.jpg" alt="">
-                            </div>
-                        </div>
-                        <div class="warning-part">
-                            <div class="warning-title">
-                                <div class="title-l">
-                                    <div class="title-line"></div>
-                                    <div class="title-block"></div>
-                                </div>
-                                <div>{{ t("growthReport.futureWeatherRisk") }}</div>
-                                <div class="title-l">
-                                    <div class="title-block"></div>
-                                    <div class="title-line title-line-right"></div>
-                                </div>
-                            </div>
-
-                            <div class="report-part" v-for="(part, partI) in riskList" :key="partI">
-                                <div class="part-title">{{ part.title }}</div>
-                                <div class="part-text" v-html="boldKeywordsInText(part.description, part.boldKeywords)"></div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-
-                <div class="report-box">
-                    <div class="box-title">{{ t("growthReport.farmAdvice") }}</div>
-                    <div class="box-text">
-                        <div class="warning-part" v-for="(part, partI) in adviceList" :key="partI">
-                            <div class="report-part">
-                                <div class="part-top">
-                                    <div class="part-title">{{ part.title }}</div>
-                                    <!-- <div class="part-link">
-                                        <el-icon class="part-link-icon"><Link /></el-icon>
-                                        <div class="text-link">{{ t('查看农事') }}</div>
-                                    </div> -->
-                                </div>
-                                <div class="part-text" v-html="boldKeywordsInText(part.description, part.boldKeywords)"></div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-                <div class="report-box">
-                    <div class="box-title">{{ t("growthReport.patrolFocus") }}</div>
-                    <div class="box-text">
-                        <div class="warning-part" v-for="(part, partI) in patrolList" :key="partI">
-                            <div class="report-part">
-                                <div class="part-top">
-                                    <div class="part-title">{{ part.title }}</div>
-                                    <!-- <div class="part-link">
-                                        <el-icon class="part-link-icon"><Link /></el-icon>
-                                        <div class="text-link">{{ t('查看互动') }}</div>
-                                    </div> -->
-                                </div>
-                                <div class="part-text" v-html="boldKeywordsInText(part.description, part.boldKeywords)"></div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-
-                <div class="report-box" v-for="(work, workI) in workItems" :key="workI">
-                    <div class="box-title">{{ work?.title }}</div>
-                    <div class="box-text">
-                        <div class="box-bg" v-show="work?.backgroundDesc">
-                            <span class="box-subtitle">{{ t("common.backgroundDesc") }}</span>
-                            <div class="pre-text">{{ work?.backgroundDesc }}</div>
-                        </div>
-                        <div class="box-advice" v-show="work?.suggestion">
-                            <span class="box-subtitle">{{ t("common.suggestion") }}</span>
-                            <div class="pre-text">{{ work?.suggestion }}</div>
-                        </div>
-                        <div class="box-sum pre-text" v-show="work?.summary">{{ work?.summary }}</div>
-                    </div>
-                </div>
-            </div>
-
-            <!-- <swipe ref="swipeRef" class="my-swipe" :loop="false" indicator-color="white" @change="handleSwipeChange">
-                <swipe-item v-for="(item, index) in regionsData" :key="index">
-                    
-                </swipe-item>
-            </swipe> -->
-        </div>
-
-        <div v-else-if="activeGardenTab === 'current'" class="fake-report-wrap report-content-wrap">
-            <div class="report-content">
-
-                <img class="header-img" src="@/assets/img/home/report.png" alt="" />
-                <div class="report-header" :class="{ 'no-farm': !currentFarmName }">
-                    <div class="time-tag">{{ new Date().toISOString().split('T')[0] }}</div>
-                    <div
-                        class="report-title"
-                        :class="{ 'report-title-toggle': localeToggleEnabled }"
-                        @click="onReportTitleClick"
-                    >{{ t("growthReport.cropTitle") }}</div>
-                    <div class="report-info pb-4">
-                        <div class="info-item">
-                            <img class="info-icon" src="@/assets/img/home/farm.png" alt="" />
-                            <span class="info-text">{{ t("common.demoFarm") }}</span>
-                        </div>
-                    </div>
-                </div>
-                <div class="fake-img">
-                    <img src="@/assets/img/home/fake.png" alt="" class="fake-img-item" />
-                </div>
-
-                <div class="lock-img">
-                    <img @click="handleLockClick" src="@/assets/img/home/lock-blue.png" alt=""
-                        class="has-click lock-img-item" />
-                    <div class="lock-text">
-                        {{ t("growthReport.lockTitle") }}
-                        <div>{{ t("growthReport.lockSub") }}</div>
-                    </div>
-
-                    <div @click="handleLockClick" class="lock-btn has-click">{{ t("common.unlock") }}</div>
-                </div>
-
-                <div class="lock-bg"></div>
-            </div>
-        </div>
-
-        <!-- 农场列表引导 -->
-        <div class="mask-wrap" @click="closeTabMask" v-if="showTabMask"></div>
-
-        <tip-popup v-model:show="showBindSuccess" type="success" :text="t('growthReport.bindSuccess')" hideBtn />
-
-        <start-interact-popup ref="startInteractPopupRef" />
-
-        <agri-execute-popup ref="agriExecutePopupRef" />
-
-        <!-- 校准物候期 -->
-        <adjust-popup ref="adjustPopupRef" />
-    </div>
-</template>
-
-<script setup>
-import wx from "weixin-js-sdk";
-import weatherInfo from "@/components/weatherInfo.vue";
-import { ref, onActivated, onDeactivated, onUnmounted, computed, nextTick } from "vue";
-import { useRoute, useRouter } from "vue-router";
-import { useStore } from "vuex";
-import { Swipe, SwipeItem, Badge, Icon } from 'vant';
-import tipPopup from "@/components/popup/tipPopup.vue";
-import startInteractPopup from "@/components/popup/startInteractPopup.vue";
-import agriExecutePopup from "@/components/popup/agriExecutePopup.vue";
-import gardenList from "@/components/gardenList.vue";
-import adjustPopup from "./adjustPopup.vue";
-import { useI18n } from "@/i18n";
-import { boldKeywordsInText } from "@/utils/boldKeywords";
-
-const { t, toggleLocale: dispatchToggleLocale } = useI18n();
-const store = useStore();
-
-/** 暂时隐藏标题中英切换,恢复时改为 true */
-const localeToggleEnabled = false;
-const tabBarHeight = computed(() => store.state.home.tabBarHeight);
-
-const route = useRoute();
-const router = useRouter();
-const loading = ref(false);
-const hasReport = ref(true);
-const workItems = ref([]);
-const swipeRef = ref(null);
-
-//
-const riskList = computed(() => [
-    {
-        title:
-            currentFarmVariety.value == 1
-                ? t("growthReport.risk.pest.title")
-                : t("growthReport.risk.pest.titleRice"),
-        description:
-            currentFarmVariety.value == 1
-                ? t("growthReport.risk.pest.desc")
-                : t("growthReport.risk.pest.descRice"),
-        boldKeywords:
-            currentFarmVariety.value == 1
-                ? ["高温干旱", "中等水平", "果皮灼伤"]
-                : ["中等水平", "做好排水工作"],
-    },
-    // {
-    //     title: t("growthReport.risk.rain.title"),
-    //     description: t("growthReport.risk.rain.desc"),
-    // },
-]);
-
-const adviceList = computed(() => [
-    {
-        title:
-            currentFarmVariety.value == 1
-                ? t("growthReport.advice.foliar.title")
-                : t("growthReport.advice.foliar.titleRice"),
-        description:
-            currentFarmVariety.value == 1
-                ? t("growthReport.advice.foliar.desc")
-                : t("growthReport.advice.foliar.descRice"),
-        boldKeywords:
-            currentFarmVariety.value == 1 ? ["需及时喷撒清水"] : [],
-    },
-    // {
-    //     title: t("growthReport.advice.pestControl.title"),
-    //     description: t("growthReport.advice.pestControl.desc"),
-    // },
-]);
-
-const patrolList = computed(() => {
-    const isLychee = currentFarmVariety.value == 1;
-    return [
-        {
-            title: t("growthReport.patrol.process.title"),
-            description: isLychee
-                ? t("growthReport.patrol.process.desc")
-                : t("growthReport.patrol.process.descRice"),
-            boldKeywords: isLychee ? ["5%", "果实转色期"] : ["60%", "拔节期"],
-        },
-        {
-            title: t("growthReport.patrol.growth.title"),
-            description: isLychee
-                ? t("growthReport.patrol.growth.desc")
-                : t("growthReport.patrol.growth.descRice"),
-            boldKeywords: isLychee ? ["10%", "抽生新梢"] : ["10%", "干旱缺素"],
-        },
-    ];
-    // {
-    //     title: t("growthReport.patrol.pest.title"),
-    //     description: t("growthReport.patrol.pest.desc"),
-    // },
-});
-//
-const paramsPage = ref({});
-const showBindSuccess = ref(false);
-const startInteractPopupRef = ref(null);
-const agriExecutePopupRef = ref(null);
-const adjustPopupRef = ref(null);
-
-const handleAdjustPopup = () => {
-    adjustPopupRef.value.open();
-}
-// 天气组件相关
-const isExpanded = ref(false);
-const weatherInfoRef = ref(null);
-
-const showTabMask = ref(false);
-const TAB_GUIDE_SHOWN_KEY = "GROWTH_REPORT_TAB_GUIDE_SHOWN";
-const weatherExpanded = (isExpandedValue) => {
-    isExpanded.value = isExpandedValue;
-};
-
-// 点击遮罩时收起天气
-const handleMaskClick = () => {
-    if (weatherInfoRef.value && weatherInfoRef.value.toggleExpand) {
-        weatherInfoRef.value.toggleExpand();
-    }
-};
-
-const currentFarmName = ref('');
-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 currentFarmVariety = ref(null);
-const varietyName = ref(null);
-const currentPhenologyStage = computed(() =>
-    currentFarmVariety.value == 1
-        ? t("growthReport.phenologyFruitExpansion")
-        : t("growthReport.phenologyLateTillering")
-);
-// 切换农场时,更新报告数据
-const changeGarden = async ({ id, name,farm_variety,variety_name }) => {
-    currentFarmVariety.value = farm_variety;
-    varietyName.value = variety_name;
-    if (!id) return;
-    currentFarmName.value = name;
-    if (sessionStorage.getItem('activeSwipeIndex')) {
-        currentIndex.value = Number(sessionStorage.getItem('activeSwipeIndex'));
-    } else {
-        currentIndex.value = 0;
-        swipeRef.value && swipeRef.value.swipeTo(0, { immediate: true });
-    }
-    paramsPage.value = {
-        ...(paramsPage.value || {}),
-        subjectId: id,
-    };
-    // 初始化品种/大物候期转换
-    startInteractPopupRef.value.getPhenologyInitOrConfirmStatus();
-    await getSubjectData(id);
-    hasReport.value = true;
-    // await getRegions();
-};
-
-onActivated(() => {
-    if (!localeToggleEnabled) {
-        store.dispatch("locale/setLocale", "zh");
-    }
-    window.scrollTo(0, 0);
-    // 从新增农场页返回时,优先用缓存中的最新选中农场
-    const savedFarmId = localStorage.getItem("selectedFarmId");
-    selectedGardenId.value = savedFarmId ? Number(savedFarmId) : null;
-    gardenListRef.value?.refreshFarmList?.();
-
-    // 如果路由中带有 miniJson,并且其中有 showBind,则展示绑定成功弹窗
-    const { miniJson } = route.query || {};
-    if (miniJson) {
-        try {
-            const parsed = typeof miniJson === "string" ? JSON.parse(miniJson) : miniJson;
-            if (parsed && parsed.showBind) {
-                showBindSuccess.value = true;
-                // 处理完后清空路由中的 miniJson 参数,避免重复弹出
-                const newQuery = { ...(route.query || {}) };
-                delete newQuery.miniJson;
-                router.replace({ path: route.path, query: newQuery });
-            }
-        } catch (e) {
-            // miniJson 解析失败时忽略,不影响正常流程
-        }
-    }
-    // getResultReport();
-});
-
-const closeTabMask = () => {
-    showTabMask.value = false;
-};
-
-const userInfo = localStorage.getItem("localUserInfo");
-const userInfoObj = userInfo ? JSON.parse(userInfo) : {};
-
-const handleLockClick = () => {
-    if (currentFarmName.value) {
-        // router.push("/interaction?subjectId=" + localStorage.getItem("selectedFarmId"));
-        router.push(`/create_farm?from=growth_report&isReload=true`);
-        return;
-    }
-    if (userInfoObj?.tel) {
-        router.push(`/create_farm?from=growth_report&isReload=true`);
-        return;
-    }
-    wx.miniProgram.navigateTo({
-        url: '/pages/subPages/phone_auth/index',
-    });
-}
-
-const handleAddFarm = () => {
-    router.push(`/create_farm?from=growth_report&isReload=true`);
-}
-
-const todayPatrolFocus = ref([]);
-const pendingFarmWork = ref([]);
-const handlePendingFarmWorkClick = (card) => {
-    router.push({
-        path: "/work_detail",
-        query: {
-            miniJson: JSON.stringify({
-                paramsPage: JSON.stringify({
-                    farmId: paramsPage.value.farmId,
-                    farmWorkLibId: card?.farmWorkLibId,
-                    recordId: card?.recordId,
-                    typeId: regionsData.value[currentIndex.value].typeId
-                }),
-            }),
-        },
-    });
-}
-// 点击今日巡园重点
-const handleTodayPatrolFocusClick = (card) => {
-    if (!card.interactionTypeId) return;
-    router.push(`/interaction_list?farmId=${paramsPage.value.farmId}&regionId=${paramsPage.value.regionId}&interactionTypeId=${card.interactionTypeId}`);
-}
-
-const getTodayPatrolFocus = () => {
-    VE_API.report.todayPatrolFocus({ farmId: paramsPage.value.farmId }).then(({ data }) => {
-        todayPatrolFocus.value = data || [];
-    });
-}
-
-const getPendingFarmWork = () => {
-    VE_API.report.pendingFarmWork({ farmId: paramsPage.value.farmId, regionId: paramsPage.value.regionId }).then(({ data }) => {
-        pendingFarmWork.value = data || [];
-    });
-}
-
-const currentIndex = ref(0);
-const handleSwipeChange = (index) => {
-    currentIndex.value = index;
-    if (paramsPage.value.regionId !== regionsData.value[index].regionId) {
-        paramsPage.value = {
-            ...(paramsPage.value || {}),
-            farmId: regionsData.value[index].farmId,
-            regionId: regionsData.value[index].regionId,
-        };
-        getTodayPatrolFocus();
-        getPendingFarmWork();
-        getDetail();
-    }
-}
-
-const getDetail = () => {
-    if (!paramsPage.value.farmId) return;
-    loading.value = true;
-    VE_API.report
-        .reproductiveReport({ farmId: paramsPage.value.farmId, regionId: paramsPage.value.regionId })
-        .then(({ data }) => {
-            workItems.value = data || [];
-        })
-        .finally(() => {
-            loading.value = false;
-        });
-};
-
-const subjectData = ref([])
-const typeTabsExpanded = ref(false);
-const visibleSubjectData = computed(() => {
-    if (typeTabsExpanded.value) {
-        return subjectData.value;
-    }
-    return subjectData.value.slice(0, 4);
-});
-const showSubjectToggle = computed(() => subjectData.value.length > 4);
-
-const getSubjectData = async (id) => {
-    const res = await VE_API.monitor.listFarmsBySubjectId({ subjectId: id });
-    // subjectData.value = res.data || [];
-    subjectData.value = [...res.data, ...res.data, ...res.data, ...res.data];
-    typeTabsExpanded.value = false;
-}
-
-const activeReportIndex = ref(0);
-const activeSubjectIndex = ref(0);
-const handleTypeTabClick = (item, index) => {
-    activeSubjectIndex.value = index;
-    paramsPage.value = {
-            ...(paramsPage.value || {}),
-            farmId: item.farmId,
-    };
-    getTodayPatrolFocus();
-}
-
-const regionsData = ref([]);
-const getRegions = async () => {
-    VE_API.monitor.listRegionsBySubjectId({
-        subjectId: paramsPage.value.subjectId,
-    }).then(({ data }) => {
-        console.log(data);
-        regionsData.value = data || [];
-        if (regionsData.value.length > 0) {
-            hasReport.value = true;
-            const hasShownTabGuide = localStorage.getItem(TAB_GUIDE_SHOWN_KEY) === "1";
-
-            // 首次进入且有分区数据:显示农场列表引导
-            if (!hasShownTabGuide) {
-                showTabMask.value = true;
-                localStorage.setItem(TAB_GUIDE_SHOWN_KEY, "1");
-            } else {
-                showTabMask.value = false;
-            }
-
-            // 切换农场tab回到当前农场tab
-            weatherInfoRef.value && weatherInfoRef.value.handleGardenClick('current');
-
-            // 如果不是点击农情报告已生成弹窗过来的,则显示农情互动弹窗
-            if (!route.query.hideInteraction) {
-                agriExecutePopupRef.value.showPopup(regionsData.value[currentIndex.value].farmId);
-            }
-
-            paramsPage.value = {
-                ...(paramsPage.value || {}),
-                farmId: regionsData.value[currentIndex.value].farmId,
-                regionId: regionsData.value[currentIndex.value].regionId,
-            };
-            getTodayPatrolFocus();
-            getPendingFarmWork();
-            getDetail();
-            // 如果是新增品种后跳转过来的,等待 Swipe 实例挂载后再定位
-            if (route.query.addVarietyCount) {
-                const targetIndex = Number(route.query.addVarietyCount);
-                if (!Number.isNaN(targetIndex) && targetIndex >= 0) {
-                    const safeIndex = Math.min(targetIndex, regionsData.value.length - 1);
-                    const reverseIndex = Math.min(
-                        regionsData.value.length - 1,
-                        Math.max(0, regionsData.value.length - safeIndex)
-                    );
-                    nextTick(() => {
-                        swipeRef.value?.swipeTo?.(reverseIndex, { immediate: true });
-                    });
-                }
-            }
-
-            if (sessionStorage.getItem('activeSwipeIndex')) {
-                nextTick(() => {
-                    swipeRef.value?.swipeTo?.(currentIndex.value, { immediate: true });
-                });
-                sessionStorage.removeItem('activeSwipeIndex');
-            }
-        } else {
-            // 切换农场tab回到当前农场tab
-            // weatherInfoRef.value && weatherInfoRef.value.handleGardenClick('current');
-            showTabMask.value = false;
-            hasReport.value = false;
-        }
-    });
-}
-
-/** 切换语言后,用新 lang 参数重新请求页面数据 */
-const reloadPageDataAfterLocaleChange = () => {
-    gardenListRef.value?.refreshFarmList?.();
-
-    const subjectId = paramsPage.value.subjectId || localStorage.getItem("selectedFarmId");
-    if (subjectId) {
-        getSubjectData(subjectId);
-    }
-
-    if (paramsPage.value.farmId) {
-        getTodayPatrolFocus();
-        getPendingFarmWork();
-        getDetail();
-    }
-
-    startInteractPopupRef.value?.getPhenologyInitOrConfirmStatus?.();
-};
-
-const toggleLocale = async () => {
-    await dispatchToggleLocale();
-    reloadPageDataAfterLocaleChange();
-};
-
-const onReportTitleClick = () => {
-    if (!localeToggleEnabled) return;
-    toggleLocale();
-};
-
-// 清理数据的函数
-const clearData = () => {
-    workItems.value = [];
-    paramsPage.value = {};
-    loading.value = false;
-};
-
-onDeactivated(() => {
-    sessionStorage.setItem('activeSwipeIndex', currentIndex.value);
-    clearData();
-});
-
-onUnmounted(() => {
-    clearData();
-});
-</script>
-
-<style lang="scss" scoped>
-.mask-wrap {
-    position: fixed;
-    bottom: 0;
-    left: 0;
-    width: 100%;
-    height: 300px;
-    background-color: rgba(0, 0, 0, 0.52);
-    z-index: 99999;
-}
-
-.achievement-report-page {
-    width: 100%;
-    height: 100vh;
-    background: linear-gradient(195.35deg, #d4e4ff 16.34%, rgba(93, 189, 255, 0) 50.3%),
-        linear-gradient(156.64deg, rgba(255, 255, 255, 0.16) 27.7%, rgba(255, 255, 255, 0) 72.82%);
-
-    .weather-mask {
-        position: fixed;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        background-color: rgba(0, 0, 0, 0.52);
-        z-index: 11;
-    }
-
-    .weather-info-wrap {
-        width: calc(100% - 20px);
-        position: absolute;
-        z-index: 12;
-        left: 10px;
-        top: 10px;
-
-        .weather-info {
-            width: 100%;
-        }
-
-        .invite-follow {
-            position: absolute;
-            right: -6px;
-            top: 50px;
-
-            .invite-content {
-                display: flex;
-                align-items: center;
-                gap: 4px;
-                font-size: 14px;
-                font-family: "PangMenZhengDao";
-                color: #fff;
-                line-height: 30px;
-                padding: 0 12px;
-                border-radius: 20px 0 0 20px;
-                height: 30px;
-                cursor: pointer;
-                background: #2199F8;
-                position: relative;
-
-                &::after {
-                    content: '';
-                    position: absolute;
-                    bottom: -6px;
-                    right: 0;
-                    width: 0px;
-                    height: 0px;
-                    border-right: 3px solid transparent;
-                    border-top: 3px solid #75a8cd;
-                    border-left: 3px solid #75a8cd;
-                    border-bottom: 3px solid transparent;
-                }
-            }
-        }
-    }
-
-
-    .fake-report-wrap {
-        width: 100%;
-
-        .no-report-img {
-            width: 100%;
-        }
-
-        .fake-img {
-            position: relative;
-
-            .fake-img-item {
-                width: 100%;
-            }
-        }
-    }
-
-    .report-content-wrap {
-        height: 100%;
-        // padding-bottom: 60px;
-        overflow: auto;
-        box-sizing: border-box;
-        position: relative;
-
-        .history-risk-report-btn {
-            position: absolute;
-            right: 0px;
-            // top: 155px;
-            top: 120px;
-            z-index: 13;
-            height: 26px;
-            padding: 0 10px 0 8px;
-            display: inline-flex;
-            align-items: center;
-            gap: 4px;
-            color: #ffffff;
-            font-size: 14px;
-            border-radius: 13px 0 0 13px;
-            background: linear-gradient(180deg, #60c2ff 0%, #2199f8 100%);
-            box-shadow: 0 2px 6px rgba(33, 153, 248, 0.3);
-            cursor: pointer;
-
-            .risk-report-icon {
-                width: 14px;
-                height: 14px;
-                border-radius: 2px;
-                background: #ffffff;
-                position: relative;
-                display: inline-flex;
-                align-items: center;
-                justify-content: center;
-                transform: rotate(-12deg);
-
-                i {
-                    width: 8px;
-                    height: 2px;
-                    border-radius: 2px;
-                    background: #42a7ff;
-                    box-shadow: 0 3px 0 #42a7ff;
-                }
-            }
-
-            .risk-report-text {
-                line-height: 1;
-                white-space: nowrap;
-            }
-        }
-
-        .bottom-btn {
-            z-index: 2;
-            position: fixed;
-            bottom: 0;
-            left: 0;
-            width: 100%;
-            background: #fff;
-            height: 60px;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            padding: 0 12px;
-            box-sizing: border-box;
-            box-shadow: 2px 2px 4.5px 0px rgba(0, 0, 0, 0.4);
-
-            .btn-item {
-                height: 40px;
-                line-height: 40px;
-                padding: 0 24px;
-                border-radius: 20px;
-                font-size: 14px;
-
-                &.second {
-                    color: #666666;
-                    border: 1px solid rgba(153, 153, 153, 0.5);
-                }
-
-                &.primay {
-                    padding: 0 34px;
-                    background: linear-gradient(180deg, #76c3ff, #2199f8);
-                    color: #fff;
-                }
-            }
-        }
-    }
-
-    .code-icon {
-        position: absolute;
-        right: 10px;
-        top: 12px;
-        width: 48px;
-    }
-
-    .report-content {
-        // background: linear-gradient(0deg, #9BCCFF, #9BCCFF),
-        //     linear-gradient(160deg, rgba(255, 255, 255, 0.16) 30%, rgba(255, 255, 255, 0) 72%);
-        background: #abd4ff;
-
-        background-size: 100% auto;
-        background-position: top center;
-        padding: 0 10px 26px 10px;
-        box-sizing: border-box;
-        position: relative;
-
-        &.has-report {
-            min-height: 100%;
-            background: linear-gradient(0deg, #9BCCFF, #9BCCFF),
-                linear-gradient(156.64deg, rgba(255, 255, 255, 0.16) 27.7%, rgba(255, 255, 255, 0) 72.82%);
-        }
-
-        .lock-bg {
-            position: absolute;
-            top: 230px;
-            left: 0;
-            width: 100%;
-            height: calc(100% - 230px);
-            background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.38) 50%, rgba(255, 255, 255, 0) 100%),
-                linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2));
-        }
-
-        .lock-img {
-            pointer-events: none;
-            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;
-            }
-
-            .has-click {
-                pointer-events: auto;
-            }
-
-            .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;
-            }
-        }
-
-        .header-img {
-            position: absolute;
-            top: 0;
-            left: 0;
-            width: 100%;
-        }
-
-        .type-tabs {
-            background: rgba(255, 255, 255, 0.8);
-            display: flex;
-            align-items: center;
-            flex-wrap: wrap;
-            gap: 8px;
-            width: fit-content;
-            border-radius: 5px;
-            padding: 5px;
-            margin-bottom: 22px;
-            &.report-tabs {
-                padding: 0 5px;
-                height: 38px;
-                background: none;
-                margin-bottom: 6px;
-                .type-item {
-                    height: 34px;
-                    line-height: 34px;
-                    font-size: 14px;
-                    color: #858585;
-                }
-            }
-            .type-item {
-                height: 28px;
-                line-height: 28px;
-                text-align: center;
-                padding: 0 6px;
-                min-width: 80px;
-                color: #9A9A9A;
-                background: #FFFFFF;
-                box-sizing: border-box;
-                border-radius: 2px;
-                &.type-item-active {
-                    background: #2199F8;
-                    color: #fff;
-                }
-            }
-        }
-
-        .subject-toggle {
-            margin-top: 4px;
-            margin-bottom: 5px;
-            font-size: 14px;
-            color: rgba(0, 0, 0, 0.6);
-            width: 100%;
-            cursor: pointer;
-            text-align: center;
-        }
-
-        .report-header {
-            position: relative;
-            // padding-top: 148px;
-            padding-top: 120px;
-
-            &.no-farm {
-                padding-top: 102px;
-            }
-
-            .header-book {
-                position: absolute;
-                right: 0;
-                bottom: -6px;
-                height: 88px;
-                z-index: 10;
-            }
-
-            .time-tag {
-                background: #2199F8;
-                border-radius: 5px 0 5px 0;
-                height: 23px;
-                line-height: 23px;
-                font-size: 13px;
-                font-weight: 500;
-                color: #fff;
-                padding: 0 9px;
-                width: fit-content;
-                margin-bottom: 4px;
-            }
-
-            .report-title {
-                font-family: "PangMenZhengDao";
-                font-size: 34px;
-                line-height: 38px;
-
-                &.report-title-toggle {
-                    cursor: pointer;
-                    user-select: none;
-                }
-                color: #000000;
-            }
-
-            .report-info {
-                padding: 12px 0 28px 0;
-
-                &.pb-4 {
-                    padding-bottom: 4px;
-                }
-
-                .info-item {
-                    width: fit-content;
-                    display: flex;
-                    height: 33px;
-                    align-items: center;
-                    padding: 0 18px 0 6px;
-                    background: rgba(255, 255, 255, 0.58);
-                    backdrop-filter: blur(5px);
-                    border-radius: 20px;
-                    gap: 6px;
-
-                    .info-icon {
-                        width: 26px;
-                        height: 26px;
-                        object-fit: cover;
-                        border-radius: 50%;
-                    }
-
-                    .info-text {
-                        font-size: 14px;
-                        color: #000;
-                    }
-                }
-
-                .info-item+.info-item {
-                    margin-top: 5px;
-                }
-            }
-
-            // 左滑查看更多标签
-            .swipe-more-tag {
-                position: absolute;
-                bottom: 10px;
-                right: -16px;
-                box-sizing: border-box;
-                width: 36px;
-                height: 86px;
-                // padding: 0px 10px 2px 0;
-                background: rgba(0, 0, 0, 0.7);
-                border-radius: 10px 0 0 10px;
-                letter-spacing: 2px;
-                color: #ffffff;
-                font-size: 12px;
-                text-align: center;
-                line-height: 14px;
-                writing-mode: vertical-rl;
-                text-orientation: mixed;
-                padding-right: 5px;
-            }
-        }
-
-        .report-box {
-            display: flex;
-            align-items: center;
-            padding: 8px 12px;
-            // background: linear-gradient(0deg, #ffffff 86%, #2199f8 136%);
-            background: #fff;
-            border: 1px solid #ffffff;
-            border-radius: 8px;
-            gap: 5px;
-            position: relative;
-            &.warning-bg {
-                background: linear-gradient(0deg, #FFFFFF 86%, #FF9B48 136%);
-            }
-
-            .report-box-item {
-                flex: 1;
-                background: rgba(33, 153, 248, 0.1);
-                border-radius: 8px;
-                min-height: 62px;
-                box-sizing: border-box;
-                padding: 2px 4px;
-                display: flex;
-                flex-direction: column;
-                justify-content: center;
-
-                .item-content {
-                    color: #2199f8;
-                    font-size: 14px;
-                    text-align: center;
-                }
-
-                .item-title {
-                    color: #000000;
-                    font-size: 10px;
-                    text-align: center;
-                    padding-top: 5px;
-                }
-            }
-
-            .box-title {
-                position: absolute;
-                top: -8px;
-                left: -1px;
-                height: 32px;
-                line-height: 26px;
-                font-family: "PangMenZhengDao";
-                font-size: 14px;
-                padding: 0 10px;
-                color: #ffffff;
-                background: url("@/assets/img/home/title-bg.png") no-repeat center center / 100% 100%;
-
-                &.warning {
-                    background: url("@/assets/img/home/title-bg-warning.png") no-repeat center center / 100% 100%;
-                }
-            }
-
-            .w-100 {
-                width: 100%;
-            }
-
-            .box-text {
-                padding: 22px 0 8px 0;
-                font-weight: 350;
-                line-height: 21px;
-                width: 100%;
-                box-sizing: border-box;
-
-                .pre-text {
-                    white-space: pre-line;
-                    word-break: break-word;
-                }
-
-                .box-subtitle {
-                    color: #000;
-                }
-
-                .box-bg {
-                    font-weight: 400;
-                    color: rgba(0, 0, 0, 0.5);
-                    margin-bottom: 8px;
-                }
-
-                .types-info {
-                    background: rgba(33, 153, 248, 0.1);
-                    color: #000000;
-                    padding: 6px;
-                    border-radius: 5px;
-                    .text-bold {
-                        font-weight: bold;
-                    }
-                }
-                .tp-img {
-                    display: grid;
-                    grid-template-columns: repeat(3, 1fr);
-                    gap: 6px;
-                    width: 100%;
-                    margin-top: 8px;
-                    box-sizing: border-box;
-                    img {
-                        width: 100%;
-                        height: 78px;
-                        object-fit: contain;
-                    }
-                }
-                .text-link {
-                    color: #2199F8;
-                    text-decoration: underline;
-                }
-
-                .report-part {
-                    color: rgba(0, 0, 0, 0.5);
-                    .part-title {
-                        background: #2199F8;
-                        height: 24px;
-                        line-height: 24px;
-                        padding: 0 8px;
-                        color: #fff;
-                        border-radius: 2px;
-                        width: fit-content;
-                    }
-                    .part-text {
-                        padding-top: 6px;
-                        :deep(.text-bold) {
-                            font-weight: bold;
-                        }
-                    }
-                    .part-top {
-                        display: flex;
-                        align-items: center;
-                        justify-content: space-between;
-                        .part-link {
-                            display: inline-flex;
-                            align-items: center;
-                            gap: 4px;
-                            color: #2199F8;
-                            .part-link-icon {
-                                transform: rotate(270deg);
-                            }
-                        }
-                    }
-                }
-                .warning-part + .warning-part {
-                    margin-top: 8px;
-                }
-                .report-part + .report-part {
-                    margin-top: 8px;
-                }
-
-                .warning-part {
-                    background: rgba(178, 178, 178, 0.08);
-                    border-radius: 5px;
-                    padding: 11px 6px 6px;
-                    color: rgba(0, 0, 0, 0.5);
-                    width: 100%;
-                    box-sizing: border-box;
-                    .warning-title {
-                        display: flex;
-                        align-items: center;
-                        justify-content: center;
-                        gap: 10px;
-                        padding-bottom: 13px;
-                        .title-l {
-                            display: flex;
-                            align-items: center;
-                            .title-line {
-                                width: 68px;
-                                height: 1px;
-                                background: linear-gradient(90deg, rgba(118, 118, 118, 0) 0%, rgba(118, 118, 118, 0.4) 100%);
-                                &.title-line-right {
-                                    background: linear-gradient(270deg, rgba(118, 118, 118, 0) 0%, rgba(118, 118, 118, 0.4) 100%);
-                                }
-                            }
-                            .title-block {
-                                width: 6px;
-                                height: 6px;
-                                background: rgba(61, 61, 61, 0.2);
-                                transform: rotate(45deg);
-                            }
-                        }
-                    }
-                }
-
-                .box-advice {
-                    color: rgba(0, 0, 0, 0.5);
-                    padding-top: 10px;
-                }
-
-                .box-sum {
-                    margin-top: 10px;
-                    background: rgba(33, 153, 248, 0.1);
-                    border-radius: 5px;
-                    padding: 10px;
-                    line-height: 20px;
-                    color: #2199F8;
-                }
-
-                &.next-info {
-                    padding: 8px 0 8px 0;
-                }
-            }
-
-            .row {
-                display: grid;
-                grid-template-columns: repeat(3, 1fr);
-                gap: 6px;
-
-
-
-                .status-card {
-                    border-radius: 2px;
-                    padding: 7px 0;
-                    background: #ffffff;
-                    border: 0.5px solid #e5e6eb;
-                    color: #000;
-                    display: flex;
-                    flex-direction: column;
-                    align-items: center;
-                    justify-content: center;
-
-                    &.today-red {
-                        background: #FF6A6A;
-                        color: #fff;
-
-                        .status-sub {
-                            color: #fff;
-                        }
-                    }
-
-                    &.pending-card {
-                        color: #fff;
-                        position: relative;
-                        padding: 9px 0 7px 0;
-
-                        .tag-name {
-                            position: absolute;
-                            top: -8px;
-                            right: 0;
-                            background: #fff;
-                            color: #FF6A6A;
-                            font-size: 10px;
-                            height: 17px;
-                            line-height: 17px;
-                            padding: 0 3px;
-                            border-radius: 2px;
-                            box-sizing: border-box;
-                            border: 0.5px solid #FF6A6A;
-                        }
-                    }
-
-                    .status-badge {
-                        // position: absolute;
-                        // top: 0;
-                        // right: 0;
-                    }
-
-                    .status-title {
-                        font-size: 16px;
-                        line-height: 24px;
-
-                        &.status-title-small {
-                            font-size: 13px;
-                            line-height: 18px;
-                        }
-                    }
-
-                    .status-sub {
-                        font-size: 10px;
-                        color: rgba(32, 32, 32, 0.4);
-                        line-height: 15px;
-
-                        &.pending-sub {
-                            color: #fff;
-                            line-height: 13px;
-                        }
-                    }
-
-                    &.risk-strong {
-                        background: #FF6A6A;
-                        border-color: #FF6A6A;
-
-                        .status-title,
-                        .status-sub {
-                            color: #ffffff;
-                        }
-                    }
-
-                    &.danger {
-                        background: #FFE9E9;
-                        border-color: #ff8e8e;
-
-                        .status-sub {
-                            color: #FF6A6A;
-                        }
-                    }
-                }
-            }
-        }
-
-        .report-box+.report-box {
-            margin-top: 20px;
-        }
-
-        .report-excute {
-            position: relative;
-            margin-top: 12px;
-
-            .tag-label {
-                position: absolute;
-                top: 0;
-                left: 0;
-                padding: 4px 10px;
-                background: rgba(54, 52, 52, 0.8);
-                color: #fff;
-                font-size: 12px;
-                border-radius: 8px 0 8px 0;
-                z-index: 1;
-            }
-
-            ::v-deep {
-                .carousel-container .carousel-wrapper .carousel-img {
-                    min-width: calc(100vw - 32px);
-                    width: calc(100vw - 32px);
-                }
-            }
-        }
-    }
-
-    .download-btn {
-        position: fixed;
-        bottom: 20px;
-        left: 50%;
-        // background: #fff;
-        // box-shadow: 2px 2px 4.5px 0px #00000066;
-        // width: 100%;
-        transform: translateX(-50%);
-    }
-
-    .review-hide-box {
-        position: absolute;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        z-index: -1;
-        bottom: 0;
-    }
-
-    .review-image {
-        position: relative;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        gap: 8px;
-        margin: 12px;
-        background: #fff;
-        border-radius: 8px;
-
-        .review-mask {
-            z-index: 1;
-            pointer-events: none;
-            position: absolute;
-            left: 0;
-            top: 0;
-            width: 100%;
-            height: 100%;
-            border-radius: 8px;
-            background: linear-gradient(360deg,
-                    rgba(0, 0, 0, 0.78) 0%,
-                    rgba(0, 0, 0, 0.437208) 19.87%,
-                    rgba(0, 0, 0, 0) 33.99%);
-            display: flex;
-            flex-direction: column;
-            align-items: baseline;
-            justify-content: end;
-            padding: 12px;
-            box-sizing: border-box;
-            color: #fff;
-
-            .review-text {
-                font-family: "PangMenZhengDao";
-                font-size: 16px;
-                margin-bottom: 1px;
-            }
-
-            .review-content {
-                font-size: 10px;
-                line-height: 15px;
-            }
-        }
-
-        .vs-wrap {
-            position: absolute;
-            left: 50%;
-            top: 50%;
-            transform: translate(-50%, -50%);
-            width: 40px;
-            height: 40px;
-            z-index: 10;
-
-            img {
-                width: 100%;
-                height: 100%;
-                object-fit: cover;
-            }
-        }
-
-        .review-image-item {
-            position: relative;
-            flex: 1;
-
-            .review-image-item-title {
-                position: absolute;
-                top: 0;
-                left: 0;
-                background: rgba(54, 52, 52, 0.6);
-                padding: 4px 10px;
-                border-radius: 8px 0 8px 0;
-                backdrop-filter: 4px;
-                font-size: 12px;
-                color: #fff;
-            }
-
-            // .review-image-item-img {
-            //     width: 100%;
-            //     height: 250px;
-            //     object-fit: cover;
-            // }
-            .review-image-item-img {
-                width: 100%;
-                height: 100%;
-                object-fit: cover;
-                object-position: center;
-            }
-
-            .left-img {
-                border-radius: 8px 0 0 8px;
-            }
-
-            .right-img {
-                border-radius: 0 8px 8px 0;
-            }
-        }
-    }
-}
-
-
-.cavans-popup {
-    width: 100%;
-    max-width: 100%;
-    max-height: 92vh;
-    background: none;
-    border-radius: 12px;
-    overflow: auto;
-    display: flex;
-    flex-direction: column;
-    backdrop-filter: 4px;
-
-    .cavans-content {
-        text-align: center;
-        padding: 0 12px;
-        height: fit-content;
-        overflow: auto;
-
-        .current-img {
-            width: 100%;
-        }
-    }
-
-    // 底部操作按钮
-    .bottom-actions {
-        flex-shrink: 0;
-
-        .action-buttons {
-            padding: 12px 0 4px 0;
-            display: flex;
-            justify-content: space-around;
-
-            .action-btn {
-                display: flex;
-                flex-direction: column;
-                align-items: center;
-                cursor: pointer;
-
-                &.text-btn {
-                    font-size: 12px;
-                    color: rgba(255, 255, 255, 0.7);
-                }
-
-                .icon-circle {
-                    width: 48px;
-                    height: 48px;
-                    border-radius: 50%;
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    color: #fff;
-                    margin-bottom: 4px;
-
-                    .el-icon {
-                        color: #fff;
-                    }
-
-                    img {
-                        width: 50px;
-                    }
-                }
-
-                &.blue-btn .icon-circle {
-                    background: #2199f8;
-                }
-
-                &.green-btn .icon-circle {
-                    background: #07c160;
-                }
-
-                &.orange-btn .icon-circle {
-                    background: #ff790b;
-                }
-
-                .btn-label {
-                    font-size: 12px;
-                    color: #fff;
-                }
-            }
-        }
-
-        .cancel-btn {
-            text-align: center;
-            font-size: 18px;
-            color: #fff;
-            cursor: pointer;
-        }
-    }
-}
-</style>