campus-errand/miniapp/pages/mine/earnings-record.vue
18631081161 681d2b5fe8
All checks were successful
continuous-integration/drone/push Build is passing
提现
2026-04-02 16:55:18 +08:00

234 lines
5.2 KiB
Vue

<template>
<view class="record-page">
<!-- 自定义导航栏 -->
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="navbar-content">
<view class="nav-back" @click="goBack">
<image class="back-icon" src="/static/ic_back.png" mode="aspectFit"></image>
</view>
<text class="navbar-title">收益记录</text>
<view class="nav-placeholder"></view>
</view>
</view>
<view :style="{ height: (statusBarHeight + 44) + 'px' }"></view>
<view v-if="loading" class="loading-tip">加载中...</view>
<view v-else-if="records.length === 0" class="empty-tip">
<text>暂无收益记录</text>
</view>
<!-- 收益记录列表 -->
<view v-for="item in records" :key="item.id" class="record-card">
<view class="record-header">
<text class="record-type">{{ getTypeLabel(item.orderType) }}</text>
<text class="record-time">{{ formatTime(item.createdAt) }}</text>
</view>
<view class="record-body">
<view class="record-row">
<text class="record-label">订单号</text>
<text class="record-value">{{ item.orderNo }}</text>
</view>
<view class="record-row" v-if="item.completedAt">
<text class="record-label">完成时间</text>
<text class="record-value">{{ formatTime(item.completedAt) }}</text>
</view>
<view class="record-row" v-if="item.goodsAmount">
<text class="record-label">垫付商品金额</text>
<text class="record-value">¥{{ item.goodsAmount }}</text>
</view>
<view class="record-row">
<text class="record-label">跑腿佣金</text>
<text class="record-value price">¥{{ item.commission }}</text>
</view>
<view class="record-row" v-if="item.platformFee">
<text class="record-label">平台抽成</text>
<text class="record-value">-¥{{ item.platformFee }}</text>
</view>
<view class="record-row">
<text class="record-label">实得收益</text>
<text class="record-value highlight">¥{{ item.netEarning }}</text>
</view>
</view>
<view class="record-footer">
<view class="view-order-btn" @click="goOrderDetail(item.orderId)">
<text>查看订单</text>
</view>
</view>
</view>
</view>
</template>
<script>
import { getEarningsRecords } from '../../utils/api'
export default {
data() {
return {
records: [],
loading: false,
statusBarHeight: 0
}
},
onLoad() {
const sysInfo = uni.getSystemInfoSync()
this.statusBarHeight = sysInfo.statusBarHeight || 0
this.loadRecords()
},
methods: {
goBack() { uni.navigateBack() },
/** 加载收益记录 */
async loadRecords() {
this.loading = true
try {
const res = await getEarningsRecords()
this.records = res?.items || res || []
} catch (e) {
this.records = []
} finally {
this.loading = false
}
},
getTypeLabel(type) {
const map = { Pickup: '代取', Delivery: '代送', Help: '万能帮', Purchase: '代购', Food: '美食街' }
return map[type] || type || '跑腿'
},
/** 跳转订单详情 */
goOrderDetail(orderId) {
if (!orderId) return
uni.navigateTo({ url: `/pages/order/order-detail?id=${orderId}` })
},
formatTime(dateStr) {
if (!dateStr) return '-'
const d = new Date(typeof dateStr === 'string' && !dateStr.endsWith('Z') ? dateStr + 'Z' : dateStr)
const pad = (n) => String(n).padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
}
}
}
</script>
<style scoped>
/* 自定义导航栏 */
.custom-navbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 999;
background: #FFB700;
}
.navbar-content {
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20rpx;
}
.nav-back {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 40rpx;
height: 40rpx;
}
.navbar-title {
font-size: 34rpx;
font-weight: bold;
color: #363636;
}
.nav-placeholder {
width: 60rpx;
}
.record-page {
min-height: 100vh;
background-color: #f5f5f5;
padding: 16rpx 24rpx;
}
.loading-tip, .empty-tip {
text-align: center;
color: #999999;
font-size: 28rpx;
padding: 80rpx 0;
}
.record-card {
background-color: #ffffff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 16rpx;
}
.record-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
padding-bottom: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.record-type {
font-size: 26rpx;
color: #ffffff;
background-color: #FFB700;
padding: 4rpx 16rpx;
border-radius: 8rpx;
}
.record-time {
font-size: 24rpx;
color: #999999;
}
.record-row {
display: flex;
justify-content: space-between;
padding: 8rpx 0;
}
.record-label {
font-size: 26rpx;
color: #999999;
}
.record-value {
font-size: 26rpx;
color: #333333;
}
.record-value.price {
color: #e64340;
}
.record-value.highlight {
color: #52c41a;
font-weight: bold;
}
.record-footer {
display: flex;
justify-content: flex-end;
padding-top: 16rpx;
border-top: 1rpx solid #f0f0f0;
margin-top: 12rpx;
}
.view-order-btn {
padding: 10rpx 28rpx;
border: 1rpx solid #FFB700;
border-radius: 32rpx;
}
.view-order-btn text {
font-size: 24rpx;
color: #FFB700;
}
</style>