首页 » 技术分享 » 加入购物车功能实现

加入购物车功能实现

 

在models中建一个用户模型user,用户模型需要关联

引入mongoose

var mongoose = require('mongoose');

拿到mongoose以后,需要创建Schema模型,模型的字段必须与数据库对应起来。

var userSchema = mongoose.Schema({

          "userId":String, // 用户Id

         "userName":String, // 用户名

         "userPwd":String, // 用户密码

         "orderList":Array, // 订单列表

         "cartList":[ // 购物车列表

   {

         "productId": String, // 商品Id

         "productName": String, // 商品名称

         "salePrice":String, // 商品价格

         "productImage":String, // 图片地址

         "checked":String, // 是否选中

         "productNum":String // 商品数量

    }

],

         "addressList":Array // 用户地址列表

});

通过module.exports进行输出,这样才能加载到 三个参数分别是 模型名,userSchema名,管理数据库集合名

module.exports = mongoose.model("User",userSchema,"users");

在商品模型models/goods.js中添加商品数量prodcutNum和是否选择属性checked

var produtSchema = new Schema({

        "productId":String,

        "productName":String,

        "salePrice":Number,

        "prodcutNum": Number,

        "checked":String,

        "prodcutImage": String

});

》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

购物车业务逻辑

第一步:拿到用户信息,判断用户是否存在

第二步:如果用户信息中存在此商品,则添加商品数量

第三步:如果用户信息中不存在此商品,则添加此商品,并设置为选择状态

node后端代码

models/user.js 用户模型

var mongoose = require('mongoose')
var userSchema = mongoose.Schema({
    "userId":String,   // 用户Id
    "userName":String, // 用户名
    "userPwd":String,  // 用户密码
    "orderList":Array,  // 订单列表
    "cartList":[ // 购物车列表
        {
            "productId": String,  // 商品Id
            "productName": String, // 商品名称
            "salePrice":String, // 商品价格
            "productImage":String, // 图片地址
            "checked":String, // 是否选中
            "productNum":String // 商品数量
        }
    ],
    "addressList":Array // 用户地址列表
});

// 通过module.exports进行输出,这样才能加载到  三个参数分别是 模型名,userSchema名,管理数据库集合名
module.exports = mongoose.model("User",userSchema,"users");

node查询商品列表及添加购物车逻辑

routes/goods.js

var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Goods = require('../models/goods');

// 连接MongoDB数据库
mongoose.connect('mongodb://47.100.191.231:27017/dumall');

// 通过mongoose.connect.on的形式去监听数据库有没有连接成功
mongoose.connection.on("connected",function () {
    console.log("MongoDB connected success.")
})
// 连接失败
mongoose.connection.on("error",function () {
    console.log("MongoDB connected fail.")
})
// 连接断开
mongoose.connection.on("disconnected",function () {
    console.log("MongoDB connected disconnected.")
})

// next是往后继续执行的对象
// 查询商品列表数据
router.get("/", function (req,res,next) {
    let page = parseInt(req.param("page")); // 获取分页参数 第几页
    let pageSize = parseInt(req.param("pageSize")); // 获取一页多少条数据 必须要是数字
    let priceLevel = req.param("priceLevel"); // 接收筛选价格
    let sort = req.param("sort"); // 获取排序参数
    let skip = (page-1)*pageSize; // 分页计算公式
    var priceGt = '',priceLte = ''; // 筛选价格的区间
    let = params = {};
    // 当priceLevel不等于all是执行,默认是all
    if(priceLevel!='all'){
        switch (priceLevel){
            case '0':
                priceGt = 0; priceLte=100; 
                break;
            case '1':
                priceGt = 100; priceLte=500; 
                break;
            case '2':
                priceGt = 500; priceLte=1000; 
                break;
            case '3':
                priceGt = 1000; priceLte=5000; 
                break;
        }
        params = {
            salePrice:{
                $gt:priceGt, // 筛选价格大于priceGt
                $lte:priceLte // 筛选价格小于priceLte
            }
        }
    }

    // 通过skip param 和limit来实现分页, skip表示跳过几条数据 limit表示一页多少条数据
    let goodsModel = Goods.find(params).skip(skip).limit(pageSize);
    // 声明对哪个字段进行排序 ,这里如salePrice金额 sort 1 为升序,-1 为降序
    goodsModel.sort({'salePrice':sort});
    // 第一个是参数,目前没有入参
    // 返回的是两个参数,第一个是报错err,第二个是文档
    // 因为这里不是普通的查询,经过到这里已经执行了很多步骤了 下面通过exec来执行我们的方法
    // exec这里不需要传入参数了,因为前面已经find 拿到结果了
    goodsModel.exec(function (err,doc) {
        
        if(err) {
            res.json({
                status:'1',
                msg:err.message
            });
        } else {
            // 如果没有报错就把结果输出
            res.json({
                status:'0',
                msg:'',
                result:{
                    count: doc.length,
                    list: doc
                }
            });
        }
    });
});

// 加入购物车
router.post("/addCart", function (req,res,next) {
                            // post获取前端参数需要使用req.body.属性名
    var userId = '100000077',productId = req.body.productId;
    var User = require('../models/user'); // 获取用户模型

    // 查询当前用户
    User.findOne({userId:userId}, function (err,userDoc) {
        if(err) {
            res.json({
                status:"1",
                msg:err.message
            })
        }else{
            console.log("userDoc:"+userDoc);
            if(userDoc) {
                let goodsItem = '';
                // 遍历购物车列表查询有没有此产品
                userDoc.cartList.forEach(function (item) {
                    if(item.productId == productId){ // 如果购物车列表已经有了该商品,只将此商品数量加1
                        goodsItem = item;
                        item.productNum ++;
                    }
                });
                if(goodsItem){ // 如果此商品购物车里面已经有了,那么就更新一下productNum
                    userDoc.save(function (err2,doc2) {
                        if(err2) {
                            res.json({
                                status:"1",
                                msg:err2.message
                            })
                        }else{
                            res.json({
                                status:'0',
                                msg:'',
                                result:'suc'
                            })
                        }
                    }); 
                } else { // 如果此商品购物车列表没有,那么则将此商品添加至购物车列表
                    Goods.findOne({productId:productId},function (err1,doc) {
                        if(err1) {
                            res.json({
                                status:"1",
                                msg:err1.message
                            })
                        }else{
                            if(doc) {
                                doc.productNum = 1;
                                doc.checked = 1;
                                userDoc.cartList.push(doc); // 将数据添加
                                userDoc.save(function (err2,doc2) {
                                    if(err2) {
                                        res.json({
                                            status:"1",
                                            msg:err2.message
                                        })
                                    }else{
                                        res.json({
                                            status:'0',
                                            msg:'',
                                            result:'suc'
                                        })
                                    }
                                }); 
                            }
                        }
                    });
                }

            }
        }
    })
});

// 通过module.exports进行输出,这样才能加载到
module.exports = router;

vue前端GoodList.vue 商品列表及添加购物车逻辑

<template>
    <div>
      <nav-header></nav-header>
      <nav-bread>
        <span>Goods</span>
      </nav-bread>
      <div class="accessory-result-page accessory-page">
        <div class="container">
          <div class="filter-nav">
            <span class="sortby">Sort by:</span>
            <a href="javascript:void(0)" class="default cur">Default</a>
            <a @click="showFilterPop" href="javascript:void(0)" class="price">
              Price 
              <svg class="icon icon-arrow-short"><use xlink:href="#icon-arrow-short"></use></svg>
            </a>
            <a href="javascript:void(0)" class="filterby stopPop" @click="showFilterPop">Filter by</a>
          </div>
          <div class="accessory-result">
            <!-- filter -->
            <div class="filter stopPop" id="filter">
              <dl class="filter-price">
                <dt>Price:</dt>
                <dd><a href="javascript:void(0)" v-bind:class="{'cur':priceChecked=='all'}" @click="priceChecked='all'">All</a></dd>
                <dd v-for="(price,index) in priceFilter" :key="index">
                  <a href="javascript:void(0)" @click="setPriceFilter(index)" v-bind:class="{'cur':priceChecked==index}">{{ price.startPrice }}-{{ price.endPrice }}</a>
                </dd>
              </dl>
            </div>

            <!-- search result accessories list -->
            <div class="accessory-list-wrap">
              <div class="accessory-list col-4">
                <ul>
                  <li v-for="(item,index) in goodsList" :key="index">
                    <div class="pic">
                      <a href="#"><img v-lazy="'/static/'+item.productImage" alt=""></a>
                    </div>
                    <div class="main">
                      <div class="name">{{item.productName}}</div>
                      <div class="price">{{item.salePrice}}</div>
                      <div class="btn-area">
                        <a href="javascript:;" class="btn btn--m" @click="addCart(item.productId)">加入购物车</a>
                      </div>
                    </div>
                  </li>
                </ul>
                <div class="load-more" v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="30">
                    <img src="./../assets/loading-spinning-bubbles.svg" alt="" v-show="loading">
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- <div class="md-overlay" v-show="overLayFlag" @click="closePop"></div> -->
      <nav-footer></nav-footer>
   </div>
</template>
<script>
    import './../assets/css/base.css'
    import './../assets/css/product.css'
    import './../assets/css/checkout.css'
    import './../assets/css/login.css'
    import NavHeader from '@/components/NavHeader.vue'
    import NavFooter from '@/components/NavFooter.vue'
    import NavBread from '@/components/NavBread.vue'
    import axios from 'axios'
    
    export default {
        data () {
            return {
                goodsList: [],
                sortFlag: true, // 排序字段
                page:1, // 默认页
                pageSize: 8, // 默认一页显示8条数据
                busy:true,
                loading:true,
                // priceLevel:this.priceChecked, // 筛选选择价格
                priceFilter:[
                  {
                      startPrice:'0.00',
                      endPrice:'100.00'
                  },
                  {
                    startPrice:'100.00',
                    endPrice:'500.00'
                  },
                  {
                    startPrice:'500.00',
                    endPrice:'1000.00'
                  },
                  {
                    startPrice:'1000.00',
                    endPrice:'5000.00'
                  }
                ],
                priceChecked:'all'
                // filterBy:false,
                // overLayFlag:false
            }
        },
        components: {
          NavHeader,
          NavFooter,
          NavBread
        },
        mounted () {
          this.getGoodList();
        },
        methods: {
          getGoodList (flag) {
            var param = { // 分页及排序参数
              page:this.page,
              pageSize: this.pageSize,
              sort: this.sortFlag?1:-1,  // 升序是1 降序是-1
              priceLevel: this.priceChecked
            }
            this.loading = true;
            axios.get("/goods", {params:param}).then((result)=>{
              let res = result.data;
              this.loading = false;
              if(res.status=="0"){
                if(flag){ // 如果是分页需要累计
                     // 将数组进行串联起来 concat表示将数组连接起来
                  this.goodsList = this.goodsList.concat(res.result.list);
                  if(res.result.count == 0){
                    this.busy = true;
                  } else {
                    this.busy = false;
                  }
                } else { // 普通的请求
                  this.goodsList = res.result.list; 
                  this.busy = false;
                }
              } else {
                this.goodsList = [];
              }
            });
          },
          showFilterPop() { // 排序
                // this.filterBy = true;
                // this.overLayFlag = true;
                this.sortFlag = ! this.sortFlag; // 点击后升序降序切换
                this.page = 1; // 点击升降序后默认从第一页显示
                this.getGoodList(); // 重新加载一次
          },
          loadMore () {
              this.busy = true; // 在请求成功之前禁止再滚动加载
              // 鼠标滚动实在太快了,滚动一秒钟可能有上千个请求,这样对服务器压力太大 因此必须要通过setTimeout来控制
              // 只有第一个请求结束以后才能请求第二个
              setTimeout(() => {
                  this.page++; // 滚动之后要给page++
                  this.getGoodList(true);
              }, 500);
          },
          setPriceFilter(index) { // 价格过滤
            this.priceChecked = index;
            this.page = 1; // 价格过滤后分页从第一页重新开始
            this.getGoodList();
            // this.closePop();
          },
          addCart(productId) { // 添加购物车
            axios.post("/goods/addCart",{
              productId:productId
            }).then((res)=>{ 
              if(res.status==200){
                alert("加入成功");
              }else{
                alert("msg:"+res.msg);
              }
            });
          }
        }
    }
</script>

 

转载自原文链接, 如需删除请联系管理员。

原文链接:加入购物车功能实现,转载请注明来源!

0