admin
2024-04-24 363457b34e0e4f26ffe51aa80ecb227bf7873308
提交 | 用户 | 时间
363457 1 <template>
A 2   <div class="upload-file">
3     <el-upload
4       multiple
5       :action="uploadFileUrl"
6       :before-upload="handleBeforeUpload"
7       :file-list="fileList"
8       :limit="limit"
9       :on-error="handleUploadError"
10       :on-exceed="handleExceed"
11       :on-success="handleUploadSuccess"
12       :show-file-list="false"
13       :headers="headers"
14       class="upload-file-uploader"
15       ref="fileUpload"
16     >
17       <!-- 上传按钮 -->
18       <el-button size="mini" type="primary">选取文件</el-button>
19       <!-- 上传提示 -->
20       <div class="el-upload__tip" slot="tip" v-if="showTip">
21         请上传
22         <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
23         <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
24         的文件
25       </div>
26     </el-upload>
27
28     <!-- 文件列表 -->
29     <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
30       <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
31         <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
32           <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
33         </el-link>
34         <div class="ele-upload-list__item-content-action">
35           <el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
36         </div>
37       </li>
38     </transition-group>
39   </div>
40 </template>
41
42 <script>
43 import { getToken } from "@/utils/auth";
44
45 export default {
46   name: "FileUpload",
47   props: {
48     // 值
49     value: [String, Object, Array],
50     // 数量限制
51     limit: {
52       type: Number,
53       default: 5,
54     },
55     // 大小限制(MB)
56     fileSize: {
57       type: Number,
58       default: 5,
59     },
60     // 文件类型, 例如['png', 'jpg', 'jpeg']
61     fileType: {
62       type: Array,
63       default: () => ["doc", "xls", "ppt", "txt", "pdf"],
64     },
65     // 是否显示提示
66     isShowTip: {
67       type: Boolean,
68       default: true
69     }
70   },
71   data() {
72     return {
73       number: 0,
74       uploadList: [],
75       baseUrl: process.env.VUE_APP_BASE_API,
76       uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传文件服务器地址
77       headers: {
78         Authorization: "Bearer " + getToken(),
79       },
80       fileList: [],
81     };
82   },
83   watch: {
84     value: {
85       handler(val) {
86         if (val) {
87           let temp = 1;
88           // 首先将值转为数组
89           const list = Array.isArray(val) ? val : this.value.split(',');
90           // 然后将数组转为对象数组
91           this.fileList = list.map(item => {
92             if (typeof item === "string") {
93               item = { name: item, url: item };
94             }
95             item.uid = item.uid || new Date().getTime() + temp++;
96             return item;
97           });
98         } else {
99           this.fileList = [];
100           return [];
101         }
102       },
103       deep: true,
104       immediate: true
105     }
106   },
107   computed: {
108     // 是否显示提示
109     showTip() {
110       return this.isShowTip && (this.fileType || this.fileSize);
111     },
112   },
113   methods: {
114     // 上传前校检格式和大小
115     handleBeforeUpload(file) {
116       // 校检文件类型
117       if (this.fileType) {
118         const fileName = file.name.split('.');
119         const fileExt = fileName[fileName.length - 1];
120         const isTypeOk = this.fileType.indexOf(fileExt) >= 0;
121         if (!isTypeOk) {
122           this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
123           return false;
124         }
125       }
126       // 校检文件大小
127       if (this.fileSize) {
128         const isLt = file.size / 1024 / 1024 < this.fileSize;
129         if (!isLt) {
130           this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
131           return false;
132         }
133       }
134       this.$modal.loading("正在上传文件,请稍候...");
135       this.number++;
136       return true;
137     },
138     // 文件个数超出
139     handleExceed() {
140       this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
141     },
142     // 上传失败
143     handleUploadError(err) {
144       this.$modal.msgError("上传文件失败,请重试");
145       this.$modal.closeLoading();
146     },
147     // 上传成功回调
148     handleUploadSuccess(res, file) {
149       if (res.code === 200) {
150         this.uploadList.push({ name: res.fileName, url: res.fileName });
151         this.uploadedSuccessfully();
152       } else {
153         this.number--;
154         this.$modal.closeLoading();
155         this.$modal.msgError(res.msg);
156         this.$refs.fileUpload.handleRemove(file);
157         this.uploadedSuccessfully();
158       }
159     },
160     // 删除文件
161     handleDelete(index) {
162       this.fileList.splice(index, 1);
163       this.$emit("input", this.listToString(this.fileList));
164     },
165     // 上传结束处理
166     uploadedSuccessfully() {
167       if (this.number > 0 && this.uploadList.length === this.number) {
168         this.fileList = this.fileList.concat(this.uploadList);
169         this.uploadList = [];
170         this.number = 0;
171         this.$emit("input", this.listToString(this.fileList));
172         this.$modal.closeLoading();
173       }
174     },
175     // 获取文件名称
176     getFileName(name) {
177       // 如果是url那么取最后的名字 如果不是直接返回
178       if (name.lastIndexOf("/") > -1) {
179         return name.slice(name.lastIndexOf("/") + 1);
180       } else {
181         return name;
182       }
183     },
184     // 对象转成指定字符串分隔
185     listToString(list, separator) {
186       let strs = "";
187       separator = separator || ",";
188       for (let i in list) {
189         strs += list[i].url + separator;
190       }
191       return strs != '' ? strs.substr(0, strs.length - 1) : '';
192     }
193   }
194 };
195 </script>
196
197 <style scoped lang="scss">
198 .upload-file-uploader {
199   margin-bottom: 5px;
200 }
201 .upload-file-list .el-upload-list__item {
202   border: 1px solid #e4e7ed;
203   line-height: 2;
204   margin-bottom: 10px;
205   position: relative;
206 }
207 .upload-file-list .ele-upload-list__item-content {
208   display: flex;
209   justify-content: space-between;
210   align-items: center;
211   color: inherit;
212 }
213 .ele-upload-list__item-content-action .el-link {
214   margin-right: 10px;
215 }
216 </style>