baseline: Clover 独立仓库首次基线提交
将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。 当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包), M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
104
backend/app/workers/packaging_task.py
Normal file
104
backend/app/workers/packaging_task.py
Normal file
@@ -0,0 +1,104 @@
|
||||
"""
|
||||
app/workers/packaging_task.py — 交付打包 Celery 任务
|
||||
build_delivery_package:查已选文案+图片 → package_exporter → 存路径
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from app.workers.celery_app import celery_app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _get_db():
|
||||
from app.core.database import SessionLocal
|
||||
return SessionLocal()
|
||||
|
||||
|
||||
@celery_app.task(
|
||||
bind=True,
|
||||
name="app.workers.tasks.build_delivery_package",
|
||||
max_retries=2,
|
||||
default_retry_delay=10,
|
||||
queue="packaging",
|
||||
)
|
||||
def build_delivery_package(self, package_id: int) -> dict:
|
||||
"""打包交付任务。查 delivery_packages → 收集笔记 → package_exporter"""
|
||||
logger.info("build_delivery_package start: package_id=%s", package_id)
|
||||
db = _get_db()
|
||||
try:
|
||||
from app.models.task import DeliveryPackage, TextCandidate, ImageCandidate
|
||||
from app.constants.enums import PackageStatus
|
||||
|
||||
pkg = db.query(DeliveryPackage).filter(DeliveryPackage.id == package_id).first()
|
||||
if not pkg:
|
||||
raise ValueError(f"package_id={package_id} not found")
|
||||
|
||||
workspace_id = pkg.workspace_id
|
||||
task_id = pkg.task_id
|
||||
|
||||
from app.core.config import get_settings
|
||||
settings = get_settings()
|
||||
upload_base = settings.UPLOAD_BASE_PATH.rstrip("/")
|
||||
|
||||
selected_text = db.query(TextCandidate).filter(
|
||||
TextCandidate.task_id == task_id, TextCandidate.is_selected == True,
|
||||
).first()
|
||||
# 整套全打(倩倩姐2026-06-08拍板):一条笔记的全部图按 seq 排序进包,
|
||||
# 不再只打 is_selected 的封面。北哥6张标准套 seq=1 是 hook 封面,天然排第一。
|
||||
selected_images = db.query(ImageCandidate).filter(
|
||||
ImageCandidate.task_id == task_id,
|
||||
).order_by(ImageCandidate.seq).all()
|
||||
|
||||
if not selected_text:
|
||||
raise ValueError("无已选文案,请先选择文案")
|
||||
|
||||
text_data = json.loads(selected_text.content or "{}")
|
||||
images_data = []
|
||||
for ic in selected_images:
|
||||
img_bytes = b""
|
||||
if ic.url:
|
||||
# url 形如 /uploads/ws/task/file.jpg,本身已含 uploads 前缀。
|
||||
# 工作目录是 /app,直接 lstrip("/") 当相对路径读,不能再拼 upload_base(会重复 uploads/uploads)。
|
||||
rel = ic.url.lstrip("/")
|
||||
abs_path = rel
|
||||
try:
|
||||
with open(abs_path, "rb") as f:
|
||||
img_bytes = f.read()
|
||||
except OSError as e:
|
||||
logger.warning("图片读取失败,跳过:%s %s", abs_path, e)
|
||||
images_data.append({
|
||||
"seq": ic.seq,
|
||||
"role": ic.role.value if hasattr(ic.role, "value") else str(ic.role),
|
||||
"data": img_bytes,
|
||||
})
|
||||
|
||||
notes = [{
|
||||
"title": text_data.get("title", ""),
|
||||
"content": text_data.get("content", ""),
|
||||
"tags": text_data.get("tags", []),
|
||||
"images": images_data,
|
||||
"banned_word_status": (selected_text.banned_word_status.value
|
||||
if hasattr(selected_text.banned_word_status, "value")
|
||||
else str(selected_text.banned_word_status)),
|
||||
}]
|
||||
|
||||
from app.services.ai_engine.package_exporter import build_delivery_package as do_build
|
||||
# 打包产物放专用目录 uploads/packages/,与图片目录 uploads/{ws}/{task}/ 分开
|
||||
packages_base = f"{upload_base}/packages"
|
||||
zip_path = do_build(workspace_id, task_id, notes, base_path=packages_base)
|
||||
|
||||
pkg.package_path = zip_path
|
||||
pkg.download_url = f"/api/v1/delivery-packages/{package_id}/download-file"
|
||||
pkg.status = PackageStatus.READY
|
||||
db.commit()
|
||||
|
||||
logger.info("delivery package ready: package_id=%s path=%s", package_id, zip_path)
|
||||
return {"package_id": package_id, "status": "ready", "path": zip_path}
|
||||
|
||||
except Exception as exc:
|
||||
logger.error("build_delivery_package failed: package_id=%s err=%s", package_id, exc)
|
||||
raise self.retry(exc=exc)
|
||||
finally:
|
||||
db.close()
|
||||
Reference in New Issue
Block a user