Kaynağa Gözat

Merge branch 'agriculture' of http://www.sysuimars.cn:3000/feiniao/feiniao-farm-h5 into agriculture

wangsisi 1 gün önce
ebeveyn
işleme
f7245fe130

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


+ 23 - 7
src/components/gardenList.vue

@@ -111,11 +111,27 @@ function selectDefaultFarm(data) {
 }
 
 function selectFarmFromList(data) {
-    console.log('props.gardenId', props.gardenId);
-    const targetId = props.gardenId || localStorage.getItem("selectedFarmId");
-    console.log('targetId', targetId);
-    const targetFarm = data.find((farm) => Number(farm.id) === Number(targetId));
-    return targetFarm || selectDefaultFarm(data);
+    // 1) 传入 gardenId 时优先使用(与 weatherInfo copy 逻辑一致)
+    if (props.gardenId) {
+        const gardenFarm = data.find((farm) => Number(farm.id) === Number(props.gardenId));
+        if (gardenFarm) {
+            return gardenFarm;
+        }
+    }
+
+    // 2) gardenId 不可用时,回退到本地缓存的选中农场
+    const savedFarmId = localStorage.getItem("selectedFarmId");
+    const savedFarmName = localStorage.getItem("selectedFarmName");
+    if (savedFarmId && savedFarmName) {
+        // 名称以最新列表为准,避免改名后仍显示缓存旧值
+        const savedFarm = data.find((farm) => Number(farm.id) === Number(savedFarmId));
+        if (savedFarm) {
+            return savedFarm;
+        }
+    }
+
+    // 3) 都不可用时,按默认农场规则兜底
+    return selectDefaultFarm(data);
 }
 
 function normalizeFarmList(data) {
@@ -191,9 +207,9 @@ defineExpose({
 .garden-list-page {
     height: 100vh;
     overflow: auto;
-    padding: 115px 10px 50px 10px;
+    padding: 115px 10px 120px 10px;
     box-sizing: border-box;
-    background: linear-gradient(180deg, #2199F8 9.42%, #F5F5F5 31%, #F5F5F5 72.99%, #F5F5F5 100%);
+    background: linear-gradient(180deg, #2199F8 10%, #F5F5F5 31%, #F5F5F5 73%, #F5F5F5 100%);
 }
 
 .garden-card {

+ 75 - 23
src/components/weatherInfo.vue

@@ -23,6 +23,14 @@
                                 alt="">
                             <span class="current-name">农场列表</span>
                         </div>
+
+                        <div class="mask-wrap" v-if="props.showTabMask">
+                            <div class="mask-content">
+                                <div class="mask-text">
+                                    查看全部农场列表,并可创建农场
+                                </div>
+                            </div>
+                        </div>
                     </div>
                 </div>
 
@@ -49,7 +57,7 @@
                     </div>
 
                     <div class="button-wrap" v-if="hasFarm">
-                        <div class="button-item">
+                        <div class="button-item" @click="handleFarmInfo">
                             <img class="button-pre" src="@/assets/img/common/info.png" alt="">
                             农场信息
                         </div>
@@ -104,6 +112,10 @@ import { convertPointToArray } from "@/utils/index";
 const store = useStore();
 
 const props = defineProps({
+    showTabMask: {
+        type: Boolean,
+        default: false
+    },
     gardenId: {
         type: [Number, String],
         default: null
@@ -144,18 +156,8 @@ const farmName = ref("");
 const hasFarm = ref(false)
 const activeGarden = ref('current');
 
-function initSelectedFarm() {
-    const savedFarmId = localStorage.getItem("selectedFarmId");
-    const savedFarmName = localStorage.getItem("selectedFarmName");
-    farmId.value = savedFarmId ? Number(savedFarmId) : null;
-    farmName.value = savedFarmName || "";
-    hasFarm.value = !!farmId.value;
-}
-
 onActivated(() => {
-    // initSelectedFarm();
-    // getLocationName();
-    // getWeatherData();
+    handleGardenClick('current');
 });
 
 function setGardenLoaded(hasFarmData) {
@@ -169,6 +171,8 @@ function setGardenLoaded(hasFarmData) {
 function setSelectedGarden(payload) {
     if (!payload?.id) {
         setGardenLoaded(false);
+        getLocationName();
+        getWeatherData();
         return;
     }
 
@@ -180,12 +184,14 @@ function setSelectedGarden(payload) {
     emit('changeGarden', { id: farmId.value, name: farmName.value });
 }
 
-// 暴露方法供父页面(如长势报告)同步农场列表状态
-defineExpose({
-    setGardenLoaded,
-    setSelectedGarden,
-    toggleExpand
-});
+const handleFarmInfo = () => {
+    router.push(`/farm_info?subjectId=${farmId.value}`);
+}
+
+const handleGardenClick = (type) => {
+    activeGarden.value = type;
+    emit("changeGardenTab", type);
+};
 
 const locationName = ref("");
 const weatherData = ref(null);
@@ -206,11 +212,6 @@ function getLocationName() {
             : result?.address + "";
     });
 }
-
-const handleGardenClick = (type) => {
-    activeGarden.value = type;
-    emit("changeGardenTab", type);
-};
 const handleAddFarm = () => {
     router.push(`/create_farm?from=${props.from}&isReload=true`);
 }
@@ -260,9 +261,58 @@ const currentWeekText = computed(() => {
     const weekMap = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
     return weekMap[date.getDay()];
 });
+
+
+// 暴露方法供父页面(如长势报告)同步农场列表状态
+defineExpose({
+    setGardenLoaded,
+    setSelectedGarden,
+    toggleExpand,
+    handleGardenClick
+});
 </script>
 
 <style lang="scss" scoped>
+.mask-wrap {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: calc(100% - 300px);
+    background-color: rgba(0, 0, 0, 0.52);
+    z-index: 99999;
+    color: rgba(0, 0, 0, 0.9);
+    .mask-content {
+        position: absolute;
+        right: 51px;
+        top: 58px;
+        .mask-text {
+            background: #fff;
+            padding: 6px 16px;
+            border-radius: 10px;
+            font-size: 14px;
+            line-height: 22px;
+            text-align: center;
+            width: fit-content;
+            box-sizing: border-box;
+            border: 1px solid #DCDCDC;
+            position: relative;
+            z-index: 10px;
+            &::after {
+                content: '';
+                position: absolute;
+                right: 24px;
+                top: -10px;
+                width: 0;
+                height: 0;
+                border-right: 5px solid transparent;
+                border-top: 5px solid transparent;
+                border-left: 5px solid transparent;
+                border-bottom: 5px solid #fff;
+            }
+        }
+    }
+}
 .weather-info {
     width: 100%;
     // height: 58px;
@@ -455,6 +505,7 @@ const currentWeekText = computed(() => {
 
             &.right-item {
                 padding-right: 10px;
+                z-index: 9999999;
             }
 
             &.active {
@@ -516,6 +567,7 @@ const currentWeekText = computed(() => {
         justify-content: space-between;
         align-items: center;
         padding: 12px 7px 8px 7px;
+        height: 53px;
         box-sizing: border-box;
         background: #ffffff;
 

+ 37 - 6
src/views/old_mini/agri_record/index.vue

@@ -5,9 +5,15 @@
         <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
         <!-- 天气 -->
         <weather-info ref="weatherInfoRef" from="agri_record" class="weather-info" @weatherExpanded="weatherExpanded"
-            @changeGarden="changeGarden" :isGarden="true" :gardenId="defaultGardenId"></weather-info>
+            @changeGarden="changeGarden" @changeGardenTab="changeGardenTab" :isGarden="true"
+            :gardenId="defaultGardenId"></weather-info>
+        <!-- 农场列表 -->
+        <div v-show="activeGardenTab === 'list'">
+            <garden-list ref="gardenListRef" :garden-id="selectedGardenId" @loaded="handleGardenLoaded"
+                @selectGarden="handleGardenSelected" />
+        </div>
         <!-- 作物档案 -->
-        <div class="archives-time-line">
+        <div class="archives-time-line" :class="{ 'no-top': !varietyTabs.length && !gardenId }" v-show="activeGardenTab === 'current'">
             <div class="archives-time-line-header">
                 <div class="line-title" @click="handleFarmInfoClick">农事记录</div>
                 <div class="header-right">
@@ -71,6 +77,7 @@ import ArchivesFarmTimeLine from "@/components/pageComponents/ArchivesFarmTimeLi
 import selectRegionPopup from "@/components/popup/selectRegionPopup.vue";
 import agriExecutePopup from "@/components/popup/agriExecutePopup.vue";
 import startInteractPopup from "@/components/popup/startInteractPopup.vue";
+import gardenList from "@/components/gardenList.vue";
 
 const agriExecutePopupRef = ref(null);
 const startInteractPopupRef = ref(null);
@@ -173,6 +180,22 @@ const disabledYearDate = (time) => {
 };
 
 const defaultGardenId = ref(null);
+const selectedGardenId = ref(null);
+const gardenListRef = ref(null);
+const activeGardenTab = ref('current');
+const changeGardenTab = (tab) => {
+    activeGardenTab.value = tab;
+};
+
+const handleGardenLoaded = ({ hasFarm }) => {
+    weatherInfoRef.value?.setGardenLoaded?.(hasFarm);
+};
+
+const handleGardenSelected = (garden) => {
+    selectedGardenId.value = garden?.id ?? null;
+    weatherInfoRef.value?.setSelectedGarden?.(garden);
+};
+
 const isHeaderShow = ref(false);
 const isDefaultFarm = ref(false);
 const weatherInfoRef = ref(null);
@@ -185,6 +208,9 @@ onActivated(() => {
         // 统一转换为布尔值
         isDefaultFarm.value = route.query.defaultFarm === "true" || route.query.defaultFarm === true;
     }
+    const savedFarmId = localStorage.getItem("selectedFarmId");
+    selectedGardenId.value = savedFarmId ? Number(savedFarmId) : null;
+    gardenListRef.value?.refreshFarmList?.();
 });
 
 const store = useStore();
@@ -264,9 +290,8 @@ const handleCardClick = () => {
 .monitor-index {
     width: 100%;
     height: 100%;
-    padding: 13px 10px;
     box-sizing: border-box;
-    background: linear-gradient(180deg, #f9f9f9 0%, #f0f8ff 31.47%, #f9f9f9 46.81%, #f9f9f9 69.38%, #f9f9f9 100%);
+    background: linear-gradient(180deg, #2199F8 8%, #F5F5F5 19%, #F5F5F5 73%, #F5F5F5 100%);
 
     .weather-mask {
         position: fixed;
@@ -318,22 +343,28 @@ const handleCardClick = () => {
     .example-img {
         width: 100%;
         height: 100%;
-        object-fit: contain;
+        object-fit: inherit;
     }
 
     .weather-info {
         width: calc(100% - 20px);
         position: absolute;
+        top: 10px;
+        left: 10px;
         z-index: 12;
     }
 
     .archives-time-line {
         position: relative;
-        margin-top: 96px;
         height: calc(100% - 90px);
+        padding: 12px;
         display: flex;
         flex-direction: column;
         min-height: 0;
+        padding-top: 150px;
+        &.no-top {
+            padding-top: 96px;
+        }
 
         .archives-time-line-header {
             flex-shrink: 0;

+ 56 - 11
src/views/old_mini/growth_report/index.vue

@@ -5,7 +5,8 @@
         <!-- 组件:天气 -->
         <div class="weather-info-wrap">
             <weather-info ref="weatherInfoRef" from="growth_report" class="weather-info"
-                @weatherExpanded="weatherExpanded" @changeGarden="changeGarden" @changeGardenTab="changeGardenTab">
+                :showTabMask="showTabMask" @weatherExpanded="weatherExpanded" @changeGarden="changeGarden"
+                @changeGardenTab="changeGardenTab">
                 </weather-info>
                 
             <!-- 邀请关注 -->
@@ -53,12 +54,12 @@
                             </div>
 
                             <!-- 左滑查看更多 -->
-                            <div class="swipe-more-tag" v-show="currentIndex < regionsData.length - 1">
+                            <div class="swipe-more-tag" v-show="regionsData.length > 1 && currentIndex < regionsData.length - 1">
                                 <div>更多分区</div>
                                 左滑查看
                             </div>
                             <!-- 右滑查看更多 -->
-                            <div class="swipe-more-tag" v-show="currentIndex === regionsData.length - 1">
+                            <div class="swipe-more-tag" v-show="regionsData.length > 1 && currentIndex === regionsData.length - 1">
                                 <div>更多分区</div>
                                 右滑查看
                             </div>
@@ -183,6 +184,9 @@
             </div>
         </div>
 
+        <!-- 农场列表引导 -->
+        <div class="mask-wrap" @click="closeTabMask" v-if="showTabMask"></div>
+
         <tip-popup v-model:show="showBindSuccess" type="success" text="您的农场已绑定成功" hideBtn />
 
         <start-interact-popup ref="startInteractPopupRef" />
@@ -223,7 +227,10 @@ const weatherInfoRef = ref(null);
 
 // 首次进入页面的左滑提示遮罩
 const showSwipeGuide = ref(false);
-
+const showTabMask = ref(false);
+const pendingSwipeGuide = ref(false);
+const TAB_GUIDE_SHOWN_KEY = "GROWTH_REPORT_TAB_GUIDE_SHOWN";
+const SWIPE_GUIDE_KEY = "GROWTH_REPORT_SWIPE_GUIDE_SHOWN";
 const weatherExpanded = (isExpandedValue) => {
     isExpanded.value = isExpandedValue;
 };
@@ -273,6 +280,9 @@ const changeGarden = async ({ id, name }) => {
 
 onActivated(() => {
     window.scrollTo(0, 0);
+    // 从新增农场页返回时,优先用缓存中的最新选中农场
+    const savedFarmId = localStorage.getItem("selectedFarmId");
+    selectedGardenId.value = savedFarmId ? Number(savedFarmId) : null;
     gardenListRef.value?.refreshFarmList?.();
 
     // 如果路由中带有 miniJson,并且其中有 showBind,则展示绑定成功弹窗
@@ -299,6 +309,15 @@ const closeSwipeGuide = () => {
     showSwipeGuide.value = false;
 };
 
+const closeTabMask = () => {
+    showTabMask.value = false;
+    if (pendingSwipeGuide.value) {
+        showSwipeGuide.value = true;
+        pendingSwipeGuide.value = false;
+        localStorage.setItem(SWIPE_GUIDE_KEY, "1");
+    }
+};
+
 const userInfo = localStorage.getItem("localUserInfo");
 const userInfoObj = userInfo ? JSON.parse(userInfo) : {};
 
@@ -394,12 +413,26 @@ const getRegions = async () => {
     }).then(({ data }) => {
         regionsData.value = data || [];
         if (regionsData.value.length > 0) {
-            const guideKey = "GROWTH_REPORT_SWIPE_GUIDE_SHOWN";
-            if (!localStorage.getItem(guideKey) && regionsData.value.length > 1) {
-                showSwipeGuide.value = true;
-                localStorage.setItem(guideKey, "1");
-            }
             hasReport.value = true;
+            const hasShownTabGuide = localStorage.getItem(TAB_GUIDE_SHOWN_KEY) === "1";
+            const needSwipeGuide = !localStorage.getItem(SWIPE_GUIDE_KEY) && regionsData.value.length > 1;
+
+            // 首次进入且有分区数据:先显示农场列表引导;左滑引导在其关闭后再显示
+            if (!hasShownTabGuide) {
+                showTabMask.value = true;
+                localStorage.setItem(TAB_GUIDE_SHOWN_KEY, "1");
+                pendingSwipeGuide.value = needSwipeGuide;
+            } else {
+                showTabMask.value = false;
+                pendingSwipeGuide.value = false;
+                if (needSwipeGuide) {
+                    showSwipeGuide.value = true;
+                    localStorage.setItem(SWIPE_GUIDE_KEY, "1");
+                }
+            }
+
+            // 切换农场tab回到当前农场tab
+            weatherInfoRef.value && weatherInfoRef.value.handleGardenClick('current');
 
             // 如果不是点击农情报告已生成弹窗过来的,则显示农情互动弹窗
             if (!route.query.hideInteraction) {
@@ -436,6 +469,10 @@ const getRegions = async () => {
                 sessionStorage.removeItem('activeSwipeIndex');
             }
         } else {
+            // 切换农场tab回到当前农场tab
+            // weatherInfoRef.value && weatherInfoRef.value.handleGardenClick('current');
+            showTabMask.value = false;
+            pendingSwipeGuide.value = false;
             hasReport.value = false;
         }
     });
@@ -459,6 +496,15 @@ onUnmounted(() => {
 </script>
 
 <style lang="scss" scoped>
+.mask-wrap {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    height: 300px;
+    background-color: rgba(0, 0, 0, 0.52);
+    z-index: 99999;
+}
 .achievement-report-page {
     width: 100%;
     height: 100vh;
@@ -480,7 +526,7 @@ onUnmounted(() => {
         position: absolute;
         z-index: 12;
         left: 10px;
-        top: 12px;
+        top: 10px;
 
         .weather-info {
             width: 100%;
@@ -512,7 +558,6 @@ onUnmounted(() => {
                     right: 0;
                     width: 0px;
                     height: 0px;
-                    content: " ";
                     border-right: 3px solid transparent;
                     border-top: 3px solid #75a8cd;
                     border-left: 3px solid #75a8cd;

+ 6 - 2
src/views/old_mini/home/subPages/prescriptionPage.vue

@@ -276,8 +276,12 @@ async function submit() {
                 if (route.query.subjectId) {
                     router.go(-1);
                 } else {
-                    localStorage.setItem("selectedFarmId", res.data[0]?.subjectId);
-                    localStorage.setItem("selectedFarmName", res.data[0]?.name);
+                    const createdFarm = Array.isArray(res.data) ? res.data[0] : res.data;
+                    // 农场列表按 farm.id 匹配,优先缓存 id,兼容回退 subjectId
+                    localStorage.setItem("selectedFarmId", createdFarm?.id ?? createdFarm?.subjectId ?? "");
+                    localStorage.setItem("selectedFarmName", createdFarm?.name ?? "");
+                    // 创建农场成功后,进入长势报告且有分区数据时展示一次农场列表引导
+                    localStorage.setItem("GROWTH_REPORT_NEED_TAB_GUIDE", "1");
                     router.replace('/growth_report');
                 }
                 ElMessage.success('创建成功');

+ 38 - 8
src/views/old_mini/monitor/index.vue

@@ -5,9 +5,15 @@
         <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
         <!-- 天气 -->
         <weather-info ref="weatherInfoRef" from="monitor" class="weather-info" @weatherExpanded="weatherExpanded"
-            @changeGarden="changeGarden" :isGarden="true" :gardenId="defaultGardenId"></weather-info>
+            @changeGarden="changeGarden" @changeGardenTab="changeGardenTab" :isGarden="true"
+            :gardenId="defaultGardenId"></weather-info>
+        <!-- 农场列表 -->
+        <div v-show="activeGardenTab === 'list'">
+            <garden-list ref="gardenListRef" :garden-id="selectedGardenId" @loaded="handleGardenLoaded"
+                @selectGarden="handleGardenSelected" />
+        </div>
         <!-- 作物档案 -->
-        <div class="archives-time-line">
+        <div class="archives-time-line" :class="{ 'no-top': !varietyTabs.length && !gardenId }" v-show="activeGardenTab === 'current'">
             <div class="archives-time-line-header">
                 <div class="line-title" @click="handlePage">农情档案</div>
                 <div class="header-right">
@@ -85,6 +91,7 @@ import { ElMessage, ElMessageBox } from "element-plus";
 import ArchivesFarmTimeLine from "@/components/pageComponents/ArchivesFarmTimeLine.vue";
 import agriExecutePopup from "@/components/popup/agriExecutePopup.vue";
 import startInteractPopup from "@/components/popup/startInteractPopup.vue";
+import gardenList from "@/components/gardenList.vue";
 
 const startInteractPopupRef = ref(null);
 const handlePage = () => {
@@ -109,7 +116,7 @@ const getVarietyTabs = async (isShowPopup = true) => {
         // if(res.data && res.data.regionList && res.data.problemZones){
         //     varietyTabs.value = res.data.regionList.concat(res.data.problemZones)
         // }
-        varietyTabs.value = res.data.regionList
+        varietyTabs.value = res.data?.regionList || []
         if (varietyTabs.value.length > 0) {
             handleVarietyClick(varietyTabs.value[activeVariety.value || 0], activeVariety.value || 0)
             if (isShowPopup && !showSelectRegionPopup.value && agriExecutePopupRef.value) {
@@ -175,6 +182,22 @@ const handleGoSelectRegion = () => {
 const showFarmPopup = ref(false); // 农场领取成功弹窗
 
 const defaultGardenId = ref(null);
+const selectedGardenId = ref(null);
+const gardenListRef = ref(null);
+const activeGardenTab = ref('current');
+const changeGardenTab = (tab) => {
+    activeGardenTab.value = tab;
+};
+
+const handleGardenLoaded = ({ hasFarm }) => {
+    weatherInfoRef.value?.setGardenLoaded?.(hasFarm);
+};
+
+const handleGardenSelected = (garden) => {
+    selectedGardenId.value = garden?.id ?? null;
+    weatherInfoRef.value?.setSelectedGarden?.(garden);
+};
+
 const isHeaderShow = ref(false);
 const isDefaultFarm = ref(false);
 const weatherInfoRef = ref(null);
@@ -187,6 +210,9 @@ onActivated(() => {
         // 统一转换为布尔值
         isDefaultFarm.value = route.query.defaultFarm === "true" || route.query.defaultFarm === true;
     }
+    const savedFarmId = localStorage.getItem("selectedFarmId");
+    selectedGardenId.value = savedFarmId ? Number(savedFarmId) : null;
+    gardenListRef.value?.refreshFarmList?.();
 });
 
 const store = useStore();
@@ -271,10 +297,9 @@ const handleCardClick = () => {
 .monitor-index {
     width: 100%;
     height: 100%;
-    padding: 13px 10px;
+    // padding: 13px 10px;
     box-sizing: border-box;
-    background: linear-gradient(180deg, #f9f9f9 0%, #f0f8ff 31.47%, #f9f9f9 46.81%, #f9f9f9 69.38%, #f9f9f9 100%);
-
+    background: linear-gradient(180deg, #2199F8 6%, #F5F5F5 19%, #F5F5F5 73%, #F5F5F5 100%);
     .weather-mask {
         position: fixed;
         top: 0;
@@ -325,22 +350,27 @@ const handleCardClick = () => {
     .example-img {
         width: 100%;
         height: 100%;
-        object-fit: contain;
+        object-fit: inherit;
     }
 
     .weather-info {
         width: calc(100% - 20px);
         position: absolute;
+        top: 10px;
+        left: 10px;
         z-index: 12;
     }
 
     .archives-time-line {
         position: relative;
-        margin-top: 96px;
+        padding: 150px 12px 12px 12px;
         height: calc(100% - 90px);
         display: flex;
         flex-direction: column;
         min-height: 0;
+        &.no-top {
+            padding: 96px 12px 12px 12px;
+        }
 
         .archives-time-line-header {
             flex-shrink: 0;