美文网首页一起来看vue3让前端飞
【vue3.0】22.0 某东到家( 廿二)——订单商品列表代码

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

作者: bobokaka | 来源:发表于2021-11-29 17:22 被阅读0次

    目前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>
    
    

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/nohlxrtx.html