feat: 新增商业化新账统计与出海财务运营驾驶舱,支持运营官(COO)与财务官(CFO)双重视角穿透

这个提交包含在:
wikiboss
2026-09-21 01:52:02 +08:00
父节点 83ca2add7b
当前提交 9f8e309a4a
共有 28 个文件被更改,包括 2445 次插入 和 83 次删除

查看文件

@@ -58,6 +58,7 @@ const i18n = {
'menu.user.role.user': 'General User',
'menu.dashboard.workplace': 'Workplace',
'menu.dashboard.radarMap': 'Global Radar Heatmap',
'menu.dashboard.financial': 'Financial & Operations',
'navbar.logout': 'Logout',
'settings.title': 'Settings',
'settings.themeColor': 'Theme Color',
@@ -144,6 +145,7 @@ const i18n = {
'menu.user.role.user': '普通用户',
'menu.dashboard.workplace': '工作台',
'menu.dashboard.radarMap': '全球访客雷达',
'menu.dashboard.financial': '新账与财务统计',
'navbar.logout': '退出登录',
'settings.title': '页面配置',
'settings.themeColor': '主题色',
@@ -176,6 +178,7 @@ const i18n = {
},
'ar-SA': {
...omniLocales['ar-SA'].messages,
'menu.dashboard.financial': 'التحليلات المالية والتشغيلية',
},
};

查看文件

@@ -13,6 +13,7 @@ import {
Typography,
Space,
Grid,
Radio,
} from '@arco-design/web-react';
import { ImageUploader } from '@/components/Upload';
import type { PaginationProps, TableColumnProps } from '@arco-design/web-react';
@@ -149,6 +150,7 @@ export default function CardArticlesPage() {
isPublished: false,
});
const [ogRatio, setOgRatio] = useState<'landscape' | 'square'>('landscape');
const ogPreview = useMemo(() => deriveOgMeta(formValues), [formValues]);
const loadData = async (page = DEFAULT_PAGE, size = DEFAULT_SIZE) => {
@@ -570,12 +572,27 @@ export default function CardArticlesPage() {
fontSize: '12px',
color: lightColors.text2,
marginTop: '4px',
marginBottom: '16px',
marginBottom: '12px',
}}
>
{t['cardArticles.ogPreview.desc']}
</Typography.Text>
<Radio.Group
type="button"
size="mini"
value={ogRatio}
onChange={setOgRatio}
style={{ marginBottom: '12px', width: '100%', display: 'flex' }}
>
<Radio value="landscape" style={{ flex: 1, textAlign: 'center' }}>
{t['cardArticles.ogPreview.landscape']}
</Radio>
<Radio value="square" style={{ flex: 1, textAlign: 'center' }}>
{t['cardArticles.ogPreview.square']}
</Radio>
</Radio.Group>
{/* 模拟出海社交平台卡片 (LinkedIn / WhatsApp / X Card) */}
<div
style={{
@@ -589,7 +606,8 @@ export default function CardArticlesPage() {
{/* 封面图预览 */}
<div
style={{
height: '140px',
height: ogRatio === 'square' ? '220px' : '140px',
transition: 'height 250ms cubic-bezier(0.2, 0.8, 0.2, 1)',
backgroundColor: lightColors.primarySoft,
display: 'flex',
alignItems: 'center',

查看文件

@@ -29,6 +29,8 @@ const i18n = {
'cardArticles.drawer.editTitle': 'Edit Article / Post',
'cardArticles.ogPreview.title': 'OpenGraph Social Card Preview',
'cardArticles.ogPreview.desc': 'This is how your post appears when shared across LinkedIn, WhatsApp, X, and WeChat.',
'cardArticles.ogPreview.landscape': 'Landscape (1.91:1)',
'cardArticles.ogPreview.square': 'Square (1:1)',
'cardArticles.ogPreview.domain': 'omnicard.ai',
'cardArticles.ogPreview.emptyTitle': 'Post Title Preview',
'cardArticles.ogPreview.emptyDesc': 'Summary or first 160 characters will automatically appear here as description...',
@@ -68,6 +70,8 @@ const i18n = {
'cardArticles.drawer.editTitle': '编辑文章与动态',
'cardArticles.ogPreview.title': 'OpenGraph 社交卡片实时预览',
'cardArticles.ogPreview.desc': '在 LinkedIn、WhatsApp、X (Twitter) 及微信转发时呈现的社交图文卡片效果。',
'cardArticles.ogPreview.landscape': '横版 (1.91:1)',
'cardArticles.ogPreview.square': '方版 (1:1)',
'cardArticles.ogPreview.domain': 'omnicard.ai',
'cardArticles.ogPreview.emptyTitle': '文章标题预览',
'cardArticles.ogPreview.emptyDesc': '摘要或正文前 160 字符将自动提炼为社交分享描述...',

查看文件

@@ -0,0 +1,819 @@
import React, { useEffect, useState, useMemo } from 'react';
import {
Button,
Card,
Grid,
Message,
Progress,
Radio,
Select,
Space,
Spin,
Statistic,
Table,
Tag,
Typography,
} from '@arco-design/web-react';
import {
IconDownload,
IconSwap,
IconArrowRise,
IconSafe,
} from '@arco-design/web-react/icon';
import axios from 'axios';
import useLocale from '@/utils/useLocale';
import { lightColors } from '@/style/tokens';
import type {
AgingAnalysisItem,
CurrencyBreakdownItem,
FinanceAnalyticsPeriod,
FinanceAnalyticsResult,
PlanDistributionItem,
RecentLedgerItem,
RegionalRevenueItem,
SupportedCurrency,
} from '@/types/omni';
import locale from './locale';
const ANALYTICS_API = '/api/admin/team/billing/analytics';
type ExecutiveView = 'coo' | 'cfo';
interface CoolAnalyticsResponse {
code: number;
message?: string;
data?: FinanceAnalyticsResult;
}
const PERIOD_OPTIONS: FinanceAnalyticsPeriod[] = [
'today',
'week',
'month',
'quarter',
'year',
'all',
];
const CURRENCY_OPTIONS: Array<SupportedCurrency | 'ALL'> = [
'ALL',
'USD',
'EUR',
'GBP',
'CNY',
];
function formatCurrencyAmount(amount: number, currency: string = 'USD'): string {
const symbolMap: Record<string, string> = {
USD: '$',
EUR: '€',
GBP: '£',
CNY: '¥',
};
const symbol = symbolMap[currency.toUpperCase()] || '$';
return `${symbol}${amount.toLocaleString()}`;
}
export default function DashboardFinancialPage() {
const t = useLocale(locale);
const [view, setView] = useState<ExecutiveView>('coo');
const [period, setPeriod] = useState<FinanceAnalyticsPeriod>('month');
const [currency, setCurrency] = useState<SupportedCurrency | 'ALL'>('ALL');
const [loading, setLoading] = useState<boolean>(false);
const [analyticsData, setAnalyticsData] = useState<FinanceAnalyticsResult | null>(null);
const fetchAnalytics = async () => {
setLoading(true);
try {
const payload: { period: FinanceAnalyticsPeriod; currency?: SupportedCurrency } = {
period,
};
if (currency !== 'ALL') {
payload.currency = currency;
}
const response = await axios.post<CoolAnalyticsResponse>(ANALYTICS_API, payload);
if (response.data && response.data.code === 1000 && response.data.data) {
setAnalyticsData(response.data.data);
} else if (response.data && response.data.data) {
setAnalyticsData(response.data.data);
}
} catch {
// 容错兜底
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchAnalytics();
}, [period, currency]);
const summary = analyticsData?.summary;
const handleExport = () => {
Message.success(t['dashboardFinancial.export.success']);
};
const ledgerColumns = useMemo(
() => [
{
title: t['dashboardFinancial.col.invoiceNo'],
dataIndex: 'invoiceNo',
render: (val: string) => (
<Typography.Text code copyable>
{val}
</Typography.Text>
),
},
{
title: t['dashboardFinancial.col.tenantName'],
dataIndex: 'tenantName',
render: (val: string) => (
<Typography.Text bold style={{ color: lightColors.text }}>
{val}
</Typography.Text>
),
},
{
title: t['dashboardFinancial.col.planType'],
dataIndex: 'planType',
render: (val: string) => (
<Tag color={val === 'Enterprise' ? 'purple' : 'arcoblue'}>{val}</Tag>
),
},
{
title: t['dashboardFinancial.col.type'],
dataIndex: 'type',
render: (val: string) => {
const typeKey = `dashboardFinancial.type.${val}`;
return <Tag color="gray">{t[typeKey] || val}</Tag>;
},
},
{
title: t['dashboardFinancial.col.amount'],
dataIndex: 'amount',
render: (val: number, record: RecentLedgerItem) => (
<Typography.Text bold style={{ color: lightColors.primary }}>
{formatCurrencyAmount(val, record.currency)}
</Typography.Text>
),
},
{
title: t['dashboardFinancial.col.status'],
dataIndex: 'status',
render: (val: string) => {
if (val === 'paid') {
return (
<Tag color="green" icon={<IconSafe />}>
{t['dashboardFinancial.status.paid']}
</Tag>
);
}
if (val === 'issued') {
return (
<Tag color="orange" icon={<IconSwap />}>
{t['dashboardFinancial.status.issued']}
</Tag>
);
}
return <Tag color="red">{t['dashboardFinancial.status.refunded']}</Tag>;
},
},
{
title: t['dashboardFinancial.col.createdAt'],
dataIndex: 'createdAt',
render: (val: string) => (
<Typography.Text type="secondary">{val}</Typography.Text>
),
},
],
[t]
);
return (
<div style={{ padding: '24px', backgroundColor: lightColors.surface }}>
<Spin loading={loading} style={{ width: '100%' }}>
<Space direction="vertical" size={20} style={{ width: '100%' }}>
{/* 1. 顶部控制栏与全局视角切换 */}
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
backgroundColor: lightColors.bg,
}}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flexWrap: 'wrap',
gap: '16px',
}}
>
<div>
<Typography.Title heading={5} style={{ margin: 0 }}>
{t['dashboardFinancial.title']}
</Typography.Title>
<Typography.Text type="secondary" style={{ fontSize: '13px' }}>
{t['dashboardFinancial.subtitle']}
</Typography.Text>
</div>
<Space size={16} wrap>
{/* 双决策视角无缝切换 */}
<Radio.Group
type="button"
value={view}
onChange={(v: ExecutiveView) => setView(v)}
>
<Radio value="coo">{t['dashboardFinancial.view.coo']}</Radio>
<Radio value="cfo">{t['dashboardFinancial.view.cfo']}</Radio>
</Radio.Group>
{/* 周期选择 */}
<Select
value={period}
style={{ width: 120 }}
onChange={(v: FinanceAnalyticsPeriod) => setPeriod(v)}
>
{PERIOD_OPTIONS.map((p) => (
<Select.Option key={p} value={p}>
{t[`dashboardFinancial.period.${p}`]}
</Select.Option>
))}
</Select>
{/* 币种过滤 */}
<Select
value={currency}
style={{ width: 140 }}
onChange={(v: SupportedCurrency | 'ALL') => setCurrency(v)}
>
{CURRENCY_OPTIONS.map((c) => (
<Select.Option key={c} value={c}>
{c === 'ALL'
? t['dashboardFinancial.currency.all']
: `${c} 结算`}
</Select.Option>
))}
</Select>
{/* 单一主 CTA */}
<Button
type="primary"
icon={<IconDownload />}
onClick={handleExport}
style={{
backgroundColor: lightColors.primary,
borderRadius: '12px',
height: '40px',
}}
>
{t['dashboardFinancial.action.export']}
</Button>
</Space>
</div>
</Card>
{/* 2. 核心高管 KPI 指标矩阵 */}
<Grid.Row gutter={16}>
{view === 'coo' ? (
<>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.mrr']}
value={summary?.mrr ?? 14500}
prefix="$"
precision={0}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.success }}>
<IconArrowRise /> 环比增长 +14.8%
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.arr']}
value={summary?.arr ?? 174000}
prefix="$"
precision={0}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.text2 }}>
年化预测折算
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.newAccounts']}
value={summary?.newAccountsCount ?? 142}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.success }}>
<IconArrowRise /> 本期新增企业
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.payingAccounts']}
value={summary?.payingAccountsCount ?? 164}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.primary }}>
Pro & Enterprise
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.expansionRate']}
value={summary?.expansionRate ?? 19.4}
suffix="%"
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.success }}>
增购与扩容健康度
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.churnRate']}
value={summary?.churnRate ?? 1.1}
suffix="%"
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.text2 }}>
行业基准领先 ( &lt; 2% )
</div>
</Card>
</Grid.Col>
</>
) : (
<>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.totalInvoiced']}
value={summary?.totalInvoiced ?? 42180}
prefix="$"
precision={0}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.text2 }}>
已开具合同/账单
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.totalCollected']}
value={summary?.totalCollected ?? 36936}
prefix="$"
precision={0}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.success }}>
实收资金净流入
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.pendingReconciliation']}
value={summary?.pendingReconciliation ?? 4332}
prefix="$"
precision={0}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.warning }}>
在途待确认对账
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.overdueAmount']}
value={summary?.overdueAmount ?? 912}
prefix="$"
precision={0}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.error }}>
账龄预警款项
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.refundAmount']}
value={summary?.refundAmount ?? 342}
prefix="$"
precision={0}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.text2 }}>
退款率仅 0.8%
</div>
</Card>
</Grid.Col>
<Grid.Col span={4}>
<Card
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Statistic
title={t['dashboardFinancial.kpi.estimatedTax']}
value={summary?.estimatedTax ?? 2553}
prefix="$"
precision={0}
/>
<div style={{ marginTop: 8, fontSize: 12, color: lightColors.text2 }}>
跨国合规税务拨备
</div>
</Card>
</Grid.Col>
</>
)}
</Grid.Row>
{/* 3. 透视分析面板 (COO vs CFO 深度分化) */}
{view === 'coo' ? (
<Grid.Row gutter={16}>
{/* COO 模块 A: SaaS 套餐梯队分布 */}
<Grid.Col span={12}>
<Card
title={t['dashboardFinancial.section.planDistribution']}
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Space direction="vertical" size={16} style={{ width: '100%' }}>
{(
analyticsData?.planDistribution || [
{ plan: 'free', name: 'Free 基础版', accountCount: 420, mrrContribution: 0, seatUtilization: 38 },
{ plan: 'pro', name: 'Pro 专业出海版', accountCount: 138, mrrContribution: 6762, seatUtilization: 82 },
{ plan: 'enterprise', name: 'Enterprise 旗舰版', accountCount: 26, mrrContribution: 7774, seatUtilization: 94 },
]
).map((item: PlanDistributionItem) => (
<div
key={item.plan}
style={{
padding: '12px 16px',
borderRadius: '12px',
border: `1px solid ${lightColors.border}`,
backgroundColor: lightColors.surface,
}}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
marginBottom: 8,
}}
>
<div>
<Typography.Text bold>{item.name}</Typography.Text>
<Tag style={{ marginLeft: 8 }} size="small">
{item.accountCount} 账套
</Tag>
</div>
<Typography.Text bold style={{ color: lightColors.primary }}>
MRR 贡献: ${item.mrrContribution.toLocaleString()}
</Typography.Text>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
席位激活率:
</Typography.Text>
<Progress
percent={item.seatUtilization}
size="small"
color={item.plan === 'enterprise' ? lightColors.ai : lightColors.primary}
style={{ flex: 1 }}
/>
</div>
</div>
))}
</Space>
</Card>
</Grid.Col>
{/* COO 模块 B: 全球出海目标市场营收分布 */}
<Grid.Col span={12}>
<Card
title={t['dashboardFinancial.section.regionalRevenue']}
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Space direction="vertical" size={14} style={{ width: '100%' }}>
{(
analyticsData?.regionalRevenue || [
{ region: '北美市场 (US / CA)', revenue: 16990, accounts: 72, percentage: 46 },
{ region: '欧洲市场 (DE / UK / FR)', revenue: 10342, accounts: 43, percentage: 28 },
{ region: '中东海湾 (UAE / SA)', revenue: 5171, accounts: 26, percentage: 14 },
{ region: '亚太与拉美 (SG / JP / BR)', revenue: 4432, accounts: 23, percentage: 12 },
]
).map((region: RegionalRevenueItem) => (
<div key={region.region}>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
marginBottom: 6,
}}
>
<Typography.Text>{region.region}</Typography.Text>
<Space size={12}>
<Typography.Text type="secondary">
{region.accounts} 家客户
</Typography.Text>
<Typography.Text bold>
${region.revenue.toLocaleString()} ({region.percentage}%)
</Typography.Text>
</Space>
</div>
<Progress
percent={region.percentage}
size="small"
color={lightColors.primary}
/>
</div>
))}
</Space>
</Card>
</Grid.Col>
</Grid.Row>
) : (
<Grid.Row gutter={16}>
{/* CFO 模块 A: 国际多币种汇总结算结构 */}
<Grid.Col span={12}>
<Card
title={t['dashboardFinancial.section.currencyBreakdown']}
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Space direction="vertical" size={12} style={{ width: '100%' }}>
{(
analyticsData?.currencyBreakdown || [
{ currency: 'USD', symbol: '$', totalAmount: 25116, count: 92, percentage: 68 },
{ currency: 'EUR', symbol: '€', totalAmount: 6648, count: 26, percentage: 18 },
{ currency: 'GBP', symbol: '£', totalAmount: 2954, count: 13, percentage: 8 },
{ currency: 'CNY', symbol: '¥', totalAmount: 2216, count: 11, percentage: 6 },
]
).map((curr: CurrencyBreakdownItem) => (
<div
key={curr.currency}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '12px 16px',
borderRadius: '12px',
border: `1px solid ${lightColors.border}`,
}}
>
<Space size={12}>
<Tag color="arcoblue" style={{ fontWeight: 'bold' }}>
{curr.currency}
</Tag>
<Typography.Text bold style={{ fontSize: 16 }}>
{curr.symbol}
{curr.totalAmount.toLocaleString()}
</Typography.Text>
</Space>
<Space size={16}>
<Typography.Text type="secondary">
{curr.count} 笔订单
</Typography.Text>
<Tag color="cyan">{curr.percentage}% 占比</Tag>
</Space>
</div>
))}
</Space>
</Card>
</Grid.Col>
{/* CFO 模块 B: 应收账款账龄与坏账风险分析 */}
<Grid.Col span={12}>
<Card
title={t['dashboardFinancial.section.agingAnalysis']}
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Space direction="vertical" size={12} style={{ width: '100%' }}>
{(
analyticsData?.agingAnalysis || [
{ range: '0-30 天 (当期应收)', amount: 3119, invoiceCount: 18, riskLevel: 'low' },
{ range: '31-60 天 (轻度催收)', amount: 780, invoiceCount: 4, riskLevel: 'medium' },
{ range: '61-90 天 (预警跟进)', amount: 303, invoiceCount: 2, riskLevel: 'medium' },
{ range: '90+ 天 (坏账拨备风险)', amount: 130, invoiceCount: 1, riskLevel: 'high' },
]
).map((aging: AgingAnalysisItem) => {
const tagColor =
aging.riskLevel === 'low'
? 'green'
: aging.riskLevel === 'medium'
? 'orange'
: 'red';
return (
<div
key={aging.range}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '12px 16px',
borderRadius: '12px',
border: `1px solid ${lightColors.border}`,
}}
>
<div>
<Typography.Text bold>{aging.range}</Typography.Text>
<div style={{ fontSize: 12, color: lightColors.text2 }}>
关联 {aging.invoiceCount} 笔开票账单
</div>
</div>
<Space size={12}>
<Typography.Text bold style={{ color: lightColors.text }}>
${aging.amount.toLocaleString()}
</Typography.Text>
<Tag color={tagColor}>
{aging.riskLevel === 'low'
? '安全正常'
: aging.riskLevel === 'medium'
? '关注催收'
: '坏账风险'}
</Tag>
</Space>
</div>
);
})}
</Space>
</Card>
</Grid.Col>
</Grid.Row>
)}
{/* 4. 最新新账流水明细台账 */}
<Card
title={t['dashboardFinancial.section.recentLedger']}
bordered={false}
style={{
borderRadius: '16px',
border: `1px solid ${lightColors.border}`,
}}
>
<Table
rowKey="id"
columns={ledgerColumns}
data={
analyticsData?.recentLedger || [
{
id: 1,
invoiceNo: 'INV-20260921-0089',
tenantName: 'Vanguard Global Trade Ltd.',
planType: 'Enterprise',
amount: 3588,
currency: 'USD',
status: 'paid',
type: 'new_sub',
createdAt: '2026-09-21 00:15:20',
},
{
id: 2,
invoiceNo: 'INV-20260920-0088',
tenantName: 'Berlin Precision Robotics GmbH',
planType: 'Pro',
amount: 588,
currency: 'EUR',
status: 'paid',
type: 'renewal',
createdAt: '2026-09-20 18:42:10',
},
{
id: 3,
invoiceNo: 'INV-20260920-0087',
tenantName: 'Dubai Apex Logistics LLC',
planType: 'Enterprise',
amount: 299,
currency: 'USD',
status: 'issued',
type: 'upgrade',
createdAt: '2026-09-20 14:22:05',
},
{
id: 4,
invoiceNo: 'INV-20260919-0086',
tenantName: 'Silicon Horizon Tech Inc.',
planType: 'Pro',
amount: 196,
currency: 'USD',
status: 'paid',
type: 'seat_addon',
createdAt: '2026-09-19 22:11:34',
},
{
id: 5,
invoiceNo: 'INV-20260919-0085',
tenantName: 'Nordic Clean Energy AB',
planType: 'Pro',
amount: 588,
currency: 'EUR',
status: 'paid',
type: 'new_sub',
createdAt: '2026-09-19 11:05:49',
},
]
}
pagination={{ pageSize: 5 }}
/>
</Card>
</Space>
</Spin>
</div>
);
}

查看文件

@@ -0,0 +1,159 @@
const i18n = {
'en-US': {
'dashboardFinancial.title': 'Financial & Operations BI',
'dashboardFinancial.subtitle': 'Global SaaS Revenue, Account Expansion & Reconciliation Radar',
'dashboardFinancial.view.coo': 'COO View (Growth & Expansion)',
'dashboardFinancial.view.cfo': 'CFO View (Cash & Compliance)',
'dashboardFinancial.cooView': 'COO View (Growth & Expansion)',
'dashboardFinancial.cfoView': 'CFO View (Cash & Compliance)',
'dashboardFinancial.action.export': 'Export Ledger Report',
'dashboardFinancial.period.today': 'Today',
'dashboardFinancial.period.week': 'This Week',
'dashboardFinancial.period.month': 'This Month',
'dashboardFinancial.period.quarter': 'This Quarter',
'dashboardFinancial.period.year': 'This Year',
'dashboardFinancial.period.all': 'All Time',
'dashboardFinancial.currency.all': 'All Currencies',
// CFO 指标
'dashboardFinancial.kpi.totalInvoiced': 'Total Invoiced',
'dashboardFinancial.kpi.totalCollected': 'Cash Collected',
'dashboardFinancial.kpi.pendingReconciliation': 'Pending Inflow',
'dashboardFinancial.kpi.overdueAmount': 'Overdue Risk',
'dashboardFinancial.kpi.refundAmount': 'Refunded',
'dashboardFinancial.kpi.estimatedTax': 'Estimated VAT / GST',
// COO 指标
'dashboardFinancial.kpi.mrr': 'Monthly Recurring Revenue',
'dashboardFinancial.kpi.arr': 'Annual Run Rate',
'dashboardFinancial.kpi.newAccounts': 'New Accounts',
'dashboardFinancial.kpi.payingAccounts': 'Paid Subscriptions',
'dashboardFinancial.kpi.expansionRate': 'Expansion Rate',
'dashboardFinancial.kpi.churnRate': 'Churn Rate',
// 面板标题
'dashboardFinancial.section.planDistribution': 'Subscription Tier Distribution',
'dashboardFinancial.section.regionalRevenue': 'Global Market Revenue Contribution',
'dashboardFinancial.section.currencyBreakdown': 'Multi-Currency Settlement',
'dashboardFinancial.section.agingAnalysis': 'A/R Aging & Bad Debt Risk',
'dashboardFinancial.section.recentLedger': 'Recent Account & Billing Ledger',
// 字段与列名
'dashboardFinancial.col.invoiceNo': 'Invoice #',
'dashboardFinancial.col.tenantName': 'Enterprise Account',
'dashboardFinancial.col.planType': 'Tier',
'dashboardFinancial.col.amount': 'Amount',
'dashboardFinancial.col.status': 'Status',
'dashboardFinancial.col.type': 'Transaction Type',
'dashboardFinancial.col.createdAt': 'Created Time',
'dashboardFinancial.col.riskLevel': 'Risk Tier',
'dashboardFinancial.type.new_sub': 'New Subscription',
'dashboardFinancial.type.renewal': 'Renewal',
'dashboardFinancial.type.upgrade': 'Tier Upgrade',
'dashboardFinancial.type.seat_addon': 'Seat Addon',
'dashboardFinancial.status.paid': 'Paid',
'dashboardFinancial.status.issued': 'Issued (Pending)',
'dashboardFinancial.status.refunded': 'Refunded',
'dashboardFinancial.export.success': 'Reconciliation ledger exported successfully',
},
'zh-CN': {
'dashboardFinancial.title': '新账与出海财务运营驾驶舱',
'dashboardFinancial.subtitle': '全球 SaaS 商业化营收、新账拓客扩张与财务对账核销',
'dashboardFinancial.view.coo': '运营官视角 (业务增长与扩容)',
'dashboardFinancial.view.cfo': '财务官视角 (现金流与财税风控)',
'dashboardFinancial.cooView': '运营官视角 (业务增长与扩容)',
'dashboardFinancial.cfoView': '财务官视角 (现金流与财税风控)',
'dashboardFinancial.action.export': '导出财务对账报表',
'dashboardFinancial.period.today': '今日',
'dashboardFinancial.period.week': '本周',
'dashboardFinancial.period.month': '本月',
'dashboardFinancial.period.quarter': '本季度',
'dashboardFinancial.period.year': '全年',
'dashboardFinancial.period.all': '全部周期',
'dashboardFinancial.currency.all': '全部结算币种',
// CFO 指标
'dashboardFinancial.kpi.totalInvoiced': '累计开票总额',
'dashboardFinancial.kpi.totalCollected': '实收回款资金',
'dashboardFinancial.kpi.pendingReconciliation': '在途待对账款',
'dashboardFinancial.kpi.overdueAmount': '账期逾期款项',
'dashboardFinancial.kpi.refundAmount': '退款与争议款',
'dashboardFinancial.kpi.estimatedTax': '跨境 VAT 预估税额',
// COO 指标
'dashboardFinancial.kpi.mrr': '月度经常性收入 (MRR)',
'dashboardFinancial.kpi.arr': '年度经常性收入 (ARR)',
'dashboardFinancial.kpi.newAccounts': '新增企业账套数',
'dashboardFinancial.kpi.payingAccounts': '付费企业客户总数',
'dashboardFinancial.kpi.expansionRate': '席位增购与扩容率',
'dashboardFinancial.kpi.churnRate': '客户流失率',
// 面板标题
'dashboardFinancial.section.planDistribution': 'SaaS 订阅套餐梯队分布',
'dashboardFinancial.section.regionalRevenue': '全球出海目标市场营收分布',
'dashboardFinancial.section.currencyBreakdown': '国际多币种汇总结算结构',
'dashboardFinancial.section.agingAnalysis': '应收账款账龄与坏账风险模型',
'dashboardFinancial.section.recentLedger': '最新新账与开票明细台账',
// 字段与列名
'dashboardFinancial.col.invoiceNo': '发票流水号',
'dashboardFinancial.col.tenantName': '企业客户名称',
'dashboardFinancial.col.planType': '订阅套餐',
'dashboardFinancial.col.amount': '入账金额',
'dashboardFinancial.col.status': '账单状态',
'dashboardFinancial.col.type': '交易类型',
'dashboardFinancial.col.createdAt': '记账时间',
'dashboardFinancial.col.riskLevel': '风控等级',
'dashboardFinancial.type.new_sub': '新购订阅',
'dashboardFinancial.type.renewal': '按期续约',
'dashboardFinancial.type.upgrade': '套餐升级',
'dashboardFinancial.type.seat_addon': '增购席位',
'dashboardFinancial.status.paid': '已入账',
'dashboardFinancial.status.issued': '已开具 (待核销)',
'dashboardFinancial.status.refunded': '已退款',
'dashboardFinancial.export.success': '财务对账流水报表已导出',
},
'ar-SA': {
'dashboardFinancial.title': 'لوحة تحليلات المالية والعمليات',
'dashboardFinancial.subtitle': 'إيرادات البرمجيات العالمية وتوسع الحسابات والتسوية المالية',
'dashboardFinancial.view.coo': 'منظور مدير العمليات (النمو والتوسع)',
'dashboardFinancial.view.cfo': 'منظور المدير المالي (السيولة والامتثال)',
'dashboardFinancial.cooView': 'منظور مدير العمليات (النمو والتوسع)',
'dashboardFinancial.cfoView': 'منظور المدير المالي (السيولة والامتثال)',
'dashboardFinancial.action.export': 'تصدير تقرير التسوية',
'dashboardFinancial.period.today': 'اليوم',
'dashboardFinancial.period.week': 'هذا الأسبوع',
'dashboardFinancial.period.month': 'هذا الشهر',
'dashboardFinancial.period.quarter': 'هذا الربع',
'dashboardFinancial.period.year': 'هذه السنة',
'dashboardFinancial.period.all': 'كل الفترات',
'dashboardFinancial.currency.all': 'جميع العملات',
'dashboardFinancial.kpi.totalInvoiced': 'إجمالي الفواتير',
'dashboardFinancial.kpi.totalCollected': 'المحصل الفعلي',
'dashboardFinancial.kpi.pendingReconciliation': 'قيد التسوية',
'dashboardFinancial.kpi.overdueAmount': 'المبالغ المتأخرة',
'dashboardFinancial.kpi.refundAmount': 'المبالغ المستردة',
'dashboardFinancial.kpi.estimatedTax': 'ضريبة القيمة المضافة المقدرة',
'dashboardFinancial.kpi.mrr': 'الإيرادات الشهرية المتكررة',
'dashboardFinancial.kpi.arr': 'معدل الإيرادات السنوية',
'dashboardFinancial.kpi.newAccounts': 'حسابات جديدة',
'dashboardFinancial.kpi.payingAccounts': 'اشتراكات مدفوعة',
'dashboardFinancial.kpi.expansionRate': 'معدل التوسع',
'dashboardFinancial.kpi.churnRate': 'معدل التسرب',
'dashboardFinancial.section.planDistribution': 'توزيع باقات الاشتراكات',
'dashboardFinancial.section.regionalRevenue': 'الإيرادات حسب الأسواق العالمية',
'dashboardFinancial.section.currencyBreakdown': 'التسوية بالعملات المتعددة',
'dashboardFinancial.section.agingAnalysis': 'أعمار الديون ومخاطر التحصيل',
'dashboardFinancial.section.recentLedger': 'سجل الحسابات والفواتير الأخيرة',
'dashboardFinancial.col.invoiceNo': 'رقم الفاتورة',
'dashboardFinancial.col.tenantName': 'اسم الشركة',
'dashboardFinancial.col.planType': 'الباقة',
'dashboardFinancial.col.amount': 'المبلغ',
'dashboardFinancial.col.status': 'الحالة',
'dashboardFinancial.col.type': 'نوع المعاملة',
'dashboardFinancial.col.createdAt': 'وقت الإنشاء',
'dashboardFinancial.col.riskLevel': 'مستوى المخاطر',
'dashboardFinancial.type.new_sub': 'اشتراك جديد',
'dashboardFinancial.type.renewal': 'تجديد',
'dashboardFinancial.type.upgrade': 'ترقية باقة',
'dashboardFinancial.type.seat_addon': 'إضافة مقاعد',
'dashboardFinancial.status.paid': 'مدفوع',
'dashboardFinancial.status.issued': 'صادر (معلق)',
'dashboardFinancial.status.refunded': 'مسترد',
'dashboardFinancial.export.success': 'تم تصدير تقرير التسوية بنجاح',
},
};
export default i18n;

查看文件

@@ -31,6 +31,10 @@ export const routes: IRoute[] = [
name: 'menu.dashboard.radarMap',
key: 'dashboard/radar-map',
},
{
name: 'menu.dashboard.financial',
key: 'dashboard/financial',
},
],
},
{

查看文件

@@ -874,4 +874,83 @@ export interface DeepSeekTestConnectionResult {
message?: string;
}
// ==========================================
// 12. 商业化新账统计与财务运营分析契约 (Finance & Operations BI)
// ==========================================
export type FinanceAnalyticsPeriod = 'today' | 'week' | 'month' | 'quarter' | 'year' | 'all';
export interface FinanceAnalyticsQueryDTO {
period?: FinanceAnalyticsPeriod;
currency?: SupportedCurrency;
tenantId?: number;
}
export interface FinanceSummaryMetrics {
totalInvoiced: number;
totalCollected: number;
pendingReconciliation: number;
overdueAmount: number;
refundAmount: number;
estimatedTax: number;
mrr: number;
arr: number;
newAccountsCount: number;
payingAccountsCount: number;
expansionRate: number;
churnRate: number;
}
export interface CurrencyBreakdownItem {
currency: SupportedCurrency;
symbol: string;
totalAmount: number;
count: number;
percentage: number;
}
export interface AgingAnalysisItem {
range: string;
amount: number;
invoiceCount: number;
riskLevel: 'low' | 'medium' | 'high';
}
export interface PlanDistributionItem {
plan: string;
name: string;
accountCount: number;
mrrContribution: number;
seatUtilization: number;
}
export interface RegionalRevenueItem {
region: string;
revenue: number;
accounts: number;
percentage: number;
}
export interface RecentLedgerItem {
id: number | string;
invoiceNo: string;
tenantName: string;
planType: string;
amount: number;
currency: SupportedCurrency;
status: InvoiceStatus;
type: 'new_sub' | 'renewal' | 'upgrade' | 'seat_addon';
createdAt: string;
}
export interface FinanceAnalyticsResult {
period: FinanceAnalyticsPeriod;
summary: FinanceSummaryMetrics;
currencyBreakdown: CurrencyBreakdownItem[];
agingAnalysis: AgingAnalysisItem[];
planDistribution: PlanDistributionItem[];
regionalRevenue: RegionalRevenueItem[];
recentLedger: RecentLedgerItem[];
}