Feat(购物车):增加切换规格功能

This commit is contained in:
lifizer
2024-04-08 17:35:39 +08:00
parent b02bba911d
commit 22cd5160bf
2 changed files with 308 additions and 3 deletions
+14
View File
@@ -144,6 +144,20 @@ export function changeCartNum(id, number) {
});
}
/*
* 购物车 获取商品规格
* */
export function getCartGoodAttr(id, uniqueId) {
return request.get(`/product/attr/${id}?uniqueId=${uniqueId}`)
}
/*
* 购物车 商品规格修改
* */
export function cartGoodChangeAttr(data) {
return request.post('/cart/changeAttr', data)
}
/**
* 搜索推荐关键字
*/
+294 -3
View File
@@ -84,7 +84,7 @@
>{{ good['productInfo']['storeName'] }}</view>
<view
class="sku ai-center"
@click="navToGood(good['productId'])"
@click="changeGoodAttrHandle(good)"
>
规格:{{ good['productInfo']['attrInfo']['sku'] }}
</view>
@@ -144,6 +144,61 @@
<view class="btn-submit bold flex jc-center ai-center" @click="submit">结算</view>
</view>
</view>
<view
v-show="showAttr"
class="good-attr-wrap"
>
<view class="layer" @click="closeAttr" />
<view class="content">
<view class="close">
<text class="iconfont icon-guanbi" @click="closeAttr"></text>
</view>
<view class="good-info">
<view class="name-img">
<image :src="currGoodAttr.image" class="img" />
<view class="name">
<view class="more-t">
{{ currGood.productInfo.storeName }}
</view>
<view class="price">
<text class="txt">¥</text>{{ currGoodAttr.price }}
</view>
</view>
</view>
</view>
<view class="attr-wrap">
<view
v-for="(item, index) in goodAttr.productAttr"
:key="index"
class="item"
>
<view class="title">{{ item.attrName }}</view>
<view class="acea-row row-middle">
<view
v-for="(attr, attrIndex) in item.attrValue"
:key="attr"
:class="{
'on': attr.check
}"
class="attr"
@click="attrItemClick(attr, attrIndex, index)"
>
{{ attr.attr }}
</view>
</view>
</view>
</view>
<view class="bottom">
<view
:class="currGoodAttr.stock === 0 ? 'disabled' : ''"
class="btn"
@click="changeAttrConfirm"
>
确认
</view>
</view>
</view>
</view>
</view>
<goo-skeleton
v-else
@@ -152,7 +207,13 @@
</view>
</template>
<script>
import {changeCartNum, getCartGroup, postCartDel} from '@/api/store'
import {
changeCartNum,
getCartGroup,
postCartDel,
getCartGoodAttr,
cartGoodChangeAttr
} from '@/api/store'
import CheckboxIcon from '@/components/CheckboxIcon.vue'
export default {
components: {
@@ -162,7 +223,14 @@ export default {
return {
isLoad: false,
list: [],
isAll: false
isAll: false,
currGood: {},
currGoodAttr: {},
goodAttr: {
productAttr: [],
productValue: {}
},
showAttr: false
}
},
computed: {
@@ -192,6 +260,7 @@ export default {
if (!this.isLoad) {
return
}
this.closeAttr()
this.getCart()
},
methods: {
@@ -308,6 +377,114 @@ export default {
}
})
},
changeGoodAttrHandle(good) {
const id = good.productInfo.id
const unique = good.productInfo.attrInfo.unique
uni.showLoading()
getCartGoodAttr(id, unique).then(res => {
const { success, data } = res
if (success) {
this.currGood = good
this.goodAttr = data
this.goodAttr.productAttr.map((item, index) => {
item.attrValue.map((attr, attrIndex) => {
attr.check = data.defaultSkuIndex[index] === attrIndex
})
})
this.currGoodAttr = data.productValue[data.defaultSku.sort().join(',')]
this.showAttr = true
}
}).finally(() => {
uni.hideLoading()
})
},
getAttrItemData(attr) {
let result = {}
this.goodAttr.productAttr.map(item => {
if (item.attrItemkey === attr) {
result = item
}
})
return result
},
// 规格切换
attrItemClick(attr, attrIndex, index) {
const tempArr = JSON.parse(JSON.stringify(this.goodAttr))
tempArr.productAttr[index].attrValue.map(attrItem => {
attrItem.check = false
})
// 预设目标规格选中
tempArr.productAttr[index].attrValue[attrIndex].check = true
const arr = []
tempArr.productAttr.map((item) => {
item.attrValue.map((attrItem) => {
if (attrItem.check) {
// 将预选中的规格组合起来
arr.push(attrItem.attr)
}
})
})
if (arr.length > 0) {
const attrStr = arr.sort().join(',')
if (this.goodAttr.productValue[attrStr]) {
const stock = this.goodAttr.productValue[attrStr].stock
this.currGoodAttr = this.goodAttr.productValue[attrStr]
this.goodAttr.productAttr[index].attrValue.map(attrItem => {
attrItem.check = false
})
this.goodAttr.productAttr[index].attrValue[attrIndex].check = true
if (stock === 0) {
uni.showToast({
title: '库存不足',
icon: 'none',
duration: 3000
})
}
// if (stock > 0) {
// this.currGoodAttr = this.goodAttr.productValue[attrStr]
// this.goodAttr.productAttr[index].attrValue.map(attrItem => {
// attrItem.check = false
// })
// this.goodAttr.productAttr[index].attrValue[attrIndex].check = true
// } else {
// }
this.$forceUpdate()
}
}
},
// 确认切换
changeAttrConfirm() {
if (this.currGoodAttr.stock === 0) {
return
}
uni.showLoading()
cartGoodChangeAttr({
id: this.currGood.id,
uniqueId: this.currGoodAttr.unique
}).then(res => {
const { success } = res
if (success) {
this.getCart()
this.closeAttr()
}
}).catch(() => {
uni.hideLoading()
}).finally(() => {
uni.hideLoading()
})
},
closeAttr() {
this.currGoodAttr = {}
this.currGood = {}
this.showAttr = false
},
navToGood(id) {
this.$yrouter.push({
path: '/pages/shop/GoodsCon/index',
query: { id }
})
},
submit() {
const ids = this.handleIds()
if (ids.length === 0) return
@@ -407,4 +584,118 @@ view {
font-size: 32rpx;
}
}
.good-attr-wrap {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
.layer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
background-color: rgba(0, 0, 0, 0.5);
}
.content {
position: absolute;
left: 0;
right: 0;
bottom: 0;
z-index: 5;
max-height: 75vh;
padding: 30rpx;
border-top-left-radius: 30rpx;
border-top-right-radius: 30rpx;
box-sizing: border-box;
background-color: #fff;
overflow-y: auto;
.close {
position: absolute;
top: 30rpx;
right: 30rpx;
.iconfont {
font-size: 16px;
color: #666;
}
}
.good-info {
padding: 20rpx 0 0 0;
.name-img {
display: flex;
.img {
display: block;
width: 160rpx;
height: 160rpx;
margin: 0 20rpx 0 0;
}
.name {
width: calc(100% - 220rpx);
color: #333;
font-size: 16px;
}
.price {
margin: 20rpx 0 0 0;
color: #E92727;
font-size: 16px;
.txt{
font-size: 12px;
}
}
}
}
.attr-wrap {
padding: 30rpx 0 0 0;
.item + .item {
margin: 20rpx 0 0 0;
}
.title {
margin: 0 0 10rpx 0;
color: #999;
font-size: 28rpx;
}
.attr {
position: relative;
padding: 7rpx 33rpx;
margin: 14rpx 14rpx 0 0;
border: 1rpx solid #bbb;
border-radius: 6rpx;
color: #333;
font-size: 26rpx;
&.on {
color: #fff;
border-color: #eb3729;
background-color: #eb3729;
}
&.disabled {
color: #333;
border-color: #f1f1f1;
background-color: #f1f1f1;
.tag {
}
}
}
}
.bottom {
padding: 30rpx 0 0 0;
.btn {
height: 80rpx;
border-radius: 40rpx;
line-height: 80rpx;
text-align: center;
color: #fff;
font-size: 16px;
background-color: #E92727;
&.disabled {
color: #666;
background-color: #f1f1f1;
}
}
}
}
}
</style>