baodan/api/insurance/poster/tasks.py

422 lines
16 KiB
Python
Raw Normal View History

"""海报后台任务管理。"""
import json
import logging
import os
from datetime import datetime
from insurance.db.compat import db
logger = logging.getLogger(__name__)
# 超过此时间仍为 queued/generating 的任务视为过期(秒)
STALE_TASK_TIMEOUT = 600 # 10 分钟
def recover_stale_tasks():
"""启动时恢复过期任务:将长时间 queued/generating 的任务标记为 failed。
应在应用启动时调用
"""
from insurance.models.poster_record import PosterRecord
from insurance.models.poster_case_upload import PosterCaseUpload
from sqlalchemy import inspect
cutoff = datetime.now().timestamp() - STALE_TASK_TIMEOUT
# 恢复过期的海报生成任务
stale_records = PosterRecord.query.filter(
PosterRecord.task_status.in_(["queued", "generating"]),
PosterRecord.created_at < datetime.fromtimestamp(cutoff),
).all()
for record in stale_records:
record.task_status = "failed"
record.task_error = "任务因服务重启而中断,请重新生成"
record.finished_at = datetime.now()
logger.warning(f"恢复过期海报任务: record_id={record.id}")
# 恢复过期的计划书解析任务
case_columns = {
item["name"] for item in inspect(db.engine).get_columns("poster_case_uploads")
}
stale_cases = []
if {"parse_progress", "parse_message", "parse_error"}.issubset(case_columns):
stale_cases = PosterCaseUpload.query.filter(
PosterCaseUpload.parse_status.in_(["queued", "parsing"]),
PosterCaseUpload.created_at < datetime.fromtimestamp(cutoff),
).all()
for case in stale_cases:
case.parse_status = "failed"
case.parse_progress = 100
case.parse_message = "解析任务已中断"
case.parse_error = "任务因服务重启或 Worker 中断,请重新解析"
case.parse_finished_at = datetime.now()
logger.warning(f"恢复过期解析任务: case_id={case.id}")
if stale_records or stale_cases:
db.session.commit()
logger.info(f"已恢复 {len(stale_records)} 个海报任务, {len(stale_cases)} 个解析任务")
# ─── 计划书解析任务 ───────────────────────────────────────
def start_case_parse_task(case_upload_id: int) -> bool:
"""将计划书解析提交到 Celery Worker。"""
try:
from insurance.generation.celery_tasks import parse_poster_case_task
from insurance.models.poster_case_upload import PosterCaseUpload
result = parse_poster_case_task.apply_async(
args=[case_upload_id],
queue="insurance",
)
record = PosterCaseUpload.query.get(case_upload_id)
if record:
record.parse_task_id = result.id
db.session.commit()
return True
except Exception as exc:
logger.error("海报计划书解析任务提交失败 [%s]: %s", case_upload_id, exc, exc_info=True)
return False
def _execute_case_parse(case_upload_id: int):
from insurance.models.poster_case_upload import PosterCaseUpload
record = PosterCaseUpload.query.get(case_upload_id)
if not record:
return
filepath = record.source_file_url
if not filepath or not os.path.exists(filepath):
raise FileNotFoundError("计划书源文件不存在")
from insurance.ppt.extraction import ExtractionOrchestrator
orchestrator = ExtractionOrchestrator(use_cache=False)
import asyncio
2026-07-31 09:00:39 +08:00
parsed = None
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
product_context = {}
if record.product_snapshot_json:
try:
product_context = json.loads(record.product_snapshot_json) or {}
except (json.JSONDecodeError, TypeError):
logger.warning("计划书产品快照无效: case_id=%s", case_upload_id)
plan_type = str(product_context.get("planType") or "savings").lower()
product_data = product_context.get("productData") or {}
product_name = (
product_context.get("productName")
or product_data.get("displayName")
or ""
)
product_aliases = product_data.get("aliases") or []
company_id = (
product_context.get("companyId")
or product_data.get("companyId")
or ""
)
def report_progress(progress: int, message: str):
_update_case_progress(case_upload_id, progress, message)
# 优先使用海报紧凑解析,只提取基础字段和代表性利益年度。
2026-07-31 09:00:39 +08:00
try:
compact_data = asyncio.run(orchestrator.extract_for_poster(
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
filepath,
plan_type=plan_type,
progress_callback=report_progress,
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
))
compact_data = compact_data or {}
if product_name and not compact_data.get("product_name"):
compact_data["product_name"] = product_name
parsed = _map_extract_plan_fields(
compact_data, plan_type, "poster_compact", product_context=product_context,
)
if (parsed.get("meta") or {}).get("status") == "failed":
parsed = None
else:
logger.info("使用海报紧凑解析成功: case_id=%s, type=%s", case_upload_id, plan_type)
2026-07-31 09:00:39 +08:00
except Exception as exc:
logger.warning("海报紧凑解析失败,降级到完整解析: %s", exc)
2026-07-31 09:00:39 +08:00
# 降级:完整解析仍跳过海报不使用的提领方案和销售分析。
2026-07-31 09:00:39 +08:00
if not parsed:
try:
result = asyncio.run(orchestrator.extract_plan(
filepath,
plan_type=plan_type,
progress_callback=report_progress,
company_id=company_id,
product_id=record.product_id or "",
product_name_hint=product_name,
product_aliases=product_aliases,
include_withdrawal=False,
))
if result.status != "error" and result.data:
parsed = _map_extract_plan_fields(
result.data, result.plan_type, result.status, product_context=product_context,
)
logger.info("使用完整解析降级成功: case_id=%s, type=%s", case_upload_id, result.plan_type)
2026-07-31 09:00:39 +08:00
except Exception as exc:
logger.error("完整解析降级也失败: %s", exc)
if not parsed:
raise ValueError("计划书中未识别到可用于海报的字段")
2026-07-30 16:07:57 +08:00
2026-07-31 09:00:39 +08:00
record = PosterCaseUpload.query.get(case_upload_id)
if not record:
2026-07-30 16:07:57 +08:00
return
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
parse_status = (parsed.get("meta") or {}).get("status", "failed")
2026-07-31 09:00:39 +08:00
record.parsed_data = json.dumps(parsed, ensure_ascii=False)
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
record.parse_status = parse_status
record.parse_progress = 100
record.parse_message = "解析完成" if parse_status == "parsed" else "解析完成,部分字段需核对"
record.parse_error = None
record.parse_heartbeat_at = datetime.now()
record.parse_finished_at = datetime.now()
2026-07-31 09:00:39 +08:00
db.session.commit()
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
def _map_extract_plan_fields(
data: dict,
plan_type: str,
status: str,
product_context: dict | None = None,
) -> dict:
2026-07-31 09:00:39 +08:00
"""将 extract_plan 的完整数据映射为海报前端所需字段结构。
兼容多种可能的字段命名LLM 输出不固定
"""
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
insured = data.get("insured") or {}
policy = data.get("policy") or {}
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
product_context = product_context or {}
product_data = product_context.get("productData") or {}
company_data = product_context.get("companyData") or {}
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
def first_value(*values):
for value in values:
if value is not None and value != "":
return value
return None
raw_gender = first_value(insured.get("gender"), data.get("gender"))
gender_map = {
"male": "", "m": "", "": "",
"female": "", "f": "", "": "",
}
gender = gender_map.get(str(raw_gender).strip().lower(), raw_gender) if raw_gender else None
raw_currency = first_value(policy.get("currency"), data.get("currency"))
from insurance.ppt.normalizer import _normalize_currency
currency = _normalize_currency(raw_currency)
# 保额:优先读取正式提取结构中的 policy
2026-07-31 09:00:39 +08:00
sum_assured = (
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
policy.get("sum_insured")
or policy.get("basic_sum_insured")
or policy.get("sum_assured")
or data.get("sum_insured")
2026-07-31 09:00:39 +08:00
or data.get("basic_sum_insured")
or data.get("sum_assured")
or data.get("face_amount")
or data.get("coverage_amount")
)
# 缴费年期
premium_term = (
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
policy.get("premium_payment_period")
or policy.get("premium_term")
or data.get("premium_term")
2026-07-31 09:00:39 +08:00
or data.get("payment_period")
or data.get("paying_period")
or data.get("premium_payment_term")
)
# 年缴保费
annual_premium = (
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
policy.get("annual_premium")
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
or policy.get("basic_plan_annual_premium")
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
or policy.get("target_premium")
or data.get("annual_premium")
2026-07-31 09:00:39 +08:00
or data.get("premium_amount")
or data.get("yearly_premium")
)
# 保障期限
coverage_period = (
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
policy.get("coverage_period")
or data.get("coverage_period")
2026-07-31 09:00:39 +08:00
or data.get("policy_term")
or data.get("coverage_term")
)
2026-07-30 16:07:57 +08:00
2026-07-31 09:00:39 +08:00
# 利益演示表
benefit_table = (
data.get("benefit_illustration")
or data.get("benefit_table")
or data.get("cash_value_projection")
or []
)
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
smoking_status = first_value(
insured.get("smoking_status"), insured.get("smoker_status"),
insured.get("smoker"), insured.get("is_smoker"),
data.get("smoking_status"), data.get("is_smoker"),
)
if isinstance(smoking_status, bool):
smoking_status = "吸烟" if smoking_status else "非吸烟"
elif smoking_status is not None:
smoking_status = {
"yes": "吸烟", "y": "吸烟", "smoker": "吸烟", "吸烟": "吸烟", "吸煙": "吸烟",
"no": "非吸烟", "n": "非吸烟", "non-smoker": "非吸烟",
"不吸烟": "非吸烟", "不吸煙": "非吸烟", "非吸烟": "非吸烟",
}.get(str(smoking_status).strip().lower(), smoking_status)
explicit_total_premium = first_value(
policy.get("total_premium"), policy.get("total_basic_premium"),
data.get("total_premium"), data.get("total_basic_premium"),
)
total_premium = explicit_total_premium
if total_premium is None and isinstance(annual_premium, (int, float)) and isinstance(premium_term, (int, float)):
total_premium = annual_premium * premium_term
def benefit_value(year: int, *keys: str):
for row in benefit_table:
row_year = first_value(row.get("policy_year"), row.get("policyYear"), row.get("year"))
try:
if int(row_year) != year:
continue
except (TypeError, ValueError):
continue
return first_value(*(row.get(key) for key in keys))
return None
explicit_initial_death_benefit = first_value(
policy.get("initial_death_benefit"), data.get("initial_death_benefit"),
)
initial_death_benefit = first_value(
explicit_initial_death_benefit,
benefit_value(1, "death_benefit", "deathBenefit", "non_guaranteed_death_benefit"),
)
milestone_values = {
year: first_value(
data.get(f"surrender_value_{year}"),
benefit_value(year, "total_surrender_value", "totalSurrenderValue", "total_surrender"),
)
for year in (10, 20, 30)
}
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
result = {
"age": first_value(insured.get("age"), data.get("age")),
"gender": gender,
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
"smoking_status": smoking_status,
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
"currency": currency,
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
"company_name": first_value(
product_context.get("companyName"), company_data.get("displayName"), data.get("company_name"),
),
"product_name": first_value(
product_context.get("productName"), product_data.get("displayName"), data.get("product_name"),
),
2026-07-31 09:00:39 +08:00
"sum_assured": sum_assured,
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
"basic_sum_assured": first_value(policy.get("basic_sum_insured"), data.get("basic_sum_insured"), sum_assured),
2026-07-31 09:00:39 +08:00
"premium_term": premium_term,
"annual_premium": annual_premium,
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
"basic_plan_annual_premium": first_value(
policy.get("basic_plan_annual_premium"), data.get("basic_plan_annual_premium"), annual_premium,
),
"total_premium": total_premium,
"first_year_amount_due": first_value(
policy.get("first_year_amount_due"), data.get("first_year_amount_due"),
),
2026-07-31 09:00:39 +08:00
"coverage_period": coverage_period,
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
"initial_death_benefit": initial_death_benefit,
"surrender_value_10": milestone_values[10],
"surrender_value_20": milestone_values[20],
"surrender_value_30": milestone_values[30],
2026-07-30 16:07:57 +08:00
"key_benefits": data.get("key_benefits") or [],
2026-07-31 09:00:39 +08:00
"benefit_table": benefit_table,
"plan_type": plan_type,
"extraction_status": status,
2026-07-30 16:07:57 +08:00
}
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
business_fields = (
"age", "gender", "currency", "sum_assured",
"premium_term", "annual_premium", "coverage_period",
)
valid_count = sum(
1 for key in business_fields
if result.get(key) is not None and result.get(key) != ""
)
required_by_type = {
"savings": ("age", "currency", "annual_premium", "premium_term"),
"ci": ("age", "currency", "sum_assured"),
"iul": ("age", "currency", "sum_assured", "annual_premium"),
}
required = required_by_type.get(str(plan_type or "").lower(), ("age", "currency"))
missing = [
key for key in required
if result.get(key) is None or result.get(key) == ""
]
mapped_status = "failed" if valid_count == 0 else ("partial" if missing else "parsed")
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
raw_provenance = data.get("_provenance") or data.get("provenance") or {}
provenance = dict(raw_provenance) if isinstance(raw_provenance, dict) else {}
if total_premium is not None and explicit_total_premium is None:
provenance["total_premium"] = {
"source": "system_derived",
"formula": "annual_premium * premium_term",
}
if initial_death_benefit is not None and explicit_initial_death_benefit is None:
provenance["initial_death_benefit"] = {
"source": "system_derived",
"from": "benefit_table.year_1",
}
for year, value in milestone_values.items():
if value is not None and data.get(f"surrender_value_{year}") is None:
provenance[f"surrender_value_{year}"] = {
"source": "system_derived",
"from": f"benefit_table.year_{year}",
}
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
result["meta"] = {
"planType": plan_type,
"status": mapped_status,
"sourceStatus": status,
"missingFields": missing,
"validFieldCount": valid_count,
"method": (
(data.get("_meta") or {}).get("method")
or (data.get("extraction_meta") or {}).get("method")
or status
),
主要改动: PPT 表格现在按槽位解析,正确保留 —、空列和单空格表格,不再发生金额左移。[regex_extractor.py (line 470)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/regex_extractor.py:470) 补齐年龄、累计保费、非保证现金价值、非保证身故赔偿等别名。 IUL 使用专属 LLM 提取结构,并加强年度、年龄、账户价值完整性校验。[extraction.py (line 741)](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py:741) PPT 缓存升级到 v6,旧错误缓存会自动失效。 提领方案不再与普通退保价值混淆,相关提示语已统一。 海报摘要年度金额与收益图表改为同一数据源;缺少部分里程碑时会从原始真实年度补足,不会隐藏图表。[content_builder.py (line 51)](D:/work/code/python/coding/baodanagent/api/insurance/poster/content_builder.py:51) 系统计算、利益表派生、人工修改增加来源标记。 增加“重新解析”功能,旧海报计划书无需重新上传。[routes.py (line 266)](D:/work/code/python/coding/baodanagent/api/insurance/poster/routes.py:266) ECharts 导出增加双帧就绪检测和事件竞态保护,不再依赖不存在的 .once()。 PPT 手机端改为可编辑数据卡片,320px 操作栏自动纵向排列;补齐按钮语义、键盘焦点及 44px 触控区域。[PptDataReview.vue (line 195)](D:/work/code/python/coding/baodanagent/frontend/src/pages/components/ppt/PptDataReview.vue:195) 验证结果: 核心专项测试:145 passed 除既有聊天日志测试外的测试集:236 passed 前端生产构建:通过 Python 语法检查:通过 git diff --check:通过 Impeccable 前端检测:无发现 全量测试仅剩一个与本次无关的既有失败:test_chat_logs_query 缺少 Flask application context
2026-08-01 01:22:07 +08:00
"provenance": provenance,
"lowQualityPages": (
(data.get("_meta") or {}).get("low_quality_pages")
or (data.get("extraction_meta") or {}).get("lowQualityPages")
or []
),
已按计划书完成本轮核心 P0/P1 修复,覆盖用户反馈的三个主要问题。 主要结果: PPT: 已完成步骤可自由返回,刷新后保留当前步骤。 结果页改为固定三栏视口,缩略图和质量面板独立滚动。 修复画布宽度计算和宽高自适应缩放。 返回配置页时恢复上次模板。 Worker 禁止静默替换模板,不兼容时明确失败。 结果页显示实际应用的模板。 海报解析与合规: 修复 insured/policy 嵌套字段映射。 增加 partial/failed 解析质量判断和缺失字段提示。 传入险种、产品、保司和别名上下文。 修复性别、币种归一化和错误字段计数。 新增服务端字符级合规接口与生成前复检。 不合规文字可高亮、点击定位并选中对应文字。 海报编辑: AI 图片现在作为背景资产,不再替换整个海报。 单图、长图生成后仍可编辑标题、正文、CTA、数据和卖点。 背景生成失败不会清空当前编辑内容。 下载时合成背景、文字、数据、图表和免责声明。 增加可编辑文档快照、最终 PNG 保存和历史继续编辑。 新增数据库迁移:[migrate_028.py](/D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_028.py) 验证结果: 专项及相关后端测试:26 passed, 1 skipped Python 全模块编译检查:通过 前端生产构建:通过 git diff --check:通过 全量测试收集受本机缺少 python-pptx 依赖影响,报错为 ModuleNotFoundError: pptx,不是本次修改产生的测试失败。
2026-07-31 15:20:37 +08:00
}
return result
def _mark_case_failed(case_upload_id: int, error: str):
from insurance.models.poster_case_upload import PosterCaseUpload
record = PosterCaseUpload.query.get(case_upload_id)
if not record:
return
record.parse_status = "failed"
record.parse_progress = 100
record.parse_message = "解析失败"
record.parse_error = error[:1000]
record.parse_heartbeat_at = datetime.now()
record.parse_finished_at = datetime.now()
db.session.commit()
def _update_case_progress(case_upload_id: int, progress: int, message: str):
from insurance.models.poster_case_upload import PosterCaseUpload
record = PosterCaseUpload.query.get(case_upload_id)
if not record:
return
record.parse_progress = max(0, min(int(progress), 99))
record.parse_message = message[:500]
record.parse_heartbeat_at = datetime.now()
db.session.commit()