实习日志5

活字格图片上传功能(批量)

这个报错真的恶心,又看不了他服务器源码,接口文档又是错的

活字格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的形式

实习日志5_第1张图片

代码: 

// 获取当前页面上名称为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 "";
    }
}

这个代码暂时只能识别一张图片

实习日志5_第2张图片 

图片预览功能

暂时没啥头绪,不能改html真的难写,建议@活字格给个插入HTML代码的插件

实习日志5_第3张图片

更改数据库(功能已加入代码,还没测试)

关联图片功能 和 查重的记录功能

关联图片功能

实习日志5_第4张图片

查重的记录功能

实习日志5_第5张图片

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#代码改动等。需要注意的是,确保在循环中正确处理闭包以防止变量覆盖的问题是关键之一。此外,对于图片预览功能,可能需要进一步探讨或等待相关插件支持。

后续需要的操作:

1.完善批量识别和验真
2.图片预览
3.图片关联识别
4.我捷通的FRID打印机和那个EPC程序还没搞明白嘞

你可能感兴趣的:(前端,javascript,开发语言)