99 lines
3.4 KiB
TypeScript
99 lines
3.4 KiB
TypeScript
import React, { useState } from 'react';
|
|
import './FinalReport.css';
|
|
import MarkdownContent from './MarkdownContent';
|
|
|
|
const REPORT_FIELD_LABELS: Record<string, string> = {
|
|
core_strategy: '核心策略',
|
|
action_plan: '行动计划',
|
|
key_messages: '核心话术',
|
|
risk_warnings: '风险预警',
|
|
};
|
|
|
|
type Props = {
|
|
output?: any;
|
|
reportSchema?: Record<string, string>;
|
|
};
|
|
|
|
export default function FinalReport({ output, reportSchema }: Props): JSX.Element | null {
|
|
const [dimOpen, setDimOpen] = useState(false);
|
|
if (!output) return null;
|
|
|
|
const { report, dimensions, meta } = output;
|
|
const reportKeys = reportSchema && Object.keys(reportSchema).length > 0
|
|
? Object.keys(reportSchema)
|
|
: (report ? Object.keys(report) : []);
|
|
|
|
return (
|
|
<div className="final-report">
|
|
<div className="final-report-header">
|
|
<span className="final-report-icon">✦</span>
|
|
<span className="final-report-title">最终方案</span>
|
|
{meta && meta.total_rounds != null && (
|
|
<span className="final-report-meta">共 {meta.total_rounds} 轮分析</span>
|
|
)}
|
|
</div>
|
|
|
|
{report && reportKeys.length > 0 && (
|
|
<div className="final-report-sections">
|
|
{reportKeys.map(key => {
|
|
const content = report[key];
|
|
if (content == null) return null;
|
|
const label = (reportSchema && reportSchema[key])
|
|
? reportSchema[key]
|
|
: (REPORT_FIELD_LABELS[key] || key);
|
|
return (
|
|
<div key={key} className="final-report-section">
|
|
<div className="final-report-section-label">{label}</div>
|
|
<div className="final-report-section-content">
|
|
<MarkdownContent
|
|
content={typeof content === 'string' ? content : JSON.stringify(content, null, 2)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
|
|
{dimensions && Object.keys(dimensions).length > 0 && (
|
|
<>
|
|
<button
|
|
className="final-report-dimensions-toggle"
|
|
onClick={() => setDimOpen(o => !o)}
|
|
>
|
|
<span>维度详情</span>
|
|
<span className={`final-report-dimensions-chevron ${dimOpen ? 'open' : ''}`}>▾</span>
|
|
</button>
|
|
|
|
{dimOpen && (
|
|
<div className="final-report-dimensions-body">
|
|
{Object.entries(dimensions).map(([dim, dimData]: [string, any]) => (
|
|
<div key={dim} className="dim-detail">
|
|
<div className="dim-detail-label">
|
|
<span>{dim}</span>
|
|
{typeof dimData === 'object' && dimData?.label && (
|
|
<span className="dim-detail-sublabel">{dimData.label}</span>
|
|
)}
|
|
</div>
|
|
|
|
{typeof dimData === 'string' && (
|
|
<div className="dim-detail-analysis">
|
|
<MarkdownContent content={dimData} />
|
|
</div>
|
|
)}
|
|
|
|
{typeof dimData === 'object' && dimData?.latest_analysis && (
|
|
<div className="dim-detail-analysis">
|
|
<MarkdownContent content={dimData.latest_analysis} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|