用户进入购物车页面对其进行查看和管理。系统在商品详情页提供了加入购物车按钮,用户在浏览时遇到自己心仪的商品,但又暂时不想购买或犹豫不决,可以将其加入购物车以便二次查询。
在购物车里中点击商品可以进入对应商品详情页再次浏览,除此之外还提供了全选,单条/选中删除,结算等功能。购物车内标题栏有全选框,显示的每条商品信息前也有勾选框,点击批量删除或结算可以一次性对选中的商品进行对应功能处理。购物车界面如图
删除单条产品,当用户点击某条商品信息后对应的红色删除按钮时,即可删除对应商品。
删除所有选中的产品。批量删除,是通过全选按钮和商品勾选框结合实现。
结算后,结算的商品都要加入个人订单数据表。
点击查看详情。当用户点击某条商品信息时,跳转到对应详情页供用户查看详细信息。
对应代码:
<template>
<div id="ShoppingCart">
<div class="ShoppingCart_box">
<h4 class="cart-title">购物清单</h4>
<table>
<!-- 标题栏 -->
<tr class="product_title">
<td class="t_check" onselectstart="return false">
<span class="check_box" @click="selectProduct(isSelectAll)">
<i class="iconfont icon-duigou1" :class="{'check-true':isSelectAll}"></i>
</span>全选
</td>
<td colspan="2" class="t_name">名称</td>
<td class="t_price">单价(元)</td>
<td class="t_quantity">数量</td>
<td class="t_total">总价(元)</td>
<td class="t_delete">操作</td>
</tr>
<!-- 商品栏 -->
<tr :key="index" v-for="(item,index) in productList">
<td>
<span class="check_box" @click='item.select=!item.select'>
<i class="iconfont icon-duigou1" :class="{'check-true':item.select}"></i>
</span>
</td>
<td colspan="2" class="product_data" @click="viewdetails(item.proid,item.category,'购物车')">
<div class="p-img">
<img :src="item.img" class="p_img" alt="">
</div>
<div class="p_info">
<p>{{item.name}}</p>
<p>规格:{{item.size}}</p>
</div>
</td>
<td class="p_price">¥{{item.price}}</td>
<!-- 调整数量 -->
<td class="p_quantity">
<input type="button" value="-" @click="subQuantity(item)">
<input class="quantity" type="text" v-model="item.quantity">
<input type="button" value="+" @click="addQuantity(item)">
</td>
<td class="p_total">¥{{item.price*item.quantity}}</td>
<td>
<button class="p_delete" @click='deleteOneProduct(index,item.id)'>删除</button>
</td>
</tr>
<!-- 购物车为空时显示 -->
<tr>
<td colspan="7" v-show="productList == undefined || productList.length <= 0" class="cartEmpty">
购物车什么也没有,<span @click="$router.push({path:'/home/first'})">去逛逛></span>
</td>
</tr>
</table>
<!-- 统计结算行 -->
<div class="statistic">
<button class="check_delete" @click='deleteCheckProduct'>
<i class="iconfont icon-shanchu"></i>删除勾选商品
</button>
<button class="buy" @click="displayPay = true">去结算</button>
<div class="div_total">
<!-- 数量和总金额由计算属性得出 -->
<span class="total_num">{{productTotal.quantity}}件商品总计:</span>
<span class="total_price">¥{{productTotal.totalPrice}}元</span>
</div>
</div>
<!-- 支付提示框 -->
<div class="payAlert" :class="{payShow:displayPay}">
<h5>结算确认</h5>
<img src="../../assets/imgs/pay.jpg" alt="">
<div class="payBtns">
<button class="payCancel" @click="displayPay = false">取消</button>
<button class="payConfirm" @click="settle()">确认支付</button>
</div>
</div>
</div>
</div>
</template>
<script>
import {getLoginData,getcoData,deletecoData,batchJoin} from '@/api/index'
//订单号和创建时间函数封装
import {getTime,getNumber} from '@/assets/js/reuse'
// 混入属性,页面跳转方法复用
import {productInfoMixin} from '@/assets/js/mixin'
export default {
name: 'ShoppingCart',
// 混入对象
mixins:[productInfoMixin],
data(){
return {
productList:[],
userdata:[],
displayPay:false
}
},
mounted(){
// 获取商品数据
this.getcartList()
// 获取用户数据
this.getUserdata()
},
computed:{
// 检测是否全部勾选
isSelectAll() {
// 如果数组为空,返回false
if(this.productList == undefined || this.productList.length <= 0){
return false
}else{
// 如果数组中中每一条数据的select都为true,才返回true,否则返回false
return this.productList.every((value) => {return value.select});
}
},
// 计算选择商品的总数和总价
productTotal() {
// 获取list中select为true的数据,即被勾选了的商品
var List_true = this.productList.filter((item) => {return item.select});
var totalPrice = 0;
for (var i = 0; i < List_true.length; i++) {
// 总价 = 每种商品的数量*单价
totalPrice += List_true[i].quantity * List_true[i].price;
}
// 选择产品的件数:List_true.lenth,总价:totalPrice
return{quantity:List_true.length,totalPrice:totalPrice}
}
},
methods:{
//给数组元素添加属性
addAttribute(){
//为productList添加select(用于判定是否勾选,初始值为false,即不选中)
this.productList.map((item) =>{ //map:'键值对'
this.$set(item,'select',false) //往item添加select属性,默认为false
})
},
// 全选与取消全选
selectProduct(_isSelect){
//遍历productList,全部取反
for (var i = 0; i < this.productList.length; i++) {
this.productList[i].select = !_isSelect
}
},
//数量-
subQuantity(item){
if(item.quantity > 1){
item.quantity--
}
},
//数量+
addQuantity(item){
//请求商品库存,传入商品类别,id
getProInfo({
colname:'quantity',
formname:'productlist',
id:item.proid
})
.then((res) =>{
// 计算库存是否足够
if(item.quantity < res[0].quantity){
item.quantity++
}
})
},
//删除单条产品
deleteOneProduct(index,id){
//根据索引删除productList的记录
this.productList.splice(index,1);
let idlist = []
idlist.push(id)
this.deletecart(idlist)
},
//删除所有选中的产品
deleteCheckProduct(){
let idlist = []
// 将所有选中的商品id存入数组
this.productList = this.productList.filter((item) => {
if(item.select == true){
idlist.push(item.id)
}
return item.select == false
})
this.deletecart(idlist)
},
// 点击确认,选中商品一次性购买,将所有选中商品加入个人订单
settle(){
// 支付确认框隐藏
this.displayPay = false
// 存放勾选商品信息
let selectList= []
// 存放勾选商品id
let idlist = []
// 遍历整个购物车数据
this.productList = this.productList.filter((item) => {
if(item.select == true){
// 将dataProcess处理好的这条信息加入数组
selectList.push(this.dataProcess(item))
idlist.push(item.id)
}
return item.select == false
})
// 选中结算的商品,从购物车删除
this.deletecart(idlist)
// 批量加入个人订单
batchJoin(selectList)
.then((res) => {
alert('勾选商品购买成功,已加入订单')
})
.catch(error => {
alert('批量添加失败')
})
},
//将信息处理为一个符合订单数据表的数组格式
dataProcess(item){
let proarr = Object.values(item)
// 将商品id置空,在订单表内会自增
proarr[0] = 0
// 将最后一个select属性去除
proarr.splice(-1)
// 加入状态(status)值,结算后应为待收货即1
proarr.push(1)
// 加入收货人信息
proarr.push(this.userdata.name,this.userdata.phone,this.userdata.place)
//获取订单创建时间
let timedata = getTime()
//订单时间
proarr.push(timedata.time)
//订单号编写
let orderNumber = getNumber(timedata.orderNumTime,item.proid,item.category)
//把这一条订单信息加入数组
proarr.push(orderNumber)
return proarr
},
// 获取购物车数据
getcartList(){
getcoData({
formname:'shoppingcart',
username:sessionStorage.getItem("userName")
})
.then((res) => {
this.productList = res
// 添加用于判断勾选的属性
this.addAttribute()
})
.catch(error => {
alert('获取失败')
})
},
//删除购物车数据
deletecart(idlist){
deletecoData({
formname:'shoppingcart',
idlist:idlist
})
.then((res) => {
// // 重新获取购物车数据
// this.getcartList()
})
.catch(error => {
alert('删除失败')
})
},
// 获取用户数据作为默认收货人
getUserdata(){
let userName = sessionStorage.getItem("userName")
getLoginData({username: userName})
.then(res => {
this.userdata = res[0]
})
}
}
}
</script>
<style scoped>
/* 图片名称处样式订单和购物车相同,所以复用 */
@import '../../assets/css/cartorder.css';
/* 支付提示框 */
@import '../../assets/css/payAlert.css';
*{
margin: 0;
padding: 0;
list-style: none;
}
#ShoppingCart{
width: 100%;
}
.ShoppingCart_box{
border: 1px solid #aaa;
border-top: 2px solid rgb(131, 131, 226);
width: 1020px;
margin: 50px auto;
position: relative;
}
.cart-title{
font-size: 25px;
color: #66b1ff;
text-align: center;
line-height: 60px;
}
table{
border-collapse: collapse;
}
/* 标题栏 */
.product_title{
background-color: #f7f7f7;
border-top: 1px solid #e3e3e3;
border-bottom: 1px solid #e3e3e3;
}
.product_title td{
text-align: center;
height: 38px;
line-height: 38px;
}
.t_check{
width: 100px;
}
.t_name{
width: 350px;
}
.t_price{
width: 100px;
}
.t_quantity{
width: 210px;
}
.t_total{
width: 120px;
}
.t_delete{
width: 140px;
}
table .check_box{
display: block;
width: 20px;
height: 20px;
float: left;
border: 1px solid #e3e3e3;
background-color: white;
margin: 8px 5px 8px 15px;
position: relative;
}
.product_title td .icon-duigou1{
line-height: 20px;
}
.icon-duigou1{
color: red;
margin-left: 2px;
display: none;
}
.check-true{display: block;}
/* 商品栏 */
.p_price{
text-align: center;
color: #e92846;
}
/* 调整数量的按键 */
.p_quantity{
padding: 0 30px;
}
table input{
border: #e3e3e3 solid 1px;
padding: 5px 10px;
color: #848484;
font-size: 16px;
cursor: pointer;
margin-left: 10px;
}
.quantity{
width: 30px;
color: black;
text-align: center;
font-size: 14px;
}
.p_total{
text-align: center;
color: #e92846;
}
.p_delete{
width: 80px;
height: 30px;
background-color: #fd3729;
border: none;
margin: 0 30px;
border-radius: 8px;
color: white;
cursor: pointer;
}
/* 购物车为空时提示字 */
.cartEmpty{
width: 1005px;
height: 100px;
text-align: center;
}
.cartEmpty span{
color: blue;
cursor: pointer;
}
/* 统计结算行 */
.statistic{
height: 40px;
background-color: #eeecec;
}
.check_delete{
font-size: 14px;
color: #333;
padding: 0 10px;
margin-top: 10px;
cursor: pointer;
border: none;
}
.buy,.div_total{
float: right;
}
.div_total{
margin-top: 10px;
}
.total_price{
color: #e92846;
}
.buy{
margin-left: 20px;
width: 100px;
height: 40px;
border: none;
color: #fff;
font-size: 18px;
text-align: center;
background-color: #ff3300;
border: 1px solid #eeecec;
cursor: pointer;
}
/* 结算提示框 */
.payAlert{
height: 280px;
top: -400px;
left: 300px;
}
.payShow{
top: 130px;
left: 300px;
}
</style>