A8多套打包+M4归档+R5多图:存量功能备份

A8 多套交付包(packaging_task.py):
- 修复交付包只打第1条混乱note的bug,按ImageCandidate.strategy分A/B/C组
- 每组生独立note_0N夹(6图+文案.txt),同seq留最新去重,老数据兼容
- task74端到端验:3套各6图,独立agent7项交叉验证全过

M4 归档(tasks.py/exports.py/前端):
- list_tasks加date_from/date_to/product_id筛选+product_name批量填(防N+1)
- 新增exports.py:产品JSON导出+标杆CSV导出(UTF-8 BOM)
- 前端HistoryFilters日期/产品筛选+产品列+打回原因红banner
- response.py加raise_param_error;独立agent验A1/A2/A9通过

R5 产品多图(product_images.py/020迁移/前端):
- product_images表+5端点(上传/列/改场景/设主图/删图)
- 生图按ROLE_SCENE_PREFERENCE选对应场景图,回落primary
- 前端ProductImageManager多图画廊

R6 账号config拆页(settings/):
- 配置页按角色拆/settings(运营+组长+admin)+/config(仅admin)
- Key只显末4位不显余额(守红线)

核销表对齐真实代码状态:D1改稿框/M7裂变/E12评图分纠偏为已完成(曾漏回写)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
yangqianqian
2026-06-18 17:32:49 +08:00
parent 285791c12f
commit 4bed7425a8
41 changed files with 1211 additions and 236 deletions

View File

@@ -58,6 +58,7 @@ def build_clients_and_clear_key(plain_key: str):
def build_product_dict(product) -> dict:
"""把 ORM product 转成 AI 引擎所需的 dict不含任何 key"""
return {
"id": product.id,
"name": product.name,
"category": product.category or "通用好物",
"selling_points": json.loads(product.selling_points or "[]"),
@@ -66,10 +67,52 @@ def build_product_dict(product) -> dict:
"custom_prompt": product.custom_prompt or "",
"brand_keyword": product.brand_keyword or "", # S3: 品牌词透传进生成prompt(每条植入)
"target_audience": product.target_audience or "", # 012: 人群透传进storyboard/文案prompt
"image_path": product.image_path or "", # 产品参考图路径(前端上传后填入
"image_path": product.image_path or "", # 产品参考图路径(主图,向后兼容
# R5多图每张产品图 {path, scene}生图按分镜role选对应场景图
"images": [
{"path": im.path, "scene": im.scene}
for im in (getattr(product, "images", None) or [])
],
# 第2环标杆配方默认空走 AI 主链时由 load_benchmark_features 覆盖填充
"benchmark_refs": [],
}
def load_benchmark_features(db, task, workspace_id: int) -> list[dict]:
"""
第2环→第5环接线读 task.benchmark_ids → 查 analyze_status=done 的标杆 features_json。
返回 8维配方 dict 列表(供 build_prompt 借方法层结构,禁抄竞品品牌/功效原话)。
未选/未分析完/解析失败都安全返空,绝不阻断生成。
"""
from app.models.product import BenchmarkNote
raw_ids = getattr(task, "benchmark_ids", None)
if not raw_ids:
return []
try:
ids = [int(i) for i in json.loads(raw_ids)]
except Exception:
return []
if not ids:
return []
rows = db.query(BenchmarkNote).filter(
BenchmarkNote.id.in_(ids),
BenchmarkNote.workspace_id == workspace_id,
BenchmarkNote.analyze_status == "done",
).all()
feats: list[dict] = []
for b in rows:
if not b.features_json:
continue
try:
feats.append(json.loads(b.features_json))
except Exception:
logger.warning("标杆 features_json 解析失败 id=%s", b.id)
return feats
def load_flywheel_context(db, workspace_id: int, product_id: int, product_dict: dict) -> tuple[str, dict]:
"""
查最近50条飞轮事件聚合偏好上下文。