浏览代码

fix: 农情互动弹窗接口对接

lxf 1 周之前
父节点
当前提交
6b502b2c8d

二进制
src/assets/img/home/start.png


+ 179 - 0
src/components/popup/startInteractPopup.vue

@@ -0,0 +1,179 @@
+<template>
+    <popup
+        v-model:show="showValue"
+        round
+        class="start-interact-popup"
+        teleport="body"
+        z-index="9999"
+    >
+        <div class="popup-content">
+            <div class="popup-tips">为了处方体系更加适应您当前的果园管理</div>
+            <!-- 头部区域 -->
+            <div class="popup-header">
+                <img class="expert-logo" :src="popupData?.expertAvatar" alt="" />
+                <!-- <el-avatar :size="26" :src="popupData?.expertAvatar" /> -->
+                <div class="expert-info">
+                    <span>{{ popupData?.expertName || "韦帮稳" }}专家</span>
+                    <span class="invite-text">邀请您进行农情互动</span>
+                </div>
+            </div>
+
+            <!-- 标题 -->
+            <div class="popup-title">农情互动</div>
+
+            <!-- 异常信息区域 -->
+            <div class="abnormal-info">
+                完善作物品种以及物候信息,精准匹配种植方案,实现精细化管理
+            </div>
+
+            <!-- 图片区域 -->
+            <img src="@/assets/img/home/start.png" alt="农事执行图片" class="execute-image" />
+
+            <!-- 按钮区域 -->
+            <div class="popup-buttons">
+                <div class="btn-executed" @click="handleExecuted">
+                    开始采集
+                </div>
+            </div>
+        </div>
+    </popup>
+</template>
+
+<script setup>
+import { Popup } from "vant";
+import { onActivated, ref } from "vue";
+import { useRouter } from "vue-router";
+
+const router = useRouter();
+
+const popupData = ref({
+    expertName: "",
+    expertAvatar: "",
+});
+
+const showValue = ref(false);
+
+// 开始采集
+const handleExecuted = () => {
+    router.push("/interaction?subjectId=" + localStorage.getItem("selectedFarmId"));
+};
+
+onActivated(() => {
+    // 查询物候期初始化/确认弹窗状态
+    // getPhenologyInitOrConfirmStatus();
+});
+
+const getPhenologyInitOrConfirmStatus = async () => {
+    const { data } = await VE_API.farm_v3.phenologyInitOrConfirmStatus({ subjectId: localStorage.getItem("selectedFarmId") });
+    if (!data?.farms ||!data.farms.length) {
+        return;
+    }
+    popupData.value = data.farms[0];
+    showValue.value = true;
+}
+
+defineExpose({
+    getPhenologyInitOrConfirmStatus,
+});
+</script>
+
+<style scoped lang="scss">
+.start-interact-popup {
+    width: 100%;
+    padding: 13px 16px;
+    border-radius: 12px;
+
+    .popup-content {
+        display: flex;
+        flex-direction: column;
+    }
+
+    .popup-tips{
+        color: rgba(93, 93, 93, 0.8);
+        margin-bottom: 5px;
+    }
+
+    .popup-header {
+        margin-bottom: 5px;
+        display: flex;
+        align-items: center;
+        gap: 6px;
+        .expert-logo {
+            width: 26px;
+            height: 26px;
+            border-radius: 50%;
+            object-fit: cover;
+        }
+
+        .expert-info {
+            font-size: 16px;
+            .invite-text {
+                margin-left: 6px;
+            }
+        }
+    }
+
+    .popup-title {
+        font-size: 24px;
+        margin-bottom: 6px;
+        font-family: "PangMenZhengDao";
+        color: #0785E8;
+    }
+
+    .abnormal-info {
+        padding: 12px;
+        color: #2199f8;
+        background: rgba(33, 153, 248, 0.1);
+        padding: 3px 9px 9px;
+        border-radius: 8px;
+        position: relative;
+        margin-top: 5px;
+        
+        // 三角形小尖尖
+        &::before {
+            content: "";
+            position: absolute;
+            top: -7.5px;
+            left: 20px;
+            width: 0;
+            height: 0;
+            border-left: 15px solid transparent;
+            border-right: 2px solid transparent;
+            border-bottom: 8px solid rgba(33, 153, 248, 0.1);
+        }
+    }
+
+    .execute-image {
+        width: 100%;
+        height: 170px;
+        border-radius: 5px;
+        object-fit: cover;
+        margin: 11px 0 13px 0;
+    }
+
+    .popup-buttons {
+        display: flex;
+        gap: 13px;
+
+        .btn-later,
+        .btn-executed {
+            flex: 1;
+            padding: 8px;
+            border-radius: 4px;
+            font-size: 16px;
+            text-align: center;
+        }
+
+        .btn-later {
+            border: 1px solid #d7d7d7;
+            color: #9d9d9d;
+        }
+
+        .btn-executed {
+            background: #2199f8;
+            color: #ffffff;
+            border: 1px solid #2199f8;
+        }
+    }
+}
+</style>

+ 23 - 27
src/components/weatherInfo.vue

@@ -1,8 +1,8 @@
 <template>
-    <div class="weather-info" :class="{ expanded: isExpanded, 'is-garden': isGarden ,'bg-white': isWhite}">
+    <div class="weather-info is-garden" :class="{ expanded: isExpanded}">
         <div class="header flex-center">
             <div class="header-left">
-                <div class="address-select flex-center" v-if="isGarden">
+                <div class="address-select flex-center" v-if="hasFarm">
                     <el-dropdown class="select-garden" trigger="click" popper-class="select-garden-popper">
                         <div class="el-dropdown-link flex-center">
                             <span class="ellipsis-l1">{{ farmName }}</span>
@@ -31,6 +31,10 @@
                         </div>
                     </div>
                 </div>
+
+                <div class="address-select flex-center farm-name" v-else>
+                    示范农场
+                </div>
                 <div class="temperature flex-center">
                     <div class="temperature-number">{{ currentWeather.temp || '--' }}</div>
                     <div class="temperature-text">
@@ -80,10 +84,6 @@ import { convertPointToArray } from "@/utils/index";
 const store = useStore();
 
 const props = defineProps({
-    isGarden: {
-        type: Boolean,
-        default: false
-    },
     gardenId: {
         type: [Number, String],
         default: null
@@ -109,11 +109,7 @@ const handleCommand = ({id, name}) => {
 };
 
 const isExpanded = ref(false);
-const isWhite = ref(false);
 const toggleExpand = () => {
-    if(props.isGarden){
-        isWhite.value = !isWhite.value;
-    }
     isExpanded.value = !isExpanded.value;
     emit('weatherExpanded',isExpanded.value);
 };
@@ -121,6 +117,7 @@ const toggleExpand = () => {
 const farmId = ref(null);
 const farmName = ref("");
 const farmList = ref([]);
+const hasFarm = ref(true)
 const isDefaultFarm = ref(false); // 添加默认农场标识
 
 // 根据传入的gardenId设置农场(先刷新列表再设置)
@@ -154,7 +151,10 @@ async function setFarmByGardenId(gardenIdValue) {
                     resolve(false);
                 }
             } else {
-                farmList.value = [{id: 1, name: '示范农场', defaultOption: false, wkt: localStorage.getItem('MINI_USER_LOCATION_POINT')}];
+                farmList.value = [];
+                hasFarm.value = false;
+                getLocationName();
+                getWeatherData();
                 resolve(false);
             }
         }).catch(() => {
@@ -215,12 +215,13 @@ function getFarmListWithoutGardenId() {
         // const fullData = data.filter(item => item.userType === 2);
         const fullData = data;
         farmList.value = fullData || [];
-        console.log('getFarmListWithoutGardenId', 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);
+            farmList.value = [];
+            hasFarm.value = false;
+            getLocationName();
+            getWeatherData();
         }
     })
 }
@@ -275,19 +276,9 @@ const weatherData = ref(null);
 const currentWeather = ref({ temp: "--", text: "--", iconDay: "" });
 const MAP_KEY = "CZLBZ-LJICQ-R4A5J-BN62X-YXCRJ-GNBUT";
 function getLocationName() {
-    const farmLocation = convertPointToArray(localStorage.getItem('selectedFarmPoint'));
-    let formattedLocation = null;
-
-    if (farmLocation) {
-        formattedLocation = `${farmLocation[1]},${farmLocation[0]}`;
-    } else {
-        const location = store.state.home.miniUserLocation;
-        // 将 location 从"经度,纬度"格式转换为"纬度,经度"格式
-        if (typeof location === 'string' && location.includes(',')) {
-            const [lng, lat] = location.split(',');
-            formattedLocation = `${lat},${lng}`;
-        }
-    }
+    const locationPoint = localStorage.getItem('selectedFarmPoint') || store.state.home.miniUserLocationPoint;
+    const farmLocation = convertPointToArray(locationPoint);
+    let formattedLocation = `${farmLocation[1]},${farmLocation[0]}`;
     const params = {
             key: MAP_KEY,
             location: formattedLocation,
@@ -361,6 +352,7 @@ const currentDateText = computed(() => {
 
     &.expanded {
         height: 312px;
+        background-image: linear-gradient(90deg, #e2f1fe 0%, #ffffff 80%);
     }
 
     &.bg-white{
@@ -427,6 +419,10 @@ const currentDateText = computed(() => {
                     border: 1px solid rgba(145, 145, 145, 0.5);
                 }
             }
+            .farm-name {
+                font-size: 16px;
+                color: #1D2129;
+            }
             .temperature {
                 .temperature-number {
                     font-size: 40px;

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

@@ -61,10 +61,10 @@ onMounted(async () => {
         store.dispatch(`app/${SET_USER_CUR_ROLE}`, roles[roles.length - 1]);
     }
     // 进入首页时请求接口,确定是否为托管农户
-    await fetchUserType();
-    await getFarmList(() => {
-        targetUrl = '/create_farm?type=farmer&expertMiniUserId=81881&isReload=true';
-    });
+    // await fetchUserType();
+    // await getFarmList(() => {
+    //     targetUrl = '/create_farm?type=farmer&expertMiniUserId=81881&isReload=true';
+    // });
     
     localStorage.setItem("MINI_USER_LOCATION", route.query.point)
     localStorage.setItem("MINI_USER_LOCATION_POINT", `POINT(${pointXy[0]} ${pointXy[1]})`)

+ 37 - 5
src/views/old_mini/growth_report/index.vue

@@ -120,8 +120,15 @@
 
                 <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 class="lock-text">
+                        专属数字农场,种好卖好
+                        <div>点击解锁一键溯源增产</div>
+                    </div>
+
+                    <div class="lock-btn">点击解锁</div>
                 </div>
+
+                <div class="lock-bg"></div>
             </div>
         </div>
 
@@ -134,6 +141,8 @@
         </div>
 
         <tip-popup v-model:show="showBindSuccess" type="success" text="您的农场已绑定成功" />
+
+        <start-interact-popup ref="startInteractPopupRef" />
     </div>
 </template>
 
@@ -145,6 +154,7 @@ import { useRoute, useRouter } from "vue-router";
 import { useStore } from "vuex";
 import { Swipe, SwipeItem, Badge } from 'vant';
 import tipPopup from "@/components/popup/tipPopup.vue";
+import startInteractPopup from "@/components/popup/startInteractPopup.vue";
 
 const store = useStore();
 const tabBarHeight = computed(() => store.state.home.tabBarHeight);
@@ -157,6 +167,7 @@ const workItems = ref([]);
 
 const paramsPage = ref({});
 const showBindSuccess = ref(false);
+const startInteractPopupRef = ref(null);
 // 天气组件相关
 const isExpanded = ref(false);
 const weatherInfoRef = ref(null);
@@ -184,6 +195,7 @@ const changeGarden = ({ id, name }) => {
         ...(paramsPage.value || {}),
         subjectId: id,
     };
+    startInteractPopupRef.value.getPhenologyInitOrConfirmStatus();
     getRegions();
 };
 
@@ -460,8 +472,19 @@ onUnmounted(() => {
                 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 {
             position: fixed;
+            z-index: 10;
             top: 50%;
             left: 50%;
             transform: translate(-50%, -20%);
@@ -475,13 +498,22 @@ onUnmounted(() => {
                 width: 57px;
             }
             .lock-text {
-                font-size: 16px;
+                font-size: 14px;
                 color: #000;
-                padding: 0 24px;
-                height: 34px;
-                line-height: 34px;
+                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 {

+ 37 - 21
src/views/old_mini/interaction/index.vue

@@ -8,7 +8,7 @@
             </div>
 
             <!-- 作物块(每个农场一块) -->
-            <div v-for="(crop, cropIndex) in farmData" :key="cropIndex" class="crop-section">
+            <div v-for="(crop, cropIndex) in farmData.farms" :key="cropIndex" class="crop-section">
                 <div class="crop-header">
                     <div class="crop-tag">{{ crop.speciesName }}</div>
                     <div class="add-btn" @click="addVariety(crop)">+ 新增品种</div>
@@ -114,11 +114,14 @@ onActivated(() => {
     getPhenologyInitOrConfirmStatus(subjectId);
 });
 
-const farmData = ref([])
+const farmData = ref({
+    farms: [],
+    status: "",
+})
 const getPhenologyInitOrConfirmStatus = async (subjectId) => {
     const {data} = await VE_API.farm_v3.phenologyInitOrConfirmStatus({subjectId});
-    farmData.value = data.farms;
-    farmData.value.forEach(item => {
+    farmData.value = data;
+    data.farms.forEach(item => {
         addVariety(item);
     });
 }
@@ -152,7 +155,7 @@ const selectRegionTitle = ref("勾选 区域");
 
 // 获取第一个选择的品种名称用于弹窗标题
 const getFirstSelectedVarietyName = () => {
-    for (const farm of farmData.value) {
+    for (const farm of farmData.value.farms) {
         const selectedRegion = (farm.regions || []).find(
             (r) => r.regionId && r.phenologyId && r.phenologyStartDate
         );
@@ -170,7 +173,8 @@ const getFirstSelectedVarietyName = () => {
 
 const handleConfirm = async () => {
     // 组装为 initFarmData 接口所需的 farmDataList 结构
-    const farmDataList = farmData.value
+    const status = farmData.value.status;
+    const farmDataList = farmData.value.farms
         .map((farm) => {
             const typeIdItems = (farm.regions || [])
                 .filter(
@@ -181,12 +185,20 @@ const handleConfirm = async () => {
                         (farm.typeIdItems || []).find(
                             (t) => String(t.id) === String(r.regionId)
                         ) || {};
-                    return {
-                        id: r.regionId,
-                        name: origin.name || "",
-                        phenologyId: r.phenologyId,
-                        phenologyStartDate: r.phenologyStartDate,
-                    };
+                    if (status === 'INIT') {
+                        return {
+                            id: r.regionId,
+                            name: origin.name || "",
+                            phenologyId: r.phenologyId,
+                            phenologyStartDate: r.phenologyStartDate,
+                        };
+                    } else {
+                        return {
+                            regionId: r.regionId,
+                            phenologyId: r.phenologyId,
+                            phenologyStartDate: r.phenologyStartDate,
+                        }
+                    }
                 })
                 .filter((item) => item.id);
 
@@ -207,16 +219,20 @@ const handleConfirm = async () => {
         expertMiniUserId: 81881,
         farmDataList,
     };
-    console.log("params", params);
 
-    // 显示勾选区域引导弹窗
-    const varietyName = getFirstSelectedVarietyName();
-    if (varietyName) {
-        selectRegionTitle.value = `勾选 ${varietyName} 区域`;
-    }
-    const { code, msg } = await VE_API.farm_v3.initFarmData(params);
+    const { code, msg } = await VE_API.farm_v3[status === 'INIT' ? 'initFarmData' : 'confirmReproductivePhenology'](params);
     if (code === 0) {
-        showSelectRegionPopup.value = true;
+        // 从点击新增品种进来的才需要勾选区域
+        if (route.query.from === 'addVariety') {
+            // 显示勾选区域引导弹窗
+            const varietyName = getFirstSelectedVarietyName();
+            if (varietyName) {
+                selectRegionTitle.value = `勾选 ${varietyName} 区域`;
+            }
+            showSelectRegionPopup.value = true;
+        } else {
+            showTipPopup.value = true;
+        }
     } else {
         ElMessage.error(msg || "提交失败");
     }
@@ -229,7 +245,7 @@ const handleSkipSelectRegion = () => {
 
 const handleGoSelectRegion = () => {
     showSelectRegionPopup.value = false;
-    router.push("/draw_area");
+    router.push("/draw_area?subjectId=" + route.query.subjectId);
 };
 
     // 大物候期转换所需参数// 组装为后端所需的 farmDataList 结构