Vue3电商项目实战-个人中心模块7【16-订单详情-steps组件、17-订单详情-物流信息】


16-订单详情-steps组件

目的:封装一个高可用的步骤条组件

在这里插入图片描述

大致步骤:

  • xtx-steps 封装一个静态步骤条
  • xtx-steps-item 封装步骤条-条目
  • xtx-steps 组织组件结构
  • xtx-steps 设置激活步骤
  • 使用steps组件显示订单进度

落的代码:

1.xtx-steps 封装一个静态步骤条

<template>
  <div class="xtx-steps">
    <div class="xtx-steps-item active" v-for="i in 5" :key="i">
      <div class="step"><span>{
   
   {i}}</span></div>
      <div class="title">提交订单</div>
      <div class="desc">2021-03-18 02:11:47</div>
    </div>
  </div>
</template>
<script>
export default {
      
      
  name: 'XtxSteps'
}
</script>
<style lang="less">
.xtx-steps {
      
      
  display: flex;
  text-align: center;
  &-item {
      
      
    flex: 1;
    &:first-child {
      
      
      .step {
      
      
        &::before {
      
      
          display: none;
        }
      }
    }
    &:last-child {
      
      
      .step {
      
      
        &::after {
      
      
          display: none;
        }
      }
    }
    &.active {
      
      
      .step {
      
      
        > span {
      
      
          border-color: @xtxColor;
          background: @xtxColor;
          color: #fff
        }
        &::before,&::after {
      
      
          background: @xtxColor;
        }
      }
      .title {
      
      
        color: @xtxColor;
      }
    }
    .step {
      
      
      position: relative;
      > span {
      
      
        width: 48px;
        height: 48px;
        font-size: 28px;
        border: 2px solid #e4e4e4;
        background: #fff;
        border-radius: 50%;
        line-height: 44px;
        color: #ccc;
        display: inline-block;
        position: relative;
        z-index: 1;
      }
      &::after,&::before{
      
      
        content: "";
        position: absolute;
        top: 23px;
        width: 50%;
        height: 2px;
        background: #e4e4e4;
      }
      &::before {
      
      
         left: 0;
      }
      &::after {
      
      
         right: 0;
       }
    }
    .title {
      
      
      color: #999;
      padding-top: 12px;
    }
    .desc {
      
      
      font-size: 12px;
      color: #999;
      padding-top: 6px;
    }
  }
}
</style>

2.xtx-steps-item 封装步骤条-条目
xtx-steps-item.vue

<script>
export default {
    
    
  name: 'XtxStepsItem',
  props: {
    
    
    title: {
    
    
      type: String,
      default: ''
    },
    desc: {
    
    
      type: String,
      default: ''
    }
  }
}
</script>

3.xtx-steps 组织组件结构
xtx-steps.vue

<script>
import {
    
     getCurrentInstance } from 'vue'
export default {
    
    
  name: 'XtxSteps',
  render () {
    
    
    const {
    
     ctx } = getCurrentInstance()
    const items = ctx.$slots.default()
    const dynamicItems = []
    items.forEach(item => {
    
    
      if (item.type.name === 'XtxStepsItem') {
    
    
        dynamicItems.push(item)
      } else {
    
    
        item.children.forEach(c => {
    
    
          dynamicItems.push(c)
        })
      }
    })
    const itemsJsx = dynamicItems.map((item, i) => {
    
    
      return <div class="xtx-steps-item">
        <div class="step"><span>{
    
    i + 1}</span></div>
        <div class="title">{
    
    item.props.title}</div>
        <div class="desc">{
    
    item.props.desc}</div>
      </div>
    })
    return <div class="xtx-steps">{
    
    itemsJsx}</div>
  }
}
</script>

使用

    <!-- 步骤条-->
    <XtxSteps>
      <XtxStepsItem title="提交订单" desc="2021-03-18 02:11:47" />
      <XtxStepsItem title="付款成功" desc="2021-03-18 02:11:47" />
      <XtxStepsItem title="商品发货" desc="2021-03-18 02:11:47" />
      <XtxStepsItem title="确认收货" />
      <XtxStepsItem title="订单完成" />
    </XtxSteps>

4.xtx-steps 设置激活步骤

  props: {
    
    
    active: {
    
    
      type: Number,
      default: 1
    }
  },
    const itemsJsx = dynamicItems.map((item, i) => {
    
    
+      return <div class="xtx-steps-item" class={
    
    {
    
     active: i < props.active }}>
        <div class="step"><span>{
    
    i + 1}</span></div>
        <div class="title">{
    
    item.props.title}</div>
        <div class="desc">{
    
    item.props.desc}</div>
      </div>
    })

使用

<XtxSteps :active="3">

5.使用steps组件显示订单进度
src/views/member/order/components/detail-steps.vue

<template>
  <div class="detail-steps" style="padding:20px">
    <XtxSteps :active="order.orderState===6?1:order.orderState">
      <XtxStepsItem title="提交订单" :desc="order.createTime" />
      <XtxStepsItem title="付款成功" :desc="order.payTime" />
      <XtxStepsItem title="商品发货" :desc="order.consignTime" />
      <XtxStepsItem title="确认收货" :desc="order.evaluationTime" />
      <XtxStepsItem title="订单完成" :desc="order.endTime" />
    </XtxSteps>
  </div>
</template>
<script>
export default {
      
      
  props: {
      
      
    order: {
      
      
      type: Object,
      default: () => ({
      
      })
    }
  },
  name: 'DetailSteps'
}
</script>
<style scoped lang="less"></style>

src/views/member/order/index.vue

    <!-- 步骤条-->
    <DetailSteps :order="order" />
import DetailSteps from './components/detail-steps'
export default {
    
    
  name: 'OrderDetailPage',
  components: {
    
     DetailAction, DetailSteps },

17-订单详情-物流信息

大致步骤:

  • 基础布局
  • 获取数据,渲染
  • 使用 suspense 渲染 async setup 的组件
  • 复用订单列表的查看物流逻辑

落的代码:

1.基础布局

<template>
  <div class="detail-logistics">
    <p>
      <span>2016-09-14 15:00:32</span>
      <span>浦东转运中心公司 已收入</span>
    </p>
    <a href="javascript:;">查看物流</a>
  </div>
</template>
<script>
export default {
      
      
  name: 'DetailLogistics'
}
</script>
<style scoped lang="less">
.detail-logistics {
      
      
  height: 50px;
  display: flex;
  align-items: center;
  padding: 0 30px;
  background-color: #f5f5f5;
  margin: 30px 50px 0;
  > p {
      
      
    flex: 1;
    span {
      
      
      color: #999;
      &:first-child {
      
      
        margin-right: 30px;
      }
    }
  }
  > a {
      
      
    color: @xtxColor;
    text-align: center;
  }
}
</style>

2.获取数据,渲染

<template>
  <div class="detail-logistics" v-if="logistics">
    <p>
      <span>{
   
   {logistics.list[0].time}}</span>
      <span>{
   
   {logistics.list[0].text}}</span>
    </p>
    <a href="javascript:;">查看物流</a>
  </div>
  <!-- 查看物流组件 -->
  <Teleport to="#dailog">
    <OrderLogistics ref="logisticsOrderCom" />
  </Teleport>
</template>
<script>
import {
      
       ref } from 'vue'
import {
      
       logisticsOrder } from '@/api/order'
export default {
      
      
  name: 'DetailLogistics',
  props: {
      
      
    order: {
      
      
      type: Object,
      default: () => ({
      
      })
    }
  },
  async setup (props) {
      
      
    const logistics = ref(null)
    // 模拟加载时间
    const $sleep = () => new Promise((resolve, reject) => {
      
      
      setTimeout(() => {
      
      
        resolve()
      }, 2000)
    })
    await $sleep()
    const data = await logisticsOrder(props.order.id)
    logistics.value = data.result
    return {
      
       logistics }
  }
}
</script>
<style scoped lang="less">
.detail-logistics {
      
      
  height: 50px;
  display: flex;
  align-items: center;
  padding: 0 30px;
  background-color: #f5f5f5;
  margin: 30px 50px 0;
  > p {
      
      
    flex: 1;
    span {
      
      
      color: #999;
      &:first-child {
      
      
        margin-right: 30px;
      }
    }
  }
  > a {
      
      
    color: @xtxColor;
    text-align: center;
  }
}
</style>

3.使用

    <!-- 物流区块 -->
+    <Suspense  v-if="[3,4,5].includes(order.orderState)">
+      <!-- 组件加载完毕 -->
+      <template #default>
+        <DetailLogistics :order="order" />
+      </template>
+      <!-- 组件加载中显示 -->
+      <template #fallback>
+        <div class="loading">loading</div>
+      </template>
+    </Suspense>
    <!-- 订单商品信息 -->
  </div>
</template>
<script>
+import DetailLogistics from './components/detail-logistics'
export default {
  name: 'OrderDetailPage',
+  components: { DetailAction, DetailSteps, DetailLogistics },

4.使用订单列表的查看物理逻辑
src/views/memner/order/index.vue

// 封装逻辑-查看物流
export const useLogisticsOrder = () => {
    
    

src/views/memner/order/components/detail-logistics.vue

import OrderLogistics from './order-logistics'
import {
    
     useLogisticsOrder } from '../index'
export default {
    
    
  name: 'DetailLogistics',
+  components: {
    
     OrderLogistics },
    const data = await logisticsOrder(props.order.id)
    logistics.value = data.result
+    return {
    
     logistics, ...useLogisticsOrder() }
+    <a href="javascript:;" @click="onLogisticsOrder(order)">查看物流</a>
  </div>
  <!-- 查看物流组件 -->
+  <Teleport to="#dailog">
+    <OrderLogistics ref="logisticsOrderCom" />
+  </Teleport>

猜你喜欢

转载自blog.csdn.net/m0_52896752/article/details/128883764