Browse Source

订单列表渲染与操作

template
liruiqiang 4 weeks ago
parent
commit
0d987a0c9f
  1. 388
      src/pagesOrder/list/components/OrderList.vue
  2. 243
      src/pagesOrder/list/list.vue
  3. 14
      src/services/order.ts
  4. 24
      src/types/order.d.ts

388
src/pagesOrder/list/components/OrderList.vue

@ -0,0 +1,388 @@
<template>
<scroll-view
enable-back-to-top
scroll-y
class="orders"
refresher-enabled
:refresher-triggered="isTriggered"
@refresherrefresh="onRefresherrefresh"
@scrolltolower="getMemberOrderData"
>
<view class="card" v-for="order in orderList" :key="order.id">
<!-- 订单信息 -->
<view class="status">
<text class="date">{{ order.createTime }}</text>
<!-- 订单状态文字 -->
<text>{{ orderStateList[order.orderState].text }}</text>
<!-- 待评价/已完成/已取消 状态: 展示删除订单 -->
<text
v-if="order.orderState >= OrderState.DaiPingJia"
class="icon-delete"
@tap="onOrderDelete(order.id)"
></text>
</view>
<!-- 商品信息点击商品跳转到订单详情不是商品详情 -->
<navigator
v-for="item in order.skus"
:key="item.id"
class="goods"
:url="`/pagesOrder/detail/detail?id=${order.id}`"
hover-class="none"
>
<view class="cover">
<image class="image" mode="aspectFit" :src="item.image"></image>
</view>
<view class="meta">
<view class="name ellipsis">{{ item.name }}</view>
<view class="type">{{ item.attrsText }}</view>
</view>
</navigator>
<!-- 支付信息 -->
<view class="payment">
<text class="quantity">{{ order.totalNum }}件商品</text>
<text>实付</text>
<text class="amount"> <text class="symbol">¥</text>{{ order.payMoney }}</text>
</view>
<!-- 订单操作按钮 -->
<view class="action">
<!-- 待付款状态显示去支付按钮 -->
<template v-if="order.orderState === OrderState.DaiFuKuan">
<view class="button primary" @tap="onOrderPay(order.id)">去支付</view>
</template>
<template v-else>
<navigator
class="button secondary"
:url="`/pagesOrder/create/create?orderId=${order.id}`"
hover-class="none"
>
再次购买
</navigator>
<!-- 待收货状态: 展示确认收货 -->
<view
v-if="order.orderState === OrderState.DaiShouHuo"
class="button primary"
@tap="onOrderConfirm(order.id)"
>
确认收货
</view>
</template>
</view>
</view>
<!-- 底部提示文字 -->
<view class="loading-text" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
{{ isFinish ? '没有更多数据~' : '正在加载...' }}
</view>
</scroll-view>
</template>
<script setup lang="ts">
import { OrderState, orderStateList } from '@/services/constants'
import {
putMemberOrderReceiptByIdAPI,
deleteMemberOrderAPI,
getMemberOrderAPI,
} from '@/services/order'
import { getPayMockAPI, getPayWxPayMiniPayAPI } from '@/services/pay'
import type { OrderItem, OrderListParams } from '@/types/order'
import { onMounted, ref } from 'vue'
//
const { safeAreaInsets } = uni.getSystemInfoSync()
// porps
const props = defineProps<{
orderState: number
}>()
//
const queryParams: Required<OrderListParams> = {
page: 1,
pageSize: 5,
orderState: props.orderState,
}
//
const orderList = ref<OrderItem[]>([])
//
const isLoading = ref(false)
const getMemberOrderData = async () => {
// 退
if (isLoading.value) return
// 退
if (isFinish.value === true) {
return uni.showToast({ icon: 'none', title: '没有更多数据~' })
}
//
isLoading.value = true
//
const res = await getMemberOrderAPI(queryParams)
//
isLoading.value = false
//
orderList.value.push(...res.result.items)
//
if (queryParams.page < res.result.pages) {
//
queryParams.page++
} else {
//
isFinish.value = true
}
}
onMounted(() => {
getMemberOrderData()
})
//
const onOrderPay = async (id: string) => {
if (import.meta.env.DEV) {
//
await getPayMockAPI({ orderId: id })
} else {
// #ifdef MP-WEIXIN
// 1.2.API
// const res = await getPayWxPayMiniPayAPI({ orderId: id })
// await wx.requestPayment(res.result)
// 线 0.01
await getPayMockAPI({ orderId: id })
// #endif
}
//
uni.showToast({ title: '模拟支付成功' })
//
setTimeout(() => {
wx.showModal({
title: '温馨提示',
content: '此交易是模拟支付,您并未付款,不会导致实际购买商品或服务',
confirmText: '知道了',
showCancel: false,
})
}, 2000)
//
const order = orderList.value.find((v) => v.id === id)
order!.orderState = OrderState.DaiFaHuo
}
//
const onOrderConfirm = (id: string) => {
uni.showModal({
content: '为保障您的权益,请收到货并确认无误后,再确认收货',
confirmColor: '#27BA9B',
success: async (res) => {
if (res.confirm) {
await putMemberOrderReceiptByIdAPI(id)
uni.showToast({ icon: 'success', title: '确认收货成功' })
//
const order = orderList.value.find((v) => v.id === id)
order!.orderState = OrderState.DaiPingJia
}
},
})
}
//
const onOrderDelete = (id: string) => {
uni.showModal({
content: '你确定要删除该订单?',
confirmColor: '#27BA9B',
success: async (res) => {
if (res.confirm) {
await deleteMemberOrderAPI({ ids: [id] })
//
const index = orderList.value.findIndex((v) => v.id === id)
orderList.value.splice(index, 1)
}
},
})
}
//
const isFinish = ref(false)
//
const isTriggered = ref(false)
//
const onRefresherrefresh = async () => {
//
isTriggered.value = true
//
queryParams.page = 1
orderList.value = []
isFinish.value = false
//
await getMemberOrderData()
//
isTriggered.value = false
}
</script>
<style lang="scss">
//
.orders {
.card {
min-height: 100rpx;
padding: 20rpx;
margin: 20rpx 20rpx 0;
border-radius: 10rpx;
background-color: #fff;
&:last-child {
padding-bottom: 40rpx;
}
}
.status {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
color: #999;
margin-bottom: 15rpx;
.date {
color: #666;
flex: 1;
}
.primary {
color: #ff9240;
}
.icon-delete {
line-height: 1;
margin-left: 10rpx;
padding-left: 10rpx;
border-left: 1rpx solid #e3e3e3;
}
}
.goods {
display: flex;
margin-bottom: 20rpx;
.cover {
width: 170rpx;
height: 170rpx;
margin-right: 20rpx;
border-radius: 10rpx;
overflow: hidden;
position: relative;
.image {
width: 170rpx;
height: 170rpx;
}
}
.quantity {
position: absolute;
bottom: 0;
right: 0;
line-height: 1;
padding: 6rpx 4rpx 6rpx 8rpx;
font-size: 24rpx;
color: #fff;
border-radius: 10rpx 0 0 0;
background-color: rgba(0, 0, 0, 0.6);
}
.meta {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.name {
height: 80rpx;
font-size: 26rpx;
color: #444;
}
.type {
line-height: 1.8;
padding: 0 15rpx;
margin-top: 10rpx;
font-size: 24rpx;
align-self: flex-start;
border-radius: 4rpx;
color: #888;
background-color: #f7f7f8;
}
.more {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
color: #333;
}
}
.payment {
display: flex;
justify-content: flex-end;
align-items: center;
line-height: 1;
padding: 20rpx 0;
text-align: right;
color: #999;
font-size: 28rpx;
border-bottom: 1rpx solid #eee;
.quantity {
font-size: 24rpx;
margin-right: 16rpx;
}
.amount {
color: #444;
margin-left: 6rpx;
}
.symbol {
font-size: 20rpx;
}
}
.action {
display: flex;
justify-content: flex-end;
align-items: center;
padding-top: 20rpx;
.button {
width: 180rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
margin-left: 20rpx;
border-radius: 60rpx;
border: 1rpx solid #ccc;
font-size: 26rpx;
color: #444;
}
.secondary {
color: #27ba9b;
border-color: #27ba9b;
}
.primary {
color: #fff;
background-color: #27ba9b;
border-color: #27ba9b;
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
}
</style>

243
src/pagesOrder/list/list.vue

@ -6,7 +6,12 @@
class="item"
v-for="(item, index) in orderTabs"
:key="item.title"
@tap="activeIndex = index"
@tap="
() => {
activeIndex = index
item.isRender = true
}
"
>
{{ item.title }}
</text>
@ -18,65 +23,7 @@
<!-- 滑动项 -->
<swiper-item v-for="item in orderTabs" :key="item.title">
<!-- 订单列表 -->
<scroll-view scroll-y class="orders">
<view class="card" v-for="item in 2" :key="item">
<!-- 订单信息 -->
<view class="status">
<text class="date">2023-04-14 13:14:20</text>
<!-- 订单状态文字 -->
<text>待付款</text>
<!-- 待评价/已完成/已取消 状态: 展示删除订单 -->
<text class="icon-delete"></text>
</view>
<!-- 商品信息点击商品跳转到订单详情不是商品详情 -->
<navigator
v-for="sku in 2"
:key="sku"
class="goods"
:url="`/pagesOrder/detail/detail?id=1`"
hover-class="none"
>
<view class="cover">
<image
mode="aspectFit"
src="https://yanxuan-item.nosdn.127.net/c07edde1047fa1bd0b795bed136c2bb2.jpg"
></image>
</view>
<view class="meta">
<view class="name ellipsis">ins风小碎花泡泡袖衬110-160cm</view>
<view class="type">藏青小花 130</view>
</view>
</navigator>
<!-- 支付信息 -->
<view class="payment">
<text class="quantity">共5件商品</text>
<text>实付</text>
<text class="amount"> <text class="symbol">¥</text>99</text>
</view>
<!-- 订单操作按钮 -->
<view class="action">
<!-- 待付款状态显示去支付按钮 -->
<template v-if="true">
<view class="button primary">去支付</view>
</template>
<template v-else>
<navigator
class="button secondary"
:url="`/pagesOrder/create/create?orderId=id`"
hover-class="none"
>
再次购买
</navigator>
<!-- 待收货状态: 展示确认收货 -->
<view v-if="false" class="button primary">确认收货</view>
</template>
</view>
</view>
<!-- 底部提示文字 -->
<view class="loading-text" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
{{ true ? '没有更多数据~' : '正在加载...' }}
</view>
</scroll-view>
<OrderList v-if="item.isRender" :order-state="item.orderState" />
</swiper-item>
</swiper>
</view>
@ -84,16 +31,17 @@
<script setup lang="ts">
import { ref } from 'vue'
import OrderList from './components/OrderList.vue'
//
const { safeAreaInsets } = uni.getSystemInfoSync()
// tabs
const orderTabs = ref([
{ orderState: 0, title: '全部' },
{ orderState: 1, title: '待付款' },
{ orderState: 2, title: '待发货' },
{ orderState: 3, title: '待收货' },
{ orderState: 4, title: '待评价' },
{ orderState: 0, title: '全部', isRender: false },
{ orderState: 1, title: '待付款', isRender: false },
{ orderState: 2, title: '待发货', isRender: false },
{ orderState: 3, title: '待收货', isRender: false },
{ orderState: 4, title: '待评价', isRender: false },
])
//
@ -103,6 +51,9 @@ const query = defineProps<{
//
const activeIndex = ref(orderTabs.value.findIndex((v) => v.orderState === Number(query.type)))
//
orderTabs.value[activeIndex.value].isRender = true
</script>
<style lang="scss">
@ -154,166 +105,4 @@ page {
.swiper {
background-color: #f7f7f8;
}
//
.orders {
.card {
min-height: 100rpx;
padding: 20rpx;
margin: 20rpx 20rpx 0;
border-radius: 10rpx;
background-color: #fff;
&:last-child {
padding-bottom: 40rpx;
}
}
.status {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
color: #999;
margin-bottom: 15rpx;
.date {
color: #666;
flex: 1;
}
.primary {
color: #ff9240;
}
.icon-delete {
line-height: 1;
margin-left: 10rpx;
padding-left: 10rpx;
border-left: 1rpx solid #e3e3e3;
}
}
.goods {
display: flex;
margin-bottom: 20rpx;
.cover {
width: 170rpx;
height: 170rpx;
margin-right: 20rpx;
border-radius: 10rpx;
overflow: hidden;
position: relative;
}
.quantity {
position: absolute;
bottom: 0;
right: 0;
line-height: 1;
padding: 6rpx 4rpx 6rpx 8rpx;
font-size: 24rpx;
color: #fff;
border-radius: 10rpx 0 0 0;
background-color: rgba(0, 0, 0, 0.6);
}
.meta {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.name {
height: 80rpx;
font-size: 26rpx;
color: #444;
}
.type {
line-height: 1.8;
padding: 0 15rpx;
margin-top: 10rpx;
font-size: 24rpx;
align-self: flex-start;
border-radius: 4rpx;
color: #888;
background-color: #f7f7f8;
}
.more {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
color: #333;
}
}
.payment {
display: flex;
justify-content: flex-end;
align-items: center;
line-height: 1;
padding: 20rpx 0;
text-align: right;
color: #999;
font-size: 28rpx;
border-bottom: 1rpx solid #eee;
.quantity {
font-size: 24rpx;
margin-right: 16rpx;
}
.amount {
color: #444;
margin-left: 6rpx;
}
.symbol {
font-size: 20rpx;
}
}
.action {
display: flex;
justify-content: flex-end;
align-items: center;
padding-top: 20rpx;
.button {
width: 180rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
margin-left: 20rpx;
border-radius: 60rpx;
border: 1rpx solid #ccc;
font-size: 26rpx;
color: #444;
}
.secondary {
color: #27ba9b;
border-color: #27ba9b;
}
.primary {
color: #fff;
background-color: #27ba9b;
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
}
</style>

14
src/services/order.ts

@ -1,5 +1,7 @@
import type {
OrderCreateParams,
OrderListParams,
OrderListResult,
OrderLogisticResult,
OrderPreResult,
OrderResult,
@ -127,3 +129,15 @@ export const getMemberOrderCancelByIdAPI = (id: string, data: { cancelReason: st
data,
})
}
/**
*
* @param data orderState
*/
export const getMemberOrderAPI = (data: OrderListParams) => {
return http<OrderListResult>({
method: 'GET',
url: `/member/order`,
data,
})
}

24
src/types/order.d.ts

@ -1,5 +1,6 @@
import type { AddressItem } from './address'
import type { OrderState } from '@/services/constants'
import type { PageParams } from '@/types/global'
/** 获取预付订单 返回信息 */
export type OrderPreResult = {
@ -151,3 +152,26 @@ export type LogisticItem = {
/** 时间 */
time: string
}
/** 订单列表参数 */
export type OrderListParams = PageParams & { orderState: number }
/** 订单列表 */
export type OrderListResult = {
/** 总记录数 */
counts: number
/** 数据集合 [ 订单信息 ] */
items: OrderItem[]
/** 当前页码 */
page: number
/** 总页数 */
pages: number
/** 页尺寸 */
pageSize: number
}
/** 订单列表项 */
export type OrderItem = OrderResult & {
/** 总件数 */
totalNum: number
}
Loading…
Cancel
Save