diff --git a/python-api/app/crud/broll_category.py b/python-api/app/crud/broll_category.py index 8fa1ad3..f1155e1 100644 --- a/python-api/app/crud/broll_category.py +++ b/python-api/app/crud/broll_category.py @@ -57,6 +57,19 @@ class BrollCategoryCRUD(CRUDBase[BrollCategory]): ) return list(result.scalars().all()) + async def get_by_name_like_and_level( + self, db: AsyncSession, *, name: str, level: int + ) -> BrollCategory | None: + """根据名称模糊匹配和层级获取启用的分类(LIKE %name%)""" + result = await db.execute( + select(BrollCategory).where( + BrollCategory.name.like(f"%{name}%"), + BrollCategory.level == level, + BrollCategory.status == "active", + ) + ) + return result.scalar_one_or_none() + # 导出实例 broll_category = BrollCategoryCRUD() diff --git a/python-api/app/services/material_service.py b/python-api/app/services/material_service.py index d6fe5a4..7aac534 100644 --- a/python-api/app/services/material_service.py +++ b/python-api/app/services/material_service.py @@ -69,6 +69,11 @@ async def _try_fallback_to_parent( - 若 scene 含 '-',取后半部分作为 parent_name(如 '电路施工-电路施工' -> '电路施工') - 若不含 '-',直接以整个 scene 作为 parent_name + 匹配策略(逐级降级): + 1. 精确匹配 level=2 分类 name + 2. 模糊匹配(LIKE %parent_name%),兼容 "电路施工" → "电路施工镜" + 3. 去掉常见后缀(镜、阶段等)再精确匹配 + 返回: 随机选中的一个 level=3 子分类,或 None """ @@ -77,9 +82,28 @@ async def _try_fallback_to_parent( else: parent_name = normalized_scene + # 1. 精确匹配 parent = await broll_category.get_by_name_and_level( db, name=parent_name, level=2 ) + + # 2. 模糊匹配(兼容 "电路施工" → "电路施工镜") + if parent is None: + parent = await broll_category.get_by_name_like_and_level( + db, name=parent_name, level=2 + ) + + # 3. 去掉常见后缀再试 + if parent is None: + for suffix in ("镜", "阶段"): + if not parent_name.endswith(suffix): + candidate = parent_name + suffix + parent = await broll_category.get_by_name_and_level( + db, name=candidate, level=2 + ) + if parent: + break + if parent is None: return None