소스 검색

fix: 对接胁迫

lxf 2 주 전
부모
커밋
9a57666e96

+ 1 - 1
src/components/popup/diagnosisReportPopup.vue

@@ -88,7 +88,7 @@ onMounted(() => {
 });
 
 onActivated(() => {
-    console.log("rerereonActivated");
+    checkShouldShow();
 });
 
 defineExpose({

+ 3 - 3
src/views/old_mini/agri_file/pages/growthTrack.vue

@@ -81,9 +81,9 @@
                         <div class="situation-card__assess-title">{{ t("agriFile.agriAssessment") }}</div>
                         <div class="situation-card__assess-desc">{{ item.interaction_reason }}</div>
                     </div>
-                    <div class="situation-card__guide">
+                    <div class="situation-card__guide" v-if="item.guideImg">
                         <div class="guide-title">{{ t("agriFile.patrolGuide") }}</div>
-                        <div v-if="item.guideImg" class="situation-card__guide-box">
+                        <div class="situation-card__guide-box">
                             <photo-provider :photo-closable="true">
                                 <photo-consumer :src="item.guideImg">
                                     <img :src="item.guideImg" alt="" />
@@ -191,7 +191,7 @@ function readEntryFarmData() {
 const interactImg = ref("");
 
 function resolveGuideImg(item) {
-    const raw = item?.interact_pic_url || item?.pic_url || item?.image_url || item?.guide_img || "";
+    const raw = item?.url || "";
     if (!raw || typeof raw !== "string") return "";
     if (/^https?:\/\//i.test(raw) || raw.startsWith("data:")) return raw;
     return `${base_img_url2}${raw}`;

+ 151 - 36
src/views/old_mini/growth_report/alert_detail.vue

@@ -1,7 +1,11 @@
 <template>
     <div class="alert-detail-page">
         <custom-header :name="pageTitle" />
-        <div class="alert-detail-body" v-loading="loading">
+        <div
+            class="alert-detail-body"
+            :class="{ 'alert-detail-body--with-bar': detailType === 'stress' }"
+            v-loading="loading"
+        >
             <!-- 综合研判 -->
             <div class="section-card">
                 <div class="section-card__title">综合研判</div>
@@ -9,7 +13,7 @@
 
                 <div class="crop-panel">
                     <div class="crop-panel__head">
-                        <img class="crop-panel__cover" :src="analysis.crop.cover" alt="" />
+                        <!-- <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>
@@ -29,10 +33,11 @@
                 </div>
             </div>
 
-            <!-- 农事建议 -->
-            <div class="section-card" v-if="adviceList.length">
-                <div class="section-card__title">农事建议</div>
-                <div class="advice-list">
+            <!-- 农事建议(风险) / 巡园重要性(胁迫) -->
+            <div class="section-card" v-if="showBottomSection">
+                <div class="section-card__title">{{ bottomSectionTitle }}</div>
+                <div v-if="importanceDesc" class="section-card__desc">{{ importanceDesc }}</div>
+                <div v-else class="advice-list">
                     <div
                         v-for="item in adviceList"
                         :key="item.id"
@@ -44,18 +49,28 @@
                 </div>
             </div>
         </div>
+
+        <!-- 当下胁迫:底部巡园引导 -->
+        <div v-if="detailType === 'stress'" class="stress-patrol-bar">
+            <div class="stress-patrol-bar__icon">!</div>
+            <div class="stress-patrol-bar__text">当前气象胁迫风险较高,建议巡园诊断异常情况</div>
+            <div class="stress-patrol-bar__btn" @click="handleGoPatrol">巡园要点</div>
+        </div>
     </div>
 </template>
 
 <script setup>
 import { computed, onActivated, onMounted, ref } from "vue";
-import { useRoute } from "vue-router";
+import { useRoute, useRouter } from "vue-router";
 import customHeader from "@/components/customHeader.vue";
 
 const route = useRoute();
+const router = useRouter();
 const ENTRY_FARM_DATA_KEY = "ENTRY_FARM_DATA";
 
 const pageTitle = computed(() => route.query.title || "预警详情");
+/** risk:气象风险;stress:当下胁迫 */
+const detailType = computed(() => String(route.query.detailType || "risk"));
 
 const phenologyIcon = require("@/assets/img/common/header-icon-3.png");
 const weatherIcon = require("@/assets/img/common/header-icon-1.png");
@@ -78,8 +93,17 @@ const analysis = ref({
     },
 });
 
-/** 农事建议:farmwork_info */
+/** 农事建议:farmwork_info(risk) */
 const adviceList = ref([]);
+/** 巡园重要性:importance_desc(stress) */
+const importanceDesc = ref("");
+
+const bottomSectionTitle = computed(() =>
+    detailType.value === "stress" ? "巡园重要性" : "农事建议"
+);
+const showBottomSection = computed(() =>
+    detailType.value === "stress" ? !!importanceDesc.value : adviceList.value.length > 0
+);
 
 function readEntryFarmData() {
     try {
@@ -100,6 +124,14 @@ function resolveUserTel() {
     }
 }
 
+function buildMetrics({ phenophaseDesc, middleLabel, middleValue, soilDesc }) {
+    return [
+        { label: "当前物候", value: phenophaseDesc || "", icon: phenologyIcon },
+        { label: middleLabel, value: middleValue || "", icon: weatherIcon },
+        { label: "土壤类型", value: soilDesc || "", icon: soilIcon },
+    ];
+}
+
 function applyRiskReport(data) {
     if (!data || typeof data !== "object") return;
     const entry = readEntryFarmData();
@@ -108,26 +140,16 @@ function applyRiskReport(data) {
         crop: {
             name: data.crop_name || entry?.crop || "",
             cover: cropCover,
-            metrics: [
-                {
-                    label: "当前物候",
-                    value: data.phenophase_desc || "",
-                    icon: phenologyIcon,
-                },
-                {
-                    label: "气象预警",
-                    value: data.risk_desc || "",
-                    icon: weatherIcon,
-                },
-                {
-                    label: "土壤类型",
-                    value: data.soil_desc || "",
-                    icon: soilIcon,
-                },
-            ],
+            metrics: buildMetrics({
+                phenophaseDesc: data.phenophase_desc,
+                middleLabel: "气象预警",
+                middleValue: data.risk_desc,
+                soilDesc: data.soil_desc,
+            }),
         },
     };
 
+    importanceDesc.value = "";
     const rawWorks = data.farmwork_info;
     let works = [];
     if (Array.isArray(rawWorks)) {
@@ -147,18 +169,49 @@ function applyRiskReport(data) {
     }));
 }
 
-/** 预警详情:risk_report */
-async function fetchRiskReportDetail() {
+function applyStressReport(data) {
+    if (!data || typeof data !== "object") return;
+    const entry = readEntryFarmData();
+    analysis.value = {
+        summary: data.interact_explain || "",
+        crop: {
+            name: data.crop_name || entry?.crop || "",
+            cover: cropCover,
+            metrics: buildMetrics({
+                phenophaseDesc: data.phenophase_desc,
+                middleLabel: "当下胁迫",
+                middleValue: data.stress_desc,
+                soilDesc: data.soil_desc,
+            }),
+        },
+    };
+    adviceList.value = [];
+    importanceDesc.value = data.importance_desc || "";
+}
+
+async function requestReport(apiFn) {
     // TODO: 接口有正式数据后改回 resolveUserTel()
-    const tel = "13232323233";
-    if (!tel) return;
+    const tel = resolveUserTel();
+    if (!tel) return null;
+    const raw = await apiFn({ tel });
+    const res = Array.isArray(raw) ? raw[0] : raw;
+    if (Number(res?.code) !== 200 || !res.data) return null;
+    return Array.isArray(res.data) ? res.data[0] : res.data;
+}
+
+/** 按 detailType 拉取详情:risk → risk_report;stress → stress_report */
+async function fetchAlertDetail() {
     loading.value = true;
+    adviceList.value = [];
+    importanceDesc.value = "";
     try {
-        const raw = await VE_API.questionnaire.riskReport({ tel });
-        const res = Array.isArray(raw) ? raw[0] : raw;
-        if (Number(res?.code) !== 200 || !res.data) return;
-        const data = Array.isArray(res.data) ? res.data[0] : res.data;
-        applyRiskReport(data);
+        if (detailType.value === "stress") {
+            const data = await requestReport(VE_API.questionnaire.stressReport);
+            if (data) applyStressReport(data);
+            return;
+        }
+        const data = await requestReport(VE_API.questionnaire.riskReport);
+        if (data) applyRiskReport(data);
     } catch {
         // ignore
     } finally {
@@ -166,8 +219,18 @@ async function fetchRiskReportDetail() {
     }
 }
 
-onMounted(fetchRiskReportDetail);
-onActivated(fetchRiskReportDetail);
+onMounted(fetchAlertDetail);
+onActivated(fetchAlertDetail);
+
+function handleGoPatrol() {
+    router.push({
+        path: "/growth_track",
+        query: {
+            type: "abnormal",
+            pageName: "异常态势巡园",
+        },
+    });
+}
 </script>
 
 <style lang="scss" scoped>
@@ -181,6 +244,58 @@ onActivated(fetchRiskReportDetail);
     box-sizing: border-box;
     overflow-y: auto;
     height: calc(100vh - 44px);
+
+    &--with-bar {
+        padding-bottom: 88px;
+    }
+}
+
+.stress-patrol-bar {
+    position: fixed;
+    left: 10px;
+    right: 10px;
+    bottom: calc(32px + env(safe-area-inset-bottom));
+    z-index: 20;
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    padding: 10px 10px 10px 12px;
+    border-radius: 12px;
+    background: linear-gradient(90deg, #fff7f0 0%, #ffffff 100%);
+    box-shadow: 0 4px 16px rgba(255, 122, 48, 0.18);
+    box-sizing: border-box;
+
+    &__icon {
+        flex: none;
+        width: 22px;
+        height: 22px;
+        border-radius: 50%;
+        background: #ff7a30;
+        color: #fff;
+        font-size: 14px;
+        font-weight: 700;
+        line-height: 22px;
+        text-align: center;
+    }
+
+    &__text {
+        flex: 1;
+        min-width: 0;
+        color: #ff7a30;
+        font-size: 13px;
+        line-height: 18px;
+    }
+
+    &__btn {
+        flex: none;
+        padding: 6px 12px;
+        border-radius: 20px;
+        background: #ff7a30;
+        color: #fff;
+        font-size: 13px;
+        line-height: 18px;
+        white-space: nowrap;
+    }
 }
 
 .section-card {

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

@@ -270,15 +270,17 @@ watch(
 const alertCards = computed(() => [
     {
         id: "warning",
-        title: `未来预警: ${props.weatherRisk || "具体预警"}`,
+        detailType: 'risk',
+        title: `未来预警: ${props.weatherRisk || "预警"}`,
         icon: weatherIcon,
         content: props.weatherRiskExplain || "",
         patrolTip: "",
     },
     {
         id: 2,
+        detailType: 'stress',
         type: "abnormal",
-        title: `当下胁迫: ${props.weatherStress || "某某胁迫"}`,
+        title: `当下胁迫: ${props.weatherStress || "胁迫"}`,
         icon: weatherIcon,
         content: props.weatherStressExplain || "",
         patrolTip: "异常态势巡园要点",
@@ -293,8 +295,8 @@ const handlePatrolTip = (item) => {
     router.push({
         path: "/growth_track",
         query: {
-            id: item.id,
-            type: item.type || "growth",
+            type: "abnormal",
+            pageName: t("agriFile.patrolAbnormalTitle"),
         },
     });
 };

+ 1 - 0
src/views/old_mini/growth_report/index.vue

@@ -438,6 +438,7 @@ const handleViewDetail = (item) => {
         path: "/alert_detail",
         query: {
             title: item?.title || "具体预警",
+            detailType: item?.detailType || ''
         },
     });
 };