/** 多企业对比工作区 — 2-5 家企业并排对比,数据来自后端 API。 */ "use client"; import { GitCompareArrows } from "lucide-react"; import { CompareMode, type CompareColumn } from "@/components/workbench/CompareMode"; import { useState, useEffect, useMemo } from "react"; import { useCompanyScope } from "@/lib/company-scope"; import { listHealthScores, type HealthScore } from "@/lib/dashboard"; import { listRisks } from "@/lib/risks"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; import { EmptyState } from "@/components/shared/EmptyState"; /** 企业对比数据。 */ interface CompanyCompareData { healthScore: number; runway: number; highRisks: number; trend: string | null; aiCommercial: number | null; aiCost: number | null; } /** 多企业对比页面。 */ export default function ComparePage() { const { companies } = useCompanyScope(); const [selectedIds, setSelectedIds] = useState([]); const [scores, setScores] = useState([]); const [riskCounts, setRiskCounts] = useState>({}); const [isLoading, setIsLoading] = useState(false); // 默认选中前 3 家企业 const allCompanies = useMemo(() => companies, [companies]); const effectiveSelected = selectedIds.length > 0 ? selectedIds : allCompanies.slice(0, 3).map((c) => c.id); // 加载选中企业的健康度和风险数据 async function loadData(companyIds: string[]) { if (companyIds.length < 2) return; setIsLoading(true); try { // 并行加载健康度(全量)和各企业风险数 const [scoresResp, ...riskResps] = await Promise.all([ listHealthScores(), ...companyIds.map((id) => listRisks({ company_id: id, page_size: 1 }) ), ]); const allScores = (scoresResp.data as HealthScore[]) ?? []; setScores(allScores); const counts: Record = {}; riskResps.forEach((resp, i) => { const id = companyIds[i]; counts[id] = resp.data?.total ?? 0; }); setRiskCounts(counts); } catch { // ignore } finally { setIsLoading(false); } } // 当选中企业变化时加载数据 useEffect(() => { if (effectiveSelected.length >= 2) { loadData(effectiveSelected); } }, [effectiveSelected.join(",")]); // 构建对比列 const columns: CompareColumn[] = effectiveSelected.map((id) => { const company = allCompanies.find((c) => c.id === id); const score = scores.find((s) => s.company_id === id); const data: CompanyCompareData = { healthScore: score?.total_score ?? 0, runway: 0, highRisks: riskCounts[id] ?? 0, trend: score?.trend ?? null, aiCommercial: score?.ai_commercial_score ?? null, aiCost: score?.ai_cost_score ?? null, }; return { id, name: company?.name ?? id.slice(0, 8), healthScore: data.healthScore, runway: data.runway, highRisks: data.highRisks, content: (
{data.aiCommercial != null && (
AI 商业化 {data.aiCommercial.toFixed(1)}
)} {data.aiCost != null && (
AI 成本 {data.aiCost.toFixed(1)}
)} {data.trend && (
趋势 {data.trend === "up" ? "↑" : data.trend === "down" ? "↓" : "→"}
)}
), }; }); function toggleCompany(id: string) { setSelectedIds((prev) => { if (prev.includes(id)) { return prev.filter((n) => n !== id); } if (prev.length >= 5) return prev; return [...prev, id]; }); } return (

多企业对比

{/* 企业选择器 */}
选择企业(2-5 家): {allCompanies.map((c) => ( ))}
{/* 对比卡片 */} {isLoading ? ( ) : columns.length < 2 ? ( ) : ( )}
); }