Browse Source

refactor(购物车): 重构购物车相关逻辑和动画处理

将购物车小球动画逻辑移至函数开头统一处理
使用store的getCartMap和getCartTotalQuantity方法替代手动计算
修复preview接口参数名错误
添加initCartInfo调用确保数据一致性
优化购物车数量增减逻辑和验证
master
wei 3 days ago
parent
commit
453ad43de3
  1. 20
      pages/allDish/allDish.vue
  2. 232
      pages/home/home.vue
  3. 11
      pages/recipeOrder/recipeOrder.vue

20
pages/allDish/allDish.vue

@ -354,7 +354,7 @@ async function loadProductList(parentId, tips) {
// const cartList = store.cartList;
// console.log(store.cartList, 3333);
const total = store.cartList.reduce((acc, cur) => acc + cur.quantity, 0);
const total = store.getCartTotalQuantity();
store.increment(total);
@ -380,12 +380,9 @@ async function loadProductList(parentId, tips) {
return;
}
res.data.forEach((item) => {
// specId_price -> quantity
const cartMap = store.cartList.reduce((acc, cur) => {
return { ...acc, [`${cur.specId}_${cur.price}`]: cur.quantity };
}, {});
const cartMap = store.getCartMap();
res.data.forEach((item) => {
item.specs.forEach((specsItem) => {
//
const specKey = `${specsItem.id}_${specsItem.price}`;
@ -567,6 +564,10 @@ function onGotoDetail(item) {
* 创建购物车小球的动画
*/
async function createAnimation(eX, eY) {
actionTime.value = false;
testX.value = eX;
testY.value = eY;
const bottomX = (store.tabbarItemWidth || 83) * 2 - 30;
const bottomY = uni.getWindowInfo().windowHeight;
@ -622,8 +623,6 @@ async function initCartInfo() {
// cartCount.value = res.total;
// cartList.value = res.data || [];
console.log(res.data, 3333);
store.changeCartList(res.data);
totalPrice.value = res.data.reduce((acc, item) => acc + item.amount, 0).toFixed(2);
if (store.cartList.length > 0) {
@ -662,9 +661,6 @@ async function onAdd(item, e) {
return;
}
actionTime.value = false;
testX.value = e.detail.x;
testY.value = e.detail.y;
createAnimation(e.detail.x, e.detail.y);
const isPass = validates([
@ -713,6 +709,8 @@ async function toCart(item, diff) {
}
if (!data.warehouseId || !data.addrId) {
console.log(data.warehouseId, data.addrId);
uni.showModal({
title: "提示",
content: "请先选择收货地址,再添加商品",

232
pages/home/home.vue

@ -4,23 +4,39 @@ import { onLoad, onShow } from "@dcloudio/uni-app";
import { nextTick, ref } from "vue";
import customTabBar from "@/components/custom-tab-bar/my-tab-bar.vue";
import {
addCartApi,
// editDefaultAddressApi,
// getBroadcastApi,
getCarouselsApi,
getCartInfoApi,
getMyAreaApi,
getNoticesApi,
getProductsApi,
getProductTypesApi,
getProductTypesHomeApi,
getSystemSettingApi,
// myOrdersApi,
myOrdersApi,
} from "@/libs/api";
import { sleep } from "@/libs/utils";
import { sleep, validates } from "@/libs/utils";
import useStore from "@/store";
// import permissionPopup from "@/components/permissionPopup/permissionPopup.vue";
// import checkUpdate from "@/uni_modules/uni-upgrade-center-app/utils/check-update";
const store = useStore();
//
const showBall = ref(false);
//
const actionTime = ref(true);
//
const animationY = ref({});
// X
const animationX = ref({});
// Y
const testY = ref(0);
// X
const testX = ref(0);
/**
* 顶部安全距离
*/
@ -87,6 +103,10 @@ const products = ref([]);
* 新品商品
*/
const newGoods = ref([]);
/**
* 输入框
*/
const inputValue = ref("");
/**
* 招聘求职有关信息查询
*/
@ -175,6 +195,17 @@ async function getProductTypes() {
});
});
// specId_price -> quantity
const cartMap = store.getCartMap();
res2.data.forEach((item) => {
item.specs.forEach((specsItem) => {
//
const specKey = `${specsItem.id}_${specsItem.price}`;
// 0
specsItem.sum = cartMap[specKey] || 0;
});
});
if (each.name === "新品") {
newGoods.value = res2.data;
}
@ -198,15 +229,14 @@ function getDFKDataLength() {
* 随后获取特价新品
*/
async function getMyArea() {
const postData = {
warehouseid: "",
isEnabled: 1,
};
uni.showLoading({
title: "加载中",
mask: true,
});
const res = await getMyAreaApi(postData);
const res = await getMyAreaApi({
warehouseid: "",
isEnabled: 1,
});
if (res.code !== "0") {
uni.hideLoading();
return;
@ -214,9 +244,10 @@ async function getMyArea() {
const list = res.data.list.sort((pre, cur) => Number(cur) - Number(pre));
// each isLastDefaultAddr
const each = list.find(each => each.isLastDefaultAddr) || list[0];
uni.setStorageSync("warehousId", each.warehousId);
uni.setStorageSync("addressId", each.addrId);
selectAddress.value = each;
selectAddress.value = list[0];
// getBroadcast();
getDFKDataLength();
@ -260,9 +291,8 @@ async function getMyArea() {
* 查看公告列表
*/
async function onNotice() {
uni.showToast({
title: "待完善",
icon: "none",
uni.navigateTo({
url: "/pages/home/announcement",
});
}
/**
@ -321,10 +351,14 @@ function onHonest() {
* 打开走进菜大王
*/
function onEnterPage() {
uni.showToast({
title: "待完善",
icon: "none",
uni.navigateTo({
url: "/pages/home/enterKing/enterKing",
});
// enterVegetableKing
// uni.showToast({
// title: "",
// icon: "none",
// });
}
/**
* 打开招聘求职
@ -340,47 +374,107 @@ function onJoin() {
* -1 到购物车
* @param {{specs: {sum: number}[]}} item
*/
function onMinusGoods(item, index = 0) {
const cur = item.specs[index];
if (cur.stock === 0) {
uni.showToast({
icon: "none",
title: "库存数量为0无法添加",
});
function onMinusGoods(item) {
const isPass = validates([
() => item.stock == item.sum && "采购数量不能大于库存数量",
() => item.sum === 0 && "库存数量为0",
() => item.stock === 0 && "库存数量为0无法添加",
]);
if (!isPass) {
return;
}
if (cur.sum === 0) {
uni.showToast({
icon: "none",
title: "库存数量为0",
});
return;
}
item.specs[index].sum -= 1;
// 0,
item.sum = Number(item.sum) || 0;
const minNum = item.minNum || 1;
// (item.minNum), -1
const diff = -(item.sum === minNum ? minNum : 1);
item.sum += diff;
//
inputValue.value = item.sum;
toCart(item, diff);
}
/**
* +1 到购物车
* @param {{specs: {sum: number}[]}} item
*/
function onAddGoods(item, index = 0) {
const cur = item.specs[index];
function onAddGoods(item, e) {
// const cur = item.specs[index];
if (item.specs[index].sum > cur.stock) {
uni.showToast({
icon: "none",
title: "采购数量不能大于库存数量",
});
if (!actionTime.value) {
return;
}
if (cur.stock === 0) {
uni.showToast({
icon: "none",
title: "库存数量为0无法添加",
});
createAnimation(e.detail.x, e.detail.y);
const isPass = validates([
() => item.stock == item.sum && "采购数量不能大于库存数量",
() => item.stock == 0 && "库存数量为0无法添加",
]);
if (!isPass) {
return;
}
item.specs[index].sum += 1;
// 0,
item.sum = Number(item.sum) || 0;
// (item.minNum), +1
const diff = item.sum === 0 ? (item.minNum || 1) : 1;
item.sum += diff;
//
inputValue.value = item.sum;
toCart(item, diff);
}
/**
* 更新购物车
* @param item 商品项
* @param diff 变化量
*/
async function toCart(item, diff) {
const data = {
quantity: diff,
specId: item.id,
Chuxiao: item.chuxiao,
isChuxiao: false,
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
// isChuxiao: item.chuxiao,
};
if (!data.specId) {
uni.showModal({
title: "提示",
content: "当前商品规格错误,请稍候再试",
showCancel: false,
confirmText: "确定",
});
}
const res = addCartApi(data);
if (res.code !== "0") {
initCartInfo();
}
}
/**
* 初始化购物车信息
*/
async function initCartInfo() {
const data = {
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
};
const res = await getCartInfoApi(data);
if (res.code !== "0")
return;
store.changeCartList(res.data);
}
/**
@ -403,6 +497,55 @@ function onChangeGoods(e, item, index) {
item.specs[index].sum = value;
}
/**
* 创建购物车小球的动画
*/
async function createAnimation(eX, eY) {
actionTime.value = false;
testX.value = eX;
testY.value = eY;
const bottomX = (store.tabbarItemWidth || 83) * 2 - 30;
const bottomY = uni.getWindowInfo().windowHeight;
const stepX = flyX(bottomX, eX);
const stepY = flyY(bottomY, eY);
showBall.value = true;
animationX.value = stepX.export(); //
animationY.value = stepY.export(); //
await sleep(400);
actionTime.value = true;
showBall.value = false;
animationX.value = flyX(0, 0).export();
animationY.value = flyY(0, 0).export();
// await sleep(800);
}
/**
* 购物车小球水平移动动画
*/
function flyX(bottomX, ballX, duration = 400) {
const animation = uni.createAnimation({
duration,
timingFunction: "linear",
});
animation.translateX(-bottomX).step();
return animation;
}
/**
* 购物车小球垂直移动动画
*/
function flyY(bottomY, ballY, duration = 400) {
const animation = uni.createAnimation({
duration,
timingFunction: "ease-in",
});
animation.translateY(bottomY - ballY).step();
return animation;
}
onLoad(() => {
// #ifdef APP
uni.hideTabBar();
@ -433,6 +576,7 @@ onLoad(() => {
onShow(async () => {
await sleep(1000);
await initCartInfo();
getMyArea();
});
</script>
@ -658,7 +802,7 @@ onShow(async () => {
<block v-if="item.specs[0].sum !== 0">
<view class="line-one" />
<view class="line-two" />
<view class="minus" @tap="() => onMinusGoods(item)">
<view class="minus" @tap="() => onMinusGoods(item.specs[0], index)">
<image class="icon" src="/static/home/minus.png" mode="" />
</view>
<input
@ -668,7 +812,7 @@ onShow(async () => {
@input="e => onChangeGoods(e, item)"
>
</block>
<view class="add" @tap="() => onAddGoods(item)">
<view class="add" @tap="(e) => onAddGoods(item.specs[0], e)">
<image class="icon" src="/static/home/add.png" mode="" />
</view>
</view>

11
pages/recipeOrder/recipeOrder.vue

@ -259,9 +259,7 @@ async function onAdd(item, e) {
if (!actionTime.value) {
return;
}
actionTime.value = false;
testX.value = e.detail.x;
testY.value = e.detail.y;
createAnimation(e.detail.x, e.detail.y);
const res = await newMenusToCartApi({
@ -312,7 +310,7 @@ async function initCartInfo() {
async function preview(itemIds) {
const res = await previewApi({
addrId: uni.getStorageSync("addressId"),
mealIds: itemIds.join(","),
itemIds: itemIds.join(","),
});
if (res.code !== "0") {
return;
@ -326,6 +324,10 @@ async function preview(itemIds) {
* 创建购物车小球的动画
*/
async function createAnimation(eX, eY) {
actionTime.value = false;
testX.value = eX;
testY.value = eY;
const bottomX = (store.tabbarItemWidth || 83) * 2 - 30;
const bottomY = uni.getWindowInfo().windowHeight;
@ -389,6 +391,7 @@ onShow(() => {
pageContainerHeight.value = content - boxHeight - 80;
});
initCartInfo();
},
);
</script>

Loading…
Cancel
Save