rentease-app/pages/billing/payment-record.vue

404 lines
9.0 KiB
Vue
Raw Normal View History

2026-04-20 06:23:11 +00:00
<template>
<view class="payment-record-page">
<!-- 自定义导航栏 -->
<view class="custom-nav safe-area-top">
<view class="nav-content">
<view class="nav-btn" @click="goBack">
<uni-icons type="left" size="22" color="#1E293B"></uni-icons>
</view>
<text class="nav-title">支付记录</text>
<view class="nav-btn" @click="refreshData">
<uni-icons type="refresh" size="20" color="#64748B"></uni-icons>
</view>
</view>
</view>
<!-- 统计卡片 -->
<view class="stats-section">
<view class="stats-card">
<text class="stats-label">累计支付</text>
<text class="stats-value">¥{{totalAmount}}</text>
</view>
<view class="stats-card">
<text class="stats-label">支付次数</text>
<text class="stats-value">{{totalCount}}</text>
</view>
</view>
<scroll-view
scroll-y
class="page-content"
@scrolltolower="loadMore"
refresher-enabled
:refresher-triggered="refreshing"
@refresherrefresh="onRefresh"
>
<!-- 记录列表 -->
<view class="record-list" v-if="payments.length > 0">
<view
v-for="(payment, index) in payments"
:key="payment.id"
class="record-card"
>
<view class="record-header">
<view class="payment-icon" :class="payment.paymentMethod">
<text>{{getPaymentMethodIcon(payment.paymentMethod)}}</text>
</view>
<view class="payment-info">
<text class="payment-title">{{getPaymentTitle(payment)}}</text>
<text class="payment-time">{{formatDateTime(payment.payTime)}}</text>
</view>
<view class="payment-amount">
<text class="amount">¥{{payment.amount}}</text>
</view>
</view>
<view class="record-body">
<view class="record-item">
<text class="item-label">订单编号</text>
<text class="item-value">{{payment.orderNo}}</text>
</view>
<view class="record-item" v-if="payment.transactionId">
<text class="item-label">交易号</text>
<text class="item-value">{{payment.transactionId}}</text>
</view>
<view class="record-item">
<text class="item-label">支付方式</text>
<text class="item-value">{{getPaymentMethodText(payment.paymentMethod)}}</text>
</view>
</view>
</view>
<!-- 加载更多 -->
<view class="load-more" v-if="hasMore">
<text v-if="loading">加载中...</text>
<text v-else @click="loadMore">加载更多</text>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" v-else>
<uni-icons type="wallet-filled" size="80" color="#E4E7ED"></uni-icons>
<text class="empty-title">暂无支付记录</text>
<text class="empty-desc">您还没有支付记录</text>
</view>
<view class="safe-area-bottom" style="height: 40rpx;"></view>
</scroll-view>
</view>
</template>
<script>
import { billingApi } from '@/api/index.js'
export default {
data() {
return {
payments: [],
totalAmount: 0,
totalCount: 0,
page: 1,
pageSize: 10,
hasMore: true,
loading: false,
refreshing: false
}
},
onLoad() {
this.loadPayments()
},
onShow() {
this.refreshData()
},
methods: {
async loadPayments() {
if (this.loading || !this.hasMore) return
this.loading = true
try {
const res = await billingApi.getPayments({
page: this.page,
pageSize: this.pageSize
})
if (res.code === 200) {
const newPayments = res.data.list || []
if (this.page === 1) {
this.payments = newPayments
} else {
this.payments = [...this.payments, ...newPayments]
}
this.totalAmount = res.data.totalAmount || 0
this.totalCount = res.data.totalCount || 0
this.hasMore = newPayments.length >= this.pageSize
}
} catch (error) {
console.error('加载支付记录失败:', error)
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
this.loading = false
this.refreshing = false
}
},
onRefresh() {
this.refreshing = true
this.page = 1
this.hasMore = true
this.loadPayments()
},
refreshData() {
this.page = 1
this.hasMore = true
this.loadPayments()
},
loadMore() {
if (this.hasMore && !this.loading) {
this.page++
this.loadPayments()
}
},
getPaymentMethodIcon(method) {
const map = {
alipay: '支',
wechat: '微',
bank: '银'
}
return map[method] || '付'
},
getPaymentMethodText(method) {
const map = {
alipay: '支付宝',
wechat: '微信支付',
bank: '银行转账'
}
return map[method] || method || '-'
},
getPaymentTitle(payment) {
if (payment.subscriptionPlan) {
return payment.subscriptionPlan.name
}
return '套餐购买'
},
formatDateTime(dateTime) {
if (!dateTime) return '-'
const date = new Date(dateTime)
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
},
goBack() {
uni.navigateBack()
}
}
}
</script>
<style scoped>
.payment-record-page {
min-height: 100vh;
background: #F8FAFC;
display: flex;
flex-direction: column;
}
/* 导航栏 */
.custom-nav {
background: #FFFFFF;
border-bottom: 2rpx solid #F1F5F9;
}
.nav-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 32rpx;
}
.nav-btn {
width: 72rpx;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.nav-title {
font-size: 34rpx;
font-weight: 600;
color: #1E293B;
}
/* 统计区域 */
.stats-section {
display: flex;
gap: 24rpx;
padding: 24rpx 32rpx;
background: #FFFFFF;
border-bottom: 2rpx solid #F1F5F9;
}
.stats-card {
flex: 1;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 20rpx;
padding: 32rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.stats-label {
font-size: 26rpx;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 12rpx;
}
.stats-value {
font-size: 40rpx;
font-weight: 700;
color: #FFFFFF;
}
/* 页面内容 */
.page-content {
flex: 1;
padding: 24rpx 32rpx;
}
/* 记录列表 */
.record-list {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.record-card {
background: #FFFFFF;
border-radius: 24rpx;
padding: 28rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
.record-header {
display: flex;
align-items: center;
gap: 20rpx;
margin-bottom: 20rpx;
padding-bottom: 20rpx;
border-bottom: 2rpx solid #F1F5F9;
}
.payment-icon {
width: 72rpx;
height: 72rpx;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
}
.payment-icon.alipay {
background: #1677FF;
}
.payment-icon.wechat {
background: #07C160;
}
.payment-icon.bank {
background: #FF6B6B;
}
.payment-icon text {
font-size: 32rpx;
color: #FFFFFF;
font-weight: 700;
}
.payment-info {
flex: 1;
}
.payment-title {
display: block;
font-size: 30rpx;
font-weight: 600;
color: #1E293B;
margin-bottom: 8rpx;
}
.payment-time {
display: block;
font-size: 24rpx;
color: #94A3B8;
}
.payment-amount {
text-align: right;
}
.payment-amount .amount {
font-size: 36rpx;
font-weight: 700;
color: #F56C6C;
}
.record-body {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.record-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.item-label {
font-size: 26rpx;
color: #64748B;
}
.item-value {
font-size: 26rpx;
color: #1E293B;
}
/* 加载更多 */
.load-more {
text-align: center;
padding: 32rpx;
color: #64748B;
font-size: 26rpx;
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 32rpx;
}
.empty-title {
font-size: 32rpx;
font-weight: 600;
color: #1E293B;
margin-top: 32rpx;
margin-bottom: 16rpx;
}
.empty-desc {
font-size: 26rpx;
color: #64748B;
}
</style>