baodan/api/insurance/db/migrate_032.py
wsb1224 9939188a4b 主要修复:
海报 PDF 解析从 Gunicorn 后台线程迁移到 Celery Worker,消除 gevent/asyncio.run 冲突和任务卡死。
海报改为紧凑解析,只选择客户资料、保费和核心利益页;排除提领方案、悲观/乐观情景页。
LLM 调用由原来的约 27 次降为 1 次。
补充年缴保费、首年实缴、缴费期、总保费及第 1/5/10/15/20/25/30 年退保价值。
增加真实解析进度、错误信息、任务 ID、心跳和完成时间。
相同用户重复上传同一份计划书时复用现有任务或结果。
前端取消 180 秒本地假超时,改为串行轮询后端真实状态;网络波动不再误判解析失败。
增加服务重启后的过期任务恢复机制。
修复解析结果 JSON 序列化遗漏问题。
关键文件:
[extraction.py](D:/work/code/python/coding/baodanagent/api/insurance/ppt/extraction.py)
[tasks.py](D:/work/code/python/coding/baodanagent/api/insurance/poster/tasks.py)
[celery_tasks.py](D:/work/code/python/coding/baodanagent/api/insurance/generation/celery_tasks.py)
[service.py](D:/work/code/python/coding/baodanagent/api/insurance/poster/service.py)
[migrate_032.py](D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_032.py)
[PosterSourcePanel.vue](D:/work/code/python/coding/baodanagent/frontend/src/components/poster/workspace/PosterSourcePanel.vue)
[回归测试](D:/work/code/python/coding/baodanagent/tests/ppt_poster_optimization_test.py)
2026-08-01 03:15:43 +08:00

63 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""迁移 032海报计划书解析任务进度与文件去重字段。"""
import logging
from sqlalchemy import inspect, text
logger = logging.getLogger(__name__)
def migrate():
from insurance.db.compat import db
table_name = "poster_case_uploads"
columns = {
item["name"]
for item in inspect(db.engine).get_columns(table_name)
}
additions = {
"parse_progress": "INTEGER NOT NULL DEFAULT 0",
"parse_message": "VARCHAR(500) NOT NULL DEFAULT ''",
"parse_error": "TEXT",
"parse_task_id": "VARCHAR(200)",
"parse_started_at": "TIMESTAMP",
"parse_heartbeat_at": "TIMESTAMP",
"parse_finished_at": "TIMESTAMP",
"file_hash": "VARCHAR(64)",
}
for name, column_type in additions.items():
if name not in columns:
db.session.execute(text(
f"ALTER TABLE {table_name} ADD COLUMN {name} {column_type}"
))
indexes = {
item["name"]
for item in inspect(db.engine).get_indexes(table_name)
}
if "idx_poster_case_owner_hash" not in indexes:
db.session.execute(text(
"CREATE INDEX idx_poster_case_owner_hash "
"ON poster_case_uploads (user_id, file_hash)"
))
db.session.execute(text(
"UPDATE poster_case_uploads SET parse_status = 'failed', parse_progress = 100, "
"parse_message = '解析任务已中断', "
"parse_error = '服务升级后请重新解析', parse_finished_at = CURRENT_TIMESTAMP "
"WHERE parse_status IN ('queued', 'parsing')"
))
db.session.execute(text(
"UPDATE poster_case_uploads SET parse_progress = 100 "
"WHERE parse_status IN ('parsed', 'partial', 'failed')"
))
db.session.execute(text(
"UPDATE poster_case_uploads SET parse_message = CASE "
"WHEN parse_status = 'parsed' THEN '解析完成' "
"WHEN parse_status = 'partial' THEN '解析完成,部分字段需核对' "
"WHEN parse_status = 'failed' THEN '解析失败' "
"ELSE COALESCE(parse_message, '') END "
"WHERE parse_message IS NULL OR parse_message = ''"
))
db.session.commit()
logger.info("[migrate_032] 海报计划书解析任务字段迁移完成")