fix: 第12轮搜索审计修复 — _normalize_field_label 崩溃/keyset NULLSLAT/共享列表变异等21项修复
P0 (3): _normalize_field_label 函数缺失导致 (a OR b)[TI] 崩溃;
共享列表变异污染 result.groups;POST /search/advanced 缺少用户认证
P1 (8): has_not 忽略括号内 NOT;紧凑日期 YYYYMMDD 未归一化;
日期字段非日期文本 SQL 错误;keyset NULLSLAT ~50% 空值行跳过;
first_author 非 dict JSON 崩溃;MeSH 无匹配静默丢弃;
相关性排序含否定词;词数检查在 PubMed 清洗之前;
普通搜索缺错误处理;#N 引号感知不完整
P2 (6): 月越界退化;MH/MAJR FALSE 语义;field 白名单缺字段;
retracted/negative_result/tag_ids 验证器;resolveQuery 重复调用;
SearchRequestBody.page 可选;restoreFromQuery showCustomYear
This commit is contained in:
@@ -26,9 +26,11 @@ function saveAll(entries: HistoryEntry[]) {
|
||||
|
||||
/** 把 #N 引用替换为 expanded_query(加括号保护优先级) */
|
||||
export function resolveQuery(query: string, entries: HistoryEntry[]): string {
|
||||
return query.replace(/#(\d+)/g, (_m, num) => {
|
||||
// P12: skip quoted #N, only expand unquoted references
|
||||
return query.replace(/"[^"]*"|'[^']*'|#(\d+)/g, (m, num) => {
|
||||
if (num === undefined) return m // inside quotes, literal
|
||||
const found = entries.find(e => e.id === `#${num}`)
|
||||
return found ? `(${found.expanded_query})` : _m
|
||||
return found ? `(${found.expanded_query})` : m
|
||||
})
|
||||
}
|
||||
|
||||
@@ -39,8 +41,11 @@ export function expandQuery(query: string, entries: HistoryEntry[]): string {
|
||||
let current = query
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (current === prev) break
|
||||
const refs = current.match(/#(\d+)/g)
|
||||
if (refs) {
|
||||
// P12: only count #N outside quotes for cycle detection
|
||||
const refs = [...current.matchAll(/"[^"]*"|'[^']*'|#(\d+)/g)]
|
||||
.filter(m => m[1] !== undefined)
|
||||
.map(m => `#${m[1]}`)
|
||||
if (refs.length) {
|
||||
const uniqueRefs = [...new Set(refs)]
|
||||
for (const ref of uniqueRefs) {
|
||||
if (seen.has(ref)) return prev // 循环引用 → 返回上次安全结果
|
||||
|
||||
@@ -330,7 +330,7 @@ export interface SearchRequestBody {
|
||||
field?: string
|
||||
boolean?: string // "and" | "or"
|
||||
exact_phrase?: boolean
|
||||
page: number
|
||||
page?: number
|
||||
page_size: number
|
||||
sort?: string
|
||||
cursor_val?: string
|
||||
|
||||
@@ -397,8 +397,14 @@ function restoreFromQuery() {
|
||||
if (dt.length >= 4) yearToStr.value = dt.slice(0, 4)
|
||||
}
|
||||
} else {
|
||||
if (route.query.year_from) yearFromStr.value = String(route.query.year_from)
|
||||
if (route.query.year_to) yearToStr.value = String(route.query.year_to)
|
||||
if (route.query.year_from) {
|
||||
yearFromStr.value = String(route.query.year_from)
|
||||
showCustomYear.value = true
|
||||
}
|
||||
if (route.query.year_to) {
|
||||
yearToStr.value = String(route.query.year_to)
|
||||
showCustomYear.value = true
|
||||
}
|
||||
}
|
||||
if (route.query.tag) selectedTags.value = String(route.query.tag).split(',')
|
||||
if (route.query.tier) selectedTiers.value = String(route.query.tier).split(',')
|
||||
|
||||
@@ -226,8 +226,11 @@ function resolveQuery(q: string): string {
|
||||
let current = q
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (current === prev) break
|
||||
const refs = current.match(/#\d+/g)
|
||||
if (refs) {
|
||||
// P12: only count #N outside quotes for cycle detection (quoted #N are literals)
|
||||
const refs = [...current.matchAll(/"[^"]*"|'[^']*'|#(\d+)/g)]
|
||||
.filter(m => m[1] !== undefined)
|
||||
.map(m => `#${m[1]}`)
|
||||
if (refs.length) {
|
||||
const uniqueRefs = [...new Set(refs)]
|
||||
for (const ref of uniqueRefs) {
|
||||
if (seen.has(ref)) return prev
|
||||
@@ -304,9 +307,9 @@ function validateQuery(q: string): { valid: boolean; query: string; error?: stri
|
||||
}
|
||||
|
||||
// 校验括号匹配(在展开后的查询上检查,确保历史引用展开后也平衡)
|
||||
const expandedForCheck = resolveQuery(q)
|
||||
const expanded = resolveQuery(q)
|
||||
let depth = 0
|
||||
for (const ch of expandedForCheck) {
|
||||
for (const ch of expanded) {
|
||||
if (ch === '(') depth++
|
||||
if (ch === ')') depth--
|
||||
if (depth < 0) {
|
||||
@@ -317,7 +320,7 @@ function validateQuery(q: string): { valid: boolean; query: string; error?: stri
|
||||
return { valid: false, query: q, error: '括号不匹配:缺少右括号(结合历史查询展开后)' }
|
||||
}
|
||||
|
||||
return { valid: true, query: resolveQuery(q) }
|
||||
return { valid: true, query: expanded }
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
Reference in New Issue
Block a user