410 lines
11 KiB
Vue
410 lines
11 KiB
Vue
<template>
|
||
<view class="pages-cart">
|
||
<u-navbar
|
||
leftIcon="trash"
|
||
title="购物车"
|
||
fixed
|
||
@leftClick="remove"
|
||
/>
|
||
<view v-if="isLoad">
|
||
<view
|
||
v-if="list.length === 0"
|
||
class="tc"
|
||
style="margin-top: 300rpx"
|
||
>
|
||
<image
|
||
:src="$VUE_APP_RESOURCES_URL + '/20240106211138206789.png'"
|
||
style="width: 420rpx;height: 418rpx"
|
||
mode="scaleToFill"
|
||
/>
|
||
</view>
|
||
<view
|
||
v-for="(item, index) in list"
|
||
:key="index"
|
||
class="group-item"
|
||
>
|
||
<view class="flex jc-between">
|
||
<view class="flex ai-center">
|
||
<CheckboxIcon
|
||
:default-state="item['state']"
|
||
:mark="[index]"
|
||
style="margin-right: 24rpx;"
|
||
@change="onChange"
|
||
/>
|
||
<image
|
||
:src="item['merAvatar']"
|
||
class="store-cover"
|
||
mode="scaleToFill"
|
||
/>
|
||
<view style="color:#333333;font-size: 30rpx">{{ item['merName'] }}</view>
|
||
</view>
|
||
<view
|
||
class="flex ai-center"
|
||
style="color:#E92727;font-size: 24rpx"
|
||
@click="navToStore(item['hotelId'])"
|
||
>
|
||
进店逛逛
|
||
<image
|
||
:src="$VUE_APP_RESOURCES_URL + '/20240109234706982937.png'"
|
||
style="width: 24rpx;height: 24rpx"
|
||
mode="scaleToFill"
|
||
/>
|
||
</view>
|
||
</view>
|
||
<view class="good-box">
|
||
<view
|
||
v-for="(good, gIndex) in item['carts']"
|
||
:key="gIndex"
|
||
class="good flex ai-center"
|
||
>
|
||
<CheckboxIcon
|
||
:default-state="good['state']"
|
||
:mark="[index, gIndex]"
|
||
style="margin-right: 24rpx;"
|
||
@change="onChange"
|
||
/>
|
||
<image
|
||
v-if="good['productInfo']['attrInfo']['image']"
|
||
:src="good['productInfo']['attrInfo']['image']"
|
||
class="good-cover flex-0"
|
||
mode="scaleToFill"
|
||
@click="navToGood(good['productId'])"
|
||
/>
|
||
<image
|
||
v-else
|
||
:src="good['productInfo']['image']"
|
||
mode="scaleToFill"
|
||
class="good-cover flex-0"
|
||
@click="navToGood(good['productId'])"
|
||
/>
|
||
<view style="width: 100%">
|
||
<view
|
||
class="one-t"
|
||
@click="navToGood(good['productId'])"
|
||
>{{ good['productInfo']['storeName'] }}</view>
|
||
<view
|
||
class="sku ai-center"
|
||
@click="navToGood(good['productId'])"
|
||
>
|
||
规格:{{ good['productInfo']['attrInfo']['sku'] }}
|
||
</view>
|
||
<view
|
||
class="flex jc-between ai-center"
|
||
style="width: 100%;margin-top: 26rpx;"
|
||
>
|
||
<view
|
||
style="color:#E92727;font-size: 32rpx;"
|
||
@click="navToGood(good['productId'])"
|
||
>
|
||
<text class="bold" style="font-size: 24rpx">¥</text>
|
||
{{ good['truePrice'] }}
|
||
</view>
|
||
<u-number-box
|
||
:value="good.cartNum"
|
||
:max="good['productInfo']['attrInfo']['stock']"
|
||
integer
|
||
disabledInput
|
||
iconStyle="color: #fff"
|
||
class="num-step"
|
||
@change="e => changeNumHandle(index, gIndex, good, e)"
|
||
>
|
||
<template v-slot:minus>
|
||
<view class="num-btn flex jc-center ai-center">
|
||
<u-icon name="minus" size="12" color="#FFFFFF"/>
|
||
</view>
|
||
</template>
|
||
<template v-slot:input>
|
||
<view class="num-input tc">{{ good['cartNum'] }}</view>
|
||
</template>
|
||
<template v-slot:plus>
|
||
<view class="num-btn flex jc-center ai-center">
|
||
<u-icon name="plus" size="12" color="#FFFFFF"/>
|
||
</view>
|
||
</template>
|
||
</u-number-box>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="footer-fixed flex jc-between ai-center">
|
||
<view style="margin-left: 32rpx;">
|
||
<CheckboxIcon
|
||
style="margin-right: 24rpx;"
|
||
:default-state="isAll"
|
||
:mark="[-1]"
|
||
@change="onChange"
|
||
/>
|
||
<text style="color:#666666;font-size: 32rpx">全选({{ selectCount }})</text>
|
||
</view>
|
||
<view class="flex ai-center">
|
||
<view style="margin-right: 20rpx;color:#666666;font-size: 32rpx">合计:
|
||
<text class="bold" style="color:#E92727">¥{{ total }}</text>
|
||
</view>
|
||
<view class="btn-submit bold flex jc-center ai-center" @click="submit">结算</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<goo-skeleton
|
||
v-else
|
||
:show-avatar="false"
|
||
/>
|
||
</view>
|
||
</template>
|
||
<script>
|
||
import {changeCartNum, getCartGroup, postCartDel} from '@/api/store'
|
||
import CheckboxIcon from '@/components/CheckboxIcon.vue'
|
||
export default {
|
||
components: {
|
||
CheckboxIcon
|
||
},
|
||
data() {
|
||
return {
|
||
isLoad: false,
|
||
list: [],
|
||
isAll: false
|
||
}
|
||
},
|
||
computed: {
|
||
total() {
|
||
let price = 0
|
||
this.list.forEach(item => {
|
||
item['carts'].forEach(good => {
|
||
if (good.state) price += Math.round(good['cartNum'] * good['truePrice'] * 100) / 100
|
||
})
|
||
})
|
||
return Math.round(price * 100) / 100
|
||
},
|
||
selectCount() {
|
||
let count = 0
|
||
this.list.forEach(item => {
|
||
item['carts'].forEach(good => {
|
||
if (good.state) count++
|
||
})
|
||
})
|
||
return count
|
||
}
|
||
},
|
||
created() {
|
||
this.getCart()
|
||
},
|
||
onShow() {
|
||
if (!this.isLoad) {
|
||
return
|
||
}
|
||
this.getCart()
|
||
},
|
||
methods: {
|
||
async getCart() {
|
||
const res = await getCartGroup()
|
||
if (res.success) {
|
||
this.isLoad = true
|
||
this.list = res.data['valid']
|
||
this.handleAll(false)
|
||
}
|
||
},
|
||
handleAll(state) {
|
||
this.isAll = state
|
||
this.list = this.list.map(item => {
|
||
item.state = state
|
||
item.carts = item.carts.map(good => {
|
||
good.state = state
|
||
return good
|
||
})
|
||
return item
|
||
})
|
||
},
|
||
navToStore(id) {
|
||
if (id === 0) {
|
||
uni.showToast({
|
||
title: '店铺装修中~',
|
||
icon: 'none',
|
||
duration: 3000
|
||
})
|
||
return
|
||
}
|
||
uni.navigateTo({
|
||
url: '/pagesInn/inn/innHome?id=' + id
|
||
})
|
||
},
|
||
onChange(state, mark) {
|
||
if (mark.length === 1) {
|
||
if (mark[0] === -1) {
|
||
this.handleAll(state)
|
||
} else {
|
||
this.list[mark[0]]['state'] = state
|
||
this.list[mark[0]]['carts'] = this.list[mark[0]]['carts'].map(good => {
|
||
good.state = state
|
||
return good
|
||
})
|
||
}
|
||
}
|
||
if (mark.length === 2) {
|
||
this.list[mark[0]]['carts'][mark[1]]['state'] = state
|
||
const length = this.list[mark[0]]['carts'].length
|
||
let count = 0
|
||
this.list[mark[0]]['carts'] = this.list[mark[0]]['carts'].map((good, gIndex) => {
|
||
if (gIndex === mark[1]) good['state'] = state
|
||
if (good['state']) count++
|
||
return good
|
||
})
|
||
this.list[mark[0]]['state'] = count === length
|
||
}
|
||
},
|
||
changeNumHandle(index, gIndex, good, e) {
|
||
const { type } = e
|
||
const value = good.cartNum + (type === 'plus' ? 1 : -1)
|
||
const id = good.id
|
||
uni.showLoading()
|
||
changeCartNum(id, value).then(res => {
|
||
const { success } = res
|
||
if (success) {
|
||
this.$set(this.list[index].carts[gIndex], 'cartNum', value)
|
||
}
|
||
}).catch(() => {
|
||
uni.hideLoading()
|
||
}).finally(() => {
|
||
uni.hideLoading()
|
||
})
|
||
},
|
||
handleIds() {
|
||
if (this.selectCount === 0) {
|
||
uni.showToast({
|
||
title: '请选择产品',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
return []
|
||
}
|
||
const ids = []
|
||
this.list.forEach(item => {
|
||
item['carts'].forEach(good => {
|
||
if (good['state']) ids.push(good['id'])
|
||
})
|
||
})
|
||
return ids
|
||
},
|
||
remove() {
|
||
const ids = this.handleIds()
|
||
if (ids.length === 0) return
|
||
uni.showModal({
|
||
title: '确认删除已选商品?',
|
||
content: '',
|
||
showCancel: true,
|
||
cancelText: '取消',
|
||
confirmText: '确认',
|
||
success: async (result) => {
|
||
if (result.confirm) {
|
||
uni.showLoading()
|
||
postCartDel(ids).then(res => {
|
||
const { success } = res
|
||
if (success) {
|
||
this.getCart()
|
||
}
|
||
}).finally(() => {
|
||
uni.hideLoading()
|
||
})
|
||
}
|
||
}
|
||
})
|
||
},
|
||
submit() {
|
||
const ids = this.handleIds()
|
||
if (ids.length === 0) return
|
||
uni.navigateTo({
|
||
url: '/pages/order/OrderSubmission/index?id=' + ids.join(',')
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
view {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.pages-cart {
|
||
min-height: 100vh;
|
||
padding-top: calc(var(--status-bar-height) + 54px);
|
||
padding-bottom: 100rpx;
|
||
}
|
||
|
||
.group-item {
|
||
width: 710rpx;
|
||
margin: 12rpx 20rpx;
|
||
padding: 8rpx 8rpx 32rpx 20rpx;
|
||
background: #FFFFFF;
|
||
border-radius: 12rpx;
|
||
|
||
.store-cover {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
margin-right: 8rpx;
|
||
border-radius: 50%;
|
||
}
|
||
}
|
||
|
||
.good-box {
|
||
.good {
|
||
margin-top: 24rpx;
|
||
|
||
.good-cover {
|
||
width: 160rpx;
|
||
height: 160rpx;
|
||
margin-right: 16rpx;
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
.one-t {
|
||
width: 420rpx;
|
||
color: #333333;
|
||
font-size: 30rpx;
|
||
line-height: 42rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.sku {
|
||
display: inline-flex;
|
||
margin-top: 12rpx;
|
||
padding: 10rpx 20rpx;
|
||
border-radius: 22rpx;
|
||
background: #FDF1F3;
|
||
color: #999999;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.num-btn {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
background: rgba(236, 236, 238, 1);
|
||
border: 2px solid rgba(236, 236, 238, 1);
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.num-input {
|
||
width: 64rpx;
|
||
color: #333333;
|
||
font-size: 30rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.footer-fixed {
|
||
position: fixed;
|
||
left: 0;
|
||
bottom: 0;
|
||
width: 100vw;
|
||
height: 100rpx;
|
||
box-shadow: 0 6rpx 12rpx rgba(0, 0, 0, 0.16);
|
||
background: #FFFFFF;
|
||
|
||
.btn-submit {
|
||
width: 196rpx;
|
||
height: 100rpx;
|
||
background: #FD5749;
|
||
color: #FFFFFF;
|
||
font-size: 32rpx;
|
||
}
|
||
}
|
||
</style> |