Initial commit: snapAna 截图智能整理工具
包含 FastAPI 后端、React 前端、队列/OCR/标签/待办等完整功能。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
"""截图列表搜索:FTS + 子串模糊(兼容中文标签/标题)。"""
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import or_, select, text
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.meta import ScreenshotMeta
|
||||
from app.models.screenshot import Screenshot
|
||||
from app.models.tag import Tag
|
||||
|
||||
|
||||
def fts_query_string(raw: str) -> str:
|
||||
"""把用户输入处理成 FTS5 查询串(中英文均支持前缀匹配)。"""
|
||||
parts = [p for p in raw.replace("\n", " ").split() if p]
|
||||
if not parts:
|
||||
return raw
|
||||
cleaned: list[str] = []
|
||||
for p in parts:
|
||||
p = p.replace('"', "").strip()
|
||||
if not p:
|
||||
continue
|
||||
cleaned.append(f'"{p}"*')
|
||||
return " ".join(cleaned)
|
||||
|
||||
|
||||
def collect_search_ids(session: Session, q: str, *, limit: int = 5000) -> set[int]:
|
||||
"""联合 FTS5 与 LIKE 子串搜索,返回匹配的 screenshot id 集合。"""
|
||||
q = q.strip()
|
||||
if not q:
|
||||
return set()
|
||||
|
||||
ids: set[int] = set()
|
||||
like = f"%{q}%"
|
||||
|
||||
# 1) FTS5 全文索引
|
||||
try:
|
||||
fts_sql = text(
|
||||
"SELECT rowid FROM screenshots_fts WHERE screenshots_fts MATCH :q LIMIT :lim"
|
||||
)
|
||||
rows = session.execute(fts_sql, {"q": fts_query_string(q), "lim": limit}).fetchall()
|
||||
ids.update(int(row[0]) for row in rows)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 2) 子串模糊:OCR/AI 文本(解决「三花」匹配「三花猫」)
|
||||
meta_ids = session.scalars(
|
||||
select(ScreenshotMeta.screenshot_id).where(
|
||||
or_(
|
||||
ScreenshotMeta.ocr_text.ilike(like),
|
||||
ScreenshotMeta.ai_title.ilike(like),
|
||||
ScreenshotMeta.ai_summary.ilike(like),
|
||||
ScreenshotMeta.ai_suggestion.ilike(like),
|
||||
)
|
||||
).limit(limit)
|
||||
).all()
|
||||
ids.update(int(i) for i in meta_ids)
|
||||
|
||||
# 3) 标签名子串匹配
|
||||
tag_ids = session.scalars(
|
||||
select(Screenshot.id)
|
||||
.join(Screenshot.tags)
|
||||
.where(Tag.name.ilike(like))
|
||||
.limit(limit)
|
||||
).all()
|
||||
ids.update(int(i) for i in tag_ids)
|
||||
|
||||
return ids
|
||||
Reference in New Issue
Block a user