Files
deerflow-code/web-code/components/qa/components/ProgressSidebar.tsx
T
2026-05-27 19:43:15 +08:00

142 lines
5.4 KiB
TypeScript

import './ProgressSidebar.css';
type MemoryListProps = {
items?: any[];
emptyText: string;
};
type Props = {
phase?: string;
status?: string;
currentRound?: number;
divergeRounds?: number;
reportSchema?: Record<string, any>;
sharedMemory?: Record<string, any>;
finalReportPartial?: Record<string, string>;
currentFinalField?: string;
};
function MemoryList({ items, emptyText }: MemoryListProps): JSX.Element {
if (!items || items.length === 0) {
return <div className="empty-hint">{emptyText}</div>;
}
return (
<div className="memory-list">
{items.map((item, index) => (
<div key={`${index}-${String(item).slice(0, 20)}`} className="memory-item">{item}</div>
))}
</div>
);
}
export default function ProgressSidebar({
phase,
status,
currentRound,
divergeRounds,
reportSchema,
sharedMemory,
finalReportPartial,
currentFinalField,
}: Props): JSX.Element {
const fields = Object.keys(reportSchema || {});
const finalFilled = fields.filter(field => (finalReportPartial?.[field] || '').trim()).length;
const progressPercent = fields.length > 0 ? Math.round((finalFilled / fields.length) * 100) : 0;
const fieldMemoryEntries = Object.entries(sharedMemory?.field_memory || {});
const agentMemoryEntries = Object.entries(sharedMemory?.agent_memory || {});
const displayStatus = status || '等待中';
return (
<div className="progress-sidebar">
<div className="progress-card">
<div className="progress-title">方案进度</div>
<div className="progress-meta">
<span className={`progress-phase phase-${phase || 'starting'}`}>{phase || 'starting'}</span>
<span className="progress-status">{displayStatus}</span>
</div>
<div className="progress-line">
<div className="progress-line-fill" style={{ width: `${progressPercent}%` }} />
</div>
<div className="progress-text">第 {currentRound || 0} 轮 / 发散 {divergeRounds || 0} 轮</div>
<div className="progress-text">最终报告已生成字段 {finalFilled}/{fields.length || 0}</div>
{currentFinalField && <div className="field-current">当前字段:{currentFinalField}</div>}
</div>
<div className="progress-card">
<div className="progress-title">稳定判断</div>
<MemoryList items={sharedMemory?.stable_claims || []} emptyText="尚未形成稳定判断" />
</div>
<div className="progress-card">
<div className="progress-title">关键依据</div>
<MemoryList items={sharedMemory?.key_evidence || []} emptyText="尚未沉淀关键依据" />
</div>
<div className="progress-card">
<div className="progress-title">冲突与待核</div>
<MemoryList items={sharedMemory?.conflicts || []} emptyText="当前没有显式冲突" />
<div className="memory-subtitle">待核问题</div>
<MemoryList items={sharedMemory?.open_questions || []} emptyText="当前没有待核问题" />
</div>
<div className="progress-card">
<div className="progress-title">字段记忆</div>
{fieldMemoryEntries.length === 0 ? (
<div className="empty-hint">尚未形成字段记忆</div>
) : (
<div className="field-memory-list">
{fieldMemoryEntries.map(([field, item]: [string, any]) => (
<div key={field} className={`field-memory-card status-${item.status || 'partial'}`}>
<div className="field-memory-head">
<span className="field-memory-title">{item.title || field}</span>
<span className="field-memory-status">{item.status || 'partial'}</span>
</div>
{item.current_takeaways?.length > 0 && (
<>
<div className="memory-subtitle">当前判断</div>
<MemoryList items={item.current_takeaways} emptyText="" />
</>
)}
{item.missing_points?.length > 0 && (
<>
<div className="memory-subtitle">待补内容</div>
<MemoryList items={item.missing_points} emptyText="" />
</>
)}
</div>
))}
</div>
)}
</div>
<div className="progress-card">
<div className="progress-title">角色记忆</div>
{agentMemoryEntries.length === 0 ? (
<div className="empty-hint">尚未形成角色记忆</div>
) : (
<div className="agent-memory-list">
{agentMemoryEntries.map(([agentId, item]: [string, any]) => (
<div key={agentId} className="agent-memory-card">
<div className="agent-memory-name">{item.name || agentId}</div>
{item.latest_position && <div className="agent-memory-position">{item.latest_position}</div>}
{item.useful_findings?.length > 0 && (
<>
<div className="memory-subtitle">有效发现</div>
<MemoryList items={item.useful_findings} emptyText="" />
</>
)}
{item.open_issues?.length > 0 && (
<>
<div className="memory-subtitle">待继续澄清</div>
<MemoryList items={item.open_issues} emptyText="" />
</>
)}
</div>
))}
</div>
)}
</div>
</div>
);
}