feat: improve operations diagnostics and channel management

This commit is contained in:
hectorzhao
2026-08-09 14:27:19 +08:00
parent 44352aeb2f
commit 4724b9db6a
65 changed files with 1211 additions and 293 deletions
+14 -1
View File
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useState } from 'react';
import { Download, Search } from 'lucide-react';
import { adminApi, type AdminChannel, type DailyProfitReport, type EnterpriseApplication, type TenantOption } from '@/api/adminApi';
import { adminApi, type AdminChannel, type DailyProfitReport, type EnterpriseApplication, type ProfitReportSummary, type TenantOption } from '@/api/adminApi';
import { Breadcrumb, Button, DateRangeInput, Pagination, Select, Tag, type DateRangeValue } from '@/components/ui';
import { formatCents } from '@/utils/currency';
import { formatDateTime } from '@/utils/dateTime';
@@ -19,6 +19,7 @@ export function AdminProfitReportsPage() {
const [channelId, setChannelId] = useState('');
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const [summary, setSummary] = useState<ProfitReportSummary>(emptyProfitSummary);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [exporting, setExporting] = useState(false);
@@ -37,9 +38,11 @@ export function AdminProfitReportsPage() {
const response = await adminApi.listProfitReports({ dateFrom: dateRange.start, dateTo: dateRange.end, dimensionType, tenantId: tenantId || undefined, applicationId: applicationId || undefined, channelId: channelId || undefined, page, pageSize });
setRows(response.items);
setTotal(response.total);
setSummary(response.summary);
} catch (failure) {
setRows([]);
setTotal(0);
setSummary(emptyProfitSummary);
setError(failure instanceof Error ? failure.message : '利润报表加载失败');
} finally {
setLoading(false);
@@ -71,6 +74,14 @@ export function AdminProfitReportsPage() {
<Button icon={<Search size={16} />} onClick={() => void loadData()}></Button>
</div>
<div className="surface admin-report-summary">
<div className="admin-report-summary__heading"><strong></strong><span></span></div>
<div className="admin-report-summary__grid">{[
['提交合计', summary.submittedUnits.toLocaleString('zh-CN')], ['发送合计', summary.sentUnits.toLocaleString('zh-CN')], ['未知合计', summary.unknownUnits.toLocaleString('zh-CN')], ['成功合计', summary.successUnits.toLocaleString('zh-CN')], ['失败合计', summary.failedUnits.toLocaleString('zh-CN')],
['净消费合计', `¥${formatCents(summary.revenueCents)}`], ['返还合计', `¥${formatCents(summary.refundCents)}`], ['成本合计', `¥${formatCents(summary.costCents)}`], ['利润合计', `¥${formatCents(summary.profitCents)}`], ['综合利润率', `${(summary.profitRateBps / 100).toFixed(2)}%`],
].map(([label, value]) => <div key={label}><span>{label}</span><strong>{value}</strong></div>)}</div>
</div>
<div className="surface">
<div className="ui-table-wrap">
<table className="ui-table">
@@ -89,6 +100,8 @@ export function AdminProfitReportsPage() {
);
}
const emptyProfitSummary: ProfitReportSummary = { submittedUnits: 0, sentUnits: 0, unknownUnits: 0, successUnits: 0, failedUnits: 0, revenueCents: 0, refundCents: 0, costCents: 0, profitCents: 0, profitRateBps: 0 };
function defaultDateRange(): DateRangeValue {
const end = new Date();
end.setDate(end.getDate() - 1);