feat:架构重构
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
"""查询前端组件目录:目录只来自启动时从 MongoDB 载入的进程内存缓存,没有文件回退"""
|
||||
"""前端组件目录:运行时只读启动时从 MongoDB 载入的进程内存缓存,没有文件回退"""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from app.schemas.component_resource import (
|
||||
ComponentCatalog,
|
||||
ComponentQuery,
|
||||
ComponentResult,
|
||||
)
|
||||
from app.schemas.component_resource import ComponentCatalog
|
||||
|
||||
# 进程内共享的组件目录,由启动流程载入;agent 与前端接口读取同一份
|
||||
_cached_catalog: ComponentCatalog | None = None
|
||||
@@ -28,7 +24,9 @@ MATERIALS_DIR = Path(__file__).resolve().parent / "materials"
|
||||
FIELD_GROUPS_FILE = "field_groups.json"
|
||||
|
||||
|
||||
def load_material_definitions(directory: str | Path = MATERIALS_DIR) -> ComponentCatalog:
|
||||
def load_material_definitions(
|
||||
directory: str | Path = MATERIALS_DIR,
|
||||
) -> ComponentCatalog:
|
||||
"""读取物料定义目录:共享字段分组一个文件,每个物料一个文件;不合法直接报错
|
||||
|
||||
version 为全部文件内容的摘要,定义有任何改动都会得到新版本
|
||||
@@ -61,52 +59,3 @@ def load_material_definitions(directory: str | Path = MATERIALS_DIR) -> Componen
|
||||
"field_groups": field_groups,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
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 "已查询组件目录,未找到匹配的组件",
|
||||
)
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
from pydantic import JsonValue
|
||||
|
||||
from app.schemas.component_resource import ComponentCatalog, ComponentDefinition
|
||||
from app.schemas.component_resource import (
|
||||
ComponentCatalog,
|
||||
ComponentDefinition,
|
||||
ComponentSummary,
|
||||
)
|
||||
from app.schemas.material_field import (
|
||||
MISSING,
|
||||
PANEL_CONTROLS,
|
||||
@@ -82,6 +86,24 @@ def material_payload(component: ComponentDefinition) -> dict:
|
||||
return component.model_dump(mode="json", by_alias=True, exclude={"field_groups"})
|
||||
|
||||
|
||||
def list_components(catalog: ComponentCatalog) -> dict:
|
||||
"""组件目录摘要:选类型用,默认配置和字段定义另行查询"""
|
||||
return {
|
||||
"catalog_version": catalog.version,
|
||||
"components": [
|
||||
ComponentSummary(
|
||||
key=item.key,
|
||||
type=item.type,
|
||||
name=item.name,
|
||||
description=item.description,
|
||||
default_width=item.schema_.layout.width,
|
||||
default_height=item.schema_.layout.height,
|
||||
).model_dump(mode="json")
|
||||
for item in catalog.components
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def get_materials(catalog: ComponentCatalog, component_types: list[str]) -> dict:
|
||||
"""指定类型的物料默认配置,同一类型的多个预设全部返回"""
|
||||
known = {item.type for item in catalog.components}
|
||||
|
||||
Reference in New Issue
Block a user