diff --git a/api/insurance/ppt/routes.py b/api/insurance/ppt/routes.py index e9c8be7..d8d48ab 100644 --- a/api/insurance/ppt/routes.py +++ b/api/insurance/ppt/routes.py @@ -1723,8 +1723,20 @@ def pdf_info(session_id, extraction_index): import pymupdf as fitz doc = fitz.open(pdf_path) page_count = len(doc) + page_sizes = [ + { + "pageNumber": index + 1, + "width": round(float(page.rect.width), 3), + "height": round(float(page.rect.height), 3), + } + for index, page in enumerate(doc) + ] doc.close() - return success({"pageCount": page_count, "pdfName": ext.get("pdfName", "")}) + return success({ + "pageCount": page_count, + "pageSizes": page_sizes, + "pdfName": ext.get("pdfName", ""), + }) except ImportError: return error(ErrorCode.INTERNAL_ERROR, "PDF 渲染库未安装") except Exception as e: diff --git a/backups/baodan_before_migrate_037_fix.dump b/backups/baodan_before_migrate_037_fix.dump new file mode 100644 index 0000000..55b46c0 Binary files /dev/null and b/backups/baodan_before_migrate_037_fix.dump differ diff --git a/docs/PPT与海报Phase4至6补充实施记录_20260802.md b/docs/PPT与海报Phase4至6补充实施记录_20260802.md new file mode 100644 index 0000000..1ca91ea --- /dev/null +++ b/docs/PPT与海报Phase4至6补充实施记录_20260802.md @@ -0,0 +1,84 @@ +# PPT 与海报 Phase 4~6 补充实施记录 + +> 日期:2026-08-02 +> 对应计划:`PPT与海报生成全链路详细修复计划书_20260802.md` +> 结论:代码层已具备版本治理、冻结重放、输出失败关闭、留存清理和灰度观测能力;生产验收尚不能用“代码已完成”替代。 + +## 1. 本轮已实现 + +### Phase 4:场景、策略与模板可执行化 + +- 新增 `migrate_038` 及场景、生成策略、PPT 模板三类不可变版本模型;生命周期统一为 `draft -> validated -> published -> retired`。 +- 发布门禁要求使用已批准 Golden snapshot 试跑;发布后定义不可原地修改,只能复制为新草稿。 +- 场景 resolver 使用文件数、险种、保司、产品、优先级和特异度确定唯一结果;无匹配和同优先级多匹配均失败关闭并返回 `matchTrace`。 +- 运行时严格按 Scenario `pageSpecs`、Template `pageSlots` 和 GenerationPolicy 合并;缺页、重复槽位、容量溢出、资产 SHA 变化和不兼容版本均阻断。 +- 管理后台已支持版本创建、JSON 编辑、校验、发布、试跑、复制、停用及失败原因查看。 + +### Phase 5:冻结、对账与任务可靠性 + +- `migrate_039` 为统一任务补齐 snapshot/scenario/policy/template/asset/renderer、提交版本、对账、视觉检查和结果状态字段。 +- PPT 与海报任务按实际使用的快照和配置完整冻结;重放只复用原任务冻结输入,不重新读取当前后台配置。 +- PPTX 输出按 XML 可见文本和字段清单核对金额、币种和缺失字段;失败不产生可下载成功成品。 +- 海报在生成背景前核对 `renderDocument`;最终浏览器合成时再次提交 DOM 导出清单,服务端校验: + - PNG 实际尺寸; + - DOM 与 PNG 尺寸一致性; + - 必需模块存在且非空; + - 文本裁切/溢出; + - 可见文本 SHA-256; + - 冻结文档与计划投影中的金额、币种。 +- 最终校验失败时前端不再绕过服务端直接下载。 +- 任务支持稳定幂等键、心跳、暂时性错误重试、冻结输入重放和 current/stale 结果标记。 +- 旧 PPT 线程解析器已标记 deprecated;海报紧凑解析仅在关闭 `DOCUMENT_IR_V1` 时作为短期回滚路径,默认不再承担新链路事实职责。 + +### Phase 6:质量、留存与灰度基础 + +- `migrate_040` 增加 Golden 审批字段和脱敏清理审计表。 +- 管理后台可审批/撤销 Golden snapshot,并汇总文档、页面、OCR、表格、跨页表、冲突、快照、覆盖、版本、任务、重试、心跳、延迟、对账及视觉检查指标。 +- 新增结构化质量告警:输出对账失败、视觉检查失败、运行任务无心跳、文档阻断和 Golden 数量不足。 +- 留存策略覆盖 Document、Snapshot、GenerationTask、Poster、PPT History 和审计日志;支持 dry-run、批次上限、脱敏审计、存储根目录保护和失败记录。 +- 新增只读孤儿文件检查,结果仅返回相对路径和 hash,不执行自动删除。 +- 灰度开关支持按 profile 白名单和稳定百分比分桶: + - `DOCUMENT_IR_V1` + - `PLAN_SNAPSHOT_V1` + - `SCENARIO_ENGINE_V2` + - `OUTPUT_RECONCILIATION_V1` + - `RETENTION_CLEANUP_V1` + +## 2. 数据库迁移顺序 + +部署时须按现有迁移注册顺序执行,新增部分为: + +1. `migrate_038`:场景、策略、模板版本; +2. `migrate_039`:任务冻结与输出审计; +3. `migrate_040`:Golden 与留存审计。 + +真实清理默认关闭。必须先执行 dry-run,核对候选及孤儿文件,再设置 `INSURANCE_RETENTION_CLEANUP_V1=true` 执行实删。 + +## 3. 建议上线顺序 + +1. 收集并脱敏不少于 30 份真实 PDF,完成双人标注,在“生成治理”页面批准为 Golden。 +2. 由业务 SME 固化各险种允许的派生公式、缺失值和结论策略,创建并校验 GenerationPolicyVersion。 +3. 上传带语义 shape name 的真实 PPTX 模板,逐页声明 `pageType`、slot 和容量,使用 Golden 试跑后发布。 +4. 保持 `SCENARIO_ENGINE_V2` 默认关闭,按保司/profile 依次灰度 10% -> 30% -> 100%。 +5. 每个阶段观察对账失败、视觉失败、无心跳和人工修改率;出现 P0 告警立即回退对应开关。 +6. 连续观察期通过后关闭旧写路径;旧数据只允许只读查看和冻结输入重放。 + +## 4. 尚需外部输入或生产环境完成的验收 + +以下事项不能由仓库代码自动代替,因此当前不标记正式里程碑完成: + +- 30 份获批脱敏 Golden 的双人标注及强制精确率门槛; +- 业务 SME 对公式、可比较性、缺失值和结论规则的签字; +- 真实生产模板的语义槽位标注、字体安装、图片差异基线和人工视觉验收; +- 生产队列、对象存储、数据库和告警通道上的 dry-run/实删演练; +- 10%/30%/100% 灰度及全量切换后的连续观察期。 + +因此,当前准确表述是:工程能力已覆盖 Phase 0~6 的主要代码任务并具备 M5 能力及 M6 基础,但 M2、M4、M6 的正式验收仍受真实样本、业务签字、模板资产和生产观察约束。 + +## 5. 本轮验证基线 + +- 后端计划相关专项回归:107 passed,1 skipped; +- 前端 TypeScript 检查:通过; +- 前端生产构建:通过; +- 治理页与海报页静态 UI 审查:无阻断项; +- 仓库全量 `tests/` 中另有 2 个与本轮无关的既有失败,详见交付说明,不能计入本轮回归失败。 diff --git a/docs/PPT与海报生成全链路详细修复计划书_20260802.md b/docs/PPT与海报生成全链路详细修复计划书_20260802.md index 3612d41..b8164f2 100644 --- a/docs/PPT与海报生成全链路详细修复计划书_20260802.md +++ b/docs/PPT与海报生成全链路详细修复计划书_20260802.md @@ -5,6 +5,8 @@ > 适用范围:计划书 PDF 解析、人工复核、PlanData、海报生成、PPT 生成、场景与模板、异步任务、质量门禁、测试、监控与数据留存 > 文档性质:实施主计划。既有 PPT、海报和 PDF 专项计划继续作为局部设计参考;若与本计划冲突,以“统一事实快照、字段证据链、失败关闭、版本可追溯”四项原则为准。 +> 2026-08-02 实施说明:计划中的代码基础、治理接口和失败关闭门禁已推进至 Phase 6;实际里程碑仍须以 30 份获批金标准、真实模板试跑、业务公式签字和灰度观察结果验收。详见 `docs/PPT与海报Phase4至6补充实施记录_20260802.md`。 + ## 1. 结论与实施决策 本次整改不能按“海报修一套、PPT 再修一套”的方式推进。审计报告中的 55 项问题共享四个根因:事实来源分裂、字段语义失真、配置运行时失效、任务与输出不可复现。因此,修复主线确定为: diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs new file mode 100644 index 0000000..aa73422 --- /dev/null +++ b/frontend/eslint.config.mjs @@ -0,0 +1,15 @@ +import pluginVue from 'eslint-plugin-vue' +import { withVueTs, vueTsConfigs } from '@vue/eslint-config-typescript' + +export default withVueTs( + { rootDir: import.meta.dirname }, + { ignores: ['dist/**'] }, + pluginVue.configs['flat/essential'], + vueTsConfigs.recommended, + { + rules: { + '@typescript-eslint/no-explicit-any': 'off', + 'vue/multi-word-component-names': 'off', + }, + }, +) diff --git a/frontend/package.json b/frontend/package.json index 73c9acf..ff82340 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,6 +24,7 @@ "@vitejs/plugin-vue": "^5.2.0", "@vue/eslint-config-typescript": "^14.0.0", "eslint": "^9.0.0", + "eslint-plugin-vue": "^10.9.2", "prettier": "^3.4.0", "typescript": "^5.7.0", "vite": "^6.0.0", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 1b2e262..289dba5 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -42,6 +42,9 @@ importers: eslint: specifier: ^9.0.0 version: 9.39.4 + eslint-plugin-vue: + specifier: ^10.9.2 + version: 10.9.2(@typescript-eslint/parser@8.61.1(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(vue-eslint-parser@10.4.1(eslint@9.39.4)) prettier: specifier: ^3.4.0 version: 3.8.4 diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 08cf947..d3d00f3 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -254,9 +254,9 @@ import { ref, computed, onMounted } from 'vue' import zhCn from 'element-plus/es/locale/lang/zh-cn' import { useAuth } from '@/composables/useAuth' import { useMobile } from '@/composables/useMobile' -import { ChatDotRound, ChatLineRound, Document, Clock, User, Setting, ArrowDown, SwitchButton, Menu, Edit, OfficeBuilding, View, DataBoard, Lock, TrendCharts, Connection, Picture } from '@element-plus/icons-vue' +import { ChatDotRound, ChatLineRound, Document, User, Setting, ArrowDown, SwitchButton, Menu, Edit, OfficeBuilding, View, DataBoard, Lock, TrendCharts, Picture } from '@element-plus/icons-vue' -const { user, logout, restoreFromUrl, checkAuth, fetchPermissions, hasPermission, permissionsLoading } = useAuth() +const { user, logout, restoreFromUrl, fetchPermissions, hasPermission, permissionsLoading } = useAuth() const showMobileMenu = ref(false) const { isMobile } = useMobile() diff --git a/frontend/src/components/RecommendForm.vue b/frontend/src/components/RecommendForm.vue index 2c49bfd..a857cab 100644 --- a/frontend/src/components/RecommendForm.vue +++ b/frontend/src/components/RecommendForm.vue @@ -137,7 +137,7 @@ + + diff --git a/frontend/src/components/generation/ReviewStatusSummary.vue b/frontend/src/components/generation/ReviewStatusSummary.vue new file mode 100644 index 0000000..f409c60 --- /dev/null +++ b/frontend/src/components/generation/ReviewStatusSummary.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/frontend/src/components/poster/long/PosterHtmlCanvas.vue b/frontend/src/components/poster/long/PosterHtmlCanvas.vue index 832321b..a462cfa 100644 --- a/frontend/src/components/poster/long/PosterHtmlCanvas.vue +++ b/frontend/src/components/poster/long/PosterHtmlCanvas.vue @@ -90,7 +90,7 @@ const props = defineProps<{ sections?: Array<{ id: string; visible: boolean }> }>() -const emit = defineEmits<{ +defineEmits<{ edit: [field: string, value: string] }>() diff --git a/frontend/src/components/poster/workspace/PosterSourcePanel.vue b/frontend/src/components/poster/workspace/PosterSourcePanel.vue index 3ef9bed..54739c6 100644 --- a/frontend/src/components/poster/workspace/PosterSourcePanel.vue +++ b/frontend/src/components/poster/workspace/PosterSourcePanel.vue @@ -1,6 +1,6 @@