供应商模块自动提取填充-问题总结.md 8.7 KB

供应商管理模块自动提取填充功能 - 问题与解决方案

📅 日期

2025年11月24日

🎯 功能概述

实现了供应商管理模块的附件自动提取并填充表单功能,支持上传 Word(.docx)、Excel(.xlsx/.xls)、PDF 文件,自动提取供应商信息并填充到表单。


❌ 遇到的问题及解决方案

问题1:图片上传和附件上传位置错误

现象:图片上传和附件上传控件显示在表单底部,而非第一行和第二行

原因:HTML 中这两个上传表单项在其他表单字段之后

解决

  • 使用 search_replace 工具
  • certificateUpload(图片上传)从第229行移到第122行
  • attachmentUpload(附件上传)紧跟在图片上传之后
  • 其他表单字段从第三行开始

文件d:\project\RuoYi-Vue-master\ruoyi-ui\src\views\system\supplier\index.vue


问题2:附件上传后自动填充不生效

现象:修改 handleAttachmentChange 方法添加自动填充逻辑后,上传文件并未自动打开表单并填充数据

原因:el-upload 的 @change 事件处理可能存在异步延迟或事件触发时序问题

解决

  • 移除自动触发逻辑
  • 在附件上传区域下方添加"自动提取并填充"按钮
  • 创建新方法 autoFillFromAttachment() 作为按钮点击事件处理器
  • 用户可显式点击按钮手动触发填充流程

优势

  • 更加可控和可靠
  • 用户可以明确知道什么时候触发填充
  • 避免异步事件处理的不确定性

问题3:Vue 表单响应式更新失败

现象:虽然表单对象的数据被修改,但页面视图未更新,表单验证仍然失败

根本原因

  1. 直接属性赋值 (this.form.fieldName = value) 不能触发 Vue 的响应式更新
  2. 表单对话框未打开时填充数据,数据被填充到错误的对象实例

错误写法

// ❌ 不会触发响应式更新
this.form.supplierName = extractedValue;

正确写法

// ✅ 正确方式:使用 $set 和 $nextTick
if (!this.open) {
  this.reset();
  this.open = true;
  this.title = "新增供应商";
}

this.$nextTick(() => {
  this.$set(this.form, 'supplierName', extractedValue);
  this.$refs.form.clearValidate();
  this.$modal.msgSuccess('数据填充成功');
});

关键步骤

  1. 打开表单对话框(确保 DOM 存在)
  2. 使用 $set() 而非直接赋值
  3. $nextTick() 回调中执行,确保 DOM 渲染完成
  4. 调用 clearValidate() 清空旧的验证错误

问题4:el-upload 组件无法获取上传文件

现象:选择文件后提示"请先选择文件",无法获取上传的文件列表

原因:Vue 2 中 el-upload 不支持 v-model 直接绑定文件列表

错误写法

// ❌ v-model 绑定无效
this.form.attachments // 无法获取文件

正确写法

// ✅ 通过 ref 直接访问
const uploadRef = this.$refs.attachmentUpload;
const files = uploadRef.uploadFiles; // 获取已上传的文件列表

// 获取第一个文件的原始 File 对象
const fileObj = files[0].raw || files[0];

问题5:productName 反复被提取为"卖方"

现象:多次测试都显示 productName 为"卖方"而非实际产品名称"电缆"

原因:初期的文本匹配逻辑过于简单,没有足够的上下文判断

第一轮修复(不成功):

  • extractProductName() 方法的排除列表中添加"卖方"

第二轮修复(不成功):

  • 在备用方案中也添加排除列表

最终修复(成功):

  • 添加多层备用方案
  • 主动检测非产品词并替换
  • 从常见产品列表中查找正确的产品名称
// 最终的备用方案逻辑
if (!extracted.productName || extracted.productName.match(/^(买方|卖方|丫方|按一|按二)$/)) {
  const commonProducts = ['电缆', '电线', '管材', '配件', '材料', '设备'];
  for (const product of commonProducts) {
    if (text.includes(product)) {
      extracted.productName = product;
      break;
    }
  }
}

问题6:金额提取包含年份数字

现象:contractAmount 显示为 2025.00(来自日期 2025.11.12)而非正确的 252471.16

原因:金额正则表达式过于宽泛,无法排除年份数字

解决

  • 在金额提取逻辑中添加年份排除判断
  • 只保留 1000-1999 或 2100-999999 范围内的数字
// 金额提取的关键逻辑
const amounts = [];
const amountMatches = text.match(/\b([0-9]+(?:\.[0-9]{2})?)\b/g) || [];

for (const match of amountMatches) {
  const n = parseFloat(match);
  // 排除年份 (2000-2099) 和过小的数字
  if (n > 1000 && n < 999999 && !(n >= 2000 && n <= 2099)) {
    amounts.push(n);
  }
}

问题7:税号无法识别含空格的格式

现象:含空格的税号格式(如"9143 0111 5765 6395 79")无法被识别

原因:正则表达式中只支持连续的数字和字母,未考虑空格分隔

原始正则

// ❌ 无法匹配含空格的格式
/税号[\uff1a:]*\s*([0-9]{15,})/

修改后的正则

// ✅ 支持数字、字母和空格
/税号[\uff1a:]*\s*([0-9A-Z\s]{15,25})/

💡 关键经验与最佳实践

1. Vue 响应式更新三步曲

// 1. 打开对话框(确保 DOM 存在)
if (!this.open) {
  this.reset();
  this.open = true;
}

// 2. 使用 $nextTick 等待 DOM 渲染
this.$nextTick(() => {
  // 3. 使用 $set 触发响应式更新
  this.$set(this.form, 'fieldName', value);
  
  // 清空验证错误
  this.$refs.form.clearValidate();
});

2. el-upload 文件访问方式

// 通过 ref 获取上传组件
const uploadRef = this.$refs.attachmentUpload;

// 获取文件列表
const files = uploadRef.uploadFiles;

// 获取原始 File 对象
const fileObj = files[0].raw || files[0];

3. 文件内容提取三阶段策略

  • 阶段一:全文扫描(查找关键词)

    • 优先级最高
    • 查找"乙方"、"卖方"等标记
  • 阶段二:逐行扫描(提取详细字段)

    • 查找银行账户、税号等
    • 支持多种标签变种
  • 阶段三:备用方案和数据清洗

    • 处理格式变化
    • 检测和纠正提取错误
    • 排除干扰数据

4. 手动触发优于自动触发

  • 当异步处理复杂时,提供显式按钮更可靠
  • 用户体验更好(明确知道何时触发)
  • 调试和排查更容易

5. 正则表达式需要充分考虑

  • 真实数据格式多样(含空格、多种分隔符等)
  • 需要测试各种格式的输入
  • 添加排除条件避免误匹配

📝 代码改动清单

修改文件

  • d:\project\RuoYi-Vue-master\ruoyi-ui\src\views\system\supplier\index.vue

主要改动

  1. UI 布局调整(第120-160行)

    • 将图片上传移到表单顶部(第一行)
    • 将附件上传移到表单顶部(第二行)
    • 在附件上传下方添加"自动提取并填充"按钮
  2. 方法修改

    • 修改 handleAttachmentChange() 方法
    • 添加 autoFillFromAttachment() 新方法
  3. 功能实现

    • 支持 Word、Excel、PDF 三种文件格式
    • 自动提取 10 个供应商字段
    • 自动打开表单并填充数据

📦 备份标签

  • 标签名v1.0-supplier-auto-extract
  • 提交 IDa438cb0
  • 描述:供应商模块自动提取填充功能完成版

查看和切换备份

# 查看所有标签
git tag -l

# 查看标签详情
git show v1.0-supplier-auto-extract

# 切换到这个版本
git checkout v1.0-supplier-auto-extract

# 回到最新版本
git checkout master

🚀 后续优化方向

  1. AI 辅助识别:使用 AI 模型提高文本识别准确率
  2. 格式导入:支持更多文件格式(PPT、HTML 等)
  3. 批量处理:支持批量上传多个文件同时处理
  4. 预览确认:提取后显示预览,用户确认后再填充
  5. 历史记录:保存提取历史,支持撤销恢复
  6. 性能优化:大文件处理的流式读取

📚 相关文档链接


最后更新:2025年11月24日
版本:v1.0-supplier-auto-extract