# CRM 销售报价单 AI OCR 识别 - 前端联调方案 ## 涉及页面 - `saleQuotation/index.vue` — 报价单列表页,新增"AI 识别录入"按钮 - `saleQuotation/form.vue` — 报价单新增/编辑弹窗,接收 OCR 识别结果预填表单 ## 业务流程与数据带入 1. 报价单列表页 → 点击"AI 识别录入"按钮 → 弹出上传弹窗 2. 上传弹窗中:选择文件上传 → 调用 `/admin-api/system/storage-blob/upload` → 获得 `blobId` 3. 调用 `/admin-api/crm/sale-quotation/ai/ocr` 传入 `blobId` → 获得识别结果 4. 预览识别结果 → 用户点击"确认并填入表单" → 关闭上传弹窗 → 打开新增报价单弹窗 5. 新增弹窗中:识别结果预填到对应字段,用户补充完善后保存 ## API | 方法 | 路径 | 说明 | |------|------|------| | POST | `/admin-api/crm/sale-quotation/ai/ocr` | AI OCR 识别报价文件 | **请求参数:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | blobId | Long | 是 | 已上传文件的 blob ID(通过 `/admin-api/system/storage-blob/upload` 获取) | **响应字段:** | 字段 | 类型 | 说明 | |------|------|------| | name | String | 报价单名称 | | customerName | String | 客户名称(文本,需用户手动匹配 CRM 客户) | | quotationTime | String (LocalDate) | 报价日期,格式 yyyy-MM-dd | | validUntil | String (LocalDate) | 有效期至,格式 yyyy-MM-dd | | taxRate | BigDecimal | 税率(百分比),如 13.0 | | discountPercent | BigDecimal | 折扣率(百分比),如 5.0 | | remark | String | 备注 | | items | Array\ | 物料明细列表 | | items[].itemName | String | 物料名称(文本,需用户在 MdmItemSelect 中匹配) | | items[].itemSpec | String | 物料规格型号 | | items[].count | BigDecimal | 数量 | | items[].quotationPrice | BigDecimal | 单价 | | rawText | String | 原始识别文本,前端可选展示用于调试/参考 | 所有字段均为可选,AI 未识别到的字段为 null。 **响应示例:** ```json { "code": 0, "data": { "name": "XX公司报价单", "customerName": "XX科技有限公司", "quotationTime": "2026-07-31", "validUntil": "2026-08-30", "taxRate": 13.0, "discountPercent": 5.0, "remark": "含税含运费", "items": [ { "itemName": "伺服电机", "itemSpec": "SV-1000W", "count": 10, "quotationPrice": 1500.00 } ], "rawText": "原始文件内容..." } } ``` **错误情况(HTTP 200,所有字段为 null,rawText 中包含错误提示):** | rawText 值 | 场景 | |------------|------| | 文件不存在 | blobId 无效 | | 不支持的文件类型,请上传 PDF/Word/Excel/图片文件 | 文件后缀不在白名单内 | | 文件读取失败 | 文件下载失败 | | 文件内容为空,无法识别 | 文件解析出空内容 | | AI 识别暂时不可用,请手动录入 | AI 服务异常 | ## 支持的文件类型 | 类型 | 后缀 | |------|------| | PDF | .pdf | | Word | .doc, .docx | | Excel | .xls, .xlsx | | 图片 | .png, .jpg, .jpeg, .gif, .bmp | | 纯文本 | .txt, .csv | ## 数据填入规则 | OCR 字段 | 填入新增表单字段 | 说明 | |----------|-----------------|------| | name | 报价单名称 | 直接填入 | | customerName | 客户名称(文本展示) | 不自动匹配 CRM 客户,用户需手动通过 CrmCustomerSelect 选择 | | quotationTime | 报价日期 | 直接填入日期选择器 | | validUntil | 有效期至 | 直接填入日期选择器 | | taxRate | 税率 | 直接填入,单位为百分比 | | discountPercent | 折扣率 | 直接填入,单位为百分比 | | remark | 备注 | 直接填入 | | items[].itemName + itemSpec | 物料明细行 | 填入物料名称和规格文本,用户需在 MdmItemSelect 中手动匹配实际物料 | | items[].count | 物料明细行 - 数量 | 直接填入 | | items[].quotationPrice | 物料明细行 - 单价 | 直接填入 | ## 业务规则说明 | 场景 | 规则 | |------|------| | AI 识别结果全为 null | 弹窗提示"未识别到报价数据",用户可手动录入或重新上传 | | 部分字段识别成功 | 预填已有字段,缺失字段留空由用户手动填写 | | 识别到多个物料但用户只需部分 | 用户在新增弹窗中增删调整物料行 | | 客户名称无法匹配 CRM 客户 | 用户通过 CrmCustomerSelect 搜索并选择正确的客户 | ## 注意事项 - 文件上传使用现有的 `/admin-api/system/storage-blob/upload` 接口,不要使用 `/infra/file/upload` - 文件大小限制由 system 模块的 storage-blob 上传接口控制 - AI OCR 识别可能需要几秒时间,前端需显示 loading 状态 - `customerName` 是纯文本,前端不要尝试自动匹配,需要用户通过 CrmCustomerSelect 手动选择 - `itemName` 同理,用户需在 MdmItemSelect 中搜索物料编码/名称来匹配实际物料 - 识别结果中的日期格式为 `yyyy-MM-dd`,直接可用于日期选择器 - 当 rawText 中包含错误提示(如"文件不存在")时,前端应展示错误信息,不要继续填入表单流程