feat(frontend): Day 7 - frontend complete layout finished

This commit is contained in:
AI Clinical Dev Team
2025-10-10 17:52:47 +08:00
parent df20300190
commit fef8feb9db
11 changed files with 872 additions and 129 deletions

View File

@@ -0,0 +1,167 @@
import { useParams } from 'react-router-dom'
import { Card, Typography, Input, Button, Space, Select, Upload, Tag, Alert, Divider } from 'antd'
import {
SendOutlined,
PaperClipOutlined,
RobotOutlined,
FolderOpenOutlined,
SyncOutlined,
} from '@ant-design/icons'
import { AGENTS } from '../layouts/MainLayout'
const { Title, Paragraph } = Typography
const { TextArea } = Input
const AgentChatPage = () => {
const { agentId } = useParams()
const agent = AGENTS.find((a) => a.id === agentId)
if (!agent) {
return (
<Alert
message="智能体不存在"
description="请从首页选择一个智能体"
type="error"
showIcon
/>
)
}
if (!agent.enabled) {
return (
<Alert
message="该智能体正在开发中"
description="敬请期待后续版本..."
type="warning"
showIcon
/>
)
}
return (
<div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
{/* 标题栏 */}
<Card style={{ marginBottom: 16 }}>
<Space align="center">
<span style={{ fontSize: 32 }}>{agent.icon}</span>
<div>
<Title level={3} style={{ marginBottom: 4 }}>
{agent.name}
</Title>
<Paragraph type="secondary" style={{ marginBottom: 0 }}>
DeepSeek-V3
</Paragraph>
</div>
</Space>
</Card>
{/* 聊天区域 */}
<Card
style={{
flex: 1,
display: 'flex',
flexDirection: 'column',
overflow: 'hidden',
}}
bodyStyle={{
flex: 1,
display: 'flex',
flexDirection: 'column',
padding: 0,
}}
>
{/* 消息列表区域(占位符) */}
<div
style={{
flex: 1,
padding: 24,
overflowY: 'auto',
background: '#fafafa',
}}
>
<div style={{ textAlign: 'center', padding: '60px 0', color: '#999' }}>
<RobotOutlined style={{ fontSize: 64, marginBottom: 16 }} />
<div></div>
</div>
{/* 消息示例(占位符) */}
<div style={{ maxWidth: 800, margin: '0 auto' }}>
<div style={{ marginBottom: 24 }}>
<Tag color="blue" style={{ marginBottom: 8 }}>
</Tag>
<Card size="small">
<Paragraph style={{ marginBottom: 0 }}>
...
</Paragraph>
</Card>
</div>
<div style={{ marginBottom: 24 }}>
<Tag color="green" style={{ marginBottom: 8 }}>
AI助手
</Tag>
<Card size="small">
<Paragraph style={{ marginBottom: 0 }}>
AI的回复示例...
</Paragraph>
</Card>
</div>
</div>
</div>
<Divider style={{ margin: 0 }} />
{/* 输入区域 */}
<div style={{ padding: 16, background: '#fff' }}>
{/* 工具栏 */}
<Space style={{ marginBottom: 12, width: '100%', justifyContent: 'space-between' }}>
<Space>
<Upload showUploadList={false}>
<Button icon={<PaperClipOutlined />}></Button>
</Upload>
<Button icon={<FolderOpenOutlined />}>
@
</Button>
<Select
defaultValue="deepseek-v3"
style={{ width: 180 }}
options={[
{ label: 'DeepSeek-V3', value: 'deepseek-v3' },
{ label: 'Qwen3-72B', value: 'qwen3-72b' },
{ label: 'Gemini Pro', value: 'gemini-pro' },
]}
/>
</Space>
<Tag color="orange" icon={<SyncOutlined spin />}>
...
</Tag>
</Space>
{/* 输入框 */}
<Space.Compact style={{ width: '100%' }}>
<TextArea
placeholder="输入您的问题... (功能开发中)"
autoSize={{ minRows: 2, maxRows: 6 }}
disabled
/>
<Button
type="primary"
icon={<SendOutlined />}
style={{ height: 'auto' }}
disabled
>
</Button>
</Space.Compact>
</div>
</Card>
</div>
)
}
export default AgentChatPage

View File

@@ -1,92 +0,0 @@
import { useParams } from 'react-router-dom'
import { Card, Typography, Tag, Button, Space } from 'antd'
import { ArrowLeftOutlined } from '@ant-design/icons'
import { useNavigate } from 'react-router-dom'
const { Title, Paragraph } = Typography
const AGENTS_MAP: Record<string, { name: string; icon: string; desc: string }> = {
'topic-evaluation': { name: '选题评价智能体', icon: '🎯', desc: '从创新性、临床价值、科学性和可行性等维度评估研究选题' },
'scientific-question': { name: '科学问题梳理智能体', icon: '🔬', desc: '将模糊的研究想法提炼成清晰、具体、可验证的科学问题' },
'picos-construction': { name: 'PICOS构建智能体', icon: '📋', desc: '按照PICOS原则结构化定义临床研究的核心要素' },
'observation-design': { name: '观察指标设计智能体', icon: '📊', desc: '推荐合适的主要、次要及安全性观察指标集' },
'crf-development': { name: 'CRF制定智能体', icon: '📝', desc: '自动生成结构化、符合规范的病例报告表CRF框架' },
'sample-size': { name: '样本量计算智能体', icon: '🔢', desc: '根据研究参数提供科学合理的样本量估算结果' },
'protocol-writing': { name: '临床研究方案撰写智能体', icon: '📄', desc: '自动生成结构完整的临床研究设计方案' },
'paper-polishing': { name: '论文润色智能体', icon: '✨', desc: '提供专业级的语言润色,修正语法、拼写和表达方式' },
'paper-translation': { name: '论文翻译智能体', icon: '🌐', desc: '提供专业、精准的中英互译服务' },
'methodology-review': { name: '方法学评审智能体', icon: '🔍', desc: '对研究方案或论文进行全面的方法学评审' },
'journal-methodology-review': { name: '期刊方法学评审智能体', icon: '📑', desc: '模拟期刊审稿人视角,进行方法学挑战' },
'journal-guidelines-review': { name: '期刊稿约评审智能体', icon: '✅', desc: '检查文章格式、字数、参考文献规范等是否符合投稿要求' },
}
const AgentPage = () => {
const { agentId } = useParams<{ agentId: string }>()
const navigate = useNavigate()
const agent = agentId ? AGENTS_MAP[agentId] : null
if (!agent) {
return (
<Card>
<Paragraph></Paragraph>
<Button onClick={() => navigate('/')}></Button>
</Card>
)
}
return (
<div>
{/* 头部 */}
<Space direction="vertical" size="large" style={{ width: '100%' }}>
<Button icon={<ArrowLeftOutlined />} onClick={() => navigate('/')}>
</Button>
<Card>
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
<div>
<span style={{ fontSize: 48, marginRight: 16 }}>{agent.icon}</span>
<Title level={2} style={{ display: 'inline', margin: 0 }}>
{agent.name}
</Title>
<Tag color="blue" style={{ marginLeft: 16 }}>
AI智能体
</Tag>
</div>
<Paragraph type="secondary" style={{ fontSize: 16 }}>
{agent.desc}
</Paragraph>
</Space>
</Card>
{/* 功能区域 - 占位符 */}
<Card title="智能对话区域" extra={<Tag color="orange"></Tag>}>
<div
style={{
height: 400,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#f5f5f5',
borderRadius: 8,
}}
>
<Space direction="vertical" align="center">
<div style={{ fontSize: 64 }}>💬</div>
<Title level={4} type="secondary">
...
</Title>
<Paragraph type="secondary">
Day 9-10
</Paragraph>
</Space>
</div>
</Card>
</Space>
</div>
)
}
export default AgentPage

View File

@@ -0,0 +1,36 @@
import { Card, Empty, Alert } from 'antd'
import { HistoryOutlined, SyncOutlined } from '@ant-design/icons'
const HistoryPage = () => {
return (
<div>
<Alert
message="功能开发中"
description="历史记录功能正在开发中,您将能够查看和管理所有对话历史..."
type="warning"
showIcon
icon={<SyncOutlined spin />}
style={{ marginBottom: 24 }}
/>
<Card>
<Empty
image={Empty.PRESENTED_IMAGE_SIMPLE}
imageStyle={{ height: 120 }}
description={
<div>
<HistoryOutlined style={{ fontSize: 48, color: '#d9d9d9', marginBottom: 16 }} />
<div style={{ color: '#999' }}>线</div>
<div style={{ color: '#ccc', fontSize: 12, marginTop: 8 }}>
</div>
</div>
}
/>
</Card>
</div>
)
}
export default HistoryPage

View File

@@ -1,27 +1,35 @@
import { Card, Row, Col, Typography, Button } from 'antd'
import { Card, Row, Col, Typography, Button, Tag, message } from 'antd'
import { useNavigate } from 'react-router-dom'
import { ExperimentOutlined, RocketOutlined } from '@ant-design/icons'
import { ExperimentOutlined, RocketOutlined, LockOutlined } from '@ant-design/icons'
const { Title, Paragraph } = Typography
const AGENTS = [
{ id: 'topic-evaluation', name: '选题评价智能体', icon: '🎯', desc: '从创新性、临床价值、科学性和可行性等维度评估研究选题' },
{ id: 'scientific-question', name: '科学问题梳理智能体', icon: '🔬', desc: '将模糊的研究想法提炼成清晰、具体、可验证的科学问题' },
{ id: 'picos-construction', name: 'PICOS构建智能体', icon: '📋', desc: '按照PICOS原则结构化定义临床研究的核心要素' },
{ id: 'observation-design', name: '观察指标设计智能体', icon: '📊', desc: '推荐合适的主要、次要及安全性观察指标集' },
{ id: 'crf-development', name: 'CRF制定智能体', icon: '📝', desc: '自动生成结构化、符合规范的病例报告表CRF框架' },
{ id: 'sample-size', name: '样本量计算智能体', icon: '🔢', desc: '根据研究参数提供科学合理的样本量估算结果' },
{ id: 'protocol-writing', name: '临床研究方案撰写智能体', icon: '📄', desc: '自动生成结构完整的临床研究设计方案' },
{ id: 'paper-polishing', name: '论文润色智能体', icon: '✨', desc: '提供专业级的语言润色,修正语法、拼写和表达方式' },
{ id: 'paper-translation', name: '论文翻译智能体', icon: '🌐', desc: '提供专业、精准的中英互译服务' },
{ id: 'methodology-review', name: '方法学评审智能体', icon: '🔍', desc: '对研究方案或论文进行全面的方法学评审' },
{ id: 'journal-methodology-review', name: '期刊方法学评审智能体', icon: '📑', desc: '模拟期刊审稿人视角,进行方法学挑战' },
{ id: 'journal-guidelines-review', name: '期刊稿约评审智能体', icon: '✅', desc: '检查文章格式、字数、参考文献规范等是否符合投稿要求' },
{ id: 'topic-evaluation', name: '选题评价智能体', icon: '🎯', desc: '从创新性、临床价值、科学性和可行性等维度评估研究选题', enabled: true },
{ id: 'scientific-question', name: '科学问题梳理智能体', icon: '🔬', desc: '将模糊的研究想法提炼成清晰、具体、可验证的科学问题', enabled: false },
{ id: 'picos-construction', name: 'PICOS构建智能体', icon: '📋', desc: '按照PICOS原则结构化定义临床研究的核心要素', enabled: false },
{ id: 'observation-design', name: '观察指标设计智能体', icon: '📊', desc: '推荐合适的主要、次要及安全性观察指标集', enabled: false },
{ id: 'crf-development', name: 'CRF制定智能体', icon: '📝', desc: '自动生成结构化、符合规范的病例报告表CRF框架', enabled: false },
{ id: 'sample-size', name: '样本量计算智能体', icon: '🔢', desc: '根据研究参数提供科学合理的样本量估算结果', enabled: false },
{ id: 'protocol-writing', name: '临床研究方案撰写智能体', icon: '📄', desc: '自动生成结构完整的临床研究设计方案', enabled: false },
{ id: 'paper-polishing', name: '论文润色智能体', icon: '✨', desc: '提供专业级的语言润色,修正语法、拼写和表达方式', enabled: false },
{ id: 'paper-translation', name: '论文翻译智能体', icon: '🌐', desc: '提供专业、精准的中英互译服务', enabled: false },
{ id: 'methodology-review', name: '方法学评审智能体', icon: '🔍', desc: '对研究方案或论文进行全面的方法学评审', enabled: false },
{ id: 'journal-methodology-review', name: '期刊方法学评审智能体', icon: '📑', desc: '模拟期刊审稿人视角,进行方法学挑战', enabled: false },
{ id: 'journal-guidelines-review', name: '期刊稿约评审智能体', icon: '✅', desc: '检查文章格式、字数、参考文献规范等是否符合投稿要求', enabled: false },
]
const HomePage = () => {
const navigate = useNavigate()
const handleAgentClick = (agent: typeof AGENTS[0]) => {
if (!agent.enabled) {
message.info('该智能体正在开发中,敬请期待!')
return
}
navigate(`/agent/${agent.id}`)
}
return (
<div>
{/* 欢迎区域 */}
@@ -44,10 +52,23 @@ const HomePage = () => {
{AGENTS.map((agent) => (
<Col xs={24} sm={12} md={8} lg={6} key={agent.id}>
<Card
hoverable
style={{ height: '100%' }}
onClick={() => navigate(`/agent/${agent.id}`)}
hoverable={agent.enabled}
style={{
height: '100%',
opacity: agent.enabled ? 1 : 0.7,
position: 'relative',
}}
onClick={() => handleAgentClick(agent)}
>
{!agent.enabled && (
<Tag
color="orange"
icon={<LockOutlined />}
style={{ position: 'absolute', top: 8, right: 8 }}
>
线
</Tag>
)}
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 48, marginBottom: 12 }}>{agent.icon}</div>
<Title level={4} style={{ marginBottom: 8 }}>
@@ -56,8 +77,8 @@ const HomePage = () => {
<Paragraph type="secondary" style={{ marginBottom: 16, minHeight: 44 }}>
{agent.desc}
</Paragraph>
<Button type="primary" block>
使
<Button type={agent.enabled ? 'primary' : 'default'} block disabled={!agent.enabled}>
{agent.enabled ? '开始使用' : '敬请期待'}
</Button>
</div>
</Card>

View File

@@ -0,0 +1,225 @@
import {
Card,
Button,
Space,
Table,
Tag,
Progress,
Alert,
} from 'antd'
import {
PlusOutlined,
FolderOutlined,
FileTextOutlined,
UploadOutlined,
DeleteOutlined,
SyncOutlined,
} from '@ant-design/icons'
const KnowledgePage = () => {
// 模拟知识库数据
const mockKnowledgeBases = [
{
id: '1',
name: '心血管疾病研究文献库',
fileCount: 15,
totalSize: '45MB',
createdAt: '2025-10-05',
status: 'ready',
},
]
// 模拟文档数据
const mockDocuments = [
{
id: '1',
name: '高血压治疗指南2024.pdf',
size: '3.2MB',
uploadedAt: '2025-10-05 14:30',
status: 'processed',
},
{
id: '2',
name: '心血管疾病流行病学研究.docx',
size: '1.8MB',
uploadedAt: '2025-10-05 15:20',
status: 'processing',
},
]
const kbColumns = [
{
title: '知识库名称',
dataIndex: 'name',
key: 'name',
render: (text: string) => (
<Space>
<FolderOutlined style={{ color: '#1890ff' }} />
<span>{text}</span>
</Space>
),
},
{
title: '文档数量',
dataIndex: 'fileCount',
key: 'fileCount',
render: (count: number) => `${count} / 50`,
},
{
title: '总大小',
dataIndex: 'totalSize',
key: 'totalSize',
},
{
title: '创建时间',
dataIndex: 'createdAt',
key: 'createdAt',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => (
<Tag color={status === 'ready' ? 'green' : 'orange'}>
{status === 'ready' ? '就绪' : '处理中'}
</Tag>
),
},
{
title: '操作',
key: 'actions',
render: () => (
<Space>
<Button size="small" icon={<UploadOutlined />} disabled>
</Button>
<Button size="small" danger icon={<DeleteOutlined />} disabled>
</Button>
</Space>
),
},
]
const docColumns = [
{
title: '文件名',
dataIndex: 'name',
key: 'name',
render: (text: string) => (
<Space>
<FileTextOutlined />
<span>{text}</span>
</Space>
),
},
{
title: '大小',
dataIndex: 'size',
key: 'size',
},
{
title: '上传时间',
dataIndex: 'uploadedAt',
key: 'uploadedAt',
},
{
title: '处理状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => {
if (status === 'processed') {
return <Tag color="green"></Tag>
}
return (
<Space>
<Tag color="processing" icon={<SyncOutlined spin />}>
</Tag>
<Progress percent={65} size="small" style={{ width: 100 }} />
</Space>
)
},
},
{
title: '操作',
key: 'actions',
render: () => (
<Button size="small" danger icon={<DeleteOutlined />} disabled>
</Button>
),
},
]
return (
<div>
{/* 提示信息 */}
<Alert
message="知识库功能说明"
description="每个用户最多可创建3个知识库每个知识库最多上传50个文件支持PDF、DOCX格式。在对话时可以@知识库让AI基于您的文献进行回答。"
type="info"
showIcon
closable
style={{ marginBottom: 16 }}
/>
<Alert
message="功能开发中"
description="知识库管理功能正在开发中,敬请期待..."
type="warning"
showIcon
icon={<SyncOutlined spin />}
style={{ marginBottom: 24 }}
/>
{/* 知识库列表 */}
<Card
title={
<Space>
<FolderOutlined />
<span> (1/3)</span>
</Space>
}
extra={
<Button type="primary" icon={<PlusOutlined />} disabled>
</Button>
}
style={{ marginBottom: 24 }}
>
<Table
columns={kbColumns}
dataSource={mockKnowledgeBases}
rowKey="id"
pagination={false}
/>
</Card>
{/* 文档列表 */}
<Card
title={
<Space>
<FileTextOutlined />
<span></span>
</Space>
}
extra={
<Button icon={<UploadOutlined />} disabled>
</Button>
}
>
<Table
columns={docColumns}
dataSource={mockDocuments}
rowKey="id"
pagination={false}
/>
</Card>
</div>
)
}
export default KnowledgePage