121 lines
4.3 KiB
Vue
121 lines
4.3 KiB
Vue
<template>
|
|
<section class="m-page m-page--white m-finance-records">
|
|
<PageHeader title="记录" />
|
|
<div class="m-finance-tabs" role="tablist">
|
|
<button
|
|
v-for="item in tabs"
|
|
:key="item.value"
|
|
:class="{ active: tab === item.value }"
|
|
@click="changeTab(item.value)"
|
|
>
|
|
{{ item.label }}
|
|
</button>
|
|
</div>
|
|
<AsyncState
|
|
:loading="loading"
|
|
:error="error"
|
|
:empty="!visibleRecords.length"
|
|
empty-text="暂无相关记录"
|
|
@retry="load"
|
|
>
|
|
<div class="m-finance-list">
|
|
<button v-for="item in visibleRecords" :key="`${item.type}-${item.id}`" type="button">
|
|
<span class="m-finance-icon" :class="`is-${item.type}`">
|
|
<img
|
|
:src="item.type === 'recharge' ? mobileAssets.rechargeRecord : mobileAssets.withdrawalRecord"
|
|
alt=""
|
|
/>
|
|
</span>
|
|
<span class="m-finance-main">
|
|
<b>{{ item.no }}</b>
|
|
<time>{{ dateTime(item.created_at) }}</time>
|
|
</span>
|
|
<span class="m-finance-result">
|
|
<b>{{ item.type === 'recharge' ? '+' : '-' }}{{ plainMoney(item.amount) }}</b>
|
|
<em :class="item.success ? 'is-success' : 'is-failed'">{{ item.status_text }}</em>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</AsyncState>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, onMounted, ref } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import PageHeader from '../components/PageHeader.vue';
|
|
import AsyncState from '../components/AsyncState.vue';
|
|
import { dateTime, errorText, request } from '../api';
|
|
import { mobileAssets } from '../assets';
|
|
|
|
type RecordType = 'all' | 'recharge' | 'withdrawal';
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const tabs: { label: string; value: RecordType }[] = [
|
|
{ label: '全部', value: 'all' },
|
|
{ label: '储入记录', value: 'recharge' },
|
|
{ label: '取出记录', value: 'withdrawal' },
|
|
];
|
|
const requestedTab = String(route.query.tab || 'all');
|
|
const tab = ref<RecordType>(
|
|
requestedTab === 'recharge' || requestedTab === 'withdrawal' ? requestedTab : 'all'
|
|
);
|
|
const loading = ref(true);
|
|
const error = ref('');
|
|
const records = ref<any[]>([]);
|
|
const visibleRecords = computed(() =>
|
|
tab.value === 'all' ? records.value : records.value.filter((item) => item.type === tab.value)
|
|
);
|
|
|
|
const successful = new Set(['succeeded', 'completed', 'paid']);
|
|
const plainMoney = (value: number) => (Number(value || 0) / 100).toFixed(2);
|
|
function normalize(item: any, type: 'recharge' | 'withdrawal') {
|
|
const success = successful.has(item.status);
|
|
return {
|
|
id: item.id,
|
|
type,
|
|
no: item.recharge_no || item.withdrawal_no || `SW${item.id}`,
|
|
amount: item.request_amount || item.amount || 0,
|
|
created_at: item.created_at,
|
|
status_text:
|
|
item.status_text || `${type === 'recharge' ? '储入' : '取出'}${success ? '成功' : '失败'}`,
|
|
success,
|
|
};
|
|
}
|
|
async function load() {
|
|
loading.value = true;
|
|
error.value = '';
|
|
try {
|
|
const [rechargeResult, withdrawalResult] = await Promise.allSettled([
|
|
request<any>({
|
|
url: '/v1/recharge-orders',
|
|
params: { page: 1, page_size: 50, status: 'all' },
|
|
}),
|
|
request<any>({
|
|
url: '/v1/withdrawal-orders',
|
|
params: { page: 1, page_size: 50, status: 'all' },
|
|
}),
|
|
]);
|
|
if (rechargeResult.status === 'rejected' && withdrawalResult.status === 'rejected') {
|
|
throw withdrawalResult.reason;
|
|
}
|
|
const recharge = rechargeResult.status === 'fulfilled' ? rechargeResult.value.items || [] : [];
|
|
const withdrawals =
|
|
withdrawalResult.status === 'fulfilled' ? withdrawalResult.value.items || [] : [];
|
|
records.value = [
|
|
...recharge.map((item: any) => normalize(item, 'recharge')),
|
|
...withdrawals.map((item: any) => normalize(item, 'withdrawal')),
|
|
].sort((a, b) => String(b.created_at).localeCompare(String(a.created_at)));
|
|
} catch (err) {
|
|
error.value = errorText(err);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
async function changeTab(value: RecordType) {
|
|
tab.value = value;
|
|
await router.replace({ query: value === 'all' ? {} : { tab: value } });
|
|
}
|
|
onMounted(load);
|
|
</script>
|