电商购物网站 - 购物车结算

1、添加视图和集合

添加商品链接

上节课程里我们已经实现了商品的添加和展示,接下来我们开始进行对商品的操作——加入购物车。

首先,商品页的加入购物车按钮、购物车查看按钮添加链接,如下所示:

<a href="/addToCart/<%=Commoditys[i]._id%>">加入购物车</a>

我们先定义购物车(cart)集合的Schema属性,包含:uId(用户ID)、cId(商品ID)、cName(商品名称)、cPrice(商品价格)、cImgSrc(商品展示图片路径)、cQuantity(商品数量)、cStatus(商品结算状态,默认为false),参考如下:

cart: {
    uId: {type: String},
    cId: {type: String},
    cName: {type: String},
    cPrice: {type: String},
    cImgSrc: {type: String},
    cQuantity: {type: Number},
    cStatus: {type: Boolean, default: false}
}

以上属性定义我们还是统一放到models.js文件中以方便管理和操作。

接着views目录下添加购物车(cart.html)视图页面,参考如下:

《电商购物网站 - 购物车结算》

购物车页面的展示实现可参考如下贴图:

<ul>
    <%for(var i in carts){
    if(!carts[i].cId){
    continue;
    }
    }%>
    <li>
        <div class="li-checkbox">
            <input data-id="<%=carts[i]._id%>" data-index="<%=i%>" data-price="<%=carts[i].cPrice%" name="chkItem"
                   class="li-checkbox input" type="checkbox">
        </div>
        <div class="li-img">
            <a>
                <img src="img/<%=carts[i].cImgSrc%>" class="li-img a img">
            </a>
        </div>
        <div class="li-content">
            <a><%=carts[i].cName%></a>
        </div>
        <div class="li-price">
            <span><%=carts[i].cPrice%></span>
        </div>
        <div class="li-quantity">
            <a data-type="add" href="javascript:void(0);" class="btn btn-default btn-xs">+</a>
            <input id="Q<%=i%>" style="width: 40px;" type="text" value="<%=carts[i].cQuantity%>">
            <a data-type="subtr" href="javascript:void(0);" class="btn btn-default btn-xs">-</a>
        </div>
        <div class="li-del">
            <a href="/delFromCart/<%=carts[i]._id%>" class="btn btn-primary btn-xs">删除</a>
        </div>
    </li>
    <%}%>
</ul>

2、定义视图路由

访问视图

接着在routes目录添加cart.js文件(index.js文件中引用),来定义路由处理规则。

比如cart路径的处理,如下:

1.检测登陆用户是否过期,已过期则跳转login页同时给出提示信息。

2.通过global.dbHelper.getModel方法获取cart模型。

3.通过find查询用户所有商品并传入模板,条件:用户ID,结算状态。

4.贴出部分代码:

app.get('/cart', function (req, res) {
    ......
    Cart.find({"uId": 用户ID, "cStatus": false}, function (error, docs) {
        res.render('cart', {carts: docs});
    });
});

加入购物车按钮链接所对应路径的处理,如:/addToCart/:商品id

app.get("/addToCart/:id", function(req, res) {...});

1.通过req.params.id获取商品ID号并检测登陆用户状态。

2.通过global.dbHelper.getModel方法获取购物车(cart)、商品(commodity)模型。

3.商品已存在则进行更新操作,贴出部分参考代码:

Cart.update({"uId":用户ID,"cId":商品ID},{$set:{cQuantity:已有数量+1}}

4.商品未存在则进行添加操作,贴出部分代码:

Commodity.findOne({"_id": 商品ID}, function (error, doc) {
        Cart.create({
            uId: 用户ID,
            cId: 商品ID,
            cName: doc.name,
            cPrice: doc.price,
            cImgSrc: doc.imgSrc,
            cQuantity : 1
        },function(error,doc){
            if(doc){
                res.redirect('/home');
            }
        });
});

3、商品的单选和全选

在购物车页面展示还是使用ejs模板(具体实现可参考贴图)来实现用户购物车商品的展示,现期间我们用到了checkbox,这里我们就来简单的实现商品的全选和单选。

首先,简单介绍实现步骤:

  1. 用户选中全选按钮时,列表内选框全部变为勾选状态。

  2. 用户取消全选按钮选中状态时,列表内选框全部取消勾选状态。

  3. 列表内选框为全部勾选状态时,全选按钮为选中状态,反之不勾选。

  4. 全选按钮未选中情况下,当列表内按钮全部选中则全选按钮也要被选中。

对于checkbox按钮如下图所示:

<div class="li-checkbox">
    <input data-id="<%=carts[i]._id%>" data-index="<%=i%>" data-price="<%=carts[i].cPrice%" name="chkItem"
           class="li-checkbox input" type="checkbox">
</div>  

注:data-index属性存储索引值用来获取商品数量,data=id存储商品IDdata-price存储商品价格。

实现全选:为全选框(如idCheckAll)添加单击事件,这里我们使用prop方法设置checkbox状态、is方法判断checkbox状态,如下参考示例:

$('#CheckAll').click(function(){
       var self = $(this);
       $('input[name="chkItem"]').each(function(){
          $(this).prop("checked",self.is(':checked'));
       });
 });

实现单选:单选框(如namechkItem)添加单击事件,这里我们使用prop方法设置checkbox状态、not方法判断checkbox状态,如下参考示例:

$('input[name="chkItem"]:checkbox').click(function(){
   var isCheck = $('input[name="chkItem"]:not(:checked)').length?false:true;
   $('#CheckAll').prop("checked",isCheck);
});

到这里我们就简单实现了按钮的全选和单选,以上方法可供参考也可以自行思路去实现。

4、商品的数量加减

前面我们实现了对于商品的单选和全选功能,下面我们就开始实现商品数量的加减。

对于+-按钮如下所示:

<div class="li-quantity">
    <a data-type="add" href="javascript:void(0);" class="btn btn-default btn-xs">+</a>
    <input id="Q<%=i%>" style="width: 40px;" type="text" value="<%=carts[i].cQuantity%>">
    <a data-type="subtr" href="javascript:void(0);" class="btn btn-default btn-xs">-</a>
</div>

简单实现步骤如下:

  1. 定义data-type属性用于区分+-按钮。

  2. a标签添加单击事件。并同时改变显示框的值。

  3. 使用siblings()方法改变同级标签的数量值。

具体实现可参考如下方法:

$('.li-quantity a').click(function(){
    var self = $(this);
    var type = self.attr('data-type'),
        num = parseFloat(self.siblings('input').val());
    if(type == 'add'){
          num += 1;
     }else if(type == 'subtr'){
          if(num > 1){
             num -= 1;
          }else{
             return false;
          }
     }
    self.siblings('input').val(num);
});

到这里对于商品数量的加、减也实现了,接着我们开始实现用户选中商品的总价格计算功能。

5、商品总金额的计算

计算总金额

商品的状态选择和数量的加减功能我们已经实现了,选择我们就开始实现当用户选择相关商品时总金额的计算功能。

实现步骤如下:

  1. 定义公共方法,用于用户不同加、减、全选等操作时皆可调用。

  2. 循环列表内所有被选中的checkbox(假设namechkItem)。

  3. 使用checkbox的相应属性值,来获取价格和数量。

  4. 定义全局变量(假设为sum)存储总金额并赋值显示。

具体方法实现可参考如下内容:

sum = 0;
$('input[name="chkItem"]:checked').each(function () {
    var self = $(this),
        price = self.attr('data-price'),
        index = self.attr('data-index');
    var quantity = $('#Q' + index).val();
    sum += (parseFloat(price) * parseFloat(quantity));
});
$("金额标签").html('¥' + sum + '.00');

到这里,选中商品的价格总计功能也就简单实现了。

6、结算功能的实现

商品结算

关于结算功能,这里就做简单介绍,当用户点击结算按钮时,计算出被选商品的总金额,给予alert出总金额,数据库则更新相应商品的结算状态和数量,当然你也可以在购物车集合中添加一个用户消费金额的属性来保存所消费的金额总数更好,这里就简单处理了。

具体功能实现这里简单介绍如下:

  1. 定义公共方法,用于用户不同加、减、全选等操作时皆可调用。

  2. 循环列表内所有被选中的checkbox(假设namechkItem)。

  3. 使用checkbox的相应属性值,来获取价格和数量。

  4. 定义全局变量(假设为sum)存储总金额并赋值显示。

这里贴出部分实现代码,如下:

//结算方法内容
$('input[name="chkItem"]:checked').each(function(){
     var self = $(this),
         //通过data-index属性,获取索引值
         index = self.attr('data-index'),
        //通过data-id属性,获取对应ID
         ID= self.attr('data-id');
     var 数量= $('#Q'+index).val();
     var data = { "cid": ID, "cnum":数量};
     //发送数据请求
     ...   
});
alert('所付金额为:¥'+sum);
location.href = "cart";

cart.js文件添加对应路由处理如下:

app.post("路径",function(req,res){
   var Cart = global.dbHelper.getModel('cart');
   Cart.update({"_id":req.body.ID},{$set : { cQuantity : req.body.数量,cStatus:true }},function(error,doc){ 
...

7、购物车商品的删除

商品删除

关于商品的删除功能就简单多了,我们只需获取其ID即可实现对于购物车内商品的删除操作

在购物车商品的展示功能实现时,我们就可以获取其ID,如下参考:

<a href="/delFromCart/<%=carts[i]._id%>" >删除</a>

cart.js文件,添加对应路径处理方法,这里简单实现参考如下:

app.get("/delFromCart/:id", function(req, res) {
   //req.params.id 获取ID号
   var Cart = global.dbHelper.getModel('cart');
   Cart.remove({"_id":req.params.id},function(error,doc){
       //成功返回1  失败返回0
       if(doc > 0){
           res.redirect('/cart');
       }
   });
});

好,到这里所有功能都已经实现了。

附上本电商网站项目的源码,供各位研究、开发、扩展

欢迎提issues

    原文作者:whjin
    原文地址: https://segmentfault.com/a/1190000009944506
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞