glhcp/pc/pages/shop_cart.vue

479 lines
17 KiB
Vue
Raw Normal View History

2023-08-10 06:59:52 +00:00
<template>
<div class="shop-cart">
<div class="cart-list">
<div v-show="!isDataNull">
<div class="cart-hd flex bg-white">
<div class="check-box">
<!-- 更改选中状态 type为1选中店铺/2选中商品/3全选 -->
<el-checkbox
v-model="isSelectedAll"
@change="onBoxClick($event, 3, '')"
>全选</el-checkbox
>
</div>
<div class="info flex row-center">商品信息</div>
<div class="price flex row-center">单价</div>
<div class="num flex row-center">数量</div>
<div class="money flex row-center">合计</div>
<div class="operate flex row-center">操作</div>
</div>
<div class="cart-con bg-white">
<div
class="m-b-10 bg-white"
v-for="(item, index) in shopCartList"
:key="index"
>
<div class="flex shop">
<!-- 更改选中状态 type为1选中店铺/2选中商品/3全选 -->
<el-checkbox
:value="item.is_selected == 1"
@change="onBoxClick($event, 1, index)"
>
</el-checkbox>
<div class="xs normal m-l-10">
{{ item.shop.shop_name }}
</div>
</div>
<div
class="item flex"
v-for="(item2, index2) in item.cart"
:key="index2"
>
<div class="check-box">
<!-- 更改选中状态 type为1选中店铺/2选中商品/3全选 -->
<el-checkbox
:value="item2.selected == 1"
@change="
onBoxClick($event, 2, item2.cart_id)
"
>
</el-checkbox>
</div>
<nuxt-link
class="info flex"
:to="'/goods_details/' + item2.goods_id"
>
<div class="pictrue flexnone">
<img :src="item2.image" alt="" />
</div>
<div>
<div class="name line2">
{{ item2.goods_name }}
</div>
<div class="muted">
{{ item2.spec_value_str }}
</div>
</div>
</nuxt-link>
<div class="price flex row-center">
¥{{ item2.price }}
</div>
<div class="num flex row-center">
<number-box
:min="1"
v-model="item2.goods_num"
@change="
changeShopCartCount(
$event,
item2.cart_id
)
"
async-change
/>
</div>
<div class="money flex row-center">
¥{{ item2.sub_price }}
</div>
<el-popconfirm
title="确定删除该商品吗?"
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
@confirm="goodsDelete(item2.cart_id)"
>
<div
class="operate flex row-center delete-btn"
slot="reference"
>
<img
src="~/static/images/icon_cart_del.png"
/>
</div>
</el-popconfirm>
</div>
</div>
</div>
<div class="cart-footer flex row-between bg-white">
<div class="lighter flex">
<div class="check-box">
<el-checkbox
v-model="isSelectedAll"
@change="onBoxClick($event, 3, '')"
>全选</el-checkbox
>
</div>
<div style="margin: 0 24px"></div>
<el-popconfirm
title="确定删除选中商品吗?"
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
@confirm="deleteSelectedGoods"
>
<div
class="xs normal"
style="cursor: pointer"
slot="reference"
>
删除选中商品
</div>
</el-popconfirm>
<el-popconfirm
title="确定清空吗?"
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
@confirm="deleteAlldGoods"
>
<div
class="m-l-14 xs muted"
style="cursor: pointer"
slot="reference"
>
清空购物车
</div>
</el-popconfirm>
</div>
<div class="total flex">
<div class="flex m-r-14">
<div class="xs">已选{{ selected }}件商品</div>
<div class="primary m-l-20" style="font-size: 22px">
¥{{ totalAmount }}
</div>
</div>
<div
class="white lg btn flex row-center"
:style="{
background:
selected == 0 ? '#A4ADB3' : '#FF2C3C',
}"
@click="toOrderBuy"
>
去结算
</div>
</div>
</div>
</div>
<div class="column-center data-null" v-show="isDataNull">
<img
src="@/static/images/cart_null.png"
style="width: 150px; height: 150px"
/>
<div class="muted xs m-t-10">购物车是空的</div>
<div class="m-t-30">
<el-button
round
type="primary"
size="medium"
@click="toIndex"
>去逛逛</el-button
>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
head() {
return {
title: this.$store.getters.headTitle,
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: this.$store.getters.favicon,
},
],
}
},
data() {
return {
shopCartList: [],
totalAmount: 0,
totalNum: 0,
isDataNull: false,
}
},
mounted() {},
computed: {
// 是否全选
isSelectedAll: {
get() {
if (!this.shopCartList.length) return false
if (this.allInvalid()) return false
let index = this.shopCartList.findIndex(
(item) => item.is_selected == 0
)
return index == -1 ? true : false
},
set(val) {
return val
},
},
// 已经选择的数量
selected: {
get() {
return this.shopCartList.reduce((pre, item) => {
return pre.concat(item.cart.filter((i) => i.selected == 1))
}, []).length
},
},
},
methods: {
...mapActions(['getPublicData']),
async getCartList() {
let res = await this.$get('cart/lists')
if (res.code == 1) {
this.shopCartList = Object.assign([], res.data.lists)
this.totalAmount = res.data.total_amount
this.totalNum = res.data.total_num
if (this.shopCartList.length > 0) {
this.isDataNull = false
} else {
this.isDataNull = true
}
}
},
// 更改选中状态 type为1选中店铺/2选中商品/3全选
onBoxClick(e, type, number) {
let cartId = []
switch (type) {
case 1:
cartId = this.shopCartList[number].cart.map(
(item) => item.cart_id
)
break
case 2:
cartId.push(number)
break
case 3:
cartId = this.shopCartList.reduce((pre, item) => {
return pre.concat(item.cart.map((i) => i.cart_id))
}, cartId)
break
}
this.changeSelected(cartId, e)
},
cartInvalid(item) {
return item.goods_status == 0 || item.goods_del != 0 ? true : false
},
shopInvalid(item) {
return item.cart.every((citem) => this.cartInvalid(citem))
},
allInvalid() {
return this.shopCartList.every((item) => this.shopInvalid(item))
},
// 选中/取消选中购物车
async changeSelected(id, selected) {
let res = await this.$post('cart/selected', {
cart_id: id,
selected: selected,
})
if (res.code == 1) {
this.getCartList()
}
},
// 修改购物车商品数量
async changeShopCartCount(number, cartId) {
let res = await this.$post('cart/change', {
cart_id: cartId,
goods_num: number,
})
if (res.code == 1) {
this.getCartList()
this.getPublicData()
}
},
// 删除购物车商品
async goodsDelete(cartId) {
let res = await this.$post('cart/del', {
cart_id: cartId,
})
if (res.code == 1) {
this.getPublicData()
this.getCartList()
this.$message({
message: '删除商品成功',
type: 'success',
})
}
},
// 删除选中购物车
deleteSelectedGoods() {
let selectedGoodsArr = this.shopCartList.reduce((pre, item) => {
return pre.concat(item.cart.filter((i) => i.selected == 1))
}, [])
if (selectedGoodsArr.length <= 0) {
this.$message({
message: '没有选择商品',
type: 'error',
})
return
}
let cartIdArr = selectedGoodsArr.map((item) => item.cart_id)
this.goodsDelete(cartIdArr)
},
// 清空购物车
deleteAlldGoods() {
let allGoodsArr = this.shopCartList.reduce((pre, item) => {
return pre.concat(item.cart.filter((i) => i.cart_id))
}, [])
if (allGoodsArr.length <= 0) {
this.$message({
message: '没有商品',
type: 'error',
})
return
}
let cartIdArr = allGoodsArr.map((item) => item.cart_id)
this.goodsDelete(cartIdArr)
},
getSelectCart() {
const { shopCartList } = this
return shopCartList.reduce((pre, item) => {
return pre.concat(
item.cart
.filter((i) => i.selected && !this.cartInvalid(i))
.map((i) => i.cart_id)
)
}, [])
},
// 去购买商品
toOrderBuy() {
let { shopCartList } = this
let goods = []
let carts = this.getSelectCart()
if (carts.length == 0) return this.$message.err('您还没有选择商品哦')
// 处理出商品数组数据
shopCartList.forEach((item) => {
if (item.cart.length != 0) {
item.cart.forEach((el, i) => {
// 选中的商品才能进入
if (el.selected == 1) {
goods.push({
item_id: el.item_id,
num: el.goods_num,
goods_id: el.goods_id,
shop_id: item.shop.shop_id,
})
}
})
}
})
const params = {
carts: carts,
goods: goods,
type: 'cart',
}
this.$router.push({
path: '/confirm_order',
query: {
data: encodeURIComponent(JSON.stringify(params)),
},
})
},
toIndex() {
this.$router.push('/')
},
},
created() {
this.getCartList()
},
}
</script>
<style lang="scss" scoped>
.shop-cart {
padding: 24px 0;
.cart-list {
min-height: 600px;
.cart-hd {
height: 50px;
color: #101010;
padding: 10px 10px;
margin-bottom: 10px;
}
.cart-con {
padding: 0 10px;
.shop {
padding: 20px 10px;
border-bottom: 1px solid #d7d7d7;
}
.item {
padding: 20px 10px;
border-bottom: 1px dashed #e5e5e5;
}
.item:last-child {
border-bottom: 0;
}
}
.check-box {
padding-left: 10px;
width: 40px;
}
.info {
width: 450px;
.pictrue {
margin-right: 10px;
img {
width: 72px;
height: 72px;
}
}
.name {
margin-bottom: 10px;
}
}
.price {
width: 150px;
}
.num {
width: 250px;
}
.money {
width: 150px;
}
.delete-btn {
cursor: pointer;
}
}
.cart-footer {
padding: 20px;
.total {
.btn {
width: 152px;
height: 50px;
cursor: pointer;
border-radius: 4px;
}
}
}
.data-null {
text-align: center;
padding-top: 170px;
}
}
</style>