刘秀芳 1 день назад
Родитель
Сommit
bb72f38703

BIN
src/assets/img/agricultural/notice.png


BIN
src/assets/img/common/header-icon-1.png


BIN
src/assets/img/common/header-icon-2.png


BIN
src/assets/img/common/header-icon-3.png


+ 8 - 10
src/views/old_mini/agri_file/components/patrolPanel.vue

@@ -364,12 +364,12 @@ const fetchAbnormalInteract = async () => {
     try {
         const res = await VE_API.questionnaire.getAbnormalInteract({
             crop_type: cropType,
-            // farm_id: farmId,
-            // zone_id: zoneId,
-            // calc_date: formatToday(),
-            farm_id: 321,
-            zone_id: 46,
-            calc_date: '2025-08-30',
+            farm_id: farmId,
+            zone_id: zoneId,
+            calc_date: formatToday(),
+            // farm_id: 321,
+            // zone_id: 46,
+            // calc_date: '2025-08-30',
         });
         if (res?.code !== 200) {
             clearAbnormalPatrol();
@@ -504,15 +504,13 @@ const goAddVariety = () => {
 };
 
 const goGrowthTrack = (item) => {
-    const isAbnormal = item?.type === "abnormal";
+    const isAbnormal = item?.type !== "growth";
     router.push({
         path: isAbnormal ? "/abnormal_track" : "/growth_track",
         query: {
             id: item?.id,
             ...(item?.zoneId != null && item?.zoneId !== "" ? { zoneId: item.zoneId } : {}),
-            pageName: isAbnormal
-                ? t("agriFile.patrolAbnormalTitle")
-                : t("agriFile.patrolGrowthTitle"),
+            pageName: item.title || "详情"
         },
     });
 };

+ 142 - 127
src/views/old_mini/agri_file/pages/abnormalTrack.vue

@@ -17,7 +17,7 @@
                 <div class="abnormal-top">
                     <div class="abnormal-hero__tags">
                         <span class="abnormal-hero__tag abnormal-hero__tag--level">
-                            <el-icon><BellFilled /></el-icon>
+                            <el-icon><WarningFilled /></el-icon>
                             {{ level }}
                         </span>
                         <span class="abnormal-hero__tag abnormal-hero__tag--zone">{{ zoneName }}</span>
@@ -37,15 +37,8 @@
                         </div>
                         <div class="analysis-card__desc">{{ assessmentDesc }}</div>
                         <div class="analysis-card__stats">
-                            <div
-                                v-for="(item, index) in analysisStats"
-                                :key="index"
-                                class="analysis-card__stat"
-                            >
-                                <div
-                                    class="analysis-card__stat-value"
-                                    :class="{ highlight: item.highlight }"
-                                >
+                            <div v-for="(item, index) in analysisStats" :key="index" class="analysis-card__stat">
+                                <div class="analysis-card__stat-value" :class="{ highlight: item.highlight }">
                                     <template v-if="item.unit">
                                         <span class="num">{{ item.value }}</span>
                                         <span class="unit">{{ item.unit }}</span>
@@ -60,82 +53,71 @@
 
                 <!-- 异常排查互动 -->
                 <div class="interact-section-head">
-                    <span class="interact-section-head__text">
-                        异常排查互动 · 共 {{ interactList.length }} 项
-                    </span>
+                    <span class="interact-section-head__text"> 异常排查互动 · 共 {{ interactList.length }} 项 </span>
                     <span class="interact-section-head__line"></span>
                 </div>
 
-                <div
-                    v-for="(item, index) in interactList"
-                    :key="item.fw_code || index"
-                    class="abnormal-item"
-                >
-                    <div class="abnormal-item__title">
-                        <img
-                            class="abnormal-item__icon"
-                            src="@/assets/img/agricultural/gaojin.png"
-                            alt=""
-                        />
-                        <span>{{ item.abnormal_type || t("agriFile.rootAbnormal") }}</span>
-                    </div>
+                <div v-for="(item, index) in interactList" :key="item.fw_code || index" class="abnormal-item">
+                    <div class="abnormal-item__wrap">
+                        <div class="abnormal-item__title">
+                            <img class="abnormal-item__icon" src="@/assets/img/agricultural/gaojin.png" alt="" />
+                            <span>{{ item.abnormal_type || t("agriFile.rootAbnormal") }}</span>
+                        </div>
 
-                    <div class="box-wrap stage-card interact-card">
-                        <div class="work-info">
-                            <div class="interact-card__head">
-                                <div class="section-title">
-                                    <span class="title-bar"></span>
-                                    {{ t("agriFile.interactQuestion") }}
-                                </div>
-                                <div
-                                    class="interact-card__submit"
-                                    :class="{ disabled: selectedMap[item.fw_code || index] == null }"
-                                    @click="handleSubmit(item, index)"
-                                >
-                                    确认提交
-                                </div>
-                            </div>
-                            <div class="interact-card__qa">
-                                <div class="interact-card__question">{{ item.interact_problem }}</div>
-                                <div class="interact-card__options">
+                        <div class="stage-card interact-card">
+                            <div class="work-info">
+                                <div class="interact-card__head">
+                                    <div class="section-title interact-card__title">
+                                        <span class="title-bar"></span>
+                                        {{ t("agriFile.interactQuestion") }}
+                                    </div>
                                     <div
-                                        v-for="(opt, optIndex) in item.options"
-                                        :key="`${item.fw_code || index}-${optIndex}`"
-                                        class="interact-option"
-                                        :class="{
-                                            selected: selectedMap[item.fw_code || index] === optIndex,
-                                        }"
-                                        @click="selectedMap[item.fw_code || index] = optIndex"
+                                        class="interact-card__submit"
+                                        :class="{ disabled: selectedMap[item.fw_code || index] == null }"
+                                        @click="handleSubmit(item, index)"
                                     >
-                                        <span class="interact-option__text">{{ opt }}</span>
+                                        确认提交
+                                    </div>
+                                </div>
+                                <div class="interact-card__qa">
+                                    <div class="interact-card__question">{{ item.interact_problem }}</div>
+                                    <div class="interact-card__options">
+                                        <div
+                                            v-for="(opt, optIndex) in item.options"
+                                            :key="`${item.fw_code || index}-${optIndex}`"
+                                            class="interact-option"
+                                            :class="{
+                                                selected: selectedMap[item.fw_code || index] === optIndex,
+                                            }"
+                                            @click="selectedMap[item.fw_code || index] = optIndex"
+                                        >
+                                            <span class="interact-option__text">{{ opt }}</span>
+                                        </div>
                                     </div>
                                 </div>
                             </div>
                         </div>
-                    </div>
-                </div>
-
-                <!-- 巡园向导 -->
-                <div class="box-wrap stage-card guide-card">
-                    <div class="work-info">
-                        <div class="section-title">
-                            <img class="guide-icon" src="@/assets/img/farm/guide.png" alt="" />
-                            {{ t("agriFile.patrolGuide") }}
-                        </div>
-                        <photo-provider :photo-closable="true">
-                            <photo-consumer :src="guideImage">
-                                <img class="guide-card__img" :src="guideImage" alt="" />
-                            </photo-consumer>
-                        </photo-provider>
-                    </div>
+                        <!-- 巡园向导 -->
+                        <div class="guide-card">
+                            <div class="work-info">
+                                <div class="section-title">
+                                    <img class="guide-icon" src="@/assets/img/farm/guide.png" alt="" />
+                                    {{ t("agriFile.patrolGuide") }}
+                                </div>
+                                <div class="guide-card__img-box">
+                                    <photo-provider :photo-closable="true">
+                                        <photo-consumer :src="resolveGuideImage(item.pic_url)">
+                                            <img :src="resolveGuideImage(item.pic_url)" alt="" />
+                                        </photo-consumer>
+                                    </photo-provider>
+                                </div>
+                            </div>
 
-                    <div class="guide-card__upload-wrap">
-                        <div class="guide-card__upload" @click="handleUploadClick">
-                            <img
-                                class="guide-card__upload-icon"
-                                src="@/assets/img/common/camera.png"
-                                alt=""
-                            />
+                            <div class="guide-card__upload-wrap">
+                                <div class="guide-card__upload" @click="handleUploadClick">
+                                    <img class="guide-card__upload-icon" src="@/assets/img/common/camera.png" alt="" />
+                                </div>
+                            </div>
                         </div>
                     </div>
                 </div>
@@ -207,17 +189,11 @@ const zoneId = computed(() => route.query.zoneId || route.query.id);
 
 const firstInteract = computed(() => interactList.value[0] || null);
 /** interaction_theme */
-const theme = computed(
-    () => firstInteract.value?.interaction_title || t("agriFile.interactTheme")
-);
+const theme = computed(() => firstInteract.value?.interaction_title || t("agriFile.interactTheme"));
 /** interaction_title */
-const reason = computed(
-    () => firstInteract.value?.interaction_theme || t("agriFile.interactReason")
-);
+const reason = computed(() => firstInteract.value?.interaction_theme || t("agriFile.interactReason"));
 /** 农情研判说明 */
-const assessmentDesc = computed(
-    () => firstInteract.value?.interaction_reason || t("agriFile.agriAssessmentDesc")
-);
+const assessmentDesc = computed(() => firstInteract.value?.interaction_reason || t("agriFile.agriAssessmentDesc"));
 const guideImage = computed(() => resolveGuideImage(firstInteract.value?.pic_url));
 /** stress_info.level */
 const level = computed(() => {
@@ -303,6 +279,13 @@ function mapInteractItem(raw) {
     };
 }
 
+const formatLocalDate = (date) => {
+    const y = date.getFullYear();
+    const m = String(date.getMonth() + 1).padStart(2, "0");
+    const d = String(date.getDate()).padStart(2, "0");
+    return `${y}-${m}-${d}`;
+};
+
 // ---------- 业务逻辑 ----------
 const fetchAbnormalInteract = async () => {
     const farm = getSelectedFarm();
@@ -314,9 +297,11 @@ const fetchAbnormalInteract = async () => {
         stressInfo.value = {};
         return;
     }
-    // 与 patrolPanel 调试参数保持一致;正式环境改回 farmId / zId / 当天日期
     const params = {
         crop_type: cropType,
+        // farm_id: farmId,
+        // zone_id: zId,
+        // calc_date: formatLocalDate(new Date()),
         farm_id: 321,
         zone_id: 46,
         calc_date: "2025-08-30",
@@ -494,18 +479,17 @@ onActivated(() => {
         flex: 1;
         overflow-y: auto;
         -webkit-overflow-scrolling: touch;
-        padding-bottom: 100px;
+        padding-bottom: 10px;
         box-sizing: border-box;
     }
 
     .abnormal-hero {
         position: relative;
-        padding: 86px 70px 10px 12px;
+        padding: 86px 70px 0px 12px;
         box-sizing: border-box;
         z-index: 2;
-        min-height: 250px;
-        background:
-            linear-gradient(
+        min-height: 240px;
+        background: linear-gradient(
                 180deg,
                 rgba(11, 11, 11, 0) 8.51%,
                 rgba(11, 11, 11, 0.416) 42.95%,
@@ -532,6 +516,7 @@ onActivated(() => {
         .abnormal-top {
             position: relative;
             z-index: 2;
+            padding-bottom: 40px;
         }
 
         &__share {
@@ -564,24 +549,24 @@ onActivated(() => {
             display: inline-flex;
             align-items: center;
             gap: 3px;
-            height: 22px;
-            padding: 0 8px;
-            border-radius: 4px;
+            height: 20px;
+            padding: 0 7px;
+            border-radius: 24px;
             font-size: 12px;
-            line-height: 22px;
+            line-height: 20px;
             box-sizing: border-box;
+            border: 1px solid rgba(138, 106, 46, 1);
         }
 
         &__tag--level {
-            color: #fff;
-            background: #822422;
-            border: 1px solid rgba(208, 49, 46, 0.4);
+            background: linear-gradient(90deg, #7e2321 0%, #350302 100%);
+            color: #ff7d7b;
+            border-color: rgba(201, 53, 50, 0.41);
         }
 
         &__tag--zone {
-            color: rgba(255, 255, 255, 0.85);
-            background: rgba(0, 0, 0, 0.4);
-            border: 1px solid rgba(255, 255, 255, 0.12);
+            color: #e8c27a;
+            background: #2a2418;
         }
 
         &__title {
@@ -638,6 +623,9 @@ onActivated(() => {
         font-weight: 500;
         color: #f2e9d8;
         margin-bottom: 10px;
+        &.interact-card__title {
+            font-size: 14px;
+        }
 
         .title-bar {
             width: 4px;
@@ -720,9 +708,9 @@ onActivated(() => {
 
         &__text {
             flex-shrink: 0;
-            font-size: 13px;
+            font-size: 12px;
             line-height: 18px;
-            color: rgba(255, 255, 255, 0.45);
+            color: #727272;
         }
 
         &__line {
@@ -733,6 +721,18 @@ onActivated(() => {
     }
 
     .abnormal-item {
+        padding: 1px;
+        border-radius: 12px;
+        background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 25%),
+            linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 25%);
+
+
+        &__wrap {
+            padding: 11px 13px;
+            border-radius: 12px;
+            background: linear-gradient(180deg, #1A191D 0%, #121216 100%);
+        }
+
         & + .abnormal-item {
             margin-top: 16px;
         }
@@ -740,27 +740,32 @@ onActivated(() => {
         &__title {
             display: flex;
             align-items: center;
-            gap: 8px;
-            margin-bottom: 10px;
-            font-size: 18px;
-            font-weight: 600;
-            color: #ffd489;
+            gap: 10px;
+            margin-bottom: 12px;
+            font-size: 16px;
+            font-weight: 500;
+            color: #FFD489;
         }
 
         &__icon {
-            width: 20px;
-            height: 20px;
+            width: 18px;
+            height: 23px;
             object-fit: contain;
         }
     }
 
     .interact-card {
+        padding: 10px 12px;
+        border-radius: 12px;
+        border: 1px solid rgba(255, 241, 217, 0.2);
+        background: linear-gradient(180deg, #1A191D 0%, #121216 100%);
+
         &__head {
             display: flex;
             align-items: center;
             justify-content: space-between;
             gap: 8px;
-            margin-bottom: 4px;
+            margin-bottom: 12px;
 
             .section-title {
                 margin-bottom: 0;
@@ -769,13 +774,14 @@ onActivated(() => {
 
         &__submit {
             flex-shrink: 0;
-            height: 28px;
-            padding: 0 12px;
-            border-radius: 14px;
-            border: 1px solid rgba(255, 212, 137, 0.45);
-            color: #ffd489;
+            height: 27px;
+            padding: 0 15px;
+            border-radius: 24px;
+            background: rgba(255, 212, 137, 0.1);
+            border: 1px solid rgba(255, 212, 137, 0.4);
+            color: #FFD489;
             font-size: 12px;
-            line-height: 26px;
+            line-height: 27px;
             text-align: center;
             box-sizing: border-box;
 
@@ -785,29 +791,29 @@ onActivated(() => {
         }
 
         &__question {
-            font-size: 15px;
-            font-weight: 600;
-            line-height: 22px;
-            color: #ffd489;
+            font-size: 16px;
+            font-family: "PangMenZhengDao";
+            line-height: 20px;
+            color: #FFD489;
             margin-bottom: 12px;
         }
 
         &__options {
             display: flex;
-            gap: 8px;
+            gap: 12px;
         }
 
         .interact-option {
             position: relative;
             flex: 1;
             min-width: 0;
-            min-height: 44px;
+            min-height: 41px;
             display: flex;
             align-items: center;
             justify-content: center;
-            border-radius: 10px;
+            border-radius: 8px;
             background: rgba(255, 255, 255, 0.05);
-            border: 1px solid rgba(255, 255, 255, 0.08);
+            border: 1px solid rgba(255, 255, 255, 0.12);
             box-sizing: border-box;
             cursor: pointer;
 
@@ -822,11 +828,11 @@ onActivated(() => {
             }
 
             &.selected {
-                border-color: rgba(255, 212, 137, 0.55);
-                background: rgba(255, 212, 137, 0.1);
+                border-color: rgba(255, 255, 255, 0.5);
+                background: rgba(255, 255, 255, 0.1);
 
                 .interact-option__text {
-                    color: #ffd489;
+                    color: #fff;
                 }
             }
         }
@@ -835,12 +841,21 @@ onActivated(() => {
     .guide-card {
         position: relative;
         margin-top: 12px;
+        background: rgba(75, 74, 70, 0.2);
+        border-radius: 10px;
+        padding: 10px;
 
         &__img {
             display: block;
             width: 100%;
             border-radius: 8px;
         }
+        .guide-card__img-box {
+            img {
+                display: block;
+                width: 100%;
+            }
+        }
 
         .section-title {
             gap: 6px;

+ 211 - 131
src/views/old_mini/growth_report/alert_detail.vue

@@ -3,26 +3,27 @@
         <custom-header :name="pageTitle" />
         <div class="alert-detail-body" v-loading="loading">
             <!-- 综合研判 -->
-            <div v-if="analysis.summary || analysis.crop.name" class="section-card">
-                <div class="section-card__title">综合研判</div>
-                <div v-if="analysis.summary" class="section-card__desc">{{ analysis.summary }}</div>
-
-                <div v-if="analysis.crop.name || analysis.crop.metrics.length" class="crop-panel">
-                    <div class="crop-panel__head">
-                        <img class="crop-panel__cover" :src="analysis.crop.cover" alt="" />
-                        <span class="crop-panel__name">{{ analysis.crop.name }}</span>
-                        <span class="crop-panel__tag">当前作物</span>
+            <div v-if="analysis.summary || analysis.crop.name" class="analysis-top">
+                <div class="analysis-card">
+                    <div class="analysis-card__content">
+                        <div class="section-card__title">综合研判</div>
+                        <div v-if="analysis.summary" class="section-card__desc">{{ analysis.summary }}</div>
                     </div>
-                    <div v-if="analysis.crop.metrics.length" class="crop-panel__list">
-                        <div
-                            v-for="item in analysis.crop.metrics"
-                            :key="item.label"
-                            class="crop-metric"
-                        >
-                            <img class="crop-metric__icon" :src="item.icon" alt="" />
-                            <div class="crop-metric__content">
-                                <div class="crop-metric__label">{{ item.label }}</div>
-                                <div class="crop-metric__value">{{ item.value }}</div>
+                </div>
+                <div v-if="analysis.crop.name || analysis.crop.metrics.length" class="crop-panel">
+                    <div class="crop-panel__content">
+                        <div class="crop-panel__head">
+                            <img class="crop-panel__cover" :src="analysis.crop.cover" alt="" />
+                            <span class="crop-panel__name">{{ analysis.crop.name }}</span>
+                            <span class="crop-panel__tag">当前作物</span>
+                        </div>
+                        <div v-if="analysis.crop.metrics.length" class="crop-panel__list">
+                            <div v-for="item in analysis.crop.metrics" :key="item.label" class="crop-metric">
+                                <img class="crop-metric__icon" :src="item.icon" alt="" />
+                                <div class="crop-metric__content">
+                                    <div class="crop-metric__label">{{ item.label }}</div>
+                                    <div class="crop-metric__value">{{ item.value }}</div>
+                                </div>
                             </div>
                         </div>
                     </div>
@@ -31,17 +32,15 @@
 
             <!-- 巡园结果与分析 -->
             <div v-if="patrolResults.length" class="section-card">
-                <div class="section-card__title">巡园结果与分析</div>
-                <div class="patrol-list">
-                    <div
-                        v-for="item in patrolResults"
-                        :key="item.id"
-                        class="patrol-item"
-                    >
-                        <img v-if="item.cover" class="patrol-item__cover" :src="item.cover" alt="" />
-                        <div class="patrol-item__body">
-                            <div class="patrol-item__title">{{ item.title }}</div>
-                            <div class="patrol-item__desc">{{ item.desc }}</div>
+                <div class="section-card__wrap">
+                    <div class="section-card__title">巡园结果与分析</div>
+                    <div class="patrol-list">
+                        <div v-for="item in patrolResults" :key="item.id" class="patrol-item">
+                            <img v-if="item.cover" class="patrol-item__cover" :src="item.cover" alt="" />
+                            <div class="patrol-item__body">
+                                <div class="patrol-item__title">{{ item.title }}</div>
+                                <div class="patrol-item__desc">{{ item.desc }}</div>
+                            </div>
                         </div>
                     </div>
                 </div>
@@ -49,31 +48,27 @@
 
             <!-- 诊断研判分析 -->
             <div v-if="diagnosisList.length" class="section-card">
-                <div class="section-card__title">诊断研判分析</div>
-                <div class="diag-list">
-                    <div
-                        v-for="item in diagnosisList"
-                        :key="item.id"
-                        class="diag-item"
-                    >
-                        <span v-if="item.tag" class="diag-item__tag">{{ item.tag }}</span>
-                        <div v-if="item.title" class="diag-item__title">{{ item.title }}</div>
-                        <div v-if="item.desc" class="diag-item__desc">{{ item.desc }}</div>
+                <div class="section-card__wrap">
+                    <div class="section-card__title">诊断研判分析</div>
+                    <div class="diag-list">
+                        <div v-for="item in diagnosisList" :key="item.id" class="diag-item">
+                            <span v-if="item.tag" class="diag-item__tag">{{ item.tag }}</span>
+                            <div v-if="item.title" class="diag-item__title">{{ item.title }}</div>
+                            <div v-if="item.desc" class="diag-item__desc">{{ item.desc }}</div>
+                        </div>
                     </div>
                 </div>
             </div>
 
             <!-- 农事建议 -->
             <div v-if="adviceList.length" class="section-card">
-                <div class="section-card__title">农事建议</div>
-                <div class="advice-list">
-                    <div
-                        v-for="item in adviceList"
-                        :key="item.id"
-                        class="advice-item"
-                    >
-                        <div class="advice-item__title">{{ item.title }}</div>
-                        <div class="advice-item__desc">{{ item.desc }}</div>
+                <div class="section-card__wrap">
+                    <div class="section-card__title">农事建议</div>
+                    <div class="advice-list">
+                        <div v-for="item in adviceList" :key="item.id" class="advice-item">
+                            <div class="advice-item__title">{{ item.title }}</div>
+                            <div class="advice-item__desc">{{ item.desc }}</div>
+                        </div>
                     </div>
                 </div>
             </div>
@@ -102,14 +97,10 @@ const cropCover = require("@/assets/img/home/plant.png");
 const resolveCropCover = (cropName) => resolveCropIcon(cropName, cropCover);
 
 const detailType = computed(() =>
-    String(route.query.type || "") === DETAIL_TYPE.STRESS
-        ? DETAIL_TYPE.STRESS
-        : DETAIL_TYPE.WARNING
+    String(route.query.type || "") === DETAIL_TYPE.STRESS ? DETAIL_TYPE.STRESS : DETAIL_TYPE.WARNING,
 );
 const detailTitle = ref("");
-const pageTitle = computed(
-    () => detailTitle.value || route.query.title || "具体预警/具体胁迫"
-);
+const pageTitle = computed(() => detailTitle.value || route.query.title || "具体预警/具体胁迫");
 
 const analysis = ref({
     summary: "",
@@ -242,10 +233,7 @@ const applyRecord = (record, type) => {
             id: record.id || 1,
             tag: (isStress ? record.stress_type : record.risk_type) || "",
             title: (isStress ? record.stress_name : record.risk_name) || "",
-            desc:
-                (isStress
-                    ? record.importance_desc || record.explain_simple
-                    : record.explain_simple) || "",
+            desc: (isStress ? record.importance_desc || record.explain_simple : record.explain_simple) || "",
         },
     ].filter((item) => item.title || item.desc);
 
@@ -262,8 +250,8 @@ const fetchDetail = async () => {
             ? VE_API.questionnaire.getWeatherStress
             : VE_API.questionnaire.getWeatherRisk
         : type === DETAIL_TYPE.STRESS
-          ? VE_API.questionnaire.getPointStressReport
-          : VE_API.questionnaire.getPointRiskReport;
+        ? VE_API.questionnaire.getPointStressReport
+        : VE_API.questionnaire.getPointRiskReport;
     const params = farmParams || countyParams;
     if (!params) return;
 
@@ -286,35 +274,75 @@ onMounted(() => {
 <style lang="scss" scoped>
 .alert-detail-page {
     min-height: 100vh;
-    background: #F2F5F6;
+    background: #0b0b0b;
+    color: #fff;
 }
 
 .alert-detail-body {
-    padding: 10px 10px 24px;
+    padding: 24px 12px 24px;
     box-sizing: border-box;
     overflow-y: auto;
-    height: calc(100vh - 44px);
+    height: calc(100vh - 40px);
+
+    :deep(.el-loading-mask) {
+        background-color: rgba(11, 11, 11, 0.7);
+    }
+}
+
+.analysis-top {
+}
+
+.analysis-card {
+    padding: 1px;
+    border-radius: 12px;
+    background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 72.15%);
+
+    &__content {
+        padding: 11px 13px;
+        border-radius: 12px;
+        background: linear-gradient(180deg, #1a191d 0%, #121216 100%);
+        box-sizing: border-box;
+    }
 }
 
 .section-card {
-    margin-bottom: 12px;
-    padding: 10px;
-    border-radius: 10px;
-    background: #fff;
+    margin-bottom: 16px;
+    padding: 1px;
+    border-radius: 12px;
+    background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 72.15%);
     box-sizing: border-box;
 
+    .section-card__wrap {
+        padding: 12px;
+        border-radius: 12px;
+        background: linear-gradient(180deg, #1A191D 0%, #121216 100%);
+        box-sizing: border-box;
+    }
+
     &__title {
+        display: flex;
+        align-items: center;
+        gap: 8px;
         font-size: 16px;
         font-weight: 500;
         line-height: 24px;
-        color: #000;
+        color: #F2E9D8;
+
+        &::before {
+            content: "";
+            width: 4px;
+            height: 16px;
+            border-radius: 2px;
+            background: #ffd489;
+            flex-shrink: 0;
+        }
     }
 
     &__desc {
         margin-top: 10px;
         font-size: 14px;
         line-height: 22px;
-        color: rgba(6, 6, 6, 0.5);
+        color: rgba(255, 255, 255, 0.55);
         word-break: break-all;
         text-align: justify;
         font-weight: 350;
@@ -324,52 +352,60 @@ onMounted(() => {
 
 .crop-panel {
     margin-top: 12px;
-    padding: 10px;
-    border-radius: 10px;
-    background: #E7F1FD;
+    border-radius: 12px;
+    padding: 1px;
     box-sizing: border-box;
+    background: linear-gradient(180deg, rgba(255, 212, 137, 0.4) 0%, rgba(255, 212, 137, 0) 72.15%);
+
+    .crop-panel__content {
+        padding: 10px 12px;
+        border-radius: 12px;
+        background: rgba(26, 24, 20, 1);
+    }
 
     &__head {
         display: flex;
         align-items: center;
-        gap: 6px;
-        margin-bottom: 10px;
+        gap: 8px;
+        padding-bottom: 14px;
+        border-bottom: 1px solid rgba(255, 255, 255, 0.06);
     }
 
     &__cover {
-        width: 24px;
-        height: 24px;
+        width: 40x;
+        height: 40px;
         border-radius: 50%;
         object-fit: cover;
         flex-shrink: 0;
-        background: #fff;
+        border: 1px solid rgba(255, 212, 137, 0.5);
+        background: rgba(255, 255, 255, 0.08);
     }
 
     &__name {
-        font-size: 16px;
-        font-weight: 500;
-        color: #2199F8;
+        font-size: 18px;
+        color: #fff;
     }
 
     &__tag {
-        padding: 0 5px;
-        border-radius: 2px;
-        background: #2199f8;
-        backdrop-filter: blur(4px);
-        color: #fff;
+        padding: 0 6px;
+        border-radius: 3px;
+        background: rgba(255, 212, 137, 0.1);
+        border: 1px solid rgba(255, 212, 137, 0.16);
+        color: #ffd489;
         font-size: 12px;
-        height: 18px;
-        line-height: 18px;
+        height: 19px;
+        line-height: 19px;
         flex-shrink: 0;
+        box-sizing: border-box;
     }
 
     &__list {
         display: flex;
         flex-direction: column;
-        gap: 10px;
-        background: #fff;
-        padding: 10px;
-        border-radius: 10px;
+        gap: 0;
+        background: transparent;
+        padding: 0;
+        border-radius: 0;
         box-sizing: border-box;
     }
 }
@@ -377,36 +413,45 @@ onMounted(() => {
 .crop-metric {
     display: flex;
     align-items: flex-start;
-    gap: 6px;
+    gap: 8px;
+    padding-top: 14px;
+
+    // & + & {
+    //     border-top: 1px solid rgba(255, 255, 255, 0.08);
+    // }
 
     &__icon {
         width: 16px;
         height: 16px;
         flex-shrink: 0;
         object-fit: contain;
-        filter: grayscale(1);
+        filter: brightness(0) invert(0.7);
         flex: none;
-        margin-top: 2px;
+        margin-top: 3px;
+        opacity: 0.85;
     }
 
     &__content {
-        display: flex;
-        align-items: flex-start;
-        gap: 6px;
+        // display: flex;
+        // align-items: flex-start;
+        // gap: 8px;
         flex: 1;
         min-width: 0;
         font-size: 14px;
         line-height: 22px;
+        padding-bottom: 10px;
         word-break: break-all;
+        border-bottom: 1px solid rgba(255, 255, 255, 0.06);
     }
 
     &__label {
-        color: #9F9F9F;
+        color: rgba(255, 255, 255, 0.6);
         flex: none;
     }
 
     &__value {
-        color: #1a1a1a;
+        padding-top: 3px;
+        color: rgba(255, 255, 255, 0.9);
     }
 }
 
@@ -414,25 +459,26 @@ onMounted(() => {
     margin-top: 12px;
     display: flex;
     flex-direction: column;
-    gap: 14px;
+    gap: 10px;
 }
 
 .patrol-item {
     display: flex;
     align-items: flex-start;
     gap: 10px;
-    background: #F7F8FA;
+    background: rgba(255, 255, 255, 0.04);
     padding: 10px;
-    border-radius: 4px;
+    border-radius: 10px;
+    border: 1px solid rgba(255, 255, 255, 0.06);
     box-sizing: border-box;
 
     &__cover {
         width: 100px;
         height: 86px;
-        border-radius: 5px;
+        border-radius: 6px;
         object-fit: cover;
         flex-shrink: 0;
-        background: #f5f5f5;
+        background: rgba(255, 255, 255, 0.06);
     }
 
     &__body {
@@ -444,77 +490,111 @@ onMounted(() => {
         font-size: 14px;
         font-weight: 500;
         line-height: 22px;
-        color: #1D2129;
+        color: #fff;
     }
 
     &__desc {
         margin-top: 4px;
         font-size: 12px;
         line-height: 20px;
-        color: #4E5969;
+        color: rgba(255, 255, 255, 0.5);
         word-break: break-all;
         text-align: justify;
     }
 }
 
-.diag-list,
-.advice-list {
-    margin-top: 10px;
+.diag-list {
+    margin-top: 12px;
     display: flex;
     flex-direction: column;
     gap: 10px;
 }
 
-.diag-item,
-.advice-item {
-    padding: 10px;
-    border-radius: 4px;
-    background: #F7F8FA;
+.diag-item {
+    padding: 12px;
+    border-radius: 10px;
+    background: rgba(255, 255, 255, 0.05);
+    border: 1px solid rgba(255, 255, 255, 0.06);
     box-sizing: border-box;
-}
 
-.diag-item {
     &__tag {
         display: inline-block;
         padding: 0 8px;
         height: 22px;
-        line-height: 22px;
-        border-radius: 2px;
-        background: #2199f8;
-        color: #fff;
+        line-height: 20px;
+        border-radius: 3px;
+        background: rgba(255, 212, 137, 0.08);
+        border: 1px solid rgba(255, 212, 137, 0.5);
+        color: #ffd489;
         font-size: 12px;
+        box-sizing: border-box;
     }
 
     &__title {
-        margin-top: 4px;
-        font-size: 14px;
+        margin-top: 8px;
+        font-size: 15px;
         font-weight: 500;
         line-height: 22px;
-        color: #1D2129;
+        color: #fff;
     }
 
     &__desc {
-        margin-top: 4px;
-        font-size: 12px;
+        margin-top: 6px;
+        font-size: 13px;
         line-height: 20px;
-        color: #4E5969;
+        color: rgba(255, 255, 255, 0.5);
         word-break: break-all;
     }
 }
 
+.advice-list {
+    margin-top: 12px;
+    display: flex;
+    flex-direction: column;
+    gap: 0;
+    padding: 2px 4px;
+    border-radius: 10px;
+    background: rgba(255, 255, 255, 0.03);
+    box-sizing: border-box;
+    counter-reset: advice-idx;
+}
+
 .advice-item {
+    padding: 14px 8px;
+    background: transparent;
+    border-radius: 0;
+    box-sizing: border-box;
+    counter-increment: advice-idx;
+
+    & + & {
+        border-top: 1px solid rgba(255, 255, 255, 0.08);
+    }
+
     &__title {
+        display: flex;
+        align-items: flex-start;
+        gap: 8px;
         font-size: 14px;
-        font-weight: 500;
         line-height: 22px;
-        color: #1D2129;
+        color: #fff;
+
+        &::before {
+            content: counter(advice-idx, decimal-leading-zero);
+            color: #ffd489;
+            font-size: 15px;
+            font-weight: 600;
+            line-height: 22px;
+            flex-shrink: 0;
+            font-variant-numeric: tabular-nums;
+        }
     }
 
     &__desc {
-        margin-top: 4px;
+        margin-top: 6px;
+        margin-left: 30px;
         font-size: 12px;
         line-height: 20px;
-        color: #4E5969;
+        color: rgba(255, 255, 255, 0.5);
         word-break: break-all;
         white-space: pre-line;
     }

+ 8 - 4
src/views/old_mini/growth_report/components/CropAlertPanel.vue

@@ -79,6 +79,7 @@
                                 v-for="(item, index) in alertCards"
                                 :key="index"
                                 class="alert-card"
+                                @click.stop="handleViewDetail(item)"
                             >
                                 <div class="alert-card__header">
                                     <div class="alert-card__category">
@@ -98,8 +99,8 @@
                                 <div class="alert-card__advice">{{ item.content || "—" }}</div>
                                 <div class="alert-card__footer">
                                     <span class="alert-card__time">{{ item.timeText }}</span>
-                                    <span class="alert-card__link" @click="handleViewDetail(item)">
-                                        详情 &gt;
+                                    <span class="alert-card__link" @click.stop="handleViewDetail(item)">
+                                        详情 <el-icon size="10"><ArrowRightBold /></el-icon>
                                     </span>
                                 </div>
                             </div>
@@ -993,10 +994,13 @@ defineExpose({ refreshAlerts: fetchAlertCards, refreshZones: fetchZones, reloadF
         }
 
         &__link {
+            display: flex;
+            align-items: center;
+            gap: 2px;
             flex-shrink: 0;
-            font-size: 11px;
+            font-size: 12px;
             line-height: 16px;
-            color: rgba(255, 255, 255, 0.45);
+            color: rgba(255, 255, 255, 0.5);
         }
     }
 

+ 128 - 105
src/views/old_mini/growth_report/index.vue

@@ -12,40 +12,8 @@
             </div>
         </div>
 
-        <!-- 浮窗:长势互动 -->
-        <div v-if="showInteractCard" class="interact-float">
-            <div class="interact-card">
-                <div class="interact-card__head">
-                    <div class="interact-card__tab">
-                        <img class="interact-card__star" src="@/assets/img/agricultural/start.png" alt="" />
-                        <span>长势互动</span>
-                    </div>
-                    <el-icon class="interact-card__close" @click="showInteractCard = false">
-                        <Close />
-                    </el-icon>
-                </div>
-                <div class="interact-card__qa">
-                    <div class="interact-card__question">{{ interactQuestionText }}</div>
-                    <div class="interact-card__options">
-                        <div
-                            v-for="item in interactOptions"
-                            :key="item.id"
-                            class="interact-option"
-                            :class="{
-                                selected: selectedOptionId === item.id,
-                                disabled: interactSubmitting,
-                            }"
-                            @click="handleInteractOptionClick(item)"
-                        >
-                            <span class="interact-option__text">{{ item.name }}</span>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-
         <!-- 左上角:位置切换 -->
-        <div v-if="!showInteractCard" class="location-bar">
+        <div class="location-bar">
             <el-icon class="location-bar__icon">
                 <LocationFilled />
             </el-icon>
@@ -53,36 +21,73 @@
             <span v-if="hasSelectedFarm()" class="location-bar__action" @click="handleSwitchFarm">切换农场</span>
         </div>
 
-        <!-- 左侧:气象底图图层菜单(有农场 getHomeMapCalc / 无农场 getHomeMapCalcByCounty) -->
-        <div v-if="stressMenuItems.length" class="side-menu side-menu--left">
-            <div v-for="item in stressMenuItems" :key="item.key" class="side-menu__item"
-                :class="{ active: activeMenuKey === item.key }" @click="handleSelectMenu(item.key)">
-                <img class="side-menu__icon" :src="base_img_url3 + item.icon_path" alt="" />
-                <div class="side-menu__text">
-                    <span>{{ item.line1 }}</span>
-                    <span>{{ item.line2 }}</span>
+        <div class="growth-top">
+            <!-- 浮窗:长势互动 -->
+            <div v-if="!showInteractCard" class="interact-float">
+                <div class="interact-card">
+                    <el-icon class="interact-card__close" @click="showInteractCard = true">
+                        <Close />
+                    </el-icon>
+                    <div class="interact-card__qa">
+                        <div class="interact-card__question">
+                            <div class="interact-card__question-icon">
+                                <img class="interact-card__question-icon-img" :src="periodIcon" alt="">
+                            </div>
+                            <span>{{ interactQuestionText }}</span>
+                        </div>
+                        <div class="interact-card__options">
+                            <div
+                                v-for="item in interactOptions"
+                                :key="item.id"
+                                class="interact-option"
+                                :class="{
+                                    selected: selectedOptionId === item.id,
+                                    disabled: interactSubmitting,
+                                }"
+                                @click="handleInteractOptionClick(item)"
+                            >
+                                <span class="interact-option__text">{{ item.name }}</span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="growth-top__content">
+                <!-- 左侧:气象底图图层菜单(有农场 getHomeMapCalc / 无农场 getHomeMapCalcByCounty) -->
+                <div v-if="stressMenuItems.length" class="side-menu side-menu--left">
+                    <div v-for="item in stressMenuItems" :key="item.key" class="side-menu__item"
+                        :class="{ active: activeMenuKey === item.key }" @click="handleSelectMenu(item.key)">
+                        <img class="side-menu__icon" :src="base_img_url3 + item.icon_path" alt="" />
+                        <div class="side-menu__text">
+                            <span>{{ item.line1 }}</span>
+                            <span>{{ item.line2 }}</span>
+                        </div>
+                    </div>
+                </div>
+                
+                <div class="invite-group">
+                    <div class="invite-btn">
+                        <img class="current-icon" src="@/assets/img/home/current.png" alt="">
+                    </div>
+                    <div class="invite-btn" @click="handleInvite('service')">
+                        <img class="invite-icon" src="@/assets/img/home/user-icon.png" alt="">
+                        邀请农服
+                    </div>
+                    <div class="invite-btn" @click="handleInvite('farmer')">
+                        <img class="invite-icon" src="@/assets/img/home/user-icon.png" alt="">
+                        邀请农户
+                    </div>
                 </div>
             </div>
+
         </div>
 
+
         <div v-if="activeLegendUrl" class="map-legend map-legend--image" :style="{ bottom: `${inviteBottom + 10}px` }">
             <img class="map-legend__img" :src="activeLegendUrl" alt="" />
         </div>
 
-        <div class="invite-group">
-            <div class="invite-btn">
-                <img class="current-icon" src="@/assets/img/home/current.png" alt="">
-            </div>
-            <div class="invite-btn" @click="handleInvite('service')">
-                <img class="invite-icon" src="@/assets/img/home/user-icon.png" alt="">
-                邀请农服
-            </div>
-            <div class="invite-btn" @click="handleInvite('farmer')">
-                <img class="invite-icon" src="@/assets/img/home/user-icon.png" alt="">
-                邀请农户
-            </div>
-        </div>
-
         <crop-alert-panel :crop-name="currentCropName" :farm-id="selectedFarmId" :county-code="countyCode"
             @zone-change="handleZoneChange" @height-change="handlePanelHeightChange" />
     </div>
@@ -121,6 +126,9 @@ const MAP_POINT_STORAGE_KEY = "GROWTH_REPORT_MAP_POINT";
 const COUNTY_CODE_STORAGE_KEY = "GROWTH_REPORT_COUNTY_CODE";
 
 const menuIcon = require("@/assets/img/common/farm-active.png");
+const periodIcon = require("@/assets/img/agricultural/period.png");
+const lightningIcon = require("@/assets/img/agricultural/lightning.png");
+const soilIcon = require("@/assets/img/agricultural/soil.png");
 
 const store = useStore();
 const tabBarHeight = computed(() => store.state.home.tabBarHeight);
@@ -290,8 +298,8 @@ const goAddZone = (type) => {
 };
 
 const showInteractCard = ref(false);
-const interactQuestionText = ref("");
-const interactOptions = ref([]);
+const interactQuestionText = ref("物候问题物候问题");
+const interactOptions = ref([{id: 1, name: "未到"}, {id: 2, name: "顺利进入"}, {id: 3, name: "已过"}]);
 const selectedOptionId = ref(null);
 const interactSubmitting = ref(false);
 /** getOuterRecords 返回的 records */
@@ -592,7 +600,7 @@ const handleZoneChange = (zoneId) => {
     panelZoneId.value = zoneId != null && zoneId !== "" ? zoneId : null;
     fetchHomeMapCalc();
     fetchFarmRangeStatus();
-    fetchInteractTask();
+    // fetchInteractTask();
 };
 
 async function getLocationName(point = currentMapPoint.value) {
@@ -869,7 +877,7 @@ onActivated(() => {
     if (!applied) syncMapFromSelectedFarm();
     initMap();
     fetchFarmRangeStatus();
-    fetchInteractTask();
+    // fetchInteractTask();
     tryOpenInviteEntryPopup();
 });
 </script>
@@ -882,24 +890,24 @@ onActivated(() => {
     box-sizing: border-box;
 
     .interact-float {
-        position: fixed;
-        top: 10px;
-        left: 10px;
-        right: 10px;
-        z-index: 30;
+        margin-bottom: 6px;
         pointer-events: none;
+        padding: 1px;
+        background:  linear-gradient(180deg, rgba(255, 255, 255, 0.25) 0%, rgba(153, 153, 153, 0.25) 100%);
+        border-radius: 14px;
+        backdrop-filter: blur(4px);
 
         .interact-card {
+            position: relative;
             pointer-events: auto;
             overflow: hidden;
-            border-radius: 12px;
-            background: #fff;
-            box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
+            border-radius: 14px;
+            padding: 10px;
+            background: linear-gradient(180deg, rgba(26, 25, 29, 0.6) 0%, rgba(18, 18, 22, 0.6) 100%);
         }
 
         .interact-card__head {
             position: relative;
-            background: linear-gradient(180deg, #e5f4ff 0%, #ffffff 72%);
         }
 
         .interact-card__tab {
@@ -910,8 +918,6 @@ onActivated(() => {
             padding: 0 32px 10px 8px;
             color: #fff;
             font-size: 16px;
-            font-family: "PangMenZhengDao";
-            background: url("@/assets/img/agricultural/title-bg.png") no-repeat center / 100% 100%;
 
             span {
                 margin-top: -3px;
@@ -925,24 +931,35 @@ onActivated(() => {
 
         .interact-card__close {
             position: absolute;
-            top: 8px;
+            top: 12px;
             right: 10px;
             font-size: 16px;
-            color: #9c9c9c;
+            color: rgba(255, 255, 255, 0.5);
             cursor: pointer;
         }
 
         .interact-card__qa {
-            margin: 0 10px 10px;
-            padding: 10px;
-            border-radius: 8px;
-            background: rgba(33, 153, 248, 0.1);
         }
 
         .interact-card__question {
-            font-size: 14px;
-            font-weight: 500;
-            color: #333;
+            font-size: 16px;
+            color: #fff;
+            display: flex;
+            align-items: center;
+            gap: 12px;
+            .interact-card__question-icon {
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                width: 31px;
+                height: 31px;
+                background: rgba(255, 255, 255, 0.05);
+                border: 1px solid rgba(255, 255, 255, 0.12);
+                border-radius: 8px;
+                .interact-card__question-icon-img {
+                    width: 13px;
+                }
+            }
         }
 
         .interact-card__options {
@@ -955,11 +972,11 @@ onActivated(() => {
             position: relative;
             flex: 1;
             min-width: 0;
-            height: 36px;
-            line-height: 36px;
+            height: 41px;
+            line-height: 41px;
             border-radius: 6px;
-            background: #fff;
-            border: 1px solid transparent;
+            background: rgba(255, 255, 255, 0.05);
+            border: 1px solid rgba(255, 255, 255, 0.12);
             text-align: center;
             box-sizing: border-box;
             cursor: pointer;
@@ -971,25 +988,26 @@ onActivated(() => {
                 text-overflow: ellipsis;
                 white-space: nowrap;
                 font-size: 14px;
-                color: #666;
+                color: rgba(255, 255, 255, 0.7);
             }
 
             &.selected {
-                border-color: #2199f8;
+                border-color: rgba(255, 255, 255, 0.5);
+                background: rgba(255, 255, 255, 0.1);
 
                 .interact-option__text {
-                    color: #2199f8;
+                    color: #fff;
                 }
 
-                &::after {
-                    content: "";
-                    position: absolute;
-                    top: -1px;
-                    right: -1px;
-                    width: 18px;
-                    height: 14px;
-                    background: url("@/assets/img/home/checked-bg-top.png") no-repeat bottom right / 18px 13px;
-                }
+                // &::after {
+                //     content: "";
+                //     position: absolute;
+                //     top: -1px;
+                //     right: -1px;
+                //     width: 18px;
+                //     height: 14px;
+                //     background: url("@/assets/img/home/checked-bg-top.png") no-repeat bottom right / 18px 13px;
+                // }
             }
 
             &.disabled {
@@ -1032,25 +1050,34 @@ onActivated(() => {
         }
     }
 
-    .side-menu {
+    .growth-top {
+        width: 100%;
         position: fixed;
         top: 52px;
         z-index: 15;
+        pointer-events: none;
+        padding: 0 12px;
+        box-sizing: border-box;
+
+        .growth-top__content {
+            display: flex;
+            align-items: flex-start;
+            justify-content: space-between;
+        }
+    }
+
+    .side-menu {
         display: flex;
         flex-direction: column;
         align-items: center;
         gap: 12px;
         padding: 4px;
         border-radius: 10px;
-        // background: rgba(20, 20, 22, 0.8);
+        pointer-events: auto;
         background: #1b1b1d;
         box-sizing: border-box;
         border: 1px solid rgba(255, 255, 255, 0.12);
 
-        &--left {
-            left: 10px;
-        }
-
         &__item {
             display: flex;
             flex-direction: column;
@@ -1092,10 +1119,6 @@ onActivated(() => {
 
 
     .invite-group {
-        position: fixed;
-        top: 52px;
-        right: 16px;
-        z-index: 20;
         pointer-events: none;
 
         .invite-btn {