Quincy_J 29734666a6 1
2025-07-29 20:18:40 +08:00

241 lines
7.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>