Browse Source

订单列表和订单详情页初步完善

sfmind 2 năm trước cách đây
mục cha
commit
d5c1c29795

+ 2 - 0
yudao-ui-app/api/order.js

@@ -2,3 +2,5 @@ const { http } = uni.$u
 
 // 获得订单交易分页
 export const getOrderPage = params => http.get('/trade/order/page', { params })
+// 获得交易订单详情
+export const getOrderDetail = params => http.get('/trade/order/get-detail', { params })

+ 7 - 0
yudao-ui-app/common/orderStatus.js

@@ -0,0 +1,7 @@
+export default {
+  '0': { name: '待付款', icon: 'red-packet'},
+  '10': { name: '待发货', icon: 'car'},
+  '20': { name: '待收货', icon: 'order'},
+  '30': { name: '已完成', icon: 'integral'},
+  '40': { name: '已取消', icon: 'close-circle'}
+}

+ 7 - 1
yudao-ui-app/pages.json

@@ -75,11 +75,17 @@
       }
     },
     {
-      "path": "pages/order/order",
+      "path": "pages/order/list",
       "style": {
         "navigationBarTitleText": "我的订单"
       }
     },
+    {
+      "path": "pages/order/detail",
+      "style": {
+        "navigationBarTitleText": "订单详情"
+      }
+    },
     {
       "path": "pages/address/list",
       "style": {

+ 252 - 0
yudao-ui-app/pages/order/detail.vue

@@ -0,0 +1,252 @@
+<template>
+  <view class="container">
+    <viwe class="detail-header">
+      <view class="order-status">{{ order.status | getStatusName }}</view>
+    </viwe>
+
+    <view class="order-product">
+      <view class="order-item" v-for="item in order.items" :key="item.id">
+        <image class="product-image" :src="item.picUrl"></image>
+        <view class="item-info">
+          <view class="info-text">
+            <u--text :lines="1" size="15px" color="#333333" :text="item.spuName"></u--text>
+            <u-gap height="10"></u-gap>
+            <yd-text-price class="product-price" size="13" intSize="14" :price="item.originalUnitPrice"></yd-text-price>
+          </view>
+          <view class="price-number-box">
+            <view class="number-box">
+              <view class="product-number">共 {{ item.count }} 件</view>
+              小计:
+            </view>
+            <view class="number-box" @click.stop>
+              <yd-text-price size="13" intSize="16" :price="item.originalPrice"></yd-text-price>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <view v-if="order.no" >
+      <view v-if="order.no" class="base-info">
+        <view class="info-item">
+          <view class="item-name">订单编号:</view>
+          <view class="item-value">{{ order.no }}</view>
+        </view>
+        <view class="info-item">
+          <view class="item-name">下单时间:</view>
+          <view class="item-value">{{ order.createTime }}</view>
+        </view>
+        <view v-if="order.payOrderId" class="info-item">
+          <view class="item-name">支付方式:</view>
+          <view class="item-value">{{ order.payOrderId }}</view>
+        </view>
+        <view v-if="order.payTime" class="info-item">
+          <view class="item-name">支付时间:</view>
+          <view class="item-value">{{ order.payTime }}</view>
+        </view>
+      </view>
+
+      <view class="delivery-info">
+        <view class="info-item">
+          <view class="item-name">收货地址:</view>
+          <view class="item-value">{{ order.receiverAreaName + order.receiverDetailAddress  + order.receiverDetailAddress  + order.receiverDetailAddress }}</view>
+        </view>
+        <view v-if="order.receiverName" class="info-item">
+          <view class="item-name">收货人:</view>
+          <view class="item-value">{{ order.receiverName }}</view>
+        </view>
+        <view v-if="order.receiverMobile" class="info-item">
+          <view class="item-name">联系电话:</view>
+          <view class="item-value">{{ order.receiverMobile }}</view>
+        </view>
+      </view>
+
+      <view class="delivery-info">
+        <view class="info-item">
+          <view class="item-name">商品总额:</view>
+          <yd-text-price class="product-price" size="13" intSize="16" :price="order.originalPrice"></yd-text-price>
+        </view>
+        <view class="info-item">
+          <view class="item-name">运费:</view>
+          <yd-text-price class="product-price" size="13" intSize="16" :price="order.deliveryPrice"></yd-text-price>
+        </view>
+        <view class="info-item">
+          <view class="item-name">优惠:</view>
+          <yd-text-price class="product-price" size="13" intSize="16" symbol="-¥" :price="order.discountPrice"></yd-text-price>
+        </view>
+        <view class="info-item">
+          <view class="item-name">订单金额:</view>
+          <yd-text-price class="product-price" size="15" intSize="20" :price="order.orderPrice"></yd-text-price>
+        </view>
+      </view>
+    </view>
+
+  </view>
+</template>
+
+<script>
+import { getOrderDetail } from '../../api/order'
+import orderStatus from '@/common/orderStatus'
+
+export default {
+  name: 'orderDetail',
+  filters: {
+    getStatusName(status) {
+      return orderStatus[status + ''].name
+    }
+  },
+  data() {
+    return {
+      orderId: undefined,
+      order: {}
+    }
+  },
+  onLoad(e) {
+    this.orderId = e.orderId
+    if (!this.orderId) {
+      uni.$u.toast('请求参数错误')
+    } else {
+      this.loadOrderDetailData()
+    }
+  },
+  methods: {
+    loadOrderDetailData() {
+      getOrderDetail({ id: this.orderId })
+        .then(res => {
+          this.order = res.data || {}
+        })
+        .catch(err => {
+          console.log(err)
+        })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+  background-color: #f3f3f3;
+  height: 100vh;
+}
+
+.detail-header {
+  @include flex-center();
+  background-color: $custom-bg-color;
+  padding: 10rpx 0;
+  border-radius: 0 0 20rpx 20rpx;
+}
+
+.order-product {
+  background-color: $custom-bg-color;
+  border-radius: 20rpx;
+  margin: 20rpx;
+  padding: 10rpx 20rpx;
+  .order-item {
+    background: #ffffff;
+    @include flex-space-between;
+    padding: 10rpx 0 10rpx 5rpx;
+
+    .product-check {
+      padding: 20rpx;
+
+      .un-check-box {
+        width: 20px;
+        height: 20px;
+        border: 1px solid #939393;
+        border-radius: 50%;
+      }
+    }
+
+    .product-image {
+      width: 180rpx;
+      height: 180rpx;
+      border-radius: 10rpx;
+    }
+
+    .item-info {
+      flex: 1;
+      padding: 0 20rpx;
+
+      .info-text {
+        padding-bottom: 10rpx;
+
+        .product-price {
+          margin-top: 15rpx;
+        }
+      }
+
+      .price-number-box {
+        @include flex-space-between;
+
+        .number-box {
+          font-size: 24rpx;
+
+          .product-number {
+            width: 200rpx;
+          }
+        }
+
+        .number-box {
+          height: 60rpx;
+          @include flex-center;
+        }
+      }
+    }
+  }
+}
+
+.base-info {
+  background-color: $custom-bg-color;
+  border-radius: 20rpx;
+  margin: 20rpx;
+  padding: 20rpx;
+  .info-item {
+    @include flex-left();
+    padding: 10rpx 0;
+    .item-name {
+      color: #999;
+      font-size: 26rpx;
+    }
+    .item-value {
+      color: #333;
+      font-size: 26rpx;
+    }
+  }
+}
+
+.delivery-info {
+  background-color: $custom-bg-color;
+  border-radius: 20rpx;
+  margin: 20rpx;
+  padding: 20rpx;
+  .info-item {
+    @include flex-left();
+    padding: 10rpx 0;
+    .item-name {
+      color: #999;
+      font-size: 26rpx;
+      width: 260rpx;
+    }
+    .item-value {
+      color: #333;
+      font-size: 26rpx;
+    }
+  }
+}
+
+.delivery-info {
+  background-color: $custom-bg-color;
+  border-radius: 20rpx;
+  margin: 20rpx;
+  padding: 20rpx;
+  .info-item {
+    @include flex-space-between();
+    padding: 10rpx 0;
+    .item-name {
+      color: #999;
+      font-size: 26rpx;
+    }
+  }
+}
+
+</style>

+ 195 - 0
yudao-ui-app/pages/order/list.vue

@@ -0,0 +1,195 @@
+<template>
+  <view class="container">
+    <u-sticky style="top: 0" offset-top="0">
+      <u-tabs :list="tabArray" :current="tabIndex" itemStyle="padding-left: 18px; padding-right: 18px; height: 36px;" @change="handleStatusChange"></u-tabs>
+    </u-sticky>
+    <view class="order-list">
+      <view v-for="order in orderList" :key="order.no" class="order-item">
+        <view class="order-header">
+          <view class="order-no">订单编号:{{ order.no }}</view>
+          <view class="order-status">{{ order.status | getStatusName }}</view>
+        </view>
+
+        <view v-if="order.items.length === 1" class="order-single-item" @click="handleOrderClick(order.id)">
+          <view class="item-wrap" v-for="item in order.items" :key="item.id">
+            <view class="item-info">
+              <image class="item-cover" :src="item.picUrl"></image>
+              <u--text :lines="2" size="15px" color="#333333" :text="item.spuName"></u--text>
+            </view>
+            <view class="item-count">共{{ item.count }}件</view>
+          </view>
+        </view>
+        <view v-else class="order-multi-item" @click="handleOrderClick(order.id)">
+          <u-scroll-list :indicator="false">
+            <view class="item-wrap" v-for="item in order.items" :key="item.id">
+              <image class="item-image" :src="item.picUrl"></image>
+            </view>
+          </u-scroll-list>
+          <view class="product-count">共{{ order.productCount }}件</view>
+        </view>
+
+        <view class="order-btn-group">
+          <view class="order-btn">再次购买</view>
+          <view class="order-btn">其他操作</view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import { getOrderPage } from '../../api/order'
+import orderStatus from '@/common/orderStatus'
+
+export default {
+  name: 'orderList',
+  filters: {
+    getStatusName(status) {
+      return orderStatus[status + ''].name
+    }
+  },
+  data() {
+    return {
+      pageNo: 1,
+      tabIndex: 0,
+      orderList: []
+    }
+  },
+  computed: {
+    tabArray() {
+      let tabArray = [{ name: '全部', status: 'all' }]
+      for (let status in orderStatus) {
+        if (status !== '40') {
+          tabArray.push({ name: orderStatus[status].name, status: status })
+        }
+      }
+      return tabArray
+    }
+  },
+  onLoad(e) {
+    const status = e.status
+    if (status !== undefined) {
+      this.tabArray.forEach((item, index) => {
+        if (item.status === status) {
+          this.tabIndex = index
+        }
+      })
+    }
+    this.loadOrderPageData()
+  },
+  methods: {
+    handleStatusChange({ index }) {
+      this.tabIndex = index
+      this.loadOrderPageData()
+    },
+    loadOrderPageData() {
+      let params = { pageNo: this.pageNo }
+      const status = this.tabArray[this.tabIndex].status
+      if (status !== 'all') {
+        params.orderStatus = status
+      }
+      getOrderPage(params)
+        .then(res => {
+          this.orderList = res.data.list || []
+        })
+        .catch(err => {
+          console.log(err)
+        })
+    },
+    handleOrderClick(orderId) {
+      uni.$u.route('/pages/order/detail', {
+        orderId: orderId
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.order-list {
+  background-color: #f3f3f3;
+
+  .order-item {
+    padding: 20rpx;
+    background-color: #ffffff;
+    border-bottom: $custom-border-style;
+
+    .order-header {
+      @include flex-space-between;
+      height: 80rpx;
+
+      .order-no {
+        font-size: 28rpx;
+        color: #333;
+      }
+
+      .order-status {
+        font-size: 24rpx;
+        color: #999;
+      }
+    }
+
+    .order-single-item {
+      .item-wrap {
+        @include flex-space-between();
+
+        .item-info {
+          @include flex-left();
+
+          .item-cover {
+            width: 100rpx;
+            height: 100rpx;
+            border-radius: 10rpx;
+            margin-right: 15rpx;
+          }
+        }
+
+        .item-count {
+          color: #999;
+          font-size: 24rpx;
+          width: 120rpx;
+          text-align: right;
+        }
+      }
+    }
+
+    .order-multi-item {
+      @include flex-space-between();
+
+      .item-wrap {
+        margin-right: 20rpx;
+
+        .item-image {
+          width: 100rpx;
+          height: 100rpx;
+          border-radius: 10rpx;
+        }
+      }
+
+      .product-count {
+        color: #999;
+        font-size: 24rpx;
+        width: 120rpx;
+        text-align: right;
+      }
+    }
+
+    .order-btn-group {
+      margin-top: 10rpx;
+      @include flex-right();
+
+      .order-btn {
+        width: 120rpx;
+        height: 36rpx;
+        line-height: 36rpx;
+        border-radius: 36rpx;
+        border: 1px solid #777;
+        color: #777;
+        font-size: 22rpx;
+        text-align: center;
+        margin-left: 15rpx;
+      }
+    }
+  }
+}
+</style>

+ 0 - 87
yudao-ui-app/pages/order/order.vue

@@ -1,87 +0,0 @@
-<template>
-  <view class="container">
-    <u-sticky style="top: 0" offset-top="0">
-      <u-tabs :list="statusArray" :current="statusIndex" @change="handleStatusChange"></u-tabs>
-    </u-sticky>
-    <view class="order-list">
-      <view v-for="(item, index) in orderList" :key="item.orderNo" class="order-item">
-        <view class="item-title">{{ item.orderNo }}</view>
-        <view class="item-content">{{ item.orderStatus }}</view>
-        <view class="item-btn-group"></view>
-      </view>
-    </view>
-  </view>
-</template>
-
-<script>
-import { getOrderPage } from '../../api/order'
-
-export default {
-  name: 'order',
-  data() {
-    return {
-      pageNo: 1,
-      statusIndex: 0,
-      statusArray: [
-        {
-          name: '全部',
-          status: '-1'
-        },
-        {
-          name: '待付款',
-          status: '0'
-        },
-        {
-          name: '待发货',
-          status: '10'
-        },
-        {
-          name: '待收货',
-          status: '20'
-        },
-        {
-          name: '已完成',
-          status: '30'
-        },
-        {
-          name: '已取消', // TODO @辰尘:已取消不展示
-          status: '50'
-        }
-      ],
-      orderList: []
-    }
-  },
-  onLoad(e) {
-    const status = e.status
-    if (status !== undefined) {
-      this.statusArray.forEach((item, index) => {
-        if (item.status === status) {
-          this.statusIndex = index
-        }
-      })
-    }
-    this.loadOrderPageData()
-  },
-  methods: {
-    handleStatusChange(item) {
-      this.statusIndex = item.status
-    },
-    loadOrderPageData() {
-      let params = { pageNo: this.pageNo }
-      const status = this.statusArray[this.statusIndex].status
-      if (status >= 0) {
-        params.orderStatus = status
-      }
-      getOrderPage(params)
-        .then(res => {
-          console.log(res)
-        })
-        .catch(err => {
-          console.log(err)
-        })
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped></style>

+ 28 - 25
yudao-ui-app/pages/user/user.vue

@@ -4,7 +4,7 @@
       <view class="user-info" @click="pageRouter('/pages/profile/profile')">
         <u-avatar size="60" shape="square" :src="userInfo.avatar"></u-avatar>
         <view class="info-text">
-          <view class="user-nickname">{{ hasLogin ? userInfo.nickname || ' ' : '匿名用户' }}</view>
+          <view class="user-nickname">{{ hasLogin ? userInfo.nickname || '会员用户' : '匿名用户' }}</view>
           <view class="user-mobile">{{ hasLogin ? userInfo.mobile || ' ' : '登录/注册' }}</view>
         </view>
       </view>
@@ -26,9 +26,9 @@
 
       <view class="order-status-box">
         <u-grid :border="false" :col="orderStatusList.length">
-          <u-grid-item v-for="(item, index) in orderStatusList" :key="index" @click="pageRouter(orderPage, item.state)">
+          <u-grid-item v-for="(item, index) in orderStatusList" :key="index" @click="pageRouter(orderPage, item.status)">
             <u-icon :name="item.icon" :size="32"></u-icon>
-            <text class="grid-title">{{ item.title }}</text>
+            <text class="grid-title">{{ item.name }}</text>
           </u-grid-item>
         </u-grid>
       </view>
@@ -37,8 +37,8 @@
     <u-gap height="10" bgColor="#f3f3f3"></u-gap>
 
     <view class="stat-box">
-      <u-grid :border="false" col="3"
-        ><u-grid-item v-for="(item, index) in statList" :key="index">
+      <u-grid :border="false" col="3">
+        <u-grid-item v-for="(item, index) in statList" :key="index">
           <text class="grid-value">{{ item.value }}</text>
           <text class="grid-title">{{ item.title }}</text>
         </u-grid-item>
@@ -53,21 +53,16 @@
       <u-cell class="fun-item" :border="false" icon="coupon" title="我的优惠券" isLink></u-cell>
       <u-cell class="fun-item" :border="false" icon="map" title="收货地址" @click="pageRouter('/pages/address/list')" isLink></u-cell>
     </u-cell-group>
-
   </view>
 </template>
 
 <script>
+import orderStatus from '@/common/orderStatus'
+
 export default {
   data() {
     return {
-      orderPage: '/pages/order/order',
-      orderStatusList: [
-        { icon: 'red-packet', title: '待付款', state: '0' },
-        { icon: 'car', title: '待发货', state:'20' },
-        { icon: 'order', title: '待收货', state: '30' },
-        { icon: 'integral', title: '已完成', state: '40' }
-      ],
+      orderPage: '/pages/order/list',
       statList: [
         { value: '0', title: '我的收藏' },
         { value: '0', title: '我的消息' },
@@ -76,10 +71,27 @@ export default {
     }
   },
   onLoad() {
-    if (this.hasLogin){
+    if (this.hasLogin) {
       this.$store.dispatch('ObtainUserInfo')
     }
   },
+  computed: {
+    userInfo() {
+      return this.$store.getters.userInfo
+    },
+    hasLogin() {
+      return this.$store.getters.hasLogin
+    },
+    orderStatusList() {
+      let orderStatusList = []
+      for (let status in orderStatus) {
+        if (status !== '40') {
+          orderStatusList.push({ name: orderStatus[status].name, status: status, icon: orderStatus[status].icon })
+        }
+      }
+      return orderStatusList
+    }
+  },
   methods: {
     pageRouter(pageUrl, param) {
       if (!this.hasLogin) {
@@ -87,7 +99,7 @@ export default {
       } else if (pageUrl === this.orderPage) {
         uni.$u.route(this.orderPage, {
           status: param
-        });
+        })
       } else {
         uni.$u.route(pageUrl)
       }
@@ -105,20 +117,11 @@ export default {
         }
       })
     }
-  },
-  computed: {
-    userInfo() {
-      return this.$store.getters.userInfo
-    },
-    hasLogin() {
-      return this.$store.getters.hasLogin
-    }
   }
 }
 </script>
 
 <style lang="scss" scoped>
-
 .user-header {
   background-color: #fff;
   @include flex-space-between;
@@ -161,6 +164,7 @@ export default {
     color: #333333;
     font-size: 34rpx;
   }
+
   .see-all {
     height: 40rpx;
     @include flex-right;
@@ -196,5 +200,4 @@ export default {
     border-bottom: $custom-border-style;
   }
 }
-
 </style>

+ 2 - 2
yudao-ui-app/uni.scss

@@ -28,14 +28,14 @@ $custom-border-style: 1rpx solid #f3f3f3;
   display: flex;
   flex-direction: $direction;
   align-items: center;
-  justify-content: left;
+  justify-content: flex-start;
 }
 
 @mixin flex-right($direction: row) {
   display: flex;
   flex-direction: $direction;
   align-items: center;
-  justify-content: right;
+  justify-content: flex-end;
 }
 
 @mixin flex-center($direction: row) {