实习日志5

news2024/11/16 1:35:35

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

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

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

后续需要的操作:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1411512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

eclipse启动Java服务及注意事项

1、导入项目 选择file——》import…——》Generate——》Exiting Projects into Workspace——》选择要导入的项目 2、添加tomcat 1&#xff09;点击Serves——》No servers are available. Click this link to create a new server… 2&#xff09;点击“Add…” 3&…

【Servlet】如何编写第一个Servlet程序

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Servlet】 本专栏旨在分享学习Servlet的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; Servlet是Java编写的服务器端…

STM32第一节——初识STM32

1 硬件介绍 1.1 硬件平台 配套硬件&#xff1a;以野火的STM32 F1霸道开发板为平台&#xff0c;若用的是别的开发板&#xff0c;可自己进行移植。 1.2 什么是STM32 STM32是由意法半导体&#xff08;STMicroelectronics&#xff09;公司推出的一系列32位的ARM Cortex-M微控制…

CMIP6数据驱动WRF和WRF-Chem模式、WRF-Chem的未来大气污染变化模拟

目录 一、CMIP6数据及运行平台建设 二、CMIP6数据驱动WRF和WRF-Chem模式 三、WRF-Chem的未来情景模拟 更多应用 对模式比较计划的全球气候预估数据进行动力降尺度&#xff0c;结合预估的未来气候变化&#xff0c;运用区域气候模式和气候-化学耦合模式&#xff0c;实现对未来…

【数据结构】数据结构初识

前言&#xff1a; 数据结构是计算存储&#xff0c;组织数据的方式。数据结构是指相互间存在一种或多种特定关系的数据元素的集合。通常情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。 Data Structure Vi…

day2 C++

封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show() #include <iostre…

笔记--写代码好习惯

原文&#xff1a;写代码有这16个好习惯&#xff0c;可以减少80%非业务的bug

uniapp vuecli项目融合[小记]:将多个项目融合,打包成一个小程序/App,拆分多个H5应用

前言&#xff1a; 目前两个uniapp vuecli开发的项目【A、B】&#xff0c;新规划的项目C&#xff1a;需要融合项目B 80%的功能模块&#xff0c;同时也需要涵盖项目A的所有功能模块。 应用需求&#xff1a; 1、新项目C【小程序】可支持切换到应用A/C界面【内部通过初始化、路由跳…

对于小微企业而言,数字化转型的重要性是什么?

数字化转型对于小微企业至关重要&#xff0c;原因如下&#xff1a; 1.效率和生产力&#xff1a;采用数字工具和技术可以简化业务流程、自动化重复性任务并提高整体效率。这使得小型企业能够用更少的资源完成更多的工作&#xff0c;最终提高生产力。 2.节省成本&#xff1a;数…

Gradle学习笔记:Gradle的简介、下载与安装

文章目录 一、什么是Gradle二、为什么选择Gradle三、下载并安装Gradle四、Gradle的bin目录添加到环境变量五、测试Gradle是否安装正常 一、什么是Gradle Gradle是一个开源构建自动化工具&#xff0c;专为大型项目设计。它基于DSL&#xff08;领域特定语言&#xff09;编写&…

江科大STM32 中

目录 6、TIM&#xff08;Timer&#xff09;定时器基本定时器通用定时器高级定时器示例程序&#xff08;定时器定时中断&定时器外部时钟&#xff09;TIM输出比较示例程序&#xff08;PWM驱动LED呼吸灯&PWM驱动舵机&PWM驱动直流电机&#xff09;TIM输入捕获示例程序&…

Qt 基于海康相机 的视频标绘

需求&#xff1a; 基于 视频 进行 标注&#xff0c;从而进行测量。 曾经搞在线教育时&#xff0c;尝试在视频上进行文字或者图形的绘制&#xff0c;但是发现利用Qt widget 传sdk 句柄的方式&#xff0c;只能使用窗口叠加的方式&#xff08;Qt 基于海康相机的视频绘图_海康相…

在 Linux 上搭建 Java 环境

目录 一、安装jdk 1. 挑选 jdk 版本 2. 安装 3. 验证 jdk 二、安装tomcat 1. 下载压缩包 2. 上传压缩包给 Linux &#xff08;需要用到 rz 命令&#xff09; 3. 解压压缩包&#xff08;需要用到 unzip&#xff09; 4. 进入 bin 目录 5. 给启动脚本增加可执行权限 6. 启…

CAN基础知识介绍

1.CAN的基本介绍 CAN&#xff08;Controller Area Network&#xff09;&#xff0c;是ISO国际标准化的串行通信协议。为了满足汽车产业的“减少线束的数量”、“通过多个LAN&#xff0c;进行大量数据的高速通信”的需求。 发展历史&#xff1a; 1986年&#xff0c;博世公司开…

JVM篇----第七篇

系列文章目录 文章目录 系列文章目录前言一、老年代二、永久代三、JAVA8 与元数据四、引用计数法五、可达性分析前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一…

postman自动化测试如何设置环境变量教程

在接口测试中&#xff0c;我们经常会用到一些通用请求参数&#xff0c;或者需要使用某个接口的返回参数作为另一个接口的请求参数&#xff0c;静态的参数还好&#xff0c;如果是经常变动的参数&#xff0c;那么操作起来&#xff0c;就特别的麻烦&#xff0c;这时候&#xff0c;…

pytorch代码实现注意力机制之SK Attention

SK注意力机制 简介&#xff1a;在标准卷积神经网络 &#xff08;CNN&#xff09; 中&#xff0c;每一层人工神经元的感受野被设计为共享相同的大小。在神经科学界众所周知&#xff0c;视觉皮层神经元的感受野大小受到刺激的调节&#xff0c;这在构建 CNN 时很少被考虑。我们在…

使用阿里云的oss对象存储服务实现图片上传(前端vue后端java详解)

一&#xff1a;前期准备&#xff1a; 1.1&#xff1a;注册阿里云账号&#xff0c;开启对象存储oss功能&#xff0c;创建一个bucket&#xff08;百度教程多的是&#xff0c;跟着创建一个就行&#xff0c;创建时注意存储类型是标准存储&#xff0c;读写权限是公共读&#xff09;…

深度学习(6)---Transformer

文章目录 一、介绍二、架构2.1 Multi-head Attention2.2 Encoder(编码器)2.3 Decoder(解码器) 三、Encoder和Decoder之间的传递四、Training五、其他介绍5.1 Copy Mechanism5.2 Beam Search 一、介绍 1. Transformer是一个Seq2Seq&#xff08;Sequence-to-Sequence&#xff09;…

redis + 拦截器 :防止数据重复提交

1.项目用到,不是核心 我们干系统开发,不免要考虑一个点&#xff0c;数据的重复提交。 我想我们之前如果要校验数据重复提交要求&#xff0c;会怎么干?会在业务层&#xff0c;对数据库操作&#xff0c;查询数据是否存在,存在就禁止插入数据; 但是吧,我们每次crud操作都会连接…