迁移系统加固 — 加 advisory lock 防并发,失败回滚并中止启动(原来是 catch-and-continue) 安全漏洞 — Settings/History API 权限收紧,API key 返回掩码值,海报 case 所有权校验 依赖缺失 — requirements.txt 补齐 python-pptx/openai/Pillow,Dockerfile 改为统一安装 海报鉴权下载 — 前端全部改用 authenticated blob,不再 window.open 无 token URL LLM 配置分离 — 海报文案读取 poster_llm_*(不再复用 ppt_llm_*),支持 config namespace 图片生成器 — 兼容 b64_json 和 URL 两种响应格式,追踪 generation_mode/provider/model 种子数据 — 新环境自动获得 2 个海报模板 + 2 个文案模板
49 lines
2.5 KiB
Python
49 lines
2.5 KiB
Python
"""海报生成记录模型。"""
|
||
from sqlalchemy import Column, String, Text, BigInteger, TIMESTAMP, func
|
||
from insurance.db.compat import db
|
||
|
||
|
||
class PosterRecord(db.Model):
|
||
"""海报生成记录表。"""
|
||
__tablename__ = "poster_records"
|
||
|
||
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||
user_id = Column(String(50), nullable=False, comment="用户 ID")
|
||
product_id = Column(String(50), nullable=True, comment="产品 ID")
|
||
case_upload_id = Column(BigInteger, nullable=True, comment="关联计划书上传 ID")
|
||
template_id = Column(BigInteger, nullable=True, comment="海报模板 ID")
|
||
copy_mode = Column(String(20), nullable=True, comment="文案模式: template/ai")
|
||
copy_content = Column(Text, nullable=True, comment="最终文案 JSON")
|
||
ai_raw_content = Column(Text, nullable=True, comment="AI 原始文案 JSON(合规留痕)")
|
||
export_url = Column(String(500), nullable=True, comment="导出文件地址")
|
||
export_format = Column(String(10), nullable=True, comment="导出格式: png/jpg")
|
||
export_size = Column(String(20), nullable=True, comment="导出尺寸")
|
||
reference_image_used = Column(String(500), nullable=True, comment="使用的参考图(合规留痕)")
|
||
prompt_used = Column(Text, nullable=True, comment="完整 prompt(合规留痕)")
|
||
generation_mode = Column(String(20), nullable=True, comment="生成方式: ai/fallback")
|
||
image_provider = Column(String(50), nullable=True, comment="图片供应商")
|
||
image_model = Column(String(100), nullable=True, comment="图片模型名称")
|
||
created_at = Column(TIMESTAMP, server_default=func.now())
|
||
|
||
def to_dict(self):
|
||
import json
|
||
return {
|
||
"id": self.id,
|
||
"userId": self.user_id,
|
||
"productId": self.product_id,
|
||
"caseUploadId": self.case_upload_id,
|
||
"templateId": self.template_id,
|
||
"copyMode": self.copy_mode,
|
||
"copyContent": json.loads(self.copy_content) if self.copy_content else None,
|
||
"aiRawContent": json.loads(self.ai_raw_content) if self.ai_raw_content else None,
|
||
"exportUrl": self.export_url,
|
||
"exportFormat": self.export_format,
|
||
"exportSize": self.export_size,
|
||
"referenceImageUsed": self.reference_image_used,
|
||
"promptUsed": self.prompt_used,
|
||
"generationMode": self.generation_mode,
|
||
"imageProvider": self.image_provider,
|
||
"imageModel": self.image_model,
|
||
"createdAt": self.created_at.isoformat() if self.created_at else None,
|
||
}
|