feat: add superadmin wallet view

This commit is contained in:
2026-01-15 11:21:37 +08:00
parent 37325ab1b4
commit 56082bad4f
10 changed files with 495 additions and 5 deletions

View File

@@ -84,6 +84,10 @@ export const UserService = {
if (!userID) throw new Error('userID is required');
return requestJson(`/super/v1/users/${userID}`);
},
async getUserWallet(userID) {
if (!userID) throw new Error('userID is required');
return requestJson(`/super/v1/users/${userID}/wallet`);
},
async listUserTenants(userID, { page, limit, tenant_id, code, name, role, status, created_at_from, created_at_to } = {}) {
if (!userID) throw new Error('userID is required');

View File

@@ -15,6 +15,9 @@ const userID = computed(() => Number(route.params.userID));
const loading = ref(false);
const user = ref(null);
const wallet = ref(null);
const walletLoading = ref(false);
const tabValue = ref('owned');
function formatDate(value) {
@@ -31,6 +34,25 @@ function formatCny(amountInCents) {
return new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY' }).format(amount);
}
function formatWalletFlow(value) {
if (value === 'income') return '收入';
if (value === 'expense') return '支出';
return value || '-';
}
function formatOrderType(value) {
switch (value) {
case 'content_purchase':
return '内容购买';
case 'recharge':
return '充值';
case 'withdrawal':
return '提现';
default:
return value || '-';
}
}
function getStatusSeverity(status) {
switch (status) {
case 'active':
@@ -65,6 +87,19 @@ async function loadUser() {
}
}
async function loadWallet() {
const id = userID.value;
if (!id || Number.isNaN(id)) return;
walletLoading.value = true;
try {
wallet.value = await UserService.getUserWallet(id);
} catch (error) {
toast.add({ severity: 'error', summary: '加载失败', detail: error?.message || '无法加载钱包信息', life: 4000 });
} finally {
walletLoading.value = false;
}
}
const statusDialogVisible = ref(false);
const statusLoading = ref(false);
const statusOptionsLoading = ref(false);
@@ -237,6 +272,7 @@ watch(
ownedTenantsPage.value = 1;
joinedTenantsPage.value = 1;
loadUser();
loadWallet();
loadOwnedTenants();
loadJoinedTenants();
},
@@ -306,6 +342,7 @@ onMounted(() => {
<TabList>
<Tab value="owned">拥有的租户</Tab>
<Tab value="joined">加入的租户</Tab>
<Tab value="wallet">钱包</Tab>
</TabList>
<TabPanels>
<TabPanel value="owned">
@@ -453,6 +490,54 @@ onMounted(() => {
</DataTable>
</div>
</TabPanel>
<TabPanel value="wallet">
<div class="flex flex-col gap-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-6">
<div>
<div class="text-sm text-muted-color">可用余额</div>
<div class="font-medium">{{ formatCny(wallet?.balance) }}</div>
</div>
<div>
<div class="text-sm text-muted-color">冻结余额</div>
<div class="font-medium">{{ formatCny(wallet?.balance_frozen) }}</div>
</div>
</div>
<Button label="刷新" icon="pi pi-refresh" severity="secondary" @click="loadWallet" :disabled="walletLoading" />
</div>
<DataTable :value="wallet?.transactions || []" dataKey="id" :loading="walletLoading" scrollable scrollHeight="420px" responsiveLayout="scroll">
<Column field="id" header="订单ID" style="min-width: 8rem" />
<Column field="order_type" header="类型" style="min-width: 10rem">
<template #body="{ data }">
{{ formatOrderType(data.order_type) }}
</template>
</Column>
<Column field="type" header="流向" style="min-width: 8rem">
<template #body="{ data }">
{{ formatWalletFlow(data.type) }}
</template>
</Column>
<Column field="amount" header="金额" style="min-width: 10rem">
<template #body="{ data }">
{{ formatCny(data.amount) }}
</template>
</Column>
<Column header="租户" style="min-width: 16rem">
<template #body="{ data }">
<div class="flex flex-col">
<span class="font-medium">{{ data.tenant_name || '平台/系统' }}</span>
<span class="text-xs text-muted-color">Code: {{ data.tenant_code || '-' }} / ID: {{ data.tenant_id ?? '-' }}</span>
</div>
</template>
</Column>
<Column field="date" header="时间" style="min-width: 14rem">
<template #body="{ data }">
{{ formatDate(data.date) }}
</template>
</Column>
</DataTable>
</div>
</TabPanel>
</TabPanels>
</Tabs>
</div>