AIA V2.0 Major Updates: - Add StreamingService with OpenAI Compatible format (backend/common/streaming) - Upgrade Chat component V2 with Ant Design X deep integration - Implement 12 intelligent agents (5 phases: topic/design/review/data/writing) - Create AgentHub with 100% prototype V11 restoration - Create ChatWorkspace with fullscreen immersive experience - Add ThinkingBlock for deep thinking display - Add useAIStream Hook for stream handling - Add ConversationList for conversation management Backend (~1300 lines): - common/streaming: OpenAI adapter and streaming service - modules/aia: 12 agents config, conversation service, attachment service - Unified API routes to /api/v1 (RVW, PKB, AIA modules) - Update authentication and permission helpers Frontend (~3500 lines): - modules/aia: AgentHub + ChatWorkspace + AgentCard components - shared/Chat: AIStreamChat, ThinkingBlock, useAIStream, useConversations - Update all modules API endpoints to v1 - Modern design with theme colors (blue/yellow/teal/purple) Documentation (~2500 lines): - AIA module status and development guide - Universal capabilities catalog (11 services) - Quick reference card - System overview updates - All module documentation synchronization Other Updates: - DC Tool C: Python operations and frontend components - IIT Manager: session memory and wechat service - PKB/RVW/ASL: API route updates - Docker configs and deployment scripts - Database migrations and scripts - Test files and documentation Tested: AIA streaming verified, authentication working, core features functional Status: AIA V2.0 completed (85%), all changes synchronized
120 lines
4.2 KiB
TypeScript
120 lines
4.2 KiB
TypeScript
/**
|
|
* 报告详情页组件
|
|
*/
|
|
import { useState } from 'react';
|
|
import { ArrowLeft, FileCheck, Tag } from 'lucide-react';
|
|
import type { ReviewReport } from '../types';
|
|
import EditorialReport from './EditorialReport';
|
|
import MethodologyReport from './MethodologyReport';
|
|
|
|
interface ReportDetailProps {
|
|
report: ReviewReport;
|
|
onBack: () => void;
|
|
}
|
|
|
|
export default function ReportDetail({ report, onBack }: ReportDetailProps) {
|
|
const [activeTab, setActiveTab] = useState<'editorial' | 'methodology'>('editorial');
|
|
|
|
const hasEditorial = !!report.editorialReview;
|
|
const hasMethodology = !!report.methodologyReview;
|
|
|
|
// 如果只有方法学,默认显示方法学
|
|
const effectiveTab = activeTab === 'editorial' && !hasEditorial && hasMethodology ? 'methodology' : activeTab;
|
|
|
|
return (
|
|
<div className="flex-1 flex flex-col h-full bg-slate-50 relative fade-in">
|
|
{/* 顶部导航栏 */}
|
|
<header className="h-16 bg-white border-b border-gray-200 px-6 flex items-center justify-between sticky top-0 z-20 shadow-sm">
|
|
<div className="flex items-center gap-4">
|
|
<button
|
|
onClick={onBack}
|
|
className="flex items-center gap-2 text-slate-500 hover:text-slate-800 transition-colors px-2 py-1 rounded hover:bg-slate-100"
|
|
>
|
|
<ArrowLeft className="w-5 h-5" />
|
|
<span className="text-sm font-medium">返回列表</span>
|
|
</button>
|
|
<div className="h-6 w-px bg-slate-200" />
|
|
<div>
|
|
<h1 className="text-base font-bold text-slate-800 flex items-center gap-2">
|
|
{report.fileName}
|
|
{report.overallScore && (
|
|
<span className={`tag ${
|
|
report.overallScore >= 80 ? 'tag-green' :
|
|
report.overallScore >= 60 ? 'tag-amber' : 'tag-red'
|
|
}`}>
|
|
{report.overallScore}分
|
|
</span>
|
|
)}
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<button className="px-3 py-1.5 bg-indigo-600 text-white rounded text-sm font-medium hover:bg-indigo-700 transition shadow-sm flex items-center gap-2">
|
|
<FileCheck className="w-4 h-4" />
|
|
导出报告
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
{/* 内容区域 */}
|
|
<div className="flex-1 overflow-auto p-8 max-w-5xl mx-auto w-full">
|
|
{/* Tab切换 */}
|
|
{(hasEditorial || hasMethodology) && (
|
|
<div className="flex gap-1 bg-slate-200/50 p-1 rounded-lg mb-8 w-fit mx-auto">
|
|
{hasEditorial && (
|
|
<button
|
|
onClick={() => setActiveTab('editorial')}
|
|
className={`px-6 py-2 rounded-md text-sm transition-all ${
|
|
effectiveTab === 'editorial'
|
|
? 'font-bold bg-white text-indigo-600 shadow-sm'
|
|
: 'font-medium text-slate-500 hover:text-slate-700'
|
|
}`}
|
|
>
|
|
稿约规范性 ({report.editorialReview?.overall_score}分)
|
|
</button>
|
|
)}
|
|
{hasMethodology && (
|
|
<button
|
|
onClick={() => setActiveTab('methodology')}
|
|
className={`px-6 py-2 rounded-md text-sm transition-all ${
|
|
effectiveTab === 'methodology'
|
|
? 'font-bold bg-white text-indigo-600 shadow-sm'
|
|
: 'font-medium text-slate-500 hover:text-slate-700'
|
|
}`}
|
|
>
|
|
方法学评估 ({report.methodologyReview?.overall_score}分)
|
|
</button>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{/* 报告内容 */}
|
|
{effectiveTab === 'editorial' && report.editorialReview && (
|
|
<EditorialReport data={report.editorialReview} />
|
|
)}
|
|
{effectiveTab === 'methodology' && report.methodologyReview && (
|
|
<MethodologyReport data={report.methodologyReview} />
|
|
)}
|
|
|
|
{/* 无数据状态 */}
|
|
{!hasEditorial && !hasMethodology && (
|
|
<div className="text-center py-12 text-slate-500">
|
|
<Tag className="w-12 h-12 mx-auto mb-4 text-slate-300" />
|
|
<p>暂无评估报告</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|