houzhongjian
2024-07-11 759b1c71011abd6b58c37d2566f3f3c208c2f1b2
提交 | 用户 | 时间
759b1c 1 <template>
H 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="`${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 { getAccessToken } 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 + "/admin-api/infra/file/upload", // 请求地址
77       headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部
78       fileList: [],
79     };
80   },
81   watch: {
82     value: {
83       handler(val) {
84         if (val) {
85           let temp = 1;
86           // 首先将值转为数组
87           const list = Array.isArray(val) ? val : this.value.split(',');
88           // 然后将数组转为对象数组
89           this.fileList = list.map(item => {
90             if (typeof item === "string") {
91               item = { name: item, url: item };
92             }
93             item.uid = item.uid || new Date().getTime() + temp++;
94             return item;
95           });
96         } else {
97           this.fileList = [];
98           return [];
99         }
100       },
101       deep: true,
102       immediate: true
103     }
104   },
105   computed: {
106     // 是否显示提示
107     showTip() {
108       return this.isShowTip && (this.fileType || this.fileSize);
109     },
110   },
111   methods: {
112     // 上传前校检格式和大小
113     handleBeforeUpload(file) {
114       // 校检文件类型
115       if (this.fileType) {
116         let fileExtension = "";
117         if (file.name.lastIndexOf(".") > -1) {
118           fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
119         }
120         const isTypeOk = this.fileType.some((type) => {
121           if (file.type.indexOf(type) > -1) return true;
122           if (fileExtension && fileExtension.indexOf(type) > -1) return true;
123           return false;
124         });
125         if (!isTypeOk) {
126           this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
127           return false;
128         }
129       }
130       // 校检文件大小
131       if (this.fileSize) {
132         const isLt = file.size / 1024 / 1024 < this.fileSize;
133         if (!isLt) {
134           this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
135           return false;
136         }
137       }
138       this.$modal.loading("正在上传文件,请稍候...");
139       this.number++;
140       return true;
141     },
142     // 文件个数超出
143     handleExceed() {
144       this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
145     },
146     // 上传失败
147     handleUploadError(err) {
148       this.$modal.msgError("上传图片失败,请重试");
149       this.$modal.closeLoading()
150     },
151     // 上传成功回调
152     handleUploadSuccess(res, file) {
153       if (res.code === 0) {
154         // edit by iailab
155         this.uploadList.push({ name: res.data, url: res.data });
156         this.uploadedSuccessfully();
157       } else {
158         this.number--;
159         this.$modal.closeLoading();
160         this.$modal.msgError(res.msg);
161         this.$refs.fileUpload.handleRemove(file);
162         this.uploadedSuccessfully();
163       }
164     },
165     // 删除文件
166     handleDelete(index) {
167       this.fileList.splice(index, 1);
168       this.$emit("input", this.listToString(this.fileList));
169     },
170     // 上传结束处理
171     uploadedSuccessfully() {
172       if (this.number > 0 && this.uploadList.length === this.number) {
173         this.fileList = this.fileList.concat(this.uploadList);
174         this.uploadList = [];
175         this.number = 0;
176         this.$emit("input", this.listToString(this.fileList));
177         this.$modal.closeLoading();
178       }
179     },
180     // 获取文件名称
181     getFileName(name) {
182       if (name.lastIndexOf("/") > -1) {
183         return name.slice(name.lastIndexOf("/") + 1);
184       } else {
185         return "";
186       }
187     },
188     // 对象转成指定字符串分隔
189     listToString(list, separator) {
190       let strs = "";
191       separator = separator || ",";
192       for (let i in list) {
193         strs += list[i].url + separator;
194       }
195       return strs != '' ? strs.substr(0, strs.length - 1) : '';
196     }
197   }
198 };
199 </script>
200
201 <style scoped lang="scss">
202 .upload-file-uploader {
203   margin-bottom: 5px;
204 }
205 .upload-file-list .el-upload-list__item {
206   border: 1px solid #e4e7ed;
207   line-height: 2;
208   margin-bottom: 10px;
209   position: relative;
210 }
211 .upload-file-list .ele-upload-list__item-content {
212   display: flex;
213   justify-content: space-between;
214   align-items: center;
215   color: inherit;
216 }
217 .ele-upload-list__item-content-action .el-link {
218   margin-right: 10px;
219 }
220 </style>