Files
frontend-app/pages/shopping_cart/shopping_cart.vue
T

636 lines
19 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<view :class="[
isDataNull ? 'isDataNull-calss' : 'isDataNull-active',
platformType ? '' : 'iosplatformType',
]" class="shopping_cart_warp">
<view class="shopping_cart_header">
<view class="cart">购物车({{ shoppingTotal }})</view>
<view class="enit_but" @click="isEdit = true" v-if="!isEdit" v-show="!isDataNull">编辑</view>
<view class="enit_but" @click="isEdit = false" v-else>完成</view>
</view>
<!-- 购物车列表 -->
<up-loading-page :loading="listLoading"></up-loading-page>
<view class="shopping_cart_content">
<view v-if="!isDataNull" class="shopping_cart_content_item" v-for="(item, index) in shoppingList"
:key="item.id">
<!-- 店铺头部 -->
<up-checkbox :customStyle="{ marginBottom: '8px' }" name="isCheck" usedAlone v-model:checked="item.isCheck"
shape="circle" activeColor="#7934F6" size="19" iconSize="18"
@change="(event) => shoppingChange(event, index)">
<template #label>
<view class="content_item_header">
<up-image :src="item.shopLogo ? item.shopLogo : '/static/shopping/store.png'
" width="22" height="22" bgColor="#f1f6ff00" shape="circle"></up-image>
<view class="order_product_title">{{ item.shopName }}{{ item.id }}</view>
</view>
</template>
</up-checkbox>
<view>
<view class="content_item_info" v-for="(pItem, pIndex) in item.product" :key="pItem.id">
<!-- 单个商品 -->
<up-checkbox :customStyle="{ marginBottom: '8px' }" name="isCheck" usedAlone
v-model:checked="pItem.isCheck" shape="circle" activeColor="#7934F6" size="19" iconSize="18"
:disabled="!isEdit && [1, 2].includes(pItem.goodsStatus)"
@change="(event) => productChange(event, index, pIndex)">
</up-checkbox>
<view class="info_item">
<up-image :lazy-load="true" :src="pItem.mainGraph" width="100" height="100" bgColor="#f1f6ff00"
@click="jumpInfo(pItem)"></up-image>
<view class="content_info">
<view class="shopping_content_info_title" @click="jumpInfo(pItem)">{{ pItem.name }}</view>
<view class="content_info_description">{{ pItem.goodsSpece }}</view>
<view class="shopping_info_amount">
<view>
<view style="color: #7934f6">
<text style="font-size: 22rpx" v-if="pItem.couponPrice">券后</text>
<text style="font-size: 22rpx">¥</text>
<text style="font-size: 32rpx">{{
pItem.couponPrice || pItem.unitPrice
}}</text>
</view>
<view class="shopping_info_amount_original" v-if="pItem.originalPrice">
¥{{
pItem.originalPrice
}}
</view>
</view>
<view>
<view class="shopping_info_quantity">
<view class="quantity_but" @click="quantityFun('minus', index, pIndex, pItem.id)">-</view>
<view class="quantity_value">{{ pItem.buyNum }}</view>
<view class="quantity_but" @click="quantityFun('add', index, pIndex, pItem.id)">+</view>
</view>
<view v-if="[1].includes(pItem.goodsStatus)" class="insufficient_stock">库存不足</view>
<view v-if="[2].includes(pItem.goodsStatus)" class="insufficient_stock">商品已下架</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view v-else class="not_order_warp">
<up-image src="https://static.tbmall.xin/static/not_shopping.png" width="80" height="80"
bgColor="#f1f6ff00"></up-image>
<view class="not_order_msg_warp">购物车是空的</view>
</view>
<choiceness />
</view>
<!-- 操作按钮 -->
<view v-if="!isDataNull">
<view class="shopping_cart_but">
<!-- 全选 -->
<view class="shopping_cart_but_total">
<up-checkbox name="isAll" usedAlone v-model:checked="isAll" shape="circle" activeColor="#7934F6" size="19"
iconSize="18" @change="isAllChange">
<template #label>
<text style="font-size: 26rpx; color: #444444">全选</text>
</template>
</up-checkbox>
<text style="margin-left: 20rpx; font-size: 24rpx; color: #444444" v-if="!isEdit">合计:</text>
<text style="font-size: 24rpx" v-if="!isEdit">¥</text>
<text style="font-size: 32rpx" v-if="!isEdit">{{ total }}</text>
</view>
<view v-if="isEdit" class="delete_but_css" @click="deleteShopping">
删除({{ count }})
</view>
<view v-else class="add_but_css" @click="settleShopping">
结算({{ count }})
</view>
</view>
</view>
<up-toast ref="uToastRef"></up-toast>
</view>
<!-- #ifndef H5 || MP-WEIXIN-->
<CustomTabBar :tabIndex="3" />
<!-- #endif -->
<qiaobao-assistant page-key="pages/shopping_cart/shopping_cart" title="购物车" />
</view>
</template>
<script>
import choiceness from "@/components/choiceness/choiceness.vue";
import { getCartList, updateGoodsNum, removeGoods } from "@/api/cart.js";
import CustomTabBar from "@/components/custom-tab-bar.vue";
export default {
components: { choiceness, CustomTabBar },
data() {
return {
shoppingTotal: 0, // 总条数
setShoppingList: [],
isDataNull: false, // 数据是否为空
shoppingList: [], // 购物车列表
isEdit: false, // 是否编辑
isAll: false, // 是否全选
total: 0, // 总合计的金额
count: 0, // 总条数
listLoading: false,
platformType: true,
};
},
onShow() {
/*#ifdef APP-PLUS*/
uni.hideTabBar({
animation: false,
});
const appUpdate = uni.getStorageSync("platform");
this.platformType = appUpdate == "android" ? "ANDROID" : "IOS";
/*#endif*/
this.getCartList();
},
onLoad() { },
methods: {
/**
* 查询购物车列表
*/
async getCartList() {
this.listLoading = true;
let result = [];
const resp = await getCartList();
if (resp && resp.bizcode === 100) {
const data = resp.data || [];
if (data && data.length !== 0) {
// 处理了后的数据
result = this.transformedArray(data);
}
this.shoppingTotal = data.length;
}
this.shoppingList = result;
this.listLoading = false;
this.total = 0; // 总合计的金额
this.count = 0; // 总条数
this.isDataNull = result.length === 0 ? true : false;
},
// 处理购物车的数据
transformedArray(originalArray) {
const newOriginalArray = [];
if (!originalArray || originalArray.length === 0) {
return newOriginalArray;
}
originalArray.map((curr) => {
const existingShop = newOriginalArray.find(
(shop) =>
shop.shopId === curr.shopId && shop.shopName === curr.shopName
);
if (existingShop) {
// 如果商店已存在,则向 productObj 数组中添加新产品对象
existingShop.product.push({
id: curr.id,
goodsId: curr.goodsId, // 商品ID
name: curr.name, // 商品名称
mainGraph: curr.mainGraph, // 主图
buyNum: curr.buyNum, // 数量
unitPrice: curr.unitPrice, // 商品单价
goodsSpece: curr.goodsSpece, // 规格
specsId: curr.specsId, // 规格Id
isCheck: false, // 用作于全选
originalPrice: curr.originalPrice,
couponPrice: curr.couponPrice,
goodsStatus: curr.goodsStatus, //商品状态:0-可下单,1-库存不够,2-商品已下架
});
} else {
// 如果商店不存在,则创建一个新商店对象,并初始化 productObj 数组
newOriginalArray.push({
isCheck: false, // 用作于全选
shopId: curr.shopId,
shopName: curr.shopName,
name: curr.name,
shopLogo: curr.shopLogo,
product: [
{
id: curr.id,
goodsId: curr.goodsId, // 商品ID
name: curr.name, // 商品名称
mainGraph: curr.mainGraph, // 主图
buyNum: curr.buyNum, // 数量
unitPrice: curr.unitPrice, // 商品单价
goodsSpece: curr.goodsSpece, // 规格
specsId: curr.specsId, // 规格Id
isCheck: false, // 用作于全选
originalPrice: curr.originalPrice,
couponPrice: curr.couponPrice,
goodsStatus: curr.goodsStatus, //商品状态:0-可下单,1-库存不够,2-商品已下架
},
],
});
}
});
return newOriginalArray;
},
/**
* 数量进行增加删除
* @param {Object} type 区分是 + 还是 -
* @param {Object} pItem 父节点数据,用作与从新修改数据
* @param {Object} cItem 需要修改的数据节点
*/
async quantityFun(type, index, pIndex, id) {
// 选中的当前商品
const currentData = this.shoppingList[index].product[pIndex];
let currentQuantity = this.shoppingList[index].product[pIndex].buyNum; // 当前数量
let total = Number(this.total);
let count = Number(this.count);
const data = this.shoppingList[index].product[pIndex];
if (type === "minus") {
if (currentQuantity === 1) {
this.$refs.uToastRef.show({
type: "warring",
message: "宝贝数量不能在减少啦~",
});
return;
} else {
currentQuantity = currentQuantity - 1;
total = total - data.unitPrice;
count = count - 1;
}
} else if (type === "add") {
// 需要判断一下库存
currentQuantity = currentQuantity + 1;
total = total + data.unitPrice;
count = count + 1;
}
const params = {
id,
goodsNum: currentQuantity,
};
const result = await updateGoodsNum(params);
if (result && result.bizcode === 100) {
this.shoppingList[index].product[pIndex].buyNum = currentQuantity;
if (currentData.isCheck) {
this.total = total.toFixed(2);
this.count = count;
}
}
},
/**
* 结算订单
*/
settleShopping() {
const deleteId = this.getCheckList();
if (!deleteId || deleteId.length === 0) {
this.$refs.uToastRef.show({
type: "warring",
message: "请先选择需要结算的商品",
});
return;
}
uni.navigateTo({
url:
"/pages/order_package/order_submit/order_submit?ids=" +
deleteId.join(","),
});
this.isAll = false;
},
/**
* 删除选中的
*/
deleteShopping() {
const then = this;
uni.showModal({
title: "提示",
content:
"您确定要删除选中的(" + this.getCheckList().length + "件)商品吗?",
success: function (res) {
if (res.confirm) {
then.deleteShoppingFun();
}
},
});
},
// 删除选中的
async deleteShoppingFun() {
const deleteId = this.getCheckList();
if (!deleteId || deleteId.length === 0) {
this.$refs.uToastRef.show({
type: "warring",
message: "请先选择需要删除的商品",
});
return;
}
const params = {
ids: deleteId.join(","),
};
const result = await removeGoods(params);
if (result && result.bizcode === 100) {
this.isEdit = false;
this.$refs.uToastRef.show({
type: "success",
message: "删除成功",
});
this.getCartList();
} else {
this.$refs.uToastRef.show({
type: "error",
message: "删除失败",
});
}
},
// 获取选中的数据
getCheckList() {
const shoppingList = this.shoppingList;
const deleteId = [];
shoppingList.map((item) => {
if (item.product && item.product.length !== 0) {
item.product.map((pItem) => {
if (pItem.isCheck) {
deleteId.push(pItem.id);
}
});
}
});
return deleteId;
},
// 全部选中 or 全部取消选中
isAllChange(isAll) {
const currentShoppingList = this.shoppingList;
currentShoppingList.map((item, index) => {
if (isAll) {
item.isCheck = true;
} else {
item.isCheck = false;
}
if (item.product && item.product.length !== 0) {
if (isAll) {
item.product.forEach((o) => (o.isCheck = true));
} else {
item.product.forEach((o) => (o.isCheck = false));
}
}
});
this.shoppingList = currentShoppingList;
if (isAll) {
this.checkIsAll();
} else {
this.total = 0;
this.count = 0;
}
},
/**
* 商品详情
* @param {Object} item
*/
jumpInfo(item) {
uni.navigateTo({
url: "/pages/other_package/productInfo/productInfo?id=" + item.goodsId,
});
},
// 单个产品的单选按钮选中与取消选中
productChange(val, index, pIndex) {
setTimeout(() => {
// 检查全选按钮
this.checkIsAll();
}, 300);
},
// 单个店铺的单选按钮选中与取消选中
shoppingChange(isAll, index) {
const data = this.shoppingList[index];
if (isAll) {
data.product.forEach((o) => (o.isCheck = true));
} else {
data.product.forEach((o) => (o.isCheck = false));
}
this.shoppingList[index] = data;
setTimeout(() => {
// 检查全选按钮
this.checkIsAll();
}, 300);
},
/**
* 检查是否全选
*/
checkIsAll() {
let total = 0;
let count = 0;
const shoppingList = this.shoppingList;
if (shoppingList && shoppingList.length !== 0) {
let sumFlag = false;
shoppingList.map((item) => {
let flag = true;
item.product.map((oItem) => {
if (oItem.isCheck) {
total = total + oItem.buyNum * oItem.unitPrice;
count = count + oItem.buyNum;
} else {
flag = false;
}
});
if (flag) {
item.isCheck = true;
sumFlag = true;
} else {
item.isCheck = false;
}
});
this.shoppingList = shoppingList;
this.isAll = sumFlag;
// 删除不需要显示价格
if (!this.isEdit) {
this.total = total.toFixed(2);
}
this.count = count;
}
},
},
};
</script>
<style lang="scss" scoped>
.shopping_cart_warp {
background-color: $app-bj;
padding: 104rpx 30rpx 0;
/* #ifdef MP-WEIXIN */
padding-top: calc(var(--status-bar-height) + 140rpx) !important;
/* #endif */
overflow: hidden;
height: 100%;
display: flex;
flex-direction: column;
// &.isDataNull-calss {
// height: calc(100vh - 100rpx - env(safe-area-inset-bottom));
// }
// &.isDataNull-active {
// height: calc(100vh - 100rpx - env(safe-area-inset-bottom) - 100rpx);
// }
// &.iosplatformType {
// height: calc(100vh - 100rpx - 50rpx) !important;
// .shopping_cart_content {
// height: calc(100vh - 104rpx - 30rpx - 30rpx - 100rpx - 10rpx) !important;
// }
// .shopping_cart_but {
// bottom: 90rpx !important;
// }
// }
}
.shopping_cart_header {
display: flex;
justify-content: space-between;
color: #222222;
.cart {
font-weight: bold;
font-size: 38rpx;
}
.enit_but {
font-weight: 500;
font-size: 28rpx;
}
}
.shopping_cart_content {
margin-top: 30rpx;
flex: 1;
overflow-y: auto;
padding-bottom: calc(240rpx + env(safe-area-inset-bottom));
.shopping_cart_content_item {
background-color: #ffffff;
border-radius: 30rpx;
padding: 30rpx;
margin-bottom: 20rpx;
.content_item_header {
display: flex;
}
.order_product_title {
margin-left: 10rpx;
}
.info_item {
display: flex;
margin-top: 10rpx;
width: calc(100% - 40rpx);
}
.content_info {
margin-left: 10rpx;
width: calc(100% - 100rpx);
}
.shopping_content_info_title {
font-weight: bold;
font-size: 28rpx;
color: #272727;
}
.content_info_description {
font-size: 24rpx;
color: #999999;
margin-top: 6rpx;
overflow: hidden;
text-overflow: ellipsis;
/* #ifndef APP-NVUE */
display: -webkit-box;
/* autoprefixer: off */
-webkit-box-orient: vertical;
/* autoprefixer: on */
-webkit-line-clamp: 2;
line-clamp: 2;
box-orient: vertical;
/* #endif */
/* #ifdef APP-NVUE */
lines: 2;
/* #endif */
word-break: break-all;
}
.shopping_info_amount {
display: flex;
justify-content: space-between;
margin-top: 20rpx;
}
.shopping_info_amount_original {
font-size: 24rpx;
color: #999999;
text-decoration-line: line-through;
}
.insufficient_stock {
text-align: center;
color: #9e9e9e;
font-size: 22rpx;
margin-top: 4rpx;
}
}
.content_item_info {
display: flex;
}
}
.shopping_cart_but {
position: fixed;
left: 0;
right: 0;
width: 100%;
box-sizing: border-box;
background: #ffffff;
box-shadow: 0rpx -1rpx 0rpx 0rpx #eeeeee;
height: 119rpx;
display: flex;
justify-content: space-between;
padding: 20rpx 30rpx 15rpx;
align-items: center;
z-index: 99;
/* #ifdef H5 */
bottom: var(--window-bottom);
/* #endif */
/* #ifdef MP-WEIXIN */
bottom: 0;
/* #endif */
/* #ifdef APP-PLUS */
bottom: calc(100rpx + env(safe-area-inset-bottom));
/* #endif */
/* #ifndef H5 || MP-WEIXIN || APP-PLUS */
bottom: 0;
/* #endif */
.shopping_cart_but_total {
font-weight: bold;
color: $app-bt-bj;
display: flex;
align-items: center;
}
.add_but_css {
height: 38rpx;
width: 226rpx;
}
.delete_but_css {
width: 226rpx;
}
}
.iosplatformType {
.shopping_cart_but {
/* #ifdef APP-PLUS */
bottom: 100rpx;
/* #endif */
}
}
</style>