实习日志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的形式

代码: 

// 获取当前页面上名称为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.mzph.cn/news/647899.shtml

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

相关文章

【oracle】oracle客户端及oracle连接工具

一、关于oracle客户端 1.1 Oracle Client 完整客户端 包含完整的客户端连接工具。 包很大&#xff0c;需要安装 1.2 instantclient 即时客户端 是 Oracle(R) 发布的轻量级数据库客户端&#xff0c;减少甚至只包含几个文件&#xff0c;您无需安装标准的客户端&#xff0c;就可以…

视频渲染靠cpu还是显卡 会声会影视频渲染的作用是什么

视频渲染最占用的资源就是CPU&#xff0c;多核心多线程&#xff0c;这样才能渲染快。渲染可以在时间线上实时平滑预览&#xff0c;便于编辑&#xff0c;最终导出成片的时候速度也会快一些&#xff0c;渲染就是对每桢的图像进行重新优化的过程。 渲染的作用主要是能够保证使用者…

【java面试】Spring

目录 1. Spring 介绍1.1 Spring 的优点1.2 Spring 的缺点1.3 详细讲解一下核心容器&#xff08;spring context应用上下文) 模块 2. Spring俩大核心概念IOC&#xff0c;Inversion of Control&#xff0c;控制反转AOP(Aspect-OrientedProgramming)&#xff0c;面向切面编程Sprin…

Gradle学习笔记:Gradle的使用方法

文章目录 1.初始化项目2.构建脚本语言选择3.项目命名4.项目构建过程 1.初始化项目 创建一个test空文件夹&#xff0c;在该文件夹下打开终端&#xff0c;并执行命令&#xff1a;gradle init. 会有一个选项让你选择项目的类型。下面是每个选项的含义和用途&#xff1a; basic&am…

Hylicos - MINI2440 - 中断控制

中断 中断源管理 中断是一种异步异常&#xff0c;CPU需要处理很多来自设备的中断请求&#xff0c;而CPU引出的line只有IRQ线和FIQ线&#xff0c;所以就得引入中断控制器帮助CPU搞清楚是中断的来源。 MINI2440的中断控制器&#xff0c;可以接受来自60个中断源的请求。提供这些…

机器学习笔记 - 基于自定义数据集 + 3D CNN进行视频分类

一、简述 这里主要介绍了基于自定义动作识别数据集训练用于视频分类的 3D 卷积神经网络 (CNN) 。3D CNN 使用三维滤波器来执行卷积。内核能够在三个方向上滑动,而在 2D CNN 中它可以在二维上滑动。 这里的模型主要基于D. Tran 等人2017年的论文“动作识别的时空卷积研究”。 …

【算法】糖果(差分约束)

题目 幼儿园里有 N 个小朋友&#xff0c;老师现在想要给这些小朋友们分配糖果&#xff0c;要求每个小朋友都要分到糖果。 但是小朋友们也有嫉妒心&#xff0c;总是会提出一些要求&#xff0c;比如小明不希望小红分到的糖果比他的多&#xff0c;于是在分配糖果的时候&#xff…

RocketMQ源码阅读-九-自定义过滤规则Flitersrv

RocketMQ源码阅读-九-自定义过滤规则Flitersrv 什么是FiltersrvFiltersrv注册到Broker过滤类Consumer发起订阅设置过滤类代码Consumer上传过滤类代码Flitersrv编译过滤类代码 过滤消息Consumer 从 Filtersrv 拉取消息Flitersrv从Broker拉取消息 Flitersrv的高可用总结 什么是Fi…

【C++】内存分区模型

目录 1.程序运行前 2.程序运行后 3. new操作符 3.1 基本语法 3.2 开辟数组 C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的 全局区&#xff1a; 存放全局变量和静态变量以及常量栈区 …

时序分解 | MATLAB实现CEEMDAN+SE自适应经验模态分解+样本熵计算

时序分解 | MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算 目录 时序分解 | MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算 包括频谱图 附赠案例数据 可直接运行 …

喜报|「云原生数据库PolarDB」、「阿里云瑶池一站式数据管理平台」揽获“2023技术卓越奖”

日前&#xff0c;国内知名IT垂直媒体&技术社区IT168公布2023年“技术卓越奖”评选结果&#xff0c;经由行业CIO/CTO大咖、技术专家及IT媒体三方的联合严格评审&#xff0c;阿里云瑶池数据库揽获两项大奖&#xff1a;云原生数据库PolarDB荣获“2023年度技术卓越奖”&#xf…

YOLOv5全网独家首发:Powerful-IoU更好、更快的收敛IoU,效果秒杀CIoU、GIoU等 | 2024年最新IoU

💡💡💡本文独家改进:Powerful-IoU更好、更快的收敛IoU,是一种结合了目标尺寸自适应惩罚因子和基于锚框质量的梯度调节函数的损失函数 💡💡💡MS COCO和PASCAL VOC数据集实现涨点 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/category_1251193…

《SPSS统计学基础与实证研究应用精解》视频讲解:数据加权处理

《SPSS统计学基础与实证研究应用精解》4.7 视频讲解 视频为《SPSS统计学基础与实证研究应用精解》张甜 杨维忠著 清华大学出版社 一书的随书赠送视频讲解4.7节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。本书旨在手把手教会使…

Redis 面试题 | 11.精选Redis高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

CNN卷积理解

1 卷积的步骤 1 过滤器&#xff08;卷积核&#xff09;&#xff08;Filter或Kernel&#xff09;&#xff1a; 卷积层使用一组可学习的过滤器来扫描输入数据&#xff08;通常是图像&#xff09;。每个过滤器都是一个小的窗口&#xff0c;包含一些权重&#xff0c;这些权重通过训…

小红书如何做混部?

作者&#xff1a;宋泽辉&#xff08;小红书&#xff09;、张佐玮&#xff08;阿里云&#xff09; 编者按&#xff1a; Koordinator 是一个开源项目&#xff0c;是基于阿里巴巴内部多年容器调度、混部实践经验孵化诞生&#xff0c;是行业首个生产可用、面向大规模场景的开源混…

在 Linux 上搭建 Java 环境

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

Internet Download Manager 6.42.3 (IDM) 中文破解免激活绿色版

Internet Download Manager 6.42.3中文破解版&#xff0c;全球最佳下载利器。Internet Download Manager (简称IDM) 是一款Windows 平台功能强大的多线程下载工具&#xff0c;国外非常受欢迎。支持断点续传&#xff0c;支持嗅探视频音频&#xff0c;接管所有浏览器&#xff0c;…

将AWS iot消息数据发送S3

观看此文章之前&#xff0c;请先学习AWS iot的数据收集&#xff1a; 使用Linux SDK客户端向AWS Iot发送数据-CSDN博客 上述的文章向大家展示了如何从客户端向AWS iot发送数据&#xff0c;那么数据收到之后&#xff0c;我们如何通过AWS的服务进行数据处理或者保存呢&#xff1…

jmeter之接口测试实现参数化(利用函数助手),参数值为1-9(自增的数字)

1.前言 思考&#xff1a;为什么不用postman&#xff0c;用postman的话就得导入csv文件/json文件 如果不想导入文件&#xff0c;postman是实现不了&#xff0c;因为postman每次只会运行一次 2.jmeter函数助手实现参数化 &#xff08;1&#xff09;新建“线程组”--新建“http…