欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

node和vue实现商城用户地址模块

程序员文章站 2022-04-13 15:48:29
本文为大家分享了node和vue商城用户地址模块的实现,供大家参考,具体内容如下 server/models/user.js var mongoose = re...

本文为大家分享了node和vue商城用户地址模块的实现,供大家参考,具体内容如下

server/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":[ // 用户地址列表
   {
    "addressid": string,
    "username": string,
    "streetname": string,
    "postcode": number,
    "tel": number,
    "isdefault": boolean
   }
  ]
});
 
// 通过module.exports进行输出,这样才能加载到 三个参数分别是 模型名,userschema名,管理数据库集合名
module.exports = mongoose.model("user",userschema,"users");

server/routes/users.js

var express = require('express');
var router = express.router();
 
var user = require('./../models/user');
 
/* get users listing. */
router.get('/', function(req, res, next) {
 res.send('respond with a resource');
});
 
router.get('/test', function(req, res, next) {
 res.send('test');
});
 
// 登录
router.post('/login', function(req, res, next) {
 // 获取前端传过来的参数 post方式用req.body形式获取参数
 var param = {
  username:req.body.username,
  userpwd:req.body.userpwd
 }
 user.findone(param, function(err,doc) {
  if(err){
   res.json({
    status:"1",
    msg:err.message
   });
  }else{
    if(doc){
     res.cookie("userid",doc.userid,{ // 将用户信息存入cookie
      path:'/',
      maxage: 1000*60*60
     }); 
     res.cookie("username",doc.username, {
      path:'/',
      maxage: 1000*60*60
     });
     // req.session.user = doc; // 将用户信息存入session
     res.json({
      status:'0',
      msg:'',
      result:{
       username:doc.username
      }
     })
    }
  }
 });
});
 
// 登出接口
router.post("/logout", function (req,res,next) {
 res.cookie("userid", "", { // 登出将userid设置为""
  path:"/",
  maxage:-1 // 设置位过期
 })
 res.json({
  status:"0",
  msg:'',
  result:''
 })
})
 
// 校验用户信息
router.get("/checklogin", function (req,res,next) {
  if(req.cookies.userid){
   res.json({
    status:'0',
    msg:'',
    result: req.cookies.username || '' // 获取cookeie req.cookies.属性
   });
  }else{ // 取不到就说明当前没有登录
   res.json({
    status:'1',
    msg:'未登录',
    result:''
   });
  }
})
 
// 查询当前用户的购物车数据
router.get("/cartlist", function (req,res,next) {
 var userid = req.cookies.userid;
 console.log(userid);
 user.findone({userid:userid}, function (err,doc) {
   if(err){
    res.json({
     status:'1',
     msg:err.message,
     result:''
    });
   }else{
     if(doc){
      res.json({
       status:'0',
       msg:'',
       result:doc.cartlist
      });
     }
   }
 });
});
 
// 购物车删除
router.post("/cartdel", function (req,res,next) {
 // 获取浏览器的cookie 以及用户传递过来的参数 productid
 var userid = req.cookies.userid,productid = req.body.productid;
 user.update({
  userid:userid
 },{
  $pull:{
   'cartlist':{
    'productid':productid
   }
  }
 }, function (err,doc) {
  if(err){
   res.json({
    status:'1',
    msg:err.message,
    result:''
   });
  }else{
   res.json({
    status:'0',
    msg:'',
    result:'suc'
   });
  }
 });
});
 
//修改购物车商品数量
router.post("/cartedit", function (req,res,next) {
 var userid = req.cookies.userid,   // 获取用户客户端的userid
   productid = req.body.productid, // 获取用户传的参数商品id
   productnum = req.body.productnum, // 获取用户传的参数商品id
   checked = req.body.checked;    // 获取用户传的参数是否选中
 user.update({
  "userid":userid,
  "cartlist.productid":productid},{
  "cartlist.$.productnum":productnum,
  "cartlist.$.checked":checked,
 }, function (err,doc) {
  if(err){
   res.json({
    status:'1',
    msg:err.message,
    result:''
   });
  }else{
   res.json({
    status:'0',
    msg:'',
    result:'suc'
   });
  }
 })
});
 
// 商品全选不选
router.post("/editcheckall", function (req,res,next) {
 var userid = req.cookies.userid,
   checkall = req.body.checkall?'1':'0';
 user.findone({userid:userid}, function (err,user) {
  if(err){
   res.json({
    status:'1',
    msg:err.message,
    result:''
   });
  }else{
   if(user){
    user.cartlist.foreach((item)=>{
     item.checked = checkall;
    })
    user.save(function (err1,doc) {
      if(err1){
       res.json({
        status:'1',
        msg:err1,message,
        result:''
       });
      }else{
       res.json({
        status:'0',
        msg:'',
        result:'suc'
       });
      }
    })
   }
  }
 });
});
 
// 用户地址模块开始-----------------------------------------------------------------------------------------------
// 查询用户地址接口
router.get("/addresslist", function (req,res,next) {
 var userid = req.cookies.userid;
 user.findone({userid:userid}, function (err,doc) {
  if(err){
   res.json({
    status:'1',
    msg:err.message,
    result:''
   });
  }else{
   res.json({
    status:'0',
    msg:'',
    result:doc.addresslist
   });
  }
 })
});
 
// 设置默认地址
router.post("/setdefault", function (req,res,next) {
 var userid = req.cookies.userid,
   addressid = req.body.addressid;
 if(!addressid){
  res.json({
   status:'1003',
   msg:'addressid is null',
   result:''
  });
 }else{
  user.findone({userid:userid}, function (err,doc) {
   if(err){
    res.json({
     status:'1',
     msg:err.message,
     result:''
    });
   }else{
    var addresslist = doc.addresslist;
    addresslist.foreach((item)=>{
     if(item.addressid == addressid){
       item.isdefault = true;
     }else{
      item.isdefault = false;
     }
    });
 
    doc.save(function (err1,doc1) {
     if(err){
      res.json({
       status:'1',
       msg:err.message,
       result:''
      });
     }else{
       res.json({
        status:'0',
        msg:'',
        result:''
       });
     }
    })
   }
  });
 }
});
 
// 删除地址接口 
router.post("/deladdress", function (req,res,next) {
 var userid = req.cookies.userid,addressid = req.body.addressid;
 user.update({
  userid:userid
 },{
  $pull:{ // 删除子文档元素
   'addresslist':{
    'addressid':addressid
   }
  }
 }, function (err,doc) {
   if(err){
    res.json({
      status:'1',
      msg:err.message,
      result:''
    });
   }else{
    res.json({
     status:'0',
     msg:'',
     result:''
    });
   }
 });
});
// 用户地址模块开始-----------------------------------------------------------------------------------------------
 
 
module.exports = router;

vue 前端部分

src/router/index.js 路由

import vue from 'vue'
import router from 'vue-router'
import goodslist from './../views/goodslist.vue'
import cart from '@/views/cart.vue'
import address from '@/views/address'
vue.use(router);
 
export default new router({
  routes: [
    {
      path: '/',
      name: 'goodslist',
      component:goodslist
    },
    {
      path: '/cart',
      name: 'cart',
      component:cart
    },
    {
      path: '/address',
      name: 'address',
      component:address
    }
  ]
})

src/views/address.vue

<template>
  <div>
   <nav-header></nav-header>
   <nav-bread>
    <span>address</span>
   </nav-bread>
   <div class="checkout-page">
    <svg style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
     <defs>
      <symbol id="icon-add" viewbox="0 0 31 32">
       <title>add</title>
       <path class="path1" d="m30.745 15.152h-14.382v-14.596c0-0.308-0.243-0.557-0.543-0.557s-0.543 0.249-0.543 0.557v14.596h-14.665c-0.3 0-0.543 0.249-0.543 0.557s0.243 0.557 0.543 0.557h14.665v15.177c0 0.307 0.243 0.557 0.543 0.557s0.543-0.249 0.543-0.557v-15.177h14.382c0.3 0 0.543-0.249 0.543-0.557s-0.243-0.557-0.543-0.557z"></path>
      </symbol>
      <symbol id="icon-ok" viewbox="0 0 32 32">
       <title>ok</title>
       <path class="path1" d="m14.084 20.656l-7.845-9.282c-1.288-1.482-3.534-1.639-5.016-0.351s-1.639 3.534-0.351 5.016l10.697 12.306c1.451 1.669 4.057 1.623 5.448-0.096l18.168-22.456c1.235-1.527 0.999-3.765-0.528-5.001s-3.765-0.999-5.001 0.528l-15.573 19.337z"></path>
      </symbol>
      <symbol id="icon-edit" viewbox="0 0 32 32">
       <title>edit</title>
       <path class="path1" d="m28.287 8.51l-4.805-4.806 0.831-0.831c0.472-0.472 1.086-0.777 1.564-0.777 0.248 0 0.452 0.082 0.622 0.253l3.143 3.144c0.539 0.54 0.133 1.529-0.524 2.186l-0.831 0.831zm26.805 9.992l-1.138 1.138-4.805-4.806 1.138-1.138 4.805 4.806zm24.186 12.612l-14.758 14.762-4.805-4.806 14.758-14.762 4.805 4.806zm7.379 28.288l-4.892 1.224 1.223-4.894 3.669 3.67zm31.123 4.011l-3.143-3.144c-0.567-0.567-1.294-0.867-2.103-0.867-1.036 0-2.174 0.52-3.045 1.391l-20.429 20.436c-0.135 0.134-0.23 0.302-0.276 0.487l-2.095 8.385c-0.089 0.355 0.017 0.736 0.276 0.995 0.198 0.198 0.461 0.307 0.741 0.307 0.085 0 0.171-0.010 0.254-0.031l8.381-2.096c0.185-0.047 0.354-0.142 0.487-0.276l20.43-20.436c1.409-1.41 2.042-3.632 0.524-5.15v0z"></path>
      </symbol>
      <symbol id="icon-del" viewbox="0 0 32 32">
       <title>delete</title>
       <path class="path1" d="m11.355 4.129v-2.065h9.29v2.065h-9.29zm6.194 29.935v-23.742h19.613v23.742h-19.613zm30.968 4.129h-8.258v-3.097c0-0.569-0.463-1.032-1.032-1.032h-11.355c-0.569 0-1.032 0.463-1.032 1.032v3.097h-8.258c-0.569 0-1.032 0.463-1.032 1.032s0.463 1.032 1.032 1.032h3.097v24.774c0 0.569 0.463 1.032 1.032 1.032h21.677c0.569 0 1.032-0.463 1.032-1.032v-24.774h3.097c0.569 0 1.032-0.463 1.032-1.032s-0.463-1.032-1.032-1.032v0z"></path>
       <path class="path2" d="m10.323 9.806c-0.569 0-1.032 0.463-1.032 1.032v14.452c0 0.569 0.463 1.032 1.032 1.032s1.032-0.463 1.032-1.032v-14.452c0-0.569-0.463-1.032-1.032-1.032z"></path>
       <path class="path3" d="m16 9.806c-0.569 0-1.032 0.463-1.032 1.032v14.452c0 0.569 0.463 1.032 1.032 1.032s1.032-0.463 1.032-1.032v-14.452c0-0.569-0.463-1.032-1.032-1.032z"></path>
       <path class="path4" d="m21.677 9.806c-0.569 0-1.032 0.463-1.032 1.032v14.452c0 0.569 0.463 1.032 1.032 1.032s1.032-0.463 1.032-1.032v-14.452c0-0.569-0.463-1.032-1.032-1.032z"></path>
      </symbol>
      <symbol id="icon-clock" viewbox="0 0 32 32">
       <title>clock</title>
       <path class="path1" d="m29.333 16c0-7.364-5.97-13.333-13.333-13.333s-13.333 5.97-13.333 13.333c0 7.364 5.97 13.333 13.333 13.333s13.333-5.97 13.333-13.333v0 0 0 0 0 0zm0 16c0-8.837 7.163-16 16-16s16 7.163 16 16c0 8.837-7.163 16-16 16s-16-7.163-16-16zm14.667 14.667v1.333h2.667v-10.667h-2.667v9.333zm24 18.667h1.333v-2.667h-10.667v2.667h9.333z"></path>
      </symbol>
      <symbol id="icon-question" viewbox="0 0 32 32">
       <title>question</title>
       <path class="path1" d="m16 2.56c7.411 0 13.44 6.029 13.44 13.44s-6.029 13.44-13.44 13.44c-7.411 0-13.44-6.029-13.44-13.44s6.029-13.44 13.44-13.44zm16 0c-8.822 0-16 7.178-16 16s7.178 16 16 16c8.822 0 16-7.178 16-16s-7.178-16-16-16z"></path>
       <path class="path2" d="m16 22.080c-1.059 0-1.92 0.861-1.92 1.92s0.861 1.92 1.92 1.92c1.059 0 1.92-0.861 1.92-1.92s-0.861-1.92-1.92-1.92z"></path>
       <path class="path3" d="m12.16 12.48c0.706 0 1.28-0.574 1.28-1.28 0-1.412 1.148-2.56 2.56-2.56s2.56 1.148 2.56 2.56c0 1.412-1.148 2.56-2.56 2.56-0.706 0-1.28 0.574-1.28 1.28v3.84c0 0.706 0.574 1.28 1.28 1.28s1.28-0.574 1.28-1.28v-2.723c2.224-0.575 3.84-2.616 3.84-4.957 0-2.823-2.297-5.12-5.12-5.12s-5.12 2.297-5.12 5.12c0 0.706 0.574 1.28 1.28 1.28z"></path>
      </symbol>
     </defs>
    </svg>
    <div class="container">
     <div class="checkout-addr">
      <div class="page-title-normal">
       <h2 class="page-title-h2"><span>check out</span></h2>
      </div>
      <!-- process step -->
      <div class="check-step">
       <ul>
        <li class="cur"><span>confirm</span> address</li>
        <li><span>view your</span> order</li>
        <li><span>make</span> payment</li>
        <li><span>order</span> confirmation</li>
       </ul>
      </div>
 
      <!-- address list -->
      <div class="page-title-normal checkout-title">
       <h2><span>shipping address</span></h2>
      </div>
      <div class="addr-list-wrap">
       <div class="addr-list">
        <ul>
         <li v-for="(item,index) in addresslistfilter" :key="index" v-bind:class="{'check':checkindex==index}" @click="checkindex=index;selectedaddrid=item.addressid">
          <dl>
           <dt>{{item.username}}</dt>
           <dd class="address">{{item.streetname}}</dd>
           <dd class="tel">{{item.tel}}</dd>
          </dl>
          <div class="addr-opration addr-del">
           <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="addr-del-btn" @click="deladdressconfirm(item.addressid)">
            <svg class="icon icon-del"><use xlink:href="#icon-del" rel="external nofollow" ></use></svg>
           </a>
          </div>
          <div class="addr-opration addr-set-default">
           <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="addr-set-default-btn" v-if="!item.isdefault" @click="setdefault(item.addressid)"><i>set default</i></a>
          </div>
          <div class="addr-opration addr-default" v-if="item.isdefault">default address</div>
         </li>
         <li class="addr-new">
          <div class="add-new-inner">
           <i class="icon-add">
            <svg class="icon icon-add"><use xlink:href="#icon-add" rel="external nofollow" ></use></svg>
           </i>
           <p>add new address</p>
          </div>
         </li>
        </ul>
       </div>
 
       <div class="shipping-addr-more">
        <a class="addr-more-btn up-down-btn" href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="expand" v-bind:class="{'open':limit>3}">
         more
         <i class="i-up-down">
          <i class="i-up-down-l"></i>
          <i class="i-up-down-r"></i>
         </i>
        </a>
       </div>
      </div>
 
      <!-- shipping method-->
      <div class="page-title-normal checkout-title">
       <h2><span>shipping method</span></h2>
      </div>
      <div class="shipping-method-wrap">
       <div class="shipping-method">
        <ul>
         <li class="check">
          <div class="name">standard shipping</div>
          <div class="price">free</div>
          <div class="shipping-tips">
           <p>once shipped,order should arrive in the destination in 1-7 business days</p>
          </div>
         </li>
        </ul>
       </div>
      </div>
      <div class="next-btn-wrap">
       <router-link class="btn btn--m btn--red" v-bind:to="{path:'orderconfirm',query:{'addressid':selectedaddrid}}">next</router-link>
      </div>
     </div>
    </div>
   </div>
   <modal :mdshow="ismdshow" @close="closemodal">
    <p slot="message">
     您是否确认要删除此地址?
    </p>
    <div slot="btngroup">
      <a class="btn btn--m" href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="deladdress">确认</a>
      <a class="btn btn--m btn--red" href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="ismdshow=false">取消</a>
    </div>
   </modal>
   <nav-footer></nav-footer>
  </div>
</template>
<style>
</style>
<script>
 import navheader from './../components/navheader'
 import navfooter from './../components/navfooter'
 import navbread from './../components/navbread'
 import modal from './../components/modal'
 import {currency} from './../util/currency'
 import axios from 'axios'
 export default{
   data(){
     return{
       limit:3,
       checkindex:0, // 默认选中第一个地址
       selectedaddrid:'',
       addresslist:[],
       ismdshow:false,
       addressid:''
     }
   },
   mounted(){
     this.init();
   },
   computed:{
    addresslistfilter(){ // 动态计算,默认显示3条地址数据
     return this.addresslist.slice(0,this.limit); // 默认显示3条数据
    }
   },
  components:{
    navheader,
    navfooter,
    navbread,
    modal
   },
   methods:{
     init(){
       axios.get("/users/addresslist").then((response)=>{ // 获取用户地址列表
         let res = response.data;
         this.addresslist = res.result;
         this.selectedaddrid = this.addresslist[0].addressid;
         for(var i=0;i<this.addresslist.length;i++){
           if(this.addresslist[i].isdefault){
             this.checkindex = i;
           }
         }
       });
     },
     expand(){ // 展开和收起地址列表
       if(this.limit==3){
        this.limit = this.addresslist.length;
       }else{
        this.limit = 3;
       }
     },
     setdefault(addressid){ // 设置默认地址
       axios.post("/users/setdefault",{
        addressid:addressid
       }).then((response)=>{
         let res = response.data;
         if(res.status=='0'){
           console.log("set default");
           this.init();
         }
       })
     },
     closemodal(){ // 管理删除地址提示弹框
       this.ismdshow = false;
     },
     deladdressconfirm(addressid){ // 弹出模态框 选中删除的地址
      this.ismdshow = true;
      this.addressid = addressid;
     },
     deladdress(){ // 删除该地址
      axios.post("/users/deladdress",{
       addressid:this.addressid
      }).then((response)=>{
        let res = response.data;
        if(res.status=="0"){
         console.log("del suc");
         this.ismdshow = false;
         this.init();
        }
      })
     }
   }
 }
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。