活字格图片上传功能(批量)
这个报错真的恶心,又看不了他服务器源码,接口文档又是错的
活字格V9获取图片失败bug,报错404-CSDN博客
代码BUG记录:
问题:上传多个文件的base64编码被最后一个文件给覆盖导致循环多张图片的base64编码都一样
在代码中,使用了一个循环来加载图片并获取其base64编码。然而,在
image.onload
回调函数中,使用了i
变量,而这个变量在循环结束后可能已经发生了变化。这可能导致所有的回调函数都在循环结束后执行,因此它们都使用了相同的i
值。为了解决这个问题,可以使用一个闭包来保存每次循环的
i
值。可以通过将i
传递给一个立即执行的函数,并在该函数内部返回一个新的函数,该新函数就是image.onload
的回调函数。
//imgs=ffc31308-ec72-4268-a977-16f4c366a75f_whitepig.png|3e8582d5-7e4b-4544-8e51-446ba8f70905_blackpig.png
//img[1]=ffc31308-ec72-4268-a977-16f4c366a75f_whitepig.png
//img[2]=3e8582d5-7e4b-4544-8e51-446ba8f70905_blackpig.png
//....
const imgs = Forguncy.Page.getCell("img").getValue();
const imgArray = imgs.split("|");
//遍历imgArray
for (let i = 0; i < imgArray.length; i++) {(function(index) {var img = `http://${window.location.host}/Forguncy/FileDownloadUpload/Download?file=` + imgArray[index];var image = new Image();var base64;image.src = img;console.log("第" + index + "轮次的src:" + image.src);image.onload = function () {base64 = getBase64Image(image);console.log(index + base64);Forguncy.modifyTablesData({image: {addRows: [{name: getImgName(imgArray[index]),code: imgArray[index],base64: base64,is_identify: false}],}});}})(i);
}function getBase64Image(img) {var canvas = document.createElement("canvas");canvas.width = img.width;canvas.height = img.height;var ctx = canvas.getContext("2d");ctx.drawImage(img, 0, 0, img.width, img.height);var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();var dataURL = canvas.toDataURL("image/" + ext);return dataURL;
}function getImgName(input) {var match = input.match(/_([^_]*)(?:\.|$)/);var result = match && match[1];return result || null;
}
活字格发票识别功能(批量)*待完善
这个改了一下数据库,打算把刚刚上传的图片标记一个false,识别后标为true,之前的图片再加一个past_标记一下,批量识别就只用识别FALSE的文件了
因为要循环的缘故,把后续操作都改成js的形式
代码:
// 获取当前页面上名称为account的单元格
// 获取当前页面
var page = Forguncy.Page;
var access_token = page.getCell("access_token").getValue();var invoiceTypeChooseCell = page.getCell("invoice_type_choose");var invoiceCodeCell = page.getCell("invoice_code");
var invoiceNumCell = page.getCell("invoice_num");
var invoiceDateCell = page.getCell("invoice_date");
var invoiceTypeCell = page.getCell("invoice_type");
var checkCodeCell = page.getCell("check_code");
var totalAmountCell = page.getCell("total_amount");var imgIdCell = page.getCell("img_id");
var imageBase64Cell = page.getCell("image_base64");
var imgLengthCell = page.getCell("img_length");var identifyResultCell = page.getCell("identify_result");var isRepeatCell = page.getCell("is_repeat");var imageBase64;for (let i = 0; i < imgLengthCell.getValue(); i++) {imageBase64 = imageBase64Cell.getValue();InvoiceIdentificationPost();
}function InvoiceIdentificationPost() {//获取单元格的值var data = {//传入请求地址token: access_token,imageUrl: imageBase64};console.log("***发送百度AI*发票识别*请求***");Forguncy.Helper.post("customapi/fapiaoapi/vatinvoicebyimg", data,function (res) {console.log("res:" + res);let jsonData = JSON.parse(res);if (jsonData.words_result === undefined || jsonData.words_result === null) {alert("发送百度AI发票识别请求失败:" + jsonData.error_msg);return;}jsonData = jsonData.words_result;console.log(jsonData);//获取发票类型let invoiceType = invoiceTypeChooseCell.getValue();console.log("获取发票类型:" + invoiceType);//获取不到,自动识别if (invoiceType === "" || invoiceType === null) {console.log(jsonData.InvoiceType);invoiceType = translateInvoiceType(jsonData.InvoiceType);}console.log("识别发票类型:" + invoiceType);//识别不到if (invoiceType === "" || invoiceType === null) {console.log("无法自动识别出发票类型!!!");return;}invoiceCodeCell.setValue(jsonData.InvoiceCode);invoiceNumCell.setValue(jsonData.InvoiceNum);invoiceDateCell.setValue(convertDateFormat(jsonData.InvoiceDate));invoiceTypeCell.setValue(invoiceType);let checkCode = jsonData.CheckCode;/*** 处理分类逻辑*/// 发票金额// 增值税专票、电子专票、区块链电子发票、机动车销售发票、货运专票填写不含税金额// 二手车销售发票填写车价合计// 全电发票(专用发票)、全电发票(普通发票)填写价税合计金额// 其他类型发票可为空if (invoiceType == "elec_invoice_special" || invoiceType == "elec_invoice_normal") {console.log("价税合计金额");//价税合计金额totalAmountCell.setValue(jsonData.AmountInFiguers);} else if (invoiceType == "used_vehicle_invoice") {console.log("车价合计");//车价合计totalAmountCell.setValue(jsonData.AmountInFiguers);} else {console.log("不含税金额");// 不含税金额totalAmountCell.setValue(jsonData.TotalAmount);}//invoice_code:全电发票(专用发票)、全电发票(普通发票)此参数可为空if (invoiceType != "elec_invoice_special" && invoiceType != "elec_invoice_normal") {//其他的类型不能为空if (jsonData.InvoiceCode == "" || jsonData.InvoiceCode == null) {alert("发票代码不可为空!!!");return;}}//校验码。填写发票校验码后6位。//增值税电子专票、普票、电子普票、卷票、//区块链电子发票、通行费增值税电子普通发票此参数必填;if (invoiceType == "elec_special_vat_invoice" || invoiceType == "normal_invoice" || invoiceType == "elec_normal_invoice" || invoiceType == "roll_normal_invoice" || invoiceType == "blockchain_invoice" || invoiceType == "toll_elec_normal_invoice") {console.log("需要校验码");if (checkCode != "" && checkCode != null) {checkCode = getLastSixDigits(checkCode);console.log(checkCode);checkCodeCell.setValue(checkCode);} else {alert("校验码不可为空!!!");return;}} else {console.log("不需要校验码");checkCodeCell.setValue(checkCode);}identifyResultCell.setValue(JSON.stringify(jsonData));});//后续操作//判断发票是否重复Forguncy.getTableData("invoice", {"invoice_num": page.getCell("invoice_num").getValue()},function (data) {console.log("发票重复识别");isRepeatCell.setValue("重复");}, function (errorMessage) {isRepeatCell.setValue("未重复");});//没用重复则添加if (isRepeatCell.getValue() === "未重复") {Forguncy.modifyTablesData({invoice: {// 添加操作addRows: [{invoice_code: invoiceCodeCell.getValue(),invoice_num: invoiceNumCell.getValue(),invoice_date: invoiceDateCell.getValue(),invoice_type: invoiceTypeCell.getValue(),check_code: checkCodeCell.getValue(),total_amount: totalAmountCell.getValue(),is_repeat: isRepeatCell.getValue(),img_id: imgIdCell.getValue()}]}});} else if (isRepeatCell.getValue() === "重复") {alert("识别到重复发票,请核对发票信息");}
}//日期格式转换
function convertDateFormat(inputDateString) {// 使用正则表达式提取数字var numbersArray = inputDateString.match(/\d+/g);// 将数字字符串拼接在一起var outputDateString = numbersArray.join("");return outputDateString;
}//发票类型自动识别转换
function translateInvoiceType(chineseInvoiceType) {var translationMap = {//增值税专票、电子专票、区块链电子发票、机动车销售发票、货运专票填写不含税金额"电子专用发票": "elec_special_vat_invoice","普通发票(电子)": "elec_normal_invoice","电子普通发票": "elec_normal_invoice","普通发票(卷式)": "roll_normal_invoice","卷式普通发票": "roll_normal_invoice","通行费增值税电子普通发票": "toll_elec_normal_invoice","区块链电子发票": "blockchain_invoice", // 全电发票(专用发票)、全电发票(普通发票)填写价税合计金额"全电发票(专用发票)": "elec_invoice_special","电子发票(专用发票)": "elec_invoice_special","全电发票(普通发票)": "elec_invoice_normal","电子发票(普通发票)": "elec_invoice_normal","货运运输业增值税专用发票": "special_freight_transport_invoice","机动车销售发票": "motor_vehicle_invoice", //二手车销售发票填写车价合计"二手车销售发票": "used_vehicle_invoice","普通发票": "normal_invoice","专用发票": "special_vat_invoice",};// 检查输入的中文发票类型是否在映射中,如果是则返回对应的英文翻译,否则返回原始值for (var chineseType in translationMap) {if (chineseInvoiceType.includes(chineseType)) {return translationMap[chineseType];}}// 如果未找到匹配的中文发票类型,则返回空值return "";
}//获取发票校验码后六位数
function getLastSixDigits(str) {// 通过正则表达式匹配字符串中的数字const matches = str.match(/\d+/g);// 如果有匹配到数字if (matches) {// 获取最后一个匹配到的数字const lastNumber = matches[matches.length - 1];// 如果数字的长度大于等于六位,则返回后六位if (lastNumber.length >= 6) {return lastNumber.slice(-6);} else {// 如果数字的长度小于六位,则直接返回该数字return lastNumber;}} else {// 如果没有匹配到数字,则返回空字符串或其他适当的值return "";}
}
这个代码暂时只能识别一张图片
图片预览功能
暂时没啥头绪,不能改html真的难写,建议@活字格给个插入HTML代码的插件
更改数据库(功能已加入代码,还没测试)
关联图片功能 和 查重的记录功能
关联图片功能
查重的记录功能
C#代码更改
从图片URL来请求改成从图片base64编码来请求,还增加了pdf请求的发票识别功能
现在支持图片和PDF形式的发票上传、识别
活字格C#代码调用服务器给百度ai接口发送请求设置-CSDN博客
总结一下:
呃呃,有一种牵一发而动全身的感觉,改个图片识别形式,代码全都改了
1. 修复上传多个文件的base64编码被最后一个文件覆盖的问题:
在图片上传的循环中,通过使用闭包来保存每次循环的i
值,确保image.onload
回调函数使用正确的i
值。这解决了循环多张图片的base64编码都一样的问题。
2. 活字格发票识别功能(批量):
- 通过循环处理多张图片的发票识别。
- 使用闭包确保在循环中正确传递
imageBase64
值,以防止最后一个值覆盖其他图片的问题。 - 对识别结果进行处理,并根据发票类型分类填充相应的单元格。
3. 改动数据库:
- 在发票识别后,标记已识别的图片,并将未重复的发票信息添加到数据库中。
- 实现了查重的记录功能,根据发票号码判断是否重复。
4. C#代码更改:
- 从图片URL请求改成从图片base64编码请求,增加了对PDF形式的发票上传和识别的功能。
5. 图片预览功能:
- 目前尚未实现图片预览功能,可能需要活字格提供插入HTML代码的插件来更方便地修改HTML。
总体而言,代码经历了多个方面的修改,包括修复bug、批量处理发票识别、数据库操作、C#代码改动等。需要注意的是,确保在循环中正确处理闭包以防止变量覆盖的问题是关键之一。此外,对于图片预览功能,可能需要进一步探讨或等待相关插件支持。