前言
大家好,我是yma16,本文分享二次封装a-upload组件,自定义上传预览。
效果
编辑
预览
不展示删除和上传
空数据
自定义图片样式
vue2 引入 andesign
要在Vue2中引入Ant Design,需要遵循以下步骤:
- 安装Ant Design Vue
使用npm或者yarn安装Ant Design Vue:
npm install ant-design-vue --save
或
yarn add ant-design-vue
- 引入Ant Design Vue
在Vue应用程序的入口文件中,你需要引入Ant Design Vue的主题文件以及CSS文件:
import Vue from 'vue'; import Antd from 'ant-design-vue'; import 'ant-design-vue/dist/antd.css'; Vue.use(Antd);
- 使用Ant Design Vue组件
现在你可以在Vue组件中使用Ant Design Vue组件了,例如:
<template> <a-button type="primary">Primary Button</a-button> </template> <script> export default { name: 'MyComponent' } </script>
这样就可以在Vue2中使用Ant Design Vue了。
自定义上传customRequest
入参是本地上传的文件流
async customRequest(file) { const form = new FormData() form.append('file', file.file) form.append('name', file.name) try { this.uploadLoading = true const res = await postAction(this.uploadActionUrl, form) if (res.success) { this.picUrl = true const length = this.fileList.length const url = getFileAccessHttpUrl(res.message) const type = res.message ? res.message.split('.')[res.message.split('.').length - 1] : 'null' const addFile = { uid: new Date().valueOf(), type: type, name: this.renderDisplayName(file.file.name), status: 'done', response: { status: 'done', message: res.message, }, url: url, message: res.message, index: length, } this.fileList.push(addFile) this.$message.success('上传成功') this.$emit('change', this.fileList.map((item) => item.message).join(',')) } else { this.$message.error('上传失败') } this.uploadLoading = false } catch (r) { this.uploadLoading = false this.$message.error('上传失败') console.warn(r) } }
transformFile上传前修改文件流
入参是本地上传的文件流
这里我修改文件流的名称,返回file的promise
transformFile(file) { return new Promise((resolve) => { const currentTime = new Date() const type = file.type.split('/') const renameFile = new File([file], currentTime.valueOf() + '.' + type[1], { type: file.type }) resolve(renameFile) }) }
自定义预览
handlePreview(file) { return new Promise((resolve, reject) => { try { resolve(this.previewFile(file)) } catch (r) { reject(r) } }) },
调整props和a-uoload一致
<template> <div style="display: inline-block"> <div> <a-upload name="file" :accept="accept" :multiple="isMultiple" :disabled="disabled" :headers="headers" :fileList="[]" :customRequest="customRequest" :beforeUpload="beforeUpload" :remove="handleDelete" :transformFile="transformFile" > <a-button :loading="uploadLoading" v-if="!disabled && isMultiple && fileList.length < limit"> <a-icon type="upload" /> {{text}} </a-button> </a-upload> <template v-if="fileList.length"> <div v-for="(item, index) in fileList" :key="index" class="file-list-box"> <img v-if="isImg(item.type)" :src="item.url" class="upload-icon-view" /> <a-icon v-else-if="isPdf(item.type)" class="upload-icon-view" type="file" /> <a-tooltip :title="item.name"> <span class="upload-name-view">{{ item.name }}</span> </a-tooltip> <a-tooltip title="预览"> <span style="color: #0071fc; margin: 0 20px"><a-icon type="eye" @click="handlePreview(item)" /></span> </a-tooltip> <a-tooltip title="删除"> <span style="color: #f5222d" v-if="!disabled"><a-icon type="delete" @click="handleDelete(item)" /></span> </a-tooltip> </div> </template> <template v-else-if="disabled"> <div style="text-align: left"> <img :src="require('@/assets/gaoxinImgs/null-content.png')" alt="暂无数据" style="max-width: 100px" /> <p style="text-align: center; width: 100px">暂无数据</p> </div> </template> </div> <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel"> <img alt="图片" style="width: 100%; height: 100%" :src="previewImage" /> </a-modal> </div> </template> <script> import Vue from 'vue' import { ACCESS_TOKEN } from '@/store/mutation-types' import { postAction, getFileAccessHttpUrl, getAction } from '@/api/manage' const uidGenerator = () => { return '-' + parseInt(Math.random() * 10000 + 1, 10) } const getFileName = (path) => { if (path.lastIndexOf('\\') >= 0) { let reg = new RegExp('\\\\', 'g') path = path.replace(reg, '/') } return path.substring(path.lastIndexOf('/') + 1) } export default { name: 'JFileUpload', data() { return { url: window._CONFIG['pdfDomainURL'], staticUrl: window._CONFIG['pdfPreviewURL'], id: 'pdfFilePreviewIframeId', fileName: '', uploadAction: window._CONFIG['domianURL'] + '/sys/common/upload', uploadActionUrl: '/sys/common/upload', uploadLoading: false, picUrl: false, headers: {}, token: {}, fileList: [], previewImage: '', previewVisible: false, } }, props: { accept: { type: String, default: () => 'image/*,.pdf', }, limit: { type: Number, default: 10, }, text: { type: String, required: false, default: '上传附件(图片、pdf)', }, /*这个属性用于控制文件上传的业务路径*/ bizPath: { type: String, required: false, default: 'temp', }, value: { type: [String, Array], required: false, }, disabled: { type: Boolean, required: false, default: false, }, isMultiple: { type: Boolean, required: false, default: true, }, }, watch: { value: { deep: true, handler(val) { this.initFile(val) }, }, }, created() { const token = Vue.ls.get(ACCESS_TOKEN) this.token = token this.headers = { 'X-Access-Token': token } this.initFile(this.value) }, methods: { initFile(val) { if (val instanceof Array) { this.initFileList(val.join(',')) } else { this.initFileList(val) } }, isWord(fileType) { const wordTypeArray = ['doc', 'docx'] const isWord = wordTypeArray.some((type) => { return fileType.toString().toUpperCase().includes(type.toString().toUpperCase()) }) return isWord }, isExcel(fileType) { const excelTypeArray = ['XLS', 'XLSX', 'XLSB', 'XLSM', 'XLST', 'sheet'] const isExcel = excelTypeArray.some((type) => { return fileType.toString().toUpperCase().includes(type.toString().toUpperCase()) }) return isExcel }, isImg(fileType) { const imgTypeArray = ['BMP', 'JPG', 'JPEG', 'PNG', 'GIF'] const isImgType = imgTypeArray.some((type) => { return fileType.toString().toUpperCase().includes(type.toString().toUpperCase()) }) return isImgType }, isPdf(fileType) { const pdfTypeArray = ['PDF'] const isPdfType = pdfTypeArray.some((type) => { return fileType.toString().toUpperCase().includes(type.toString().toUpperCase()) }) return isPdfType }, renderDisplayName(name) { return name }, async customRequest(file) { const form = new FormData() form.append('file', file.file) form.append('biz', this.bizPath) try { this.uploadLoading = true const res = await postAction(this.uploadActionUrl, form) if (res.success) { this.picUrl = true const length = this.fileList.length const url = getFileAccessHttpUrl(res.message) const type = res.message ? res.message.split('.')[res.message.split('.').length - 1] : 'null' const addFile = { uid: uidGenerator(), type: type, name: this.renderDisplayName(file.file.name), status: 'done', response: { status: 'done', message: res.message, }, url: url, message: res.message, index: length, } this.fileList.push(addFile) this.$message.success('上传成功') this.$emit('change', this.fileList.map((item) => item.message).join(',')) } else { this.$message.error('上传失败') } this.uploadLoading = false } catch (r) { this.uploadLoading = false this.$message.error('上传失败') console.warn(r) } }, transformFile(file) { return new Promise((resolve) => { const currentTime = new Date() const type = file.type.split('/') const renameFile = new File([file], currentTime.valueOf() + '.' + type[1], { type: file.type }) resolve(renameFile) }) }, previewPdf(file) { const prefixUrl = this.staticUrl const path = file.response.message const fileUrl = prefixUrl + path return getAction(`/mybiz/myfile/preview/${fileUrl}`).then((previewUrl) => { if (previewUrl.toString().indexOf('http://') === 0) { const page = window.open(previewUrl) console.warn('page', page) } else { const page = window.open('http://' + previewUrl) console.warn('page', page) } }) }, previewImg(file) { this.previewImage = file.url this.previewVisible = true }, previewExcel(file) { console.log('previewExcel', file) // 创建blob对象,解析流数据 }, previewFile(file) { const fileType = file.type console.log('fileType', fileType) if (this.isImg(fileType)) { return this.previewImg(file) } else { return this.previewPdf(file) } }, initFileList(paths) { this.fileList = [] if (!paths || paths.length === 0) { return 0 } paths.split(',').forEach((item, index) => { const url = getFileAccessHttpUrl(item) const name = getFileName(item) const type = name && name.split('.').length ? name.split('.')[name.split('.').length - 1] : 'null' this.fileList.push({ uid: uidGenerator(), name: this.renderDisplayName(name), type: type, status: 'done', url: url, response: { status: 'history', message: item, }, message: item, index: index, }) }) }, beforeUpload(file) { console.log('file', file) const fileType = file.name.split('.')[file.name.split('.').length - 1] // console.log('fileType', fileType) if (!this.isImg(fileType) && !this.isPdf(fileType)) { this.$message.warning('请上传图片或PDF') return false } }, // 自定义预览 handlePreview(file) { return new Promise((resolve, reject) => { try { resolve(this.previewFile(file)) } catch (r) { reject(r) } }) }, handleDelete(file) { this.fileList = this.fileList.filter((item) => item.uid!== file.uid) }, handleCancel() { this.close() }, close() { this.previewImage = '' this.previewVisible = false }, }, model: { prop: 'value', event: 'change', }, } </script> <style scoped> .upload-name-view { max-width: 80px; white-space: nowrap; text-overflow: ellipsis; } .upload-icon-view { position: relative; max-height: 48px; min-height: 48px; font-size: 32px; padding: 2px 10px 2px 2px; color: #0071fc; } .after-icon { line-height: 48px; } .file-list-box { position: relative; height: 66px; line-height: 48px; padding: 8px; border: 1px solid #d9d9d9; border-radius: 4px; margin-top: 10px; width: fit-content; } </style>
install封装vue组件
抛出去install在入口调用即可
import JFileUpload from './JFileUpload.vue' export default { install(Vue) { Vue.component(JFileUpload.name, JFileUpload) }, }
结束
本文分享到这结束,如有错误或者不足之处欢迎指出,感谢大家的阅读!