Преглед изворни кода

feat:修改农事规划逻辑bug

wangsisi пре 1 недеља
родитељ
комит
f5d210f777

+ 5 - 0
src/api/modules/home.js

@@ -98,4 +98,9 @@ module.exports = {
         url: config.base_dev_url + "container_farm_work_arrange/answerQuestion",
         type: "post",
     },
+    //判断是否存在可用方案
+    existsEnabledScheme: {
+        url: config.base_dev_url + "container_farm_work_scheme/existsEnabledScheme",
+        type: "get",
+    },
 }

+ 100 - 53
src/components/pageComponents/FarmWorkPlanTimeline.vue

@@ -56,7 +56,7 @@
 </template>
 
 <script setup>
-import { ref, nextTick, watch } from "vue";
+import { ref, nextTick, watch, onMounted, onUnmounted } from "vue";
 import interactPopup from "@/components/popup/interactPopup.vue";
 import { ElMessage } from "element-plus";
 import { WarningFilled } from "@element-plus/icons-vue";
@@ -112,6 +112,8 @@ const isInitialLoad = ref(true);
 const timelineListHeight = ref(0);
 // 生成唯一的时间戳,用于确保key的唯一性
 const uniqueTimestamp = ref(Date.now());
+// ResizeObserver 实例,用于监听高度变化
+let resizeObserver = null;
 
 // 获取当前季节
 const getCurrentSeason = () => {
@@ -251,43 +253,23 @@ const calculatePhenologyPositions = () => {
 const calculateTotalHeightByFarmWorks = () => {
     const { totalHeight } = calculatePhenologyPositions();
 
-    // 计算最后一个物候期的底部位置
-    let lastPhenologyBottom = 0;
-    if (phenologyList.value && phenologyList.value.length > 0) {
-        const sortedPhenologyList = [...phenologyList.value].sort((a, b) => {
-            const aProgress = Math.min(Number(a?.progress) || 0, Number(a?.progress2) || 0);
-            const bProgress = Math.min(Number(b?.progress) || 0, Number(b?.progress2) || 0);
-            return aProgress - bProgress;
-        });
-
-        let currentTop = 10; // 起始位置
-        sortedPhenologyList.forEach((phenology) => {
-            const height = getPhenologyRequiredHeight(phenology);
-            currentTop += height;
-        });
-        lastPhenologyBottom = currentTop; // 最后一个物候期的底部位置
-    }
-
-    // 直接使用最后一个物候期的底部位置作为总高度,不添加额外余量
-    // 在getTermStyle中,我们已经调整了最后一个节气的top位置(total - 46)
-    // 这样最后一个节气的底部(total - 46 + 46 = total)就能与物候期底部对齐
-    if (lastPhenologyBottom > 0) {
+    // 如果有物候期数据,直接使用计算出的总高度
+    // totalHeight 已经包含了从 10 开始的起始位置和所有物候期的高度
+    if (totalHeight > 10) {
+        // 确保总高度至少能容纳所有节气(每个节气至少50px)
         const baseHeight = (solarTerms.value?.length || 0) * 50;
-        // 总高度 = 最后一个物候期的底部位置,精确匹配,不添加额外余量
-        return Math.max(lastPhenologyBottom, totalHeight, baseHeight);
+        // 返回物候期总高度和基础高度的较大值,确保节气能正常显示
+        return Math.max(totalHeight, baseHeight);
     }
 
-    // 基础高度:每个节气至少需要一定高度,确保节气标签能显示
+    // 如果没有物候期数据,返回基础高度
     const baseHeight = (solarTerms.value?.length || 0) * 50;
-
-    // 返回物候期总高度和基础高度的较大值,不添加最小高度限制
-    return Math.max(totalHeight, baseHeight);
+    return baseHeight || 100; // 至少返回100px,避免为0
 };
 
 const getTermStyle = (t, index) => {
     // 优先使用实际测量的timeline-list高度,如果没有测量到则使用计算值作为后备
     const totalHeight = timelineListHeight.value > 0 ? timelineListHeight.value : calculateTotalHeightByFarmWorks();
-
     // 获取节气总数
     const termCount = solarTerms.value?.length || 1;
 
@@ -423,34 +405,45 @@ const getFarmWorkPlan = () => {
                       })
                     : [];
 
+                // 使用多次 nextTick 和 requestAnimationFrame 确保DOM完全渲染
                 nextTick(() => {
-                    // 测量timeline-list的实际渲染高度
-                    if (timelineListRef.value) {
-                        requestAnimationFrame(() => {
-                            const height = timelineListRef.value.offsetHeight || timelineListRef.value.clientHeight;
-                            if (height > 0) {
-                                timelineListHeight.value = height;
-
-                                // 如果是首次加载,滚动到当前季节对应的节气
+                    requestAnimationFrame(() => {
+                        nextTick(() => {
+                            requestAnimationFrame(() => {
+                                // 测量timeline-list的实际渲染高度
+                                if (timelineListRef.value) {
+                                    const height = timelineListRef.value.offsetHeight || timelineListRef.value.clientHeight;
+                                    if (height > 0) {
+                                        timelineListHeight.value = height;
+
+                                        // 如果是首次加载,滚动到当前季节对应的节气
+                                        if (isInitialLoad.value) {
+                                            const currentSeason = getCurrentSeason();
+                                            handleSeasonClick(currentSeason);
+                                            isInitialLoad.value = false;
+                                        }
+                                    }
+                                }
+
                                 if (isInitialLoad.value) {
-                                    const currentSeason = getCurrentSeason();
-                                    handleSeasonClick(currentSeason);
-                                    isInitialLoad.value = false;
+                                    // 如果测量失败,延迟一下再尝试滚动
+                                    setTimeout(() => {
+                                        if (timelineListRef.value) {
+                                            const height = timelineListRef.value.offsetHeight || timelineListRef.value.clientHeight;
+                                            if (height > 0) {
+                                                timelineListHeight.value = height;
+                                            }
+                                        }
+                                        const currentSeason = getCurrentSeason();
+                                        handleSeasonClick(currentSeason);
+                                        isInitialLoad.value = false;
+                                    }, 200);
+                                } else if (timelineContainerRef.value && savedScrollTop > 0) {
+                                    timelineContainerRef.value.scrollTop = savedScrollTop;
                                 }
-                            }
+                            });
                         });
-                    }
-
-                    if (isInitialLoad.value) {
-                        // 如果测量失败,延迟一下再尝试滚动
-                        setTimeout(() => {
-                            const currentSeason = getCurrentSeason();
-                            handleSeasonClick(currentSeason);
-                            isInitialLoad.value = false;
-                        }, 100);
-                    } else if (timelineContainerRef.value && savedScrollTop > 0) {
-                        timelineContainerRef.value.scrollTop = savedScrollTop;
-                    }
+                    });
                 });
 
                 // 收集所有farmWorkId
@@ -509,6 +502,60 @@ watch(
         }
     }
 );
+
+// 使用 ResizeObserver 监听高度变化,确保在DOM完全渲染后获取准确高度
+const setupResizeObserver = () => {
+    if (!timelineListRef.value || typeof ResizeObserver === 'undefined') {
+        return;
+    }
+
+    // 如果已经存在观察者,先断开
+    if (resizeObserver) {
+        resizeObserver.disconnect();
+    }
+
+    // 创建新的观察者
+    resizeObserver = new ResizeObserver((entries) => {
+        for (const entry of entries) {
+            const height = entry.contentRect.height;
+            if (height > 0 && height !== timelineListHeight.value) {
+                timelineListHeight.value = height;
+            }
+        }
+    });
+
+    // 开始观察
+    resizeObserver.observe(timelineListRef.value);
+};
+
+// 组件挂载后设置 ResizeObserver
+onMounted(() => {
+    nextTick(() => {
+        requestAnimationFrame(() => {
+            setupResizeObserver();
+        });
+    });
+});
+
+// 组件卸载前清理 ResizeObserver
+onUnmounted(() => {
+    if (resizeObserver) {
+        resizeObserver.disconnect();
+        resizeObserver = null;
+    }
+});
+
+// 在数据更新后重新设置 ResizeObserver
+watch(
+    () => phenologyList.value.length,
+    () => {
+        nextTick(() => {
+            requestAnimationFrame(() => {
+                setupResizeObserver();
+            });
+        });
+    }
+);
 </script>
 
 <style scoped lang="scss">

+ 14 - 1
src/views/old_mini/create_farm/index.vue

@@ -735,7 +735,14 @@ function getSpecieList() {
     });
 }
 
-function changeSpecie(v) {
+async function changeSpecie(v) {
+    const data = await checkExistsEnabledScheme(v.defaultContainerId);
+    if (!data) {
+        ElMessage.warning("该品类暂无可用方案,请选择其他品类");
+        ruleForm.speciesItem = "";
+        fruitsList.value = [];
+        return;
+    }
     getFruitsTypeItemList(v.id);
     // 清空品种选择
     ruleForm.typeId = "";
@@ -745,6 +752,12 @@ function changeSpecie(v) {
     }
 }
 
+//判断是否存在可用方案
+async function checkExistsEnabledScheme(containerId) {
+    const { data } = await VE_API.home.existsEnabledScheme({containerId});
+    return data;
+}
+
 const fruitsList = ref([]);
 function getFruitsTypeItemList(parentId) {
     VE_API.farm.fruitsTypeItemList({ parentId }).then(({ data }) => {

+ 1 - 1
src/views/old_mini/mine/index.vue

@@ -70,7 +70,7 @@ const router = useRouter();
 
 const showTipPopup = ref(false);
 const handleBtn = () => {
-    router.push("/plan?pageType=plant");
+    router.push("/plan?pageType=plant&headerTitle=请设置您的种植方案");
 };
 
 // 0: 农户, 1: 专家, 2:农资农服

+ 2 - 4
src/views/old_mini/modify_work/reviewWork.vue

@@ -60,14 +60,12 @@
                             <img class="subject-img" src="@/assets/img/home/nz.png" alt="" />
                             <div class="subject-tag">
                                 {{ workItem.serviceMain }}
-                                <el-icon class="right-icon" size="10"><ArrowRight /></el-icon>
                             </div>
                         </div>
                         <div class="subject-item">
                             <img class="subject-img" :src="workItem.expertIcon" alt="" />
                             <div class="subject-tag">
-                                {{ workItem.expertName }}
-                                <el-icon class="right-icon" size="10"><ArrowRight /></el-icon>
+                                {{ workItem.executeName }}
                             </div>
                         </div>
                     </div>
@@ -777,7 +775,7 @@ const handleUpload = ({ imgArr }) => {
                     }
                     .subject-tag {
                         font-size: 12px;
-                        padding: 2px 3px 3px 8px;
+                        padding: 2px 8px;
                         background: #e0efff;
                         color: #2199f8;
                         border-radius: 4px;

+ 44 - 19
src/views/old_mini/monitor/subPages/plan.vue

@@ -28,7 +28,7 @@
             <div class="tip-box">
                 <Highlight
                     :keywords="['关注农事/托管农事', '取消关注']"
-                    source-string="提示:关注农事/托管农事 会触发农情互动,并且为您推送农事,取消关注 会为您取消推送农事"
+                    source-string="提示:关注农事/托管农事 会触发农情互动,并且为您推送农事,取消关注 则不会为您推送任何与该农事相关的内容"
                 />
             </div>
             <div
@@ -36,7 +36,7 @@
                 :class="{
                     'timeline-container-plant-wrap': pageType == 'plant',
                     'timeline-container-no-permission-wrap': !hasPlanPermission,
-                    'no-default-plan-wrap': active !== tabs[0]?.id,
+                    'no-default-plan-wrap': active !== tabs[0]?.id && pageType == 'plant' && currentTab?.enabled == 0,
                 }"
             >
                 <farm-work-plan-timeline
@@ -50,9 +50,9 @@
                 />
             </div>
         </div>
-        <div class="custom-bottom-fixed-btns" :class="{ center: active === tabs[0]?.id }" v-has-permission="'农事规划'">
+        <div class="custom-bottom-fixed-btns" :class="{ center: (active === tabs[0]?.id && pageType == 'plant') }" v-has-permission="'农事规划'">
             <div class="bottom-btn-group-wrap">
-                <div class="bottom-btn-group">
+                <div class="bottom-btn-group" :class="{ 'justify-center': active === tabs[0]?.id && pageType == 'plant' }">
                     <div
                         class="bottom-btn secondary-btn"
                         @click="handlePhenologySetting"
@@ -66,9 +66,9 @@
                 </div>
                 <div class="bottom-btn primary-btn" @click="addNewTask" v-show="active !== tabs[0]?.id">新增农事</div>
             </div>
-            <template v-if="active !== tabs[0]?.id">
+            <template v-if="active !== tabs[0]?.id && pageType == 'plant' && currentTab?.enabled == 0">
                 <div class="bottom-btn-divider"></div>
-                <div class="bottom-btn primary-btn submit-btn">提交方案</div>
+                <div class="bottom-btn primary-btn submit-btn" @click="handleSubmitPlan">提交方案</div>
             </template>
         </div>
     </div>
@@ -182,7 +182,12 @@ const getSpecieList = () => {
     VE_API.farm.fetchSpecieList({ agriculturalId: userInfo?.agriculturalId }).then(({ data }) => {
         if (data && data.length) {
             options.value = data || [];
-            specieValue.value = data[0]?.defaultContainerId;
+            if(sessionStorage.getItem('specieValue')) {
+                specieValue.value = sessionStorage.getItem('specieValue');
+                sessionStorage.removeItem('specieValue');
+            } else {
+                specieValue.value = data[0]?.defaultContainerId;
+            }
             getListMySchemes("left");
         }
     });
@@ -197,14 +202,19 @@ const containerIdData = ref(null);
 const getListMySchemes = (type = "auto") => {
     VE_API.home.listMySchemes({ containerId: specieValue.value }).then(({ data }) => {
         tabs.value = data || [];
-        containerIdData.value = data[0]?.containerId;
-        if (type === "right") {
-            active.value = data[data.length - 1].id;
-        } else if (type === "left") {
-            active.value = data[0].id;
+        containerIdData.value = tabs.value[0]?.containerId;
+        if(sessionStorage.getItem('active')) {
+            active.value = sessionStorage.getItem('active');
+            sessionStorage.removeItem('active');
         } else {
-            currentTab.value = data.filter((item) => item.id === currentTab.value.id)[0];
-            copyPlanName.value = currentTab.value.name;
+            if (type === "right") {
+                active.value = data[data.length - 1].id;
+            } else if (type === "left") {
+                active.value = data[0].id;
+            } else {
+                currentTab.value = data.filter((item) => item.id === currentTab.value.id)[0];
+                copyPlanName.value = currentTab.value.name;
+            }
         }
         scrollType.value = type;
         getFarmWorkPlanForPhenology();
@@ -350,8 +360,19 @@ const handleConfirmCopyPlan = () => {
     }
 };
 
+const handleSubmitPlan = () => {
+    // showTipPopup.value = true;
+    console.log('ti')
+};
+
+const savePlanPageInfo = () => {
+    sessionStorage.setItem('specieValue', specieValue.value);
+    sessionStorage.setItem('active', active.value);
+};
+
 // 新增农事
 const addNewTask = () => {
+    savePlanPageInfo();
     router.push({
         path: "/add_work",
         query: {
@@ -373,6 +394,7 @@ const triggerFarmWork = () => {
 const curFarmObj = ref({});
 const handleRowClick = (item) => {
     curFarmObj.value = item;
+    savePlanPageInfo();
     router.push({
         path: "/modify",
         query: {
@@ -393,13 +415,11 @@ const handleRowClick = (item) => {
     height: 100vh;
     background: #f5f7fb;
     .plan-content {
-        padding: 12px 0;
         .plan-content-header {
             display: flex;
             align-items: center;
             gap: 12px;
-            margin-bottom: 10px;
-            margin-left: 12px;
+            margin: 10px 0 10px 12px;
             .select-item {
                 width: 82px;
                 ::v-deep {
@@ -424,13 +444,13 @@ const handleRowClick = (item) => {
             color: #444;
         }
         .timeline-wrap {
-            height: calc(100vh - 90px - 85px);
+            height: calc(100vh - 90px - 80px);
             padding: 0 12px;
             &.timeline-container-plant-wrap {
                 height: calc(100vh - 90px - 85px - 38px);
             }
             &.no-default-plan-wrap {
-                height: calc(100vh - 90px - 85px - 66px);
+                height: calc(100vh - 90px - 85px - 100px);
             }
             // 没有权限时,底部按钮不显示,高度增加 73px
             &.timeline-container-no-permission-wrap {
@@ -444,10 +464,15 @@ const handleRowClick = (item) => {
         .bottom-btn-group-wrap {
             display: flex;
             gap: 12px;
+            width: 100%;
             justify-content: space-between;
             .bottom-btn-group {
                 display: flex;
                 gap: 12px;
+                &.justify-center {
+                    justify-content: center;
+                    width: 100%;
+                }
             }
         }
         &.center {

+ 4 - 6
src/views/old_mini/plan/index.vue

@@ -71,9 +71,8 @@ onDeactivated(() => {
 const getListMySchemes = () => {
     VE_API.home.listMySchemes({containerId: route.query.containerId}).then(({ data }) => {
         if (data.length) {
-            tabs.value = data || [];
-            const index = data.findIndex((item) => item.containerId == route.query.containerId);
-            active.value = data[index].id;
+            tabs.value = data.filter((item) => item.enabled == 1) || [];
+            active.value = tabs.value[0].id;
             containerId.value = route.query.containerId;
         }
     });
@@ -181,8 +180,7 @@ const handleClickOverlay = () => {
     height: 100vh;
     background: #f5f7fb;
     .system-generated {
-        padding: 17px 10px 10px;
-        height: calc(100vh - 150px);
+        padding: 10px;
         .tip-box {
             display: flex;
             align-items: center;
@@ -201,7 +199,7 @@ const handleClickOverlay = () => {
             margin-bottom: 10px;
         }
         .timeline-wrap{
-            height: calc(100vh - 150px - 50px);
+            height: calc(100vh - 150px - 54px);
         }
     }
     .tabs-wrap {