Browse Source

fix: 长势报告

lxf 5 days ago
parent
commit
e25bc00bab

+ 17 - 0
src/api/modules/farm_v3.js

@@ -0,0 +1,17 @@
+const config = require("../config")
+const url = config.base_dev_url + "v3/farm/"
+
+module.exports = {
+    phenologyInitOrConfirmStatus: {
+        url: url + "phenologyInitOrConfirmStatus",
+        type: "get",
+    },
+    initFarmData: {
+        url: url + "initFarmData",
+        type: "post",
+    },
+    confirmReproductivePhenology: {
+        url: url + "confirmReproductivePhenology",
+        type: "post",
+    },
+}

BIN
src/assets/img/home/fake.png


BIN
src/assets/img/home/lock-blue.png


BIN
src/assets/img/home/title-bg-warning.png


+ 7 - 1
src/components/popup/tipPopup.vue

@@ -20,7 +20,10 @@
         <template v-else-if="type === 'success'">
             <img class="tip-icon success-icon" src="@/assets/img/home/right.png" alt="" />
             <slot name="default"></slot>
-            <div class="tip-text success-text" :class="{pmzd:font}">{{ text }} <span class="highlight-text">{{ highlightText }}</span></div>
+            <div class="tip-text success-text" :class="{pmzd:font}">
+                {{ text }} <span class="highlight-text">{{ highlightText }}</span>
+                <div class="text2">{{ text2 }}</div>
+            </div>
         </template>
         <template v-else>
             <img class="tip-icon success-icon" src="@/assets/img/home/create-farm-icon.png" alt="" />
@@ -166,6 +169,9 @@ const handleClosed = () => {
         &.pmzd{
             font-family: 'PangMenZhengDao';
         }
+        .text2 {
+            padding-top: 4px;
+        }
     }
     .tip-btn {
         width: 100%;

+ 4 - 0
src/components/weatherInfo.vue

@@ -154,6 +154,7 @@ async function setFarmByGardenId(gardenIdValue) {
                     resolve(false);
                 }
             } else {
+                farmList.value = [{id: 1, name: '示范农场', defaultOption: false, wkt: localStorage.getItem('MINI_USER_LOCATION_POINT')}];
                 resolve(false);
             }
         }).catch(() => {
@@ -216,6 +217,9 @@ function getFarmListWithoutGardenId() {
         farmList.value = fullData || [];
         if (fullData && fullData.length > 0) {
             selectFarmFromList(fullData);
+        } else {
+            farmList.value = [{id: 1, name: '示范农场', defaultOption: false, wkt: localStorage.getItem('MINI_USER_LOCATION_POINT')}];
+            selectFarmFromList(farmList.value);
         }
     })
 }

+ 7 - 0
src/router/globalRoutes.js

@@ -480,4 +480,11 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/monitor/subPages/darwArea.vue"),
     },
+    // 农情互动
+    {
+        path: "/interaction",
+        name: "Interaction",
+        meta: { keepAlive: true },
+        component: () => import("@/views/old_mini/interaction/index.vue"),
+    },
 ];

+ 1 - 1
src/views/old_mini/dev_login.vue

@@ -16,7 +16,7 @@ let userId = route.query.userId;
 
 onMounted(async () => {
     const token = route.query.token
-    let targetUrl = route.query.targetUrl ? route.query.targetUrl : '/home';
+    let targetUrl = route.query.targetUrl ? route.query.targetUrl : '/growth_report';
     
     // 先从 session 获取保存的角色
     let savedRole = null;

+ 257 - 20
src/views/old_mini/growth_report/index.vue

@@ -5,10 +5,10 @@
         <!-- 组件:天气 -->
         <weather-info ref="weatherInfoRef" class="weather-info" @weatherExpanded="weatherExpanded"
             @changeGarden="changeGarden" :isGarden="true"></weather-info>
-        <div class="report-content-wrap" v-loading="loading">
+        <div class="report-content-wrap" v-if="hasReport" v-loading="loading">
             <swipe class="my-swipe" :loop="false" indicator-color="white">
                 <swipe-item v-for="(item, index) in 4" :key="index">
-                    <div class="report-content">
+                    <div class="report-content has-report">
                         <!-- <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">
@@ -24,14 +24,47 @@
 
                             <!-- 左滑查看更多 -->
                             <div class="swipe-more-tag">
-                                左滑查看更多
+                                左滑查看更多分区
                             </div>
                         </div>
 
                         <div class="report-box">
-                            <div class="box-title">农情总结</div>
-                            <div class="box-text">
-                                {{ workItem?.summaryAgricultural || "--" }}
+                            <div class="box-title warning">今日巡园重点</div>
+                            <div class="box-text w-100">
+                                <div class="row" v-for="row in todayRows" :key="row.label">
+                                    <div v-for="card in row.cards" :key="card.id" class="status-card" :class="card.type"
+                                        @click="handleBlockClick(card, row.label)">
+                                        <badge class="status-badge" dot v-if="card.title === '冲楸异常'"
+                                            :offset="[80, -10]">
+                                        </badge>
+                                        <div class="status-title">
+                                            {{ card.title }}
+                                        </div>
+                                        <div class="status-sub" v-if="card.sub">
+                                            {{ card.sub }}
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="report-box">
+                            <div class="box-title warning">待执行农事</div>
+                            <div class="box-text w-100">
+                                <div class="row" v-for="row in todoRows" :key="row.label">
+                                    <div v-for="card in row.cards" :key="card.id" class="status-card" :class="card.type"
+                                        @click="handleBlockClick(card, row.label)">
+                                        <badge class="status-badge" dot v-if="card.title === '冲楸异常'"
+                                            :offset="[80, -10]">
+                                        </badge>
+                                        <div class="status-title">
+                                            {{ card.title }}
+                                        </div>
+                                        <div class="status-sub" v-if="card.sub">
+                                            {{ card.sub }}
+                                        </div>
+                                    </div>
+                                </div>
                             </div>
                         </div>
 
@@ -101,6 +134,32 @@
             </swipe>
         </div>
 
+        <div v-else 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">
+                    <!-- <img class="header-book" src="@/assets/img/home/book.png" alt="" /> -->
+                    <div class="time-tag">{{ workItem?.reportDate }}</div>
+                    <div class="report-title">作物长势报告</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">{{ workItem?.orchardName }}</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" @click="handleLockClick">
+                    <img src="@/assets/img/home/lock-blue.png" alt="" class="lock-img-item" />
+                    <div class="lock-text">解锁某某某某某,解锁某某某某某</div>
+                </div>
+            </div>
+        </div>
+
         <!-- 首次进入页面的左滑查看提示遮罩 -->
         <div class="swipe-guide-mask" v-if="showSwipeGuide" @click="closeSwipeGuide">
             <div class="swipe-guide-content">
@@ -112,19 +171,23 @@
 </template>
 
 <script setup>
+import wx from "weixin-js-sdk";
 import weatherInfo from "@/components/weatherInfo.vue";
 import { ref, onActivated, onDeactivated, onUnmounted, computed } from "vue";
 import { useRoute } from "vue-router";
 import { useStore } from "vuex";
-import { Swipe, SwipeItem } from 'vant';
+import { Swipe, SwipeItem, Badge } from 'vant';
 
 const store = useStore();
 const tabBarHeight = computed(() => store.state.home.tabBarHeight);
 
 const route = useRoute();
 const loading = ref(false);
+const hasReport = ref(false);
 const workItem = ref({
-    executeDate: '2026-02-02',
+    reportDate: new Date().toISOString().split('T')[0],
+    executeDate: new Date().toISOString().split('T')[0],
+    orchardName: '示范农场',
     farmName: '荔枝博览园',
     resultInfo: '近7天时间地点,当下农情指标(物候期指标等等),面临的风险和出现的问题。',
     growthInfo: {
@@ -144,6 +207,60 @@ function formatArea(val) {
     if (Number.isNaN(num)) return val;
     return Number.isInteger(num) ? num : num.toFixed(2) + "亩";
 }
+
+const todayRows = ref([
+    {
+        label: "农情",
+        cards: [
+            {
+                id: 1,
+                title: "新梢萌动",
+                sub: "预计3天后进入",
+                type: "risk-strong",
+            },
+            {
+                id: 2,
+                title: "冲梢异常",
+                sub: "占比3%",
+                type: "normal",
+                badge: true,
+            },
+            {
+                id: 3,
+                title: "病虫风险",
+                sub: "一级风险",
+                type: "danger",
+            },
+        ],
+    },
+]);
+const todoRows = ref([
+    {
+        label: "农事",
+        cards: [
+            {
+                id: 4,
+                title: "第一段防治",
+                sub: "待完成",
+                type: "risk-strong",
+            },
+            {
+                id: 5,
+                title: "控梢",
+                sub: "待触发",
+                type: "normal",
+            },
+            {
+                id: 6,
+                title: "无",
+                sub: "",
+                type: "disabled",
+            },
+        ],
+    },
+]);
+
+
 const paramsPage = ref({});
 // 天气组件相关
 const isExpanded = ref(false);
@@ -190,6 +307,15 @@ const closeSwipeGuide = () => {
     showSwipeGuide.value = false;
 };
 
+const handleLockClick = () => {
+    wx.miniProgram.navigateTo({
+        url: '/pages/subPages/phone_auth/index',
+    });
+
+    // wx.miniProgram.navigateTo({
+    //     url: `/pages/subPages/share_page/index?pageParams=${JSON.stringify(query)}&type=sharePage`,
+    // });
+}
 
 const setReadStatus = (id) => {
     VE_API.farm.readReportByFarm({ id, isRead: 1 }).then(({ data }) => {
@@ -203,8 +329,9 @@ const getDetail = () => {
         .growthReportBySubject({ subjectId: paramsPage.value.farmId, limit: 20 })
         .then(({ data }) => {
             console.log('data', data);
-            workItem.value = data?.[0] || {};
+            // workItem.value = data?.[0] || {};
             data?.[0]?.id && setReadStatus(data[0]?.id);
+            // hasReport.value = data && data.length > 0;
         })
         .finally(() => {
             loading.value = false;
@@ -252,6 +379,22 @@ onUnmounted(() => {
         top: 12px;
     }
 
+    .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;
@@ -338,14 +481,45 @@ onUnmounted(() => {
 
     .report-content {
         // background: url("@/assets/img/home/report_bg.png") no-repeat center center;
-        background: linear-gradient(0deg, #9BCCFF, #9BCCFF),
-            linear-gradient(160deg, rgba(255, 255, 255, 0.16) 30%, rgba(255, 255, 255, 0) 72%);
+        // 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 16px 26px 16px;
         box-sizing: border-box;
         position: relative;
-        min-height: 100%;
+
+        &.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-img {
+            position: fixed;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -20%);
+            width: 100%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            flex-direction: column;
+            gap: 16px;
+            .lock-img-item {
+                width: 57px;
+            }
+            .lock-text {
+                font-size: 16px;
+                color: #000;
+                padding: 0 24px;
+                height: 34px;
+                line-height: 34px;
+                background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #FFFFFF 50%, rgba(255, 255, 255, 0) 100%);
+            }
+        }
 
         .header-img {
             position: absolute;
@@ -367,7 +541,7 @@ onUnmounted(() => {
             }
 
             .time-tag {
-                background: linear-gradient(137.86deg, #9fd5ff 5.87%, #2199f8 82.98%);
+                background: #2199F8;
                 border-radius: 5px 0 5px 0;
                 height: 23px;
                 line-height: 23px;
@@ -376,6 +550,7 @@ onUnmounted(() => {
                 color: #fff;
                 padding: 0 9px;
                 width: fit-content;
+                margin-bottom: 2px;
             }
 
             .report-title {
@@ -388,6 +563,10 @@ onUnmounted(() => {
             .report-info {
                 padding: 12px 0 28px 0;
 
+                &.pb-4 {
+                    padding-bottom: 4px;
+                }
+
                 .info-item {
                     width: fit-content;
                     display: flex;
@@ -408,7 +587,7 @@ onUnmounted(() => {
 
                     .info-text {
                         font-size: 14px;
-                        color: #2199f8;
+                        color: #000;
                     }
                 }
 
@@ -420,18 +599,17 @@ onUnmounted(() => {
             // 左滑查看更多标签
             .swipe-more-tag {
                 position: absolute;
-                top: 50%;
+                bottom: 10px;
                 right: -16px;
                 box-sizing: border-box;
                 width: 36px;
-                height: 116px;
-                padding: 10px 10px 2px 0;
+                height: 134px;
+                padding: 0px 10px 2px 0;
                 background: rgba(0, 0, 0, 0.7);
-                border-radius: 16px 0 0 16px;
+                border-radius: 10px 0 0 10px;
                 letter-spacing: 2px;
                 color: #ffffff;
-                font-size: 14px;
-                font-weight: 500;
+                font-size: 12px;
                 text-align: center;
                 line-height: 20px;
                 writing-mode: vertical-rl;
@@ -485,6 +663,14 @@ onUnmounted(() => {
                 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 {
@@ -519,6 +705,57 @@ onUnmounted(() => {
                     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;
+                    display: flex;
+                    flex-direction: column;
+                    align-items: center;
+                    justify-content: center;
+
+                    .status-badge {
+                        // position: absolute;
+                        // top: 0;
+                        // right: 0;
+                    }
+
+                    .status-title {
+                        font-size: 16px;
+                    }
+
+                    .status-sub {
+                        font-size: 10px;
+                        color: rgba(32, 32, 32, 0.4);
+                    }
+
+                    &.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 {

+ 66 - 10
src/views/old_mini/interaction/index.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="interaction-page">
-        <custom-header name="农情互动" bgColor="#f2f4f5" :isClose="true" :showClose="false" />
+        <custom-header name="农情互动" bgColor="#f2f4f5" />
         <div class="interaction-content">
             <!-- 顶部说明 -->
             <div class="intro-card">
@@ -71,7 +71,7 @@
         </div>
     </div>
 
-    <tip-popup v-model:show="showTipPopup" type="success" text="您的作物信息已完善" />
+    <tip-popup v-model:show="showTipPopup" type="success" text="您的农情报告已生成" text2="请查看" buttonText="点击查看" @confirm="handleTipConfirm" />
 
 
     <popup class="add-tag-popup" :z-index="2500" round v-model:show="showAddPopup" @update:show="handlePopupClose">
@@ -84,6 +84,16 @@
             <div @click="handleAddVariety">确认</div>
         </div>
     </popup>
+
+    <!-- 勾选区域引导弹窗 -->
+    <select-region-popup
+        v-model:show="showSelectRegionPopup"
+        :image="selectRegionImage"
+        :title="selectRegionTitle"
+        sub-title="精准匹配农情信息,高效管理分区"
+        @confirm="handleGoSelectRegion"
+        @skip="handleSkipSelectRegion"
+    />
 </template>
 
 <script setup>
@@ -91,8 +101,11 @@ import { ref, nextTick, onActivated } from "vue";
 import { ElMessage } from "element-plus";
 import { Popup } from "vant";
 import customHeader from "@/components/customHeader.vue";
-import { useRoute } from "vue-router";
+import { useRoute, useRouter } from "vue-router";
 import tipPopup from "@/components/popup/tipPopup.vue";
+import selectRegionPopup from "@/components/popup/selectRegionPopup.vue";
+
+const router = useRouter();
 
 const route = useRoute();
 
@@ -132,6 +145,29 @@ const getPhenologyLabel = (farm, phenologyId) => {
 
 const showTipPopup = ref(false);
 
+// 勾选区域引导弹窗相关
+const showSelectRegionPopup = ref(false);
+const selectRegionImage = ref("");
+const selectRegionTitle = ref("勾选 区域");
+
+// 获取第一个选择的品种名称用于弹窗标题
+const getFirstSelectedVarietyName = () => {
+    for (const farm of farmData.value) {
+        const selectedRegion = (farm.regions || []).find(
+            (r) => r.regionId && r.phenologyId && r.phenologyStartDate
+        );
+        if (selectedRegion) {
+            const varietyItem = (farm.typeIdItems || []).find(
+                (t) => String(t.id) === String(selectedRegion.regionId)
+            );
+            if (varietyItem?.name) {
+                return varietyItem.name;
+            }
+        }
+    }
+    return "";
+};
+
 const handleConfirm = async () => {
     // 组装为 initFarmData 接口所需的 farmDataList 结构
     const farmDataList = farmData.value
@@ -163,7 +199,7 @@ const handleConfirm = async () => {
         .filter((item) => item.typeIdItems.length > 0);
 
     if (!farmDataList.length) {
-        ElMessage.warning("请先选择品种、物候期和时间");
+        ElMessage.warning("请完善信息");
         return;
     }
 
@@ -173,12 +209,29 @@ const handleConfirm = async () => {
     };
     console.log("params", params);
 
-    const { code, msg } = await VE_API.farm_v3.initFarmData(params);
-    if (code === 0) {
-        showTipPopup.value = true;
-    } else {
-        ElMessage.error(msg || "提交失败");
+    // 显示勾选区域引导弹窗
+    const varietyName = getFirstSelectedVarietyName();
+    if (varietyName) {
+        selectRegionTitle.value = `勾选 ${varietyName} 区域`;
+            showSelectRegionPopup.value = true;
     }
+    // const { code, msg } = await VE_API.farm_v3.initFarmData(params);
+    // if (code === 0) {
+    //     showSelectRegionPopup.value = true;
+    // } else {
+    //     ElMessage.error(msg || "提交失败");
+    // }
+};
+
+const handleSkipSelectRegion = () => {
+    showSelectRegionPopup.value = false;
+    showTipPopup.value = true;
+};
+
+const handleGoSelectRegion = () => {
+    showSelectRegionPopup.value = false;
+    router.push("/draw_area");
+};
 
     // 大物候期转换所需参数// 组装为后端所需的 farmDataList 结构
     // const farmDataList = farmData.value
@@ -212,7 +265,6 @@ const handleConfirm = async () => {
     // } else {
     //     ElMessage.error(msg);
     // }
-};
 
 const showAddPopup = ref(false);
 const newVarietyName = ref("");
@@ -260,6 +312,10 @@ const handlePopupClose = (show) => {
         currentVariety.value = null;
     }
 }
+
+const handleTipConfirm = () => {
+    router.push("/growth_report");
+}
 </script>
 
 <style lang="scss" scoped>

+ 2 - 1
src/views/old_mini/monitor/index.vue

@@ -120,7 +120,8 @@ const showSelectRegionPopup = ref(false);
 const selectRegionImage = ref("");
 
 const handleAddVariety = () => {
-    showSelectRegionPopup.value = true;
+    // showSelectRegionPopup.value = true;
+    router.push("/interaction?subjectId=" + gardenId.value);
 };
 
 const handleSkipSelectRegion = () => {