فهرست منبع

feat(pageScroll): enhance data handling and loading logic

- Introduced a normalization function for list data to handle various response formats.
- Improved loading sequence management to prevent outdated responses from updating the list.
- Updated error handling for API responses and loading states.
- Refactored upCallback to streamline data processing and ensure correct pagination handling.
- Added loading state management to the form submission process in the code-storage-add component.
- Updated exception item key handling for better uniqueness in the route-exception component.
ylong 3 هفته پیش
والد
کامیت
3005292c35
29فایلهای تغییر یافته به همراه115 افزوده شده و 71 حذف شده
  1. 34 24
      components/pageScroll/index.vue
  2. 1 1
      config/request.js
  3. 2 0
      pages/index/express/components/ExceptionItem.vue
  4. 10 2
      pages/index/express/route-exception.vue
  5. 40 30
      pages/index/wms/code-storage-add.vue
  6. 16 5
      pages/index/wms/code-storage.vue
  7. 3 2
      pages/index/work-order/mall.vue
  8. 3 2
      pages/index/work-order/recycle.vue
  9. 1 1
      unpackage/dist/build/app-plus/app-config-service.js
  10. 0 0
      unpackage/dist/build/app-plus/app-service.js
  11. 1 1
      unpackage/dist/build/app-plus/manifest.json
  12. 0 0
      unpackage/dist/build/app-plus/pages/index/audit/isbn-order.css
  13. 0 0
      unpackage/dist/build/app-plus/pages/index/audit/review-order.css
  14. 0 0
      unpackage/dist/build/app-plus/pages/index/audit/sender.css
  15. 0 0
      unpackage/dist/build/app-plus/pages/index/detail/user-orders.css
  16. 0 0
      unpackage/dist/build/app-plus/pages/index/express/route-exception.css
  17. 0 0
      unpackage/dist/build/app-plus/pages/index/offline/check-record.css
  18. 0 0
      unpackage/dist/build/app-plus/pages/index/statistic/after-sale-result.css
  19. 0 0
      unpackage/dist/build/app-plus/pages/index/statistic/audit.css
  20. 0 0
      unpackage/dist/build/app-plus/pages/index/statistic/package.css
  21. 0 0
      unpackage/dist/build/app-plus/pages/index/wms/code-storage-add.css
  22. 0 0
      unpackage/dist/build/app-plus/pages/index/wms/code-storage.css
  23. 0 0
      unpackage/dist/build/app-plus/pages/index/work-order/mall.css
  24. 0 0
      unpackage/dist/build/app-plus/pages/index/work-order/recycle.css
  25. 0 0
      unpackage/dist/build/app-plus/pages/my/page/audit-unfinished.css
  26. 0 0
      unpackage/dist/build/app-plus/pages/order/mall/pending.css
  27. 0 0
      unpackage/dist/build/app-plus/pages/order/recycle/pending.css
  28. 0 0
      unpackage/dist/build/app-plus/pages/order/stat/receive-stat.css
  29. 4 3
      utils/utils.js

+ 34 - 24
components/pageScroll/index.vue

@@ -75,6 +75,14 @@ const props = defineProps({
 })
 })
 
 
 const list = ref([])
 const list = ref([])
+let loadSeq = 0
+
+const normalizeListData = (res) => {
+    if (Array.isArray(res?.rows)) return res.rows
+    if (Array.isArray(res?.data?.rows)) return res.data.rows
+    if (Array.isArray(res?.data)) return res.data
+    return []
+}
 
 
 const getList = (mescroll) => {
 const getList = (mescroll) => {
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
@@ -88,45 +96,47 @@ const getList = (mescroll) => {
         })
         })
 
 
         methods.then(res => {
         methods.then(res => {
-            emit('update:total', res.total || res.data.total || 0)
+            emit('update:total', res.total || res.data?.total || 0)
             resolve(res)
             resolve(res)
-        })
+        }).catch(reject)
     })
     })
 }
 }
 
 
 // 上拉加载的回调: 其中num:当前页 从1开始, size:每页数据条数,默认10
 // 上拉加载的回调: 其中num:当前页 从1开始, size:每页数据条数,默认10
 const upCallback = (mescroll) => {
 const upCallback = (mescroll) => {
-    if (!props.requestStr) return;
+    if (!props.requestStr) {
+        mescroll.endErr()
+        return
+    }
+    const seq = ++loadSeq
     getList(mescroll).then(res => {
     getList(mescroll).then(res => {
-        console.log(res, 'res')
-        const curPageData = res.rows || res.data?.rows || res.data || [] // 当前页数据
-        if (mescroll.num == 1) list.value = []; // 第一页需手动制空列表
-        list.value = list.value.concat(curPageData); //追加新数据
-
+        if (seq !== loadSeq) return
+        if (res?.code !== undefined && res.code !== 200) {
+            mescroll.endErr()
+            return
+        }
+        const curPageData = normalizeListData(res)
+        if (mescroll.num == 1) list.value = []
+        list.value = list.value.concat(curPageData)
         emit('updateList', list.value, mescroll.num)
         emit('updateList', list.value, mescroll.num)
-        //联网成功的回调,隐藏下拉刷新和上拉加载的状态;
-        //mescroll会根据传的参数,自动判断列表如果无任何数据,则提示空;列表无下一页数据,则提示无更多数据;
-
-        //方法一(推荐): 后台接口有返回列表的总页数 totalPage
-        //mescroll.endByPage(curPageData.length, totalPage); //必传参数(当前页的数据个数, 总页数)
-
-        //方法二(推荐): 后台接口有返回列表的总数据量 totalSize
-        mescroll.endBySize(curPageData.length, res.total || res.data.total || 0); //必传参数(当前页的数据个数, 总数据量)
-
-        //方法三(推荐): 您有其他方式知道是否有下一页 hasNext
-        //mescroll.endSuccess(curPageData.length, hasNext); //必传参数(当前页的数据个数, 是否有下一页true/false)
-
-        //方法四 (不推荐),会存在一个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据当前页的数据个数判断,则需翻到第三页才会知道无更多数据.
-        // mescroll.endSuccess(curPageData.length); // 请求成功, 结束加载
+        const total = res.total ?? res.data?.total ?? 0
+        mescroll.endBySize(curPageData.length, total)
     }).catch(() => {
     }).catch(() => {
-        mescroll.endErr(); // 请求失败, 结束加载
+        if (seq !== loadSeq) return
+        mescroll.endErr()
     })
     })
 }
 }
 
 
 //重置列表
 //重置列表
 const resetUpScroll = () => {
 const resetUpScroll = () => {
+    loadSeq++
     setTimeout(() => {
     setTimeout(() => {
-        getMescroll().resetUpScroll()
+        const mescroll = getMescroll()
+        if (!mescroll) return
+        if (mescroll.isUpScrolling) {
+            mescroll.endErr()
+        }
+        mescroll.resetUpScroll()
     }, 100)
     }, 100)
 }
 }
 
 

+ 1 - 1
config/request.js

@@ -1,7 +1,7 @@
 /**
 /**
  * 文档地址:https://uiadmin.net/uview-plus/js/http.html
  * 文档地址:https://uiadmin.net/uview-plus/js/http.html
  */
  */
-const baseUrl = "https://bk.shuhi.com";
+const baseUrl = "https://bpi.shuhi.com";
 export function initRequest() {
 export function initRequest() {
     console.log("初始化了 http 请求代码");
     console.log("初始化了 http 请求代码");
     // 初始化请求配置
     // 初始化请求配置

+ 2 - 0
pages/index/express/components/ExceptionItem.vue

@@ -81,6 +81,8 @@ function handleButtonClick(checkStatus, reason) {
         } else {
         } else {
             uni.$u.toast(res.msg);
             uni.$u.toast(res.msg);
         }
         }
+    }).catch(() => {
+        uni.$u.toast('操作失败');
     })
     })
 }
 }
 
 

+ 10 - 2
pages/index/express/route-exception.vue

@@ -10,7 +10,7 @@
 
 
             </u-sticky>
             </u-sticky>
             <view class="list-container">
             <view class="list-container">
-                <exception-item v-for="item in exceptionList" :key="item.orderNo" :order="item" @refresh="handleSearch" />
+                <exception-item v-for="item in exceptionList" :key="item.id || item.orderId" :order="item" @refresh="handleRefresh" />
             </view>
             </view>
         </page-scroll>
         </page-scroll>
 
 
@@ -27,6 +27,7 @@
 <script setup>
 <script setup>
 import {
 import {
     ref,
     ref,
+    nextTick,
     onUnmounted
     onUnmounted
 } from 'vue';
 } from 'vue';
 import { onLoad, onShow } from '@dcloudio/uni-app';
 import { onLoad, onShow } from '@dcloudio/uni-app';
@@ -60,7 +61,14 @@ const updateList = (list) => {
 
 
 // 搜索处理
 // 搜索处理
 const handleSearch = () => {
 const handleSearch = () => {
-    pageScrollRef.value?.resetUpScroll();
+    nextTick(() => {
+        pageScrollRef.value?.resetUpScroll();
+    });
+};
+
+// 操作成功后刷新列表
+const handleRefresh = () => {
+    handleSearch();
 };
 };
 
 
 // 扫码处理
 // 扫码处理

+ 40 - 30
pages/index/wms/code-storage-add.vue

@@ -27,21 +27,19 @@
 		<!-- 底部按钮 -->
 		<!-- 底部按钮 -->
 		<view class="fixed-bottom">
 		<view class="fixed-bottom">
 			<u-button size="large" type="warning" @click="cancelForm" text="取消" class="cancel-button" />
 			<u-button size="large" type="warning" @click="cancelForm" text="取消" class="cancel-button" />
-			<u-button size="large" type="success" @click="submitForm" text="提交" class="submit-button" />
+			<u-button size="large" type="success" @click="submitForm" text="提交" class="submit-button" :loading="isSubmitting" :disabled="isSubmitting" />
 		</view>
 		</view>
 	</view>
 	</view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
 	import {
 	import {
-		ref,
-		reactive,
-		onUnmounted,
-		nextTick
+		ref
 	} from 'vue';
 	} from 'vue';
 	import {
 	import {
 		onLoad,
 		onLoad,
-		onShow
+		onShow,
+		onUnload
 	} from '@dcloudio/uni-app'
 	} from '@dcloudio/uni-app'
 	import cyUpload from '@/components/cy-upload/index.vue'
 	import cyUpload from '@/components/cy-upload/index.vue'
 
 
@@ -55,14 +53,32 @@
 
 
 	// 图片上传状态
 	// 图片上传状态
 	const isImageUploaded = ref(false);
 	const isImageUploaded = ref(false);
+	const isSubmitting = ref(false);
+
+	const resetForm = () => {
+		form.value = {
+			isbn: '',
+			imgUrl: ''
+		};
+		isImageUploaded.value = false;
+	};
+
+	onLoad(() => {
+		resetForm();
+		const storedInfo = uni.getStorageSync('bookInfo');
+		bookInfo.value = storedInfo || {};
+	});
 
 
 	onShow(() => {
 	onShow(() => {
-		// 从本地存储获取书籍信息
-		nextTick(() => {
-			const storedInfo = uni.getStorageSync('bookInfo');
-			bookInfo.value = storedInfo
-		})
-	})
+		const storedInfo = uni.getStorageSync('bookInfo');
+		if (storedInfo) {
+			bookInfo.value = storedInfo;
+		}
+	});
+
+	onUnload(() => {
+		uni.removeStorageSync('bookInfo');
+	});
 
 
 	// 图片上传成功回调
 	// 图片上传成功回调
 	function onUploadSuccess(result) {
 	function onUploadSuccess(result) {
@@ -76,6 +92,13 @@
 	}
 	}
 
 
 	function submitForm() {
 	function submitForm() {
+		if (isSubmitting.value) return;
+
+		if (!bookInfo.value?.isbn) {
+			uni.$u.toast('书籍信息缺失,请重新扫码');
+			return;
+		}
+
 		if (!form.value.imgUrl || form.value.imgUrl.length === 0) {
 		if (!form.value.imgUrl || form.value.imgUrl.length === 0) {
 			uni.$u.toast('请先上传图片');
 			uni.$u.toast('请先上传图片');
 			return;
 			return;
@@ -86,7 +109,7 @@
 			return;
 			return;
 		}
 		}
 
 
-		// 这里应该调用实际的API接口
+		isSubmitting.value = true;
 		uni.$u.http.post('/activation/bookActivationInfo/activationAdd', {
 		uni.$u.http.post('/activation/bookActivationInfo/activationAdd', {
 			isbn: bookInfo.value.isbn,
 			isbn: bookInfo.value.isbn,
 			img: form.value.imgUrl[0]
 			img: form.value.imgUrl[0]
@@ -95,32 +118,19 @@
 				uni.$u.toast('提交成功')
 				uni.$u.toast('提交成功')
 				let text = '提交成功,请销毁激活码'
 				let text = '提交成功,请销毁激活码'
 				uni.$u.ttsModule.speak(text)
 				uni.$u.ttsModule.speak(text)
-				// 返回上一页
+				resetForm();
 				uni.navigateBack();
 				uni.navigateBack();
 			} else {
 			} else {
 				let text = '提交失败:' + (res.msg || '未知错误')
 				let text = '提交失败:' + (res.msg || '未知错误')
 				uni.$u.toast(text)
 				uni.$u.toast(text)
 				uni.$u.ttsModule.speak(text)
 				uni.$u.ttsModule.speak(text)
 			}
 			}
-		}).catch(err => {
+		}).catch(() => {
 			uni.$u.ttsModule.speak('网络错误')
 			uni.$u.ttsModule.speak('网络错误')
+		}).finally(() => {
+			isSubmitting.value = false;
 		})
 		})
 	}
 	}
-
-	// #ifdef APP-PLUS
-	const {
-		unregister
-	} = uni.$u.useEventListener((e) => {
-		form.value.isbn = e.barcode;
-		queryBookInfo(e.barcode);
-	});
-	// #endif
-
-	onUnmounted(() => {
-		// #ifdef APP-PLUS
-		unregister();
-		// #endif
-	});
 </script>
 </script>
 
 
 <style>
 <style>

+ 16 - 5
pages/index/wms/code-storage.vue

@@ -35,6 +35,11 @@ const form = ref({
     "isbn": ""
     "isbn": ""
 })
 })
 
 
+let barcodeLock = false
+let lastBarcode = ''
+let lastBarcodeAt = 0
+const BARCODE_DEBOUNCE_MS = 2000
+
 function scanCode() {
 function scanCode() {
     uni.scanCode({
     uni.scanCode({
         success: (res) => {
         success: (res) => {
@@ -59,24 +64,30 @@ function checkIsbn(isbn) {
 function handleBarcode(code) {
 function handleBarcode(code) {
     if (!code) return uni.$u.toast('请输入ISBN')
     if (!code) return uni.$u.toast('请输入ISBN')
 
 
+    const now = Date.now()
+    if (barcodeLock) return
+    if (code === lastBarcode && now - lastBarcodeAt < BARCODE_DEBOUNCE_MS) return
+
     // 验证ISBN格式
     // 验证ISBN格式
     if (!checkIsbn(code)) {
     if (!checkIsbn(code)) {
         return uni.$u.ttsModule.speak('不是正确的ISBN码')
         return uni.$u.ttsModule.speak('不是正确的ISBN码')
     }
     }
 
 
-    // 这里可以添加ISBN查询逻辑
+    barcodeLock = true
     uni.$u.http.post('/activation/bookActivationInfo/queryBookBasicByIsbn/' + code).then(res => {
     uni.$u.http.post('/activation/bookActivationInfo/queryBookBasicByIsbn/' + code).then(res => {
         if (res.code == 200) {
         if (res.code == 200) {
-            // 处理查询成功的逻辑
+            uni.setStorageSync('bookInfo', res.data)
             uni.navigateTo({
             uni.navigateTo({
-                url: '/pages/index/wms/code-storage-add?isbn=' + code
+                url: '/pages/index/wms/code-storage-add?isbn=' + encodeURIComponent(code)
             })
             })
             form.value.isbn = ""
             form.value.isbn = ""
-            // 传递书籍信息到下一页
-            uni.setStorageSync('bookInfo', res.data)
+            lastBarcode = code
+            lastBarcodeAt = Date.now()
         } else {
         } else {
             uni.$u.toast('未找到该书籍')
             uni.$u.toast('未找到该书籍')
         }
         }
+    }).finally(() => {
+        barcodeLock = false
     })
     })
 }
 }
 
 

+ 3 - 2
pages/index/work-order/mall.vue

@@ -45,7 +45,8 @@ const handleSubmit = async () => {
     try {
     try {
         const res = await uni.$u.http.get("/app/workOrder/scanWorkOrder", {
         const res = await uni.$u.http.get("/app/workOrder/scanWorkOrder", {
             params: {
             params: {
-                waybillCode: formData.value.search
+                waybillCode: formData.value.search,
+                type: 1
             }
             }
         });
         });
         
         
@@ -101,4 +102,4 @@ onUnmounted(() => {
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 @import "../components/common.scss";
 @import "../components/common.scss";
-</style>
+</style>

+ 3 - 2
pages/index/work-order/recycle.vue

@@ -52,7 +52,8 @@ const handleSubmit = async () => {
         const res = await uni.$u.http.get("/app/workOrder/scanWorkOrder", {
         const res = await uni.$u.http.get("/app/workOrder/scanWorkOrder", {
             params: {
             params: {
                 waybillCode: formData.value.searchType === '2' ? formData.value.search : undefined,
                 waybillCode: formData.value.searchType === '2' ? formData.value.search : undefined,
-                orderId: formData.value.searchType === '1' ? formData.value.search : undefined
+                orderId: formData.value.searchType === '1' ? formData.value.search : undefined,
+                type: 2
             }
             }
         });
         });
         
         
@@ -111,4 +112,4 @@ onUnmounted(() => {
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 @import "../components/common.scss";
 @import "../components/common.scss";
-</style>
+</style>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
unpackage/dist/build/app-plus/app-config-service.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/app-service.js


+ 1 - 1
unpackage/dist/build/app-plus/manifest.json

@@ -171,7 +171,7 @@
     "uni-app": {
     "uni-app": {
       "control": "uni-v3",
       "control": "uni-v3",
       "vueVersion": "3",
       "vueVersion": "3",
-      "compilerVersion": "5.06",
+      "compilerVersion": "5.07",
       "nvueCompiler": "uni-app",
       "nvueCompiler": "uni-app",
       "renderer": "auto",
       "renderer": "auto",
       "nvue": {
       "nvue": {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/audit/isbn-order.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/audit/review-order.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/audit/sender.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/detail/user-orders.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/express/route-exception.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/offline/check-record.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/statistic/after-sale-result.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/statistic/audit.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/statistic/package.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/wms/code-storage-add.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/wms/code-storage.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/work-order/mall.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/work-order/recycle.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/my/page/audit-unfinished.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/order/mall/pending.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/order/recycle/pending.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
unpackage/dist/build/app-plus/pages/order/stat/receive-stat.css


+ 4 - 3
utils/utils.js

@@ -72,11 +72,12 @@ export function useGlobalEvent(onScan) {
 
 
     //页面监听event事件,建议在页面onLoad方法里调用
     //页面监听event事件,建议在页面onLoad方法里调用
     var globalEvent = uni.requireNativePlugin('globalEvent');
     var globalEvent = uni.requireNativePlugin('globalEvent');
-    globalEvent.addEventListener('iDataBarcodeEvent', (e) => {
+    const handler = (e) => {
         onScan(e);
         onScan(e);
-    });
+    };
+    globalEvent.addEventListener('iDataBarcodeEvent', handler);
     return () => {
     return () => {
-        globalEvent.removeEventListener('iDataBarcodeEvent', onScan);
+        globalEvent.removeEventListener('iDataBarcodeEvent', handler);
         barcodeModel.closeScan((ret) => {});
         barcodeModel.closeScan((ret) => {});
     };
     };
 }
 }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است