<template>
|
<div class="app-container">
|
<el-card class="box-card">
|
<div slot="header" class="clearfix">
|
<span>OCR图像识别测试</span>
|
</div>
|
|
<!-- 功能说明 -->
|
<el-alert
|
title="功能说明"
|
type="info"
|
:closable="false"
|
style="margin-bottom: 20px"
|
>
|
<div>
|
本页面用于测试阿里云OCR、百度OCR和腾讯云OCR图像识别功能。支持通用文字识别、发票识别、身份证识别、手写体识别等。<br/>
|
<strong>支持格式:</strong>JPG、PNG、BMP等常见图片格式;<strong>文件大小:</strong>不超过4MB
|
</div>
|
</el-alert>
|
|
<!-- 识别类型选择 -->
|
<el-form :inline="true" style="margin-bottom: 20px">
|
<el-form-item label="识别类型">
|
<el-select v-model="recognizeType" placeholder="请选择识别类型" style="width: 200px">
|
<el-option label="通用文字识别" value="General" />
|
<el-option label="发票识别" value="Invoice" />
|
<el-option label="身份证识别" value="IdCard" />
|
<el-option label="手写体识别" value="HandWriting" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="OCR服务">
|
<el-select v-model="provider" placeholder="请选择OCR服务提供商" style="width: 200px">
|
<el-option label="阿里云OCR" value="ali" />
|
<el-option label="百度OCR" value="baidu" />
|
<el-option label="腾讯云OCR" value="tencent" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="提取字段">
|
<el-input
|
v-if="provider === 'tencent' && recognizeType === 'HandWriting'"
|
v-model="itemNames"
|
placeholder="请输入需要提取的字段,用逗号分隔"
|
style="width: 200px"
|
clearable
|
/>
|
</el-form-item>
|
</el-form>
|
|
<!-- 图片上传区域 -->
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-card shadow="hover">
|
<div slot="header">
|
<span>图片上传</span>
|
</div>
|
|
<el-upload
|
ref="upload"
|
class="upload-demo"
|
drag
|
action="#"
|
:auto-upload="false"
|
:on-change="handleFileChange"
|
:limit="1"
|
:file-list="fileList"
|
accept="image/*"
|
>
|
<i class="el-icon-upload"></i>
|
<div class="el-upload__text">将图片拖到此处,或<em>点击上传</em></div>
|
<div class="el-upload__tip" slot="tip">
|
支持JPG、PNG、BMP格式,文件不超过4MB
|
</div>
|
</el-upload>
|
|
<div style="margin-top: 20px; text-align: center">
|
<el-button
|
type="primary"
|
:loading="recognizing"
|
:disabled="!fileList.length"
|
@click="handleRecognize"
|
>
|
<i class="el-icon-view"></i> 开始识别
|
</el-button>
|
<el-button @click="handleClear">
|
<i class="el-icon-delete"></i> 清空
|
</el-button>
|
</div>
|
|
<!-- 图片预览 -->
|
<div v-if="imagePreview" style="margin-top: 20px">
|
<el-divider>图片预览</el-divider>
|
<div style="text-align: center">
|
<el-image
|
:src="imagePreview"
|
fit="contain"
|
style="max-width: 100%; max-height: 400px"
|
:preview-src-list="[imagePreview]"
|
/>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
|
<!-- 识别结果区域 -->
|
<el-col :span="12">
|
<el-card shadow="hover" style="min-height: 500px">
|
<div slot="header">
|
<span>识别结果</span>
|
<el-button
|
v-if="ocrResult"
|
style="float: right; padding: 3px 0"
|
type="text"
|
@click="handleCopyResult"
|
>
|
<i class="el-icon-document-copy"></i> 复制结果
|
</el-button>
|
</div>
|
|
<!-- 加载中 -->
|
<div v-if="recognizing" style="text-align: center; padding: 50px 0">
|
<i class="el-icon-loading" style="font-size: 40px; color: #409EFF"></i>
|
<p style="margin-top: 20px; color: #909399">正在识别中,请稍候...({{ provider === 'ali' ? '阿里云' : provider === 'baidu' ? '百度' : '腾讯云' }})</p>
|
</div>
|
|
<!-- 识别成功 -->
|
<div v-else-if="ocrResult && ocrResult.success">
|
<el-alert
|
title="识别成功"
|
type="success"
|
:closable="false"
|
style="margin-bottom: 15px"
|
>
|
<div>服务提供商: {{ provider === 'ali' ? '阿里云OCR' : provider === 'baidu' ? '百度OCR' : '腾讯云OCR' }}</div>
|
</el-alert>
|
|
<!-- 提取的字段信息 -->
|
<div v-if="extractedFields && Object.keys(extractedFields).length > 0">
|
<el-descriptions title="提取字段" :column="1" border>
|
<el-descriptions-item
|
v-for="(value, key) in extractedFields"
|
:key="key"
|
:label="getFieldLabel(key)"
|
>
|
{{ value }}
|
</el-descriptions-item>
|
</el-descriptions>
|
<el-divider />
|
</div>
|
|
<!-- 完整识别内容 -->
|
<div>
|
<h4>完整识别内容:</h4>
|
<el-input
|
type="textarea"
|
:value="getFullContent(ocrResult)"
|
:autosize="{ minRows: 10, maxRows: 20 }"
|
readonly
|
style="margin-top: 10px"
|
/>
|
</div>
|
|
<!-- 原始JSON数据 -->
|
<el-collapse style="margin-top: 20px">
|
<el-collapse-item title="查看原始JSON数据" name="json">
|
<pre style="background: #f5f7fa; padding: 15px; border-radius: 4px; max-height: 400px; overflow: auto">{{ JSON.stringify(ocrResult, null, 2) }}</pre>
|
</el-collapse-item>
|
</el-collapse>
|
</div>
|
|
<!-- 识别失败 -->
|
<div v-else-if="ocrResult && !ocrResult.success">
|
<el-alert
|
title="识别失败"
|
:description="ocrResult.error || '未知错误'"
|
type="error"
|
:closable="false"
|
>
|
<div>服务提供商: {{ provider === 'ali' ? '阿里云OCR' : provider === 'baidu' ? '百度OCR' : '腾讯云OCR' }}</div>
|
</el-alert>
|
<div v-if="ocrResult.detail" style="margin-top: 15px">
|
<el-tag type="warning">{{ ocrResult.detail }}</el-tag>
|
</div>
|
</div>
|
|
<!-- 未开始识别 -->
|
<div v-else style="text-align: center; padding: 50px 0; color: #909399">
|
<i class="el-icon-picture-outline" style="font-size: 60px"></i>
|
<p style="margin-top: 20px">请上传图片并点击"开始识别"按钮</p>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
</el-card>
|
</div>
|
</template>
|
|
<script>
|
import { recognizeImage, extractFields } from "@/api/system/ocr";
|
|
export default {
|
name: "OCRTest",
|
data() {
|
return {
|
// 识别类型
|
recognizeType: "General",
|
// OCR服务提供商
|
provider: "ali",
|
// 腾讯云OCR提取字段
|
itemNames: "患者姓名,性别,年龄,身份证号,诊断,需支付转运费用,行程,开始时间,结束时间,家属签名",
|
// 文件列表
|
fileList: [],
|
// 当前文件
|
currentFile: null,
|
// 图片预览
|
imagePreview: null,
|
// 识别中
|
recognizing: false,
|
// OCR识别结果
|
ocrResult: null,
|
// 提取的字段
|
extractedFields: null
|
};
|
},
|
methods: {
|
/** 文件选择变化 */
|
handleFileChange(file, fileList) {
|
// 限制只能上传一个文件
|
if (fileList.length > 1) {
|
fileList.splice(0, 1);
|
}
|
|
this.fileList = fileList;
|
this.currentFile = file.raw;
|
|
// 生成图片预览
|
const reader = new FileReader();
|
reader.onload = (e) => {
|
this.imagePreview = e.target.result;
|
};
|
reader.readAsDataURL(file.raw);
|
|
// 清空之前的识别结果
|
this.ocrResult = null;
|
this.extractedFields = null;
|
},
|
|
/** 开始识别 */
|
handleRecognize() {
|
if (!this.currentFile) {
|
this.$modal.msgWarning("请先上传图片");
|
return;
|
}
|
|
// 检查文件大小(4MB)
|
const maxSize = 4 * 1024 * 1024;
|
if (this.currentFile.size > maxSize) {
|
this.$modal.msgError("图片大小不能超过4MB");
|
return;
|
}
|
|
this.recognizing = true;
|
this.ocrResult = null;
|
this.extractedFields = null;
|
|
// 构建FormData
|
const formData = new FormData();
|
formData.append("file", this.currentFile);
|
formData.append("type", this.recognizeType);
|
formData.append("provider", this.provider);
|
|
// 如果是腾讯云OCR手写体识别,则添加itemNames参数
|
if (this.provider === 'tencent' && this.recognizeType === 'HandWriting' && this.itemNames) {
|
const itemNamesArray = this.itemNames.split(',').map(item => item.trim()).filter(item => item);
|
itemNamesArray.forEach((itemName, index) => {
|
formData.append(`itemNames[${index}]`, itemName);
|
});
|
}
|
|
// 调用OCR识别接口
|
recognizeImage(formData).then(response => {
|
this.ocrResult = response.data.ocrResult;
|
|
// 自动提取字段
|
if (this.ocrResult.success) {
|
extractFields(this.ocrResult).then(res => {
|
this.extractedFields = res.data;
|
}).catch(() => {
|
// 提取失败不影响主流程
|
});
|
}
|
|
this.recognizing = false;
|
}).catch(error => {
|
this.$modal.msgError("OCR识别失败: " + (error.message || "未知错误"));
|
this.recognizing = false;
|
});
|
},
|
|
/** 清空 */
|
handleClear() {
|
this.fileList = [];
|
this.currentFile = null;
|
this.imagePreview = null;
|
this.ocrResult = null;
|
this.extractedFields = null;
|
this.$refs.upload.clearFiles();
|
},
|
|
/** 复制识别结果 */
|
handleCopyResult() {
|
const content = this.getFullContent(this.ocrResult);
|
this.copyToClipboard(content);
|
this.$modal.msgSuccess("复制成功");
|
},
|
|
/** 复制到剪贴板 */
|
copyToClipboard(text) {
|
const textarea = document.createElement("textarea");
|
textarea.value = text;
|
document.body.appendChild(textarea);
|
textarea.select();
|
document.execCommand("copy");
|
document.body.removeChild(textarea);
|
},
|
|
/** 获取完整识别内容 */
|
getFullContent(ocrResult) {
|
if (!ocrResult) return "";
|
|
if (ocrResult.content) {
|
return ocrResult.content;
|
}
|
|
// 如果有prism_wordsInfo,拼接所有文字
|
if (ocrResult.prism_wordsInfo && Array.isArray(ocrResult.prism_wordsInfo)) {
|
return ocrResult.prism_wordsInfo.map(item => item.word).join("\n");
|
}
|
|
return JSON.stringify(ocrResult, null, 2);
|
},
|
|
/** 获取字段标签 */
|
getFieldLabel(key) {
|
const labelMap = {
|
totalAmount: "总金额",
|
date: "日期",
|
remark: "备注",
|
fullText: "全文",
|
error: "错误信息"
|
};
|
return labelMap[key] || key;
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.box-card {
|
margin-bottom: 20px;
|
}
|
|
.upload-demo {
|
width: 100%;
|
}
|
|
.el-upload-dragger {
|
width: 100%;
|
}
|
|
pre {
|
font-family: 'Courier New', Courier, monospace;
|
font-size: 12px;
|
line-height: 1.5;
|
white-space: pre-wrap;
|
word-wrap: break-word;
|
}
|
|
.el-descriptions {
|
margin-top: 10px;
|
}
|
|
h4 {
|
margin: 15px 0 10px 0;
|
color: #303133;
|
}
|
</style>
|