xm
2024-06-14 722af26bc6fec32bb289b1df51a9016a4935610f
提交 | 用户 | 时间
722af2 1 <template>
X 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 { getToken } from "@/utils/auth";
44 import { listByIds, delOss } from "@/api/system/oss";
45
46 export default {
47   name: "FileUpload",
48   props: {
49     // 值
50     value: [String, Object, Array],
51     // 数量限制
52     limit: {
53       type: Number,
54       default: 5,
55     },
56     // 大小限制(MB)
57     fileSize: {
58       type: Number,
59       default: 5,
60     },
61     // 文件类型, 例如['png', 'jpg', 'jpeg']
62     fileType: {
63       type: Array,
64       default: () => ["doc", "xls", "ppt", "txt", "pdf"],
65     },
66     // 是否显示提示
67     isShowTip: {
68       type: Boolean,
69       default: true
70     }
71   },
72   data() {
73     return {
74       number: 0,
75       uploadList: [],
76       baseUrl: process.env.VUE_APP_BASE_API,
77       uploadFileUrl: process.env.VUE_APP_BASE_API + "/system/oss/upload", // 上传文件服务器地址
78       headers: {
79         Authorization: "Bearer " + getToken(),
80       },
81       fileList: [],
82     };
83   },
84   watch: {
85     value: {
86       async handler(val) {
87         if (val) {
88           let temp = 1;
89           // 首先将值转为数组
90           let list;
91           if (Array.isArray(val)) {
92             list = val;
93           } else {
94             await listByIds(val).then(res => {
95               list = res.data.map(oss => {
96                 oss = { name: oss.originalName, url: oss.url, ossId: oss.ossId };
97                 return oss;
98               });
99             })
100           }
101           // 然后将数组转为对象数组
102           this.fileList = list.map(item => {
103             item = { name: item.name, url: item.url, ossId: item.ossId };
104             item.uid = item.uid || new Date().getTime() + temp++;
105             return item;
106           });
107         } else {
108           this.fileList = [];
109           return [];
110         }
111       },
112       deep: true,
113       immediate: true
114     }
115   },
116   computed: {
117     // 是否显示提示
118     showTip() {
119       return this.isShowTip && (this.fileType || this.fileSize);
120     },
121   },
122   methods: {
123     // 上传前校检格式和大小
124     handleBeforeUpload(file) {
125       // 校检文件类型
126       if (this.fileType) {
127         const fileName = file.name.split('.');
128         const fileExt = fileName[fileName.length - 1];
129         const isTypeOk = this.fileType.indexOf(fileExt) >= 0;
130         if (!isTypeOk) {
131           this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
132           return false;
133         }
134       }
135       // 校检文件大小
136       if (this.fileSize) {
137         const isLt = file.size / 1024 / 1024 < this.fileSize;
138         if (!isLt) {
139           this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
140           return false;
141         }
142       }
143       this.$modal.loading("正在上传文件,请稍候...");
144       this.number++;
145       return true;
146     },
147     // 文件个数超出
148     handleExceed() {
149       this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
150     },
151     // 上传失败
152     handleUploadError(err) {
153       this.$modal.msgError("上传文件失败,请重试");
154       this.$modal.closeLoading();
155     },
156     // 上传成功回调
157     handleUploadSuccess(res, file) {
158       if (res.code === 200) {
159         this.uploadList.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });
160         this.uploadedSuccessfully();
161       } else {
162         this.number--;
163         this.$modal.closeLoading();
164         this.$modal.msgError(res.msg);
165         this.$refs.fileUpload.handleRemove(file);
166         this.uploadedSuccessfully();
167       }
168     },
169     // 删除文件
170     handleDelete(index) {
171       let ossId = this.fileList[index].ossId;
172       delOss(ossId);
173       this.fileList.splice(index, 1);
174       this.$emit("input", this.listToString(this.fileList));
175     },
176     // 上传结束处理
177     uploadedSuccessfully() {
178       if (this.number > 0 && this.uploadList.length === this.number) {
179         this.fileList = this.fileList.concat(this.uploadList);
180         this.uploadList = [];
181         this.number = 0;
182         this.$emit("input", this.listToString(this.fileList));
183         this.$modal.closeLoading();
184       }
185     },
186     // 获取文件名称
187     getFileName(name) {
188       // 如果是url那么取最后的名字 如果不是直接返回
189       if (name.lastIndexOf("/") > -1) {
190         return name.slice(name.lastIndexOf("/") + 1);
191       } else {
192         return name;
193       }
194     },
195     // 对象转成指定字符串分隔
196     listToString(list, separator) {
197       let strs = "";
198       separator = separator || ",";
199       for (let i in list) {
200         strs += list[i].ossId + separator;
201       }
202       return strs != "" ? strs.substr(0, strs.length - 1) : "";
203     },
204   },
205 };
206 </script>
207
208 <style scoped lang="scss">
209 .upload-file-uploader {
210   margin-bottom: 5px;
211 }
212 .upload-file-list .el-upload-list__item {
213   border: 1px solid #e4e7ed;
214   line-height: 2;
215   margin-bottom: 10px;
216   position: relative;
217 }
218 .upload-file-list .ele-upload-list__item-content {
219   display: flex;
220   justify-content: space-between;
221   align-items: center;
222   color: inherit;
223 }
224 .ele-upload-list__item-content-action .el-link {
225   margin-right: 10px;
226 }
227 </style>