From 7ead7fc11c5b70b9f5ec85b2000dd2d50a801e5d Mon Sep 17 00:00:00 2001 From: Rogee Date: Fri, 16 Jan 2026 12:37:45 +0800 Subject: [PATCH] feat: add tenant finance report overview --- docs/superadmin_progress.md | 14 +- .../src/views/superadmin/Reports.vue | 40 ++- .../src/views/superadmin/TenantDetail.vue | 276 +++++++++++++++++- 3 files changed, 320 insertions(+), 10 deletions(-) diff --git a/docs/superadmin_progress.md b/docs/superadmin_progress.md index 86848ba..2417100 100644 --- a/docs/superadmin_progress.md +++ b/docs/superadmin_progress.md @@ -5,7 +5,7 @@ ## 1) 总体结论 - **已落地**:登录、租户/用户/订单/内容基础管理、内容审核(含批量)、平台概览(内容趋势/退款率/漏斗)、提现审核、钱包流水与异常排查、报表概览与导出、用户钱包/通知/优惠券/实名/充值记录、互动(收藏/点赞/关注)与内容消费明细视图、创作者申请/成员审核/邀请、优惠券创建/编辑/发放/冻结/发放记录/异常核查、资产治理(列表/用量/清理)、通知中心(列表/群发/模板)、审计日志与系统配置、评论治理。 -- **部分落地**:租户详情(缺财务/报表聚合)、内容治理(缺批量处置扩展)、创作者治理(缺提现审核联动与结算账户审批流)。 +- **部分落地**:内容治理(缺批量处置扩展)、创作者治理(缺提现审核联动与结算账户审批流)。 - **未落地**:暂无。 ## 2) 按页面完成度(对照 2.x) @@ -26,9 +26,9 @@ - 备注:成员加入审核/邀请由创作者页统一处理。 ### 2.4 租户详情 `/superadmin/tenants/:tenantID` -- 状态:**部分完成** -- 已有:租户信息、状态/续期、成员列表、内容与订单查询。 -- 缺口:租户级财务与报表聚合入口(成员审核/邀请由超管入口完成)。 +- 状态:**已完成** +- 已有:租户信息、状态/续期、成员列表、内容与订单查询、租户级财务/报表聚合入口。 +- 缺口:无显著功能缺口。 ### 2.5 用户管理 `/superadmin/users` - 状态:**已完成** @@ -92,6 +92,6 @@ ## 4) 建议的下一步(按优先级) -1. **租户详情聚合**:补齐租户财务与报表聚合入口。 -2. **订单运营补强**:问题订单标记、支付对账辅助能力。 -3. **内容批量处置扩展**:补齐内容/举报的批量下架、封禁与归档处理。 +1. **订单运营补强**:问题订单标记、支付对账辅助能力。 +2. **内容批量处置扩展**:补齐内容/举报的批量下架、封禁与归档处理。 +3. **创作者治理补强**:结算账户审批流、提现审核联动流程。 diff --git a/frontend/superadmin/src/views/superadmin/Reports.vue b/frontend/superadmin/src/views/superadmin/Reports.vue index 0988e83..551bca5 100644 --- a/frontend/superadmin/src/views/superadmin/Reports.vue +++ b/frontend/superadmin/src/views/superadmin/Reports.vue @@ -6,9 +6,10 @@ import { useLayout } from '@/layout/composables/layout'; import { ReportService } from '@/service/ReportService'; import { useToast } from 'primevue/usetoast'; import { computed, ref, watch } from 'vue'; -import { useRouter } from 'vue-router'; +import { useRoute, useRouter } from 'vue-router'; const toast = useToast(); +const route = useRoute(); const router = useRouter(); const { getPrimary, getSurface, isDarkTheme } = useLayout(); @@ -33,6 +34,24 @@ const interactionChartOptions = ref(null); const granularityOptions = [{ label: '按天', value: 'day' }]; +function getQueryValue(value) { + if (Array.isArray(value)) return value[0]; + return value ?? null; +} + +function parseNumber(value) { + const parsed = Number(value); + if (!Number.isFinite(parsed)) return null; + return parsed; +} + +function parseDate(value) { + if (!value) return null; + const date = new Date(value); + if (Number.isNaN(date.getTime())) return null; + return date; +} + function formatPercent(value) { const rate = Number(value); if (!Number.isFinite(rate)) return '-'; @@ -446,7 +465,24 @@ async function exportReport() { } } -loadOverview(); +watch( + () => route.query, + (query) => { + const tenantValue = parseNumber(getQueryValue(query?.tenant_id)); + tenantID.value = tenantValue || null; + + const startValue = getQueryValue(query?.start_at); + const endValue = getQueryValue(query?.end_at); + startAt.value = parseDate(startValue); + endAt.value = parseDate(endValue); + + const granularityValue = getQueryValue(query?.granularity); + if (granularityValue) granularity.value = String(granularityValue); + + loadOverview(); + }, + { immediate: true } +); watch([getPrimary, getSurface, isDarkTheme], () => { updateCharts(); diff --git a/frontend/superadmin/src/views/superadmin/TenantDetail.vue b/frontend/superadmin/src/views/superadmin/TenantDetail.vue index 82664ab..e7853fb 100644 --- a/frontend/superadmin/src/views/superadmin/TenantDetail.vue +++ b/frontend/superadmin/src/views/superadmin/TenantDetail.vue @@ -1,15 +1,19 @@