diff --git a/frontend/src/app/(investor)/aars/page.tsx b/frontend/src/app/(investor)/aars/page.tsx index 05aec20..abe8d96 100644 --- a/frontend/src/app/(investor)/aars/page.tsx +++ b/frontend/src/app/(investor)/aars/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import {Sparkles } from "lucide-react"; import { listAARs, generateAAR } from "@/lib/api-v2"; import { PageContainer, Card} from "@/components/shared/PageContainer"; @@ -11,6 +12,7 @@ import { toast } from "sonner"; /** AAR 复盘记录项。 */ interface AARItem { + company_id?: string; trigger_event: string; gap_analysis?: string; lessons?: string[]; @@ -85,6 +87,7 @@ export default function AARsPage() {
{items.map((item, i) => ( +

{item.trigger_event}

{item.gap_analysis &&

{item.gap_analysis}

} {Array.isArray(item.lessons) && ( diff --git a/frontend/src/app/(investor)/agents/page.tsx b/frontend/src/app/(investor)/agents/page.tsx index 6564c84..238f695 100644 --- a/frontend/src/app/(investor)/agents/page.tsx +++ b/frontend/src/app/(investor)/agents/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { listAgentExecutions, reviewAgentExecution } from "@/lib/api-v2"; import { PageContainer, Badge} from "@/components/shared/PageContainer"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; @@ -11,6 +12,7 @@ import { toast } from "sonner"; /** Agent 执行记录项。 */ interface AgentExecution { id: string; + company_id?: string; agent_name: string; autonomy_level: string; output_summary: string; @@ -52,6 +54,7 @@ export default function AgentsPage() { + @@ -63,6 +66,7 @@ export default function AgentsPage() { {items.map((item, i) => ( + diff --git a/frontend/src/app/(investor)/agreements/page.tsx b/frontend/src/app/(investor)/agreements/page.tsx index 99a8f61..a9ad9e5 100644 --- a/frontend/src/app/(investor)/agreements/page.tsx +++ b/frontend/src/app/(investor)/agreements/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import {Plus } from "lucide-react"; import { listAgreements } from "@/lib/api-v2"; import { PageContainer, Badge, TableEmpty } from "@/components/shared/PageContainer"; @@ -10,6 +11,7 @@ import { EmptyState } from "@/components/shared/EmptyState"; /** 投资协议项。 */ interface Agreement { + company_id?: string; title: string; signed_at: string; status: string; @@ -46,6 +48,7 @@ export default function AgreementsPage() {
企业 Agent 自治级别 输出摘要
{item.agent_name} {item.autonomy_level} {item.output_summary}
+ @@ -54,10 +57,11 @@ export default function AgreementsPage() { {items.length === 0 ? ( - + ) : ( items.map((item, i) => ( +
企业 协议名称 签署日期 状态
{item.title} {item.signed_at} diff --git a/frontend/src/app/(investor)/alpha/page.tsx b/frontend/src/app/(investor)/alpha/page.tsx index a7a25bc..afdcc2d 100644 --- a/frontend/src/app/(investor)/alpha/page.tsx +++ b/frontend/src/app/(investor)/alpha/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import {Plus } from "lucide-react"; import { listInterventions } from "@/lib/api-v2"; import { PageContainer, Badge, Card } from "@/components/shared/PageContainer"; @@ -10,6 +11,7 @@ import { EmptyState } from "@/components/shared/EmptyState"; /** 干预记录项。 */ interface Intervention { + company_id?: string; intervention_type: string; title: string; executed_at: string; @@ -48,6 +50,7 @@ export default function AlphaPage() {
{item.intervention_type} +

{item.title}

{item.executed_at} diff --git a/frontend/src/app/(investor)/board/page.tsx b/frontend/src/app/(investor)/board/page.tsx index a6f0f93..ec629f7 100644 --- a/frontend/src/app/(investor)/board/page.tsx +++ b/frontend/src/app/(investor)/board/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { listBoardMeetings } from "@/lib/api-v2"; import { PageContainer, Badge} from "@/components/shared/PageContainer"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; @@ -9,6 +10,7 @@ import { EmptyState } from "@/components/shared/EmptyState"; /** 董事会会议项。 */ interface BoardMeeting { + company_id?: string; title: string; meeting_at: string; status: string; @@ -37,6 +39,7 @@ export default function BoardPage() { + @@ -46,6 +49,7 @@ export default function BoardPage() { {items.map((item, i) => ( +
企业 会议主题 会议时间 状态
{item.title} {item.meeting_at} diff --git a/frontend/src/app/(investor)/customer-success/page.tsx b/frontend/src/app/(investor)/customer-success/page.tsx index 15f763b..a4e617f 100644 --- a/frontend/src/app/(investor)/customer-success/page.tsx +++ b/frontend/src/app/(investor)/customer-success/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { apiFetch } from "@/lib/api"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; import { EmptyState } from "@/components/shared/EmptyState"; @@ -191,7 +192,7 @@ export default function CustomerSuccessPage() { {churnRisks.map((risk, i) => (
- {risk.company_name || risk.company_id || "企业"} + {risk.signals &&

{risk.signals}

}
{item.event_type} +

{item.title}

diff --git a/frontend/src/app/(investor)/exit-signals/page.tsx b/frontend/src/app/(investor)/exit-signals/page.tsx index 41f672a..ff5ab10 100644 --- a/frontend/src/app/(investor)/exit-signals/page.tsx +++ b/frontend/src/app/(investor)/exit-signals/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import {Sparkles } from "lucide-react"; import { listExitPredictions, predictExit } from "@/lib/api-v2"; import { PageContainer, Badge, Card } from "@/components/shared/PageContainer"; @@ -11,6 +12,7 @@ import { toast } from "sonner"; /** 退出预测项。 */ interface ExitPrediction { + company_id?: string; exit_path?: string; expected_return?: string; confidence?: number; @@ -80,6 +82,7 @@ export default function ExitSignalsPage() {
{item.exit_path && {item.exit_path}} + 期望收益:{item.expected_return ?? "-"}
{item.confidence != null && ( diff --git a/frontend/src/app/(investor)/nudges/page.tsx b/frontend/src/app/(investor)/nudges/page.tsx index 57724fa..7f70a7b 100644 --- a/frontend/src/app/(investor)/nudges/page.tsx +++ b/frontend/src/app/(investor)/nudges/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { apiFetch } from "@/lib/api"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; import { EmptyState } from "@/components/shared/EmptyState"; @@ -12,6 +13,7 @@ import { Lightbulb, Sparkles, Check, X, TrendingUp, BarChart3 } from "lucide-rea /** 助推记录项。 */ interface NudgeItem { id: string; + company_id?: string; nudge_type: string; message: string; accepted: boolean; @@ -117,7 +119,10 @@ export default function NudgesPage() {
-
{n.nudge_type}
+
+ {n.nudge_type} + +
{n.message}
diff --git a/frontend/src/app/(investor)/okrs/page.tsx b/frontend/src/app/(investor)/okrs/page.tsx index 0c6d144..e1f1f34 100644 --- a/frontend/src/app/(investor)/okrs/page.tsx +++ b/frontend/src/app/(investor)/okrs/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import {Plus } from "lucide-react"; import { listOKRs } from "@/lib/api-v2"; import { PageContainer, Badge, Card } from "@/components/shared/PageContainer"; @@ -17,6 +18,7 @@ interface KeyResult { /** OKR 项。 */ interface OKRItem { + company_id?: string; quarter: string; objective: string; alignment_score?: number; @@ -56,6 +58,7 @@ export default function OKRsPage() {
{item.quarter} +

{item.objective}

diff --git a/frontend/src/app/(investor)/peer-circles/page.tsx b/frontend/src/app/(investor)/peer-circles/page.tsx index a2bb97d..3ca17f3 100644 --- a/frontend/src/app/(investor)/peer-circles/page.tsx +++ b/frontend/src/app/(investor)/peer-circles/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { apiFetch } from "@/lib/api"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; import { EmptyState } from "@/components/shared/EmptyState"; @@ -12,6 +13,7 @@ import { Users, Sparkles, Circle } from "lucide-react"; /** Circle 项。 */ interface CircleItem { id: string; + company_id?: string; topic: string; status: string; description?: string; @@ -138,6 +140,7 @@ export default function PeerCirclesPage() {
+

{c.topic}

{preMortems.map((item, i) => ( +

{item.decision_context as string}

{Array.isArray(item.failure_paths) && (
@@ -136,6 +140,7 @@ export default function PreMortemsPage() { {redTeams.map((item, i) => (
+ {item.perspective as string}

{item.analysis as string}

diff --git a/frontend/src/app/(investor)/product-diagnostics/page.tsx b/frontend/src/app/(investor)/product-diagnostics/page.tsx index 87899a2..50e7641 100644 --- a/frontend/src/app/(investor)/product-diagnostics/page.tsx +++ b/frontend/src/app/(investor)/product-diagnostics/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { apiFetch } from "@/lib/api"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; import { EmptyState } from "@/components/shared/EmptyState"; @@ -24,6 +25,7 @@ interface DiagnosticResult { /** 历史诊断项。 */ interface DiagnosticHistory { id: string; + company_id?: string; product_name?: string; dimensions?: DiagnosticDimension[]; } @@ -159,7 +161,10 @@ export default function ProductDiagnosticsPage() {
{diagnostics.map((d) => (
-

{d.product_name || "未命名产品"}

+
+ +

{d.product_name || "未命名产品"}

+
{d.dimensions && Array.isArray(d.dimensions) && (
{d.dimensions.map((dim, i: number) => ( diff --git a/frontend/src/app/(investor)/reports/page.tsx b/frontend/src/app/(investor)/reports/page.tsx index 6599e6c..8817e4c 100644 --- a/frontend/src/app/(investor)/reports/page.tsx +++ b/frontend/src/app/(investor)/reports/page.tsx @@ -4,6 +4,7 @@ import { useState, useCallback } from "react"; import {Plus, Trash2, Send } from "lucide-react"; import { listReports, submitReport, deleteReport, STATUS_LABELS, STATUS_COLORS, type MonthlyReport } from "@/lib/reports"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; import { EmptyState } from "@/components/shared/EmptyState"; @@ -80,6 +81,7 @@ export default function ReportsPage() { + @@ -90,6 +92,7 @@ export default function ReportsPage() { {reports.map((report) => ( + diff --git a/frontend/src/app/(investor)/sentinels/page.tsx b/frontend/src/app/(investor)/sentinels/page.tsx index 6c8a618..dbd504c 100644 --- a/frontend/src/app/(investor)/sentinels/page.tsx +++ b/frontend/src/app/(investor)/sentinels/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { listDecisionSentinels } from "@/lib/api-v2"; import { PageContainer, Badge} from "@/components/shared/PageContainer"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; @@ -9,6 +10,7 @@ import { EmptyState } from "@/components/shared/EmptyState"; /** 决策前哨项。 */ interface DecisionSentinel { + company_id?: string; decision_type: string; title: string; status: string; @@ -39,6 +41,7 @@ export default function SentinelsPage() {
{item.decision_type} +

{item.title}

diff --git a/frontend/src/app/(investor)/synergies/page.tsx b/frontend/src/app/(investor)/synergies/page.tsx index f325f32..8a7ec75 100644 --- a/frontend/src/app/(investor)/synergies/page.tsx +++ b/frontend/src/app/(investor)/synergies/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { listSynergies, authorizeSynergy } from "@/lib/api-v2"; import { PageContainer, Badge } from "@/components/shared/PageContainer"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; @@ -11,6 +12,7 @@ import { toast } from "sonner"; /** 协同机会项。 */ interface Synergy { id: string; + company_id?: string; type: string; title: string; status: string; @@ -63,6 +65,7 @@ export default function SynergiesPage() {
{SYNERGY_TYPE_LABELS[item.type] ?? item.type} +

{item.title}

diff --git a/frontend/src/app/(investor)/talents/page.tsx b/frontend/src/app/(investor)/talents/page.tsx index ada6cb0..6441e05 100644 --- a/frontend/src/app/(investor)/talents/page.tsx +++ b/frontend/src/app/(investor)/talents/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { listTalents } from "@/lib/api-v2"; import { PageContainer, Badge } from "@/components/shared/PageContainer"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; @@ -9,6 +10,7 @@ import { EmptyState } from "@/components/shared/EmptyState"; /** 人才项。 */ interface Talent { + company_id?: string; name: string; current_role: string; performance_rating?: string; @@ -39,6 +41,7 @@ export default function TalentsPage() {
企业 期间 状态 内容摘要
{report.period_year}年{report.period_month}月
+ @@ -50,6 +53,7 @@ export default function TalentsPage() { {items.map((item, i) => ( + diff --git a/frontend/src/app/(investor)/tasks/page.tsx b/frontend/src/app/(investor)/tasks/page.tsx index 1a03b73..40d9239 100644 --- a/frontend/src/app/(investor)/tasks/page.tsx +++ b/frontend/src/app/(investor)/tasks/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import {Plus } from "lucide-react"; import { listTasks, updateTask } from "@/lib/api-v2"; import { PageContainer, Badge } from "@/components/shared/PageContainer"; @@ -12,6 +13,7 @@ import { toast } from "sonner"; /** 任务项。 */ interface TaskItem { id: string; + company_id?: string; title: string; status: string; priority: string; @@ -80,7 +82,10 @@ export default function TasksPage() { {items.filter((i) => i.status === col).map((item, i) => (
- {item.title} +
+ + {item.title} +
{item.priority} diff --git a/frontend/src/app/(investor)/weak-signals/page.tsx b/frontend/src/app/(investor)/weak-signals/page.tsx index ee81ea8..d8b030b 100644 --- a/frontend/src/app/(investor)/weak-signals/page.tsx +++ b/frontend/src/app/(investor)/weak-signals/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useScopeEffect } from "@/lib/company-scope"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; import { listWeakSignals } from "@/lib/api-v2"; import { PageContainer, Badge} from "@/components/shared/PageContainer"; import { LoadingSpinner } from "@/components/shared/LoadingSpinner"; @@ -9,6 +10,7 @@ import { EmptyState } from "@/components/shared/EmptyState"; /** 弱信号项。 */ interface WeakSignal { + company_id?: string; signal_type: string; content: string; confidence: number; @@ -45,6 +47,7 @@ export default function WeakSignalsPage() {
企业 姓名 当前职位 绩效
{item.name} {item.current_role} {item.performance_rating ?? "-"}
+ @@ -55,6 +58,7 @@ export default function WeakSignalsPage() { {items.map((item, i) => ( + diff --git a/frontend/src/components/customer/PlanCard.tsx b/frontend/src/components/customer/PlanCard.tsx index 8777282..e4cfda4 100644 --- a/frontend/src/components/customer/PlanCard.tsx +++ b/frontend/src/components/customer/PlanCard.tsx @@ -1,6 +1,7 @@ "use client"; import { Target, ArrowRight, DollarSign, Users, Trophy } from "lucide-react"; +import { CompanyNameTag } from "@/components/shared/CompanyNameTag"; /** 决策链节点。 */ interface DecisionChainNode { @@ -16,6 +17,7 @@ interface CompetitiveAnalysis { /** 客户获取方案。 */ interface CustomerPlanData { + company_id?: string; target_customer?: string; execution_status?: string; entry_angle?: string; @@ -40,6 +42,7 @@ export function PlanCard({ plan }: { plan: CustomerPlanData }) {
+

{plan.target_customer || "未指定目标客户"}

diff --git a/frontend/src/components/risk/RiskCard.tsx b/frontend/src/components/risk/RiskCard.tsx index 377cf9b..9bdc412 100644 --- a/frontend/src/components/risk/RiskCard.tsx +++ b/frontend/src/components/risk/RiskCard.tsx @@ -1,6 +1,6 @@ "use client"; -import { AlertTriangle, Trash2 } from "lucide-react"; +import { AlertTriangle, Trash2, Building2 } from "lucide-react"; import { RISK_STATUS_LABELS, RISK_STATUS_COLORS, @@ -9,6 +9,7 @@ import { RISK_TYPE_LABELS, type RiskEvent, } from "@/lib/risks"; +import { useCompanyName } from "@/lib/company-scope"; /** 风险卡片组件 — 从风险工作台抽取的独立组件。 */ @@ -22,6 +23,7 @@ interface RiskCardProps { * 风险事件卡片。 */ export function RiskCard({ risk, onStatusChange, onDelete }: RiskCardProps) { + const getCompanyName = useCompanyName(); return (
@@ -38,6 +40,9 @@ export function RiskCard({ risk, onStatusChange, onDelete }: RiskCardProps) {
+ + {RISK_TYPE_LABELS[risk.type] || risk.type} 严重度: {SEVERITY_LABELS[risk.severity] || risk.severity} diff --git a/frontend/src/components/shared/CompanyNameTag.tsx b/frontend/src/components/shared/CompanyNameTag.tsx new file mode 100644 index 0000000..9bcbf9b --- /dev/null +++ b/frontend/src/components/shared/CompanyNameTag.tsx @@ -0,0 +1,15 @@ +"use client"; + +import { Building2 } from "lucide-react"; +import { useCompanyName } from "@/lib/company-scope"; + +/** 企业名标签 — 在数据项旁显示所属企业名。 */ +export function CompanyNameTag({ companyId, className = "" }: { companyId?: string | null; className?: string }) { + const getCompanyName = useCompanyName(); + return ( + + + ); +} diff --git a/frontend/src/lib/company-scope.tsx b/frontend/src/lib/company-scope.tsx index 0b2fb11..d075add 100644 --- a/frontend/src/lib/company-scope.tsx +++ b/frontend/src/lib/company-scope.tsx @@ -107,3 +107,17 @@ export function useScopeEffect(callback: () => void, deps: unknown[] = []) { }, [companyId, ...deps]); } +/** + * 根据企业 ID 查找企业名称。 + * + * 在"全部企业"模式下,各页面数据项需要显示所属企业名, + * 此 hook 利用 Context 中已加载的企业列表进行映射。 + */ +export function useCompanyName(): (companyId: string | undefined | null) => string { + const { companies } = useCompanyScope(); + return (companyId: string | undefined | null) => { + if (!companyId) return "—"; + return companies.find((c) => c.id === companyId)?.name ?? companyId.slice(0, 8); + }; +} +
企业 类型 内容 置信度
{SIGNAL_TYPE_LABELS[item.signal_type] ?? item.signal_type}