Pārlūkot izejas kodu

feat:修改作物档案时间轴显示逻辑

wangsisi 2 nedēļas atpakaļ
vecāks
revīzija
e81229057a
1 mainītis faili ar 70 papildinājumiem un 12 dzēšanām
  1. 70 12
      src/components/pageComponents/ArchivesFarmTimeLine.vue

+ 70 - 12
src/components/pageComponents/ArchivesFarmTimeLine.vue

@@ -19,7 +19,7 @@
                     <span class="term-name">{{ formatDate(t.startDate) }}</span>
                 </div>
                 <div
-                    v-for="(p, idx) in phenologyList"
+                    v-for="(p, idx) in sortedPhenologyList"
                     :key="`phenology-${uniqueTimestamp}-${idx}`"
                     class="phenology-bar"
                 >
@@ -135,7 +135,7 @@
 </template>
 
 <script setup>
-import { ref, nextTick, watch, onMounted, onUnmounted } from "vue";
+import { ref, computed, nextTick, watch, onMounted, onUnmounted } from "vue";
 import { ElMessage } from "element-plus";
 import { Empty, Popup } from "vant";
 import { base_img_url2 } from "@/api/config";
@@ -184,6 +184,14 @@ const emits = defineEmits(["row-click"]);
 
 const solarTerms = ref([]);
 const phenologyList = ref([]);
+// 按 progress 排序的物候期列表,用于渲染(与 calculatePhenologyPositions 中的排序保持一致)
+const sortedPhenologyList = computed(() => {
+    return [...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;
+    });
+});
 // 由 phenologyList 每项的 startDate 生成,用于左侧时间轴展示(替代原 solarTerms 在此块的展示)
 const termDateList = ref([]);
 const timelineContainerRef = ref(null);
@@ -192,6 +200,8 @@ const timelineListRef = ref(null);
 const isInitialLoad = ref(true);
 // 存储timeline-list的实际渲染高度
 const timelineListHeight = ref(0);
+// 存储每个物候期的实际DOM位置(通过startDate作为key)
+const phenologyDomPositions = ref(new Map());
 // 生成唯一的时间戳,用于确保key的唯一性
 const uniqueTimestamp = ref(Date.now());
 // ResizeObserver 实例,用于监听高度变化
@@ -313,7 +323,7 @@ const handleImageClick = (fw) => {
 
 // 获取下一个reproductive-item的phenologyName
 const getNextPhenologyName = (currentPhenologyIdx, currentReproductiveIdx) => {
-    const currentPhenology = phenologyList.value[currentPhenologyIdx];
+    const currentPhenology = sortedPhenologyList.value[currentPhenologyIdx];
     if (!currentPhenology || !Array.isArray(currentPhenology.reproductiveList)) {
         return null;
     }
@@ -325,8 +335,8 @@ const getNextPhenologyName = (currentPhenologyIdx, currentReproductiveIdx) => {
     }
 
     // 如果当前reproductive-item是最后一个,获取下一个物候期的第一个reproductive-item
-    if (currentPhenologyIdx < phenologyList.value.length - 1) {
-        const nextPhenology = phenologyList.value[currentPhenologyIdx + 1];
+    if (currentPhenologyIdx < sortedPhenologyList.value.length - 1) {
+        const nextPhenology = sortedPhenologyList.value[currentPhenologyIdx + 1];
         if (
             nextPhenology &&
             Array.isArray(nextPhenology.reproductiveList) &&
@@ -421,24 +431,54 @@ const calculateTotalHeightByFarmWorks = () => {
     return baseHeight || 100; // 至少返回100px,避免为0
 };
 
+// 更新物候期的实际DOM位置
+const updatePhenologyDomPositions = () => {
+    if (!timelineListRef.value) return;
+    
+    phenologyDomPositions.value.clear();
+    const phenologyBars = timelineListRef.value.querySelectorAll('.phenology-bar');
+    
+    phenologyBars.forEach((bar, idx) => {
+        if (idx < sortedPhenologyList.value.length) {
+            const phenology = sortedPhenologyList.value[idx];
+            const startDate = phenology.startDate;
+            if (startDate) {
+                // 使用offsetTop获取相对于timeline-list的位置
+                const top = bar.offsetTop;
+                const height = bar.offsetHeight;
+                phenologyDomPositions.value.set(startDate, { top, height });
+            }
+        }
+    });
+};
+
 const getTermStyle = (t, index) => {
     // 优先使用实际测量的timeline-list高度,如果没有测量到则使用计算值作为后备
     const totalHeight = timelineListHeight.value > 0 ? timelineListHeight.value : calculateTotalHeightByFarmWorks();
     // 左侧时间轴条数(来自 termDateList,即物候期 startDate 数量)
     const termCount = termDateList.value?.length || 1;
 
-    // 等分高度:总高度 / 节气数量
-    const termHeight = totalHeight / termCount;
-
-    // 计算top位置:索引 * 每个节气的高度
-    const top = index * termHeight;
+    // 优先使用实际DOM位置
+    let top;
+    let termHeight;
+    const domPosition = phenologyDomPositions.value.get(t.startDate);
+    
+    if (domPosition) {
+        // 使用物候期的实际DOM位置
+        top = domPosition.top;
+        termHeight = domPosition.height;
+    } else {
+        // 后备方案:等分高度
+        termHeight = totalHeight / termCount;
+        top = index * termHeight;
+    }
 
     return {
         position: "absolute",
         top: `${top}px`,
         left: 0,
         width: "32px",
-        height: `${termHeight}px`, // 高度等分,使用实际测量的高度
+        height: `${termHeight}px`,
         display: "flex",
         alignItems: "center",
     };
@@ -622,6 +662,12 @@ const getFarmWorkPlan = () => {
                                         timelineListRef.value.offsetHeight || timelineListRef.value.clientHeight;
                                     if (height > 0) {
                                         timelineListHeight.value = height;
+                                        // 更新物候期的实际DOM位置(延迟一下确保DOM完全渲染)
+                                        nextTick(() => {
+                                            requestAnimationFrame(() => {
+                                                updatePhenologyDomPositions();
+                                            });
+                                        });
 
                                         // 如果是首次加载,滚动到当前季节对应的节气
                                         if (isInitialLoad.value) {
@@ -641,6 +687,12 @@ const getFarmWorkPlan = () => {
                                                 timelineListRef.value.clientHeight;
                                             if (height > 0) {
                                                 timelineListHeight.value = height;
+                                                // 更新物候期的实际DOM位置(延迟一下确保DOM完全渲染)
+                                                nextTick(() => {
+                                                    requestAnimationFrame(() => {
+                                                        updatePhenologyDomPositions();
+                                                    });
+                                                });
                                             }
                                         }
                                         const currentSeason = getCurrentSeason();
@@ -892,6 +944,10 @@ const setupResizeObserver = () => {
             const height = entry.contentRect.height;
             if (height > 0 && height !== timelineListHeight.value) {
                 timelineListHeight.value = height;
+                // 高度变化时,更新物候期的实际DOM位置
+                nextTick(() => {
+                    updatePhenologyDomPositions();
+                });
             }
         }
     });
@@ -924,6 +980,8 @@ watch(
         nextTick(() => {
             requestAnimationFrame(() => {
                 setupResizeObserver();
+                // 物候期列表变化时,更新DOM位置
+                updatePhenologyDomPositions();
             });
         });
     }
@@ -1198,7 +1256,7 @@ watch(
             display: inline-block;
             width: 100%;
             min-height: 20px;
-            line-height: 26px;
+            line-height: 20px;
             background: #fff;
             font-size: 12px;
         }