purchase-let/pages/cart/cart.vue

507 lines
12 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 class="wrap">
<up-navbar placeholder :autoBack="true">
<template #center>
<view
style="display: flex;align-items: center;width: 100%;justify-content: flex-start;margin-left: 100rpx;">
<view class="tabs" :class="{'tabs-active': tabsActive==index}" v-for="(item, index) in list"
:key="index" @click="changeTab(index)">
{{item}}
</view>
</view>
</template>
</up-navbar>
<swiper class="swiper-box" :current="swiperCurrent" @animationfinish="animationfinish">
<swiper-item class="swiper-item">
<scroll-view scroll-y @refresherrefresh="refresherrefresh(1)" :refresher-triggered="triggered"
refresher-enabled refresher-background="#F6F6F6" style="height: 100%;width: 100%;">
<view class="page-box1">
<view class="total" @click='isAdmin=!isAdmin'>
<view>共计<text style="color: #20B128;">{{cartList.length}}</text>件</view>
<view v-if="!isAdmin">删除商品</view>
<view v-else>完成</view>
</view>
<view v-if="cartList.length>0" class="list">
<view class="shop-item" v-for="(item, index) in cartList" :key="index"
@click="openGoodPopup(item)">
<view class="shop-check" @click.stop="checkItem(item, !item.check)">
<image v-if="!item.check" src="@/static/icon/n-check.png"></image>
<image v-else src="@/static/icon/check.png"></image>
</view>
<image class="shop-img" :src="item.imgs"></image>
<view class="shop-content">
<view class="title">
<view class="name u-line-2">{{item.goods_name}}</view>
<view class="tip u-line-1">{{item.sku_name}}</view>
<view v-if="priceKey.off_activity==1" class="tip u-line-1">原价:<text
style="text-decoration: line-through;">¥{{item[priceKey.op_price]}}</text>
</view>
</view>
<view class="price-btn">
<view class="price">¥{{item[priceKey.price]}}</view>
<view class="btn">
<view class="num">{{item.cart_num}}/{{item.unit_name}}</view>
<u--icon name="plus-circle-fill" size="20" color="#20b128"></u--icon>
</view>
</view>
</view>
</view>
</view>
<view v-else style="margin-top: 100rpx;">
<up-empty text="购物车空空如也"
icon="https://lihai001.oss-cn-chengdu.aliyuncs.com/def/29955202404260944367594.png">
</up-empty>
</view>
<view style="width: 100%;height: 200rpx;"></view>
</view>
</scroll-view>
</swiper-item>
<swiper-item class="swiper-item">
<scroll-view scroll-y @refresherrefresh="refresherrefresh(2)" :refresher-triggered="triggered"
refresher-enabled refresher-background="#F6F6F6" style="height: 100%;width: 100%;">
<view class="page-box1">
<view v-if="frequentlyList.length>0" class="list">
<view class="shop-item" v-for="(item, index) in frequentlyList" :key="index"
@click="openGoodPopup(item)">
<image class="shop-img" :src="item.image"></image>
<view class="shop-content" style="width: 490rpx;">
<view class="title">
<view class="name u-line-2">{{item.name}}</view>
<!-- <view class="tip u-line-1">{{item.spec}}</view> -->
<view class="tip u-line-1">{{item.unit_name}}</view>
</view>
<view class="price-btn">
<view class="price">¥{{item.price}}</view>
<view class="btn">
<up-button size="small" plain color="#20b128"
shape="circle">加入购物车</up-button>
</view>
</view>
</view>
</view>
</view>
<view v-else style="margin-top: 100rpx;">
<up-empty text="没有常买的商品"
icon="https://lihai001.oss-cn-chengdu.aliyuncs.com/def/29955202404260944367594.png">
</up-empty>
</view>
<view style="width: 100%;height: 200rpx;"></view>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
<up-transition :show="tabsActive==0">
<view class="fiexd-btn-box cart-btn">
<view class="cart-check" @click="changeAll(checkAll===cartInfo.count)">
<image v-if="checkAll!=cartInfo.count" src="@/static/icon/n-check.png"></image>
<image v-else src="@/static/icon/check.png"></image>
<text style="font-size: 24rpx;">全选</text>
<text style="font-size: 24rpx;" v-if="checkAll">({{checkAll}})</text>
</view>
<view v-if="!isAdmin" class="btn-boxs">
<view class="all-price">
<view style="width: 80rpx;">合计:</view>
<view class="price">
<text style="font-size: 24rpx;">¥</text>
<text style="font-size: 34rpx;">{{c_price0}}</text>
<text style="font-size: 24rpx;">.{{c_price1}}</text>
</view>
</view>
<view style="width: 200rpx;">
<up-button color="#20b128" shape="circle" @click="settleAccounts">
<view class="">
去结算<text v-if="checkAll">({{checkAll}})</text>
</view>
</up-button>
</view>
</view>
<view v-else class="btn-boxs">
<!-- <view style="width: 100px;margin-right: 20rpx;"><up-button size="small" plain color="#989898" shape="circle">移入收藏夹</up-button></view> -->
<view style="width: 100px;"><up-button @click="deleteCartList()" size="small" plain color="#989898"
shape="circle">删除</up-button></view>
</view>
</view>
</up-transition>
<goodPopup ref="goodRef" :show="showGoodPopup" @close="showGoodPopup=false" @change="changeGood" />
</template>
<script setup>
import {
onShow,
onLoad
} from "@dcloudio/uni-app"
import {
computed,
ref,
watch
} from 'vue';
import {
cartListApi,
cartChangeApi,
cartCreateApi,
cartDeleteApi,
frequentlyPurchaseApi
} from "@/api/cart.js"
import goodPopup from "@/components/goodPopup.vue"
import useCartStore from "@/store/cart.js"
// 用户选择的门店信息
let STORE_INFO = uni.getStorageSync('STORE_INFO');
if (STORE_INFO)
STORE_INFO = JSON.parse(STORE_INFO)
const cartStore = useCartStore();
// 创建响应式数据
const list = ref(['购物车', '常买']);
const tabsActive = ref(0)
// 定义方法
const changeTab = (e) => {
tabsActive.value = e;
swiperCurrent.value = e;
}
const swiperCurrent = ref(0);
const animationfinish = ({
detail: {
current
}
}) => {
swiperCurrent.value = current;
tabsActive.value = current;
if (swiperCurrent.value == 1) getFrequentlyPurchase();
}
// 结算
const settleAccounts = () => {
let list = [];
cartList.value.forEach(item => {
if (item.check) list.push(item.id);
})
cartStore.setCartList(list);
uni.navigateTo({
url: '/pagesOrder/settle/settle'
})
}
// 删除
const deleteCartList = () => {
let list = [];
if (!cartList.value.length) return uni.showToast({
title: '请选择商品',
icon: 'none'
});
cartList.value.forEach(item => {
if (item.check) list.push(item.id);
})
cartDeleteApi({
id: list
}).then(() => {
getcartList(false);
})
}
// 购物车相关
const addCart = (id, cart_num) => { //加入购物车
if (uni.getStorageSync('STORE_INFO').length) {
let data = JSON.parse(uni.getStorageSync('STORE_INFO'))
let STORE_INFO = {};
for (let key in data) {
STORE_INFO[key] = data[key]
}
cartCreateApi({
cart_num: +cart_num,
product_id: id,
store_id: STORE_INFO.id
// store_id:
}).then(res => {
getcartList();
})
}
}
const isAdmin = ref(false); //是否管理
// 选择商品相关
const showGoodPopup = ref(false);
const goodRef = ref(null);
const goodData = ref({});
const openGoodPopup = (item) => { // 打开数量/重量弹窗
goodData.value = JSON.parse(JSON.stringify(item));
goodRef.value.setData(goodData.value);
showGoodPopup.value = true;
};
const changeGood = (data) => { // 确定选择商品重量
showGoodPopup.value = false;
addCart(data.product_id || data.id, data.cart_num);
}
const cartList = ref([]);
const cartInfo = ref({});
const getcartList = (check = true) => {
cartListApi({store_id:STORE_INFO.id}).then(res => {
if (check) {
res.data.lists = res.data.lists.map(item => {
item.check = true;
return item;
})
checkAll.value = res.data?.count || 0
} else {
checkAll.value = 0
}
res.data.lists = res.data.lists.map(item => {
if (!item.price) item.price = item.sell; // 兼容旧数据新数据已经添加了price字段
return item;
})
cartList.value = res.data.lists;
cartInfo.value = {
total_price: res.data?.extend.total_price || '0.00',
pay_price: res.data?.extend.pay_price || '0.00',
count: res.data?.count || 0
}
console.log(cartInfo.value)
setTimeout(() => {
triggered.value = false;
}, 300)
})
}
const c_price0 = computed(() => {
let price = cartInfo.value.pay_price + '';
return price.split('.')[0] || '0';
})
const c_price1 = computed(() => {
let price = cartInfo.value.pay_price + '';
return price.split('.')[1] || '00';
})
// 选中
let checkAll = ref(0)
const checkItem = (item, type) => {
item.check = type;
let price = Number(cartInfo.value.pay_price);
if (type) {
price += (priceKey.value.off_activity == 1 ? item[priceKey.value.price] : item[priceKey.value.op_price]) *
item
.cart_num;
checkAll.value++;
} else {
price -= (priceKey.value.off_activity == 1 ? item[priceKey.value.price] : item[priceKey.value.op_price]) *
item.cart_num;
checkAll.value--;
}
cartInfo.value.pay_price = price.toFixed(2);
}
const changeAll = (flag = false) => {
let count = 0;
cartList.value.forEach(item => {
item.check = !flag;
if (!flag) count += item.sell * item.cart_num;
})
if (!flag) {
checkAll.value = cartInfo.value.count;
} else {
checkAll.value = 0;
}
cartInfo.value.total_price = count.toFixed(2);
}
// 常买记录
const frequentlyList = ref([]);
const where = ref({
page_no: 1,
page_size: 25
})
const getFrequentlyPurchase = () => {
frequentlyPurchaseApi({
...where.value
}).then(res => {
frequentlyList.value = res.data;
setTimeout(() => {
triggered.value = false;
}, 300)
})
}
const triggered = ref(false);
const refresherrefresh = (type = 1) => {
triggered.value = true;
if (type == 1) getcartList();
if (type == 2) getFrequentlyPurchase();
}
onShow(() => {
getcartList();
})
let priceKey = ref({})
onLoad(() => {
if (uni.getStorageSync('PRICE_KEY')) {
priceKey.value = JSON.parse(uni.getStorageSync('PRICE_KEY'));
} else {
priceKey.value = {};
}
})
</script>
<style lang="scss">
.tabs {
color: #444444;
font-size: 32rpx;
margin-right: 30rpx;
}
.tabs-active {
color: #20B128;
// font-size: 34rpx;
transition: 300ms;
}
.wrap {
display: flex;
flex-direction: column;
height: calc(100vh - var(--window-top));
width: 100%;
background-color: #f6f6f6;
}
.swiper-box {
flex: 1;
}
.swiper-item {
height: 100%;
}
.page-box1 {
position: relative;
.total {
// margin-top: 10rpx;
padding: 0 40rpx;
display: flex;
justify-content: space-between;
// position: sticky;
// top: var(--window-top);
// left: 0;
// right: 0;
z-index: 100000 !important;
height: 60rpx;
line-height: 60rpx;
font-size: 26rpx;
color: #444;
}
.list {
margin: 20rpx;
border-radius: 20rpx;
overflow: hidden;
.shop-item {
padding: 20rpx;
border-bottom: 1rpx solid #f6f6f6;
background-color: #fff;
display: flex;
.shop-check {
width: 60rpx;
height: 120rpx;
display: flex;
align-items: center;
image {
width: 40rpx;
height: 40rpx;
}
}
.shop-img {
height: 164rpx;
width: 164rpx;
margin-right: 20rpx;
border-radius: 14rpx;
}
.shop-content {
width: 430rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.title {
.name {
font-size: 28rpx;
}
.tip {
color: #999;
font-size: 24rpx;
margin: 12rpx 0;
}
}
.price {
font-size: 30rpx;
font-weight: bold;
color: #F55726;
}
.price-btn {
display: flex;
justify-content: space-between;
.btn {
display: flex;
align-items: center;
.num {
margin: 0 20rpx;
text-align: center;
}
}
}
}
}
}
}
.cart-btn {
.cart-check {
display: flex;
align-items: center;
image {
width: 40rpx;
height: 40rpx;
margin: 0 10rpx;
}
}
.btn-boxs {
display: flex;
.all-price {
display: flex;
align-items: center;
margin-right: 20rpx;
.price {
color: #20B128;
display: table-cell;
vertical-align: bottom;
font-weight: bold;
}
}
}
}
</style>