111
This commit is contained in:
@@ -16,151 +16,191 @@ const isLoading = computed(() => overviewLoading.value || cashFlowLoading.value)
|
||||
const overview = computed(() => overviewData.value?.data)
|
||||
const cashFlow = computed(() => cashFlowData.value?.data || [])
|
||||
|
||||
// ========== 模块1: 资金概览 ==========
|
||||
const fundMetrics = computed(() => [
|
||||
{
|
||||
label: '在管资金',
|
||||
value: overview.value?.fundBalance || 0,
|
||||
icon: 'lucide:wallet',
|
||||
color: 'text-blue-600',
|
||||
bgColor: 'bg-blue-50 dark:bg-blue-950',
|
||||
},
|
||||
{
|
||||
label: '交易账户',
|
||||
value: overview.value?.tradeValue || 0,
|
||||
icon: 'lucide:bar-chart-3',
|
||||
color: 'text-purple-600',
|
||||
bgColor: 'bg-purple-50 dark:bg-purple-950',
|
||||
},
|
||||
{
|
||||
label: '总资产',
|
||||
value: (overview.value?.fundBalance || 0) + (overview.value?.tradeValue || 0),
|
||||
icon: 'lucide:landmark',
|
||||
color: 'text-orange-600',
|
||||
bgColor: 'bg-orange-50 dark:bg-orange-950',
|
||||
},
|
||||
])
|
||||
// ========== 工具函数 ==========
|
||||
|
||||
// ========== 模块2: 资金流动 ==========
|
||||
function calcGrowthRate(current: number, previous: number): string {
|
||||
if (previous === 0)
|
||||
return current > 0 ? '+100%' : '0%'
|
||||
const rate = new Decimal(current).minus(previous).div(previous).mul(100).toDecimalPlaces(1)
|
||||
const sign = rate.gte(0) ? '+' : ''
|
||||
return `{sign}{rate}%`
|
||||
function formatCurrency(value: number | undefined): string {
|
||||
const v = value || 0
|
||||
if (v >= 100_000_000)
|
||||
return `${(v / 100_000_000).toFixed(2)}亿`
|
||||
if (v >= 10_000)
|
||||
return `${(v / 10_000).toFixed(1)}万`
|
||||
return v.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||
}
|
||||
|
||||
const flowMetrics = computed(() => {
|
||||
const flow = cashFlow.value
|
||||
const len = flow.length
|
||||
const thisMonth = len >= 1 ? flow[len - 1] : null
|
||||
const lastMonth = len >= 2 ? flow[len - 2] : null
|
||||
function calcGrowthRate(current: number, previous: number): { text: string, up: boolean } {
|
||||
if (previous === 0) {
|
||||
return current > 0 ? { text: '+100%', up: true } : { text: '0%', up: true }
|
||||
}
|
||||
const rate = new Decimal(current).minus(previous).div(previous).mul(100).toDecimalPlaces(1)
|
||||
const sign = rate.gte(0) ? '+' : ''
|
||||
return { text: `${sign}${rate}%`, up: rate.gte(0) }
|
||||
}
|
||||
|
||||
const depositTrend = thisMonth && lastMonth
|
||||
? calcGrowthRate(thisMonth.deposit as number, lastMonth.deposit as number)
|
||||
: '+0%'
|
||||
const withdrawTrend = thisMonth && lastMonth
|
||||
? calcGrowthRate(thisMonth.withdraw as number, lastMonth.withdraw as number)
|
||||
: '+0%'
|
||||
const netInflowTrend = thisMonth && lastMonth
|
||||
? calcGrowthRate(thisMonth.netInflow as number, lastMonth.netInflow as number)
|
||||
: '+0%'
|
||||
// ========== 第一层:核心 KPI ==========
|
||||
|
||||
const kpiItems = computed(() => {
|
||||
const o = overview.value
|
||||
if (!o) return []
|
||||
|
||||
const netInflow = (o.totalDeposit || 0) - (o.totalWithdraw || 0)
|
||||
const depositGrowth = calcGrowthRate(o.monthlyDeposit, o.lastMonthDeposit)
|
||||
const withdrawGrowth = calcGrowthRate(o.monthlyWithdraw, o.lastMonthWithdraw)
|
||||
|
||||
// 净流入环比用充值环比近似(实际出款与提现趋势一致)
|
||||
const netMonthGrowth = calcGrowthRate(
|
||||
o.monthlyDeposit - o.monthlyWithdraw,
|
||||
o.lastMonthDeposit - o.lastMonthWithdraw,
|
||||
)
|
||||
|
||||
return [
|
||||
{
|
||||
label: '累计充值',
|
||||
value: overview.value?.totalDeposit || 0,
|
||||
icon: 'lucide:arrow-down-circle',
|
||||
color: 'text-green-600',
|
||||
bgColor: 'bg-green-50 dark:bg-green-950',
|
||||
trend: depositTrend,
|
||||
value: o.totalDeposit,
|
||||
icon: 'lucide:arrow-down-to-line',
|
||||
color: 'text-emerald-600',
|
||||
bgColor: 'bg-emerald-50 dark:bg-emerald-950/40',
|
||||
growth: depositGrowth,
|
||||
},
|
||||
{
|
||||
label: '累计提现',
|
||||
value: overview.value?.totalWithdraw || 0,
|
||||
icon: 'lucide:arrow-up-circle',
|
||||
color: 'text-red-600',
|
||||
bgColor: 'bg-red-50 dark:bg-red-950',
|
||||
trend: withdrawTrend,
|
||||
value: o.totalWithdraw,
|
||||
icon: 'lucide:arrow-up-from-line',
|
||||
color: 'text-red-500',
|
||||
bgColor: 'bg-red-50 dark:bg-red-950/40',
|
||||
growth: withdrawGrowth,
|
||||
},
|
||||
{
|
||||
label: '实际出款',
|
||||
value: o.totalActualPayout,
|
||||
icon: 'lucide:banknote',
|
||||
color: 'text-amber-600',
|
||||
bgColor: 'bg-amber-50 dark:bg-amber-950/40',
|
||||
growth: withdrawGrowth,
|
||||
},
|
||||
{
|
||||
label: '净流入',
|
||||
value: (overview.value?.totalDeposit || 0) - (overview.value?.totalWithdraw || 0),
|
||||
value: netInflow,
|
||||
icon: 'lucide:trending-up',
|
||||
color: 'text-emerald-600',
|
||||
bgColor: 'bg-emerald-50 dark:bg-emerald-950',
|
||||
trend: netInflowTrend,
|
||||
color: 'text-sky-600',
|
||||
bgColor: 'bg-sky-50 dark:bg-sky-950/40',
|
||||
growth: netMonthGrowth,
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
// ========== 模块3: 资金趋势图 ==========
|
||||
// ========== 第二层:资金趋势图 ==========
|
||||
|
||||
const trendChartOption = computed(() => ({
|
||||
tooltip: { trigger: 'axis' },
|
||||
legend: { data: ['充值', '提现'], bottom: 0, top: 'auto' },
|
||||
grid: { left: '3%', right: '4%', bottom: '15%', top: '5%', containLabel: true },
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter(params: any) {
|
||||
const items = Array.isArray(params) ? params : [params]
|
||||
const lines = items.map((p: any) =>
|
||||
`${p.marker} ${p.seriesName}: USDT ${Number(p.value).toLocaleString()}`,
|
||||
)
|
||||
return `<div style="font-size:12px"><b>${items[0].axisValue}</b><br/>${lines.join('<br/>')}</div>`
|
||||
},
|
||||
},
|
||||
legend: { data: ['充值', '提现'], bottom: 0 },
|
||||
grid: { left: '3%', right: '4%', bottom: '14%', top: '8%', containLabel: true },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: cashFlow.value.map((t: any) => t.month),
|
||||
axisTick: { show: false },
|
||||
axisLine: { lineStyle: { color: '#e5e7eb' } },
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: { formatter: 'USDT{value}K' },
|
||||
axisLabel: {
|
||||
formatter(value: number) {
|
||||
if (value >= 10_000) return `${(value / 10_000).toFixed(0)}万`
|
||||
return `${value}`
|
||||
},
|
||||
},
|
||||
splitLine: { lineStyle: { color: '#f3f4f6', type: 'dashed' } },
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '充值',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
data: cashFlow.value.map((t: any) => t.deposit),
|
||||
itemStyle: { color: '#10b981' },
|
||||
areaStyle: { color: 'rgba(16, 185, 129, 0.1)' },
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(16, 185, 129, 0.25)' },
|
||||
{ offset: 1, color: 'rgba(16, 185, 129, 0.02)' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '提现',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
data: cashFlow.value.map((t: any) => t.withdraw),
|
||||
itemStyle: { color: '#ef4444' },
|
||||
areaStyle: { color: 'rgba(239, 68, 68, 0.1)' },
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(239, 68, 68, 0.25)' },
|
||||
{ offset: 1, color: 'rgba(239, 68, 68, 0.02)' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}))
|
||||
|
||||
// ========== 模块4: 资金分布 ==========
|
||||
const distributionOption = computed(() => {
|
||||
const fundBalance = overview.value?.fundBalance || 0
|
||||
const tradeValue = overview.value?.tradeValue || 0
|
||||
// ========== 第二层:资产状态 ==========
|
||||
|
||||
return {
|
||||
tooltip: { trigger: 'item', formatter: '{b}: {d}%' },
|
||||
legend: { orient: 'vertical', right: '5%', top: 'center' },
|
||||
series: [{
|
||||
type: 'pie',
|
||||
radius: ['50%', '75%'],
|
||||
center: ['35%', '50%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: { borderRadius: 8, borderColor: '#fff', borderWidth: 2 },
|
||||
label: { show: true, position: 'inside', formatter: '{d}%', fontSize: 12 },
|
||||
data: [
|
||||
{ value: fundBalance, name: '在管资金', itemStyle: { color: '#3b82f6' } },
|
||||
{ value: tradeValue, name: '交易账户', itemStyle: { color: '#8b5cf6' } },
|
||||
],
|
||||
}],
|
||||
}
|
||||
const assetMetrics = computed(() => {
|
||||
const o = overview.value
|
||||
if (!o) return []
|
||||
const totalAssets = (o.fundBalance || 0) + (o.tradeValue || 0)
|
||||
|
||||
return [
|
||||
{
|
||||
label: '平台总资产',
|
||||
value: totalAssets,
|
||||
icon: 'lucide:landmark',
|
||||
color: 'text-violet-600',
|
||||
},
|
||||
{
|
||||
label: '在管资金',
|
||||
value: o.fundBalance,
|
||||
icon: 'lucide:wallet',
|
||||
color: 'text-blue-600',
|
||||
},
|
||||
{
|
||||
label: '冻结中',
|
||||
value: o.totalFrozen,
|
||||
icon: 'lucide:lock',
|
||||
color: 'text-slate-500',
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
// ========== 模块5: 运营指标 ==========
|
||||
const operationMetrics = computed(() => [
|
||||
{ label: '用户总数', value: overview.value?.userCount || 0, icon: 'lucide:users' },
|
||||
{ label: '待审批', value: overview.value?.pendingCount || 0, icon: 'lucide:clock' },
|
||||
])
|
||||
// ========== 第三层:运营快报 ==========
|
||||
|
||||
function formatCurrency(value: number): string {
|
||||
if (value >= 10000)
|
||||
return `USDT{(value / 10000).toFixed(1)}万`
|
||||
return `USDT{value.toLocaleString()}`
|
||||
}
|
||||
const operationMetrics = computed(() => {
|
||||
const o = overview.value
|
||||
if (!o) return []
|
||||
|
||||
return [
|
||||
{ label: '用户总数', value: o.userCount, icon: 'lucide:users', color: 'text-blue-600', bgColor: 'bg-blue-50 dark:bg-blue-950/40' },
|
||||
{ label: '今日活跃', value: o.todayActiveUsers, icon: 'lucide:activity', color: 'text-green-600', bgColor: 'bg-green-50 dark:bg-green-950/40' },
|
||||
{ label: '本月新增', value: o.monthNewUsers, icon: 'lucide:user-plus', color: 'text-purple-600', bgColor: 'bg-purple-50 dark:bg-purple-950/40' },
|
||||
{ label: '待审批', value: o.pendingCount, icon: 'lucide:clock', color: o.pendingCount > 0 ? 'text-amber-600' : 'text-slate-500', bgColor: o.pendingCount > 0 ? 'bg-amber-50 dark:bg-amber-950/40' : 'bg-slate-50 dark:bg-slate-950/40' },
|
||||
]
|
||||
})
|
||||
|
||||
function navigateTo(path: string) {
|
||||
router.push(path)
|
||||
@@ -168,126 +208,114 @@ function navigateTo(path: string) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicPage title="数据看板" description="核心业务数据一目了然">
|
||||
<BasicPage title="数据看板" description="核心业务数据一览">
|
||||
<div v-if="isLoading" class="flex items-center justify-center py-20">
|
||||
<UiSpinner class="w-8 h-8" />
|
||||
</div>
|
||||
|
||||
<div v-else class="grid gap-6">
|
||||
<!-- 模块1: 资金概览 -->
|
||||
<section class="space-y-3">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2">
|
||||
<Icon icon="lucide:wallet" class="size-4" />
|
||||
资金概览
|
||||
</h2>
|
||||
<div class="grid gap-3 grid-cols-1 sm:grid-cols-3">
|
||||
<UiCard v-for="item in fundMetrics" :key="item.label" class="hover:shadow-sm transition-shadow">
|
||||
<UiCardContent class="p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<!-- 第一层:核心 KPI 横幅 -->
|
||||
<section>
|
||||
<div class="grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<UiCard v-for="item in kpiItems" :key="item.label" class="hover:shadow-sm transition-shadow">
|
||||
<UiCardContent class="p-5">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div class="p-2 rounded-lg" :class="[item.bgColor]">
|
||||
<Icon :icon="item.icon" class="size-4" :class="item.color" />
|
||||
</div>
|
||||
<UiBadge
|
||||
:variant="item.growth.up ? 'default' : 'destructive'"
|
||||
class="text-xs font-mono"
|
||||
>
|
||||
{{ item.growth.text }}
|
||||
</UiBadge>
|
||||
</div>
|
||||
<div class="mt-3 space-y-1">
|
||||
<p class="text-xs text-muted-foreground">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<p class="text-lg sm:text-xl font-bold font-mono truncate" :class="item.color">
|
||||
{{ formatCurrency(item.value) }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-xs text-muted-foreground mb-1">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<p class="text-xl font-bold font-mono truncate" :class="item.color">
|
||||
{{ formatCurrency(item.value) }}
|
||||
</p>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 模块2: 资金流动 -->
|
||||
<section class="space-y-3">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2">
|
||||
<Icon icon="lucide:git-compare" class="size-4" />
|
||||
资金流动
|
||||
</h2>
|
||||
<div class="grid gap-3 grid-cols-1 sm:grid-cols-3">
|
||||
<UiCard v-for="item in flowMetrics" :key="item.label" class="hover:shadow-sm transition-shadow">
|
||||
<UiCardContent class="p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="p-2 rounded-lg" :class="[item.bgColor]">
|
||||
<Icon :icon="item.icon" class="size-4" :class="item.color" />
|
||||
</div>
|
||||
<span class="text-xs font-medium text-green-600">{{ item.trend }}</span>
|
||||
</div>
|
||||
<div class="mt-3 space-y-1">
|
||||
<p class="text-xs text-muted-foreground">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<p class="text-lg sm:text-xl font-bold font-mono truncate" :class="item.color">
|
||||
{{ formatCurrency(item.value) }}
|
||||
</p>
|
||||
</div>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 模块3+4: 图表区域 -->
|
||||
<div class="grid gap-6 lg:grid-cols-2">
|
||||
<!-- 资金趋势 -->
|
||||
<section class="space-y-3">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2">
|
||||
<!-- 第二层:资金趋势 + 资产状态 -->
|
||||
<div class="grid gap-6 lg:grid-cols-5">
|
||||
<!-- 资金趋势图 -->
|
||||
<section class="lg:col-span-3">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2 mb-3">
|
||||
<Icon icon="lucide:trending-up" class="size-4" />
|
||||
资金趋势
|
||||
资金流动趋势(近6月)
|
||||
</h2>
|
||||
<UiCard>
|
||||
<UiCardContent class="p-4">
|
||||
<VChart :option="trendChartOption" autoresize style="height: 240px" />
|
||||
<VChart :option="trendChartOption" autoresize style="height: 280px" />
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
</section>
|
||||
|
||||
<!-- 资金分布 -->
|
||||
<section class="space-y-3">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2">
|
||||
<Icon icon="lucide:pie-chart" class="size-4" />
|
||||
资金分布
|
||||
<!-- 资产状态面板 -->
|
||||
<section class="lg:col-span-2">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2 mb-3">
|
||||
<Icon icon="lucide:wallet" class="size-4" />
|
||||
资产状态
|
||||
</h2>
|
||||
<UiCard>
|
||||
<UiCardContent class="p-4">
|
||||
<VChart :option="distributionOption" autoresize style="height: 240px" />
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
<div class="grid gap-3">
|
||||
<UiCard v-for="item in assetMetrics" :key="item.label" class="hover:shadow-sm transition-shadow">
|
||||
<UiCardContent class="p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<Icon :icon="item.icon" class="size-4 text-muted-foreground" />
|
||||
<span class="text-sm text-muted-foreground">{{ item.label }}</span>
|
||||
</div>
|
||||
<span class="text-lg font-bold font-mono" :class="item.color">
|
||||
{{ formatCurrency(item.value) }}
|
||||
</span>
|
||||
</div>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- 模块5: 运营指标 + 快捷入口 -->
|
||||
<!-- 第三层:运营快报 + 快捷入口 -->
|
||||
<div class="grid gap-6 lg:grid-cols-5">
|
||||
<!-- 运营指标 -->
|
||||
<section class="space-y-3 lg:col-span-2">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2">
|
||||
<!-- 运营快报 -->
|
||||
<section class="lg:col-span-2">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2 mb-3">
|
||||
<Icon icon="lucide:activity" class="size-4" />
|
||||
运营指标
|
||||
运营快报
|
||||
</h2>
|
||||
<div class="grid gap-3 grid-cols-2">
|
||||
<UiCard v-for="item in operationMetrics" :key="item.label" class="hover:shadow-sm transition-shadow">
|
||||
<UiCard
|
||||
v-for="item in operationMetrics"
|
||||
:key="item.label"
|
||||
class="hover:shadow-sm transition-shadow"
|
||||
:class="{ 'cursor-pointer': item.label === '待审批' }"
|
||||
@click="item.label === '待审批' && navigateTo('/monisuo/orders')"
|
||||
>
|
||||
<UiCardContent class="p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="min-w-0">
|
||||
<p class="text-xs text-muted-foreground truncate">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<p class="text-lg sm:text-xl font-bold mt-1 truncate">
|
||||
{{ item.value }}
|
||||
</p>
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<div class="p-2 rounded-lg" :class="[item.bgColor]">
|
||||
<Icon :icon="item.icon" class="size-4" :class="item.color" />
|
||||
</div>
|
||||
<Icon :icon="item.icon" class="size-6 text-muted-foreground/30 shrink-0" />
|
||||
</div>
|
||||
<p class="text-xs text-muted-foreground text-center mb-1">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<p class="text-xl font-bold text-center">
|
||||
{{ item.value }}
|
||||
</p>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 快捷入口 -->
|
||||
<section class="space-y-3 lg:col-span-3">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2">
|
||||
<section class="lg:col-span-3">
|
||||
<h2 class="text-sm font-medium text-muted-foreground flex items-center gap-2 mb-3">
|
||||
<Icon icon="lucide:zap" class="size-4" />
|
||||
快捷入口
|
||||
</h2>
|
||||
|
||||
@@ -104,7 +104,7 @@ function copyToClipboard(text: string) {
|
||||
手续费
|
||||
</UiTableHead>
|
||||
<UiTableHead class="text-right">
|
||||
应付款
|
||||
到账金额
|
||||
</UiTableHead>
|
||||
<UiTableHead>审批人</UiTableHead>
|
||||
<UiTableHead class="hidden xl:table-cell">
|
||||
@@ -282,7 +282,7 @@ function copyToClipboard(text: string) {
|
||||
<div class="text-muted-foreground">手续费(10%)</div>
|
||||
<div class="col-span-2 font-mono">-{{ formatAmount(currentOrder.fee || 0) }}</div>
|
||||
|
||||
<div class="text-muted-foreground">应付款</div>
|
||||
<div class="text-muted-foreground">到账金额</div>
|
||||
<div class="col-span-2 font-mono font-bold text-green-600">{{ formatAmount(currentOrder.receivableAmount || 0) }}</div>
|
||||
|
||||
<div class="text-muted-foreground">提现地址</div>
|
||||
@@ -294,13 +294,21 @@ function copyToClipboard(text: string) {
|
||||
<span v-else class="text-muted-foreground">-</span>
|
||||
</div>
|
||||
|
||||
<template v-if="currentOrder.network">
|
||||
<div class="text-muted-foreground">提现网络</div>
|
||||
<div class="col-span-2">{{ currentOrder.network }}</div>
|
||||
</template>
|
||||
|
||||
<div class="text-muted-foreground">发起时间</div>
|
||||
<div class="col-span-2">{{ currentOrder.createTime }}</div>
|
||||
|
||||
<div v-if="currentOrder.financeApproveTime" class="text-muted-foreground">到账时间</div>
|
||||
<div v-if="currentOrder.financeApproveTime" class="col-span-2">{{ currentOrder.financeApproveTime }}</div>
|
||||
|
||||
<div v-if="currentOrder.approveAdminName" class="text-muted-foreground">审批人</div>
|
||||
<div v-if="currentOrder.approveAdminName" class="col-span-2">
|
||||
{{ currentOrder.approveAdminName }}
|
||||
</div>
|
||||
|
||||
<div class="text-muted-foreground">创建时间</div>
|
||||
<div class="col-span-2">{{ currentOrder.createTime }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<UiDialogFooter>
|
||||
@@ -340,7 +348,7 @@ function copyToClipboard(text: string) {
|
||||
<div class="font-mono font-bold text-lg">{{ formatAmount(currentOrder.amount) }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-muted-foreground">应付款</div>
|
||||
<div class="text-muted-foreground">到账金额</div>
|
||||
<div class="font-mono text-green-600">{{ formatAmount(currentOrder.receivableAmount || 0) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -133,7 +133,7 @@ function formatAmount(amount: number): string {
|
||||
function getStatusVariant(order: OrderFund): 'default' | 'secondary' | 'destructive' | 'outline' {
|
||||
const { type, status } = order
|
||||
// 充值状态: 1=待付款, 2=待确认, 3=已完成, 4=已驳回, 5=已取消
|
||||
// 提现状态: 1=待审批, 2=已完成, 3=已驳回, 4=已取消
|
||||
// 提现状态: 1=待审批, 2=已出款, 3=已驳回, 4=已取消
|
||||
if (type === 1) {
|
||||
// 充值
|
||||
if (status === 1) return 'secondary' // 待付款
|
||||
@@ -168,7 +168,7 @@ function getStatusText(order: OrderFund): string {
|
||||
// 提现状态
|
||||
switch (status) {
|
||||
case 1: return '待审批'
|
||||
case 2: return '已完成'
|
||||
case 2: return '已出款'
|
||||
case 3: return '已驳回'
|
||||
case 4: return '已取消'
|
||||
default: return '未知'
|
||||
@@ -711,7 +711,7 @@ function copyToClipboard(text: string) {
|
||||
</template>
|
||||
<template v-if="currentOrder.type === 2 && currentOrder.receivableAmount">
|
||||
<div class="text-muted-foreground">
|
||||
应收款项
|
||||
到账金额
|
||||
</div>
|
||||
<div class="col-span-2 font-mono font-bold text-green-600">
|
||||
{{ currentOrder.receivableAmount }}
|
||||
@@ -740,6 +740,16 @@ function copyToClipboard(text: string) {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 提现网络 -->
|
||||
<template v-if="currentOrder.type === 2 && currentOrder.network">
|
||||
<div class="text-muted-foreground">
|
||||
提现网络
|
||||
</div>
|
||||
<div class="col-span-2">
|
||||
{{ currentOrder.network }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="text-muted-foreground">
|
||||
创建时间
|
||||
</div>
|
||||
|
||||
@@ -60,9 +60,10 @@ export interface OrderFund {
|
||||
amount: number
|
||||
fee?: number // 手续费
|
||||
receivableAmount?: number // 应收款项
|
||||
status: number // 充值: 1待付款 2待确认 3已完成 4已驳回 5已取消; 提现: 1待审批 2已完成 3已驳回 4已取消 5待财务审核
|
||||
status: number // 充值: 1待付款 2待确认 3已完成 4已驳回 5已取消; 提现: 1待审批 2已出款 3已驳回 4已取消 5待财务审核
|
||||
walletId?: number
|
||||
walletAddress?: string
|
||||
network?: string // 提现网络类型
|
||||
withdrawContact?: string
|
||||
payTime?: string
|
||||
confirmTime?: string
|
||||
@@ -88,12 +89,24 @@ export interface ColdWallet {
|
||||
}
|
||||
|
||||
export interface FinanceOverview {
|
||||
// 核心 KPI
|
||||
totalDeposit: number
|
||||
totalWithdraw: number
|
||||
totalActualPayout: number // 实际出款金额
|
||||
// 资金状态
|
||||
fundBalance: number
|
||||
totalFrozen: number // 冻结中金额
|
||||
tradeValue: number
|
||||
// 运营数据
|
||||
pendingCount: number
|
||||
userCount: number
|
||||
monthNewUsers: number // 本月新增用户
|
||||
todayActiveUsers: number // 今日活跃用户
|
||||
// 环比数据
|
||||
monthlyDeposit: number
|
||||
monthlyWithdraw: number
|
||||
lastMonthDeposit: number
|
||||
lastMonthWithdraw: number
|
||||
}
|
||||
|
||||
// Auth API
|
||||
|
||||
Reference in New Issue
Block a user