Pārlūkot izejas kodu

feat:修改农事记录页面

wangsisi 2 nedēļas atpakaļ
vecāks
revīzija
23f0d46903

+ 62 - 15
src/components/pageComponents/ArchivesFarmTimeLine.vue

@@ -53,7 +53,7 @@
                                 @click="handleRowClick(fw)"
                             >
                                 <div class="card-content">
-                                    <div class="card-left">
+                                    <div class="card-left" v-if="pageType === 'agri_plan'">
                                         <div class="left-info">
                                             <div class="left-date">{{ formatDate(fw.createTime) }}</div>
                                             <div class="text van-ellipsis" v-if="fw?.sourceType === 6">
@@ -65,6 +65,19 @@
                                         </div>
                                         <div class="title-text van-ellipsis">{{ fw.title }}</div>
                                     </div>
+                                    <div class="card-left agri-record-card" v-else>
+                                        <div class="left-info">
+                                            <div class="left-date">{{ formatDate(fw.createTime) }}</div>
+                                            <div class="text van-ellipsis">
+                                                <span class="text-name">梢期杀虫</span>
+                                                <span class="text-detail">详情</span>
+                                            </div>
+                                        </div>
+                                        <div class="title-text van-ellipsis" v-show="shouldShowBlue(p)">
+                                            <el-icon class="icon"><WarningFilled /></el-icon>
+                                            <span>未执行</span>
+                                        </div>
+                                    </div>
                                     <div
                                         class="card-right"
                                         v-if="fw.sourceDataJson && fw.sourceDataJson.resFilename && fw.sourceDataJson.resFilename.length > 0 || fw.sourceType === 7"
@@ -147,20 +160,11 @@ const props = defineProps({
         type: [String, Number],
         default: null,
     },
-    // 页面类型:种植方案 / 农事规划,用来控制高度样式
-    pageType: {
-        type: String,
-        default: "",
-    },
     // 是否禁用所有点击事件(用于只读展示)
     disableClick: {
         type: Boolean,
         default: false,
     },
-    containerId: {
-        type: [Number, String],
-        default: null,
-    },
     // 是否是标准农事
     isStandard: {
         type: Boolean,
@@ -171,6 +175,11 @@ const props = defineProps({
         type: [Number, String],
         default: null,
     },
+    // 类型:agri_record / agri_plan
+    pageType: {
+        type: String,
+        default: "agri_plan",
+    },
 });
 
 const farmWorkType = {
@@ -226,6 +235,10 @@ let resizeObserver = null;
 const isEmpty = ref(false);
 // 控制图片弹窗显示/隐藏
 const showImagePopup = ref(false);
+// 标记是否正在请求数据,防止重复请求
+const isRequesting = ref(false);
+// 记录上一次请求的 farmId,避免相同 farmId 重复请求
+const lastRequestedFarmId = ref(null);
 
 // 获取当前季节
 const getCurrentSeason = () => {
@@ -524,6 +537,11 @@ const handleRowClick = (item) => {
 // 获取农事规划数据
 const getFarmWorkPlan = () => {
     if (!props.farmId) return;
+    // 如果正在请求,或者 farmId 与上次请求的相同,直接返回,防止重复请求
+    if (isRequesting.value || lastRequestedFarmId.value === props.farmId) return;
+    // 设置请求标志和记录 farmId
+    isRequesting.value = true;
+    lastRequestedFarmId.value = props.farmId;
     // 更新时间戳,确保key变化,触发DOM重新渲染
     uniqueTimestamp.value = Date.now();
     // 重置测量高度,等待重新测量
@@ -732,6 +750,10 @@ const getFarmWorkPlan = () => {
             isEmpty.value = true;
             solarTerms.value = [];
             phenologyList.value = [];
+        })
+        .finally(() => {
+            // 请求完成,重置请求标志
+            isRequesting.value = false;
         });
 };
 
@@ -744,13 +766,18 @@ const updateFarmWorkPlan = () => {
 
 watch(
     () => props.farmId,
-    (val) => {
-        if (val) {
-            isInitialLoad.value = true;
-            updateFarmWorkPlan();
+    (val, oldVal) => {
+        // 如果 farmId 没有值,则不触发
+        if (!val) return;
+        // 如果 farmId 变化了,重置上次请求的 farmId,允许请求新数据
+        if (val !== oldVal) {
+            lastRequestedFarmId.value = null;
         }
+        // getFarmWorkPlan 内部已经有防重复请求的检查,这里直接调用即可
+        isInitialLoad.value = true;
+        updateFarmWorkPlan();
     },
-    // { immediate: true }
+    { immediate: true }
 );
 
 // 格式化日期为 MM-DD 格式
@@ -1081,6 +1108,26 @@ watch(
                                 width: 99%;
                                 text-align: left;
                             }
+                            &.agri-record-card {
+                                .text{
+                                    font-size: 14px;
+                                    .text-name{
+                                        color: #000;
+                                    }
+                                    .text-detail{
+                                        color: rgba(0, 0, 0, 0.2);
+                                        margin-left: 5px;
+                                    }
+                                }
+                                .title-text{
+                                    display: flex;
+                                    align-items: center;
+                                    gap: 3px;
+                                    .icon{
+                                        font-size: 16px;
+                                    }
+                                }
+                            }
                         }
                         .card-right {
                             display: flex;

+ 319 - 0
src/components/popup/agriExecutePopup.vue

@@ -0,0 +1,319 @@
+<template>
+    <popup
+        v-model:show="showValue"
+        round
+        class="agri-execute-popup"
+        :overlay-style="overlayStyle"
+        :close-on-click-overlay="closeOnClickOverlay"
+        :z-index="zIndex"
+        teleport="body"
+    >
+        <div class="popup-content">
+            <!-- 头部区域 -->
+            <div class="popup-header">
+                <div class="header-left">
+                    <div class="expert-logo">
+                        <img v-if="expertAvatar" :src="expertAvatar" alt="专家头像" />
+                        <div v-else class="default-logo">
+                            <span class="logo-icon">🌿</span>
+                        </div>
+                    </div>
+                    <div class="expert-info">
+                        <div class="expert-name">{{ expertName || "专家" }} 邀请您</div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- 标题 -->
+            <div class="popup-title">{{ title }}</div>
+
+            <!-- 异常信息区域 -->
+            <div class="abnormal-info" v-if="abnormalText">
+                {{ abnormalText }}
+            </div>
+
+            <!-- 图片区域 -->
+            <div class="image-container" v-if="imageUrl">
+                <img :src="imageUrl" alt="农事执行图片" class="execute-image" />
+                <div v-if="showMarker" class="image-marker">
+                    <div class="marker-line"></div>
+                    <div class="marker-x">✕</div>
+                </div>
+            </div>
+
+            <!-- 按钮区域 -->
+            <div class="popup-buttons">
+                <div class="btn-later" @click="handleLater">
+                    {{ laterButtonText }}
+                </div>
+                <div class="btn-executed" @click="handleExecuted">
+                    {{ executedButtonText }}
+                </div>
+            </div>
+        </div>
+    </popup>
+</template>
+
+<script setup>
+import { Popup } from "vant";
+import { computed } from "vue";
+
+const props = defineProps({
+    // 控制弹窗显示/隐藏
+    show: {
+        type: Boolean,
+        default: false,
+    },
+    // 专家名称
+    expertName: {
+        type: String,
+        default: "",
+    },
+    // 专家头像
+    expertAvatar: {
+        type: String,
+        default: "",
+    },
+    // 标题
+    title: {
+        type: String,
+        default: "梢期杀虫 农事执行",
+    },
+    // 异常信息文本
+    abnormalText: {
+        type: String,
+        default: "由于***异常的出现,由于***异常的出现,由于***异常的出现,由于***异常的出现,",
+    },
+    // 图片URL
+    imageUrl: {
+        type: String,
+        default: "",
+    },
+    // 是否显示图片标记
+    showMarker: {
+        type: Boolean,
+        default: true,
+    },
+    // 稍后执行按钮文字
+    laterButtonText: {
+        type: String,
+        default: "稍后执行",
+    },
+    // 我已执行按钮文字
+    executedButtonText: {
+        type: String,
+        default: "我已执行",
+    },
+    // 遮罩层样式
+    overlayStyle: {
+        type: Object,
+        default: () => ({
+            "backdrop-filter": "blur(4px)",
+        }),
+    },
+    // 是否在点击遮罩层后关闭弹窗
+    closeOnClickOverlay: {
+        type: Boolean,
+        default: false,
+    },
+    // 遮罩层z-index
+    zIndex: {
+        type: Number,
+        default: 9999,
+    },
+});
+
+const emit = defineEmits(["update:show", "later", "executed"]);
+
+// 处理v-model双向绑定
+const showValue = computed({
+    get: () => props.show,
+    set: (value) => emit("update:show", value),
+});
+
+// 稍后执行
+const handleLater = () => {
+    emit("later");
+    emit("update:show", false);
+};
+
+// 我已执行
+const handleExecuted = () => {
+    emit("executed");
+    emit("update:show", false);
+};
+</script>
+
+<style scoped lang="scss">
+.agri-execute-popup {
+    width: 85%;
+    max-width: 400px;
+    padding: 20px;
+    box-sizing: border-box;
+    background: #ffffff;
+    border-radius: 12px;
+
+    .popup-content {
+        display: flex;
+        flex-direction: column;
+    }
+
+    .popup-header {
+        margin-bottom: 12px;
+
+        .header-left {
+            display: flex;
+            align-items: center;
+            gap: 10px;
+
+            .expert-logo {
+                width: 40px;
+                height: 40px;
+                border-radius: 50%;
+                background: #4caf50;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                flex-shrink: 0;
+                overflow: hidden;
+
+                img {
+                    width: 100%;
+                    height: 100%;
+                    object-fit: cover;
+                }
+
+                .default-logo {
+                    width: 100%;
+                    height: 100%;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+
+                    .logo-icon {
+                        font-size: 24px;
+                    }
+                }
+            }
+
+            .expert-info {
+                .expert-name {
+                    font-size: 14px;
+                    color: #666666;
+                    line-height: 1.4;
+                }
+            }
+        }
+    }
+
+    .popup-title {
+        font-size: 20px;
+        font-weight: 600;
+        color: #000000;
+        margin-bottom: 12px;
+        line-height: 1.4;
+    }
+
+    .abnormal-info {
+        background: #e3f2fd;
+        padding: 12px;
+        border-radius: 6px;
+        font-size: 14px;
+        color: #333333;
+        line-height: 1.6;
+        margin-bottom: 16px;
+        word-break: break-all;
+    }
+
+    .image-container {
+        position: relative;
+        width: 100%;
+        margin-bottom: 20px;
+        border: 2px solid #ff0000;
+        border-radius: 8px;
+        overflow: hidden;
+        background: #f5f5f5;
+        min-height: 200px;
+
+        .execute-image {
+            width: 100%;
+            height: auto;
+            display: block;
+            object-fit: cover;
+        }
+
+        .image-marker {
+            position: absolute;
+            top: 15%;
+            left: 50%;
+            transform: translateX(-50%);
+            pointer-events: none;
+            z-index: 1;
+
+            .marker-line {
+                width: 1px;
+                height: 50px;
+                background: transparent;
+                border-left: 1px dashed #2199f8;
+                margin: 0 auto;
+            }
+
+            .marker-x {
+                width: 20px;
+                height: 20px;
+                background: #2199f8;
+                border-radius: 50%;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                color: #ffffff;
+                font-size: 12px;
+                font-weight: bold;
+                margin: 0 auto;
+                margin-top: -10px;
+                border: 1px solid #ffffff;
+                box-shadow: 0 0 0 1px #2199f8;
+            }
+        }
+    }
+
+    .popup-buttons {
+        display: flex;
+        gap: 12px;
+
+        .btn-later,
+        .btn-executed {
+            flex: 1;
+            padding: 12px;
+            border-radius: 25px;
+            font-size: 16px;
+            text-align: center;
+            cursor: pointer;
+            transition: all 0.3s;
+        }
+
+        .btn-later {
+            background: #ffffff;
+            border: 1px solid rgba(153, 153, 153, 0.5);
+            color: #666666;
+
+            &:active {
+                background: #f5f5f5;
+                transform: scale(0.98);
+            }
+        }
+
+        .btn-executed {
+            background: #2199f8;
+            color: #ffffff;
+            border: none;
+
+            &:active {
+                background: #1a8ae6;
+                transform: scale(0.98);
+            }
+        }
+    }
+}
+</style>
+

+ 359 - 84
src/views/old_mini/agri_record/index.vue

@@ -1,77 +1,302 @@
 <template>
-    <div class="agri-record-index" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
-        <div class="record-content">
-            <div>
-                <!-- 天气遮罩 -->
-                <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
-                <!-- 天气 -->
-                <weather-info
-                    ref="weatherInfoRef"
-                    class="weather-info"
-                    @weatherExpanded="weatherExpanded"
-                    @changeGarden="changeGarden"
-                    :isGarden="true"
-                    :gardenId="gardenId"
-                ></weather-info>
-            </div>
-            <div class="record-list">
+    <custom-header v-if="isHeaderShow" name="农场详情"></custom-header>
+    <div class="monitor-index" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
+        <!-- 天气遮罩 -->
+        <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
+        <!-- 天气 -->
+        <weather-info
+            ref="weatherInfoRef"
+            class="weather-info"
+            @weatherExpanded="weatherExpanded"
+            @changeGarden="changeGarden"
+            :isGarden="true"
+            :gardenId="defaultGardenId"
+        ></weather-info>
+        <!-- 作物档案 -->
+        <div class="archives-time-line">
+            <div class="archives-time-line-header">
                 <div class="line-title">农事记录</div>
-                <div class="task-content" v-loading="loading">
-                    <div class="task-item" v-for="(item, index) in taskList" :key="item.id || item.workRecordId">
-                        <task-item
-                            :key="1 + '-' + index"
-                            :itemIndex="3"
-                            :status="3"
-                            :item-data="item"
-                        >
-                        </task-item>
-                    </div>
-                    <div class="empty-data" v-if="noData">暂无数据</div>
-                </div>
+                <el-date-picker style="width: 110px" v-model="date" type="year" placeholder="全部日期" />
+            </div>
+            <div class="archives-time-line-content">
+                <archives-farm-time-line :farmId="gardenId" pageType="agri_record"></archives-farm-time-line>
             </div>
         </div>
     </div>
+
+    <tip-popup
+        v-model:show="showFarmPopup"
+        type="success"
+        text="农场领取成功"
+        :overlay-style="{ 'backdrop-filter': 'blur(4px)' }"
+        :closeOnClickOverlay="false"
+        :zIndex="9999"
+    />
+
+    <!-- 农事执行弹窗 -->
+    <agri-execute-popup
+        v-model:show="showAgriExecutePopup"
+        :expert-name="agriExecuteData.expertName"
+        :expert-avatar="agriExecuteData.expertAvatar"
+        :title="agriExecuteData.title"
+        :abnormal-text="agriExecuteData.abnormalText"
+        :image-url="agriExecuteData.imageUrl"
+        :show-marker="agriExecuteData.showMarker"
+        @later="handleAgriLater"
+        @executed="handleAgriExecuted"
+    />
 </template>
 
 <script setup>
-import { ref, onMounted, computed, onActivated } from "vue";
+import customHeader from "@/components/customHeader.vue";
+import { ref, computed, onActivated, onDeactivated, onMounted } from "vue";
 import { useStore } from "vuex";
+import { Badge, List } from "vant";
 import weatherInfo from "@/components/weatherInfo.vue";
-import taskItem from "@/components/taskItem.vue";
+import { useRouter, useRoute } from "vue-router";
+import farmInfoPopup from "../home/components/farmInfoPopup.vue";
+import tipPopup from "@/components/popup/tipPopup.vue";
+import agriExecutePopup from "@/components/popup/agriExecutePopup.vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import ArchivesFarmTimeLine from "@/components/pageComponents/ArchivesFarmTimeLine.vue";
 
-const store = useStore();
-const tabBarHeight = computed(() => store.state.home.tabBarHeight);
+const showFarmPopup = ref(false); // 农场领取成功弹窗
+const showAgriExecutePopup = ref(false); // 农事执行弹窗 - 默认显示
+const date = ref(new Date());
 
-onMounted(() => {
+// 农事执行弹窗数据
+const agriExecuteData = ref({
+    expertName: "韦帮稳",
+    expertAvatar: "",
+    title: "梢期杀虫 农事执行",
+    abnormalText: "由于***异常的出现,由于***异常的出现,由于***异常的出现,由于***异常的出现,",
+    imageUrl: "",
+    showMarker: true,
 });
 
+const defaultGardenId = ref(null);
+const isHeaderShow = ref(false);
+const isDefaultFarm = ref(false);
+const weatherInfoRef = ref(null);
+
 onActivated(() => {
-    if(gardenId.value) {
-        getRecordList();
+    // 用来接收我的农场跳转过来的农场详情逻辑
+    if (route.query.isHeaderShow) {
+        isHeaderShow.value = true;
+        defaultGardenId.value = route.query.farmId;
+        // 统一转换为布尔值
+        isDefaultFarm.value = route.query.defaultFarm === "true" || route.query.defaultFarm === true;
     }
 });
-const taskList = ref([]);
-const loading = ref(false);
-const noData = ref(false);
-const getRecordList = () => {
-    loading.value = true;
-    VE_API.user.farmServiceRecord({ farmId: gardenId.value })
-        .then(({ data }) => {
-            loading.value = false;
-            taskList.value = data;
-            if(data.length === 0) {
-                noData.value = true;
+
+const receiveFarm = (json) => {
+    VE_API.monitor
+        .receiveFarm({
+            agriculturalStoreId: json.agriculturalStoreId,
+            farmId: json.farmId,
+        })
+        .then((res) => {
+            if (res.code === 0) {
+                showFarmPopup.value = true;
+                defaultGardenId.value = json.farmId;
+            } else {
+                ElMessage.warning(res.msg);
             }
+            // 清空路由参数
+            router.replace({ path: route.path });
+        });
+};
+
+const store = useStore();
+const tabBarHeight = computed(() => store.state.home.tabBarHeight);
+const router = useRouter();
+const route = useRoute();
+
+const farmInfoRef = ref(null);
+
+function toFarmInfo() {
+    farmInfoRef.value.handleShow();
+}
+
+// 功能卡片数据
+const functionCards = ref([
+    {
+        title: "农事规划",
+        route: "/plan",
+    },
+    {
+        title: "农场报告",
+        status: "最新",
+        route: "/farm_report",
+        className: "blue",
+    },
+    {
+        title: "农事方案",
+        route: "/agricultural_plan",
+    },
+    {
+        title: "复核成效",
+        status: "最新",
+        route: "/review-results",
+        className: "yellow",
+    },
+]);
+
+const getStayCount = () => {
+    VE_API.monitor
+        .getCountByStatusAndFarmId({
+            farmId: gardenId.value,
+            startStatus: 1,
+            endStatus: 3,
         })
+        .then((res) => {
+            functionCards.value[0].status = null;
+            if (res.data && res.data != 0) {
+                functionCards.value[0].status = res.data + " 待完成";
+            }
+        });
+};
+
+// 实时播报数据
+const broadcastList = ref([]);
+const loading = ref(false);
+const finished = ref(false);
+const currentPage = ref(1);
+const pageSize = ref(10);
+
+const getBroadcastList = async (page = 1, isLoadMore = false) => {
+    if (!gardenId.value) {
+        loading.value = false;
+        return;
+    }
+
+    // 如果正在加载,直接返回(避免重复请求)
+    if (loading.value) {
+        return;
+    }
+
+    loading.value = true;
+    try {
+        const res = await VE_API.monitor.broadcastPage({
+            farmId: gardenId.value,
+            limit: pageSize.value,
+            page: page,
+        });
+
+        const newData = res.data || [];
+        if (isLoadMore) {
+            broadcastList.value = [...broadcastList.value, ...newData];
+        } else {
+            broadcastList.value = newData;
+        }
+
+        // 判断是否还有更多数据
+        if (newData.length < pageSize.value) {
+            finished.value = true;
+        } else {
+            finished.value = false;
+            // 如果未完成,页码+1,为下次加载做准备
+            currentPage.value = page + 1;
+        }
+    } catch (error) {
+        console.error("获取播报列表失败:", error);
+        finished.value = true;
+    } finally {
+        // 确保 loading 状态被正确设置为 false
+        loading.value = false;
+    }
+};
+
+// 滚动加载更多
+const onLoad = async () => {
+    if (finished.value || loading.value) return;
+
+    // 判断是否是首次加载(页码为1)
+    const isLoadMore = currentPage.value > 1;
+    const pageToLoad = currentPage.value;
+
+    // 加载数据(页码会在 getBroadcastList 成功后自动更新)
+    await getBroadcastList(pageToLoad, isLoadMore);
+};
+
+// 卡片点击事件
+const handleCardClick = (card) => {
+    const params = {
+        farmId: gardenId.value,
+    };
+    router.push({
+        path: card.route,
+        query: { ...params, miniJson: JSON.stringify(params) },
+    });
 };
 
+// 播报相关事件
+const isSpeaking = ref(false);
+const speechSynthesis = window.speechSynthesis;
+
+const handleBroadcast = () => {
+    if (isSpeaking.value) {
+        // 如果正在播放,则停止
+        speechSynthesis.cancel();
+        isSpeaking.value = false;
+        return;
+    }
+
+    // 构建播报文本
+    let broadcastText = "实时播报:";
+
+    if (broadcastList.value.length === 0) {
+        broadcastText += "暂无更多播报";
+    } else {
+        broadcastList.value.forEach((item, index) => {
+            broadcastText += `${index + 1}、${item.title}。${item.content}。`;
+        });
+    }
+
+    // 创建语音合成对象
+    const utterance = new SpeechSynthesisUtterance(broadcastText);
+
+    // 设置语音参数
+    utterance.lang = "zh-CN";
+    utterance.rate = 0.8; // 语速
+    utterance.pitch = 1; // 音调
+    utterance.volume = 1; // 音量
+
+    // 播放开始事件
+    utterance.onstart = () => {
+        isSpeaking.value = true;
+    };
+
+    // 播放结束事件
+    utterance.onend = () => {
+        isSpeaking.value = false;
+    };
+
+    // 播放错误事件
+    utterance.onerror = (event) => {
+        isSpeaking.value = false;
+        console.error("播报错误:", event.error);
+    };
+
+    // 开始播报
+    speechSynthesis.speak(utterance);
+};
+
+// 组件卸载时停止语音播放
+onDeactivated(() => {
+    showFarmPopup.value = false;
+    isDefaultFarm.value = false;
+    if (isSpeaking.value) {
+        speechSynthesis.cancel();
+        isSpeaking.value = false;
+    }
+});
 
 const isExpanded = ref(false);
 const weatherExpanded = (isExpandedValue) => {
     isExpanded.value = isExpandedValue;
 };
 
-const weatherInfoRef = ref(null);
 // 点击遮罩时收起天气
 const handleMaskClick = () => {
     if (weatherInfoRef.value && weatherInfoRef.value.toggleExpand) {
@@ -79,49 +304,76 @@ const handleMaskClick = () => {
     }
 };
 
-const finished = ref(false);
 const gardenId = ref(store.state.home.gardenId);
+
+// 初始化加载数据
+onMounted(() => {
+    if (gardenId.value) {
+        currentPage.value = 1;
+        finished.value = false;
+        broadcastList.value = [];
+        getStayCount();
+        // 不在这里手动加载,让 List 组件的 immediate-check 自动触发首次加载
+    }
+});
+
 const changeGarden = ({ id }) => {
     gardenId.value = id;
     // 更新 store 中的状态
     store.commit("home/SET_GARDEN_ID", id);
+    // 重置分页状态
+    currentPage.value = 1;
     finished.value = false;
-    getRecordList();
+    broadcastList.value = [];
+    getStayCount();
+    getBroadcastList(1, false);
+};
+
+function handlePage(url) {
+    const query = {
+        farmId: gardenId.value,
+    };
+    if (url === "/message_list") {
+        query.from = "monitor";
+    }
+    router.push({
+        path: url,
+        query: query,
+    });
+}
+
+// 农事执行弹窗相关方法
+const handleAgriLater = () => {
+    console.log("稍后执行");
+    // 可以在这里添加稍后执行的逻辑
+};
+
+const handleAgriExecuted = () => {
+    console.log("我已执行");
+    // 可以在这里添加执行完成的逻辑
 };
 
+// 显示农事执行弹窗的方法(可以在需要的地方调用)
+const showAgriExecute = (data = {}) => {
+    agriExecuteData.value = {
+        expertName: data.expertName || "韦帮稳",
+        expertAvatar: data.expertAvatar || "",
+        title: data.title || "梢期杀虫 农事执行",
+        abnormalText: data.abnormalText || "由于***异常的出现,由于***异常的出现,由于***异常的出现,由于***异常的出现,",
+        imageUrl: data.imageUrl || "",
+        showMarker: data.showMarker !== undefined ? data.showMarker : true,
+    };
+    showAgriExecutePopup.value = true;
+};
 </script>
 
-<style lang="scss" scoped>
-.agri-record-index {
+<style scoped lang="scss">
+.monitor-index {
     width: 100%;
-    height: 100vh;
+    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%);
-    .line-title {
-        padding: 10px 0;
-        position: relative;
-        padding-left: 14px;
-        font-size: 16px;
-        &::before {
-            content: '';
-            position: absolute;
-            left: 5px;
-            top: 50%;
-            transform: translateY(-50%);
-            width: 4px;
-            height: 15px;
-            background: #2199f8;
-            border-radius: 20px;
-        }
-    }
-
-    .record-content {
-        position: relative;
-        height: 100%;
-        padding: 10px 12px;
-        box-sizing: border-box;
-        overflow: auto;
-    }
+    background: linear-gradient(180deg, #f9f9f9 0%, #f0f8ff 31.47%, #f9f9f9 46.81%, #f9f9f9 69.38%, #f9f9f9 100%);
     .weather-mask {
         position: fixed;
         top: 0;
@@ -136,15 +388,38 @@ const changeGarden = ({ id }) => {
         position: absolute;
         z-index: 3;
     }
-    .record-list {
+    .archives-time-line {
         position: relative;
-        top: 100px;
-        .empty-data {
-            text-align: center;
-            padding-top: 20px;
+        margin-top: 96px;
+        height: calc(100% - 90px);
+        .archives-time-line-header {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            .line-title {
+                position: relative;
+                padding-left: 14px;
+                font-size: 16px;
+                &::before {
+                    content: "";
+                    position: absolute;
+                    left: 5px;
+                    top: 50%;
+                    transform: translateY(-50%);
+                    width: 4px;
+                    height: 15px;
+                    background: #2199f8;
+                    border-radius: 20px;
+                }
+            }
         }
-        .task-item + .task-item {
+        .archives-time-line-content {
             margin-top: 10px;
+            height: calc(100% - 35px);
+            background: #fff;
+            border-radius: 8px;
+            padding: 10px;
+            box-sizing: border-box;
         }
     }
 }