1 <template>
2 <div>
3 <el-upload
4 ref="upload"
5 class="upload"
6 :drag="drag"
7 :disabled="disabled"
8 :multiple="multiple"
9 :auto-upload="autoUpload"
10 :show-file-list="showFileList"
11 :with-credentials="withCredentials"
12
13 :limit="limit"
14 :accept="accept"
15 :list-type="listType"
16
17 :name="name"
18 :action="action"
19 :data="extraParams"
20 :headers="requestHeaders"
21
22 :http-request="isRequest ? handleHttpRequest : undefined"
23
24 :on-error="handleError"
25 :on-exceed="handleExceed"
26 :on-change="handleChange"
27 :on-remove="handleRemove"
28 :on-success="hendleSuccess"
29 :on-preview="handlePreview"
30 :on-progress="handleProgress"
31
32 :before-upload="handleBeforeUpload"
33 :before-remove="handleBeforeRemove"
34
35
36 :file-list="fileList"
37 >
38 <slot></slot>
39 <slot name="trigger"></slot>
40 <div slot="tip">
41 <slot name="tip"></slot>
42 </div>
43 <div v-if="isSlotFile" slot="file" slot-scope="scope">
44 <slot name="file" v-bind="scope"></slot>
45 </div>
46 </el-upload>
47 </div>
48 </template>
49
50 <script>
51 import Sortable from 'sortablejs';
52 export default {
53 name: 'customUpload',
54 props: {
55 // 属性
56 isRequest: {
57 type: Boolean,
58 default: () => false
59 },
60 isSlotFile: {
61 type: Boolean,
62 default: () => false
63 },
64 drag: {
65 type: Boolean,
66 default: () => false
67 },
68 sortable: {
69 type: Boolean,
70 default: () => false
71 },
72 disabled: {
73 type: Boolean,
74 default: () => false
75 },
76 multiple: {
77 type: Boolean,
78 default: () => false
79 },
80 autoUpload: {
81 type: Boolean,
82 default: () => true
83 },
84 showFileList: {
85 type: Boolean,
86 default: () => true
87 },
88 withCredentials: {
89 type: Boolean,
90 default: () => false
91 },
92 // 文件限制
93 limit: {
94 type: Number,
95 default: () => 1
96 },
97 maxSize: {
98 type: Number,
99 default: () => 100 * 1024
100 },
101 accept: {
102 type: String,
103 default: () => '.jpg,.JPG,.png,.PNG'
104 },
105 listType: {
106 type: String,
107 default: () => 'text'
108 },
109 imgWidth: {
110 type: Number,
111 default: () => 0
112 },
113 imgHeight: {
114 type: Number,
115 default: () => 0
116 },
117
118 // 文件上传参数
119 name: {
120 type: String,
121 default: () => 'file'
122 },
123 action: {
124 type: String,
125 default: () => ''
126 },
127 extraParams: {
128 type: Object,
129 default: () => ({})
130 },
131 requestHeaders: {
132 type: Object,
133 default: () => ({})
134 },
135
136 // 上传事件
137 onError: { type: Function, default: function () { } },
138 onExceed: { type: Function, default: function () { } },
139 onChange: { type: Function, default: function () { } },
140 onRemove: { type: Function, default: function () { } },
141 onSuccess: { type: Function, default: function () { } },
142 onPreview: { type: Function, default: function () { } },
143 onProgress: { type: Function, default: function () { } },
144 beforeUpload: { type: Function, default: function () { return true; } },
145 beforeRemove: { type: Function, default: function () { return true; } },
146
147 httpRequest: { type: Function, default: function () { } },
148
149 customList: {
150 type: Array,
151 default: () => []
152 }
153 },
154 data() {
155 return {
156 fileList: []
157 }
158 },
159 watch: {
160 fileList: {
161 deep: true,
162 immediate: true,
163 handler(val) {
164 this.$emit('update:customList', val);
165 }
166 },
167 customList: {
168 deep: true,
169 immediate: true,
170 handler(val) {
171 if(!this.fileList.length) {
172 this.fileList = val;
173 }
174 }
175 }
176 },
177 computed: {
178
179 },
180 mounted() {
181 let _this = this;
182 if (this.sortable) {
183 var list = this.$el.querySelector('.el-upload-list');
184 Sortable.create(list, {
185 onEnd: (ev) => {
186 let arr = _this.fileList;
187 arr[ev.oldIndex] = arr.splice(ev.newIndex, 1, arr[ev.oldIndex])[0];
188 },
189 });
190 }
191 },
192 methods: {
193 // 清空
194 clearFiles() {
195 this.$refs['upload']['clearFiles']();
196 },
197
198 // 提交
199 submit() {
200 this.$refs['upload']['submit']();
201 },
202
203 // 取消
204 abort() {
205 this.$refs['upload']['abort']();
206 },
207
208
209 // 文件上传事件
210 handleError(err, file, fileList) {
211 this.onError(err, file, fileList);
212 },
213
214 handleExceed(files, fileList) {
215 this.onExceed(files, fileList);
216 },
217
218 handleChange(file, fileList) {
219 this.onChange(file, fileList);
220 },
221
222 handleRemove(file, fileList) {
223 this.fileList = fileList;
224 this.onRemove(file, fileList);
225 },
226
227 hendleSuccess(response, file, fileList) {
228 response.name = file.name;
229 response.url = file.url;
230 this.fileList.push(response);
231 this.onSuccess(response, file, fileList);
232 },
233
234 handlePreview(file) {
235 this.onPreview(file);
236 },
237
238 handleProgress(event, file, fileList) {
239 this.onProgress(event, file, fileList);
240 },
241
242 // 文件上传前操作
243 handleBeforeUpload(file) {
244 let accept = this.accept;
245 let maxSize = this.maxSize;
246 let isMaxSize = file.size < maxSize;
247 let isOkExt = accept.indexOf(file.name.substring(file.name.lastIndexOf('.'))) >= 0;
248
249 if (!isOkExt) {
250 accept = accept.replace(/\,\./g, '/');
251 accept = accept.replace('.', '');
252 this.$message.error(`只能上传${accept}格式的文件`);
253 return false;
254 }
255
256 if (!isMaxSize) {
257 const { size, sizeType } = this.sizeTypes(maxSize);
258 this.$message.error(`上传文件大小不能超过${size}${sizeType}`);
259 return false;
260 }
261
262 if(this.imgWidth && this.imgHeight) return this.scaling({ file, width: this.imgWidth, height: this.imgHeight });
263
264 return this.beforeUpload(file);
265 },
266
267 handleBeforeRemove(file) {
268 return this.beforeRemove(file);
269 },
270
271 // 自定义上传
272 handleHttpRequest(files) {
273 this.httpRequest(files);
274 },
275
276 // 文件大小类型
277 sizeTypes(maxSize) {
278 if (maxSize >= 1024 * 1024) {
279 let size = parseInt(maxSize / 1024 / 1024);
280 return {
281 size,
282 sizeType: 'M'
283 }
284 } else if (maxSize >= 1024) {
285 const size = parseInt(maxSize / 1024);
286 return {
287 size,
288 sizeType: 'kb'
289 }
290 } else {
291 return {
292 size: maxSize,
293 sizeType: 'b'
294 };
295 }
296 },
297
298
299 // 对比图片比例
300 scaling({ file, width, height }) {
301 return new Promise(function (resolve, reject) { //upload内部需要一个promise,简单的return出false并没有什么用
302 let _URL = window.URL || window.webkitURL;
303 let image = new Image();
304 image.onload = function () {
305 let valid = image.width === width && image.height === height;
306 valid ? resolve(true) : reject(false);
307 };
308 image.src = _URL.createObjectURL(file); //onload是异步加载,所以一定要在onload后在执行判断图片尺寸
309 }).then(
310 () => {
311 return file;
312 },
313 () => {
314 this.$message.error("请上传正确的图片比例");
315 return Promise.reject(false);
316 }
317 );
318 }
319
320
321 }
322 }
323 </script>