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

feat:对接农情档案接口

wangsisi 3 дней назад
Родитель
Сommit
a0ddc5c70b

+ 2 - 0
src/i18n/messages.js

@@ -263,6 +263,7 @@ export default {
             executeSuccessTitle: "农事任务已生效",
             executeSuccessDesc: "请立即按要求实地执行",
             executeSuccessNotice: "注:执行中需拍摄照片,任务完成后需提交照片审核!",
+            auditApproved: "审核通过",
             completePopup: {
                 selectExecuteTime: "请选择实际执行时间",
                 evidenceTitle: "农事凭证",
@@ -563,6 +564,7 @@ export default {
             executeSuccessTitle: "Farm task is now active",
             executeSuccessDesc: "Please execute on site as required",
             executeSuccessNotice: "Note: Take photos during execution and submit them for review after completion.",
+            auditApproved: "Approved",
             completePopup: {
                 selectExecuteTime: "Select actual execution time",
                 evidenceTitle: "Farm work evidence",

+ 76 - 79
src/views/old_mini/agri_file/index.vue

@@ -3,7 +3,7 @@
         <!-- 天气遮罩 -->
         <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
         <!-- 头部 -->
-        <div v-show="activeGardenTab === 'current'" class="agri-file-header" :style="headerMotionStyle">
+        <div class="agri-file-header" :style="activeGardenTab === 'current' ? headerMotionStyle : undefined">
             <weather-info ref="weatherInfoRef" :hasWeather="false" from="agri_file" class="weather-info"
                 @weatherExpanded="weatherExpanded" @changeGarden="changeGarden" @changeGardenTab="changeGardenTab"
                 @reportTabClick="handleReportTabClick" :isGarden="true" :gardenId="defaultGardenId" />
@@ -15,24 +15,17 @@
         </div>
 
         <div v-show="activeGardenTab === 'current'" class="tracking-list">
-            <div
-                v-for="item in trackingList"
-                :key="item.id"
-                class="tracking-item"
-                :class="`tracking-item--${item.theme}`"
-            >
+            <div v-for="item in trackingList" :key="item.id" class="tracking-item"
+                :class="`tracking-item--${item.theme}`" @click="handleTrackingItemClick(item)">
                 <div class="tracking-item__header">
                     <div class="tracking-item__header-row">
                         <div class="tracking-item__header-left">
-                            <span class="tracking-item__level">{{ item.level }}</span>
-                            <span class="tracking-item__title">{{ item.title }}</span>
+                            <span class="tracking-item__level" v-show="item.risk_level">{{ item.risk_level }}</span>
+                            <span class="tracking-item__title">{{ item.first_work?.work_name }}</span>
                         </div>
                         <div class="tracking-item__tags">
-                            <span
-                                v-for="(tag, tagIndex) in item.tags"
-                                :key="tagIndex"
-                                class="tracking-item__tag"
-                            >{{ tag }}</span>
+                            <span v-for="(tag, tagIndex) in item.list" :key="tagIndex" class="tracking-item__tag">{{
+                                tag?.category_name || tag }}</span>
                         </div>
                     </div>
                 </div>
@@ -41,24 +34,19 @@
                         <div class="tracking-item__action-main">
                             <div class="tracking-item__icon">
                                 <img :src="item.icon" alt="" />
-                                <div class="tracking-item__reason">{{ item.reason }}</div>
+                                <div class="tracking-item__reason">{{ item.first_work?.work_reason_short }}</div>
                             </div>
                             <div class="tracking-item__info">
-                                <div class="tracking-item__issue">{{ item.issue }}</div>
+                                <div class="tracking-item__issue">{{ item.first_work?.interaction_issue }}</div>
                             </div>
                         </div>
-                        <div class="tracking-item__btn">{{ item.recordText }}</div>
+                        <div class="tracking-item__btn">立即记录</div>
                     </div>
-                    <div class="tracking-item__history">
+                    <div class="tracking-item__history" v-show="false">
                         <div class="tracking-item__history-text">{{ item.historyText }}</div>
                         <div class="tracking-item__images">
-                            <img
-                                v-for="(image, imageIndex) in item.images.slice(0, 5)"
-                                :key="imageIndex"
-                                class="tracking-item__thumb"
-                                :src="image"
-                                alt=""
-                            />
+                            <img v-for="(image, imageIndex) in item.images" :key="imageIndex"
+                                class="tracking-item__thumb" :src="image" alt="" />
                         </div>
                     </div>
                 </div>
@@ -107,47 +95,48 @@ const currentFarmName = ref("");
 const currentFarmVariety = ref(null);
 
 const defaultThumb = require("@/assets/img/home/banner.png");
-const trackingList = ref([
-    {
-        id: "phenology",
-        theme: "blue",
-        level: "二级",
-        title: "物候跟踪记录",
-        tags: ["物候", "物候", "物候"],
-        icon: require("@/assets/img/report/wh-icon.png"),
-        reason: "某某原因",
-        issue: "互动问题互动问题互动问题互动问题互",
-        recordText: "立即记录",
-        historyText: "2026.06.07 某某区发生的事情",
-        images: Array.from({ length: 5 }, () => defaultThumb),
-    },
-    {
-        id: "pest",
-        theme: "red",
-        level: "二级",
-        title: "病虫害态势监控",
-        tags: ["真菌类", "真菌类", "真菌类"],
-        icon: require("@/assets/img/report/bh-icon.png"),
-        reason: "某某原因",
-        issue: "互动问题互动问题互动问题互动问题互",
-        recordText: "立即记录",
-        historyText: "2026.06.07 某某区发生的事情",
-        images: Array.from({ length: 5 }, () => defaultThumb),
-    },
-    {
-        id: "growth",
-        theme: "orange",
-        level: "二级",
-        title: "长势异常态势跟踪",
-        tags: ["真菌类", "真菌类", "真菌类"],
-        icon: require("@/assets/img/report/yc-icon.png"),
-        reason: "某某原因",
-        issue: "互动问题互动问题互动问题互动问题互",
-        recordText: "立即记录",
-        historyText: "2026.06.07 某某区发生的事情",
-        images: Array.from({ length: 5 }, () => defaultThumb),
-    },
-]);
+const trackingList = ref([]);
+// const trackingList = ref([
+//     {
+//         id: "phenology",
+//         theme: "blue",
+//         level: "二级",
+//         title: "物候跟踪记录",
+//         tags: ["物候", "物候", "物候"],
+//         icon: require("@/assets/img/report/wh-icon.png"),
+//         reason: "某某原因",
+//         issue: "互动问题互动问题互动问题互动问题互",
+//         recordText: "立即记录",
+//         historyText: "2026.06.07 某某区发生的事情",
+//         images: Array.from({ length: 5 }, () => defaultThumb),
+//     },
+//     {
+//         id: "pest",
+//         theme: "red",
+//         level: "二级",
+//         title: "病虫害态势监控",
+//         tags: ["真菌类", "真菌类", "真菌类"],
+//         icon: require("@/assets/img/report/bh-icon.png"),
+//         reason: "某某原因",
+//         issue: "互动问题互动问题互动问题互动问题互",
+//         recordText: "立即记录",
+//         historyText: "2026.06.07 某某区发生的事情",
+//         images: Array.from({ length: 5 }, () => defaultThumb),
+//     },
+//     {
+//         id: "growth",
+//         theme: "orange",
+//         level: "二级",
+//         title: "长势异常态势跟踪",
+//         tags: ["真菌类", "真菌类", "真菌类"],
+//         icon: require("@/assets/img/report/yc-icon.png"),
+//         reason: "某某原因",
+//         issue: "互动问题互动问题互动问题互动问题互",
+//         recordText: "立即记录",
+//         historyText: "2026.06.07 某某区发生的事情",
+//         images: Array.from({ length: 5 }, () => defaultThumb),
+//     },
+// ]);
 
 const handleReportTabClick = (item) => {
     if (item.key === "historyRisk") {
@@ -192,6 +181,7 @@ const changeGarden = (data) => {
     selectedGardenId.value = data.id;
     currentFarmName.value = data.name ?? "";
     currentFarmVariety.value = data.farm_variety ?? null;
+    getFarmRiskAndTracking();
 };
 
 onActivated(() => {
@@ -201,30 +191,36 @@ onActivated(() => {
     const savedFarmId = localStorage.getItem("selectedFarmId");
     selectedGardenId.value = savedFarmId ? Number(savedFarmId) : null;
     gardenListRef.value?.refreshFarmList?.();
-    getFarmRiskAndTracking();
 });
 
+const currentPheCode = ref('');
+let fetchRequestId = 0;
 const getFarmRiskAndTracking = async () => {
-    const selectedFarmData = JSON.parse(localStorage.getItem("selectedFarmData"));
+    const requestId = ++fetchRequestId;
+    trackingList.value = [];
+    const selectedFarmData = JSON.parse(localStorage.getItem("selectedFarmData") || "{}");
     const res = await VE_API.monitor.getFarmRiskAndTracking({
         farm_id: selectedGardenId.value,
         crop_type: selectedFarmData.farm_variety,
         category_code: selectedFarmData.farm_category
     });
+    if (requestId !== fetchRequestId) return;
     if (res.code === 200) {
-        console.log(res)
-        // trackingList.value = res.data;
+        currentPheCode.value = res.current_phe_code;
+        trackingList.value = [
+            { ...res.data.phenology_tracking, theme: "blue", icon: require("@/assets/img/report/wh-icon.png"), workType: 'phenology' },
+            { ...res.data.growth_abnormal_tracking, theme: "orange", icon: require("@/assets/img/report/yc-icon.png"), workType: 'growth' },
+            { ...res.data.pest_risk_assessment, theme: "red", icon: require("@/assets/img/report/bh-icon.png"), workType: 'pest' },
+        ];
     }
-}
+};
 
-// const handleTrendMonitorCardClick = (item) => {
-//     saveArchivesOuterScrollTop();
-//     blockArchivesScrollSaveOnce.value = true;
-//     router.push({
-//         path: "/record_details",
-//         query: { workId: item?.first_work?.work_id, type: item?.workType, curCode:currentPheCode.value  },
-//     });
-// };
+const handleTrackingItemClick = (item) => {
+    router.push({
+        path: "/record_details",
+        query: { workId: item?.first_work?.work_id, type: item?.workType, curCode: currentPheCode.value },
+    });
+};
 </script>
 
 <style lang="scss" scoped>
@@ -391,6 +387,7 @@ const getFarmRiskAndTracking = async () => {
             display: flex;
             align-items: center;
             gap: 4px;
+
             img {
                 width: 18px;
                 height: 16px;

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

@@ -4,7 +4,7 @@
         <!-- 天气遮罩 -->
         <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
         <!-- 头部 -->
-        <div v-show="activeGardenTab === 'current'" class="agri-record-header">
+        <div class="agri-record-header">
             <weather-info ref="weatherInfoRef" :hasWeather="false" from="agri_record" class="weather-info"
                 @weatherExpanded="weatherExpanded" @changeGarden="changeGarden" @changeGardenTab="changeGardenTab"
                 @reportTabClick="handleReportTabClick" @farmInfoMaintain="handleFarmInfoMaintain" :isGarden="true"

+ 113 - 2
src/views/old_mini/agri_record_detail/index.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="agri-record-detail">
         <custom-header :name="t('agriRecordDetail.title')"></custom-header>
-        <div class="content">
+        <div class="content" :class="{ 'content--no-footer': !showBottomButtons }">
             <div class="status-banner" :class="`status-banner--${statusBannerTheme}`">
                 <div class="status-banner__title">{{ statusBannerTitle }}</div>
                 <div class="status-banner__deadline">{{ t('agriRecordDetail.deadlinePrefix') }} {{ workDetail.work_time }}</div>
@@ -20,6 +20,21 @@
                     <div class="nav-btn" @click="handleNavigate">{{ t('agriRecordDetail.navigateHere') }}</div>
                 </div>
             </div>
+            <div v-if="isCompletedStatus" class="box-wrap execute-photos-card">
+                <div class="execute-photos-card__header">
+                    <span class="execute-photos-card__title">{{ t('workExecute.executePhotos') }}</span>
+                    <span class="execute-photos-card__status">{{ t('agriRecordDetail.auditApproved') }}</span>
+                </div>
+                <div class="execute-photos-card__list">
+                    <div
+                        v-for="(photo, index) in executePhotoList"
+                        :key="index"
+                        class="execute-photos-card__item"
+                    >
+                        <img :src="photo" alt="" />
+                    </div>
+                </div>
+            </div>
             <div class="box-wrap work-summary-card">
                 <div class="header" :class="{ 'header--en': locale === 'en' }">
                     <img class="icon" src="@/assets/img/home/task.png" alt="">
@@ -95,7 +110,7 @@
         <div
             class="custom-bottom-fixed-btns"
             :class="{ 'custom-bottom-fixed-btns--single': isExecutingStatus && !isEditing }"
-            v-if="!isAcceptOvertime && !isCompletedStatus"
+            v-if="showBottomButtons"
         >
             <template v-if="isExecutingStatus && !isEditing">
                 <div class="bottom-btn primary-btn green-btn" @click="handleAccept">{{ t('workExecute.markComplete') }}</div>
@@ -137,6 +152,18 @@ import tipPopup from '@/components/popup/tipPopup.vue';
 import completePopup from './components/completePopup.vue';
 import { ElMessage } from 'element-plus';
 import { useRoute } from 'vue-router';
+import config from '@/api/config.js';
+import executePhotoPlaceholder1 from '@/assets/img/common/sd-1.jpg';
+import executePhotoPlaceholder2 from '@/assets/img/common/sd-2.jpg';
+import executePhotoPlaceholder3 from '@/assets/img/common/sd-3.jpg';
+import executePhotoPlaceholder4 from '@/assets/img/common/sd-4.jpg';
+
+const EXECUTE_PHOTO_PLACEHOLDERS = [
+    executePhotoPlaceholder1,
+    executePhotoPlaceholder2,
+    executePhotoPlaceholder3,
+    executePhotoPlaceholder4,
+];
 
 const { t, locale } = useI18n();
 
@@ -305,6 +332,43 @@ const isCompletedStatus = computed(() =>
     route.query.statusStr === '已完成' || Number(route.query.status) === 3
 );
 
+const showBottomButtons = computed(() => !isAcceptOvertime.value && !isCompletedStatus.value);
+
+const resolveExecutePhotoUrl = (src) => {
+    if (!src) return '';
+    if (typeof src === 'object' && src.cloud_filename) {
+        return config.base_img_url3 + src.cloud_filename;
+    }
+    if (typeof src === 'string') {
+        if (src.startsWith('http')) return src;
+        return config.base_img_url2 + src;
+    }
+    return '';
+};
+
+const executePhotoList = computed(() => {
+    const raw = workDetail.value?.execute_evidence ?? workDetail.value?.executeEvidence;
+    let photos = [];
+
+    if (raw) {
+        if (Array.isArray(raw)) {
+            photos = raw.map(resolveExecutePhotoUrl).filter(Boolean);
+        } else if (typeof raw === 'string') {
+            try {
+                const parsed = JSON.parse(raw);
+                if (Array.isArray(parsed)) {
+                    photos = parsed.map(resolveExecutePhotoUrl).filter(Boolean);
+                }
+            } catch {
+                const url = resolveExecutePhotoUrl(raw);
+                if (url) photos = [url];
+            }
+        }
+    }
+
+    return (photos.length ? photos : EXECUTE_PHOTO_PLACEHOLDERS).slice(0, 4);
+});
+
 const primaryActionText = computed(() => {
     if (isEditing.value) return t('agriRecordDetail.saveInfo');
     if (isAcceptedStatus.value) return t('workExecute.startExecute');
@@ -383,6 +447,10 @@ const handleCompleteConfirm = () => {
         -webkit-overflow-scrolling: touch;
         padding-bottom: 90px;
         box-sizing: border-box;
+
+        &--no-footer {
+            padding-bottom: 12px;
+        }
         
         .status-banner {
             padding: 20px 12px 72px;
@@ -477,6 +545,49 @@ const handleCompleteConfirm = () => {
                 }
             }
 
+            &.execute-photos-card {
+                padding: 12px 10px 10px;
+
+                .execute-photos-card__header {
+                    display: flex;
+                    align-items: center;
+                    justify-content: space-between;
+                    margin-bottom: 12px;
+                }
+
+                .execute-photos-card__title {
+                    font-size: 16px;
+                }
+
+                .execute-photos-card__status {
+                    padding: 2px 8px;
+                    font-size: 12px;
+                    line-height: 18px;
+                    color: #4ABF32;
+                    background: rgba(74, 191, 50, 0.1);
+                    border-radius: 4px;
+                }
+
+                .execute-photos-card__list {
+                    display: flex;
+                    gap: 8px;
+                }
+
+                .execute-photos-card__item {
+                    flex: 1;
+                    aspect-ratio: 1;
+                    border-radius: 8px;
+                    overflow: hidden;
+
+                    img {
+                        display: block;
+                        width: 100%;
+                        height: 100%;
+                        object-fit: cover;
+                    }
+                }
+            }
+
             &.work-summary-card {
                 padding: 12px 10px 10px;
 

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

@@ -4,9 +4,8 @@
         <div class="weather-mask" v-show="isExpanded" @click="handleMaskClick"></div>
         <!-- 头部 -->
         <div
-            v-show="activeGardenTab === 'current'"
             class="growth-report-header"
-            :style="headerMotionStyle"
+            :style="activeGardenTab === 'current' ? headerMotionStyle : undefined"
         >
             <weather-info ref="weatherInfoRef" :hasWeather="false" from="growth_report" class="weather-info"
                 @weatherExpanded="weatherExpanded" @changeGarden="changeGarden" @changeGardenTab="changeGardenTab"

+ 8 - 7
src/views/old_mini/work_execute/components/calendar.vue

@@ -223,13 +223,14 @@ const selectDate = (date, day) => {
     }
 };
 
-// 初始化时不选择任何日期(默认不选中)
-// onMounted(() => {
-//     selectDate(formatDate(today), {
-//         day: today.getDate(),
-//         dayOfWeek: weekdaysShort[today.getDay() === 0 ? 6 : today.getDay() - 1],
-//     });
-// });
+// 初始化默认选中今天
+onMounted(() => {
+    const todayDay = calendarDays.value.find((day) => day.isToday);
+    if (todayDay) {
+        activeDay.value = todayDay.date;
+        selectedDate.value = `${todayDay.date} (${todayDay.dayOfWeek})`;
+    }
+});
 
 function closeDialog() {
     activeDay.value = null;

+ 62 - 66
src/views/old_mini/work_execute/index.vue

@@ -22,13 +22,13 @@
                 <div class="list-header">
                     <div class="select-group">
                         <el-select class="select-item" v-model="selectParma.farmWorkTypeId" :placeholder="t('workExecute.farmWorkType')"
-                            @change="getRegionRecordData">
+                            @change="resetAndLoad">
                             <el-option v-for="item in farmWorkTypeList" :key="item.id"
                                 :label="item.id === 0 ? t('workExecute.all') : item.name"
                                 :value="item.id" />
                         </el-select>
                         <el-select class="select-item" v-model="selectParma.districtCode" :placeholder="t('workExecute.farmFilter')"
-                            @change="getRegionRecordData">
+                            @change="resetAndLoad">
                             <el-option v-for="item in districtList" :key="item.code" :label="item.name"
                                 :value="item.code" />
                         </el-select>
@@ -313,8 +313,11 @@ const handleStatusBtn = (btn, item, index) => {
     }
 };
 
+const formatDateYMD = (date = new Date()) =>
+    `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
+
 const calendarRef = ref(null);
-const filterDate = ref(null);
+const filterDate = ref(formatDateYMD());
 const fullTaskList = ref([]);
 
 const getCalendarTaskList = (list) => {
@@ -331,19 +334,13 @@ const syncCalendarData = () => {
 };
 
 const handleDateSelect = (date) => {
-    filterDate.value = date;
-    // if (!date) {
-    //     taskList.value = [...fullTaskList.value];
-    // } else {
-    //     taskList.value = fullTaskList.value.filter((item) => {
-    //         if (!item.time) return false;
-    //         return formatGMTToYMD(item.time) === date;
-    //     });
-    // }
+    filterDate.value = date ?? formatDateYMD();
+    resetAndLoad();
     syncCalendarData();
 };
-// 各状态任务数量
-const taskCounts = ref([0, 0, 0]);
+// 各状态任务数量,key 为 work_operation_type:0待接受 1执行中 2已接受 3已完成
+const taskCounts = ref({ 0: 0, 1: 0, 2: 0, 3: 0 });
+const STATUS_TAB_VALUES = [0, 2, 1, 3];
 const filterTabs = [
     { value: 0, labelKey: "workExecute.pending" },
     { value: 2, labelKey: "workExecute.accepted" },
@@ -371,82 +368,84 @@ const mapPoint = ref(null);
 
 onMounted(() => {
     mapPoint.value = store.state.home.miniUserLocationPoint;
-    resetAndLoad();
     getFarmWorkTypeList();
     syncCalendarData();
     nextTick(() => {
         indexMap.initMap(mapPoint.value, mapContainer.value, true);
-        
-        // 更新地图数据
         indexMap.initData(taskList.value, '', 'farmPoint');
     });
 });
 
 onActivated(() => {
-    getRegionRecordData();
-    // 确保地图已初始化,使用 nextTick 等待 DOM 更新
+    resetAndLoad();
     nextTick(() => {
-        // 检查地图实例是否已初始化
         if (!indexMap.kmap) {
-            // 如果地图未初始化,重新初始化
             if (mapContainer.value) {
                 mapPoint.value = store.state.home.miniUserLocationPoint;
                 indexMap.initMap(mapPoint.value, mapContainer.value, true);
-                // 等待地图初始化完成后再加载数据
-                setTimeout(() => {
-                    resetAndLoad();
-                }, 300);
-                return;
-            }
-        } else {
-            // 如果地图已初始化,需要等待 tab 切换完成,容器完全可见后再更新尺寸
-            // Tab 切换时容器可能被隐藏,需要更长的延迟确保容器可见
-            if (mapContainer.value && indexMap.kmap.map) {
-                // 检查容器是否可见
-                const checkAndUpdateSize = () => {
-                    const container = mapContainer.value;
-                    if (container) {
-                        const rect = container.getBoundingClientRect();
-                        // 如果容器可见(有宽度和高度),更新地图尺寸
-                        if (rect.width > 0 && rect.height > 0) {
-                            indexMap.kmap.map.updateSize();
-                        } else {
-                            // 如果容器不可见,继续等待
-                            setTimeout(checkAndUpdateSize, 100);
-                        }
-                    }
-                };
-                // 延迟检查,确保 tab 切换完成
-                setTimeout(checkAndUpdateSize, 200);
             }
+            return;
+        }
+
+        if (mapContainer.value && indexMap.kmap.map) {
+            const checkAndUpdateSize = () => {
+                const container = mapContainer.value;
+                if (!container) return;
+                const rect = container.getBoundingClientRect();
+                if (rect.width > 0 && rect.height > 0) {
+                    indexMap.kmap.map.updateSize();
+                } else {
+                    setTimeout(checkAndUpdateSize, 100);
+                }
+            };
+            setTimeout(checkAndUpdateSize, 200);
         }
-        resetAndLoad();
     });
 });
 
-const getRegionRecordData = async () => {
-    const params = {
-        // farm_id: store.state.home.miniUserFarmId,
-        farm_id: '320',
-        time: '2026-06-23',
-        work_operation_type: activeIndex.value,
-    };
-    const { code, data } = await VE_API.farm.getRegionRecord(params);
-    if (code === 200 && data && data.length > 0) {
-        taskList.value = data.filter(item => item.operation !== null);
-    } else {
-        taskList.value = [];
+const getRegionRecordList = (data) => {
+    if (!Array.isArray(data)) return [];
+    return data.filter((item) => item.operation !== null);
+};
+
+const getRegionRecordParams = (workOperationType) => ({
+    farm_id: localStorage.getItem('selectedFarmId'),
+    time: filterDate.value,
+    work_operation_type: workOperationType,
+});
+
+const taskListsByType = ref({ 0: [], 1: [], 2: [], 3: [] });
+
+const loadPageData = async () => {
+    loading.value = true;
+    try {
+        const results = await Promise.all(
+            STATUS_TAB_VALUES.map((type) => VE_API.farm.getRegionRecord(getRegionRecordParams(type)))
+        );
+        const counts = { 0: 0, 1: 0, 2: 0, 3: 0 };
+        const listsByType = { 0: [], 1: [], 2: [], 3: [] };
+        STATUS_TAB_VALUES.forEach((type, index) => {
+            const { code, data } = results[index] || {};
+            const list = code === 200 ? getRegionRecordList(data) : [];
+            listsByType[type] = list;
+            counts[type] = list.length;
+        });
+        taskListsByType.value = listsByType;
+        taskCounts.value = counts;
+        taskList.value = listsByType[activeIndex.value] || [];
+    } finally {
+        loading.value = false;
     }
 };
 
-// 监听 activeIndex 变化,重新加载数据
+// 监听 activeIndex 变化,切换 Tab 时复用已请求的数据
 watch(activeIndex, () => {
-    resetAndLoad();
+    taskList.value = taskListsByType.value[activeIndex.value] || [];
 });
 
 // 重置并重新加载
 const resetAndLoad = () => {
-    getRegionRecordData();
+    loadPageData();
 };
 
 function handleActiveFilter(i) {
@@ -455,9 +454,6 @@ function handleActiveFilter(i) {
     selectParma.value.farmWorkTypeId = null;
     const statusMap = { 0: "待接受", 1: "执行中", 2: "已接受", 3: "已完成" };
     activeStatus.value = statusMap[i] || "待接受";
-    filterDate.value = null;
-    // taskList.value = [...fullTaskList.value];
-    calendarRef.value?.clearSelection();
     syncCalendarData();
 }