封装element-upload上传+预览+ocr识别
需求:上传身份证反面识别后返回父组件,图片以base64格式传值后端
html:

<div class="component-upload-image"> <el-upload :ref="UploadImg.ref" :key="UploadImg.key" multiple action="#" list-type="picture-card" :http-request="(file)=>{return handleUploadSuccess(file,UploadImg.key)}" :before-upload="handleBeforeUpload" :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed" name="file" :on-remove="(file, fileList)=>{return handleRemove(file, fileList,UploadImg.key)}" :show-file-list="true" :file-list="fileList" :on-preview="(file)=>{return handlePictureCardPreview(file,UploadImg.key)}" :class="{ocrUpload:true, hide: this.fileList.length >= this.limit } " :style="{width:UploadImg.width,height:UploadImg.height,maxWidth:UploadImg.maxWidth,maxHeight:UploadImg.maxHeight}" > <img v-if="fileList.length==0" slot="default" class="oldImg" :src="UploadImg.imgDefault"> </el-upload> <!-- 上传提示 --> <div v-if="showTip" slot="tip" class="el-upload__tip"> 请上传 <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template> <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template> 的文件 </div> <el-dialog :visible.sync="dialogVisible" :title="dialogImageTitle" width="800" append-to-body > <img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" > </el-dialog> </div>
引入图片压缩工具和ocr识别接口

import { compress } from '@/utils/compressImg'
import { ocrIdentify } from '@/api/ocr'

let _this export default { props: { value: [String, Object, Array], // 图片数量限制 limit: { type: Number, default: 1 }, // 大小限制(MB) fileSize: { type: Number, default: 5 }, // 文件类型, 例如['png', 'jpg', 'jpeg'] fileType: { type: Array, default: () => ['png', 'jpg', 'jpeg', 'bmp'] }, // 是否显示提示 isShowTip: { type: Boolean, default: false }, UploadImg: { type: Object, default: () => {} }, UploadImgList: { type: Array, default: () => [] } }, data() { return { dialogImageUrl: '', dialogImageTitle: '预览', dialogVisible: false, hideUpload: false, fileList: [], ocrFile: {}, previewUrl: '', UploadObj: {} } }, computed: { // 是否显示提示 showTip() { return this.isShowTip && (this.fileType || this.fileSize) } }, watch: { UploadImg: { handler(val) { if (val.imgBase) { const list = [{ name: val.ref, url: val.imgBase }] this.fileList = [...list] } else { this.fileList = [] return [] } }, deep: true, immediate: true } }, beforeCreate: function() { _this = this }, methods: { // 删除图片 handleRemove(file, fileList, index) { const findex = this.fileList.map(f => f.name).indexOf(file.name) if (findex > -1) { this.fileList.splice(findex, 1) this.$emit('imgbase64data', { ... _this.UploadImgList[index], ...{ Base64Url: null, data: {}, uploadType: 'M' }}) } }, // 上传成功回调 handleUploadSuccess(param, index) { this.$modal.loading('正在上传图片,请稍候...') const reader = new FileReader() reader.onload = function() { const result = this.result // 图片base64字符串--压缩 compress(result, 1000, 0.8).then(function(val) { _this.UploadObj = { ...param, ... _this.UploadImgList[index], ...{ Base64Url: val }} // OCR识别 if (_this.UploadImgList[index].type === 'OCR') { const params = { data: { image: val }, ocrType: 3 } ocrIdentify(params).then(response => { _this.$emit('imgbase64data', { ... _this.UploadObj, ...{ data: response, uploadType: 'A' }}) }).catch((err) => { _this.$emit('imgbase64data', { ... _this.UploadObj, ...{ Base64Url: null, data: {}, uploadType: 'M' }}) }) } else { _this.$emit('imgbase64data', { ... _this.UploadObj, ...{ data: {}, uploadType: 'A' }}) } // 回显 // _this.fileList = [...[{ name: _this.UploadObj.file.name, url: _this.UploadObj.Base64Url }]] setTimeout(()=>{ _this.$modal.closeLoading() },1000) }) } reader.readAsDataURL(param.file) // Base64 }, // 上传前loading加载 handleBeforeUpload(file) { let isImg = false if (this.fileType.length) { let fileExtension = '' if (file.name.lastIndexOf('.') > -1) { fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1) } isImg = this.fileType.some(type => { if (file.type.indexOf(type) > -1) return true if (fileExtension && fileExtension.indexOf(type) > -1) return true return false }) } else { isImg = file.type.indexOf('image') > -1 } if (!isImg) { this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join('/')}图片格式文件!`) return false } if (this.fileSize) { const isLt = file.size / 1024 / 1024 < this.fileSize if (!isLt) { this.$modal.msgError(`上传图片大小不能超过 ${this.fileSize} MB!`) return false } } }, // 文件个数超出 handleExceed() { this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`) }, // 上传失败 handleUploadError() { this.$modal.msgError('上传图片失败,请重试') this.$modal.closeLoading() }, // 预览 handlePictureCardPreview(file, index) { this.dialogImageUrl = file.url this.dialogImageTitle = this.UploadImgList[index].title || '预览' this.dialogVisible = true } } }
部分样式:

1 <style scoped lang="scss"> 2 // .el-upload--picture-card 控制加号部分 3 ::v-deep.hide .el-upload--picture-card { 4 display: none; 5 } 6 // 去掉动画效果 7 ::v-deep .el-list-enter-active, 8 ::v-deep .el-list-leave-active { 9 transition: all 0s; 10 } 11 12 ::v-deep .el-list-enter, .el-list-leave-active { 13 opacity: 0; 14 transform: translateY(0); 15 } 16 </style> 17 <style lang="scss"> 18 .ocrUpload{ 19 .el-upload,.is-success{ 20 max-width: 320px; 21 max-height: 208px; 22 width:100% !important; 23 height: 100% !important; 24 line-height: 0 !important; 25 border: none; 26 img{ 27 width:100%; 28 border-radius: 6px !important; 29 } 30 } 31 .el-upload-list--picture-card .el-upload-list__item{ 32 border: none !important;; 33 } 34 } 35 </style>
效果图:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!