|
|
@@ -10,7 +10,7 @@
|
|
|
placeholder="搜索工单编码、风机编号"
|
|
|
v-model="searchKeyword"
|
|
|
@confirm="handleSearch"
|
|
|
- @blur="handleSearch"
|
|
|
+ @blur="handleSearchWithPrevent"
|
|
|
/>
|
|
|
<text v-if="searchKeyword.length > 0" class="clear-icon" @click="clearSearch">✕</text>
|
|
|
</view>
|
|
|
@@ -22,21 +22,21 @@
|
|
|
<text
|
|
|
class="status-txt"
|
|
|
:class="{ 'stauts-sel': orderTypeFilter === '' }"
|
|
|
- @click="filterByOrderType('')"
|
|
|
+ @click="filterByOrderTypeWithCheck('')"
|
|
|
>
|
|
|
全部
|
|
|
</text>
|
|
|
<text
|
|
|
class="status-txt"
|
|
|
:class="{ 'stauts-sel': orderTypeFilter === '1' }"
|
|
|
- @click="filterByOrderType('1')"
|
|
|
+ @click="filterByOrderTypeWithCheck('1')"
|
|
|
>
|
|
|
维修工单
|
|
|
</text>
|
|
|
<text
|
|
|
class="status-txt"
|
|
|
:class="{ 'stauts-sel': orderTypeFilter === '2' }"
|
|
|
- @click="filterByOrderType('2')"
|
|
|
+ @click="filterByOrderTypeWithCheck('2')"
|
|
|
>
|
|
|
维保工单
|
|
|
</text>
|
|
|
@@ -51,21 +51,21 @@
|
|
|
<text
|
|
|
class="time-filter"
|
|
|
:class="{ 'time-filter-sel': timeRange === 'week' }"
|
|
|
- @click="changeTimeRange('week')"
|
|
|
+ @click="changeTimeRangeWithCheck('week')"
|
|
|
>
|
|
|
本周
|
|
|
</text>
|
|
|
<text
|
|
|
class="time-filter"
|
|
|
:class="{ 'time-filter-sel': timeRange === 'month' }"
|
|
|
- @click="changeTimeRange('month')"
|
|
|
+ @click="changeTimeRangeWithCheck('month')"
|
|
|
>
|
|
|
本月
|
|
|
</text>
|
|
|
<text
|
|
|
class="time-filter"
|
|
|
:class="{ 'time-filter-sel': timeRange === 'custom' }"
|
|
|
- @click="showCustomDatePicker"
|
|
|
+ @click="showCustomDatePickerWithCheck"
|
|
|
>
|
|
|
自定义
|
|
|
</text>
|
|
|
@@ -215,9 +215,11 @@ const totalRankingUsers = ref<number | null>(null)
|
|
|
|
|
|
// 防止重复请求的标志位
|
|
|
const isSearching = ref<boolean>(false)
|
|
|
+const isRequestPending = ref<boolean>(false)
|
|
|
|
|
|
// 添加防抖定时器
|
|
|
let searchTimer: number | null = null
|
|
|
+let lastRequestTime: number = 0
|
|
|
|
|
|
// 弹窗显示状态
|
|
|
const showDatePickerPopup = ref<boolean>(false)
|
|
|
@@ -426,6 +428,7 @@ function getStatistics() {
|
|
|
params.endDate = endDate.value
|
|
|
}
|
|
|
|
|
|
+ // 添加 finally 块确保状态始终会被重置
|
|
|
getOrderHourStatistics(params).then((response: any) => {
|
|
|
const resultObj = response as UTSJSONObject
|
|
|
const responseData = resultObj['data'] as UTSJSONObject
|
|
|
@@ -443,21 +446,43 @@ function getStatistics() {
|
|
|
rank.value = null
|
|
|
totalRankingUsers.value = null
|
|
|
}
|
|
|
+ }).catch((error) => {
|
|
|
+ console.error('获取工时统计数据失败:', error);
|
|
|
+ // 发生错误时也要重置数据
|
|
|
+ totalHours.value = 0
|
|
|
+ maintenanceHours.value = 0
|
|
|
+ repairHours.value = 0
|
|
|
+ rank.value = null
|
|
|
+ totalRankingUsers.value = null;
|
|
|
+ }).finally(() => {
|
|
|
+ // 统计数据获取完成,无特定加载状态需要重置
|
|
|
})
|
|
|
}
|
|
|
|
|
|
// 方法
|
|
|
function loadData(isRefresh: boolean) {
|
|
|
- const shouldRefresh = isRefresh
|
|
|
-
|
|
|
- if (loading.value && !shouldRefresh) {
|
|
|
+ // 防止重复请求的核心机制
|
|
|
+ if (loading.value || isRequestPending.value) {
|
|
|
return
|
|
|
}
|
|
|
+
|
|
|
+ // iOS防抖处理,避免短时间内重复请求
|
|
|
+ const currentTime = new Date().getTime();
|
|
|
+ if (currentTime - lastRequestTime < 300) { // 300ms内不重复请求
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ lastRequestTime = currentTime;
|
|
|
+
|
|
|
+ isRequestPending.value = true;
|
|
|
+ const shouldRefresh = isRefresh !== false
|
|
|
|
|
|
loading.value = true
|
|
|
if (shouldRefresh) {
|
|
|
currentPage.value = 1
|
|
|
refreshing.value = true
|
|
|
+ } else {
|
|
|
+ // 对于加载更多操作,不需要显示下拉刷新状态
|
|
|
+ refreshing.value = false;
|
|
|
}
|
|
|
|
|
|
const params: UTSJSONObject = {
|
|
|
@@ -473,6 +498,7 @@ function loadData(isRefresh: boolean) {
|
|
|
params.endDate = endDate.value
|
|
|
}
|
|
|
|
|
|
+ // 添加 finally 块确保状态始终会被重置
|
|
|
listOrderHours(params).then((response: any) => {
|
|
|
// 提取响应数据
|
|
|
const resultObj = response as UTSJSONObject
|
|
|
@@ -488,109 +514,92 @@ function loadData(isRefresh: boolean) {
|
|
|
}
|
|
|
|
|
|
hasMore.value = orderList.value.length < responseTotal
|
|
|
- loading.value = false
|
|
|
- refreshing.value = false
|
|
|
- }).catch(() => {
|
|
|
- loading.value = false
|
|
|
- refreshing.value = false
|
|
|
+ }).catch((error) => {
|
|
|
+ console.error('获取工单列表失败:', error);
|
|
|
+ }).finally(() => {
|
|
|
+ // 无论成功还是失败,都重置所有加载状态
|
|
|
+ loading.value = false;
|
|
|
+ refreshing.value = false;
|
|
|
+ isRequestPending.value = false;
|
|
|
})
|
|
|
}
|
|
|
|
|
|
function handleSearch() {
|
|
|
- // 添加防抖和防止重复请求
|
|
|
- if (isSearching.value) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
const timer = searchTimer
|
|
|
if (timer != null) {
|
|
|
clearTimeout(timer)
|
|
|
- searchTimer = null
|
|
|
}
|
|
|
-
|
|
|
searchTimer = setTimeout(() => {
|
|
|
- isSearching.value = true
|
|
|
loadData(true)
|
|
|
getStatistics()
|
|
|
- // 延迟重置标志位,确保请求发送后才允许下一次搜索
|
|
|
- setTimeout(() => {
|
|
|
- isSearching.value = false
|
|
|
- }, 100)
|
|
|
- }, 300)
|
|
|
+ }, 500)
|
|
|
}
|
|
|
|
|
|
+// 防止iOS中input事件多次触发
|
|
|
+const handleSearchWithPrevent = (() => {
|
|
|
+ let lastCall = 0;
|
|
|
+ return () => {
|
|
|
+ const now = new Date().getTime();
|
|
|
+ if (now - lastCall < 500) { // 500ms内最多执行一次
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ lastCall = now;
|
|
|
+ handleSearch();
|
|
|
+ };
|
|
|
+})();
|
|
|
+
|
|
|
function clearSearch() {
|
|
|
- // 添加防抖和防止重复请求
|
|
|
- if (isSearching.value) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
const timer = searchTimer
|
|
|
if (timer != null) {
|
|
|
clearTimeout(timer)
|
|
|
- searchTimer = null
|
|
|
}
|
|
|
-
|
|
|
searchKeyword.value = ""
|
|
|
searchTimer = setTimeout(() => {
|
|
|
- isSearching.value = true
|
|
|
loadData(true)
|
|
|
getStatistics()
|
|
|
- // 延迟重置标志位,确保请求发送后才允许下一次搜索
|
|
|
- setTimeout(() => {
|
|
|
- isSearching.value = false
|
|
|
- }, 100)
|
|
|
- }, 300)
|
|
|
+ }, 500)
|
|
|
}
|
|
|
|
|
|
function filterByOrderType(type: string) {
|
|
|
- // 添加防止重复请求
|
|
|
- if (isSearching.value) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
const timer = searchTimer
|
|
|
if (timer != null) {
|
|
|
clearTimeout(timer)
|
|
|
- searchTimer = null
|
|
|
}
|
|
|
-
|
|
|
orderTypeFilter.value = type
|
|
|
searchTimer = setTimeout(() => {
|
|
|
- isSearching.value = true
|
|
|
loadData(true)
|
|
|
getStatistics()
|
|
|
- // 延迟重置标志位,确保请求发送后才允许下一次搜索
|
|
|
- setTimeout(() => {
|
|
|
- isSearching.value = false
|
|
|
- }, 100)
|
|
|
- }, 300)
|
|
|
+ }, 500)
|
|
|
}
|
|
|
|
|
|
function changeTimeRange(range: string) {
|
|
|
- // 添加防止重复请求
|
|
|
- if (isSearching.value) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
const timer = searchTimer
|
|
|
if (timer != null) {
|
|
|
clearTimeout(timer)
|
|
|
- searchTimer = null
|
|
|
}
|
|
|
-
|
|
|
timeRange.value = range
|
|
|
searchTimer = setTimeout(() => {
|
|
|
- isSearching.value = true
|
|
|
loadData(true)
|
|
|
getStatistics()
|
|
|
- // 延迟重置标志位,确保请求发送后才允许下一次搜索
|
|
|
- setTimeout(() => {
|
|
|
- isSearching.value = false
|
|
|
- }, 100)
|
|
|
- }, 300)
|
|
|
+ }, 500)
|
|
|
}
|
|
|
|
|
|
+function filterByOrderTypeWithCheck(type: string) {
|
|
|
+ // 防止重复点击触发多次请求
|
|
|
+ if (orderTypeFilter.value === type) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ filterByOrderType(type);
|
|
|
+}
|
|
|
+
|
|
|
+function changeTimeRangeWithCheck(range: string) {
|
|
|
+ // 防止重复点击触发多次请求
|
|
|
+ if (timeRange.value === range) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ changeTimeRange(range);
|
|
|
+}
|
|
|
+
|
|
|
function loadMore() {
|
|
|
if (!hasMore.value || loading.value) return
|
|
|
|
|
|
@@ -642,26 +651,24 @@ function confirmCustomDate() {
|
|
|
closeDatePicker()
|
|
|
timeRange.value = 'custom'
|
|
|
|
|
|
- // 添加防止重复请求
|
|
|
- if (isSearching.value) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
const timer = searchTimer
|
|
|
if (timer != null) {
|
|
|
clearTimeout(timer)
|
|
|
- searchTimer = null
|
|
|
}
|
|
|
-
|
|
|
searchTimer = setTimeout(() => {
|
|
|
- isSearching.value = true
|
|
|
loadData(true)
|
|
|
getStatistics()
|
|
|
- // 延迟重置标志位,确保请求发送后才允许下一次搜索
|
|
|
- setTimeout(() => {
|
|
|
- isSearching.value = false
|
|
|
- }, 100)
|
|
|
- }, 300)
|
|
|
+ }, 500)
|
|
|
+}
|
|
|
+
|
|
|
+function showCustomDatePickerWithCheck() {
|
|
|
+ // 防止重复点击触发多次请求
|
|
|
+ if (timeRange.value === 'custom') {
|
|
|
+ // 重新选择日期
|
|
|
+ showCustomDatePicker();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ showCustomDatePicker();
|
|
|
}
|
|
|
|
|
|
// 打开开始日期选择器
|
|
|
@@ -792,8 +799,8 @@ onBeforeUnmount(() => {
|
|
|
const timer = searchTimer
|
|
|
if (timer != null) {
|
|
|
clearTimeout(timer)
|
|
|
- searchTimer = null
|
|
|
}
|
|
|
+ searchTimer = null
|
|
|
})
|
|
|
</script>
|
|
|
|