功能 文件 说明 幻灯片显隐 routes.py, PptResult.vue, ppt-api.ts 每页可点击隐藏/恢复,隐藏页在缩略图中半透明显示,页码标注隐藏数量 DeckContract 快照 renderer.py, celery_tasks.py, ppt_session.py 生成时保存完整 deck JSON 到文件系统,供版本化回溯 版本化生成 celery_tasks.py, task_service.py, routes.py POST /preview/:id/regenerate → 递增版本号 → 用 deck 重新渲染 → 追加到版本历史,不覆盖旧版 版本历史 UI PptResult.vue 右栏显示版本列表(版本号/页数/时间),当前版本高亮标记 数据库迁移 migrate_025.py 新增 deck_contract_path、versions_json 字段 阶段 4:UI 重构 功能 文件 说明 保险绿主题 PptPage.vue, PptGenerate.vue, PptResult.vue, PptSlideCanvas.vue 主色从 #2563eb 蓝改为 #3B7A57 保险绿,背景暖灰 #f0f7f3 生成决策展示 PptGenerate.vue 新增"系统决策"区域,展示检测场景、选用模板、计划书数量、险种类型、保司 骨架屏加载 PptResult.vue preview_status=none/generating 时显示骨架屏 + 加载动画,不再显示静态 fallback 新增后端接口(本轮) 方法 路径 功能 POST /ppt/preview/:id/regenerate 基于编辑内容生成新版本 PUT /ppt/preview/:id/slide/:index 增加 hidden 字段支持 新增 Celery 任务 任务名 说明 insurance.regenerate_ppt 读取 DeckContract → 应用编辑 → 重新渲染 → 保存新版本
81 lines
5.0 KiB
Python
81 lines
5.0 KiB
Python
"""PPT 生成会话模型。"""
|
||
from sqlalchemy import Column, String, Text, Integer, TIMESTAMP, func
|
||
from insurance.db.compat import db
|
||
|
||
|
||
class PptSession(db.Model):
|
||
"""PPT 生成会话表。"""
|
||
__tablename__ = "insurance_ppt_sessions"
|
||
|
||
id = Column(String(36), primary_key=True, comment="UUID")
|
||
user_id = Column(String(64), nullable=False, comment="用户 ID")
|
||
status = Column(String(20), default="created", nullable=False,
|
||
comment="状态: created/parsing/parsed/generating/done/error")
|
||
files_json = Column(Text, nullable=True, comment="上传文件列表 JSON")
|
||
extractions_json = Column(Text, nullable=True, comment="提取结果 JSON")
|
||
parse_progress = Column(Integer, default=0, nullable=False, comment="解析进度 0-100")
|
||
parse_message = Column(Text, nullable=True, comment="解析进度说明")
|
||
parse_error = Column(Text, nullable=True, comment="解析任务错误")
|
||
parse_started_at = Column(TIMESTAMP, nullable=True, comment="解析开始时间")
|
||
parse_finished_at = Column(TIMESTAMP, nullable=True, comment="解析完成时间")
|
||
chat_history_json = Column(Text, nullable=True, comment="对话历史 JSON")
|
||
ppt_path = Column(String(500), nullable=True, comment="生成的 PPT 路径")
|
||
markdown_path = Column(String(500), nullable=True, comment="Markdown 路径")
|
||
preview_paths_json = Column(Text, nullable=True, comment="预览图路径 JSON")
|
||
preview_pdf_path = Column(String(500), nullable=True, comment="预览 PDF 路径")
|
||
slide_count = Column(Integer, nullable=True, comment="幻灯片数量")
|
||
# 工作区字段(migrate_022)
|
||
title = Column(String(200), default="", comment="用户可识别名称")
|
||
workflow_step = Column(String(20), default="upload", comment="当前业务步骤")
|
||
draft_options_json = Column(Text, nullable=True, comment="模板、公司、脱敏等草稿设置")
|
||
draft_revision = Column(Integer, default=1, comment="当前草稿版本")
|
||
generated_revision = Column(Integer, default=0, comment="最新成品版本")
|
||
latest_task_id = Column(String(36), nullable=True, comment="最近一次任务 ID")
|
||
latest_output_path = Column(String(500), nullable=True, comment="最新成品路径")
|
||
archived_at = Column(TIMESTAMP, nullable=True, comment="归档时间")
|
||
# 预览与质量检查(migrate_025)
|
||
slides_json_path = Column(String(500), nullable=True, comment="幻灯片结构 JSON 路径")
|
||
quality_report_json = Column(Text, nullable=True, comment="质量检查报告 JSON")
|
||
preview_status = Column(String(20), default="none", nullable=False,
|
||
comment="预览状态: none/generating/ready/failed")
|
||
deck_contract_path = Column(String(500), nullable=True, comment="DeckContract 快照路径")
|
||
versions_json = Column(Text, nullable=True, comment="版本历史 JSON 数组")
|
||
created_at = Column(TIMESTAMP, server_default=func.now())
|
||
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
|
||
|
||
def to_dict(self):
|
||
import json
|
||
return {
|
||
"id": self.id,
|
||
"user_id": self.user_id,
|
||
"status": self.status,
|
||
"files": json.loads(self.files_json) if self.files_json else [],
|
||
"extractions": json.loads(self.extractions_json) if self.extractions_json else [],
|
||
"parse_progress": self.parse_progress or 0,
|
||
"parse_message": self.parse_message,
|
||
"parse_error": self.parse_error,
|
||
"parse_started_at": str(self.parse_started_at) if self.parse_started_at else None,
|
||
"parse_finished_at": str(self.parse_finished_at) if self.parse_finished_at else None,
|
||
"chat_history": json.loads(self.chat_history_json) if self.chat_history_json else [],
|
||
"ppt_path": self.ppt_path,
|
||
"markdown_path": self.markdown_path,
|
||
"preview_paths": json.loads(self.preview_paths_json) if self.preview_paths_json else [],
|
||
"preview_pdf_path": self.preview_pdf_path,
|
||
"slide_count": self.slide_count,
|
||
"title": self.title or "",
|
||
"workflow_step": self.workflow_step or "upload",
|
||
"draft_options": json.loads(self.draft_options_json) if self.draft_options_json else None,
|
||
"draft_revision": self.draft_revision or 1,
|
||
"generated_revision": self.generated_revision or 0,
|
||
"latest_task_id": self.latest_task_id,
|
||
"latest_output_path": self.latest_output_path,
|
||
"archived_at": str(self.archived_at) if self.archived_at else None,
|
||
"slides_json_path": self.slides_json_path,
|
||
"quality_report": json.loads(self.quality_report_json) if self.quality_report_json else None,
|
||
"preview_status": self.preview_status or "none",
|
||
"deck_contract_path": self.deck_contract_path,
|
||
"versions": json.loads(self.versions_json) if self.versions_json else [],
|
||
"created_at": str(self.created_at) if self.created_at else None,
|
||
"updated_at": str(self.updated_at) if self.updated_at else None,
|
||
}
|