feat: add paid resource order flow

This commit is contained in:
王鹏
2026-07-29 14:35:13 +08:00
parent d14f005d34
commit 01c382522a
10 changed files with 1202 additions and 57 deletions

View File

@@ -0,0 +1,330 @@
<template>
<view class="order-page">
<view class="page-title">我的订单</view>
<view v-if="orderList.length" class="order-list">
<view v-for="item in orderList" :key="item.orderNo" class="order-card">
<view class="order-head">
<text class="order-no">订单号{{item.orderNo}}</text>
<text class="order-status" :class="'status-' + item.status">{{statusText(item.status)}}</text>
</view>
<view class="resource-title">{{item.resourceTitle || '资源已删除'}}</view>
<view class="order-row">
<text class="row-label">购买版本</text>
<text class="row-value spec-name">{{item.specName || '旧版整项资源'}}</text>
</view>
<view class="order-row">
<text class="row-label">下单时间</text>
<text class="row-value">{{item.createTime || '-'}}</text>
</view>
<view class="order-footer">
<view class="price-box">
<text class="price-label">实付</text>
<text class="price-value">¥{{formatPrice(item.priceFen)}}</text>
</view>
<view class="order-actions">
<view
v-if="item.status === 0"
class="order-action cancel-action"
:class="{'action-disabled': cancellingOrderNo === item.orderNo}"
@click.stop="cancelOrder(item)"
>取消订单</view>
<view class="order-action" @click="openResource(item)">{{actionText(item.status)}}</view>
</view>
</view>
</view>
</view>
<view v-else-if="!loading" class="empty-box">
<text class="cuIcon-form empty-icon"></text>
<view class="empty-title">暂无购买订单</view>
<view class="empty-tip">购买付费资源后订单会显示在这里</view>
</view>
<view v-if="loading" class="loading-text">加载中...</view>
<view v-else-if="orderList.length && !hasMore" class="bottom-text"> 已经到底了 </view>
</view>
</template>
<script>
import {
listMyVirtualResourceOrders,
cancelVirtualResourceOrder
} from "@/api/app/index.js"
export default {
data() {
return {
queryParams: {
pageNum: 1,
pageSize: 10
},
orderList: [],
total: 0,
loading: false,
hasMore: true,
cancellingOrderNo: ''
}
},
onShow() {
this.loadOrders(true)
},
onReachBottom() {
if (!this.loading && this.hasMore) {
this.queryParams.pageNum++
this.loadOrders(false)
}
},
methods: {
loadOrders(reset) {
if (this.loading) {
return
}
if (reset) {
this.queryParams.pageNum = 1
this.orderList = []
this.total = 0
this.hasMore = true
}
this.loading = true
listMyVirtualResourceOrders(this.queryParams).then(response => {
var rows = response.rows || []
this.orderList = reset ? rows : this.orderList.concat(rows)
this.total = Number(response.total || 0)
this.hasMore = this.orderList.length < this.total
this.loading = false
}).catch(() => {
this.loading = false
})
},
statusText(status) {
return {
0: '待支付',
1: '已支付',
2: '已退款',
3: '已关闭'
}[status] || '未知状态'
},
actionText(status) {
return status === 1 ? '查看资源' : (status === 0 ? '继续支付' : '重新购买')
},
formatPrice(priceFen) {
return (Number(priceFen || 0) / 100).toFixed(2)
},
cancelOrder(item) {
if (item.status !== 0 || this.cancellingOrderNo) {
return
}
uni.showModal({
title: '取消订单',
content: '确定要取消这笔待支付订单吗?',
confirmText: '取消订单',
confirmColor: '#e54d42',
success: result => {
if (!result.confirm) {
return
}
this.cancellingOrderNo = item.orderNo
cancelVirtualResourceOrder(item.orderNo).then(() => {
item.status = 3
uni.showToast({
title: '订单已取消',
icon: 'success'
})
this.cancellingOrderNo = ''
}).catch(() => {
this.cancellingOrderNo = ''
this.loadOrders(true)
})
}
})
},
openResource(item) {
if (!item.resourceId) {
return
}
var url = '/pages/blog/resource?id=' + item.resourceId + '&type=1'
if (item.resourceListId) {
url += '&resourceListId=' + item.resourceListId
}
this.$tab.navigateTo(url)
}
}
}
</script>
<style>
page {
background: #f5f6f8;
}
.order-page {
min-height: 100vh;
padding: 28rpx;
box-sizing: border-box;
}
.page-title {
margin: 10rpx 4rpx 28rpx;
font-size: 40rpx;
font-weight: 600;
color: #202020;
}
.order-card {
margin-bottom: 24rpx;
padding: 28rpx;
border-radius: 22rpx;
background: #ffffff;
box-shadow: 0 8rpx 24rpx rgba(50, 50, 50, 0.05);
}
.order-head,
.order-row,
.order-footer {
display: flex;
align-items: center;
justify-content: space-between;
}
.order-head {
padding-bottom: 20rpx;
border-bottom: 1rpx solid #eeeeee;
}
.order-no {
max-width: 500rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 23rpx;
color: #9a9a9a;
}
.order-status {
font-size: 25rpx;
color: #8a8a8a;
}
.status-0 {
color: #ff9700;
}
.status-1 {
color: #20a05a;
}
.status-2 {
color: #e54d42;
}
.resource-title {
margin: 24rpx 0;
font-size: 31rpx;
font-weight: 600;
line-height: 1.5;
color: #242424;
}
.order-row {
margin-top: 16rpx;
font-size: 26rpx;
line-height: 1.5;
}
.row-label {
flex-shrink: 0;
color: #999999;
}
.row-value {
margin-left: 28rpx;
text-align: right;
color: #555555;
}
.spec-name {
color: #7258ee;
}
.order-footer {
margin-top: 26rpx;
padding-top: 22rpx;
border-top: 1rpx solid #eeeeee;
}
.price-label {
margin-right: 10rpx;
font-size: 24rpx;
color: #777777;
}
.price-value {
font-size: 34rpx;
font-weight: 600;
color: #e54d42;
}
.order-action {
min-width: 150rpx;
height: 58rpx;
padding: 0 22rpx;
border: 2rpx solid #765cf4;
border-radius: 999rpx;
line-height: 58rpx;
text-align: center;
font-size: 25rpx;
color: #765cf4;
}
.order-actions {
display: flex;
align-items: center;
}
.order-actions .order-action + .order-action {
margin-left: 16rpx;
}
.cancel-action {
min-width: 130rpx;
border-color: #d8d8d8;
color: #777777;
}
.action-disabled {
opacity: 0.5;
}
.empty-box {
padding-top: 220rpx;
text-align: center;
color: #a5a5a5;
}
.empty-icon {
font-size: 100rpx;
color: #c8cfdb;
}
.empty-title {
margin-top: 24rpx;
font-size: 31rpx;
color: #777777;
}
.empty-tip {
margin-top: 12rpx;
font-size: 25rpx;
}
.loading-text,
.bottom-text {
padding: 28rpx 0 40rpx;
text-align: center;
font-size: 24rpx;
color: #aaaaaa;
}
</style>