# 高级搜索独立页面设计(PubMed 风格) > 文档日期:2026-07-24 > 状态:**已规划,暂不实现**(先完成普通搜索 Phase 0 Bug 修复) > 设计目标:在 `/app/search/advanced` 独立路由上实现 PubMed 风格的 Advanced Search --- ## 1. 问题 当前系统的"高级搜索"只是 SearchView 上的一个筛选面板(年份范围、期刊等级、标签),与 PubMed 的 Advanced Search(`/pubmed/advanced/`)完全不同。 PubMed Advanced Search 是两个核心功能的组合: 1. **查询构建器(Query Builder)** — 行式字段下拉 + AND/OR/NOT 组合 2. **搜索历史(Search History)** — #1/#2/#3 编号,可点击组合为 `#1 AND #2` ## 2. 目标界面 ``` ┌─────────────────────────────────────────────────────────┐ │ [Basic Search] [Advanced Search] ← Tab 切换 │ ├─────────────────────────────────────────────────────────┤ │ 查询构建器(Query Builder) │ │ ┌───────┬────────────────────────────────────┬──────┐ │ │ │ 字段 │ 查询词 │ × │ │ │ ├───────┼────────────────────────────────────┼──────┤ │ │ │ All │ lung cancer │ × │ │ │ │ AND ▼ │ │ │ │ │ │ MeSH │ lung neoplasms │ × │ │ │ └───────┴────────────────────────────────────┴──────┘ │ │ [+ Add row] [Search] [Details ▼] │ │ ── PubMed 查询字符串 ──────────────────────────────── │ │ (lung cancer[All Fields]) AND (lung neoplasms[MeSH Terms])│ ├─────────────────────────────────────────────────────────┤ │ 搜索历史(Search History) │ │ ┌──────┬─────────────────────────┬───────┬──────────┐ │ │ │ # │ Query │ Hits │ Time │ │ │ ├──────┼─────────────────────────┼───────┼──────────┤ │ │ │ #3 │ #1 AND #2 │ 42 │ 10:32 AM │ │ │ │ #2 │ lung neoplasms[MH] │ 128 │ 10:31 AM │ │ │ │ #1 │ lung cancer[TI] │ 215 │ 10:30 AM │ │ │ └──────┴─────────────────────────┴───────┴──────────┘ │ │ [Combine selected] [Clear history] │ ├─────────────────────────────────────────────────────────┤ │ 搜索结果区域 │ │ (复用现有 LiteratureCard + Pagination) │ └─────────────────────────────────────────────────────────┘ ``` ## 3. 页面布局 ``` ┌──────────────┬──────────────────────────────────┐ │ 左栏 │ 右栏 │ │ 280px │ flex: 1 │ │ │ │ │ Search │ Query Builder (上区) │ │ History │ + 查询字符串显示 │ │ Panel │ │ │ │ ───────── 分割线 ──────── │ │ │ │ │ │ Search Results (下区) │ │ │ 复用 LiteratureCard │ │ │ + Pagination │ └──────────────┴──────────────────────────────────┘ ``` ## 4. 后端改动 ### 4.1 新建模型 SearchHistory | 字段 | 类型 | 说明 | |------|------|------| | `id` | UUID PK | | | `user_id` | FK → users | | | `query_text` | TEXT | 用户输入的原始查询字符串 | | `query_json` | JSON | 结构化查询(各字段解析结果)| | `result_count` | INTEGER | 结果数 | | `created_at` | TIMESTAMPTZ | 搜索时间 | **文件**:`backend/app/models/search_history.py`(新建) **导出**:`backend/app/models/__init__.py` 添加 SearchHistory **迁移**:`alembic revision --autogenerate -m "add_search_history"` ### 4.2 API 端点 挂载在 `features` router 下(`backend/app/api/v1/features.py`): | 方法 | 路径 | 说明 | |------|------|------| | `POST` | `/features/search/advanced` | **已有**。搜索结果后自动存入 history | | `GET` | `/features/search/history` | 获取用户最近 20 条搜索历史 | | `DELETE` | `/features/search/history/{id}` | 删除单条历史 | | `GET` | `/features/search/details` | 查询翻译详情(ATM 展开后的结构) | ### 4.3 搜索自动入 History 修改 `advanced_search()`:搜索成功后**自动 INSERT** 一条 SearchHistory 记录。 ```python # 伪代码 result = await AdvancedSearchEngine.search(db, ...) history = SearchHistory( user_id=user.id, query_text=req.query, query_json=parsed_query, # 解析后的结构化字段 result_count=result["total"], ) db.add(history) await db.commit() ``` ### 4.4 查询构建器 → 后端适配 前端行式构建器发送的结构: ```json { "query": "(lung[TI]) AND (lung neoplasms[MH])", "advanced_builder": { "rows": [ {"field": "TI", "query": "lung", "operator": "AND"}, {"field": "MH", "query": "lung neoplasms", "operator": null} ] } } ``` `AdvancedSearchRequest` 新增 `advanced_builder` 可选字段。 ### 4.5 查询详情端点 ```python @router.get("/search/details") async def search_details(query: str = Query(...)): """返回 ATM 展开后的查询结构(类似 PubMed 'Search details' 面板)""" parsed = parse_pubmed_query(query) return { "parsed": parsed.model_dump(), "translated": expanded_query, # ATM 引擎(Phase 1.7 后) } ``` ## 5. 前端改动 ### 5.1 QueryBuilder.vue **位置**:`frontend/src/components/search/QueryBuilder.vue` **功能**:行式查询构建器 - 每行:`[NSelect 字段] + [NInput 查询词] + [NSelect AND/OR/NOT] + [删除按钮]` - 第一行无运算符选择 - 底部 `[+ Add row]` 按钮 - 字段下拉选项(12 个): | 标签 | 值 | |------|-----| | All Fields | ALL | | Title | TI | | Title/Abstract | TIAB | | Author | AU | | MeSH Terms | MH | | MeSH Major Topic | MAJR | | Journal | TA | | Affiliation | AD | | Language | LA | | Publication Type | PT | | Grant Number | GR | | Chemical | NM | - 自动生成 PubMed 语法字符串:`(lung[TI]) AND (lung neoplasms[MH])` - `[Search]` → 调用 `POST /features/search/advanced` - `[Add to history]` → 后端自动存,无需手动 **Props**: 无 **Emits**: `@search(query: string, field: string, ...params)` ### 5.2 SearchHistoryPanel.vue **位置**:`frontend/src/components/search/SearchHistoryPanel.vue` **功能**:搜索历史表格 - 加载时调用 `GET /features/search/history` - 表格列:#、Query、Hits、Time - 点击行 → 将 `#1` 语法插入 Query Box - 行操作:删除 - `[Combine]` → 选中多条 → 生成 `#1 AND #2` - `[Clear history]` → 调用批量删除 **Props**: 无 **Emits**: `@useQuery(query: string)`、`@search(query: string)` ### 5.3 AdvancedSearchView.vue **位置**:`frontend/src/views/app/AdvancedSearchView.vue` **布局**: - 左栏 280px:SearchHistoryPanel - 右栏:上区 QueryBuilder + 下区搜索结果(LiteratureCard + Pagination) - 顶部 `[Basic Search] / [Advanced Search]` Tab 切换 **依赖**: - `LiteratureCard.vue`(现有,复用) - `Pagination`(现有,复用) ### 5.4 路由更新 **文件**:`frontend/src/router/index.ts` ```typescript { path: 'search/advanced', name: 'search-advanced', component: () => import('../views/app/AdvancedSearchView.vue') } ``` ### 5.5 侧边栏 在导航增加入口:`搜索` → `高级搜索` **文件**:检查侧边栏组件(Sidebar.vue 或布局文件) ### 5.6 TypeScript 类型更新 **文件**:`frontend/src/types/index.ts` ```typescript export interface AdvancedBuilderRow { field: string query: string operator: 'AND' | 'OR' | 'NOT' | null } export interface SearchHistoryItem { id: string query_text: string result_count: number created_at: string } // SearchRequestBody 补充 export interface SearchRequestBody { // ...已有字段... advanced_builder?: { rows: AdvancedBuilderRow[] } } ``` ## 6. 依赖关系 | 依赖 | 说明 | |------|------| | **Phase 0(必须完成)** | 搜索 Bug(OR 布尔、MH JOIN、recent_subq)不修复则高级搜索结果也不正确 | | **Phase 1.1(tree_number)** | MeSH Terms 字段的子树展开依赖 | | **Phase 1.3-1.5(字段标签)** | QueryBuilder 的 AD/LA/EDAT 字段依赖 | | **Phase 1.7(ATM 引擎)** | 查询详情面板的 "Translated query" 依赖 | | **无依赖** | QueryBuilder UI + SearchHistory 后端可立即实现(框架先搭好) | ## 7. 工作量估算 | 任务 | 文件 | 预估 | |------|------|------| | SearchHistory 模型 + 迁移 | `models/search_history.py` + 迁移脚本 + `__init__.py` | 30min | | 后端 CRUD 端点 | `features.py`(GET/DELETE history) | 1h | | 搜索自动入 history | `features.py` advanced_search() | 15min | | 查询详情端点 | `features.py` | 30min | | QueryBuilder.vue | `components/search/QueryBuilder.vue` | 2-3h | | SearchHistoryPanel.vue | `components/search/SearchHistoryPanel.vue` | 2h | | AdvancedSearchView.vue | `views/app/AdvancedSearchView.vue` | 2h | | 路由 + 侧边栏 + 类型 | router, Sidebar, types | 30min | | **合计** | | **~9-10h** | ## 8. 优先级排序 1. **最优先**:Phase 0 Bug 修复(12 项,代码已改待提交) 2. **次优先**:此高级搜索独立页面(9-10h) 3. **后续**:Phase 1-3 字段标签补齐、ATM 引擎、排序优化