feat: 规则冲突检测增强 — 后端接入 DB 规则 + 前端集成检查按钮
后端 validate_rules 端点改为 async,合并 DB active 平台规则与硬编码兜底规则, 新增 selling_points 字段支持和时长冲突检测。前端品牌方/代理商 Brief 页面 添加"检查规则冲突"按钮,支持选择平台后展示冲突详情弹窗。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
c17c64cd11
commit
2f24dcfd34
+53
-16
@@ -455,30 +455,67 @@ async def get_platform_rules(platform: str) -> PlatformRuleResponse:
|
||||
# ==================== 规则冲突检测 ====================
|
||||
|
||||
@router.post("/validate", response_model=RuleValidateResponse)
|
||||
async def validate_rules(request: RuleValidateRequest) -> RuleValidateResponse:
|
||||
"""检测 Brief 与平台规则冲突"""
|
||||
async def validate_rules(
|
||||
request: RuleValidateRequest,
|
||||
x_tenant_id: str = Header(..., alias="X-Tenant-ID"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> RuleValidateResponse:
|
||||
"""检测 Brief 与平台规则冲突(合并 DB 规则 + 硬编码兜底)"""
|
||||
conflicts = []
|
||||
|
||||
platform_rule = _platform_rules.get(request.platform)
|
||||
if not platform_rule:
|
||||
return RuleValidateResponse(conflicts=[])
|
||||
# 1. 收集违禁词:DB active 规则优先,硬编码兜底
|
||||
db_rules = await get_active_platform_rules(
|
||||
x_tenant_id, request.brand_id, request.platform, db
|
||||
)
|
||||
forbidden_words: set[str] = set()
|
||||
min_seconds: Optional[int] = None
|
||||
max_seconds: Optional[int] = None
|
||||
|
||||
# 检查 required_phrases 是否包含违禁词
|
||||
required_phrases = request.brief_rules.get("required_phrases", [])
|
||||
platform_forbidden = []
|
||||
for rule in platform_rule.get("rules", []):
|
||||
if db_rules:
|
||||
forbidden_words.update(db_rules.get("forbidden_words", []))
|
||||
duration = db_rules.get("duration") or {}
|
||||
min_seconds = duration.get("min_seconds")
|
||||
max_seconds = duration.get("max_seconds")
|
||||
|
||||
# 硬编码兜底
|
||||
hardcoded = _platform_rules.get(request.platform, {})
|
||||
for rule in hardcoded.get("rules", []):
|
||||
if rule.get("type") == "forbidden_word":
|
||||
platform_forbidden.extend(rule.get("words", []))
|
||||
forbidden_words.update(rule.get("words", []))
|
||||
elif rule.get("type") == "duration" and min_seconds is None:
|
||||
if rule.get("min_seconds") is not None:
|
||||
min_seconds = rule["min_seconds"]
|
||||
if rule.get("max_seconds") is not None and max_seconds is None:
|
||||
max_seconds = rule["max_seconds"]
|
||||
|
||||
for phrase in required_phrases:
|
||||
for word in platform_forbidden:
|
||||
if word in phrase:
|
||||
# 2. 检查卖点/必选短语与违禁词冲突
|
||||
phrases = list(request.brief_rules.get("required_phrases", []))
|
||||
phrases += list(request.brief_rules.get("selling_points", []))
|
||||
for phrase in phrases:
|
||||
for word in forbidden_words:
|
||||
if word in str(phrase):
|
||||
conflicts.append(RuleConflict(
|
||||
brief_rule=f"要求使用:{phrase}",
|
||||
platform_rule=f"平台禁止:{word}",
|
||||
suggestion=f"Brief 要求的 '{phrase}' 包含平台违禁词 '{word}',建议修改",
|
||||
brief_rule=f"卖点包含:{phrase}",
|
||||
platform_rule=f"{request.platform} 禁止使用:{word}",
|
||||
suggestion=f"卖点 '{phrase}' 包含违禁词 '{word}',建议修改表述",
|
||||
))
|
||||
|
||||
# 3. 检查时长冲突
|
||||
brief_min = request.brief_rules.get("min_duration")
|
||||
brief_max = request.brief_rules.get("max_duration")
|
||||
if min_seconds and brief_max and brief_max < min_seconds:
|
||||
conflicts.append(RuleConflict(
|
||||
brief_rule=f"Brief 最长时长:{brief_max}秒",
|
||||
platform_rule=f"{request.platform} 最短要求:{min_seconds}秒",
|
||||
suggestion=f"Brief 最长 {brief_max}s 低于平台最短要求 {min_seconds}s,视频可能不达标",
|
||||
))
|
||||
if max_seconds and brief_min and brief_min > max_seconds:
|
||||
conflicts.append(RuleConflict(
|
||||
brief_rule=f"Brief 最短时长:{brief_min}秒",
|
||||
platform_rule=f"{request.platform} 最长限制:{max_seconds}秒",
|
||||
suggestion=f"Brief 最短 {brief_min}s 超过平台最长限制 {max_seconds}s,建议调整",
|
||||
))
|
||||
|
||||
return RuleValidateResponse(conflicts=conflicts)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user