OcrRecognition.vue 13.5 KB
Newer Older
潘际乾 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
<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;">
潘际乾 committed
24
              <el-image :src="fileUrl" @load="ocr" alt="单据" style="display: block;"></el-image>
潘际乾 committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
            </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="发票日期">
潘际乾 committed
52
                  <c-input type="textarea" v-model="formData['commercial invoice']['Date']"></c-input>
潘际乾 committed
53 54 55 56
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="发票金额">
潘际乾 committed
57
                  <c-input type="textarea" v-model="formData['commercial invoice']['TOTAL CONTRACT VALUE']"></c-input>
潘际乾 committed
58 59 60 61
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="是否正本">
潘际乾 committed
62
                  <c-select v-model="formData['commercial invoice'].original" style="width: 100%;">
潘际乾 committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76
                    <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="发货人">
潘际乾 committed
77
                  <c-input type="textarea" v-model="formData['bill of lading']['Shipper']"></c-input>
潘际乾 committed
78 79 80 81
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="收货人">
潘际乾 committed
82
                  <c-input type="textarea" v-model="formData['bill of lading']['Consignee']"></c-input>
潘际乾 committed
83 84 85 86
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="通知地址">
潘际乾 committed
87
                  <c-input type="textarea" v-model="formData['bill of lading']['Notify address']"></c-input>
潘际乾 committed
88 89 90 91
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="船舶">
潘际乾 committed
92
                  <c-input type="textarea" v-model="formData['bill of lading']['Vessel']"></c-input>
潘际乾 committed
93 94 95 96
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="装货港">
潘际乾 committed
97
                  <c-input type="textarea" v-model="formData['bill of lading']['Port of Loading']"></c-input>
潘际乾 committed
98 99 100 101
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="卸货港">
潘际乾 committed
102
                  <c-input type="textarea" v-model="formData['bill of lading']['Port of Discharge']"></c-input>
潘际乾 committed
103 104 105 106
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="托运人的货物描述">
潘际乾 committed
107
                  <!-- <c-input type="textarea" v-model="formData['bill of lading']['Shipper's description of goods']"></c-input> -->
潘际乾 committed
108 109 110 111
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="毛重">
潘际乾 committed
112
                  <c-input type="textarea" v-model="formData['bill of lading']['GROSS WEIGHT']"></c-input>
潘际乾 committed
113 114 115 116
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="据称重量">
潘际乾 committed
117
                  <c-input type="textarea" v-model="formData['bill of lading']['SAID TO WEIGH']"></c-input>
潘际乾 committed
118 119 120 121 122 123 124
                </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="证书号码">
潘际乾 committed
125
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Certificate Number']"></c-input>
潘际乾 committed
126 127 128 129
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="预约保险单编号">
潘际乾 committed
130
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Open Policy Number']"></c-input>
潘际乾 committed
131 132 133 134
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="帐号">
潘际乾 committed
135
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Account Number']"></c-input>
潘际乾 committed
136 137 138 139
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="被保险人">
潘际乾 committed
140
                  <c-input type="textarea" v-model="formData['marine cargo certificate'].assured"></c-input>
潘际乾 committed
141 142 143 144
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="保险金额">
潘际乾 committed
145
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Sum Insured']"></c-input>
潘际乾 committed
146 147 148 149
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="航次">
潘际乾 committed
150
                  <c-input type="textarea" v-model="formData['marine cargo certificate'].voyage"></c-input>
潘际乾 committed
151 152 153 154
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="参考编号">
潘际乾 committed
155
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Reference No']"></c-input>
潘际乾 committed
156 157 158 159
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="航班号">
潘际乾 committed
160
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Airline/Fight No']"></c-input>
潘际乾 committed
161 162 163 164
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="出发日期">
潘际乾 committed
165
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Departing on or about']"></c-input>
潘际乾 committed
166 167 168 169
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="达到日期">
潘际乾 committed
170
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Arrival on or about']"></c-input>
潘际乾 committed
171 172 173 174
                </el-form-item>
              </c-col>
              <c-col :span="24">
                <el-form-item label="空运单编号">
潘际乾 committed
175
                  <c-input type="textarea" v-model="formData['marine cargo certificate']['Airway Bill No']"></c-input>
潘际乾 committed
176 177 178 179 180 181 182 183 184 185 186
                </el-form-item>
              </c-col>
            </c-col>
          </el-form>
        </el-scrollbar>
      </div>
    </div>
  </el-dialog>
</template>

<script>
潘际乾 committed
187 188
import axios from 'axios'

潘际乾 committed
189 190 191
// 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";
潘际乾 committed
192 193 194 195 196 197 198 199

export default {
  name: "OcrRecognition",
  data() {
    return {
      show: false,
      fileName: "KZ3500220597AA-001.pdf",
      // fileUrl: "/invoice.pdf",
潘际乾 committed
200 201 202
      // 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"),
潘际乾 committed
203 204 205 206 207 208 209 210 211 212 213 214
      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',
潘际乾 committed
215 216 217
        "commercial invoice": {
          'Date': '',
          'TOTAL CONTRACT VALUE': "",
潘际乾 committed
218 219
          original: 1
        },
潘际乾 committed
220 221 222 223 224 225 226 227 228 229
        "bill of lading": {
          "Shipper": '',
          "Consignee": '',
          "Notify address": '',
          "Vessel": '',
          "Port of Loading": '',
          "Port of Discharge": '',
          "Shipper's description of goods": '',
          "GROSS WEIGHT": '',
          "SAID TO WEIGH": ''
潘际乾 committed
230
        },
潘际乾 committed
231 232 233 234 235 236 237 238 239 240 241 242
        "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": ''
潘际乾 committed
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
        }
      }
    };
  },
  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) {
潘际乾 committed
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
      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("正在识别中...")
liuxin committed
289
        axios.post('/ocr/mockfile', formData, {
潘际乾 committed
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
          '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)
潘际乾 committed
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
    }
  },
};
</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>