Преглед на файлове

feat(api): 添加商品库存字段并修改接口请求方式

- 在xsbCategoryProductList接口中添加spuStock商品库存字段
- 将xsb.getCategoryProductList接口请求方式从GET改为POST
- 在全局类型定义中添加channelId字段

refactor(pages): 重构页面配置和组件地址选择逻辑

- 将selectAddress页面从common包移动到xsb包
- 更新pages.json中的页面配置,移除旧的common-selectAddress页面
- 添加新的xsb-selectAddress页面配置

feat(classify): 优化分类页面商品列表展示和库存控制

- 修改分类页面地址选择逻辑,使用地图获取地址
- 根据店铺信息动态设置shopId参数
- 添加channelId参数到商品列表请求
- 优化商品列表项的点击区域和样式结构
- 添加商品库存售罄状态显示,当spuStock为0时显示"已售罄"标识

refactor(commonTab): 重构首页组件结构和数据处理逻辑

- 引入商品项组件goodsItem,重构首页商品列表展示
- 调整状态管理store的引用顺序
- 更新地址选择页面跳转路径
- 优化分页数据加载逻辑,添加immediate: false配置
- 添加页面显示时的数据刷新功能

feat(goodsItem): 新增商品项展示组件

- 创建新的商品项组件用于展示商品信息
- 包含商品图片、名称、销量、价格等信息
- 添加商品售罄状态的遮罩层显示

fix(search): 修复搜索功能并优化搜索框布局

- 添加搜索文本为空时的校验,避免无效搜索
- 优化搜索框输入区域的布局结构
- 修复搜索按钮宽度问题

refactor(selectAddress): 重命名地址选择页面

- 将页面名称从common-selectAddress改为xsb-selectAddress
- 更新相关引用和配置
zhangtao преди 2 дни
родител
ревизия
ae29dc3115

+ 4 - 0
src/api/api.type.d.ts

@@ -44,6 +44,10 @@ namespace Api {
     children: xsbCategoriesChildren[]
   }
   interface xsbCategoryProductList {
+    /**
+     * 商品库存
+     */
+    spuStock: number
     /**
      * 分类id
      */

+ 1 - 1
src/api/apiDefinitions.ts

@@ -29,7 +29,7 @@ export default {
   'sys.uploadFile': ['POST', '/smqjh-system/api/v1/files'],
   'sys.updateUserInfo': ['PUT', '/smqjh-system/app-api/v1/members/{memberId}'],
   'xsb.categories':['GET', '/smqjh-pms/app-api/v1/categories'],
-  'xsb.getCategoryProductList':['GET', '/smqjh-pms/app-api/v1/spu/getCategoryProductList'],
+  'xsb.getCategoryProductList':['POST', '/smqjh-pms/app-api/v1/spu/getCategoryProductList'],
   'xsb.getProductDetail':['GET', '/smqjh-pms/app-api/v1/spu/getProductDetails'],
   'xsb.findUserPointsPage':['PUT', '/smqjh-system/app-api/v1/points/findUserPointsPage'],
   'xsb.findUserPoints':['GET', '/smqjh-system/app-api/v1/points/findUserPoints'],

+ 1 - 0
src/api/globals.d.ts

@@ -155,6 +155,7 @@ declare global {
           data: {
             categoryId: number;
             shopId: number
+            channelId:number
           };
         }
       >(

+ 9 - 9
src/pages.json

@@ -138,6 +138,15 @@
           "style": {
             "navigationBarTitleText": "搜索"
           }
+        },
+        {
+          "path": "selectAddress/index",
+          "type": "page",
+          "name": "xsb-selectAddress",
+          "islogin": false,
+          "style": {
+            "navigationBarTitleText": "选择收获地址"
+          }
         }
       ]
     },
@@ -260,15 +269,6 @@
             "disableScroll": true
           }
         },
-        {
-          "path": "selectAddress/index",
-          "type": "page",
-          "name": "common-selectAddress",
-          "islogin": false,
-          "style": {
-            "navigationBarTitleText": "选择收获地址"
-          }
-        },
         {
           "path": "user-center/index",
           "type": "page",

+ 1 - 1
src/pages/classfiy/index.vue

@@ -62,7 +62,7 @@ const categories = ref([
       title="" custom-style="background-color:transparent !important" :bordered="false" :z-index="99" safe-area-inset-top fixed
     >
       <template #left>
-        <view class="ml10rpx flex items-center" @click.stop="router.push({ name: 'common-selectAddress' })">
+        <view class="ml10rpx flex items-center" @click.stop="useAddressStore().getMapAddress()">
           <image :src="`${StaticUrl}/location-green.png`" class="h33.8rpx w29rpx" />
           <view class="ml10rpx max-w-280rpx truncate text-32rpx text-#222 font-semibold">
             {{ name }}

+ 17 - 6
src/subPack-xsb/commonTab/components/classfiy.vue

@@ -5,7 +5,7 @@ import router from '@/router'
 
 const props = defineProps<{ categoryList: Api.xsbCategories[], hotText: Api.xsbSearchTerm[] }>()
 const { statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
-const { topNavActive, leftActive } = storeToRefs(useSysXsbStore())
+const { topNavActive, leftActive, SelectShopInfo } = storeToRefs(useSysXsbStore())
 const classfiylist = computed(() => props.categoryList)
 const sortClassBtn = ref(1)
 const show = ref(false)
@@ -67,7 +67,8 @@ async function getProductList() {
   const res = await Apis.xsb.getCategoryProductList({
     data: {
       categoryId: Number(categoriesId.value),
-      shopId: 1,
+      shopId: Number(SelectShopInfo.value?.shopId) || 1,
+      channelId: 1,
     },
   })
   productList.value = res
@@ -161,7 +162,7 @@ onMounted(() => {
       :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }"
     >
       <scroll-view
-        scroll-x :scroll-into-view-offset="-150" scroll-with-animation enable-passive
+        :scroll-into-view-offset="-150" scroll-x enable-passive scroll-with-animation
         class="scrollx w-90% flex-shrink-0 whitespace-nowrap" :scroll-into-view="`id${topScrollView}`"
       >
         <view class="flex items-end pb10rpx">
@@ -251,8 +252,8 @@ onMounted(() => {
           @refresherrefresh="handleSrollTop" @scrolltolower="handlScrollBottom"
         >
           <view v-if="productList.length" class="p20rpx">
-            <view v-for="item in productList" :key="item.id" @click="router.push({ name: 'xsb-goods', params: { id: String(item.id) } })">
-              <view class="flex">
+            <view v-for="item in productList" :key="item.id" class="relative">
+              <view class="flex" @click="router.push({ name: 'xsb-goods', params: { id: String(item.id) } })">
                 <view class="mr20rpx h172rpx w172rpx flex-shrink-0 overflow-hidden rounded-16rpx bg-#F6F6F6">
                   <image :src="item.pic" lazy-load class="h-full w-full" />
                 </view>
@@ -281,15 +282,25 @@ onMounted(() => {
                         {{ item.channelProdPrice }}
                       </text>
                     </view>
-                    <view @click.stop="handleAddCart($event, item)">
+                    <view v-if="item.spuStock" @click.stop="handleAddCart($event, item)">
                       <image :src="`${StaticUrl}/cart-yes.png`" class="h52rpx w52rpx" />
                     </view>
+                    <view v-else>
+                      <image :src="`${StaticUrl}/cart-no.png`" class="h52rpx w52rpx" />
+                    </view>
                   </view>
                 </view>
               </view>
               <view class="line">
                 <wd-divider color="#F0F0F0" />
               </view>
+              <view v-if="!item.spuStock" class="absolute left-0 top-0 z-1 h-full w-full flex items-center bg-[rgba(255,255,255,.6)]">
+                <view class="h172rpx w172rpx flex items-center justify-center">
+                  <view class="h36rpx w112rpx flex items-center justify-center rounded-16rpx bg-[rgba(0,0,0,.6)] text-28rpx text-white">
+                    已售罄
+                  </view>
+                </view>
+              </view>
             </view>
             <wd-loadmore :state="goodsLoading" />
           </view>

+ 5 - 41
src/subPack-xsb/commonTab/components/index.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts">
+import itemGoods from '../../components/goodsItem/index.vue'
 import { StaticUrl, VITE_OSS_BASE_URL } from '@/config'
 import router from '@/router'
 
@@ -6,10 +7,8 @@ const props = defineProps<{ error: any, lastPage: boolean, categoryList: Api.xsb
 
 const emit = defineEmits(['changeNav', 'scrollBottom'])
 
-const { ScrollDown } = storeToRefs(useSysXsbStore())
-
 const { statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
-const { topNavActive, leftActive, backTop, SelectShopInfo } = storeToRefs(useSysXsbStore())
+const { topNavActive, leftActive, backTop, SelectShopInfo, ScrollDown } = storeToRefs(useSysXsbStore())
 const swiperList = computed(() => props.swiper)
 const navActive = ref(0)
 const classfiylist = computed(() => props.categoryList.slice(0, 10))
@@ -81,7 +80,7 @@ watch(() => backTop.value, () => {
       <template #left>
         <view class="h-full flex items-center">
           <wd-icon name="arrow-left" size="22px" color="#fff" />
-          <view class="ml10rpx flex items-center" @click.stop="router.push({ name: 'common-selectAddress' })">
+          <view class="ml10rpx flex items-center" @click.stop="router.push({ name: 'xsb-selectAddress' })">
             <image :src="`${StaticUrl}/location.png`" class="h33.8rpx w29rpx" />
             <view class="ml10rpx max-w-280rpx truncate text-32rpx text-white">
               {{ SelectShopInfo?.shopName || '请选择位置' }}
@@ -229,43 +228,8 @@ watch(() => backTop.value, () => {
                     `${StaticUrl}/xsb-swiper1.png`,
                   ]" :height="231"
                 />
-                <view
-                  v-for="it in goodsList" :key="it.id" class="overflow-hidden rounded-16rpx bg-white pb16rpx"
-                  @click="router.push({ name: 'xsb-goods', params: { id: it.id } })"
-                >
-                  <view class="relative h344rpx">
-                    <image
-                      :src="it.pic"
-                      class="h344rpx w344rpx"
-                    />
-                  </view>
-                  <view class="mt20rpx px20rpx">
-                    <view class="line-clamp-2 text-left text-28rpx font-semibold">
-                      <!-- <view v-for="i in 2" :key="i" class="mr5px inline-block">
-                        <wd-tag type="primary">
-                          新品{{ i }}
-                        </wd-tag>
-                      </view> -->
-                      {{ it.prodName }}
-                    </view>
-                    <view class="mt12rpx text-22rpx text-#AAAAAA">
-                      已售{{ it.soldNum }}
-                    </view>
-
-                    <view class="mt10rpx flex items-center justify-between">
-                      <view>
-                        <view class="mt20rpx flex items-end text-#FF4D3A font-semibold">
-                          <view class="text-24rpx">
-                            ¥
-                          </view>
-                          <view class="text-36rpx line-height-[36rpx]">
-                            {{ it.channelProdPrice }}
-                          </view>
-                        </view>
-                      </view>
-                      <image :src="`${StaticUrl}/cart-yes.png`" class="h52rpx w52rpx" />
-                    </view>
-                  </view>
+                <view v-for="it in goodsList" :key="it.id">
+                  <itemGoods :item-goods="it" />
                 </view>
               </grid-view>
             </scroll-view>

+ 13 - 3
src/subPack-xsb/commonTab/index.vue

@@ -22,9 +22,17 @@ definePage({
     disableScroll: true,
   },
 })
-const { ScrollDown, topNavActive, leftActive, backTop } = storeToRefs(useSysXsbStore())
+const { ScrollDown, topNavActive, leftActive, backTop, SelectShopInfo } = storeToRefs(useSysXsbStore())
 const commonCategoryData = ref<Api.xsbCategories[]>([])
-const { data: goodsList, isLastPage, page, error, refresh } = usePagination((pageNum, pageSize) => Apis.xsb.getSearchProductList({ data: { pageNum, pageSize, salesNum: 'DESC', shopId: 1, channelId: 1 } }), { data: resp => resp.list, initialData: [], initialPage: 1, initialPageSize: 10, append: true })
+const { data: goodsList, isLastPage, page, error, refresh } = usePagination((pageNum, pageSize) =>
+  Apis.xsb.getSearchProductList({ data: { pageNum, pageSize, salesNum: 'DESC', shopId: Number(SelectShopInfo.value?.shopId) || 1, channelId: 1 } }), {
+  data: resp => resp.list,
+  initialData: [],
+  initialPage: 1,
+  initialPageSize: 10,
+  append: true,
+  immediate: false,
+})
 const tabbarItems = ref([
   { name: 'xsb-home', value: null, active: true, title: '首页', icon1: '', icon2: '' },
   { name: 'xsb-classfiy', value: null, active: false, title: '分类', icon1: class1, icon2: class2 },
@@ -80,13 +88,15 @@ onMounted(async () => {
   hotText.value = await getSearchData(2)
   recommendText.value = await getSearchData(3)
 })
+onShow(() => {
+  refresh()
+})
 onShareAppMessage(() => {
   return {
     title: '市民请集合',
   }
 })
 function handleScrollBottom() {
-  console.log('触底', error.value)
   if (error.value) {
     refresh()
     return

+ 57 - 0
src/subPack-xsb/components/goodsItem/index.vue

@@ -0,0 +1,57 @@
+<script setup lang="ts">
+import { StaticUrl } from '@/config'
+import router from '@/router'
+
+defineProps<{ itemGoods: Api.xsbCategoryProductList }>()
+</script>
+
+<template>
+  <view class="relative overflow-hidden rounded-16rpx bg-white pb16rpx">
+    <view @click="router.push({ name: 'xsb-goods', params: { id: itemGoods.id } })">
+      <view class="relative h344rpx">
+        <image
+          :src="itemGoods.pic"
+          class="h344rpx w344rpx"
+        />
+      </view>
+      <view class="mt20rpx px20rpx">
+        <view class="line-clamp-2 text-left text-28rpx font-semibold">
+          <!-- <view v-for="i in 2" :key="i" class="mr5px inline-block">
+                        <wd-tag type="primary">
+                          新品{{ i }}
+                        </wd-tag>
+                      </view> -->
+          {{ itemGoods.prodName }}
+        </view>
+        <view class="mt12rpx text-22rpx text-#AAAAAA">
+          已售{{ itemGoods.soldNum }}
+        </view>
+
+        <view class="mt10rpx flex items-center justify-between">
+          <view>
+            <view class="mt20rpx flex items-end text-#FF4D3A font-semibold">
+              <view class="text-24rpx">
+                ¥
+              </view>
+              <view class="text-36rpx line-height-[36rpx]">
+                {{ itemGoods.channelProdPrice }}
+              </view>
+            </view>
+          </view>
+          <image :src="`${StaticUrl}/cart-yes.png`" class="h52rpx w52rpx" />
+        </view>
+      </view>
+    </view>
+    <view v-if="!itemGoods.spuStock" class="mask absolute left-0 top-0 z-1 h-full w-full flex items-center justify-center">
+      <view class="h156rpx w156rpx flex items-center justify-center rounded-full bg-[rgba(0,0,0,.6)] text-28rpx text-white">
+        商品已售罄
+      </view>
+    </view>
+  </view>
+</template>
+
+<style scoped>
+.mask{
+  background: rgba(255,255,255,0.6);
+}
+</style>

+ 7 - 3
src/subPack-xsb/search/index.vue

@@ -45,6 +45,8 @@ onLoad((query: any) => {
 })
 
 function handleSearch() {
+  if (!searchText.value)
+    return
   data.value = []
   isSearch.value = true
   send()
@@ -97,11 +99,13 @@ function handleSearchText(text: string) {
   <view class="page-xsb">
     <view class="sticky top-0 bg-white px24rpx pt24rpx">
       <view class="box-border flex items-center justify-between border border-2rpx border-[var(--them-color)] rounded-40rpx border-solid px24rpx py14rpx">
-        <view class="flex items-center">
+        <view class="flex flex-1 items-center">
           <wd-icon name="search" size="20px" color="#aaa" />
-          <input v-model="searchText" type="text" placeholder="请输入搜索内容" class="ml20rpx">
+          <view class="ml20rpx flex-1">
+            <input v-model.trim="searchText" type="text" placeholder="请输入搜索内容">
+          </view>
         </view>
-        <view class="flex items-center">
+        <view class="w-90rpx flex items-center">
           <view class="ml12rpx text-#DEDEDE">
             |
           </view>

+ 1 - 1
src/subPack-common/selectAddress/index.vue → src/subPack-xsb/selectAddress/index.vue

@@ -3,7 +3,7 @@ import { StaticUrl } from '@/config/index'
 import router from '@/router'
 
 definePage({
-  name: 'common-selectAddress',
+  name: 'xsb-selectAddress',
   islogin: false,
   style: {
     navigationBarTitleText: '选择收获地址',

+ 1 - 1
src/uni-pages.d.ts

@@ -13,6 +13,7 @@ type _LocationUrl =
   "/subPack-xsb/goods/index" |
   "/subPack-xsb/order/index" |
   "/subPack-xsb/search/index" |
+  "/subPack-xsb/selectAddress/index" |
   "/subPack-common/addressList/index" |
   "/subPack-common/afterSales/index" |
   "/subPack-common/afterSalesDetail/index" |
@@ -25,7 +26,6 @@ type _LocationUrl =
   "/subPack-common/paySuccess/index" |
   "/subPack-common/revalue/index" |
   "/subPack-common/revalueSuccess/index" |
-  "/subPack-common/selectAddress/index" |
   "/subPack-common/user-center/index" |
   "/subPack-smqjh/goodsList/index" |
   "/subPack-smqjh/order/index";