(七)Vue项目——微商城:收货地址,实现新增+修改+删除

目录

收货地址页面

新增收货地址

v-distpicker地区选择器

保存收货地址

显示收货地址列表

修改收货地址

删除收货地址

从购物车下订单

创建订单页面

显示默认收货地址

选择其他收货地址

创建订单

查看订单列表

查看订单详情

取消订单

从商品详情页下订单

恭喜你大功告成!!!


收货地址

收货地址页面

src\pages\User.vue

将原来的div改为router-link,并设置目标地址。

<router-link :to="{ name: 'address' }" class="mui-navigate-right">

  <img class="mui-media-object mui-pull-left" src="../assets/images/avatar_default.png">

  <div class="mui-media-body">收货地址</div>

</router-link>

src\router.js

import Address from './pages/user/Address.vue'

import AddressEdit from './pages/user/AddressEdit.vue'

routes: [

  ……(原有代码)

  { path: '/user/address', component: Address, name: 'address', meta: { title: '收货地址' } },

  { path: '/user/address/add', component: AddressEdit, name: 'address_add', meta: { title: '新增收货地址' } },

],

src\pages\user\Address.vue

<template>

  <div class="address-container">

    <div>收货地址列表</div>

    <div class="mod_btns fixed">

      <router-link :to="{ name: 'address_add' }" class="mod_btn">新增收货地址</router-link>

    </div>

  </div>

</template>

样式:

<style lang="scss" scoped>

.address-container {

  background: #eee;

  overflow: hidden;

  .mod_btn {

    font-size: 16px;

    line-height: 46px;

    height: 46px;

    text-align: center;

    background: #3884ff;

    flex: 1;

    display: block;

    color: #fff;

  }

  .mod_btns .fixed {

    display: flex;

    overflow: hidden;

  }

}

</style>

src\pages\user\AddressEdit.vue

<template>

  <div>新增收货地址</div>

</template>

访问测试。

新增收货地址

src\pages\user\AddressEdit.vue

<template>

  <form class="mui-input-group">

    <div class="mui-input-row">

      <label class="tit">收件人</label>

      <input v-model="form.name" type="text" class="mui-input-clear" placeholder="请输入收件人姓名">

    </div>

    <div class="mui-input-row">

      <label class="tit">联系方式</label>

      <input v-model="form.tel" type="text" class="mui-input-clear" placeholder="请输入手机号">

    </div>

    <div class="mui-input-row">

      <label class="tit">所在地区</label>

      <input v-model="form.area" type="text" class="mui-input-clear" placeholder="所在地区">

    </div>

    <div class="mui-input-row">

      <label class="tit">详细地址</label>

      <input v-model="form.detail" type="text" class="mui-input-clear" placeholder="请输入详细地址">

    </div>

    <div class="mui-button-row">

      <button @click="save" type="button" class="mui-btn mui-btn-primary mui-btn-block">确认</button>

    </div>

  </form>

</template>

逻辑:

<script>

export default {

  data () {

    return {

      form: {

        name: '',

        tel: '',

        area: '',

        detail: ''

      }

    }

  },

  methods: {

    save () {

      window.console.log('确认')

    }

  }

}

</script>

样式:

<style lang="scss" scoped>

  .mui-input-group .mui-button-row {

    height: auto;

  }

  .mui-input-clear {

    font-size: 14px;

  }

  .mui-input-group:before {

    list-style: none;

  }

  .mui-button-row {

    margin-top: 20px;

    button {

      margin: 20px 0;

      padding: 10px 0;

    }

  }

  .tit {

    color: #999;

  }

  input::-webkit-input-placeholder {

    color: #999;

  }

  input::-moz-placeholder {   /* Mozilla Firefox 19+ */

    color: #999;

  }

  input:-moz-placeholder {    /* Mozilla Firefox 4 to 18 */

    color: #999;

  }

  input:-ms-input-placeholder {  /* Internet Explorer 10-11 */

    color: #999;

  }

</style>

页面效果:

v-distpicker地区选择器

安装v-distpicker插件。

npm install v-distpicker@1.2 --save

src\pages\user\AddressEdit.vue

import VDistpicker from 'v-distpicker'

export default {

  ……(原有代码)

  components: {

    'v-distpicker': VDistpicker

  }

}

<label class="tit">所在地区</label>

<input v-model="form.area" type="text" class="mui-input-clear" placeholder="所在地区" @click="choose">

<div class="divwrap">

  <div class="mask" @click="choose" v-show="show"></div>

  <v-distpicker

    v-show="show"

    type="mobile"

    @province="onChangeProvince"

    @city="onChangeCity"

    @area="onChangeArea"

    :province="newInfo.province"

    :city="newInfo.city"

    :area="newInfo.district"

  >

  </v-distpicker>

</div>

数据

data () {

  return {

    ……(原有代码)

    show: false,     // 是否显示遮罩层

    newInfo: {

      province: '', //

      city: '',     //

      area: '',     //

    }

  }

}

方法:

methods: {

  ……(原有代码)

  choose () {

    this.show = !this.show

  },

  onChangeProvince (data) {

    this.newInfo.province = data.value

  },

  onChangeCity (data) {

    this.newInfo.city = data.value

  },

  onChangeArea (data) {

    this.newInfo.area = data.value

    this.form.area = this.newInfo.province + '-' + this.newInfo.city + '-' + this.newInfo.area

    this.show = false

  }

},

样式:

.divwrap > .mask {

  background: #000;

  opacity: 0.3;

  position: fixed;

  top: 0;

  bottom: 0;

  left: 0;

  right: 0;

}

.divwrap > .distpicker-address-wrapper {

  color: #999;

  background: #fff;

  border-top: 1px solid #ccc;

  z-index: 1;

  height: 300px;

  overflow-y: auto;

  position: fixed;

  left: 0;

  bottom: 0;

  width: 100%;

}

.divwrap >>> .address-header {

  position: fixed;

  bottom: 300px;

  width: 100%;

  background: #000;

  color: #fff;

}

.divwrap >>> .address-header ul li {

  flex-grow: 1;

  text-align: center;

}

.divwrap >>> .address-header .active {

  color: #fff;

  border-bottom: #666 solid 8px;

}

.divwrap >>> .address-container .active {

  color: #000;

}

页面效果:

保存收货地址

src\pages\user\AddressEdit.vue

save () {

  this.$indicator.open({

    text: '提交中'

  })

  this.$http.post('address/save', this.form).then(res => {

    this.$indicator.close()

    if (res.data.code === 0) {

    this.$toast(res.data.msg)

  } else if (res.data.code === 1) {

    this.$toast(res.data.msg)

    this.$router.go(-1)

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

  })

},

测试程序。

显示收货地址列表

src\pages\user\Address.vue

<script>

export default {

  created () {

    this.getAddressList()

  },

  methods: {

    getAddressList () {

      this.$indicator.open({

        text: '加载中'

      })

      this.$http.get('address').then(res => {

        this.$indicator.close()

         if (res.data.code === 1) {

    this.addressList = res.data.data

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

      })

    }

  }

}

</script>

data () {

  return {

    addressList: []

  }

},

在页面中显示出来

<div class="address-container">

  <div>

    <div class="mui-card" v-for="item in addressList" :key="item.id">

      <ul class="selected">

        <li class="title">

          <strong>{{ item.name }}</strong>&nbsp;

          <strong>{{ item.tel }}</strong>

        </li>

        <li>{{ item.area }} {{ item.detail }}</li>

        <li>

          <a class="edit">编辑</a>

        </li>

      </ul>

    </div>

  </div>

  ……(原有代码)

</div>

删掉:

<div>收货地址列表</div>

样式:

.address-container {

  background: #eee;

  overflow: hidden;

  ……(原有代码)

  .mui-card {

    padding: 7px 40px;

    position: relative;

    overflow: hidden;

    padding: 15px;

    color: #666;

    .selected {

      margin: 0;

      padding: 0;

      list-style: none;

      padding-right: 50px;

      .title {

        font-size: 16px;

      }

      .edit {

        color: #e93b3d;

        width: 50px;

        position: absolute;

        top: 50%;

        right: 0;

        transform: translateY(-50%);

      }

    }

  }

}

页面效果:

细节优化:

由于新增按钮显示在收货地址列表的下面,

在收货地址列表加载前后,新增按钮会发生上下跳动,

影响用户体验。

为了解决这个问题,可以在加载完成前,把按钮隐藏起来,

直到加载完成后,再显示新增按钮。

src\pages\user\Address.vue

this.$http.get('address').then(res => {

  this.$indicator.close()

  this.showAdd = true

  ……(原有代码)

})

data () {

  return {

    addressList: [],

    showAdd: false

  }

},

<div v-show="showAdd" class="mod_btns fixed">

  <router-link :to="{ name: 'address_add' }" class="mod_btn">新增收货地址</router-link>

</div>

修改收货地址

“编辑”按钮

src\pages\user\Address.vue

  <a class="edit">编辑</a>

改成:

<router-link class="edit" :to="{name: 'address_edit', params: {id: item.id}}">编辑</router-link>

商品收货地址的“修改”和“新增”其实是复用了同一个组件。

src\router.js

routes: [

  ……(原有代码)

  { path: '/user/address/edit/:id', component: AddressEdit, props: true, name: 'address_edit', meta: { title: '编辑收货地址' } },

],

在组件里通过是否传入参数id来区分当前是修改还是新增。

id是一个数字,表示待修改的记录的唯一标识。

接收一下路由传过来的id。

src\pages\user\AddressEdit.vue

props: ['id'],

created () {

  this.getAddress()

},

methods: {

  getAddress () {

    if (!this.id) {

      return

    }

    this.$indicator.open({

      text: '加载中'

    })

    var params = { id: this.id }

    this.$http.get('address/edit', { params: params }).then(res => {

      this.$indicator.close()

      window.console.log(res.data)

    })

  },

  ……(原有代码)

},

显示到页面中:

src\pages\user\AddressEdit.vue

this.$http.get('address/edit', { params: params }).then(res => {

  this.$indicator.close()

  if (res.data.code === 0) {

    this.$toast(res.data.msg)

  } else if (res.data.code === 1) {

    this.form = res.data.data

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

})

页面一打开后,就会把原有的数据显示出来。

然后修改save()方法,将id放入表单中。

save () {

  this.$indicator.open({

    text: '提交中'

  })

  this.form.id = this.id

  ……(原有代码)

}

测试程序,观察修改是否会生效。

删除收货地址

src\pages\user\AddressEdit.vue

<template>

  <form class="mui-input-group">

    ……(原有代码)

    <div class="mui-button-row">

      ……(原有代码)

      <button v-show="id" @click="del" type="button" class="mui-btn mui-btn-danger mui-btn-block">删除</button>

    </div>

  </form>

</template>

v-show的作用:只有传入了id参数的时候,显示“删除”按钮。

methods: {

  ……(原有代码)

  del () {

    this.$indicator.open({

      text: '删除中'

    })

    this.form.id = this.id

    this.$http.post('address/del', this.form).then(res => {

      this.$indicator.close()

      window.console.log(res.data)

    })

  }

},

处理服务器返回的结果。

src\pages\user\AddressEdit.vue

this.$http.post('address/del', this.form).then(res => {

  this.$indicator.close()

  if (res.data.code === 0) {

    this.$toast(res.data.msg)

  } else if (res.data.code === 1) {

    this.$toast(res.data.msg)

    this.$router.go(-1)

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

})

订单

从购物车下订单

从购物车选中要购买的商品,点击“去结算”,就会进入到下订单的页面。

src\pages\Shopcart.vue

<mt-button type="primary" @click="createOrder">去结算</mt-button>

src\pages\Shopcart.vue

methods: {

  ……(原有代码)

  createOrder () {

    if (this.goodslist.length === 0) {

      this.$toast('您的购物车为空')

      return

    }

    this.$store.commit('shopcart/setBuy')

  }

}

setBuy:用来将购物车中用户选中的商品设为要购买的商品。

将要购买的商品保存起来,方便在下订单的页面中进行读取展示。

src\store\modules\shopcart.js

const state = {

  car: getItem('car'),

  // 当前要购买的商品:buy: [{ id: '', count: '' }]

  // 当在购物车里点“去结算”时,就把购物车车中已经选中的商品放进去

  buy: getItem('buy')

}

const mutations = {

  ……(原有代码)

  setBuy (state) {

    state.buy = []

    state.car.some(item => {

      if (item.selected) {

        state.buy.push(item)

      }

    })

    setItem('buy', state.buy)

  }

}

跳转到创建订单的页面。

src\pages\Shopcart.vue

createOrder () {

  ……(原有代码)

  this.$router.push({ name: 'order_create' })

}

src\router.js

import OrderCreate from './pages/order/OrderCreate.vue'

routes: [

  ……(原有代码)

  { path: '/order/create', component: OrderCreate, name: 'order_create', meta: { title: '下订单' } },

],

创建文件:src\pages\order\OrderCreate.vue

<template>

  <div>创建订单</div>

</template>

创建订单页面

获取要购买的商品

src\pages\order\OrderCreate.vue

<script>

import { mapState } from 'vuex'

export default {

  computed: {

    ...mapState('shopcart', ['buy'])

  },

  created () {

    this.getGoodsList()

  },

  methods: {

    getGoodsList () {

      window.console.log(this.buy)

    }

  }

}

</script>

从购物车选中要购买的商品,点击“去结算”,到浏览器控制台查看运行结果:

 

可以看到当前要购买的商品数据。

为了显示到页面中,需要到服务器查询商品信息。

getGoodsList () {

  var idArr = []

  this.buy.forEach(item => idArr.push(item.id))

  if (idArr.length <= 0) {

    return

  }

  this.$indicator.open({

    text: '加载中'

  })

  var params = { ids: idArr }

  this.$http.get('shopcart', { params: params }).then(res => {

    this.$indicator.close()

    window.console.log(res.data)

  })

}

查看获取结果:

保存起来

this.$http.get('shopcart', { params: params }).then(res => {

  this.$indicator.close()

  if (res.data.code === 1) {

    this.goodslist = res.data.data

  }

})

保存到data中。

export default {

  data () {

    return {

      goodslist: []

    }

  },

  ……(原有代码)

}

计算订单总额

需要用每件商品的单价乘以购买件数。

为了方便根据id获取每件商品的购买件数,编写getBuy方法。

src\store\modules\shopcart.js

const getters = {

  ……(原有代码)

  // 获取要购买的商品

  getBuy (state) {

    var goods = {}

    state.buy.forEach(item => {

      goods[item.id] = item

    })

    return goods

  }

}

src\pages\order\OrderCreate.vue

import { mapGetters, mapState } from 'vuex'

computed: {

  ...mapState('shopcart', ['buy']),

  ...mapGetters('shopcart', ['getBuy'])

},

获取到商品数据以后,进行计算。

if (res.data.code === 1) {

  this.goodslist = res.data.data

  var amount = 0

  this.goodslist.forEach(item => {

    item.count = this.getBuy[item.id].count

    amount += item.count * item.price

  })

  this.amount = amount

}

保存到data中

data () {

  return {

    goodslist: [],

    amount: 0

  }

},

在页面中显示

<template>

  <div class="shopcart-container">

    <!-- 商品列表 -->

    <div class="goods-list">

      <!-- 商品列表项区域 -->

      <div class="mui-card">

        <div class="mui-card-content" v-for="(item) in goodslist" :key="item.id">

          <div class="mui-card-content-inner flex">

            <img :src="item.image">

            <div class="info">

              <h1>{{ item.name }}</h1>

              <p class="flex">

                <span class="price">¥{{ item.price }}</span>

                <span>x{{ item.count }}</span>

              </p>

            </div>

          </div>

        </div>

        <!-- 配送信息 -->

        <div class="process-info">

          <p>

            <strong>配送服务</strong>

            <strong>快递运输</strong>

          </p>

          <p>

            <span>中小件送货时间</span>

            <span>工作日、双休日与节假日均可送货</span>

          </p>

        </div>

        <!-- 订单备注 -->

        <div class="store-info">

          <strong>订单备注</strong>

          <textarea v-model="note" type="text" placeholder="选填,给商家留言"></textarea>

        </div>

      </div>

    </div>

    <!-- 运费信息 -->

    <ul class="fare-info mui-card">

      <li class="fare-price flex">

        <span>商品金额</span>

        <span class="red">¥{{ amount.toFixed(2) }}</span>

      </li>

      <li class="fare-price flex">

        <span>运费</span>

        <span class="red">¥0.00</span>

      </li>

      <li class="fare-price flex">

        <span><strong>总价</strong></span>

        <span class="red">¥{{ amount.toFixed(2) }}</span>

      </li>

      <!-- 创建订单按钮 -->

      <div class="flex">

        <button class="mui-btn mui-btn-primary mui-btn-block">创建订单</button>

      </div>

    </ul>

  </div>

</template>

订单备注:买家可以为订单添加备注信息,用来提醒卖家。

在data中保存订单备注。

data () {

  return {

    goodslist: [],

    amount: 0,

    note: ''

  }

},

样式代码:

<style lang="scss" scoped>

.flex {

    display: flex;

}

.shopcart-container {

  background: #eee;

  overflow: hidden;

  // 商品列表

  .goods-list {

    margin-top: 10px;

    .mui-card {

      margin: 0;

      .mui-card-content {

        border-bottom: 1px solid #eee;

        .mui-card-content-inner {

          align-items: center;

          padding: 10px;

          img {

            width: 60px;

          }

          .info {

            margin-left: 10px;

            box-sizing: border-box;

            width: 100%;

            overflow: hidden;

            h1 {

              font-size: 13px;

              font-weight: bold;

              line-height: 20px;

              padding-top: 22px;

            }

            p {

              flex-direction: row;

              align-items: center;

              justify-content: space-between;

              .price {

                font-size: 16px;

                font-weight: 700;

                color: red;

                flex: 1

              }

            }

          }

        }

      }

      // 配送信息

      .process-info {

        padding: 10px;

        border-bottom: 1px solid #eee;

        p {

          display: flex;

          flex-direction: row;

          align-items: center;

          justify-content: space-between;

          color: #333;

          span {

            color:#999

          }

        }

      }

       // 店铺备注

      .store-info {

        padding: 10px;

        textarea {

          font-size: 13px;

        }

      }

    }

  }

  // 运费信息

  .fare-info {

    padding: 10px;

    margin: 10px 0 0 0;

    .fare-price {

      padding: 5px 0;

      display: flex;

      justify-content: space-between;

      .red {

        color: red;

        font-size: 16px;

      }

    }

  }

}

</style>

页面效果:

显示默认收货地址

在创建订单时,显示用户的默认收货地址。

src\pages\order\OrderCreate.vue

先从收货地址列表中查出来一个地址,显示到页面中。

created () {

  this.getAddress(),

  this.getGoodsList()

},

methods: {

  ……(原有代码)

  getAddress () {

    this.$http.get('address/def').then(res => {

      window.console.log(res.data)

    })

  }

}

保存到data中。

src\pages\order\OrderCreate.vue

this.$http.get('address/def').then(res => {

  if (res.data.code === 0) {

    this.$toast(res.data.msg)

  } else if (res.data.code === 1) {

    if (res.data.data) {

      this.address = res.data.data

    } else {

      this.$toast('请先添加收货地址')

    }

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

})

data () {

  return {

    goodslist: [],

    amount: 0,

    note: '',

    address: {}

  }

},

在页面中显示。

<div class="shopcart-container">

  <!-- 收货地址区域 -->

  <div class="address-container">

    <div class="mui-card">

      <h3>{{ address.name }} {{ address.tel }}</h3>

      <p>{{ address.area }} {{ address.detail }}</p>

    </div>

  </div>

  ……(原有代码)

</div>

样式:

.shopcart-container {

  ……(原有代码)

  // 收货地址

  .address-container {

    .mui-card {

      margin: 0;

      padding: 10px;

      h3 {

        color: #333;

        font-size: 16px;

        font-weight: bold;

      }

    }

  }

}

运行结果:

选择其他收货地址

单击后跳转到选择收货地址页面。

src\pages\order\OrderCreate.vue

 ……(原有代码)

<router-link :to="{name: 'address_select'}">

  <h3>{{ address.name }} {{ address.tel }}</h3>

  <p>{{ address.area }} {{ address.detail }}</p>

</router-link>

 ……(原有代码)

选择收货地址页面,复用了收货地址列表组件。

src\router.js

routes: [

  ……(原有代码)

  { path: '/user/address/select', component: Address, name: 'address_select', meta: { title: '选择收货地址' } },

],

单击收货地址中的某一项时,表示选用该地址。

src\pages\user\Address.vue

<li class="title" @click="select(item.id)">

  <strong>{{ item.name }}</strong>&nbsp;

  <strong>{{ item.tel }}</strong>

</li>

<li @click="select(item.id)">{{ item.area }} {{ item.detail }}</li>

判断当前路由是否为address_select,如果是,则返回创建订单页面,并把id传过去。

methods: {

  ……(原有代码)

  select (id) {

    if (this.$route.name !== 'address_select') {

      return

    }

    this.$router.replace({ name: 'order_create', params: { id: id } })

  }

}

接收传过来的id。

src\pages\order\OrderCreate.vue

created () {

  if (this.$route.params.id) {

    this.addressId = this.$route.params.id

  }

  ……(原有代码)

},

保存到data

data () {

  return {

    goodslist: [],

    amount: 0,

    note: '',

    address: {},

    addressId: 0

  }

},

在请求默认收货地址的时候,把id传给服务器。

getAddress () {

  var params = { id:  this.addressId }

  this.$http.get('address/def', { params: params }).then(res => {

    ……(原有代码)

  })

},

访问测试。

添加多个收货地址,观察在创建订单的时候,是否可以进行切换。

并且如果用户新增或编辑了收货地址,仍然可以正确选择收货地址。

细节优化:

为了避免选择收货地址后,用户点后退,需要点多次的问题,

在跳转收货地址页面的时候,使用replace的方式,表示直接替换当前页面。

src\pages\order\OrderCreate.vue

<router-link :to="{name: 'address_select'}" replace>

  <h3>{{ address.name }} {{ address.tel }}</h3>

  <p>{{ address.area }} {{ address.detail }}</p>

</router-link>

细节优化:

当用户当前没有添加任何收货地址的时候,自动跳转到收货地址页面,

要求用户进行添加。

在添加以后,当没有选择收货地址的时候,this.addressId为0,

这时候应该把服务器返回的收货地址id保存起来,

因为后面在提交订单的时候,会用到这个收货地址id。

if (res.data.data) {

  this.address = res.data.data

  this.addressId = res.data.data.id

} else {

  this.$toast('请先添加收货地址')

  this.$router.replace({ name: 'address_select' })

}

创建订单

src\pages\order\OrderCreate.vue

<button class="mui-btn mui-btn-primary mui-btn-block" @click="order">创建订单</button>

编写order()方法

methods: {

  ……(原有代码)

  order () {

    var form = {

      address: this.addressId,

      goods: this.buy,

      note: this.note

    }

    this.$indicator.open({

      text: '创建订单中'

    })

    this.$http.post('order/create', form).then(res => {

      this.$indicator.close()

      window.console.log(res.data)

    })

  }

}

点创建订单,控制台查看测试结果。

最后,在创建订单成功后,跳转到订单列表页面。

this.$http.post('order/create', form).then(res => {

  this.$indicator.close()

  if (res.data.code === 0) {

    this.$toast(res.data.msg)

  } else if (res.data.code === 1) {

    this.$toast(res.data.msg)

    this.$router.replace({ name: 'order_list' })

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

})

使用replace()方法,这样可以禁止返回到创建订单前的页面,防止重复创建。

创建路由:

src\router.js

import OrderList from './pages/order/OrderList.vue'

routes: [

  ……(原有代码)

  { path: '/order/list', component: OrderList, name: 'order_list', meta: { title: '我的订单' } },

],

src\pages\order\OrderList.vue

<template>

  <div>订单列表</div>

</template>

查看订单列表

src\pages\User.vue

<router-link :to="{ name: 'order_list' }" class="mui-navigate-right">

  <img class="mui-media-object mui-pull-left" src="../assets/images/avatar_default.png">

  <div class="mui-media-body">我的订单</div>

</router-link>

src\pages\order\OrderList.vue

<script>

export default {

  created () {

    this.getOrderList()

  },

  methods: {

    getOrderList () {

      this.$indicator.open({

        text: '加载中'

      })

      this.$http.get('order/list').then(res => {

        this.$indicator.close()

        window.console.log(res.data)

      })

    }

  }

}

</script>

输出到页面中。

src\pages\order\OrderList.vue

this.$http.get('order/list').then(res => {

  this.$indicator.close()

  if (res.data.code === 0) {

    this.$toast(res.data.msg)

  } else if (res.data.code === 1) {

    if (res.data.data.length) {

      this.orderlist = res.data.data

    } else {

      this.$toast('订单为空')

    }

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

})

在data中定义数据

export default {

  data () {

    return {

      orderlist: []

    }

  },

  ……(原有代码)

}

在页面中输出。

<template>

  <div class="pay-list">

    <div class="mui-card" v-for="order in orderlist" :key="order.id">

      <div class="mui-card-header">

        <span class="title">{{ order.create_time }}</span>

        <span>

          <span v-if="order.is_pay">已支付</span><span v-else>未支付</span> |

          <span v-if="order.is_cancel">已取消</span>

          <span v-else>取消订单</span>

        </span>

      </div>

      <div class="mui-card-content">

        <div class="mui-card-content-inner" >

          <div class="cover" v-for="item in order.user_order_goods" :key="item.id">

            <div class="img-con">

              <img :src="item.goods_goods.image">

            </div>

            <div class="img-tag">x{{ item.count }}</div>

          </div>

        </div>

      </div>

      <p>实付金额:<span>¥{{ order.price }}</span></p>

    </div>

  </div>

</template>

样式:

<style lang="scss" scoped>

.pay-list p {

  padding: 0 10px;

  text-align: right;

  span {

    color: #151515;

  }

}

.mui-card-header {

  color:#999;

  font-size: 13px;

  span.title {

    font-size: 13px;

    color: #888;

  }

}

.mui-card-content-inner {

  .cover {

    position: relative;

    width: 70px;

    height: 70px;

    display: inline-block;

    margin-right: 10px;

    .img-con {

      width: 100%;

      height: 100%;

      margin-right: 10px;

      border-radius: 2px;

      position: relative;

      img {

        width: 100%;

        height: 100%;

        border-radius: 2px;

        position: absolute;

        left: 50%;

        top: 50%;

        transform: translate3d(-50%,-50%,0);

      }

    }

    .img-tag {

      position: absolute;

      opacity: .5;

      background: #000;

      color: #fff;

      text-align: center;

      font-size: 12px;

      right: 0;

      bottom: 0;

      padding: 0 5px;

      border-radius: 2px 0;

    }

  }

}

</style>

页面效果:

查看订单详情

src\pages\order\OrderList.vue

<div @click="show(order.id)" class="mui-card-content">

  ……

</div>

编写show()方法

methods: {

  ……(原有代码)

  show (id) {

    this.$router.push({ name: 'order_show', params: { id: id } });

  }

}

定义路由:

src\router.js

import OrderShow from './pages/order/OrderShow.vue'

routes: [

  ……

  { path: '/order/show/:id', component: OrderShow, props: true, name: 'order_show', meta: { title: '查看订单' } }

],

src\pages\order\OrderShow.vue

<template>

  <div>查看订单</div>

</template>

测试一下页面是否可以正确跳转。

加载数据

<script>

export default {

  props: ['id'],

  created () {

    this.getOrder()

  },

  methods: {

    getOrder () {

      this.$indicator.open({

        text: '加载中'

      })

      this.$http.get('order/show', {id: this.$props.id}).then(res => {

        this.$indicator.close()

        window.console.log(res.data)

      })

    }

  }

}

</script>

接收服务器返回的数据。

src\pages\order\OrderShow.vue

this.$http.get('order/show', { id: this.$props.id }).then(res => {

  this.$indicator.close()

  if (res.data.code === 0) {

    this.$toast(res.data.msg)

  } else if (res.data.code === 1) {

    this.order = res.data.data

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

})

保存到data中。

export default {

  data () {

    return {

      order: {}

    }

  },

  ……(原有代码)

}

在页面中显示。

<template>

  <div class="shopcart-container">

    <!-- 商品列表 -->

    <div class="goods-list">

      <!-- 商品列表项区域 -->

      <div class="mui-card">

        <div class="mui-card-content" v-for="(item) in order.user_order_goods" :key="item.id">

          <div class="mui-card-content-inner flex">

            <img :src="item.goods_goods.image">

            <div class="info">

              <h1>{{ item.goods_goods.name }}</h1>

              <p class="flex">

                <span class="price">¥{{ item.price }}</span>

                <span>x{{ item.count }}</span>

              </p>

            </div>

          </div>

        </div>

        <!-- 订单备注 -->

        <div class="process-info">

          <p><strong>订单备注</strong></p>

          <p><span>{{ order.note }}</span></p>

        </div>

        <!-- 配送信息 -->

        <div class="process-info">

          <p>

            <strong>配送服务</strong>

            <strong>快递运输</strong>

          </p>

          <p>

            <span>中小件送货时间</span>

            <span>工作日、双休日与节假日均可送货</span>

          </p>

        </div>

        <!-- 收货地址 -->

        <div class="process-info">

          <p><strong>收货地址</strong></p>

          <p><span>{{ order.address_name }} {{ order.address_tel }}</span></p>

          <p><span>{{ order.address_area }} {{ order.address_detail }}</span></p>

        </div>

      </div>

    </div>

    <!-- 运费信息 -->

    <ul class="fare-info mui-card">

      <li class="fare-price flex">

        <span>商品金额</span>

        <span class="red">¥{{ order.price }}</span>

      </li>

      <li class="fare-price flex">

        <span>运费</span>

        <span class="red">¥0.00</span>

      </li>

      <li class="fare-price flex">

        <span><strong>总价</strong></span>

        <span class="red">¥{{ order.price }}</span>

      </li>

      <!-- 去支付按钮 -->

      <div v-if="order.id && !order.is_cancel" class="flex">

        <button class="mui-btn mui-btn-primary mui-btn-block">去支付</button>

      </div>

    </ul>

  </div>

</template>

页面样式。

<style lang="scss" scoped>

.flex {

  display: flex;

}

.shopcart-container {

  background: #eee;

  overflow: hidden;

  // 商品列表

  .goods-list {

    margin-top: 10px;

    .mui-card {

      margin: 0;

      .mui-card-content {

        border-bottom: 1px solid #eee;

        .mui-card-content-inner {

          align-items: center;

          padding: 10px;

          img {

            width: 60px;

          }

          .info {

            margin-left: 10px;

            box-sizing: border-box;

            width: 100%;

            overflow: hidden;

            h1 {

              font-size: 13px;

              font-weight: bold;

              line-height: 20px;

              padding-top: 22px;

            }

            p {

              flex-direction: row;

              align-items: center;

              justify-content: space-between;

              .price {

                font-size: 16px;

                font-weight: 700;

                color: red;

                flex: 1

              }

            }

          }

        }

      }

      // 配送信息

      .process-info {

        padding: 10px;

        border-bottom: 1px solid #eee;

        p {

          display: flex;

          flex-direction: row;

          align-items: center;

          justify-content: space-between;

          color: #333;

          span {

            color: #999

          }

        }

      }

    }

  }

  // 运费信息

  .fare-info {

    padding: 10px;

    margin: 10px 0 0 0;

    .fare-price {

      padding: 5px 0;

      display: flex;

      justify-content: space-between;

      .red {

        color: red;

        font-size: 16px;

      }

    }

  }

}

</style>

页面效果:

取消订单

src\pages\order\OrderList.vue

<span v-else @click="cancel(order.id)">取消订单</span>

methods: {

  ……(原有代码)

  cancel (id) {

    this.$indicator.open({

      text: '取消中'

    })

    this.$http.post('order/cancel', {id: id}).then(res => {

      this.$indicator.close()

      window.console.log(res.data)

    })

  }

}

在成功取消订单以后,重新加载订单列表。

src\pages\order\OrderList.vue

this.$http.post('order/cancel', {id: id}).then(res => {

  this.$indicator.close()

  if (res.data.code === 0) {

    this.$toast(res.data.msg)

  } else if (res.data.code === 1) {

    this.getOrderList()

  } else if (res.data.code === 2) {

    this.$router.push({ name: 'login' })

  }

})

测试程序。

单击“取消订单”,会变成“已取消”。

从商品详情页下订单

在商品详情页中查看商品时,如果单击“立即购买”,

也可以创建订单,

这个时候订单中只包含当前的这一件商品。

src\pages\goods\GoodsInfo.vue

<mt-button type="primary" size="small" @click="buy">立即购买</mt-button>

单击之后跳转到创建订单的页面。

methods: {

  ……(原有代码)

  buy () {

    this.$router.push({ name: 'order_create' })

  }

}

在单击立即购买之后,应该将当前商品设为要购买的商品。

在src\store\modules\shopcart.js中修改setBuy方法,通过参数传入要设置的商品。

setBuy (state, goods) {

  state.buy = []

  if (goods) {

    state.buy.push(goods)

  } else {

    state.car.some(item => {

      if (item.selected) {

        state.buy.push(item)

      }

    })

  }

  setItem('buy', state.buy)

},

在跳转前,将当前商品设为要购买的商品。

src\pages\goods\GoodsInfo.vue

buy () {

  this.$store.commit('shopcart/setBuy', { id: this.$props.id, count: this.selectedCount  })

  this.$router.push({ name: 'order_create' })

}

测试程序。

恭喜你大功告成!!

关注我~~

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值