Просмотр исходного кода

fix:修改作物档案页面逻辑和UI

wangsisi 2 дней назад
Родитель
Сommit
abc38796dd

+ 192 - 112
src/components/pageComponents/ArchivesFarmTimeLine.vue

@@ -1,19 +1,27 @@
 <template>
     <div class="timeline-container" ref="timelineContainerRef">
         <div class="timeline-list" ref="timelineListRef">
-            <div class="timeline-middle-line"></div>
-            <div
-                v-for="(t, tIdx) in solarTerms"
-                :key="`term-${uniqueTimestamp}-${tIdx}`"
-                class="timeline-term"
-                :style="getTermStyle(t, tIdx)"
-            >
-                <span class="term-name">{{ t.displayName }}</span>
-                <!-- <span class="term-date">01-05</span> -->
-            </div>
-            <div v-for="(p, idx) in phenologyList" :key="`phenology-${uniqueTimestamp}-${idx}`" class="phenology-bar">
-                <div 
-                    class="phenology-title" 
+            <empty
+                v-if="isEmpty"
+                image="https://birdseye-img.sysuimars.com/birdseye-look-mini/custom-empty-image.png"
+                image-size="80"
+                description="暂无数据"
+                class="empty-state"
+            />
+            <template v-else>
+                <div class="timeline-middle-line"></div>
+                <div
+                    v-for="(t, tIdx) in solarTerms"
+                    :key="`term-${uniqueTimestamp}-${tIdx}`"
+                    class="timeline-term"
+                    :style="getTermStyle(t, tIdx)"
+                >
+                    <span class="term-name">{{ t.displayName }}</span>
+                    <span class="term-date">{{ formatDate(t.createDate) }}</span>
+                </div>
+                <div v-for="(p, idx) in phenologyList" :key="`phenology-${uniqueTimestamp}-${idx}`" class="phenology-bar">
+                <div
+                    class="phenology-title"
                     :class="{ 'phenology-red': !shouldShowBlue(p), 'phenology-blue': shouldShowBlue(p) }"
                     v-if="p.reproductiveList[0]?.phenologyName === getNextPhenologyName(idx, 0)"
                 >
@@ -31,30 +39,36 @@
                             class="arrange-card"
                             :class="[
                                 getArrangeStatusClass(fw),
-                                { 'last-card': aIdx === r.farmWorkArrangeList.length - 1 && rIdx !== r.farmWorkArrangeList.length - 1 },
+                                {
+                                    'last-card':
+                                        aIdx === r.farmWorkArrangeList.length - 1 &&
+                                        rIdx !== r.farmWorkArrangeList.length - 1,
+                                },
                                 // 右侧农事卡片跟随物候期颜色:未来节气对应的农事卡片置灰
-                                { 'future-card': !shouldShowBlue(p) }
-                            ]"
+                                { 'future-card': !shouldShowBlue(p) },
+                            ]"        
                             @click="handleRowClick(fw)"
                         >
                             <div class="card-content">
                                 <div class="card-left">
                                     <div class="left-info">
                                         <div class="left-date">{{ formatDate(fw.createTime) }}</div>
-                                        <span class="text">上传者:无人机</span>
+                                        <div class="text van-ellipsis" v-if="fw?.sourceType === 6">上传者:{{ fw.sourceDataJson.userName }}</div>
+                                        <div class="text green van-ellipsis" v-if="fw?.sourceType === 7">执行者:{{ fw.sourceDataJson.executorName }}</div>
                                     </div>
-                                    <div class="title-text">{{ fw.title }}</div>
+                                    <div class="title-text van-ellipsis">{{ fw.title }}</div>
                                 </div>
-                                <div class="card-right">
-                                    <img src="@/assets/img/home/farm.png" alt="">
-                                    <div class="num">2</div>
+                                <div class="card-right" v-if="fw.sourceDataJson" @click="handleImageClick(fw)">
+                                    <img src="@/assets/img/home/farm.png" alt="" />
+                                    <div class="num" v-if="fw?.sourceDataJson?.imageIds">{{ fw?.sourceDataJson?.imageIds.length || 0 }}</div>
+                                    <!-- <div class="num" v-if="fw?.sourceDataJson?.imageIds">{{ fw?.sourceDataJson?.imageIds.length || 0 }}</div> -->
                                 </div>
                             </div>
                         </div>
                     </div>
                     <template v-if="r.name === r.phenologyName">
-                        <div 
-                            class="phenology-name single" 
+                        <div
+                            class="phenology-name single"
                             :class="{ 'phenology-red': !shouldShowBlue(p), 'phenology-blue': shouldShowBlue(p) }"
                             :style="r.phenologyName === getNextPhenologyName(idx, rIdx) ? 'padding: 6px 0;' : ''"
                         >
@@ -63,22 +77,22 @@
                     </template>
                     <template v-else>
                         <template v-if="r.phenologyName === getNextPhenologyName(idx, rIdx)">
-                            <div 
-                                class="phenology-name" 
+                            <div
+                                class="phenology-name"
                                 :class="{ 'text-red': !shouldShowBlue(p), 'text-blue': shouldShowBlue(p) }"
                             >
                                 {{ r.name }}
                             </div>
                         </template>
                         <template v-else>
-                            <div 
-                                class="phenology-name" 
+                            <div
+                                class="phenology-name"
                                 :class="{ 'text-red': !shouldShowBlue(p), 'text-blue': shouldShowBlue(p) }"
                             >
                                 {{ r.name }}
                             </div>
-                            <div 
-                                class="phenology-name mr" 
+                            <div
+                                class="phenology-name mr"
                                 :class="{ 'phenology-red': !shouldShowBlue(p), 'phenology-blue': shouldShowBlue(p) }"
                             >
                                 {{ r.phenologyName }}
@@ -87,17 +101,21 @@
                     </template>
                 </div>
             </div>
+            </template>
         </div>
     </div>
-    <!-- 互动设置弹窗 -->
-    <interact-popup ref="interactPopupRef" @handleSaveSuccess="updateFarmWorkPlan"></interact-popup>
+    <!-- 图片弹窗 -->
+    <popup v-model:show="showImagePopup" closeable round class="image-popup" z-index="9999" teleport="body">
+        <div class="popup-content">
+            <p>图片详情</p>
+        </div>
+    </popup>
 </template>
 
 <script setup>
 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";
+import { Empty, Popup } from "vant";
 
 const props = defineProps({
     // 农场 ID,用于请求农事规划数据
@@ -152,11 +170,15 @@ const timelineListHeight = ref(0);
 const uniqueTimestamp = ref(Date.now());
 // ResizeObserver 实例,用于监听高度变化
 let resizeObserver = null;
+// 标记是否为空数据
+const isEmpty = ref(false);
+// 控制图片弹窗显示/隐藏
+const showImagePopup = ref(false);
 
 // 获取当前季节
 const getCurrentSeason = () => {
     const month = new Date().getMonth() + 1; // 1-12
-    if (month >= 3 && month <= 5) {
+    if (month >= 1 && month <= 5) {
         return "spring"; // 春季:3-5月
     } else if (month >= 6 && month <= 8) {
         return "summer"; // 夏季:6-8月
@@ -216,28 +238,38 @@ const batchValidatePesticideFertilizerQuotes = (ids, items) => {
         .catch(() => {});
 };
 
+// 点击图片
+const handleImageClick = (fw) => {
+    console.log(fw,'fw');
+    showImagePopup.value = true;
+}
+
 // 获取下一个reproductive-item的phenologyName
 const getNextPhenologyName = (currentPhenologyIdx, currentReproductiveIdx) => {
     const currentPhenology = phenologyList.value[currentPhenologyIdx];
     if (!currentPhenology || !Array.isArray(currentPhenology.reproductiveList)) {
         return null;
     }
-    
+
     // 如果当前reproductive-item不是最后一个,获取同一个物候期的下一个
     if (currentReproductiveIdx < currentPhenology.reproductiveList.length - 1) {
         const nextReproductive = currentPhenology.reproductiveList[currentReproductiveIdx + 1];
         return nextReproductive?.phenologyName || null;
     }
-    
+
     // 如果当前reproductive-item是最后一个,获取下一个物候期的第一个reproductive-item
     if (currentPhenologyIdx < phenologyList.value.length - 1) {
         const nextPhenology = phenologyList.value[currentPhenologyIdx + 1];
-        if (nextPhenology && Array.isArray(nextPhenology.reproductiveList) && nextPhenology.reproductiveList.length > 0) {
+        if (
+            nextPhenology &&
+            Array.isArray(nextPhenology.reproductiveList) &&
+            nextPhenology.reproductiveList.length > 0
+        ) {
             const firstReproductive = nextPhenology.reproductiveList[0];
             return firstReproductive?.phenologyName || null;
         }
     }
-    
+
     return null;
 };
 
@@ -391,23 +423,15 @@ const handleRowClick = (item) => {
     // 记录当前页面滚动位置
     if (timelineContainerRef.value) {
         const scrollTop = timelineContainerRef.value.scrollTop || 0;
-        sessionStorage.setItem('timelineScrollTop', scrollTop.toString());
+        sessionStorage.setItem("timelineScrollTop", scrollTop.toString());
     }
-    
+
     // item.isEdit = shouldShowIncompleteStatus(item.farmWorkId);
     item.invalidIds = invalidIds.value;
     item.invalidArr = invalidArr.value;
     emits("row-click", item);
 };
 
-const interactPopupRef = ref(null);
-const handleEdit = (item) => {
-    if (props.disableClick) return;
-    if (interactPopupRef.value) {
-        interactPopupRef.value.showPopup(item);
-    }
-};
-
 // 获取农事规划数据
 const getFarmWorkPlan = () => {
     if (!props.farmId) return;
@@ -415,6 +439,8 @@ const getFarmWorkPlan = () => {
     uniqueTimestamp.value = Date.now();
     // 重置测量高度,等待重新测量
     timelineListHeight.value = 0;
+    // 重置空数据状态
+    isEmpty.value = false;
     let savedScrollTop = 0;
     if (!isInitialLoad.value && timelineContainerRef.value) {
         savedScrollTop = timelineContainerRef.value.scrollTop || 0;
@@ -446,6 +472,7 @@ const getFarmWorkPlan = () => {
                                     const farmWorkArrangeList = Array.isArray(r.broadcastList)
                                         ? r.broadcastList.map((fw) => ({
                                               ...fw,
+                                              sourceDataJson: fw.sourceData && JSON.parse(fw.sourceData),
                                               containerSpaceTimeId: it.containerSpaceTimeId,
                                           }))
                                         : [];
@@ -505,7 +532,7 @@ const getFarmWorkPlan = () => {
                                     }, 200);
                                 } else {
                                     // 尝试恢复之前保存的滚动位置
-                                    const savedScrollTopFromStorage = sessionStorage.getItem('timelineScrollTop');
+                                    const savedScrollTopFromStorage = sessionStorage.getItem("timelineScrollTop");
                                     if (savedScrollTopFromStorage) {
                                         // 等待 DOM 完全渲染后再恢复滚动位置
                                         nextTick(() => {
@@ -514,7 +541,7 @@ const getFarmWorkPlan = () => {
                                                     const scrollTop = Number(savedScrollTopFromStorage);
                                                     timelineContainerRef.value.scrollTop = scrollTop;
                                                     // 恢复后清除保存的位置,避免下次误恢复
-                                                    sessionStorage.removeItem('timelineScrollTop');
+                                                    sessionStorage.removeItem("timelineScrollTop");
                                                 }
                                             });
                                         });
@@ -549,17 +576,34 @@ const getFarmWorkPlan = () => {
                 if (farmWorkIds.length > 0) {
                     batchValidatePesticideFertilizerQuotes(farmWorkIds, farmWorks);
                 }
+                
+                // 判断是否为空数据:没有节气或没有物候期数据
+                if (solarTerms.value.length === 0 && phenologyList.value.length === 0) {
+                    isEmpty.value = true;
+                } else {
+                    isEmpty.value = false;
+                }
+            } else {
+                // 接口返回错误码,显示暂无数据
+                isEmpty.value = true;
+                solarTerms.value = [];
+                phenologyList.value = [];
             }
         })
         .catch((error) => {
             console.error("获取农事规划数据失败:", error);
             ElMessage.error("获取农事规划数据失败");
+            // 接口报错,显示暂无数据
+            isEmpty.value = true;
+            solarTerms.value = [];
+            phenologyList.value = [];
         });
 };
 
 const updateFarmWorkPlan = () => {
     solarTerms.value = [];
     phenologyList.value = [];
+    isEmpty.value = false;
     getFarmWorkPlan();
 };
 
@@ -577,7 +621,7 @@ watch(
     () => props.schemeId,
     (val) => {
         // if (val) {
-            updateFarmWorkPlan();
+        updateFarmWorkPlan();
         // }
     }
 );
@@ -595,12 +639,12 @@ const formatDate = (dateStr) => {
 // 获取下一个即将到来的节气(当前节气)的 progress
 const getNextTermProgress = () => {
     if (!solarTerms.value || solarTerms.value.length === 0) return Infinity;
-    
+
     const now = new Date();
     now.setHours(0, 0, 0, 0);
-    
+
     let nextTermProgress = Infinity;
-    
+
     // 找到当前日期之后的下一个节气(当前节气)
     solarTerms.value.forEach((term) => {
         const termDate = safeParseDate(term.createDate);
@@ -616,7 +660,7 @@ const getNextTermProgress = () => {
             }
         }
     });
-    
+
     // 如果没有找到未来的节气,说明所有节气都已过,返回 Infinity(所有物候期都显示蓝色)
     return nextTermProgress === Infinity ? Infinity : nextTermProgress;
 };
@@ -624,9 +668,9 @@ const getNextTermProgress = () => {
 // 根据物候期的 progress 判断它所属节气的 progress
 const getPhenologyTermProgress = (phenologyProgress) => {
     if (!solarTerms.value || solarTerms.value.length === 0) return -1;
-    
+
     const progress = Number(phenologyProgress) || 0;
-    
+
     // 找到物候期所属的节气(progress 最接近且小于等于的节气)
     let matchedTermProgress = -1;
     solarTerms.value.forEach((term) => {
@@ -635,13 +679,13 @@ const getPhenologyTermProgress = (phenologyProgress) => {
             matchedTermProgress = termProgress;
         }
     });
-    
+
     // 如果物候期的 progress 小于所有节气,返回第一个节气的 progress
     if (matchedTermProgress === -1 && solarTerms.value.length > 0) {
         const firstTermProgress = Number(solarTerms.value[0].progress) || 0;
         return firstTermProgress;
     }
-    
+
     return matchedTermProgress;
 };
 
@@ -649,16 +693,16 @@ const getPhenologyTermProgress = (phenologyProgress) => {
 const shouldShowBlue = (phenology) => {
     // 获取下一个即将到来的节气(当前节气)的 progress
     const nextTermProgress = getNextTermProgress();
-    
+
     // 如果所有节气都已过(nextTermProgress === Infinity),所有物候期都显示蓝色
     if (nextTermProgress === Infinity) {
         return true;
     }
-    
+
     // 根据物候期的 progress 判断它属于哪个节气
     const phenologyProgress = Math.min(Number(phenology?.progress) || 0, Number(phenology?.progress2) || 0);
     const phenologyTermProgress = getPhenologyTermProgress(phenologyProgress);
-    
+
     // 找到下一个节气的完整信息,用于判断物候期是否属于当前节气
     let nextTerm = null;
     solarTerms.value.forEach((term) => {
@@ -667,20 +711,20 @@ const shouldShowBlue = (phenology) => {
             nextTerm = term;
         }
     });
-    
+
     // 如果物候期所属的节气的 progress < 下一个节气的 progress,显示蓝色
     // 如果物候期所属的节气的 progress === 下一个节气的 progress,也显示蓝色(当前节气)
     // 也就是说,只有属于当前节气或之前节气的物候期才显示蓝色
     if (phenologyTermProgress === -1) {
         return false;
     }
-    
+
     // 如果物候期正好属于下一个节气,需要判断它的 progress 是否在下一个节气的范围内
     if (phenologyTermProgress === nextTermProgress && nextTerm) {
         // 如果物候期的 progress 小于等于下一个节气的 progress,说明它属于当前节气,显示蓝色
         return phenologyProgress <= nextTermProgress;
     }
-    
+
     // 如果物候期所属的节气的 progress < 下一个节气的 progress,显示蓝色
     return phenologyTermProgress < nextTermProgress;
 };
@@ -767,7 +811,7 @@ watch(
         justify-content: center;
         box-sizing: border-box;
         position: relative;
-        .phenology-title{
+        .phenology-title {
             width: 18px;
             height: 98.5%;
             color: #fff;
@@ -782,7 +826,7 @@ watch(
                 background: #2199f8;
             }
             &.phenology-red {
-                background: #F1F1F1;
+                background: #f1f1f1;
                 color: #808080;
             }
         }
@@ -805,10 +849,10 @@ watch(
                 padding: 4px 0;
                 font-size: 12px;
                 box-sizing: border-box;
-                &.mr{
+                &.mr {
                     margin-right: 3px;
                 }
-                &.single{
+                &.single {
                     width: 39px;
                     line-height: 39px;
                 }
@@ -816,20 +860,20 @@ watch(
                     background: #2199f8;
                 }
                 &.phenology-red {
-                    background: #F1F1F1;
+                    background: #f1f1f1;
                     color: #808080;
                 }
-                &.text-blue{
+                &.text-blue {
                     background: rgba(33, 153, 248, 0.15);
                     color: #2199f8;
                     border: 1px solid #2199f8;
                     line-height: 16px;
                     box-sizing: border-box;
                 }
-                &.text-red{
-                    background:rgba(128, 128, 128,.15);
+                &.text-red {
+                    background: rgba(128, 128, 128, 0.15);
                     color: #808080;
-                    border: 1px solid rgba(128, 128, 128,.35);
+                    border: 1px solid rgba(128, 128, 128, 0.35);
                     line-height: 16px;
                     box-sizing: border-box;
                 }
@@ -840,6 +884,7 @@ watch(
                 min-width: calc(100vw - 111px);
                 gap: 5px;
                 letter-spacing: 0px;
+                min-height: 90px;
                 .arrange-card {
                     width: 95%;
                     border: 0.5px solid #2199f8;
@@ -850,9 +895,9 @@ watch(
                     padding: 8px 15px 8px 10px;
                     writing-mode: horizontal-tb;
                     margin-bottom: 10px;
-                    &.last-card{
-                        // margin-bottom: 0;
-                    }
+                    // &.last-card {
+                    //     margin-bottom: 0;
+                    // }
                     .card-content {
                         color: #242424;
                         display: flex;
@@ -860,24 +905,32 @@ watch(
                         align-items: center;
                         font-size: 14px;
                         .card-left {
-                            .left-info{
+                            width: calc(100% - 45px);
+                            .left-info {
                                 display: flex;
                                 align-items: center;
                                 gap: 5px;
-                                .left-date{
+                                .left-date { 
                                     color: #fff;
                                     background: #2199f8;
                                     padding: 1px 5px;
                                     border-radius: 2px;
                                     font-size: 12px;
                                 }
-                                .text{
+                                .text {
                                     font-size: 12px;
                                     color: rgba(33, 153, 248, 0.5);
+                                    width: calc(100% - 50px);
+                                    text-align: left;
+                                    &.green {
+                                        color: rgba(82, 192, 60, 0.5);
+                                    }
                                 }
                             }
-                            .title-text{
+                            .title-text {
                                 margin-top: 2px;
+                                width: 99%;
+                                text-align: left;
                             }
                         }
                         .card-right {
@@ -924,54 +977,60 @@ watch(
                 .arrange-card.future-card .card-content {
                     color: #808080;
                 }
+                .arrange-card.status-normal {
+                    border-color: #2199f8;
+                    &::before {
+                        border-right-color: #2199f8;
+                    }
+                }
                 .arrange-card.status-warning {
-                    border-color: #F67D7D;
-                    .card-left{
-                        .left-date{
-                            background: #F67D7D;
+                    border-color: #f67d7d;
+                    .card-left {
+                        .left-info {
+                            .left-date {
+                                background: #f67d7d;
+                            }
                         }
                     }
-                    .card-right{
-                        .num{
-                            background: #F67D7D;
+                    .card-right {
+                        .num {
+                            background: #f67d7d;
                         }
                     }
                     &::before {
-                        border-right-color: #F67D7D;
+                        border-right-color: #f67d7d;
                     }
                 }
                 .arrange-card.status-complete {
-                    border-color: #52C03C;
-                    .card-left{
-                        .left-date{
-                            background: #52C03C;
+                    border-color: #52c03c;
+                    .card-left {
+                        .left-info {
+                            .left-date {
+                                background: #52c03c;
+                            }
                         }
                     }
-                    .card-right{
-                        .num{
-                            background: #52C03C;
+                    .card-right {
+                        .num {
+                            background: #52c03c;
                         }
                     }
                     &::before {
-                        border-right-color: #52C03C;
-                    }
-                }
-                .arrange-card.status-normal {
-                    border-color: #2199f8;
-                    &::before {
-                        border-right-color: #2199f8;
+                        border-right-color: #52c03c;
                     }
                 }
                 // 未来节气对应的农事卡片:跟随左侧物候期的“未开始”灰色样式
                 .arrange-card.future-card {
-                    border-color: #E4E4E4;
-                    .card-left{
-                        .left-date{
-                            background: #E4E4E4 !important;
+                    border-color: #e4e4e4;
+                    .card-left {
+                        .left-info {
+                            .left-date {
+                                background: #e4e4e4;
+                            }
                         }
                     }
                     &::before {
-                        border-right-color: #E4E4E4;
+                        border-right-color: #e4e4e4;
                     }
                 }
             }
@@ -994,14 +1053,35 @@ watch(
         .term-name {
             display: inline-block;
             width: 100%;
-            min-height: 28px;
-            line-height: 28px;
+            min-height: 32px;
+            line-height: 26px;
             background: #fff;
             font-size: 12px;
+            margin-top: -4px;
         }
         .term-date {
-            font-size: 12px;
-            color: #242424;
+            font-size: 10px;
+            margin: -11px 0 0 -6px;
+        }
+    }
+    .empty-state {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        min-height: 200px;
+        width: 100%;
+    }
+}
+</style>
+
+<style lang="scss" scoped>
+.image-popup {
+    width: 100%;
+    .popup-content {
+        p {
+            margin: 0;
+            font-size: 16px;
+            color: #333;
         }
     }
 }

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

@@ -19,7 +19,7 @@
                 <el-date-picker style="width: 110px" v-model="date" type="year" placeholder="全部日期" />
             </div>
             <div class="archives-time-line-content">
-                <archives-farm-time-line :farmId="766"></archives-farm-time-line>
+                <archives-farm-time-line :farmId="gardenId"></archives-farm-time-line>
             </div>
         </div>
     </div>
@@ -304,7 +304,6 @@ onMounted(() => {
 });
 
 const changeGarden = ({ id }) => {
-    localStorage.setItem("isGarden", true);
     gardenId.value = id;
     // 更新 store 中的状态
     store.commit("home/SET_GARDEN_ID", id);