import { Button, CapsuleTabs, DotLoading, ErrorBlock, Tag, Toast } from 'antd-mobile' import { useMemo, useState } from 'react' import { MiniTrendChart } from '../../../components/charts/MiniTrendChart' import { KpiCard } from '../../../components/kpi/KpiCard' import { formatMoney, formatNumber } from '../../../utils/format' import { useDashboardOverview } from '../api' import { buildDailyReportArchiveHtml } from '../archive' import type { DashboardOverview, RiskLevel, SnapshotSlot, TodaySnapshot } from '../types' const snapshotStatusMeta = { pending: { color: 'default', label: '待生成' }, success: { color: 'success', label: '已生成' }, failed: { color: 'danger', label: '失败' }, temporary: { color: 'warning', label: '临时' }, } as const const riskLevelMeta: Record = { red: { color: 'danger', label: '红色' }, yellow: { color: 'warning', label: '黄色' }, gray: { color: 'default', label: '灰色' }, } const snapshotSlotMeta: Record< SnapshotSlot, { title: string subtitle: string metricLabels: { primaryUsers: string primaryOrders: string amount: string paidAmount: string merchandise: string bonus: string } checklist: string[] } > = { '1015': { title: '上午抢购快报', subtitle: '用户集中抢购上一天用户寄卖的商品,重点看成交、付款和采购用户是否达标。', metricLabels: { primaryUsers: '抢购用户', primaryOrders: '抢购订单', amount: '抢购成交额', paidAmount: '已支付金额', merchandise: '成交商品', bonus: '相关奖金', }, checklist: ['抢购成交额是否低于昨日同节点', '采购用户是否异常回落', '付款金额与成交额是否明显偏离', '高货值寄卖商品是否完成消化'], }, '1455': { title: '下午寄卖/转卖快报', subtitle: '用户把上午抢到的商品继续寄卖或转卖,重点看新增寄售供给和奖金变化是否正常。', metricLabels: { primaryUsers: '寄卖用户', primaryOrders: '转卖订单', amount: '转卖成交额', paidAmount: '回款金额', merchandise: '新增寄售', bonus: '奖金变化', }, checklist: ['抢购商品是否按预期转入寄卖', '新增寄售商品是否满足下午供给', '个人奖金与推广奖金是否同步变化', '转卖回款是否出现异常延迟'], }, } function QueryState({ isLoading, isError, refetch, title, }: { isLoading: boolean isError: boolean refetch: () => void title: string }) { if (isLoading) { return (

正在加载{title}...

) } if (isError) { return (
) } return null } function OperationsHeader({ kicker, title, description, extra, }: { kicker: string title: string description: string extra?: string }) { return (

{kicker}

{title}

{description}

{extra && {extra}}
) } function SnapshotDetailCard({ snapshot }: { snapshot: TodaySnapshot }) { const status = snapshotStatusMeta[snapshot.status] const slotMeta = snapshotSlotMeta[snapshot.slot] return (

{snapshot.slot}

{slotMeta.title}

{status.label}

{slotMeta.subtitle}

{snapshot.message}

{snapshot.generatedAt &&

生成时间:{snapshot.generatedAt}

}
{slotMeta.metricLabels.primaryUsers} {formatNumber(snapshot.purchaseUsers)}人 {slotMeta.metricLabels.primaryOrders} {formatNumber(snapshot.orderCount)}单 {slotMeta.metricLabels.amount} {formatMoney(snapshot.dealAmount)} {slotMeta.metricLabels.paidAmount} {formatMoney(snapshot.paidAmount)} {slotMeta.metricLabels.merchandise} {formatNumber(snapshot.newMerchandiseCount)}件 {slotMeta.metricLabels.bonus} {formatMoney(Number(snapshot.selfBonusChange) + Number(snapshot.shareBonusChange))}
) } function buildDailyReports(data: DashboardOverview) { return data.trends .slice(-4) .reverse() .map((trend, index) => ({ ...trend, status: index === 0 ? '已生成' : '历史快照', bonusRate: Number(trend.amount) > 0 ? (Number(trend.bonus) / Number(trend.amount)) * 100 : 0, })) } export function DailyReportPage() { const { data, isLoading, isError, refetch } = useDashboardOverview() const [isArchiving, setIsArchiving] = useState(false) const state = void refetch()} title="经营日报" /> if (!data) return state const reports = buildDailyReports(data) const handleArchive = async () => { try { setIsArchiving(true) const html = buildDailyReportArchiveHtml(data) const blob = new Blob([html], { type: 'text/html;charset=utf-8' }) const url = URL.createObjectURL(blob) const link = document.createElement('a') link.href = url link.download = `dashboard-daily-report-${data.businessDate}.html` document.body.appendChild(link) link.click() link.remove() URL.revokeObjectURL(url) Toast.show({ icon: 'success', content: '归档 HTML 已生成' }) } catch { Toast.show({ icon: 'fail', content: '归档生成失败,请稍后重试' }) } finally { setIsArchiving(false) } } return (

Workday

上个工作日重点

已归档
{data.kpis.slice(0, 4).map((metric) => ( ))}

Trend

最近 7 天趋势

Archive

日报归档

{reports.map((report) => ( ))}
) } export function TodaySnapshotPage() { const { data, isLoading, isError, refetch } = useDashboardOverview() const state = void refetch()} title="今日快报" /> if (!data) return state return (

Timeline

节点快报

{data.snapshots.map((snapshot) => ( ))}

Checklist

节点检查项

{data.snapshots.flatMap((snapshot) => snapshotSlotMeta[snapshot.slot].checklist.map((item) => ( {snapshot.slot === '1015' ? '上午' : '下午'} {item} )), )}
) } export function RiskCenterPage() { const { data, isLoading, isError, refetch } = useDashboardOverview() const [activeLevel, setActiveLevel] = useState('all') const state = void refetch()} title="风险中心" /> const filteredRisks = useMemo(() => { if (!data) return [] if (activeLevel === 'all') return data.risks return data.risks.filter((risk) => risk.level === activeLevel) }, [activeLevel, data]) if (!data) return state const dangerousFunds = data.fundPool.filter((metric) => metric.status === 'warning' || metric.status === 'danger') return (
{(['red', 'yellow', 'gray'] as const).map((level) => { const meta = riskLevelMeta[level] const count = data.risks.filter((risk) => risk.level === level).length return ( ) })}
setActiveLevel(key as RiskLevel | 'all')}>
{filteredRisks.map((risk) => { const meta = riskLevelMeta[risk.level] return ( ) })}

Fund Watch

资金池关注项

{dangerousFunds.map((metric) => ( ))}
) } export function ProfilePage() { const { data, isLoading, isError, refetch } = useDashboardOverview() const state = void refetch()} title="我的" /> if (!data) return state return (

老板视角

可查看经营概览、今日快报、排行与风险预警。

Environment

数据环境

Mock
数据日期 {data.businessDate} 生成时间 {data.generatedAt} API 模式 {import.meta.env.VITE_MOCK_ENABLED === 'false' ? '真实接口' : 'Mock 演示'}

Permissions

权限模块

经营概览:可见 资金池摘要:可见 风险预警:可见 导出能力:待接入
) }