// ========================================
// Analysis Viewer Page
// ========================================
// View analysis sessions from /workflow:analyze-with-file command
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import {
FileSearch,
Search,
Calendar,
CheckCircle,
Clock,
ChevronRight,
Loader2,
AlertCircle,
X,
FileText,
Code,
MessageSquare,
} from 'lucide-react';
import { useWorkflowStore } from '@/stores/workflowStore';
import { Card } from '@/components/ui/Card';
import { Input } from '@/components/ui/Input';
import { Badge } from '@/components/ui/Badge';
import { Button } from '@/components/ui/Button';
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/Tabs';
import { fetchAnalysisSessions, fetchAnalysisDetail } from '@/lib/api';
import { MessageRenderer } from '@/components/shared/CliStreamMonitor/MessageRenderer';
import { JsonCardView } from '@/components/shared/JsonCardView';
import type { AnalysisSessionSummary } from '@/types/analysis';
// ========== Session Card Component ==========
interface SessionCardProps {
session: AnalysisSessionSummary;
onClick: () => void;
isSelected: boolean;
}
function SessionCard({ session, onClick, isSelected }: SessionCardProps) {
return (
{session.topic}
{session.id}
{session.status === 'completed' ? (
<>完成>
) : (
<>进行中>
)}
{session.createdAt}
);
}
// ========== Detail Panel Component ==========
interface DetailPanelProps {
sessionId: string;
projectPath: string;
onClose: () => void;
}
function DetailPanel({ sessionId, projectPath, onClose }: DetailPanelProps) {
const { data: detail, isLoading, error } = useQuery({
queryKey: ['analysis-detail', sessionId, projectPath],
queryFn: () => fetchAnalysisDetail(sessionId, projectPath),
});
if (isLoading) {
return (
);
}
if (error) {
return (
加载失败: {(error as Error).message}
);
}
if (!detail) return null;
// Build available tabs based on content
const tabs = [
{ id: 'discussion', label: '讨论记录', icon: MessageSquare, content: detail.discussion },
{ id: 'conclusions', label: '结论', icon: CheckCircle, content: detail.conclusions },
{ id: 'explorations', label: '代码探索', icon: Code, content: detail.explorations },
{ id: 'perspectives', label: '视角分析', icon: FileText, content: detail.perspectives },
].filter(tab => tab.content);
const defaultTab = tabs[0]?.id || 'discussion';
return (
{/* Header */}
{detail.topic}
{detail.status === 'completed' ? '完成' : '进行中'}
{detail.createdAt}
{/* Tabs Content */}
{tabs.length > 0 ? (
{tabs.map(tab => (
{tab.label}
))}
{/* Discussion Tab */}
{detail.discussion && (
)}
{/* Conclusions Tab */}
{detail.conclusions && (
)}
{/* Explorations Tab */}
{detail.explorations && (
)}
{/* Perspectives Tab */}
{detail.perspectives && (
)}
) : (
暂无分析内容
)}
);
}
// ========== Main Component ==========
export function AnalysisPage() {
const projectPath = useWorkflowStore((state) => state.projectPath);
const [searchQuery, setSearchQuery] = useState('');
const [selectedSession, setSelectedSession] = useState(null);
const { data: sessions = [], isLoading, error } = useQuery({
queryKey: ['analysis-sessions', projectPath],
queryFn: () => fetchAnalysisSessions(projectPath),
});
// Filter sessions by search query
const filteredSessions = sessions.filter((session) =>
session.topic.toLowerCase().includes(searchQuery.toLowerCase()) ||
session.id.toLowerCase().includes(searchQuery.toLowerCase())
);
return (
{/* Left Panel - List */}
{/* Header */}
Analysis Viewer
查看 /workflow:analyze-with-file 命令的分析结果
{/* Search */}
setSearchQuery(e.target.value)}
className="pl-9"
/>
{/* Content */}
{isLoading ? (
) : error ? (
加载失败: {(error as Error).message}
) : filteredSessions.length === 0 ? (
{searchQuery ? '没有匹配的分析会话' : '暂无分析会话'}
使用 /workflow:analyze-with-file 命令创建分析
) : (
{filteredSessions.map((session) => (
setSelectedSession(session.id)}
/>
))}
)}
{/* Right Panel - Detail */}
{selectedSession && (
setSelectedSession(null)}
/>
)}
);
}
export default AnalysisPage;