feat(aia): Complete AIA V2.0 with universal streaming capabilities
Major Updates: - Add StreamingService with OpenAI Compatible format (backend/common/streaming) - Upgrade Chat component V2 with Ant Design X integration - Implement AIA module with 12 intelligent agents - Create AgentHub with 100% prototype V11 restoration - Create ChatWorkspace with streaming response support - Add ThinkingBlock for deep thinking display - Add useAIStream Hook for OpenAI Compatible stream handling Backend Common Capabilities (~400 lines): - OpenAIStreamAdapter: SSE adapter with OpenAI format - StreamingService: unified streaming service - Support content and reasoning_content dual streams - Deep thinking tag processing (<think>...</think>) Frontend Common Capabilities (~2000 lines): - AIStreamChat: modern streaming chat component - ThinkingBlock: collapsible deep thinking display - ConversationList: conversation management with grouping - useAIStream: OpenAI Compatible stream handler Hook - useConversations: conversation state management Hook - Modern design styles (Ultramodern theme) AIA Module Frontend (~1500 lines): - AgentHub: 12 agent cards with timeline design - ChatWorkspace: fullscreen immersive chat interface - AgentCard: theme-colored cards (blue/yellow/teal/purple) - 5 phases, 12 agents configuration - Responsive layout (desktop + mobile) AIA Module Backend (~900 lines): - agentService: 12 agents config with system prompts - conversationService: refactored with StreamingService - attachmentService: file upload skeleton (30k token limit) - 12 API endpoints with authentication - Full CRUD for conversations and messages Documentation: - AIA module status and development guide - Universal capabilities catalog (11 services) - Quick reference card for developers - System overview updates Testing: - Stream response verified (HTTP 200) - Authentication working correctly - Auto conversation creation working - Deep thinking display working - Message input and send working Status: Core features completed (85%), attachment and history loading pending
This commit is contained in:
143
frontend-v2/src/modules/aia/components/AgentHub.tsx
Normal file
143
frontend-v2/src/modules/aia/components/AgentHub.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* AgentHub - 智能体大厅主界面
|
||||
*
|
||||
* 100%还原原型图V11:
|
||||
* - 最大宽度 760px,居中
|
||||
* - 头部搜索框
|
||||
* - 时间轴设计(左侧序号圆点+连接线)
|
||||
* - 5个阶段,12个智能体卡片
|
||||
*/
|
||||
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { BrainCircuit, Search } from 'lucide-react';
|
||||
import { AgentCard } from './AgentCard';
|
||||
import { AGENTS, PHASES } from '../constants';
|
||||
import type { AgentConfig } from '../types';
|
||||
import '../styles/agent-hub.css';
|
||||
|
||||
interface AgentHubProps {
|
||||
onAgentSelect: (agent: AgentConfig) => void;
|
||||
}
|
||||
|
||||
export const AgentHub: React.FC<AgentHubProps> = ({ onAgentSelect }) => {
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
|
||||
// 按阶段分组智能体
|
||||
const agentsByPhase = useMemo(() => {
|
||||
const grouped: Record<number, AgentConfig[]> = {};
|
||||
AGENTS.forEach(agent => {
|
||||
if (!grouped[agent.phase]) {
|
||||
grouped[agent.phase] = [];
|
||||
}
|
||||
grouped[agent.phase].push(agent);
|
||||
});
|
||||
return grouped;
|
||||
}, []);
|
||||
|
||||
// 搜索提交
|
||||
const handleSearch = () => {
|
||||
if (searchValue.trim()) {
|
||||
// 默认进入第一个智能体并携带搜索内容
|
||||
const firstAgent = AGENTS[0];
|
||||
onAgentSelect({ ...firstAgent, initialQuery: searchValue } as any);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
handleSearch();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="agent-hub">
|
||||
{/* 主体内容 */}
|
||||
<main className="hub-main">
|
||||
{/* 头部搜索区 */}
|
||||
<div className="hub-header">
|
||||
<div className="header-title">
|
||||
<div className="title-icon">
|
||||
<BrainCircuit size={24} />
|
||||
</div>
|
||||
<h1 className="title-text">
|
||||
医学研究专属大模型
|
||||
<span className="title-badge">已接入DeepSeek</span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className="search-box">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="输入研究想法,例如:SGLT2抑制剂对心衰患者预后的影响..."
|
||||
value={searchValue}
|
||||
onChange={(e) => setSearchValue(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
className="search-input"
|
||||
/>
|
||||
<button className="search-btn" onClick={handleSearch}>
|
||||
<Search size={20} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 流水线模块 */}
|
||||
<div className="pipeline-container">
|
||||
{PHASES.map((phase, phaseIndex) => {
|
||||
const isLast = phaseIndex === PHASES.length - 1;
|
||||
const agents = agentsByPhase[phase.phase] || [];
|
||||
|
||||
// 根据阶段确定列数
|
||||
let gridCols = 'grid-cols-3';
|
||||
if (phase.phase === 2) gridCols = 'grid-cols-3'; // 4个卡片,每行3个
|
||||
if (phase.phase === 3) gridCols = 'grid-cols-3'; // 1个卡片
|
||||
if (phase.phase === 4) gridCols = 'grid-cols-3'; // 2个卡片
|
||||
if (phase.phase === 5) gridCols = 'grid-cols-3'; // 2个卡片
|
||||
|
||||
return (
|
||||
<div
|
||||
key={phase.phase}
|
||||
className={`pipeline-stage ${isLast ? 'last-stage' : ''}`}
|
||||
>
|
||||
{/* 左侧时间轴 */}
|
||||
<div className="timeline-marker">
|
||||
<div className={`timeline-dot theme-${phase.theme}`}>
|
||||
{phase.phase}
|
||||
</div>
|
||||
{!isLast && <div className="timeline-line" />}
|
||||
</div>
|
||||
|
||||
{/* 阶段内容 */}
|
||||
<div className="stage-content">
|
||||
<h2 className="stage-title">
|
||||
{phase.name}
|
||||
{phase.isTool && (
|
||||
<span className="tool-badge">工具</span>
|
||||
)}
|
||||
</h2>
|
||||
|
||||
<div className={`agents-grid ${gridCols}`}>
|
||||
{agents.map(agent => (
|
||||
<AgentCard
|
||||
key={agent.id}
|
||||
agent={agent}
|
||||
onClick={onAgentSelect}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{/* 底部 */}
|
||||
<footer className="hub-footer">
|
||||
<p>© 2025 临床研究平台 - 医学研究专属大模型</p>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AgentHub;
|
||||
|
||||
Reference in New Issue
Block a user