活字格图片上传功能(批量)
这个报错真的恶心,又看不了他服务器源码,接口文档又是错的
活字格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#代码改动等。需要注意的是,确保在循环中正确处理闭包以防止变量覆盖的问题是关键之一。此外,对于图片预览功能,可能需要进一步探讨或等待相关插件支持。