feat 对接购物车

This commit is contained in:
lwh 2023-08-06 16:17:16 +08:00
parent fa015b5cd4
commit 7272b0a14b
16 changed files with 378 additions and 145 deletions

View File

@ -1,22 +1,11 @@
<view class="cart-bar__placeholder" wx:if="{{fixed}}" />
<view class="cart-bar {{fixed ? 'cart-bar--fixed' : ''}} flex flex-v-center" style="bottom: {{fixed ? 'calc(' + bottomHeight + 'rpx + env(safe-area-inset-bottom))' : ''}};">
<t-icon
size="40rpx"
color="{{isAllSelected ? '#FA4126' : '#BBBBBB'}}"
name="{{isAllSelected ? 'check-circle-filled' : 'circle'}}"
class="cart-bar__check"
catchtap="handleSelectAll"
/>
<t-icon size="40rpx" color="{{isAllSelected ? '#FA4126' : '#BBBBBB'}}" name="{{isAllSelected ? 'check-circle-filled' : 'circle'}}" class="cart-bar__check" catchtap="handleSelectAll" />
<text>全选</text>
<view class="cart-bar__total flex1">
<view>
<text class="cart-bar__total--bold text-padding-right">总计</text>
<price
price="{{totalAmount || '0'}}"
fill="{{false}}"
decimalSmaller
class="cart-bar__total--bold cart-bar__total--price"
/>
<price priceUnit="yuan" price="{{totalAmount || '0'}}" fill="{{false}}" decimalSmaller class="cart-bar__total--bold cart-bar__total--price" />
<text class="cart-bar__total--normal">(不含运费)</text>
</view>
<view wx:if="{{totalDiscountAmount}}">
@ -28,4 +17,3 @@
去结算({{totalGoodsNum}})
</view>
</view>

View File

@ -44,7 +44,7 @@
width: 192rpx;
height: 80rpx;
border-radius: 40rpx;
background-color: #fa4126;
background-color: #1989fa;
font-size: 28rpx;
font-weight: bold;
line-height: 80rpx;

View File

@ -13,13 +13,17 @@ Component({
for (const store of storeGoods) {
for (const activity of store.promotionGoodsList) {
for (const goods of activity.goodsPromotionList) {
if(goods.specInfo){
goods.specs = goods.specInfo.map((item) => item.specValue); // 目前仅展示商品已选规格的值
}
}
}
for (const goods of store.shortageGoodsList) {
if(goods.specInfo){
goods.specs = goods.specInfo.map((item) => item.specValue); // 目前仅展示商品已选规格的值
}
}
}
this.setData({ _storeGoods: storeGoods });
},
@ -28,7 +32,9 @@ Component({
type: Array,
observer(invalidGoodItems) {
invalidGoodItems.forEach((goods) => {
if(goods.specInfo){
goods.specs = goods.specInfo.map((item) => item.specValue); // 目前仅展示商品已选规格的值
}
});
this.setData({ _invalidGoodItems: invalidGoodItems });
},
@ -127,6 +133,14 @@ Component({
});
},
gotoShop(e){
const { storeIndex } = e.currentTarget.dataset;
const store = this.data.storeGoods[storeIndex];
wx.navigateTo({
url: "/pages/shop/all-goods/index?shopGuid=" + store.storeId,
});
},
// 展开/收起切换
showToggle() {
this.setData({
@ -136,12 +150,12 @@ Component({
// 展示规格popup
specsTap(e) {
this.isSpecsTap = true;
const { goods } = e.currentTarget.dataset;
this.setData({
isShowSpecs: true,
currentGoods: goods,
});
// this.isSpecsTap = true;
// const { goods } = e.currentTarget.dataset;
// this.setData({
// isShowSpecs: true,
// currentGoods: goods,
// });
},
hideSpecsPopup() {

View File

@ -2,8 +2,8 @@
<wxs src="./utils.wxs" module="utils" />
<view class="cart-group">
<view class="goods-wrap" wx:for="{{_storeGoods}}" wx:for-item="store" wx:for-index="si" wx:key="storeId">
<view class="cart-store">
<view class="goods-wrap" wx:for="{{_storeGoods}}" wx:for-item="store" wx:for-index="si" wx:key="storeId" data-store-index="{{si}}" bindtap="gotoShop">
<view class="cart-store" >
<t-icon
size="40rpx"
color="{{store.isSelected ? '#FA4126' : '#BBBBBB'}}"
@ -17,7 +17,7 @@
<t-icon prefix="wr" size="40rpx" color="#333333" name="store" />
<view class="store-name">{{store.storeName}}</view>
</view>
<view class="get-coupon" catch:tap="gotoCoupons">优惠券</view>
<!-- <view class="get-coupon" catch:tap="gotoCoupons">优惠券</view> -->
</view>
</view>
<block wx:for="{{store.promotionGoodsList}}" wx:for-item="promotion" wx:for-index="promoindex" wx:key="promoindex">
@ -145,7 +145,7 @@
price="{{currentGoods.price || ''}}"
thumb="{{utils.imgCut(currentGoods.thumb, 180, 180)}}"
specs="{{currentGoods.specs || []}}"
zIndex="{{999}}"
zIndex="{{99}}"
bindclose="hideSpecsPopup"
/>

View File

@ -8,12 +8,18 @@
<view class="wr-goods-card__main">
<view class="wr-goods-card__thumb thumb-class" bind:tap="clickThumbHandle">
<!-- data-src 是方便加购动画读取图片用的 -->
<t-image
<!-- <t-image
t-class="wr-goods-card__thumb-com"
wx:if="{{ !!goods.thumb && !goods.hideKey.thumb }}"
src="{{ goods.thumb }}"
mode="{{ thumbMode }}"
lazy-load="{{ lazyLoad }}"
/> -->
<image
class="wr-goods-card__thumb-com"
wx:if="{{ !!goods.thumb && !goods.hideKey.thumb }}"
src="{{ goods.thumb }}"
mode="{{ thumbMode }}"
/>
<slot name="thumb-cover" />
</view>
@ -38,6 +44,7 @@
<slot name="price-prefix" />
<view wx:if="{{ goods.price && !goods.hideKey.price }}" class="wr-goods-card__price">
<price
priceUnit="yuan"
wr-class="price-class"
symbol="{{currency}}"
price="{{goods.price}}"
@ -48,6 +55,7 @@
<view wx:if="{{ goods.originPrice && !goods.hideKey.originPrice && isValidityLinePrice }}" class="wr-goods-card__origin-price">
<price
wr-class="origin-price-class"
priceUnit="yuan"
symbol="{{currency}}"
price="{{goods.originPrice}}"
fill="{{priceFill}}"

View File

@ -1,6 +1,20 @@
import Dialog from 'tdesign-miniprogram/dialog/index';
import Toast from 'tdesign-miniprogram/toast/index';
import { fetchCartGroupData } from '../../services/cart/cart';
import {
fetchCartGroupData
} from '~/services/cart/cart';
import {
updateCartGoodsNum
} from '~/services/cart/updateCartGoodsNum';
import {
updateCartGoodsSelect
} from '~/services/cart/updateCartGoodsSelect';
import {
selectAllCartGoods
} from '~/services/cart/selectAllCartGoods';
import {
deleteCart
} from '~/services/cart/deleteCart';
Page({
data: {
@ -9,6 +23,7 @@ Page({
// 调用自定义tabbar的init函数使页面与tabbar激活状态保持一致
onShow() {
this.refreshData();
this.getTabBar().init();
},
@ -20,7 +35,6 @@ Page({
this.getCartGroupData().then((res) => {
let isEmpty = true;
const cartGroupData = res;
console.log(cartGroupData,'1231232');
// 一些组件中需要的字段可能接口并没有返回,或者返回的数据结构与预期不一致,需要在此先对数据做一些处理
// 统计门店下加购的商品是否全选、是否存在缺货/无货
for (const store of cartGroupData.storeGoods) {
@ -62,7 +76,9 @@ Page({
// return goods;
// });
cartGroupData.isNotEmpty = !isEmpty;
this.setData({ cartGroupData });
this.setData({
cartGroupData
});
});
},
@ -70,7 +86,9 @@ Page({
let currentStore;
let currentActivity;
let currentGoods;
const { storeGoods } = this.data.cartGroupData;
const {
storeGoods
} = this.data.cartGroupData;
for (const store of storeGoods) {
for (const activity of store.promotionGoodsList) {
for (const goods of activity.goodsPromotionList) {
@ -96,68 +114,59 @@ Page({
// 注:实际场景时应该调用接口获取购物车数据
getCartGroupData() {
const { cartGroupData } = this.data;
if (!cartGroupData) {
return fetchCartGroupData();
}
return Promise.resolve({ data: cartGroupData });
},
// 选择单个商品
// 注:实际场景时应该调用接口更改选中状态
selectGoodsService({ spuId, skuId, isSelected }) {
this.findGoods(spuId, skuId).currentGoods.isSelected = isSelected;
return Promise.resolve();
selectGoodsService(
cartId,
isSelected
) {
let data = {
cartId: cartId,
isSelected: isSelected,
}
return updateCartGoodsSelect(data);
},
// 全选门店
// 注:实际场景时应该调用接口更改选中状态
selectStoreService({ storeId, isSelected }) {
selectStoreService({
storeId,
isSelected
}) {
const currentStore = this.data.cartGroupData.storeGoods.find((s) => s.storeId === storeId);
currentStore.isSelected = isSelected;
currentStore.promotionGoodsList.forEach((activity) => {
activity.goodsPromotionList.forEach((goods) => {
goods.isSelected = isSelected;
console.log(goods.cartId,'asdasd');
this.selectGoodsService(goods.cartId, isSelected)
});
});
return Promise.resolve();
},
// 加购数量变更
// 注:实际场景时应该调用接口
changeQuantityService({ spuId, skuId, quantity }) {
this.findGoods(spuId, skuId).currentGoods.quantity = quantity;
return Promise.resolve();
// 加购数量变更接口
changeQuantityService({
cartId,
quantity
}) {
// this.findGoods(spuId, skuId).currentGoods.quantity = quantity;
let data = {
cartId: cartId,
cartGoodsNum: quantity,
}
return updateCartGoodsNum(data).then((res) => {
this.refreshData();
})
},
// 删除加购商品
// 注:实际场景时应该调用接口
deleteGoodsService({ spuId, skuId }) {
function deleteGoods(group) {
for (const gindex in group) {
const goods = group[gindex];
if (goods.spuId === spuId && goods.skuId === skuId) {
group.splice(gindex, 1);
return gindex;
}
}
return -1;
}
const { storeGoods, invalidGoodItems } = this.data.cartGroupData;
for (const store of storeGoods) {
for (const activity of store.promotionGoodsList) {
if (deleteGoods(activity.goodsPromotionList) > -1) {
return Promise.resolve();
}
}
if (deleteGoods(store.shortageGoodsList) > -1) {
return Promise.resolve();
}
}
if (deleteGoods(invalidGoodItems) > -1) {
return Promise.resolve();
}
return Promise.reject();
deleteGoodsService(cartId) {
// console.log(cartId,'删除的id');
return deleteCart(cartId)
},
// 清空失效商品
@ -169,35 +178,59 @@ Page({
onGoodsSelect(e) {
const {
goods: { spuId, skuId },
goods: {
cartId,
spuId,
skuId
},
isSelected,
} = e.detail;
const { currentGoods } = this.findGoods(spuId, skuId);
Toast({
context: this,
selector: '#t-toast',
message: `${isSelected ? '选择' : '取消'}"${
currentGoods.title.length > 5 ? `${currentGoods.title.slice(0, 5)}...` : currentGoods.title
}"`,
icon: '',
// const {
// currentGoods
// } = this.findGoods(spuId, skuId);
// Toast({
// context: this,
// selector: '#t-toast',
// message: `${isSelected ? '选择' : '取消'}"${
// currentGoods.title.length > 5 ? `${currentGoods.title.slice(0, 5)}...` : currentGoods.title
// }"`,
// icon: '',
// });
this.selectGoodsService(
cartId,
isSelected
).then(() => {
this.refreshData()
});
this.selectGoodsService({ spuId, skuId, isSelected }).then(() => this.refreshData());
},
onStoreSelect(e) {
const {
store: { storeId },
store: {
storeId
},
isSelected,
} = e.detail;
this.selectStoreService({ storeId, isSelected }).then(() => this.refreshData());
this.selectStoreService({
storeId,
isSelected
}).then(() => this.refreshData());
},
// 修改购物车的商品数量
onQuantityChange(e) {
console.log(e.detail, '加够的信息');
const {
goods: { spuId, skuId },
goods: {
spuId,
skuId,
cartId
},
quantity,
} = e.detail;
const { currentGoods } = this.findGoods(spuId, skuId);
const {
currentGoods
} = this.findGoods(spuId, skuId);
const stockQuantity = currentGoods.stockQuantity > 0 ? currentGoods.stockQuantity : 0; // 避免后端返回的是-1
// 加购数量超过库存数量
if (quantity > stockQuantity) {
@ -218,15 +251,17 @@ Page({
})
.then(() => {
this.changeQuantityService({
spuId,
skuId,
quantity: stockQuantity,
}).then(() => this.refreshData());
cartId,
stockQuantity,
});
})
.catch(() => {});
return;
}
this.changeQuantityService({ spuId, skuId, quantity }).then(() => this.refreshData());
this.changeQuantityService({
cartId,
quantity
});
},
goCollect() {
@ -238,7 +273,10 @@ Page({
},
goGoodsDetail(e) {
const { spuId, storeId } = e.detail.goods;
const {
spuId,
storeId
} = e.detail.goods;
wx.navigateTo({
url: `/pages/goods/details/index?spuId=${spuId}&storeId=${storeId}`,
});
@ -251,28 +289,44 @@ Page({
onGoodsDelete(e) {
const {
goods: { spuId, skuId },
goods: {
cartId
},
} = e.detail;
Dialog.confirm({
content: '确认删除该商品吗?',
confirmBtn: '确定',
cancelBtn: '取消',
}).then(() => {
this.deleteGoodsService({ spuId, skuId }).then(() => {
Toast({ context: this, selector: '#t-toast', message: '商品删除成功' });
this.deleteGoodsService(cartId).then((res) => {
if (res.code === 200) {
Toast({
context: this,
selector: '#t-toast',
message: '商品删除成功'
});
this.refreshData();
}
});
});
},
onSelectAll(event) {
const { isAllSelected } = event?.detail ?? {};
Toast({
context: this,
selector: '#t-toast',
message: `${isAllSelected ? '取消' : '点击'}了全选按钮`,
});
const {
isAllSelected
} = event?.detail ?? {};
// Toast({
// context: this,
// selector: '#t-toast',
// message: `${isAllSelected ? '取消' : '点击'}了全选按钮`,
// });
// console.log(isAllSelected);
// 调用接口改变全选
selectAllCartGoods({isSelected: !isAllSelected}).then((res) => {
if(res.code === 200){
this.refreshData()
}
})
},
onToSettle() {
@ -287,9 +341,13 @@ Page({
});
});
wx.setStorageSync('order.goodsRequestList', JSON.stringify(goodsRequestList));
wx.navigateTo({ url: '/pages/order/order-confirm/index?type=cart' });
wx.navigateTo({
url: '/pages/order/order-confirm/index?type=cart'
});
},
onGotoHome() {
wx.switchTab({ url: '/pages/home/home' });
wx.switchTab({
url: '/pages/home/home'
});
},
});

View File

@ -1,5 +1,5 @@
<!-- 分层购物车 -->
<block wx:if="{{cartGroupData.isNotEmpty}}">
<block wx:if="{{cartGroupData.isNotEmpty}}" class="cart-box">
<cart-group
store-goods="{{ cartGroupData.storeGoods }}"
invalid-good-items="{{ cartGroupData.invalidGoodItems }}"
@ -20,7 +20,7 @@
total-goods-num="{{cartGroupData.selectedGoodsCount}}"
total-discount-amount="{{cartGroupData.totalDiscountAmount}}"
fixed="{{true}}"
bottomHeight="{{112}}"
bottomHeight="{{110}}"
bindhandleSelectAll="onSelectAll"
bindhandleToSettle="onToSettle"
/>

View File

@ -2,12 +2,13 @@
padding-bottom: 100rpx;
}
.cart-box{
margin-bottom: 1000rpx;
}
.gap {
height: 100rpx;
width: 100%;
}
.t-button {
--td-button-default-color: #000;
--td-button-primary-text-color: #fa4126;
}

View File

@ -338,6 +338,7 @@ Component({
this.setData({
buyNum: value,
});
this.setBuyNum(value)
},
},
});

View File

@ -2,6 +2,9 @@ import Toast from 'tdesign-miniprogram/toast/index';
import {
fetchGood
} from '~/services/good/fetchGood';
import {
addOrUpdateCart
} from '~/services/cart/addOrUpdateCart';
import {
fetchActivityList
} from '~/services/activity/fetchActivityList';
@ -77,6 +80,7 @@ Page({
specImg: '',
isSpuSelectPopupShow: false,
isAllSelectedSku: false,
selectedSkuId: 0,
buyType: 0,
outOperateStatus: false, // 是否外层加入购物车
operateType: 0,
@ -193,7 +197,9 @@ Page({
});
this.selectSpecsName(selectedSkuValues.length > 0 ? selectedAttrStr : '');
if (skuItem) {
console.log(skuItem[0]?.skuId,'选中的item');
this.setData({
selectedSkuId: skuItem[0]?.skuId,
selectItem: skuItem,
selectSkuSellsPrice: skuItem[0]?.priceInfo[0].price || 0,
selectSkuLinePrice: skuItem[0]?.priceInfo[1].price || 0,
@ -215,6 +221,7 @@ Page({
getSelectedSkuValues(skuTree, selectedSku) {
const normalizedTree = this.normalizeSkuTree(skuTree);
return Object.keys(selectedSku).reduce((selectedValues, skuKeyStr) => {
console.log(selectedSku,'sku啊');
const skuValues = normalizedTree[skuKeyStr];
const skuValueId = selectedSku[skuKeyStr];
if (skuValueId !== '') {
@ -247,29 +254,75 @@ Page({
}
},
/** 加入购物车 */
addCart() {
const {
isAllSelectedSku
isAllSelectedSku,
} = this.data;
const {
specList
specList,
} = this.data.details;
if (specList.length != 0) {
if (isAllSelectedSku) {
this.addCartFun()
} else {
Toast({
context: this,
selector: '#t-toast',
message: isAllSelectedSku ? '点击加入购物车' : '请选择规格',
message: '请选择规格',
icon: '',
duration: 1000,
});
}
}
else{
this.addCartFun()
}
},
addCartFun(){
const {
isAllSelectedSku,
buyNum,
selectedSkuId
} = this.data;
const {
specList,
shopGuid,
spuId,
} = this.data.details;
let data = {
shopGuid: shopGuid,
goodsGuid: spuId,
goodsSkuId: selectedSkuId,
cartGoodsNum: buyNum
}
console.log(data, '加入购物车的数据');
// 添加购物车接口
addOrUpdateCart(data).then((res) => {
if (res.code == 200) {
Toast({
context: this,
selector: '#t-toast',
message: '加入购物车成功',
icon: '',
duration: 1000,
});
this.setData({
isSpuSelectPopupShow: false,
});
}
})
},
gotoBuy(type) {
console.log(type);
const {
isAllSelectedSku,
buyNum
buyNum,
} = this.data;
const {
specList
@ -315,7 +368,7 @@ Page({
});
},
gotoShop(){
gotoShop() {
const {
shopGuid
} = this.data.details;
@ -506,7 +559,7 @@ Page({
const {
spuId
} = query;
// const spuId = "1680467515018448896";
// const spuId = "1672964367177617408";
this.setData({
spuId: spuId,

View File

@ -0,0 +1,21 @@
import {
request
} from '../_utils/request';
/** 添加购物车 */
export function addOrUpdateCart(data) {
return new Promise((resolve, reject) => {
request({
url: `CartApi/addOrUpdateCart`,
method: 'POST',
data: data,
success: function (res) {
resolve(res);
},
fail: function (error) {
reject(error);
}
});
});
}

View File

@ -0,0 +1,21 @@
import {
request
} from '../_utils/request';
/** 删除购物车记录 */
export function deleteCart(ids) {
return new Promise((resolve, reject) => {
request({
url: `CartApi/` + ids,
method: 'DELETE',
success: function (res) {
resolve(res);
},
fail: function (error) {
reject(error);
}
});
});
}

View File

@ -0,0 +1,21 @@
import {
request
} from '../_utils/request';
/** 全选购物车商品 */
export function selectAllCartGoods(data) {
return new Promise((resolve, reject) => {
request({
url: `CartApi/selectAllCartGoods`,
method: 'POST',
data: data,
success: function (res) {
resolve(res);
},
fail: function (error) {
reject(error);
}
});
});
}

View File

@ -0,0 +1,21 @@
import {
request
} from '../_utils/request';
/** 修改购物车商品数量 */
export function updateCartGoodsNum(data) {
return new Promise((resolve, reject) => {
request({
url: `CartApi/updateCartGoodsNum`,
method: 'POST',
data: data,
success: function (res) {
resolve(res);
},
fail: function (error) {
reject(error);
}
});
});
}

View File

@ -0,0 +1,21 @@
import {
request
} from '../_utils/request';
/** 修改购物车商品数量 */
export function updateCartGoodsSelect(data) {
return new Promise((resolve, reject) => {
request({
url: `CartApi/updateCartGoodsSelect`,
method: 'POST',
data: data,
success: function (res) {
resolve(res);
},
fail: function (error) {
reject(error);
}
});
});
}

View File

@ -47,6 +47,11 @@
--td-tab-track-color: #1989fa;
}
.t-button {
--td-button-default-color: #000;
--td-button-primary-text-color: #1989fa;
}
.dialog__button-confirm {
color: #1989fa !important;
}