241 lines
7.2 KiB
Vue
241 lines
7.2 KiB
Vue
<route lang="json5" type="page">
|
||
{
|
||
layout: 'default',
|
||
style: {
|
||
navigationBarTitleText: '退款记录',
|
||
},
|
||
}
|
||
</route>
|
||
|
||
<template>
|
||
<view class="min-h-screen bg-gray-50 pb-20">
|
||
<!-- 消费统计 -->
|
||
<view class="mx-4 mt-4">
|
||
<view class="bg-white rounded-2xl shadow-sm p-6">
|
||
<view class="text-center">
|
||
<text class="text-lg font-bold text-gray-800 mb-2 block">退款统计</text>
|
||
<view class="grid grid-cols-2 gap-4">
|
||
<view class="text-center">
|
||
<text class="text-2xl font-bold text-sky-500 block">¥{{ totalSpend }}</text>
|
||
<text class="text-sm text-gray-500">总退款数</text>
|
||
</view>
|
||
<view class="text-center">
|
||
<text class="text-2xl font-bold text-indigo-500 block">{{ spendCount }}</text>
|
||
<text class="text-sm text-gray-500">退款次数</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 消费记录列表 -->
|
||
<view class="mx-4 mt-4">
|
||
<view class="bg-white rounded-2xl shadow-sm overflow-hidden">
|
||
<view class="p-4 border-b border-gray-100 flex justify-between items-center">
|
||
<text class="text-base font-bold text-gray-800">退款明细</text>
|
||
<text class="text-sm text-sky-500" @tap="refreshData">刷新</text>
|
||
</view>
|
||
<view v-if="loading" class="p-8 text-center">
|
||
<text class="text-gray-500">加载中...</text>
|
||
</view>
|
||
<view v-else-if="error" class="p-8 text-center">
|
||
<text class="text-red-500">{{ error }}</text>
|
||
</view>
|
||
<view v-else-if="spendList.length === 0" class="p-8 text-center">
|
||
<text class="text-gray-500">暂无退款记录</text>
|
||
</view>
|
||
<view v-else class="divide-y divide-gray-100">
|
||
<view v-for="(item, index) in spendList" :key="index" class="p-4">
|
||
<!-- 顶部:退款金额和状态 -->
|
||
<view class="flex items-center justify-between mb-3">
|
||
<text class="text-lg font-bold text-rose-500">
|
||
-¥{{ formatPrice(item.refundPoints) }}
|
||
</text>
|
||
<view
|
||
:class="[
|
||
'px-3 py-1 rounded-full text-xs border',
|
||
item.refundStatus === '0'
|
||
? 'bg-yellow-50 text-yellow-600 border-yellow-100'
|
||
: item.refundStatus === '1'
|
||
? 'bg-green-50 text-green-600 border-green-100'
|
||
: 'bg-red-50 text-red-600 border-red-100',
|
||
]"
|
||
>
|
||
{{ getRefundStatusText(item.refundStatus) }}
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 中间:退款原因 -->
|
||
<view class="mb-3">
|
||
<view class="flex items-center mb-1">
|
||
<view
|
||
class="bg-sky-50 text-sky-600 px-2 py-0.5 rounded-full text-xs border border-sky-100 mr-2"
|
||
>
|
||
退款原因
|
||
</view>
|
||
<text class="text-gray-600 text-sm flex-1">{{ item.refundReason }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部:时间和操作按钮 -->
|
||
<view class="flex items-center justify-between">
|
||
<view class="flex flex-col space-y-1">
|
||
<text class="text-xs text-gray-500">
|
||
申请时间:{{ formatDate(item.createTime) }}
|
||
</text>
|
||
<text v-if="item.auditTime" class="text-xs text-gray-500">
|
||
审核时间:{{ formatDate(item.auditTime) }}
|
||
</text>
|
||
</view>
|
||
<button
|
||
v-if="item.refundStatus === '0'"
|
||
class="flex items-center justify-center bg-white border border-green-200 text-green-500 px-4 py-1.5 rounded-lg text-xs hover:bg-green-50 active:bg-green-100 transition-colors mr-0"
|
||
@tap="handleCancelRefund(item.id)"
|
||
>
|
||
<i class="i-carbon-close text-sm mr-1"></i>
|
||
撤销
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { ref, computed, onMounted } from 'vue'
|
||
import { getUserRefundInfoAPI, cancelRefundAPI } from '@/service/login'
|
||
import type { RefundInfoList } from '@/service/login/type'
|
||
|
||
const spendList = ref<RefundInfoList[]>([])
|
||
const loading = ref(false)
|
||
const error = ref('')
|
||
|
||
// 计算总消费
|
||
const totalSpend = computed(() => {
|
||
return spendList.value.reduce((sum, item) => sum + Number(item.refundPoints), 0).toFixed(2)
|
||
})
|
||
|
||
// 计算消费次数
|
||
const spendCount = computed(() => spendList.value.length)
|
||
|
||
// 获取消费类型文本
|
||
const getSpendTypeText = (type: number) => {
|
||
const typeMap: Record<number, string> = {
|
||
1: '解锁用户',
|
||
2: '充值',
|
||
3: '其他',
|
||
}
|
||
return typeMap[type] || '未知类型'
|
||
}
|
||
|
||
// 格式化日期
|
||
const formatDate = (dateStr: string) => {
|
||
try {
|
||
const date = new Date(dateStr)
|
||
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')}`
|
||
} catch (e) {
|
||
return dateStr
|
||
}
|
||
}
|
||
|
||
// 格式化价格
|
||
const formatPrice = (price: string) => {
|
||
try {
|
||
return Number(price).toFixed(2)
|
||
} catch (e) {
|
||
return '0.00'
|
||
}
|
||
}
|
||
|
||
// 获取消费记录
|
||
const getSpendList = async () => {
|
||
loading.value = true
|
||
error.value = ''
|
||
|
||
try {
|
||
const res = await getUserRefundInfoAPI()
|
||
if (res.code === 200) {
|
||
spendList.value = res.data || []
|
||
} else {
|
||
error.value = res.message || '获取充值记录失败'
|
||
uni.showToast({
|
||
title: error.value,
|
||
icon: 'none',
|
||
duration: 2000,
|
||
})
|
||
}
|
||
} catch (e) {
|
||
error.value = '网络请求失败,请稍后重试'
|
||
uni.showToast({
|
||
title: error.value,
|
||
icon: 'none',
|
||
duration: 2000,
|
||
})
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 刷新数据
|
||
const refreshData = () => {
|
||
getSpendList()
|
||
}
|
||
|
||
// 获取退款状态文本
|
||
const getRefundStatusText = (status: string) => {
|
||
const statusMap: Record<string, string> = {
|
||
'0': '审核中',
|
||
'1': '已通过',
|
||
'2': '已拒绝',
|
||
}
|
||
return statusMap[status] || '未知状态'
|
||
}
|
||
|
||
// 处理撤销退款
|
||
const handleCancelRefund = async (id: string) => {
|
||
try {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要撤销该退款申请吗?',
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
uni.showLoading({
|
||
title: '处理中...',
|
||
mask: true,
|
||
})
|
||
|
||
const result = await cancelRefundAPI(id)
|
||
|
||
if (result.code === 200) {
|
||
uni.showToast({
|
||
title: '撤销成功',
|
||
icon: 'success',
|
||
})
|
||
// 刷新列表
|
||
getSpendList()
|
||
} else {
|
||
uni.showToast({
|
||
title: result.message || '撤销失败',
|
||
icon: 'none',
|
||
})
|
||
}
|
||
}
|
||
},
|
||
})
|
||
} catch (error) {
|
||
uni.showToast({
|
||
title: '操作失败,请稍后重试',
|
||
icon: 'none',
|
||
})
|
||
} finally {
|
||
uni.hideLoading()
|
||
}
|
||
}
|
||
|
||
onMounted(() => {
|
||
getSpendList()
|
||
})
|
||
</script>
|