<template> <!-- OCR 单据智能识别 --> <el-dialog custom-class="ocr-invoices-dialog" :visible.sync="show" :show-close="false" width="80%" top="10vh" > <div slot="title" class="ocr-title"> <span style="font-weight: bold;">OCR智能识别</span> <div> <c-button type="primary" @click="save">保存</c-button> <c-button type="primary" @click="close">关闭</c-button> </div> </div> <div class="invoices-recognition"> <div class="invoices-area"> <div class="file-name">{{ fileName }}</div> <!-- <iframe class="pdf-file" :src="fileUrl" type="application/pdf" /> --> <div class="pdf-file"> <el-scrollbar :style="{ height: imgContainerHeight + 'px' }"> <div style="height: 100%;display: flex;justify-content: center;"> <el-image :src="fileUrl" @load="ocr" alt="单据" style="display: block;"></el-image> </div> </el-scrollbar> </div> </div> <div class="recognition-area"> <el-scrollbar :style="{ height: imgContainerHeight + 'px' }"> <el-form v-model="formData" label-width="100px" label-position="right" > <c-col :span="24"> <el-form-item label=""> <c-select v-model="formData.type" @change="fileTypeChangeEvent"> <el-option v-for="(item, idx) in fileType" :key="idx" :label="item.label" :value="item.value" ></el-option> </c-select> </el-form-item> </c-col> <!-- 商业发票 --> <c-col :span="24" v-if="formData.type === 'commercial_invoice'"> <c-col :span="24"> <el-form-item label="发票日期"> <c-input type="textarea" v-model="formData['commercial invoice']['Date']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="发票金额"> <c-input type="textarea" v-model="formData['commercial invoice']['TOTAL CONTRACT VALUE']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="是否正本"> <c-select v-model="formData['commercial invoice'].original" style="width: 100%;"> <el-option v-for="(item, idx) in invoicesOriginalOptions" :key="idx" :label="item.label" :value="item.value" ></el-option> </c-select> </el-form-item> </c-col> </c-col> <!-- 提货单 --> <c-col :span="24" v-if="formData.type === 'bill_of_lading'"> <c-col :span="24"> <el-form-item label="发货人"> <c-input type="textarea" v-model="formData['bill of lading']['Shipper']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="收货人"> <c-input type="textarea" v-model="formData['bill of lading']['Consignee']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="通知地址"> <c-input type="textarea" v-model="formData['bill of lading']['Notify address']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="船舶"> <c-input type="textarea" v-model="formData['bill of lading']['Vessel']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="装货港"> <c-input type="textarea" v-model="formData['bill of lading']['Port of Loading']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="卸货港"> <c-input type="textarea" v-model="formData['bill of lading']['Port of Discharge']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="托运人的货物描述"> <!-- <c-input type="textarea" v-model="formData['bill of lading']['Shipper's description of goods']"></c-input> --> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="毛重"> <c-input type="textarea" v-model="formData['bill of lading']['GROSS WEIGHT']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="据称重量"> <c-input type="textarea" v-model="formData['bill of lading']['SAID TO WEIGH']"></c-input> </el-form-item> </c-col> </c-col> <!-- 海运货物证书 --> <c-col :span="24" v-if="formData.type === 'marine_cargo_certificate'"> <c-col :span="24"> <el-form-item label="证书号码"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Certificate Number']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="预约保险单编号"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Open Policy Number']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="帐号"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Account Number']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="被保险人"> <c-input type="textarea" v-model="formData['marine cargo certificate'].assured"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="保险金额"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Sum Insured']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="航次"> <c-input type="textarea" v-model="formData['marine cargo certificate'].voyage"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="参考编号"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Reference No']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="航班号"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Airline/Fight No']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="出发日期"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Departing on or about']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="达到日期"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Arrival on or about']"></c-input> </el-form-item> </c-col> <c-col :span="24"> <el-form-item label="空运单编号"> <c-input type="textarea" v-model="formData['marine cargo certificate']['Airway Bill No']"></c-input> </el-form-item> </c-col> </c-col> </el-form> </el-scrollbar> </div> </div> </el-dialog> </template> <script> import axios from 'axios' // import bill_of_ladingPdf from "~/assets/demo-files/bill_of_lading.pdf"; // import commercial_invoicePdf from "~/assets/demo-files/commercial_invoice.pdf"; // import marine_cargo_certificatePdf from "~/assets/demo-files/marine_cargo_certificate.pdf"; export default { name: "OcrRecognition", data() { return { show: false, fileName: "KZ3500220597AA-001.pdf", // fileUrl: "/invoice.pdf", // fileUrl: require("~/assets/demo-files/bill_of_lading.jpg"), fileUrl: require("~/assets/demo-files/commercial_invoice.jpg"), // fileUrl: require("~/assets/demo-files/marine_cargo_certificate.jpg"), imgContainerHeight: 0, fileType: [ { label: "商业发票", value: "commercial_invoice" }, { label: "提货单", value: "bill_of_lading" }, { label: "海运货物证书", value: "marine_cargo_certificate" }, ], invoicesOriginalOptions: [ { label: "是", value: 1 }, { label: "否", value: 0 }, ], formData: { type: 'commercial_invoice', "commercial invoice": { 'Date': '', 'TOTAL CONTRACT VALUE': "", original: 1 }, "bill of lading": { "Shipper": '', "Consignee": '', "Notify address": '', "Vessel": '', "Port of Loading": '', "Port of Discharge": '', "Shipper's description of goods": '', "GROSS WEIGHT": '', "SAID TO WEIGH": '' }, "marine cargo certificate": { "Certificate Number": '', "Open Policy Number": '', "Account Number": '', assured: '', "Sum Insured": '', voyage: '', "Reference No": '', "Airline/Fight No": '', "Departing on or about": '', "Arrival on or about": '', "Airway Bill No": '' } } }; }, watch: { show(newVal, oldVal) { if (!this.imgContainerHeight) { if (newVal) { this.$nextTick(() => { const ele = this.$el.querySelector( ".invoices-recognition .invoices-area .pdf-file" ); this.imgContainerHeight = ele.clientHeight; }); } } }, }, methods: { save() { this.$emit("confirm"); this.close(); }, close() { this.show = false; }, fileTypeChangeEvent(val) { this.fileUrl = require(`~/assets/demo-files/${val}.jpg`) }, ocr() { const image = new Image(); image.crossOrigin = 'Anonymous'; image.src = this.fileUrl; image.onload = () => { const canvas = document.createElement('canvas') canvas.width = image.width canvas.height = image.height const ctx = canvas.getContext('2d') ctx.drawImage(image, 0, 0, image.width, image.height) var dataURL = canvas.toDataURL('image/jpeg')// base64 格式 var blob = this.dataURItoBlob(dataURL) //转二进制 const file = new File([blob], `${this.formData.type}.jpg`, { type: blob.type }) const formData = new FormData(); formData.append('mode', 'formdata'); formData.append('the_file', file) const loading = this.$parent.root.loading("正在识别中...") axios.post('/ocr/mockfile', formData, { 'Content-Type': 'multipart/form-data' }).then(res => { const data = res.data if (data.code === 200) { this.updateFormData(data.data) } else { this.$message.error(`识别失败:${data.data.err}`); } loading.close() }).catch(error => { loading.close() }) } }, dataURItoBlob (dataURI) { const arr = dataURI.split(',') // const mimeString = arr[0].match(/:(.*?);/)[0]; const mimeString = arr[0].split(':')[1].split(';')[0]; // base64 解码 const byteString = window.atob(arr[1]); const ab = new ArrayBuffer(byteString.length); const ia = new Uint8Array(ab); for (let i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ab], {type: mimeString}); }, updateFormData(data) { this.formData[data.template_name] = Object.assign(this.formData[data.template_name], data.ocr_text) } }, }; </script> <style> .ocr-invoices-dialog { height: 85%; display: flex; flex-direction: column; margin-bottom: unset; } .ocr-invoices-dialog .el-dialog__header, .ocr-invoices-dialog .el-dialog__body { padding: 0; } .ocr-invoices-dialog .el-dialog__body { flex: 1; } .ocr-invoices-dialog .el-scrollbar__wrap { overflow-x: auto; } </style> <style scoped> .ocr-title { display: flex; justify-content: space-between; padding: 5px 10px 5px 20px; border-bottom: 1px solid #dadbdd; } .invoices-recognition { height: 100%; display: flex; background-color: #f6fbff; padding: 20px; box-sizing: border-box; } .invoices-area { height: 100%; width: 50%; border-right: 1px solid #babec1; box-sizing: border-box; display: flex; flex-direction: column; padding: 0 10px; overflow: hidden; } .recognition-area { height: 100%; width: 50%; border-left: 1px solid #babec1; box-sizing: border-box; } .invoices-area .file-name { padding-bottom: 10px; text-align: center; } .invoices-area .pdf-file { flex: 1; } </style>