一起来看vue3让前端飞

【vue3.0】22.0 某东到家( 廿二)——订单商品列表代码

2021-11-29  本文已影响0人  bobokaka

目前src\views\orderConfirmation\OrderConfirmation.vue已有超过250行代码。这里将此组件进行拆分。
src\views\orderConfirmation\TopArea.vue

<template>
  <div class="top">
    <div class="top__bgcolor" />
    <div class="top__header">
      <div class="top__header__back" @click="handleBackClick">
        <i class="custom-icon custom-icon-back"></i>
      </div>
      <span>确认订单</span>
    </div>
    <div class="top__receiver">
      <div class="top__receiver__title">收货地址</div>
      <div class="top__receiver__address">
        西安一二三大学四五六科技园2号楼
      </div>
      <div class="top__receiver__info">
        <span class="top__receiver__info__name">张三(先生)</span>
        <span class="top__receiver__info__phone">18012341234</span>
      </div>
      <div class="top__receiver__icon">
        <i class="custom-icon custom-icon-back"></i>
      </div>
    </div>
  </div>
</template>
<script>
import { useRouter } from 'vue-router' // 路由跳转方法
export default {
  name: 'TopArea',
  setup() {
    const router = useRouter()
    const handleBackClick = () => {
      router.back()
    }

    return {
      handleBackClick
    }
  }
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
.top {
  position: relative;
  height: 1.96rem;
  background-size: 100% 1.59rem;
  /* 渐变轴为0度,相当于从下到上,
   高度4%位置从rgba(0, 145, 255, 0) 开始渐变
   到高度50%位置的蓝色(#0091ff)结束 */
  background-image: linear-gradient(
    0deg,
    rgba(0, 145, 255, 0) 4%,
    $btn-bg-color 50%
  );
  background-repeat: no-repeat;

  &__header {
    position: relative;
    padding-top: 0.26rem;
    line-height: 0.24rem;
    color: $bg-color;
    text-align: center;
    font-size: 0.16rem;
    &__back {
      position: absolute;
      font-size: 0.22rem;
      left: 0.18rem;
    }
  }
  &__receiver {
    position: absolute;
    left: 0.18rem;
    right: 0.18rem;
    bottom: 0rem;
    height: 1.11rem;
    background: $bg-color;
    border-radius: 0.04rem;
    &__title {
      line-height: 0.22rem;
      padding: 0.16rem 0 0.14rem 0.16rem;
      font-size: 0.16rem;
      color: $content-font-color;
    }
    &__address {
      line-height: 0.2rem;
      padding: 0 0.4rem 0 0.16rem;
      font-size: 0.16rem;
      color: $content-font-color;
    }
    &__info {
      padding: 0.06rem 0 0 0.16rem;
      &__name &__phone {
        margin-right: 0.1rem;
        line-height: 0.18rem;
        font-size: 0.12rem;
        color: $content-font-color;
      }
    }
    &__icon {
      //旋转180度
      transform: rotate(180deg);
      position: absolute;
      right: 0.16rem;
      top: 0.53rem;
      font-size: 0.16rem;
      color: $medium-font-color;
    }
  }
}
</style>

新建src\views\orderConfirmation\ProductList.vue

<template>
  <div class="products">
    <div class="products__title">{{ shopName }}</div>
    <div class="products__wrapper">
      <div class="products__list">
        <template v-for="item in productList" :key="item._id">
          <div class="products__item" v-if="item.count > 0">
            <img class="products__item__img" :src="item.imgUrl" />
            <div class="products__item__detail">
              <h4 class="products__item__title">{{ item.name }}</h4>
              <p class="products__item__price">
                <span>
                  <span class="products__item__yen"> &yen; </span>
                  {{ item.price }}×{{ item.count }}
                </span>
                <span class="products__item__total">
                  <span class="products__item__yen"> &yen; </span>
                  {{ (item.price * item.count).toFixed(2) }}
                </span>
              </p>
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>
</template>
<script>
import { useCommonCartEffect } from '@/effects/cartEffects'
import { useRoute } from 'vue-router' // 路由跳转方法
export default {
  name: 'ProductList',
  setup() {
    const route = useRoute()
    const shopId = route.params.shopId // 店铺id
    const { shopName, productList } = useCommonCartEffect(shopId)

    return {
      shopName,
      productList,
    }
  },
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
@import '@/style/mixins.scss';
.products {
  margin: 0.16rem 0.18rem 0.2rem 0.18rem;
  background: $bg-color;
  &__title {
    padding: 0.16rem;
    font-size: 0.16rem;
    color: $content-font-color;
  }
  // list外层的wrapper容器
  &__wrapper {
    overflow-y: scroll;
    position: absolute;
    margin: 0 0.18rem;
    left: 0;
    right: 0;
    bottom: 0.6rem;
    top: 2.6rem;
  }
  &__list {
    background: $bg-color;
  }
  &__item {
    position: relative;
    display: flex;
    padding: 0 0.16rem 0.16rem 0.16rem;
    &__img {
      width: 0.46rem;
      height: 0.46rem;
      margin-right: 0.16rem;
    }
    // 配合解决超出长度以省略号显示而不会出现换行
    &__detail {
      overflow: hidden;
      flex: 1;
    }

    &__title {
      margin: 0;
      line-height: 0.2rem;
      font-size: 0.14rem;
      color: $content-font-color;
      // 超出长度以省略号显示而不会出现换行
      @include ellipsis;
    }
    &__price {
      display: flex;
      margin: 0.06rem 0 0 0;
      line-height: 0.2rem;
      font-size: 0.14rem;
      color: $height-light-font-color;
    }
    &__total {
      text-align: right;
      color: $dark-font-color;
      flex: 1;
    }
    &__yen {
      font-size: 0.12rem;
    }
  }
}
</style>

新增src\views\orderConfirmation\Order.vue

<template>
  <div class="order">
    <div class="order__price">
      实付金额 &yen;<b>{{ calculations.totalPrice }}</b>
    </div>
    <div class="order__btn">
      <!-- <router-link :to="{ path: `/orderConfirmation/${shopId}` }"> -->
      提交订单
      <!-- </router-link> -->
    </div>
  </div>
</template>
<script>
// import { ref } from 'vue'
import { useCommonCartEffect } from '@/effects/cartEffects'
import { useRoute } from 'vue-router' // 路由跳转方法

export default {
  name: 'Order',
  setup() {
    const route = useRoute()
    const shopId = route.params.shopId // 店铺id
    const { calculations } = useCommonCartEffect(shopId)

    return { calculations }
  },
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
.order {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  box-sizing: border-box; //往内塞入border
  line-height: 0.49rem;
  height: 0.49rem;
  border-top: 0.01rem solid $content-bg-color;
  background: $bg-color;
  &__price {
    flex: 1;
    text-indent: 0.24rem;
    font-size: 0.14rem;
    color: $content-font-color;
  }
  &__btn {
    width: 0.98rem;
    background-color: #4fb0f9;
    text-align: center;
    color: $bg-color;
    font-size: 0.14rem;
    // 去掉a标签的下划线
    a {
      color: $bg-color;
      text-decoration: none; //去掉文本修饰
    }
  }
}
</style>

修改src\views\orderConfirmation\OrderConfirmation.vue

<template>
  <div class="wrapper">
    <top-area />
    <product-list />
    <order />
  </div>
</template>

<script>
// import { ref } from 'vue'
import TopArea from '@/views/orderConfirmation/TopArea'
import ProductList from '@/views/orderConfirmation/ProductList'
import Order from '@/views/orderConfirmation/Order'
export default {
  name: 'OrderConfirmation',
  components: { TopArea, ProductList, Order },
}
</script>
<style lang="scss" scoped>
.wrapper {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: #eee;
  overflow-y: scroll; //防止超出屏幕
}
</style>

最终效果一致。

增加一个确认支付的弹窗

修改src\views\orderConfirmation\Order.vue

<template>
  <div class="order">
......
  </div>
  <div class="mask">
    <div class="mask__content">
      <div class="mask__content__title">确认离开收银台</div>
      <p>请尽快完成支付,否则将被取消</p>
      <div>
        <div class="mask__content__btn">取消订单</div>
        <div class="mask__content__btn">确认支付</div>
      </div>
    </div>
  </div>
</template>
<script>
......
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
.order {
......
}
.mask {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  z-index: 1;
  background: rgba(0, 0, 0, 0.5);
  &__content {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 3rem;
    height: 1.56rem;
    transform: translate(-50%, -50%);
    background: #fff;
    border-radius: 0.04rem;
    &__title {
      margin: 0.24rem 0 0 0;
      font-size: 0.18rem;
      color: #333;
      text-align: center;
    }
  }
}
</style>

image.png

进一步完善样式:

<template>
  <div class="order">
......
  </div>
  <div class="mask">
    <div class="mask__content">
      <div class="mask__content__title">确认离开收银台</div>
      <p>请尽快完成支付,否则将被取消</p>
      <div class="mask__content__btns">
        <div class="mask__content__btn mask__content__btn--first">取消订单</div>
        <div class="mask__content__btn mask__content__btn--second">
          确认支付
        </div>
      </div>
    </div>
  </div>
</template>
<script>
......
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
.order {
......
}
.mask {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  z-index: 1;
  background: rgba(0, 0, 0, 0.5);
  &__content {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 3rem;
    height: 1.56rem;
    transform: translate(-50%, -50%);
    background: #fff;
    border-radius: 0.04rem;
    text-align: center;
    &__title {
      margin: 0.24rem 0 0 0;
      font-size: 0.18rem;
      color: #333;
    }
    &__desc {
      margin: 0.08rem 0 0 0;
      font-size: 0.14rem;
      color: #666;
    }
    &__btns {
      display: flex;
      margin: 0.24rem 0.58rem;
    }
    &__btn {
      flex: 1;
      width: 0.8rem;
      line-height: 0.32rem;
      border: 0.01rem solid #4fb0f9;
      border-radius: 0.16rem;
      font-size: 0.14rem;
      &--first {
        margin-right: 0.12rem;
        color: #4fb0f9;
      }
      &--second {
        margin-left: 0.12rem;
        color: #fff;
        background: #4fb0f9;
      }
    }
  }
}
</style>

image.png
完善按钮逻辑,进入fastmock增加一个post接口/api/createOrder
    /**
     * 输入
     * conten-type:json
     * body:{
       addressId:“xxx”//收货地址 id
       shopId:""//商店id
       shopName:"某什么码1",
       isCanceled:false,//订单是否被取消了
       products:[
       {
         id:"xxx",//商品id
         num:6//商品数量
       }, 
       {
         id:"xxx",//商品id
         num:6//商品数量
       },
       ]
     }
     **/
    {
      "code": 200,
      "data": {   _id: '1',},
      "desc": "成功"
    }

修改src\views\orderConfirmation\Order.vue

<template>
  <div class="order">
......
  </div>
  <div class="mask">
    <div class="mask__content">
      <div class="mask__content__title">确认离开收银台</div>
      <p>请尽快完成支付,否则将被取消</p>
      <div class="mask__content__btns">
        <div
          class="mask__content__btn mask__content__btn--first"
          @click="handleCancelOrder"
        >
          取消订单
        </div>
        <div
          class="mask__content__btn mask__content__btn--second"
          @click="handleConfirmOrder"
        >
          确认支付
        </div>
      </div>
    </div>
    <Toast v-if="show" :message="message" />
  </div>
</template>
<script>
// import { ref } from 'vue'
import { useCommonCartEffect } from '@/effects/cartEffects'
import { useRoute, useRouter } from 'vue-router' // 路由跳转方法
import { post } from '@/utils/request'
import Toast, { useToastEffect } from '@/components/Toast/Toast'
export default {
  name: 'Order',
  components: {
    Toast,
  },
  setup() {
    const route = useRoute()
    // 获取路由实例
    const router = useRouter()
    const shopId = route.params.shopId // 店铺id
    const { shopName, calculations, productList } = useCommonCartEffect(shopId)
    const handleCancelOrder = () => {}

    const { show, message, toastMsg } = useToastEffect()
    const handleConfirmOrder = async () => {
      try {
        console.log('productList:')
        console.log(productList)
        const products = []
        for (const i in productList.value) {
          const product = productList.value[i]
          products.push({ id: product._id, num: product.count })
        }
        console.log('products:')
        console.log(products)
        const resultData = await post('/api/createOrder', {
          addressId: 'xxx', // 收货地址 id
          shopId: shopId, // 商店id
          shopName: shopName.value,
          isCanceled: false, // 订单是否被取消了
          products: products,
        })
        console.log('post /api/createOrder:')
        console.log(resultData)
        if (resultData?.code === 200) {
          router.push({ name: 'Home' })
        } else {
          toastMsg('订单提交失败!')
        }
      } catch (e) {
        toastMsg('请求失败!')
      }
    }
    return {
      show,
      message,
      calculations,
      handleCancelOrder,
      handleConfirmOrder,
    }
  },
}
</script>
<style lang="scss" scoped>
......
</style>

上一篇下一篇

猜你喜欢

热点阅读