element ui 二次封装上传附件的组件

因为element ui 上传组件的代码很长,在项目中关于上传的代码过于冗余,因此我二次封装了一个上传附件的组件:

项目中使用:

 1       <!-- 附件 -->
 2       <el-form-item label="附件信息" prop="accessory" style="position: relative" class="ml30">
 3         <e-upload
 4           v-model="accessory"
 5           :limit="3"
 6           :acceptData="{ maxsize: 50 * 1024 * 1024 }"
 7           accept=".doc,.docx,.xls,.xlsx,.pdf"
 8           @change="onFileChange"
 9         >
10         </e-upload>
11         <span class="tip">(注:支持word、pdf、excel,单个文件大小不超过50M,最多上传3个文件)</span>
12       </el-form-item>
1   onFileChange(fileList) { // 该方法就可以拿到当前组件上传的文件数据
2       this.model.accessory = JSON.stringify(fileList)
3    }

 

注册组件 src/components/index.js:

1  import EUpload from './EUpload'
2  export default {
3    install(Vue) {
4      Vue.component('EUpload', EUpload)
5    }
6  }

 

main.js引入自定义组件:

 import Components from '@/components/index'
 Vue.use(Components)

 

 

组件 EUpload.vue 全部代码:

  1 <template>
  2   <!-- 上传附件组件,上传完后支持点击下载 -->
  3   <div>
  4     <el-upload
  5       :action="uploadApi()"
  6       :data="acceptData"
  7       :limit="limit"
  8       multiple
  9       :accept="accept"
 10       :file-list="fileList"
 11       :on-exceed="handleExceed"
 12       :on-success="(response, file, fileList) => handleSuccess(response, file, fileList)"
 13       :before-upload="file => beforeUpload(file)"
 14     >
 15       <el-button size="small" type="primary">点击上传</el-button>
 16       <!-- 通过插槽定义方法 -->
 17       <div slot="file" slot-scope="{ file }">
 18         <a class="el-upload-list__item-name"  @click="handleDownLoad(file)"> <i class="el-icon-document"></i>{{ file.name }} </a>
 19         <i class="el-icon-close" @click.stop="handleRemove(file)"></i>
 20         <i class="el-icon-close-tip">按 delete 键可删除</i>
 21       </div>
 22     </el-upload>
 23   </div>
 24 </template>
 25 
 26 <script>
 27 const uidGenerator = () => {
 28   return '-' + parseInt(Math.random() * 10000 + 1, 10)
 29 }
 30 
 31 export default {
 32   name: 'EUpload',
 33   props: {
 34     value: {
 35       type: [String, Array],
 36       required: false
 37     },
 38     // 文件类型
 39     accept: {
 40       type: String,
 41       default: '.doc,.docx,.xls,.xlsx,.pdf'
 42     },
 43     // 上传时附带的额外参数
 44     acceptData: {
 45       type: Object,
 46       default: () => {
 47         return {
 48           maxsize: 1024 * 1024 * 20, // 限制文件大小
 49           maxsize_text: '20M', // 上传文件超过大小时的提示语
 50           disabledDownload: false,
 51           disabledRemove: false
 52         }
 53       }
 54     },
 55     // 提示
 56     tip: {
 57       type: String,
 58       default: ''
 59     },
 60     // 最大数量
 61     limit: {
 62       type: Number,
 63       default: 10
 64     } 67   },
 68   watch: {
 69     value: { // 编辑/详情时,回显触发,生成业务可以下载的 url
 70       handler(val, oldValue) {
 71         this.initFileList(val)
 72       },
 73       // 立刻执行handler
 74       immediate: true
 75     }
 76   },
 77   data() {
 78     return {
 79       fileList: []
 80     }
 81   },
 82 methods: {
 83     // 将业务数据回显给组件
 84     initFileList(array) {
 85       if (!array || array.length == 0) {
 86         this.fileList = []
 87         return
 88       }
 89       let fileList = []
 90       let arr = array
 91       for (let a = 0; a < arr.length; a++) {
 92         let url = this.getFileAccessHttpUrl(arr[a].filePath) // 生成业务中支持下载的文件路径,该方法可根据项目不同进行修改
 93         fileList.push({
 94           uid: uidGenerator(),
 95           name: arr[a].fileName,
 96           status: 'done',
 97           url: url,
 98           response: {
 99             status: 'history',
100             message: url
101           }
102         })
103       }
104       this.fileList = fileList
105     },
106     // 添加前缀, /dispatch 是项目中支持点击下载的文件前缀,需要加上
107     getFileAccessHttpUrl(url) {
108       if (url.indexOf('/dispatch') > -1) {
109         return url
110       } else {
111         return '/dispatch' + url
112       }
113     },
114     // 上传文件地址
115     uploadApi() {
116       return '/dispatch/upload'
117     },
118     // 文件大小限制
119     beforeUpload(file) {
120       const isLessThanMaxSize = file.size < this.acceptData.maxsize
121       if (!isLessThanMaxSize) {
122         this.$toast(`上传文件大小不能超过${this.acceptData.maxsize_text}!`)
123       }
124       return isLessThanMaxSize
125     },
126     // 文件个数限制
127     handleExceed() {
128       this.$toast(`当前限制最多上传 ${this.limit} 个文件!`)
129     },
130     // 上传成功
131     handleSuccess(response, file, fileList) {
132       if (response.code == 200) {
133         this.$toast('上传成功')
134         let attachment = fileList.map(item => {
135           let url = ''
136           if (item.status === 'success' && item.response) {
137             url = item.response.data || ''
138           } else {
139             if (item.url) {
140               url = item.url || ''
141             }
142           }
143           return { name: item.name, url: url, uid: item.uid }
144         })
145         this.fileList = JSON.parse(JSON.stringify(attachment))
146         attachment = attachment.map(item => {
147           return {
148             fileName: item.name,
149             filePath: item.url,
150             uid: item.uid
151           }
152         })
153         // 回显给业务
154         this.$emit('change', attachment)
155       }
156     },
157     // 删除
158     handleRemove(file) {
159       let index
160       this.fileList.find((item, idx) => {
161         if (item.uid === file.uid) {
162           index = idx
163           return
164         }
165       })
166       if (typeof index !== 'undefined') {
167         this.fileList.splice(index, 1)
168       }
169       // 回显给业务
170       this.$emit('change', this.fileList)
171     },
172 // 点击下载文件 173     handleDownLoad(item) { 174       const uploadUrl = process.env.VUE_APP_DOWNLOAD_URL + this.getFileAccessHttpUrl(item.url) 175       if (this.isAndroid() && window.android) { // 移动端下载方法 176         window.android.updateFile(uploadUrl, item.name) 177       } else { 178         window.location.href = uploadUrl 179       } 180     }, 181 // 判断机型是android 182     isAndroid() { 183       const u = navigator.userAgent 184       const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1 // 判断android 185       return isAndroid 186     } 187   } 188 } 189 </script>

 

 

posted @ 2022-09-27 17:43  我就尝一口  阅读(291)  评论(0编辑  收藏  举报