refactor(asl): ASL frontend architecture refactoring with left navigation

- feat: Create ASLLayout component with 7-module left navigation
- feat: Implement Title Screening Settings page with optimized PICOS layout
- feat: Add placeholder pages for Workbench and Results
- fix: Fix nested routing structure for React Router v6
- fix: Resolve Spin component warning in MainLayout
- fix: Add QueryClientProvider to App.tsx
- style: Optimize PICOS form layout (P+I left, C+O+S right)
- style: Align Inclusion/Exclusion criteria side-by-side
- docs: Add architecture refactoring and routing fix reports

Ref: Week 2 Frontend Development
Scope: ASL module MVP - Title Abstract Screening
This commit is contained in:
2025-11-18 21:51:51 +08:00
parent e3e7e028e8
commit 3634933ece
213 changed files with 20054 additions and 442 deletions

View File

@@ -0,0 +1,152 @@
/**
* ASL模块布局组件
*
* 左侧导航栏 + 右侧内容区
* 参考原型AI智能文献-标题摘要初筛原型.html
*/
import { Layout, Menu } from 'antd';
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
import {
FileTextOutlined,
SearchOutlined,
FolderOpenOutlined,
FilterOutlined,
FileSearchOutlined,
DatabaseOutlined,
BarChartOutlined,
SettingOutlined,
CheckSquareOutlined,
UnorderedListOutlined,
} from '@ant-design/icons';
import type { MenuProps } from 'antd';
const { Sider, Content } = Layout;
type MenuItem = Required<MenuProps>['items'][number];
const ASLLayout = () => {
const navigate = useNavigate();
const location = useLocation();
// 菜单项配置
const menuItems: MenuItem[] = [
{
key: 'research-plan',
icon: <FileTextOutlined />,
label: '1. 研究方案生成',
disabled: true,
title: '敬请期待'
},
{
key: 'literature-search',
icon: <SearchOutlined />,
label: '2. 智能文献检索',
disabled: true,
title: '敬请期待'
},
{
key: 'literature-management',
icon: <FolderOpenOutlined />,
label: '3. 文献管理',
disabled: true,
title: '敬请期待'
},
{
key: 'title-screening',
icon: <FilterOutlined />,
label: '4. 标题摘要初筛',
children: [
{
key: '/literature/screening/title/settings',
icon: <SettingOutlined />,
label: '设置与启动',
},
{
key: '/literature/screening/title/workbench',
icon: <CheckSquareOutlined />,
label: '审核工作台',
},
{
key: '/literature/screening/title/results',
icon: <UnorderedListOutlined />,
label: '初筛结果',
},
],
},
{
key: 'fulltext-screening',
icon: <FileSearchOutlined />,
label: '5. 全文复筛',
disabled: true,
title: '敬请期待'
},
{
key: 'data-extraction',
icon: <DatabaseOutlined />,
label: '6. 全文解析与数据提取',
disabled: true,
title: '敬请期待'
},
{
key: 'data-analysis',
icon: <BarChartOutlined />,
label: '7. 数据综合分析与报告',
disabled: true,
title: '敬请期待'
},
];
// 处理菜单点击
const handleMenuClick: MenuProps['onClick'] = ({ key }) => {
if (key.startsWith('/')) {
navigate(key);
}
};
// 获取当前选中的菜单项和展开的子菜单
const currentPath = location.pathname;
const selectedKeys = [currentPath];
const openKeys = currentPath.includes('screening/title') ? ['title-screening'] : [];
return (
<Layout className="h-screen">
{/* 左侧导航栏 */}
<Sider
width={250}
className="bg-gray-50 border-r border-gray-200"
theme="light"
>
<div className="p-4 border-b border-gray-200">
<h2 className="text-lg font-bold text-gray-800">
<FilterOutlined className="mr-2" />
AI智能文献
</h2>
<p className="text-xs text-gray-500 mt-1">
MVP
</p>
</div>
<Menu
mode="inline"
selectedKeys={selectedKeys}
defaultOpenKeys={openKeys}
items={menuItems}
onClick={handleMenuClick}
className="border-none"
style={{ height: 'calc(100vh - 80px)', overflowY: 'auto' }}
/>
</Sider>
{/* 右侧内容区 */}
<Layout>
<Content className="bg-white overflow-auto">
<Outlet />
</Content>
</Layout>
</Layout>
);
};
export default ASLLayout;