ソースを参照

列表刷新防止抖动

HD_wangm 4 ヶ月 前
コミット
00f6291860

+ 1 - 12
api/user/list.uts

@@ -21,7 +21,7 @@ export const getUserList = (deptId: any): Promise<any> => {
 }
 
 /**
- * 获取用户列表
+ * 获取所有用户列表(用于负责人选择)
  */
 export const getLeaderList = (deptId: any): Promise<any> => {
 	let url = `/gxt/leader/listLeader?status=0`
@@ -29,19 +29,8 @@ export const getLeaderList = (deptId: any): Promise<any> => {
 	    // 支持工单编码和风机编号查询
 	    url += `&deptId=${deptId}`
 	}
-
     return request({
         url: url,
         method: 'GET'
     })
 }
-
-// /**
-//  * 获取所有用户列表(用于负责人选择)
-//  */
-// export const getUserList = (): Promise<any> => {
-//     return request({
-//         url: '/system/user/listNoPermi?status=0',
-//         method: 'GET'
-//     })
-// }

+ 1 - 1
pages/order/detail/acceptIndex.uvue

@@ -88,7 +88,7 @@
 			            <view class="form-picker" @click="showLeaderPicker = true">
 			                <view class="picker-display">
 			                    <text v-if="selectedTeamLeaderName" class="selected-value">{{ selectedTeamLeaderName }}</text>
-								<text v-else class="placeholder">									
+								<text v-else class="placeholder">
 									请选择工作负责人
 								</text>
 			                    <text class="arrow">▼</text>

+ 134 - 50
pages/order/index.uvue

@@ -186,6 +186,12 @@ import {checkPermi} from '../../utils/storage'
 	let currentStatus = ref<string>('') // 添加状态管理
     const statusDictList = ref<SysDictData[]>([]) // 工单状态字典列表
 
+	// 添加防重复请求的标志位(参考score/pending.uvue的实现)
+	const isSearching = ref<boolean>(false)
+	// 添加防重复刷新的标志
+	const isRefreshing = ref<boolean>(false)
+	// 添加刷新时间戳,用于防抖
+	const lastRefreshTime = ref<number>(0)
 	// 添加字典加载状态
 	const dictLoaded = ref<boolean>(false)
 	// 待处理工单加载
@@ -267,26 +273,38 @@ const statusConfig: StatusItem[] = [
 
 	let loadCount = 0
     // 加载列表数据
-    const loadData = async (isRefresh: boolean | null): Promise<void> => {
+    const loadData = async (isRefresh: boolean | null, disablePullDown: boolean | null): Promise<void> => {
 		const id = ++loadCount
-		console.log(`【loadData #${id}】开始, isRefresh=${isRefresh}`)
+		console.log(`【loadData #${id}】开始, isRefresh=${isRefresh}, disablePullDown=${disablePullDown}`)
 
+        // 防止重复请求的核心机制(参考score/pending.uvue的实现)
         if (loading.value) {
-            // 如果正在加载,直接重置刷新状态
-            refreshing.value = false
+            // 确保刷新状态最终被重置,防止卡死
+            if (isRefresh != true) {
+                refreshing.value = false;
+            }
             return
         }
 
-        try {
-            loading.value = true
+        const shouldRefresh = isRefresh != null ? isRefresh : false
+        const shouldDisablePullDown = disablePullDown != null ? disablePullDown : false
+
+        loading.value = true
+        if (shouldRefresh && !shouldDisablePullDown) {
+            page.value = 1
+            refreshing.value = true
+        } else if (shouldRefresh && shouldDisablePullDown) {
+            // 状态切换时,重置页码但不触发动画
+            page.value = 1
+            // 即使禁用下拉刷新,也要确保刷新状态最终被重置
+            refreshing.value = false
+        } else {
+            // 对于加载更多操作,不需要显示下拉刷新状态
+            refreshing.value = false;
+        }
 
+        try {
             // 处理默认值
-            const shouldRefresh = isRefresh != null ? isRefresh : false
-
-            if (shouldRefresh) {
-                page.value = 1
-            }
-            // 调用 API,传递关键字参数
             const searchKeyword = keyword.value.length > 0 ? keyword.value : null
 
             const result = await getOrderList(page.value, pageSize, searchKeyword, currentStatus.value)
@@ -361,26 +379,16 @@ const statusConfig: StatusItem[] = [
             })
         } finally {
             loading.value = false
-            // #ifdef WEB
-            // Web 平台立即重置
-            refreshing.value = false
-            // #endif
-            // #ifndef WEB
-            // App 平台延迟重置刷新状态,确保 UI 更新
-            setTimeout(() => {
-                refreshing.value = false
-            }, 100)
-            // #endif
+            // 确保刷新状态能结束(参考score/pending.uvue的实现)
+            if (shouldRefresh) {
+                refreshing.value = false;
+                // 使用setTimeout确保状态彻底重置
+                setTimeout(() => {
+                    isRefreshing.value = false;
+                }, 50);
+            }
         }
-
-        // #ifdef WEB
-        // Web 平台额外确保重置
-        refreshing.value = false
-        // #endif
     }
-
-
-
     // 辅助函数:从 any 类型提取属性
     const getOrderType = (item: any | null): string => {
         if (item == null) return ''
@@ -485,31 +493,95 @@ const statusConfig: StatusItem[] = [
 
     // 切换状态
     const switchStatus = (status: string): void => {
+        // 添加防重复调用检查(参考score/pending.uvue的实现)
+        if (loading.value) {
+            return;
+        }
+
+        // 添加防重复请求检查
+        if (isSearching.value) {
+            return
+        }
+
+        isSearching.value = true
         currentStatus.value = status
         page.value = 1
-        loadData(true)
+        loadData(true, true) // 第二个参数为true表示禁用下拉刷新动画
+
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+            isSearching.value = false
+        }, 100)
     }
 
     // 下拉刷新
     const handleRefresh = async (): Promise<void> => {
-        refreshing.value = true
-        await loadData(true as boolean | null)
+        console.log("handleRefresh被触发")
+        console.log("loading.value===",loading.value)
+        console.log("isRefreshing.value===",isRefreshing.value)
+
+        // 防抖处理,避免频繁触发(参考score/pending.uvue的实现)
+        const now = Date.now();
+        if (now - lastRefreshTime.value < 1000) {
+            refreshing.value = false;
+            return;
+        }
+        lastRefreshTime.value = now;
 
-    }
+        // 添加防重复调用检查
+        if (loading.value || isRefreshing.value) {
+            // 如果已经在加载或正在刷新,直接重置刷新状态
+            refreshing.value = false;
+            return;
+        }
 
+        console.log("loading.value1===",loading.value)
+        console.log("isRefreshing.value1===",isRefreshing.value)
+        // 设置刷新标志
+        isRefreshing.value = true;
+
+        try {
+            await loadData(true, false); // 使用默认的下拉刷新行为
+        } catch (error) {
+            console.error('刷新失败:', error);
+            refreshing.value = false;
+            isRefreshing.value = false;
+        }
+
+        // 确保在一定时间后重置刷新标志,防止意外情况
+        setTimeout(() => {
+            isRefreshing.value = false
+        }, 100) // 延迟重置,确保状态完全更新
+    }
     // 加载更多
     const loadMore = (): void => {
         if (!hasMore.value || loading.value) {
             return
         }
         page.value++
-        loadData(false as boolean | null)
+        loadData(false, false)
     }
 
     // 搜索
     const handleSearch = (): void => {
+        // 添加防重复调用检查(参考score/pending.uvue的实现)
+        if (loading.value) {
+            return;
+        }
+
+        // 添加防重复请求检查
+        if (isSearching.value) {
+            return
+        }
+
+        isSearching.value = true
         page.value = 1
-        loadData(true as boolean | null)
+        loadData(true, true) // 状态切换时禁用下拉刷新动画
+
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+            isSearching.value = false
+        }, 100)
     }
 
 	const handleSearchOnBlur = (): void => {
@@ -538,7 +610,6 @@ const statusConfig: StatusItem[] = [
 			  // 复启
 			  permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:finalize'] : ['gxt:repairOrder:finalize']
 		  }
-	  	
 	  } else if(orderItem.workOrderStatus == 'to_approve') {
 	  	// 审批
 	  	permit = orderItem.orderType == 2 ? ['gxt:maintenance:order:approve'] : ['gxt:repairOrder:approve']
@@ -619,7 +690,7 @@ const statusConfig: StatusItem[] = [
 		}
 
     }
-	
+
 	// 点击列表项
 	const handleView = (item: any | null): void => {
 	    if (item == null) return
@@ -627,7 +698,7 @@ const statusConfig: StatusItem[] = [
 		uni.navigateTo({
 			url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
 		})
-	
+
 	}
 
     // 查看工单详情
@@ -641,9 +712,25 @@ const statusConfig: StatusItem[] = [
 
     // 清空搜索
     const clearSearch = (): void => {
+        // 添加防重复调用检查(参考score/pending.uvue的实现)
+        if (loading.value) {
+            return;
+        }
+
+        // 添加防重复请求检查
+        if (isSearching.value) {
+            return
+        }
+
+        isSearching.value = true
         keyword.value = ""
         page.value = 1
-        loadData(true)
+        loadData(true, true) // 状态切换时禁用下拉刷新动画
+
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+            isSearching.value = false
+        }, 100)
     }
 
 	// 初始化
@@ -659,7 +746,7 @@ const statusConfig: StatusItem[] = [
 		// currentStatus.value = getFirstVisibleStatus()
 		currentStatus.value = 'all'
 
-	    loadData(true as boolean | null)
+	    loadData(true, true) // 首次加载时禁用下拉刷新动画
 
 		// 监听首页切换状态事件
 		uni.$on('switchOrderStatus', (status: string) => {
@@ -667,25 +754,22 @@ const statusConfig: StatusItem[] = [
 		})
 
 		// 监听接单成功的事件,刷新列表
-		uni.$on('refreshOrderList', () => {
-			page.value = 1
-			loadData(true)
-		})
-
+    uni.$on('refreshOrderList', () => {
+     page.value = 1
+     loadData(true, false)
+    })
 	})
 
     // 组件卸载前清理事件监听
     onBeforeUnmount(() => {
         refreshing.value = false
         loading.value = false
+        isRefreshing.value = false
 
 		// 移除事件监听
 		uni.$off('refreshOrderList',{})
 		uni.$off('switchOrderStatus',{})
-    })
-
-
-</script>
+    })</script>
 
 <style lang="scss">
     .list-page {

+ 113 - 36
pages/order/overdue.uvue

@@ -69,7 +69,14 @@ import {checkPermi} from '../../utils/storage'
 
 	// 添加字典加载状态
 	const dictLoaded = ref<boolean>(false)
-	
+
+	// 添加防重复请求的标志位
+	const isSearching = ref<boolean>(false)
+	// 添加防重复刷新的标志
+	const isRefreshing = ref<boolean>(false)
+	// 添加刷新时间戳,用于防抖
+	const lastRefreshTime = ref<number>(0)
+
 	// 方法:判断当前工单是否显示操作按钮(基于 orderType)
 	const canHandleOrder = (item: any | null): boolean => {
 	    if (item == null) return false
@@ -122,24 +129,34 @@ import {checkPermi} from '../../utils/storage'
 	}
 
     // 加载列表数据
-    const loadData = async (isRefresh: boolean | null): Promise<void> => {
+    const loadData = async (isRefresh: boolean | null, disablePullDown: boolean): Promise<void> => {
+        // 防止重复请求的核心机制
         if (loading.value) {
-            // 如果正在加载,直接重置刷新状态
-            refreshing.value = false
+            // 确保刷新状态最终被重置,防止卡死
+            if (isRefresh != true) {
+                refreshing.value = false;
+            }
             return
         }
 
-        try {
-            loading.value = true
+        const shouldRefresh = isRefresh != null ? isRefresh : false
 
-            // 处理默认值
-            const shouldRefresh = isRefresh != null ? isRefresh : false
+        loading.value = true
+        if (shouldRefresh && !disablePullDown) {
+            page.value = 1
+            refreshing.value = true
+        } else if (shouldRefresh && disablePullDown) {
+            // 状态切换时,重置页码但不触发动画
+            page.value = 1
+            // 即使禁用下拉刷新,也要确保刷新状态最终被重置
+            refreshing.value = false
+        } else {
+            // 对于加载更多操作,不需要显示下拉刷新状态
+            refreshing.value = false;
+        }
 
-            if (shouldRefresh) {
-                page.value = 1
-            }
-			console.log("searchKeyword===" + keyword.value)
-            // 调用 API,传递关键字参数
+        try {
+            // 处理默认值
             const searchKeyword = keyword.value.length > 0 ? keyword.value : null
 
             const result = await overdueList(page.value, pageSize, searchKeyword)
@@ -208,22 +225,15 @@ import {checkPermi} from '../../utils/storage'
             })
         } finally {
             loading.value = false
-            // #ifdef WEB
-            // Web 平台立即重置
-            refreshing.value = false
-            // #endif
-            // #ifndef WEB
-            // App 平台延迟重置刷新状态,确保 UI 更新
-            setTimeout(() => {
-                refreshing.value = false
-            }, 100)
-            // #endif
+            // 确保刷新状态能结束
+            if (shouldRefresh) {
+                refreshing.value = false;
+                // 使用setTimeout确保状态彻底重置
+                setTimeout(() => {
+                    isRefreshing.value = false;
+                }, 50);
+            }
         }
-
-        // #ifdef WEB
-        // Web 平台额外确保重置
-        refreshing.value = false
-        // #endif
     }
 
     // 辅助函数:从 any 类型提取属性
@@ -280,8 +290,43 @@ import {checkPermi} from '../../utils/storage'
 
     // 下拉刷新
     const handleRefresh = async (): Promise<void> => {
-        refreshing.value = true
-        await loadData(true as boolean | null)
+        console.log("handleRefresh被触发")
+        console.log("loading.value===",loading.value)
+        console.log("isRefreshing.value===",isRefreshing.value)
+
+        // 防抖处理,避免频繁触发
+        const now = Date.now();
+        if (now - lastRefreshTime.value < 1000) {
+            console.log("刷新操作过于频繁,忽略本次触发");
+            refreshing.value = false;
+            return;
+        }
+        lastRefreshTime.value = now;
+
+        // 添加防重复调用检查
+        if (loading.value || isRefreshing.value) {
+            // 如果已经在加载或正在刷新,直接重置刷新状态
+            refreshing.value = false;
+            return;
+        }
+
+        console.log("loading.value1===",loading.value)
+        console.log("isRefreshing.value1===",isRefreshing.value)
+        // 设置刷新标志
+        isRefreshing.value = true;
+
+        try {
+            await loadData(true, false); // 使用默认的下拉刷新行为
+        } catch (error) {
+            console.error('刷新失败:', error);
+            refreshing.value = false;
+            isRefreshing.value = false;
+        }
+
+        // 确保在一定时间后重置刷新标志,防止意外情况
+        setTimeout(() => {
+            isRefreshing.value = false
+        }, 100) // 延迟重置,确保状态完全更新
     }
 
     // 加载更多
@@ -290,14 +335,29 @@ import {checkPermi} from '../../utils/storage'
             return
         }
         page.value++
-        loadData(false as boolean | null)
+        loadData(false, false) // 加载更多时不涉及下拉刷新动画
     }
 
     // 搜索
     const handleSearch = (): void => {
+        // 添加防重复调用检查
+        if (loading.value) {
+            return;
+        }
+
+        // 添加防重复请求检查
+        if (isSearching.value) {
+            return
+        }
+
+        isSearching.value = true
         page.value = 1
-		console.log("======搜索=====" + keyword.value)
-        loadData(true as boolean | null)
+        loadData(true, true) // 状态切换时禁用下拉刷新动画
+
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+            isSearching.value = false
+        }, 100)
     }
 
     // 点击列表项
@@ -312,19 +372,35 @@ import {checkPermi} from '../../utils/storage'
 
     // 清空搜索
     const clearSearch = (): void => {
+        // 添加防重复调用检查
+        if (loading.value) {
+            return;
+        }
+
+        // 添加防重复请求检查
+        if (isSearching.value) {
+            return
+        }
+
+        isSearching.value = true
         keyword.value = ""
         page.value = 1
-        loadData(true)
+        loadData(true, true) // 状态切换时禁用下拉刷新动画
+
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+            isSearching.value = false
+        }, 100)
     }
 
 	// 初始化
 	onMounted(() => {
 	    loadStatusDictList()
-	    loadData(true as boolean | null)
+	    loadData(true as boolean | null, false)
 		// 监听接单成功的事件,刷新列表
 		uni.$on('refreshOrderList', () => {
 			page.value = 1
-			loadData(true)
+			loadData(true, false)
 		})
 	})
 
@@ -332,6 +408,7 @@ import {checkPermi} from '../../utils/storage'
     onBeforeUnmount(() => {
         refreshing.value = false
         loading.value = false
+        isRefreshing.value = false
 		// 移除事件监听
 		uni.$off('refreshOrderList',{})
     })

+ 120 - 40
pages/order/pendingOrder.uvue

@@ -90,13 +90,20 @@ import {checkPermi} from '../../utils/storage'
 
 	// 添加字典加载状态
 	const dictLoaded = ref<boolean>(false)
-	
+
+	// 添加防重复请求的标志位
+	const isSearching = ref<boolean>(false)
+	// 添加防重复刷新的标志
+	const isRefreshing = ref<boolean>(false)
+	// 添加刷新时间戳,用于防抖
+	const lastRefreshTime = ref<number>(0)
+
 	const getOrderStatus = (item: any | null): string => {
 		if (item == null) return ''
 		const orderItem = item as acceptOrderInfo
 		return orderItem.workOrderStatus ?? ''
 	}
-	
+
 	// 方法:判断当前工单是否显示操作按钮(基于 orderType)
 	const canHandleOrder = (item: any | null): boolean => {
 	  if (item == null) return false
@@ -117,7 +124,7 @@ import {checkPermi} from '../../utils/storage'
 	  } else {
 		  return false
 	  }
-	  
+
 	  // const orderType = (item as acceptOrderInfo).orderType
 	  return checkPermi(permit)
 	}
@@ -164,23 +171,35 @@ import {checkPermi} from '../../utils/storage'
 	}
 
     // 加载列表数据
-    const loadData = async (isRefresh: boolean | null): Promise<void> => {
+    const loadData = async (isRefresh: boolean | null, disablePullDown: boolean | null): Promise<void> => {
+        // 防止重复请求的核心机制
         if (loading.value) {
-            // 如果正在加载,直接重置刷新状态
-            refreshing.value = false
+            // 确保刷新状态最终被重置,防止卡死
+            if (isRefresh != true) {
+                refreshing.value = false;
+            }
             return
         }
 
-        try {
-            loading.value = true
+        const shouldRefresh = isRefresh != null ? isRefresh : false
+        const disablePull = disablePullDown != null ? disablePullDown : false
+
+        loading.value = true
+        if (shouldRefresh && !disablePull) {
+            page.value = 1
+            refreshing.value = true
+        } else if (shouldRefresh && disablePull) {
+            // 状态切换时,重置页码但不触发动画
+            page.value = 1
+            // 即使禁用下拉刷新,也要确保刷新状态最终被重置
+            refreshing.value = false
+        } else {
+            // 对于加载更多操作,不需要显示下拉刷新状态
+            refreshing.value = false;
+        }
 
+        try {
             // 处理默认值
-            const shouldRefresh = isRefresh != null ? isRefresh : false
-
-            if (shouldRefresh) {
-                page.value = 1
-            }
-            // 调用 API,传递关键字参数
             const searchKeyword = keyword.value.length > 0 ? keyword.value : null
 
             const result = await pendingList(page.value, pageSize, searchKeyword)
@@ -249,22 +268,15 @@ import {checkPermi} from '../../utils/storage'
             })
         } finally {
             loading.value = false
-            // #ifdef WEB
-            // Web 平台立即重置
-            refreshing.value = false
-            // #endif
-            // #ifndef WEB
-            // App 平台延迟重置刷新状态,确保 UI 更新
-            setTimeout(() => {
-                refreshing.value = false
-            }, 100)
-            // #endif
+            // 确保刷新状态能结束
+            if (shouldRefresh) {
+                refreshing.value = false;
+                // 使用setTimeout确保状态彻底重置
+                setTimeout(() => {
+                    isRefreshing.value = false;
+                }, 50);
+            }
         }
-
-        // #ifdef WEB
-        // Web 平台额外确保重置
-        refreshing.value = false
-        // #endif
     }
 
     // 辅助函数:从 any 类型提取属性
@@ -285,12 +297,12 @@ import {checkPermi} from '../../utils/storage'
         const orderInfoItem = item as acceptOrderInfo
         return orderInfoItem.pcsDeviceName
     }
-	
+
 	// 根据状态显示不同的时间
 	const getDisplayTime = (item: any | null): string|null => {
 		if (item == null) return null
 		const orderInfoItem = item as acceptOrderInfo
-	
+
 		// 如果是"待接单"状态,显示派单时间
 		if (orderInfoItem.workOrderStatus == 'assigned') {
 			return '下发时间:' + orderInfoItem.assignTime
@@ -308,7 +320,7 @@ import {checkPermi} from '../../utils/storage'
 		} else if(orderInfoItem.workOrderStatus == 'completed') {
 			return '结单时间:' + orderInfoItem.updateTime
 		}
-	
+
 		// 默认显示创建时间
 		return '创建时间:' + orderInfoItem.createTime
 	}
@@ -343,8 +355,43 @@ import {checkPermi} from '../../utils/storage'
 
     // 下拉刷新
     const handleRefresh = async (): Promise<void> => {
-        refreshing.value = true
-        await loadData(true as boolean | null)
+        console.log("handleRefresh被触发")
+        console.log("loading.value===",loading.value)
+        console.log("isRefreshing.value===",isRefreshing.value)
+
+        // 防抖处理,避免频繁触发
+        const now = Date.now();
+        if (now - lastRefreshTime.value < 1000) {
+            console.log("刷新操作过于频繁,忽略本次触发");
+            refreshing.value = false;
+            return;
+        }
+        lastRefreshTime.value = now;
+
+        // 添加防重复调用检查
+        if (loading.value || isRefreshing.value) {
+            // 如果已经在加载或正在刷新,直接重置刷新状态
+            refreshing.value = false;
+            return;
+        }
+
+        console.log("loading.value1===",loading.value)
+        console.log("isRefreshing.value1===",isRefreshing.value)
+        // 设置刷新标志
+        isRefreshing.value = true;
+
+        try {
+            await loadData(true, false); // 使用默认的下拉刷新行为
+        } catch (error) {
+            console.error('刷新失败:', error);
+            refreshing.value = false;
+            isRefreshing.value = false;
+        }
+
+        // 确保在一定时间后重置刷新标志,防止意外情况
+        setTimeout(() => {
+            isRefreshing.value = false
+        }, 100) // 延迟重置,确保状态完全更新
     }
 
     // 加载更多
@@ -353,13 +400,29 @@ import {checkPermi} from '../../utils/storage'
             return
         }
         page.value++
-        loadData(false as boolean | null)
+        loadData(false, false) // 加载更多时不涉及下拉刷新动画
     }
 
     // 搜索
     const handleSearch = (): void => {
+        // 添加防重复调用检查
+        if (loading.value) {
+            return;
+        }
+
+        // 添加防重复请求检查
+        if (isSearching.value) {
+            return
+        }
+
+        isSearching.value = true
         page.value = 1
-        loadData(true as boolean | null)
+        loadData(true, true) // 状态切换时禁用下拉刷新动画
+
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+            isSearching.value = false
+        }, 100)
     }
 
     // 点击列表项
@@ -385,24 +448,40 @@ import {checkPermi} from '../../utils/storage'
 			    url: `/pages/order/detail/index?id=${orderItem.id}&orderType=${orderItem.orderType}`
 			})
 		}
-		
+
     }
 
     // 清空搜索
     const clearSearch = (): void => {
+        // 添加防重复调用检查
+        if (loading.value) {
+            return;
+        }
+
+        // 添加防重复请求检查
+        if (isSearching.value) {
+            return
+        }
+
+        isSearching.value = true
         keyword.value = ""
         page.value = 1
-        loadData(true)
+        loadData(true, true) // 状态切换时禁用下拉刷新动画
+
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+            isSearching.value = false
+        }, 100)
     }
 
 	// 初始化
 	onMounted(() => {
 	    loadStatusDictList()
-	    loadData(true as boolean | null)
+	    loadData(true, false)
 		// 监听接单成功的事件,刷新列表
 		uni.$on('refreshOrderList', () => {
 			page.value = 1
-			loadData(true)
+			loadData(true, false)
 		})
 	})
 
@@ -410,6 +489,7 @@ import {checkPermi} from '../../utils/storage'
     onBeforeUnmount(() => {
         refreshing.value = false
         loading.value = false
+        isRefreshing.value = false
 		// 移除事件监听
 		uni.$off('refreshOrderList',{})
     })

+ 21 - 21
pages/score/index.uvue

@@ -215,7 +215,7 @@
     const isRefreshing = ref<boolean>(false)
     // 添加刷新时间戳,用于防抖
     const lastRefreshTime = ref<number>(0)
-    
+
     // 添加防抖定时器
     let searchTimer: number | null = null
 
@@ -514,12 +514,12 @@
 	  showDatePicker.value = false
 	  showDatePickerPopup.value = false
 	  selectedMonth.value = 'custom'
-	  
+
       // 添加防重复调用检查
       if (loading.value) {
         return;
       }
-      
+
 	  getStatistics()
 	}
 
@@ -622,18 +622,18 @@
       if (loading.value) {
         return;
       }
-      
+
       // 添加防抖和防止重复请求
       if (isSearching.value) {
         return
       }
-      
+
       const timer = searchTimer
       if (timer != null) {
         clearTimeout(timer)
         searchTimer = null
       }
-      
+
       searchTimer = setTimeout(() => {
         isSearching.value = true
         loadData(true, true); // 添加true参数表示这是筛选条件变化触发的加载,应禁用下拉刷新
@@ -649,18 +649,18 @@
       if (loading.value) {
         return;
       }
-      
+
       // 添加防抖和防止重复请求
       if (isSearching.value) {
         return
       }
-      
+
       const timer = searchTimer
       if (timer != null) {
         clearTimeout(timer)
         searchTimer = null
       }
-      
+
       searchKeyword.value = ""
       searchTimer = setTimeout(() => {
         isSearching.value = true
@@ -677,18 +677,18 @@
       if (loading.value) {
         return;
       }
-      
+
       // 添加防止重复请求
       if (isSearching.value) {
         return
       }
-      
+
       const timer = searchTimer
       if (timer != null) {
         clearTimeout(timer)
         searchTimer = null
       }
-      
+
       statusFilter.value = status
       searchTimer = setTimeout(() => {
         isSearching.value = true
@@ -706,18 +706,18 @@
       if (loading.value) {
         return;
       }
-      
+
 	  // 添加防止重复请求
 	  if (isSearching.value) {
 	    return
 	  }
-	  
+
       const timer = searchTimer
       if (timer != null) {
         clearTimeout(timer)
         searchTimer = null
       }
-      
+
       selectedMonth.value = month
       searchTimer = setTimeout(() => {
         getStatistics()
@@ -736,7 +736,7 @@
       console.log("handleRefresh被触发")
       console.log("loading.value===",loading.value)
       console.log("isRefreshing.value===",isRefreshing.value)
-      
+
       // 防抖处理,避免频繁触发
       const now = Date.now();
       if (now - lastRefreshTime.value < 1000) {
@@ -745,7 +745,7 @@
         return;
       }
       lastRefreshTime.value = now;
-      
+
       // 添加防重复调用检查
       if (loading.value || isRefreshing.value) {
         // 如果已经在加载或正在刷新,直接重置刷新状态
@@ -756,9 +756,9 @@
         console.log("isRefreshing.value1===",isRefreshing.value)
       // 设置刷新标志
       isRefreshing.value = true;
-      
+
       loadData(true); // 使用默认的下拉刷新行为
-      
+
       // 确保在一定时间后重置刷新标志,防止意外情况
       setTimeout(() => {
         isRefreshing.value = false
@@ -814,7 +814,7 @@
       getStatistics()
       dictLoaded.value = true
     })
-    
+
     // 组件销毁时清除定时器
     onBeforeUnmount(() => {
       const timer = searchTimer
@@ -822,7 +822,7 @@
         clearTimeout(timer)
         searchTimer = null
       }
-      
+
       // 如果组件销毁前还有未完成的刷新操作,确保状态被重置
       loading.value = false;
       refreshing.value = false;

+ 198 - 124
pages/score/pending.uvue

@@ -16,100 +16,6 @@
       </view>
     </view>
 
-    <!-- 工单评分状态筛选 -->
-    <!-- <view class="status-bar">
-      <view class="status-box">
-        <text
-          class="status-txt"
-          :class="{ 'status-sel': statusFilter === '' }"
-          @click="filterByStatus('')"
-        >
-          全部
-        </text>
-        <text
-          class="status-txt"
-          :class="{ 'status-sel': statusFilter === 'to_self' }"
-          @click="filterByStatus('to_self')"
-        >
-          待自评
-        </text>
-        <text
-          class="status-txt"
-          :class="{ 'status-sel': statusFilter === 'to_re' }"
-          @click="filterByStatus('to_re')"
-        >
-          待复评
-        </text>
-        <text
-          class="status-txt"
-          :class="{ 'status-sel': statusFilter === 'to_confirm' }"
-          @click="filterByStatus('to_confirm')"
-        >
-          待确认
-        </text>
-        <text
-          class="status-txt"
-          :class="{ 'status-sel': statusFilter === 'to_final' }"
-          @click="filterByStatus('to_final')"
-        >
-          待终评
-        </text>
-      </view>
-    </view> -->
-
-    <!-- 工分统计 -->
-    <!-- <view class="stats-section">
-      <view class="stats-header">
-        <text class="stats-title">{{ monthTitle }}月度工分</text>
-        <view class="month-filters">
-          <text
-            class="month-filter"
-            :class="{ 'month-filter-sel': selectedMonth === 'prev' }"
-            @click="changeMonth('prev')"
-          >
-            上月
-          </text>
-          <text
-            class="month-filter"
-            :class="{ 'month-filter-sel': selectedMonth === 'current' }"
-            @click="changeMonth('current')"
-          >
-            本月
-          </text>
-          <text
-            class="month-filter"
-            :class="{ 'month-filter-sel': selectedMonth === 'custom' }"
-            @click="showCustomDatePicker"
-          >
-            自定义
-          </text>
-        </view>
-      </view> -->
-
-      <!-- 统计数据 -->
-      <!-- <view class="stats-content">
-        <view class="total-score">
-          <text class="score-value">{{ totalScore }}分</text>
-          <text class="score-label">{{ monthTitle }}总工分</text>
-        </view>
-
-        <view class="score-breakdown">
-          <view class="breakdown-item">
-            <text class="breakdown-label">维保工分</text>
-            <text class="breakdown-value">{{ maintenanceScore }}分</text>
-          </view>
-          <view class="breakdown-item">
-            <text class="breakdown-label">维修工分</text>
-            <text class="breakdown-value">{{ repairScore }}分</text>
-          </view>
-          <view v-if="rank !== null && totalRankingUsers !== null" class="breakdown-item">
-            <text class="breakdown-label">排名</text>
-            <text class="breakdown-value">{{ rank }}/{{ totalRankingUsers }}</text>
-          </view>
-        </view>
-      </view>
-    </view> -->
-
     <!-- 工单评分列表 -->
     <common-list
       :dataList="orderList"
@@ -133,14 +39,13 @@
               <view class="info-label">
                 <text class="text-gray">{{ getWorkOrderTypeInfo(item) }}</text>
               </view>
-              <view class="info-value-row">
+              <!-- <view class="info-value-row">
                 <text v-if="getPropertyValue(item, 'score') !== ''" class="score-text">{{ formatNumber(parseFloat(getPropertyValue(item, 'score'))) }}</text>
-                <!-- <text class="status-text">{{ getOrderStatusText(getPropertyValue(item, 'scoreStatus')) }}</text> -->
-              </view>
-            </view>
+              </view> -->
+			</view>
 			<view class="info-row">
 			  <view class="info-label">
-			    <text class="text-gray">工作结束时间: {{ formatDate(getPropertyValue(item, 'assignTime')) }}</text>
+			    <text class="text-gray">工作结束时间: {{ formatDate(getPropertyValue(item, 'realEndTime')) }}</text>
 			  </view>
 			</view>
           </view>
@@ -182,19 +87,17 @@
       </l-date-time-picker>
     </l-popup>
 
-    <!-- 底部 TabBar -->
-    <!-- <custom-tabbar :current="3" /> -->
   </view>
 </template>
 
 <script setup lang="uts">
-    import { ref, computed, onMounted } from 'vue'
+    import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
     import { listOrderScores, getOrderScoreStatistics, listMyRate } from '@/api/score/index'
     import { getDictDataByType } from '@/api/dict/index'
     import type { SysDictData } from '@/types/dict'
 
     // 数据状态
-    let searchKeyword = ref<string>('')
+    const searchKeyword = ref<string>('')
     const statusFilter = ref<string>('')
     const selectedMonth = ref<string>('current')
     const loading = ref<boolean>(false)
@@ -209,6 +112,16 @@
     const totalRankingUsers = ref<number | null>(null)
     const customDate = ref<string>('')
 
+    // 防止重复请求的标志位
+    const isSearching = ref<boolean>(false)
+    // 添加防重复刷新的标志
+    const isRefreshing = ref<boolean>(false)
+    // 添加刷新时间戳,用于防抖
+    const lastRefreshTime = ref<number>(0)
+
+    // 添加防抖定时器
+    let searchTimer: number | null = null
+
     // 弹窗显示状态
     const showDatePickerPopup = ref<boolean>(false)
     const showDatePicker = ref<boolean>(false)
@@ -504,21 +417,40 @@
 	  showDatePicker.value = false
 	  showDatePickerPopup.value = false
 	  selectedMonth.value = 'custom'
+
+      // 添加防重复调用检查
+      if (loading.value) {
+        return;
+      }
+
 	  getStatistics()
 	}
 
     // 方法
-    function loadData(isRefresh: boolean) {
-      const shouldRefresh = isRefresh
-
-      if (loading.value && !shouldRefresh) {
+    function loadData(isRefresh: boolean, disablePullDown = false) {
+      // 防止重复请求的核心机制 - 参考工单页面的简单有效方式
+      if (loading.value) {
+        // 确保刷新状态最终被重置,防止卡死
+        if (!isRefresh) {
+          refreshing.value = false;
+        }
         return
       }
 
+      const shouldRefresh = isRefresh !== false
+
       loading.value = true
-      if (shouldRefresh) {
+      if (shouldRefresh && !disablePullDown) {
         currentPage.value = 1
         refreshing.value = true
+      } else if (shouldRefresh && disablePullDown) {
+        // 筛选条件变化时,重置页码但不触发下拉刷新
+        currentPage.value = 1
+        // 即使禁用下拉刷新,也要确保刷新状态最终被重置
+        refreshing.value = false
+      } else {
+        // 对于加载更多操作,不需要显示下拉刷新状态
+        refreshing.value = false;
       }
 
       // Convert 'current' and 'prev' values to actual date strings
@@ -567,36 +499,136 @@
         }
 
         hasMore.value = orderList.value.length < responseTotal
-        loading.value = false
-        refreshing.value = false
-      }).catch(() => {
-        loading.value = false
-        refreshing.value = false
+      }).catch((error) => {
+        console.error('获取工单列表失败:', error);
+        // 出错时也需要重置刷新状态
+        if (shouldRefresh) {
+          refreshing.value = false;
+          isRefreshing.value = false;
+        }
+      }).finally(() => {
+        // 无论成功还是失败,都重置所有加载状态
+        loading.value = false;
+        // 确保刷新状态最终被重置
+        if (shouldRefresh) {
+          refreshing.value = false;
+          // 使用setTimeout确保状态彻底重置
+          setTimeout(() => {
+            isRefreshing.value = false;
+          }, 50);
+        }
       })
     }
 
     function handleSearch() {
-      loadData(true)
+      // 添加防重复调用检查
+      if (loading.value) {
+        return;
+      }
+
+      // 添加防抖和防止重复请求
+      if (isSearching.value) {
+        return
+      }
+
+      const timer = searchTimer
+      if (timer != null) {
+        clearTimeout(timer)
+        searchTimer = null
+      }
+
+      searchTimer = setTimeout(() => {
+        isSearching.value = true
+        loadData(true, true); // 添加true参数表示这是筛选条件变化触发的加载,应禁用下拉刷新
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+          isSearching.value = false
+        }, 100)
+      }, 300)
     }
 
     function clearSearch() {
+      // 添加防重复调用检查
+      if (loading.value) {
+        return;
+      }
+
+      // 添加防抖和防止重复请求
+      if (isSearching.value) {
+        return
+      }
+
+      const timer = searchTimer
+      if (timer != null) {
+        clearTimeout(timer)
+        searchTimer = null
+      }
+
       searchKeyword.value = ""
-      loadData(true)
+      searchTimer = setTimeout(() => {
+        isSearching.value = true
+        loadData(true, true); // 添加true参数表示这是筛选条件变化触发的加载,应禁用下拉刷新
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+          isSearching.value = false
+        }, 100)
+      }, 300)
     }
 
     function filterByStatus(status: string) {
+      // 添加防重复调用检查
+      if (loading.value) {
+        return;
+      }
+
+      // 添加防止重复请求
+      if (isSearching.value) {
+        return
+      }
+
+      const timer = searchTimer
+      if (timer != null) {
+        clearTimeout(timer)
+        searchTimer = null
+      }
+
       statusFilter.value = status
-      loadData(true)
-      getStatistics()
+      searchTimer = setTimeout(() => {
+        isSearching.value = true
+        loadData(true, true); // 添加true参数表示这是筛选条件变化触发的加载,应禁用下拉刷新
+        getStatistics()
+        // 延迟重置标志位,确保请求发送后才允许下一次搜索
+        setTimeout(() => {
+          isSearching.value = false
+        }, 100)
+      }, 300)
     }
 
-    function changeMonth(month: string) {
+	function changeMonth(month: string) {
+	  // 添加防重复调用检查
+      if (loading.value) {
+        return;
+      }
+
+	  // 添加防止重复请求
+	  if (isSearching.value) {
+	    return
+	  }
+
+      const timer = searchTimer
+      if (timer != null) {
+        clearTimeout(timer)
+        searchTimer = null
+      }
+
       selectedMonth.value = month
-      //loadData(true)
-      getStatistics()
-    }
+      searchTimer = setTimeout(() => {
+        getStatistics()
+      }, 300)
+	}
 
     function loadMore() {
+      console.log("loadMore被触发")
       if (!hasMore.value || loading.value) return
 
       currentPage.value++
@@ -604,7 +636,36 @@
     }
 
     function handleRefresh() {
-      loadData(true)
+      console.log("handleRefresh被触发")
+      console.log("loading.value===",loading.value)
+      console.log("isRefreshing.value===",isRefreshing.value)
+
+      // 防抖处理,避免频繁触发
+      const now = Date.now();
+      if (now - lastRefreshTime.value < 1000) {
+        console.log("刷新操作过于频繁,忽略本次触发");
+        refreshing.value = false;
+        return;
+      }
+      lastRefreshTime.value = now;
+
+      // 添加防重复调用检查
+      if (loading.value || isRefreshing.value) {
+        // 如果已经在加载或正在刷新,直接重置刷新状态
+        refreshing.value = false;
+        return;
+      }
+      console.log("loading.value1===",loading.value)
+        console.log("isRefreshing.value1===",isRefreshing.value)
+      // 设置刷新标志
+      isRefreshing.value = true;
+
+      loadData(true); // 使用默认的下拉刷新行为
+
+      // 确保在一定时间后重置刷新标志,防止意外情况
+      setTimeout(() => {
+        isRefreshing.value = false
+      }, 100) // 延迟重置,确保状态完全更新
     }
 
     // 点击列表项
@@ -656,6 +717,20 @@
       getStatistics()
       dictLoaded.value = true
     })
+
+    // 组件销毁时清除定时器
+    onBeforeUnmount(() => {
+      const timer = searchTimer
+      if (timer != null) {
+        clearTimeout(timer)
+        searchTimer = null
+      }
+
+      // 如果组件销毁前还有未完成的刷新操作,确保状态被重置
+      loading.value = false;
+      refreshing.value = false;
+      isRefreshing.value = false;
+    })
 </script>
 
 <style lang="scss">
@@ -720,7 +795,7 @@
     font-size: 28rpx;
   }
 
-  .status-sel {
+  .stauts-sel {
     background-color: #007AFF;
     color: #fff;
   }
@@ -1010,4 +1085,3 @@
   border-color: #c2e7b0;
 }
 </style>
-

+ 10 - 10
pages/worktime/index.uvue

@@ -551,7 +551,7 @@ function handleSearch() {
   if (loading.value) {
     return;
   }
-  
+
   loadData(true, true); // 添加true参数表示这是筛选条件变化触发的加载,应禁用下拉刷新
   getStatistics()
 }
@@ -575,7 +575,7 @@ function filterByOrderType(type: string) {
   if (loading.value) {
     return;
   }
-  
+
   orderTypeFilter.value = type;
   loadData(true, true); // 添加true参数表示这是筛选条件变化触发的加载,应禁用下拉刷新
   getStatistics();
@@ -587,7 +587,7 @@ function changeTimeRange(range: string) {
   if (loading.value) {
     return;
   }
-  
+
   timeRange.value = range;
   loadData(true, true); // 添加true参数表示这是筛选条件变化触发的加载,应禁用下拉刷新
   getStatistics();
@@ -607,7 +607,7 @@ function changeTimeRangeWithCheck(range: string) {
     return;
   }
   changeTimeRange(range);
-} 
+}
 
 function loadMore() {
 	console.log("loadMore被触发")
@@ -621,7 +621,7 @@ function handleRefresh() {
 	console.log("handleRefresh被触发")
 	console.log("loading.value===",loading.value)
 	console.log("isRefreshing.value===",isRefreshing.value)
-	
+
 	// 防抖处理,避免频繁触发
 	const now = Date.now();
 	if (now - lastRefreshTime.value < 1000) {
@@ -630,7 +630,7 @@ function handleRefresh() {
 		return;
 	}
 	lastRefreshTime.value = now;
-	
+
   // 添加防重复调用检查
   if (loading.value || isRefreshing.value) {
     // 如果已经在加载或正在刷新,直接重置刷新状态
@@ -641,9 +641,9 @@ function handleRefresh() {
   	console.log("isRefreshing.value1===",isRefreshing.value)
   // 设置刷新标志
   isRefreshing.value = true;
-  
+
   loadData(true); // 使用默认的下拉刷新行为
-  
+
   // 确保在一定时间后重置刷新标志,防止意外情况
   setTimeout(() => {
     isRefreshing.value = false
@@ -689,12 +689,12 @@ function confirmCustomDate() {
 
   closeDatePicker()
   timeRange.value = 'custom'
-  
+
   // 添加防重复调用检查
   if (loading.value) {
     return;
   }
-  
+
   loadData(true, true); // 添加true参数表示这是筛选条件变化触发的加载,应禁用下拉刷新
   getStatistics()
 }