feat: add superadmin wallet view
This commit is contained in:
@@ -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');
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user