glhcp/pc/pages/shop_cart.vue

479 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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>