package cn.iocoder.yudao.module.qcreport.controller.admin.aiimport.vo; import cn.iocoder.yudao.module.qcreport.dal.dataobject.version.ReportTemplateSchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; import java.util.Map; /** * AI 识别结果:一份**模板草稿**,不落库。 *

* 刻意不返回 {@link ReportTemplateSchema}:草稿只是「一串组件 + 各自的属性」这个更小的物化形态, * 由前端装配器配上活注册表才能编译成画布数据({@code grapes})。让后端产出完整 Schema * 就得在这里再实现一遍组件的 canvas 结构,等于把渲染引擎的职责抄进 AI 模块,还会让 * Schema 契约为了 AI 而膨胀——语义层是刻意收窄的子集,不该为这条路开口子。 *

* 因此草稿的消费者只有前端装配器:它逐项查注册表,未注册的 type 直接跳过。 * 即便模型编出清单外的组件,也永远变不成任意 HTML。 * *

为什么没有 rawText 字段

* 没解析出来时本接口直接抛错({@code AI_IMPORT_RESPONSE_UNPARSEABLE}),响应体是错误结构而非本 VO, * 塞一个恒为 null 的字段只会让后来人以为「解析失败时前端能拿到原文」。模型原文写进了服务端日志。 */ @Schema(description = "管理后台 - 智能质检报告 AI 模板草稿 Response VO") @Data public class QcReportAiDraftRespVO { @Schema(description = "AI 识别出的组件草稿,按报告从上到下的顺序;已做过合并去重与非法项过滤", requiredMode = Schema.RequiredMode.REQUIRED) private List components; @Schema(description = "AI 猜测的纸张配置,可能为空(为空表示按当前模板的纸张走)") private ReportTemplateSchema.Page page; @Schema(description = "AI 对这份文档的一句话说明,展示在预览弹窗顶部") private String summary; /** * 软失败清单:被跳过的页、无法表达的区块、被丢弃的未知组件等。 *

* 与「整体失败抛异常」是两回事:这些情况不影响草稿可用,但必须让用户看见, * 否则会以为文件里的内容都识别到了。 */ @Schema(description = "识别过程中的软提示,需在界面上展示给用户") private List warnings; @Schema(description = "识别总耗时(毫秒),含多次模型调用", example = "12400") private Long durationMs; /** * 一个组件草稿。 *

* 结构完全扁平:没有 children、没有嵌套。props 的 key 由前端积木清单定义, * 因此这里用 {@code Map} 而不是强类型——合法 key 的权威在前端注册表,后端不该重复声明一遍。 */ @Schema(description = "管理后台 - AI 草稿里的一个组件") @Data public static class DraftComponent { @Schema(description = "组件类型,必须是积木清单里声明过的 type", example = "QualityTable") private String type; @Schema(description = "组件属性;清单里未声明的 key 已被后端丢弃") private Map props; } }