Files
my-v0-server/app/resources/component.py
T

81 lines
3.4 KiB
Python

"""查询前端组件目录:目录只来自启动时从 MongoDB 载入的进程内存缓存,没有文件回退"""
from pathlib import Path
from app.schemas.component_resource import (
ComponentCatalog,
ComponentQuery,
ComponentResult,
)
# 进程内共享的组件目录,由启动流程载入;agent 与前端接口读取同一份
_cached_catalog: ComponentCatalog | None = None
def set_catalog_cache(catalog: ComponentCatalog | None) -> None:
global _cached_catalog
_cached_catalog = catalog
def get_catalog_cache() -> ComponentCatalog | None:
return _cached_catalog
def load_catalog_file(path: str | Path) -> ComponentCatalog:
"""读取导出的目录文件,只供导入脚本使用,运行时不读取文件"""
# 如果传入的是相对路径,以项目根目录为基准,避免受启动时工作目录影响
target = Path(path)
if not target.is_absolute():
target = Path(__file__).resolve().parents[2] / target
# utf-8-sig 同时兼容带 BOM 和不带 BOM 的 UTF-8 文件;损坏或不合法直接报错
return ComponentCatalog.model_validate_json(target.read_text(encoding="utf-8-sig"))
class ComponentProvider:
def query(self, query: ComponentQuery) -> ComponentResult:
catalog = _cached_catalog
if catalog is None:
# 启动时未载入目录,返回未支持状态和原因,由调用方决定失败处理方式
return ComponentResult(
status="unsupported",
message="物料目录未载入,请确认已配置 MongoDB 并导入物料",
)
# 如果提供关键词,去除首尾空白并统一大小写,未提供时不启用关键词筛选
keyword = (
query.keyword.strip().casefold() if query.keyword is not None else None
)
# 收集同时满足所有已提供条件的组件,未设置任何条件时返回全量目录
matches = []
for component in catalog.components:
# 如果指定目录编号,则跳过编号不完全匹配的组件
if query.key is not None and component.key != query.key:
continue
# 如果指定前端组件类型,则跳过类型不完全匹配的组件
if query.type is not None and component.type != query.type:
continue
# 将编号、类型、名称、说明和标签拼成检索文本,并与关键词统一大小写
searchable = " ".join(
[
component.key,
component.type,
component.name,
component.description,
*component.tags,
]
).casefold()
# 如果设置了关键词,但检索文本中不包含该关键词,则跳过当前组件
if keyword is not None and keyword not in searchable:
continue
# 深拷贝后返回,调用方修改结果不会污染共享缓存
matches.append(component.model_copy(deep=True))
# 根据是否有匹配项区分查询成功和未找到,同时保留目录版本、来源及结果说明
return ComponentResult(
status="resolved" if matches else "not_found",
components=matches,
catalog_version=catalog.version,
message="已找到组件定义" if matches else "已查询组件目录,未找到匹配的组件",
)