Browse Source

```
feat: 添加应用更新管理功能并优化商品列表

- 添加 useUpdateManager 组合式函数处理应用版本更新
- 在 App.vue 中引入并使用更新管理器
- 更新 auto-imports.d.ts 类型声明文件
- 重构首页商品列表为分页加载模式
- 添加骨架屏加载效果提升用户体验
- 集成全局加载中间件
- 修复确认订单页面地址选择验证逻辑
- 优化店铺选择逻辑避免重复赋值
```

zhangtao 1 tuần trước cách đây
mục cha
commit
b092be3e5e

+ 3 - 0
src/App.vue

@@ -1,4 +1,7 @@
 <script setup lang="ts">
+import useUpdateManager from './composables/useUpdateManager'
+
+useUpdateManager()
 useSysStore().getSystemData()
 onLaunch(() => { })
 </script>

+ 2 - 0
src/auto-imports.d.ts

@@ -332,6 +332,7 @@ declare global {
   const useToast: typeof import('wot-design-uni')['useToast']
   const useToggle: typeof import('@vueuse/core')['useToggle']
   const useTransition: typeof import('@vueuse/core')['useTransition']
+  const useUpdateManager: typeof import('./composables/useUpdateManager')['default']
   const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
   const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
   const useUserStore: typeof import('./store/user')['useUserStore']
@@ -691,6 +692,7 @@ declare module 'vue' {
     readonly useToast: UnwrapRef<typeof import('wot-design-uni')['useToast']>
     readonly useToggle: UnwrapRef<typeof import('@vueuse/core')['useToggle']>
     readonly useTransition: UnwrapRef<typeof import('@vueuse/core')['useTransition']>
+    readonly useUpdateManager: UnwrapRef<typeof import('./composables/useUpdateManager')['default']>
     readonly useUrlSearchParams: UnwrapRef<typeof import('@vueuse/core')['useUrlSearchParams']>
     readonly useUserMedia: UnwrapRef<typeof import('@vueuse/core')['useUserMedia']>
     readonly useUserStore: UnwrapRef<typeof import('./store/user')['useUserStore']>

+ 41 - 0
src/composables/useUpdateManager.ts

@@ -0,0 +1,41 @@
+import { ref } from 'vue'
+import { onShow } from '@dcloudio/uni-app'
+
+function useUpdateManager() {
+  if (!uni.canIUse('getUpdateManager') || !uni.getUpdateManager) {
+    return
+  }
+
+  const updateManager = uni.getUpdateManager()
+  const isUpdateReady = ref(false)
+
+  updateManager.onCheckForUpdate((res) => {
+    // 请求完新版本信息的回调
+    console.log('版本信息', res)
+  })
+
+  updateManager.onUpdateReady(() => {
+    isUpdateReady.value = true
+  })
+
+  updateManager.onUpdateFailed(() => {
+    // 新版本下载失败
+  })
+
+  onShow(() => {
+    if (isUpdateReady.value) {
+      uni.showModal({
+        title: '更新提示',
+        content: '新版本已经准备好,是否重启应用?',
+        success(res) {
+          if (res.confirm) {
+            // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
+            updateManager.applyUpdate()
+          }
+        },
+      })
+    }
+  })
+}
+
+export default useUpdateManager

+ 89 - 60
src/pages/index/index.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts">
+import { createGlobalLoadingMiddleware } from '@/api/core/middleware'
 import { StaticUrl, VITE_OSS_BASE_URL } from '@/config'
 import router from '@/router'
 
@@ -18,12 +19,29 @@ const { show } = useGlobalToast()
 const addressStore = useAddressStore()
 const { ScrollDown, statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
 const { name } = storeToRefs(addressStore)
+const { userInfo } = storeToRefs(useUserStore())
 const { getTotalNum } = storeToRefs(useSmqjhCartStore())
-
+const { data: goodsList, isLastPage, page, reload, error, loading } = usePagination((pageNum, pageSize) =>
+  Apis.xsb.getSearchProductList({ data: { pageNum, pageSize, salesNum: 'DESC', shopId: 1, channelId: userInfo.value.channelId || 1 } }), {
+  data: resp => resp.data?.list,
+  initialData: [],
+  initialPage: 1,
+  initialPageSize: 10,
+  append: true,
+  middleware: createGlobalLoadingMiddleware(),
+})
+const state = computed(() => {
+  return error.value ? 'error' : !isLastPage.value ? 'loading' : 'finished'
+})
 onShow(() => {
   useSmqjhCartStore().getCartList('XSB')
   useTabbar().setTabbarItem('smqjh-cart', getTotalNum.value)
 })
+onReachBottom(() => {
+  if (!isLastPage.value) {
+    page.value++
+  }
+})
 const navList = ref([
   { icon: `${VITE_OSS_BASE_URL}2025/11/4dabcf9b8d794d3c99aa6b49be34f205.png`, title: '星闪豹', name: 'xsb-homeTabbar' },
   { icon: `${VITE_OSS_BASE_URL}2025/11/40cb38e287234a83885d68f30c9c39bc.png`, title: '充电', name: '' },
@@ -156,74 +174,83 @@ onShareAppMessage(() => {
         </view>
       </view>
       <view class="mt20rpx">
-        <view class="flex items-center">
-          <scroll-view scroll-y type="custom">
-            <grid-view type="masonry" cross-axis-count="2" main-axis-gap="10" cross-axis-gap="10">
-              <view class="flex items-center justify-between">
-                <view class="rounded-16rpx bg-white px12rpx py20rpx">
-                  <view class="flex items-center rounded-8rpx bg-#FFEEEC text-24rpx font-semibold">
-                    <image :src="`${VITE_OSS_BASE_URL}2025/11/5e2df94dea5e4e4ca5cb1239321930f5.png`" class="h36rpx w36rpx" />
-                    <view class="px4rpx py2rpx text-#FF4A39">
-                      直播低价
+        <wd-skeleton theme="image" animation="gradient" :loading="loading" :row-col="[[{ height: '568rpx', width: '344rpx' }, { height: '568rpx', width: '344rpx' }], [{ height: '568rpx', width: '344rpx' }, { height: '568rpx', width: '344rpx' }]]">
+          <view class="flex items-center">
+            <scroll-view scroll-y type="custom">
+              <grid-view type="masonry" cross-axis-count="2" main-axis-gap="10" cross-axis-gap="10">
+                <view class="flex items-center justify-between">
+                  <view class="rounded-16rpx bg-white px12rpx py20rpx">
+                    <view class="flex items-center rounded-8rpx bg-#FFEEEC text-24rpx font-semibold">
+                      <image :src="`${VITE_OSS_BASE_URL}2025/11/5e2df94dea5e4e4ca5cb1239321930f5.png`" class="h36rpx w36rpx" />
+                      <view class="px4rpx py2rpx text-#FF4A39">
+                        直播低价
+                      </view>
                     </view>
-                  </view>
-                  <view class="mt16rpx flex items-center justify-center">
-                    <image :src="`${VITE_OSS_BASE_URL}2025/11/358c2f46c0ea4e00b98615712ccc142a.png`" class="h116rpx w116rpx" />
-                  </view>
-                  <view class="mt8rpx text-center text-24rpx text-#FF4A39 font-semibold">
-                    ¥35.9
-                  </view>
-                </view>
-                <view class="rounded-16rpx bg-white px12rpx py20rpx">
-                  <view class="flex items-center rounded-8rpx bg-#FFEEEC text-24rpx font-semibold">
-                    <image :src="`${VITE_OSS_BASE_URL}2025/11/5e2df94dea5e4e4ca5cb1239321930f5.png`" class="h36rpx w36rpx" />
-                    <view class="px4rpx py2rpx text-#FF4A39">
-                      爆品好价
+                    <view class="mt16rpx flex items-center justify-center">
+                      <image :src="`${VITE_OSS_BASE_URL}2025/11/358c2f46c0ea4e00b98615712ccc142a.png`" class="h116rpx w116rpx" />
+                    </view>
+                    <view class="mt8rpx text-center text-24rpx text-#FF4A39 font-semibold">
+                      ¥35.9
                     </view>
                   </view>
-                  <view class="mt16rpx flex items-center justify-center">
-                    <image :src="`${VITE_OSS_BASE_URL}2025/11/00fc4d8ffba6453685c05ffae06e2d78.png`" class="h116rpx w116rpx" />
-                  </view>
-                  <view class="mt8rpx text-center text-24rpx text-#FF4A39 font-semibold">
-                    ¥25.6
-                  </view>
-                </view>
-              </view>
-              <view class="overflow-hidden rounded-16rpx bg-white pb16rpx">
-                <view class="relative h344rpx">
-                  <image :src="`${VITE_OSS_BASE_URL}2025/11/9d42892888304abf85487deea0271f62.png`" class="h344rpx w344rpx" />
-                  <view class="absolute bottom-0 left-0 flex items-center text-22rpx">
-                    <view class="rounded-tl-8rpx bg-#02ECFD pl4rpx">
-                      充电
+                  <view class="rounded-16rpx bg-white px12rpx py20rpx">
+                    <view class="flex items-center rounded-8rpx bg-#FFEEEC text-24rpx font-semibold">
+                      <image :src="`${VITE_OSS_BASE_URL}2025/11/5e2df94dea5e4e4ca5cb1239321930f5.png`" class="h36rpx w36rpx" />
+                      <view class="px4rpx py2rpx text-#FF4A39">
+                        爆品好价
+                      </view>
                     </view>
-                    <view class="rounded-tr-8rpx bg-[rgba(0,0,0,0.5)] pl8rpx pr4rpx text-white">
-                      峰10:00-13:00
+                    <view class="mt16rpx flex items-center justify-center">
+                      <image :src="`${VITE_OSS_BASE_URL}2025/11/00fc4d8ffba6453685c05ffae06e2d78.png`" class="h116rpx w116rpx" />
+                    </view>
+                    <view class="mt8rpx text-center text-24rpx text-#FF4A39 font-semibold">
+                      ¥25.6
                     </view>
                   </view>
                 </view>
-                <view class="mt16rpx pl20rpx pr6rpx">
-                  <view class="flex items-center">
-                    <view class="rounded-8rpx bg-#FF4D3A px12rpx text-24rpx text-white">
-                      补贴
+                <view v-for="item in goodsList" :key="item.id" class="relative overflow-hidden rounded-16rpx bg-white pb16rpx">
+                  <view @click="router.push({ name: 'xsb-goods', params: { id: item.prodId } })">
+                    <view class="relative h344rpx">
+                      <image :src="item.pic" class="h344rpx w344rpx" />
+                      <view class="absolute bottom-0 left-0 flex items-center text-22rpx">
+                        <view class="rounded-tl-8rpx bg-#02ECFD pl4rpx">
+                          星闪豹
+                        </view>
+                        <!-- <view class="rounded-tr-8rpx bg-[rgba(0,0,0,0.5)] pl8rpx pr4rpx text-white">
+                      峰10:00-13:00
+                    </view> -->
+                      </view>
                     </view>
-                    <view class="ml12rpx text-28rpx font-semibold">
-                      轩宇智慧停车场
+                    <view class="mt16rpx pl20rpx pr6rpx">
+                      <view class="flex items-center">
+                        <!-- <view class="rounded-8rpx bg-#FF4D3A px12rpx text-24rpx text-white">
+                      补贴
+                    </view> -->
+                        <view class="ml12rpx text-28rpx font-semibold">
+                          {{ item.prodName }}
+                        </view>
+                      </view>
+                      <view class="mt20rpx flex items-end text-#FF4D3A">
+                        <view class="text-24rpx">
+                          ¥
+                        </view>
+                        <view class="text-36rpx line-height-[36rpx]">
+                          {{ item.channelProdPrice }}
+                        </view>
+                        <view class="text-24rpx">
+                          元
+                        </view>
+                      </view>
                     </view>
                   </view>
-                  <view class="mt20rpx flex items-end text-#FF4D3A">
-                    <view class="text-24rpx">
-                      ¥
-                    </view>
-                    <view class="text-36rpx line-height-[36rpx]">
-                      1.395
-                    </view>
-                    <view class="text-24rpx">
-                      元/度
+                  <view v-if="!item.spuStock" class="absolute left-0 top-0 z-1 h-full w-full flex items-center justify-center bg-[rgba(255,255,255,0.6)]">
+                    <view class="h156rpx w156rpx flex items-center justify-center rounded-full bg-[rgba(0,0,0,.6)] text-28rpx text-white">
+                      商品已售罄
                     </view>
                   </view>
                 </view>
-              </view>
-              <view class="overflow-hidden rounded-16rpx bg-white pb16rpx">
+
+              <!-- <view class="overflow-hidden rounded-16rpx bg-white pb16rpx">
                 <view class="relative h344rpx">
                   <image :src="`${VITE_OSS_BASE_URL}2025/11/8177f50dc5f040188dbd40149831273a.png`" class="h344rpx w344rpx" />
                   <view class="absolute bottom-0 left-0 flex items-center text-22rpx">
@@ -371,10 +398,12 @@ onShareAppMessage(() => {
                     </view>
                   </view>
                 </view>
-              </view>
-            </grid-view>
-          </scroll-view>
-        </view>
+              </view> -->
+              </grid-view>
+            </scroll-view>
+          </view>
+        </wd-skeleton>
+        <wd-loadmore :state="state" :loading-props="{ color: '#9ED605', size: 20 }" @reload="reload" />
       </view>
     </view>
   </view>

+ 7 - 1
src/subPack-xsb/confirmOrder/index.vue

@@ -30,7 +30,9 @@ onLoad((options: any) => {
 })
 onShow(() => {
   useUserStore().getuserAddresslist()
-  getDevryList()
+  if (selectedAddress.value) {
+    getDevryList()
+  }
 })
 
 async function getDevryList() {
@@ -46,6 +48,10 @@ async function getDevryList() {
 }
 
 async function handlePay() {
+  if (!selectedAddress.value) {
+    useGlobalToast().show({ msg: '请选择收货地址' })
+    return
+  }
   if (!orderInfo.value) {
     useGlobalToast().show({ msg: '网络异常!请联系客服' })
     return

+ 3 - 1
src/subPack-xsb/store-xsb/sys.ts

@@ -63,7 +63,9 @@ export const useSysXsbStore = defineStore('system-xsb', {
               )
               if (distance < minDistance) {
                 minDistance = distance
-                this.SelectShopInfo = { ...shop, distance: Number(distance.toFixed(2)) }
+                if (!this.SelectShopInfo) {
+                  this.SelectShopInfo = { ...shop, distance: Number(distance.toFixed(2)) }
+                }
               }
             }
           }