/** * 年度价值报告页面 * 量化系统为企业创造的价值:ROI + 规避损失 + 节约工时 + 月度时间轴 */ import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' import { TrendingUp, Save, History, Download, ShieldCheck, Clock, DollarSign, Sparkles, Users, FileText, Calculator, Award } from 'lucide-react' import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, Cell } from 'recharts' import api from '../../lib/api' import Card from '../../components/ui/Card' import Button from '../../components/ui/Button' function fmtMoney(n: number): string { if (n >= 10000) return `¥${(n / 10000).toFixed(1)}万` return `¥${n.toLocaleString('zh-CN')}` } /** * 年度价值报告页面 */ export default function AnnualValueReport() { const queryClient = useQueryClient() const currentYear = new Date().getFullYear() const [year, setYear] = useState(currentYear) const [showHistory, setShowHistory] = useState(false) const { data: report, isLoading } = useQuery({ queryKey: ['annual-value', year], queryFn: async () => { const res = await api.get(`/dashboard/annual-value?year=${year}`) as any return res.data }, }) const { data: history } = useQuery({ queryKey: ['annual-value-history'], queryFn: async () => { const res = await api.get('/dashboard/annual-value/history') as any return res.data }, enabled: showHistory, }) const saveMutation = useMutation({ mutationFn: async () => { const res = await api.post('/dashboard/annual-value/save', { year }) as any return res.data }, onSuccess: () => { toast.success('报告已保存') queryClient.invalidateQueries({ queryKey: ['annual-value-history'] }) }, onError: () => toast.error('保存失败'), }) if (isLoading) { return
加载中...
} if (!report) return null const metricCards = [ { label: '规避损失', value: fmtMoney(report.lossAvoided || 0), icon: ShieldCheck, color: 'text-safe', bg: 'bg-green-50' }, { label: '节约工时', value: `${report.timeSaved || 0}h`, icon: Clock, color: 'text-blue-600', bg: 'bg-blue-50' }, { label: '节约成本', value: fmtMoney(report.costSaved || 0), icon: DollarSign, color: 'text-primary', bg: 'bg-indigo-50' }, { label: '总价值', value: fmtMoney(report.totalValue || 0), icon: TrendingUp, color: 'text-amber-600', bg: 'bg-amber-50' }, ] const stats = [ { label: '处理风险', value: report.metrics?.risksResolved ?? 0, icon: ShieldCheck, color: 'text-danger' }, { label: 'AI 咨询', value: report.metrics?.aiQueries ?? 0, icon: Sparkles, color: 'text-primary' }, { label: '合同审查', value: report.metrics?.contractsReviewed ?? 0, icon: FileText, color: 'text-blue-600' }, { label: '签订合同', value: report.metrics?.contractsSigned ?? 0, icon: FileText, color: 'text-safe' }, { label: '算薪批次', value: report.metrics?.payrollProcessed ?? 0, icon: Calculator, color: 'text-amber-600' }, { label: '在管员工', value: report.metrics?.employeesManaged ?? 0, icon: Users, color: 'text-gray-700' }, { label: '解聘处理', value: report.metrics?.terminations ?? 0, icon: Users, color: 'text-orange-600' }, { label: '制度公示', value: report.metrics?.policiesPublished ?? 0, icon: FileText, color: 'text-purple-600' }, ] const timelineData = (report.timeline || []).map((t: any) => ({ name: `${t.month}月`, risks: t.value, event: t.event, })) return (
{/* 标题栏 */}

年度价值报告

{year} 年度 · 系统价值量化分析

{/* 年度总价值概览 */}
年度总价值
{fmtMoney(report.totalValue)}
规避损失
{fmtMoney(report.adjustedLossAvoided || 0)}

{report.summary}

{/* 4 核心指标 */}
{metricCards.map((m) => { const Icon = m.icon return (
{m.value}
{m.label}
) })}
{/* 历史报告 */} {showHistory && (

历史年度报告

{history && history.length > 0 ? (
{history.map((r: any) => (
{r.year} 年 总价值 {fmtMoney(r.totalValue)} {r.summary}
{new Date(r.createdAt).toLocaleDateString('zh-CN')}
))}
) : (
暂无历史报告
)}
)} {/* 月度风险趋势 */}

月度风险趋势

[`${v} 项`, '风险']} contentStyle={{ fontSize: 12, borderRadius: 6, border: '1px solid #e5e7eb' }} /> {timelineData.map((d: any, i: number) => ( 5 ? '#EF4444' : d.risks > 0 ? '#F59E0B' : '#16A34A'} /> ))}
{/* 8 项运营统计 */}

年度运营统计

{stats.map((s) => { const Icon = s.icon return (
{s.value}
{s.label}
) })}
{/* 员工规避损失明细 */} {report.employeeDetails && report.employeeDetails.length > 0 && (

员工规避损失明细

{report.employeeDetails.map((emp: any, idx: number) => ( ))}
员工 部门 风险数 预估损失 规避方式 风险明细
{emp.name} {emp.department} {emp.riskCount} ¥{emp.adjustedLoss.toLocaleString()}
{emp.details.map((d: any, i: number) => (
{d.resolutionMethod}
))}
{emp.details.map((d: any, i: number) => (
{d.title} · {d.legalBasis} · ¥{d.estimatedLoss.toLocaleString()}
))}
合计 ¥{(report.adjustedLossAvoided || 0).toLocaleString()}
)} {/* 未解决风险列表 */} {report.pendingRiskDetails && report.pendingRiskDetails.length > 0 && (

待处理风险 ({report.pendingRiskDetails.length} 人)

{report.pendingRiskDetails.map((emp: any, idx: number) => ( ))}
员工 部门 风险数 潜在损失 风险明细
{emp.name} {emp.department} {emp.riskCount} ¥{emp.totalLoss.toLocaleString()}
{emp.details.map((d: any, i: number) => (
{d.title} · {d.legalBasis} · ¥{d.estimatedLoss.toLocaleString()}
))}
合计 ¥{report.pendingRiskDetails.reduce((s: number, e: any) => s + e.totalLoss, 0).toLocaleString()}
)} {/* 价值计算说明 */}

价值计算说明

规避损失:已解决风险的预估损失之和(系统已发现并解决,全部潜在损失即为规避价值,依据《劳动合同法》量化模型,单条上限按法定标准封顶)
节约工时:AI 咨询 × 0.5h + 合同审查 × 1h + 算薪批次 × 2h + 制度公示 × 1h
节约成本:节约工时 × 100 元/h(HR 平均时薪参考)
总价值:规避损失 + 节约成本
法定上限:双倍工资≤11个月(第82条)、经济补偿N≤12个月月薪≤社平3倍(第47条)、违法解除2N≤24个月(第87条)
) }