|
|
@@ -8,11 +8,52 @@ const props = defineProps<{ categoryList: Api.xsbCategories[], hotText: Api.xsbS
|
|
|
const { statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
|
|
|
const { topNavActive, leftActive, SelectShopInfo } = storeToRefs(useSysXsbStore())
|
|
|
const { userInfo, token } = storeToRefs(useUserStore())
|
|
|
+const { getTotalNum } = storeToRefs(useSmqjhCartStore())
|
|
|
const classfiylist = computed(() => props.categoryList)
|
|
|
const sortClassBtn = ref(1)
|
|
|
const show = ref(false)
|
|
|
const cartList = ref<Api.xsbCategoriesCartList[]>([])
|
|
|
+const cartPopup = ref(false)
|
|
|
+const totalProduct = ref<Api.shoppingCartOrderConfirm>()
|
|
|
+const priceDetailPopup = ref(false)
|
|
|
const cartIds = computed(() => cartList.value.filter(it => it.isDelete !== '1' && it.shopSkuStocks !== '0').map(it => it.id))
|
|
|
+// 勾选状态:只计算勾选商品的价格
|
|
|
+const selectedIds = ref<number[]>([])
|
|
|
+const isAllSelected = computed(() => cartIds.value.length > 0 && cartIds.value.every(id => selectedIds.value.includes(id)))
|
|
|
+const selectedCount = computed(() => selectedIds.value.length)
|
|
|
+
|
|
|
+function toggleSelectAll() {
|
|
|
+ if (isAllSelected.value) {
|
|
|
+ selectedIds.value = []
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ selectedIds.value = [...cartIds.value]
|
|
|
+ }
|
|
|
+ getGoodsPrice()
|
|
|
+}
|
|
|
+async function handleClearCart() {
|
|
|
+ useGlobalMessage().confirm({
|
|
|
+ title: '提示',
|
|
|
+ msg: '确认清空购物车?',
|
|
|
+ success: async () => {
|
|
|
+ uni.showLoading({ mask: true })
|
|
|
+ try {
|
|
|
+ const ids = cartList.value.map(it => it.id).join(',')
|
|
|
+ if (ids) {
|
|
|
+ await Apis.common.deleteShoppingCart({ pathParams: { ids } })
|
|
|
+ }
|
|
|
+ cartPopup.value = false
|
|
|
+ selectedIds.value = []
|
|
|
+ totalProduct.value = undefined
|
|
|
+ useSmqjhCartStore().getCartList('XSB')
|
|
|
+ await getCartCategorList()
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ uni.hideLoading()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ })
|
|
|
+}
|
|
|
const showball = ref(false)
|
|
|
const _this = getCurrentInstance()
|
|
|
const selectGoods = ref(false)
|
|
|
@@ -23,7 +64,6 @@ const goodsInTo = ref()
|
|
|
const goodsInfo = ref<Api.xsbCategoryProductList | Api.xsbProductDetail | undefined>()
|
|
|
|
|
|
const isTopLoading = ref(false)
|
|
|
-const cartPopup = ref(false)
|
|
|
const basllObj = ref({
|
|
|
left: 0,
|
|
|
top: 0,
|
|
|
@@ -42,7 +82,6 @@ const goodsLoading = ref<LoadMoreState>()
|
|
|
const navHeight = computed(() => {
|
|
|
return (`${Number(MenuButtonHeight.value) + Number(statusBarHeight.value)}px`)
|
|
|
})
|
|
|
-const totalProduct = ref<Api.shoppingCartOrderConfirm>()
|
|
|
function handleTopNavChange(item: Api.xsbCategoriesChildren) {
|
|
|
topNavActive.value = item.code
|
|
|
if (!item.children)
|
|
|
@@ -65,6 +104,8 @@ const categoriesId = computed(() => {
|
|
|
})
|
|
|
async function getCartCategorList() {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
+ // 记录刷新前的 ID 集合,用于检测新增商品
|
|
|
+ const prevIdSet = new Set(cartList.value.map(it => it.id))
|
|
|
Apis.xsb.myShoppingCartCategory({
|
|
|
data: {
|
|
|
businessType: 'XSB',
|
|
|
@@ -73,9 +114,23 @@ async function getCartCategorList() {
|
|
|
},
|
|
|
}).then((res) => {
|
|
|
cartList.value = res.data
|
|
|
+ const validIds = res.data
|
|
|
+ .filter(it => it.isDelete !== '1' && it.shopSkuStocks !== '0')
|
|
|
+ .map(it => it.id)
|
|
|
+ // 保留仍有效的已选项 + 自动选中新添加的商品
|
|
|
+ const newlyAdded = validIds.filter(id => !prevIdSet.has(id))
|
|
|
+ const keepSelected = selectedIds.value.filter(id => validIds.includes(id))
|
|
|
+ selectedIds.value = [...new Set([...keepSelected, ...newlyAdded])]
|
|
|
+ // 第一次加载时全选
|
|
|
+ if (selectedIds.value.length === 0 && validIds.length > 0) {
|
|
|
+ selectedIds.value = [...validIds]
|
|
|
+ }
|
|
|
if (cartList.value.length) {
|
|
|
getGoodsPrice()
|
|
|
}
|
|
|
+ else {
|
|
|
+ totalProduct.value = undefined
|
|
|
+ }
|
|
|
resolve(res)
|
|
|
}).catch((err) => {
|
|
|
reject(err)
|
|
|
@@ -239,10 +294,13 @@ function handleGo(item: Api.xsbCategoryProductList) {
|
|
|
}
|
|
|
|
|
|
async function getGoodsPrice() {
|
|
|
- if (cartIds.value.length) {
|
|
|
- const res = await useSmqjhCartStore().getCartAddGoodsPrice(cartIds.value.join(','))
|
|
|
+ if (selectedIds.value.length) {
|
|
|
+ const res = await useSmqjhCartStore().getCartAddGoodsPrice(selectedIds.value.join(','))
|
|
|
totalProduct.value = res
|
|
|
}
|
|
|
+ else {
|
|
|
+ totalProduct.value = undefined
|
|
|
+ }
|
|
|
}
|
|
|
async function handleSub(item: Api.xsbCategoriesCartList) {
|
|
|
if (item.num === 1) {
|
|
|
@@ -563,11 +621,31 @@ function handlePay() {
|
|
|
class="fixedShadow fixed bottom-60rpx left-0 z-100 box-border w-full flex items-center justify-between rounded-t-16rpx bg-white px24rpx pb60rpx pt10rpx"
|
|
|
>
|
|
|
<view class="ios w-full flex items-center justify-between">
|
|
|
- <view class="flex items-center" @click="cartPopup = true">
|
|
|
- <image :src="`${StaticUrl}/cart-lanzi.png`" class="cart-box h100rpx w100rpx" />
|
|
|
+ <view class="flex items-center">
|
|
|
+ <view class="flex items-center" @click="cartPopup = true, priceDetailPopup = false">
|
|
|
+ <wd-badge :model-value="getTotalNum" :top="20">
|
|
|
+ <image :src="`${StaticUrl}/cart-lanzi.png`" class="cart-box h100rpx w100rpx" />
|
|
|
+ </wd-badge>
|
|
|
+ </view>
|
|
|
+ <view class="ml40rpx">
|
|
|
+ <view class="flex items-center">
|
|
|
+ <view class="font-semibold">
|
|
|
+ ¥ {{ totalProduct?.amount || 0 }}
|
|
|
+ </view>
|
|
|
+ <view v-if="totalProduct?.coupon" class="ml10rpx text-24rpx text-#FF4A39">
|
|
|
+ 共减¥{{ totalProduct?.coupon }}
|
|
|
+ </view>
|
|
|
+ <view v-if="totalProduct?.amount" class="ml10rpx text-24rpx text-gray" @click="priceDetailPopup = true, cartPopup = false">
|
|
|
+ 明细 <wd-icon name="arrow-up" size="24rpx" color="#aaa" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="mt10rpx text-24rpx text-gray">
|
|
|
+ 配送费:¥{{ totalProduct?.transfee || 0 }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
<view class="flex items-center">
|
|
|
- <view class="flex items-center font-semibold">
|
|
|
+ <!-- <view class="flex items-center font-semibold">
|
|
|
<view class="text-22rpx text-#222">
|
|
|
总计:
|
|
|
</view>
|
|
|
@@ -577,7 +655,7 @@ function handlePay() {
|
|
|
{{ totalProduct?.price || '0.00' }}
|
|
|
</text>
|
|
|
</view>
|
|
|
- </view>
|
|
|
+ </view> -->
|
|
|
<view class="ml20rpx w160rpx">
|
|
|
<wd-button block size="large" @click="handlePay">
|
|
|
结算
|
|
|
@@ -586,70 +664,147 @@ function handlePay() {
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
+ <!-- 价格明细弹窗 -->
|
|
|
+ <Zpopup v-model="priceDetailPopup" :zindex="10" bg="#fff">
|
|
|
+ <view class="ios box-border w-full px-40rpx pb-60rpx pt-36rpx">
|
|
|
+ <view class="mb-40rpx text-center text-32rpx font-semibold">
|
|
|
+ 价格明细
|
|
|
+ </view>
|
|
|
+ <!-- 商品合计 -->
|
|
|
+ <view class="flex items-center justify-between py-20rpx">
|
|
|
+ <view class="text-30rpx font-semibold">
|
|
|
+ 商品合计
|
|
|
+ </view>
|
|
|
+ <view class="text-30rpx font-semibold">
|
|
|
+ ¥{{ totalProduct?.amount }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- 商品总价 -->
|
|
|
+ <view class="flex items-center justify-between py-20rpx">
|
|
|
+ <view class="text-28rpx text-#333">
|
|
|
+ 商品总价
|
|
|
+ </view>
|
|
|
+ <view class="text-28rpx text-#333">
|
|
|
+ ¥{{ totalProduct?.price }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- 下单用券共减 -->
|
|
|
+ <template v-if="totalProduct?.coupon">
|
|
|
+ <view class="flex items-center justify-between py-20rpx">
|
|
|
+ <view class="text-28rpx text-#333">
|
|
|
+ 下单用券共减
|
|
|
+ </view>
|
|
|
+ <view class="text-28rpx text-#FF4A39 font-semibold">
|
|
|
+ -¥{{ totalProduct?.coupon }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- 券名称子行 -->
|
|
|
+ <view v-if="totalProduct?.couponName" class="flex items-center justify-between pb-20rpx">
|
|
|
+ <view class="text-24rpx text-#AAAAAA">
|
|
|
+ {{ totalProduct?.couponName }}
|
|
|
+ </view>
|
|
|
+ <view class="text-24rpx text-#AAAAAA">
|
|
|
+ -¥{{ totalProduct?.coupon }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ <!-- 配送费 -->
|
|
|
+ <view class="flex items-center justify-between py-20rpx">
|
|
|
+ <view class="text-28rpx text-#333">
|
|
|
+ 配送费
|
|
|
+ </view>
|
|
|
+ <view class="text-28rpx text-#333">
|
|
|
+ ¥{{ totalProduct?.transfee }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="h200rpx" />
|
|
|
+ </Zpopup>
|
|
|
<Zpopup v-model="cartPopup" :zindex="99">
|
|
|
- <view class="ios h800rpx overflow-y-scroll">
|
|
|
- <view class="p24rpx">
|
|
|
- <view
|
|
|
- v-for="item in cartList" :key="item.id" class="relative mt20rpx box-border flex items-center overflow-hidden rounded-16rpx bg-white p24rpx"
|
|
|
- >
|
|
|
- <view class="flex flex-1">
|
|
|
- <image
|
|
|
- :src="item.pic"
|
|
|
- class="h206rpx w200rpx flex-shrink-0"
|
|
|
- @click.stop="router.push({ name: 'xsb-goods', params: { id: String(item.prodId) } })"
|
|
|
- />
|
|
|
- <view class="ml20rpx flex-1">
|
|
|
- <view class="text-left text-28rpx font-semibold">
|
|
|
- <!-- <view v-for="i in 2" :key="i" class="mr5px inline-block">
|
|
|
- <wd-tag type="danger">
|
|
|
- 惊喜回馈
|
|
|
- </wd-tag>
|
|
|
- </view> -->
|
|
|
- {{ item.skuName }}
|
|
|
- </view>
|
|
|
- <view class="mt14rpx text-24rpx text-#AAAAAA">
|
|
|
- 规格:{{ item.spec }}
|
|
|
- </view>
|
|
|
- <view class="mt14rpx flex items-center justify-between">
|
|
|
- <view class="text-36rpx text-#FF4A39 font-semibold">
|
|
|
- ¥{{ item.price }}
|
|
|
- </view>
|
|
|
- <!-- <wd-input-number v-model="item.num" disable-input @change="handleChangeNum($event, item)" /> -->
|
|
|
- <view v-if="item.shopSkuStocks !== '0' && item.isDelete !== '1'" class="flex items-center">
|
|
|
- <image
|
|
|
- :src="` ${StaticUrl}/sub-cart.png`"
|
|
|
- class="h44rpx w44rpx"
|
|
|
- @click.stop="handleSub(item)"
|
|
|
- />
|
|
|
- <view class="box-border h44rpx w84rpx flex items-center justify-center border border-#F0F0F0 border-solid text-24rpx text-#AAAAAA">
|
|
|
- {{ item.num }}
|
|
|
+ <view class="ios overflow-hidden">
|
|
|
+ <!-- 头部:全选 + 已选件数 + 清空购物车 -->
|
|
|
+ <view class="flex items-center justify-between border-b border-[#F5F5F5] border-solid px-24rpx py-24rpx">
|
|
|
+ <view class="flex items-center">
|
|
|
+ <wd-checkbox :model-value="isAllSelected" size="large" @change="toggleSelectAll">
|
|
|
+ 全选
|
|
|
+ </wd-checkbox>
|
|
|
+ <text class="ml-16rpx text-24rpx text-[#AAAAAA]">
|
|
|
+ 已选{{ selectedCount }}件
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ <view class="text-24rpx text-[#AAAAAA]" @click="handleClearCart">
|
|
|
+ <wd-icon name="delete" size="24rpx" /> 清空购物车
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- 商品列表 -->
|
|
|
+ <view class="h-700rpx overflow-y-scroll">
|
|
|
+ <view class="p-24rpx">
|
|
|
+ <wd-checkbox-group v-model="selectedIds" @change="getGoodsPrice">
|
|
|
+ <view
|
|
|
+ v-for="item in cartList" :key="item.id"
|
|
|
+ class="relative mt-20rpx box-border flex items-center overflow-hidden rounded-16rpx bg-white p-24rpx"
|
|
|
+ >
|
|
|
+ <!-- 复选框 -->
|
|
|
+ <wd-checkbox
|
|
|
+ v-if="item.shopSkuStocks !== '0' && item.isDelete !== '1'"
|
|
|
+ :model-value="item.id"
|
|
|
+ size="large"
|
|
|
+ class="mr-16rpx flex-shrink-0"
|
|
|
+ />
|
|
|
+ <view v-else class="mr-16rpx h-40rpx w-40rpx flex-shrink-0" />
|
|
|
+ <view class="flex flex-1">
|
|
|
+ <image
|
|
|
+ :src="item.pic"
|
|
|
+ class="h206rpx w200rpx flex-shrink-0"
|
|
|
+ @click.stop="router.push({ name: 'xsb-goods', params: { id: String(item.prodId) } })"
|
|
|
+ />
|
|
|
+ <view class="ml20rpx flex-1">
|
|
|
+ <view class="text-left text-28rpx font-semibold">
|
|
|
+ {{ item.skuName }}
|
|
|
+ </view>
|
|
|
+ <view class="mt14rpx text-24rpx text-#AAAAAA">
|
|
|
+ 规格:{{ item.spec }}
|
|
|
+ </view>
|
|
|
+ <view class="mt14rpx flex items-center justify-between">
|
|
|
+ <view class="text-36rpx text-#FF4A39 font-semibold">
|
|
|
+ ¥{{ item.price }}
|
|
|
+ </view>
|
|
|
+ <view v-if="item.shopSkuStocks !== '0' && item.isDelete !== '1'" class="flex items-center">
|
|
|
+ <image
|
|
|
+ :src="` ${StaticUrl}/sub-cart.png`"
|
|
|
+ class="h44rpx w44rpx"
|
|
|
+ @click.stop="handleSub(item)"
|
|
|
+ />
|
|
|
+ <view class="box-border h44rpx w84rpx flex items-center justify-center border border-#F0F0F0 border-solid text-24rpx text-#AAAAAA">
|
|
|
+ {{ item.num }}
|
|
|
+ </view>
|
|
|
+ <image
|
|
|
+ :src="` ${StaticUrl}/add-cart.png`"
|
|
|
+ class="h44rpx w44rpx"
|
|
|
+ @click.stop="handleAdd(item)"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
</view>
|
|
|
- <image
|
|
|
- :src="` ${StaticUrl}/add-cart.png`"
|
|
|
- class="h44rpx w44rpx"
|
|
|
- @click.stop="handleAdd(item)"
|
|
|
- />
|
|
|
</view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- <view v-if="item.shopSkuStocks == '0' || item.isDelete == '1'" class="absolute left-0 top-0 z-1 h-full w-full bg-[rgba(255,255,255,.6)]">
|
|
|
- <view class="relative w-full flex items-center justify-center">
|
|
|
- <view class="rounded-16rpx bg-[rgba(0,0,0,.5)] p20rpx text-white">
|
|
|
- {{ item.shopSkuStocks == '0' ? '商品已售罄' : '商品已删除' }}
|
|
|
- </view>
|
|
|
- <view class="absolute bottom-20rpx right-20rpx">
|
|
|
- <wd-button @click="handleDelCartGoods(item)">
|
|
|
- 删除商品
|
|
|
- </wd-button>
|
|
|
+ <view v-if="item.shopSkuStocks == '0' || item.isDelete == '1'" class="absolute left-0 top-0 z-1 h-full w-full bg-[rgba(255,255,255,.6)]">
|
|
|
+ <view class="relative w-full flex items-center justify-center">
|
|
|
+ <view class="rounded-16rpx bg-[rgba(0,0,0,.5)] p20rpx text-white">
|
|
|
+ {{ item.shopSkuStocks == '0' ? '商品已售罄' : '商品已删除' }}
|
|
|
+ </view>
|
|
|
+ <view class="absolute bottom-20rpx right-20rpx">
|
|
|
+ <wd-button @click="handleDelCartGoods(item)">
|
|
|
+ 删除商品
|
|
|
+ </wd-button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
+ </wd-checkbox-group>
|
|
|
</view>
|
|
|
+ <StatusTip v-if="!cartList.length" tip="暂无内容" />
|
|
|
+ <view class="h320rpx" />
|
|
|
</view>
|
|
|
- <StatusTip v-if="!cartList.length" tip="暂无内容" />
|
|
|
-
|
|
|
- <view class="h320rpx" />
|
|
|
</view>
|
|
|
</Zpopup>
|
|
|
<selectSku v-model:show="selectGoods" v-model:sku-id="selectSkuId" v-model:select-goods-num="SelectGoodsNum" :goods-info="goodsInfo!">
|