Core Components: - PDFStorageService with Dify/OSS adapters - LLM12FieldsService with Nougat-first + dual-model + 3-layer JSON parsing - PromptBuilder for dynamic prompt assembly - MedicalLogicValidator with 5 rules + fault tolerance - EvidenceChainValidator for citation integrity - ConflictDetectionService for dual-model comparison Prompt Engineering: - System Prompt (6601 chars, Section-Aware strategy) - User Prompt template (PICOS context injection) - JSON Schema (12 fields constraints) - Cochrane standards (not loaded in MVP) Key Innovations: - 3-layer JSON parsing (JSON.parse + json-repair + code block extraction) - Promise.allSettled for dual-model fault tolerance - safeGetFieldValue for robust field extraction - Mixed CN/EN token calculation Integration Tests: - integration-test.ts (full test) - quick-test.ts (quick test) - cached-result-test.ts (fault tolerance test) Documentation Updates: - Development record (Day 2-3 summary) - Quality assurance strategy (full-text screening) - Development plan (progress update) - Module status (v1.1 update) - Technical debt (10 new items) Test Results: - JSON parsing success rate: 100% - Medical logic validation: 5/5 passed - Dual-model parallel processing: OK - Cost per PDF: CNY 0.10 Files: 238 changed, 14383 insertions(+), 32 deletions(-) Docs: docs/03-涓氬姟妯″潡/ASL-AI鏅鸿兘鏂囩尞/05-寮€鍙戣褰?2025-11-22_Day2-Day3_LLM鏈嶅姟涓庨獙璇佺郴缁熷紑鍙?md
159 lines
3.7 KiB
TypeScript
159 lines
3.7 KiB
TypeScript
/**
|
||
* 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;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|