私人定制:阿里oss上传组件

本文代码只是vue前端组件代码,还需要依赖vuedraggable组件库(支持拖拽排序);还需要ossUpload.js工具函数(详见另外一文:阿里oss上传工具

该组件写的时候大部分都是参照elementUI的上传组件(其实是本来的业务代码都是通过后端上传,后面领导说要用oss,所以就写了这个组件),所以使用到了elementUI的部分组件

  1 <template>
  2   <div>
  3     <div class="flex-wrap">
  4       <div class="oss-upload">
  5         <slot></slot>
  6         <label v-if="!disabled" class="hand">
  7           <input
  8             :multiple="multiple"
  9             type="file"
 10             class="hidden"
 11             @change="change"
 12           />
 13         </label>
 14       </div>
 15 
 16       <el-button
 17         v-if="!disabled && onDelete && value"
 18         @click="handleDelete"
 19         type="text"
 20         size="small"
 21         >删除</el-button
 22       >
 23 
 24       <slot name="tips">
 25         <span class="tips">{{ tips }}</span>
 26       </slot>
 27     </div>
 28     <draggable
 29       class="drag-list"
 30       v-if="!disabled && showFileList && filelist.length > 0"
 31       v-model="filelist"
 32       @change="drag"
 33     >
 34       <div class="drag-item" v-for="(item, idx) in filelist" :key="idx">
 35         <img class="drag-item-img" :src="item" />
 36         <i class="el-icon-error" @click="remove(idx)"></i>
 37       </div>
 38     </draggable>
 39     <template v-else-if="showFileList && filelist.length > 0">
 40       <div class="drag-list">
 41         <div class="drag-item" v-for="(item, idx) in filelist" :key="idx">
 42           <img class="drag-item-img" :src="item" />
 43         </div>
 44       </div>
 45     </template>
 46   </div>
 47 </template>
 48 
 49 <script>
 50 import draggable from "vuedraggable";
 51 import { uploadOSS, defaultLimit } from "@/utils/ossUpload";
 52 export default {
 53   components: {
 54     draggable,
 55   },
 56   props: {
 57     value: String,
 58     limit: [String, Number],
 59     maxCount: [String, Number],
 60     tips: String,
 61     disabled: {
 62       type: Boolean,
 63       default: false,
 64     },
 65     compress: {
 66       type: Boolean,
 67       default: false,
 68     },
 69     showUploadResult: {
 70       type: Boolean,
 71       default: true,
 72     },
 73     multiple: {
 74       type: Boolean,
 75       default: false,
 76     },
 77     showFileList: {
 78       type: Boolean,
 79       default: false,
 80     },
 81     fileList: {
 82       type: Array,
 83       default: () => [],
 84     },
 85     onBeforeUpload: {
 86       type: Function,
 87       default: () => {},
 88     },
 89     onSuccess: {
 90       type: Function,
 91       default: () => {},
 92     },
 93     onError: {
 94       type: Function,
 95       default: () => {},
 96     },
 97     onChange: {
 98       type: Function,
 99       default: () => {},
100     },
101     onDelete: {
102       type: Function,
103       default: null,
104     },
105     dir: {
106       type: String,
107       default: "file",
108     },
109   },
110   watch: {
111     fileList: {
112       handler(val) {
113         this.filelist = val || [];
114       },
115       immediate: true,
116     },
117   },
118   data() {
119     return {
120       filelist: [],
121     };
122   },
123   methods: {
124     clearFileList() {
125       this.filelist = [];
126     },
127     handleDelete() {
128       this.onDelete && this.onDelete();
129     },
130     remove(index) {
131       this.filelist = this.filelist.filter((item, idx) => idx !== index);
132       this.onChange(this.filelist);
133     },
134     drag() {
135       this.onChange(this.filelist);
136     },
137     change(e) {
138       const files = Array.from(e.target.files);
139       const limit = Number(this.limit);
140       const maxCount = Number(this.maxCount);
141       if (maxCount === maxCount) {
142         // maxCount值有效,则限制数量
143         if (this.filelist.length + files.length > maxCount) {
144           this.$message.warning(`最多上传${maxCount}张图片`);
145           return;
146         }
147       }
148       // 限制图片类型
149       const _files = files.filter((d) => {
150         if (d.type == "image/png" || d.type == "image/jpeg") {
151           return true;
152         } else {
153           return false;
154         }
155       });
156       e.target.value = null;
157 
158       // 存在不符合的图片类型
159       if (_files.length !== files.length) {
160         this.$message.warning("图片类型不是png或者jpeg");
161       }
162       // 没有有效的图片直接返回
163       if (_files.length === 0) {
164         return;
165       }
166       this.onBeforeUpload(); // 上传前钩子
167       uploadOSS(_files, this.dir, {
168         limitSize: isNaN(limit) ? defaultLimit : limit,
169         compress: this.compress,
170       })
171         .then(({ result, code, msg }) => {
172           this.showUploadResult &&
173             this.$message({
174               type: code == 1 ? "success" : "warning",
175               message: msg,
176             });
177           result.forEach((res) => {
178             this.filelist.push(res.url);
179           });
180 
181           if (this.multiple || this.filelist[this.filelist.length - 1]) {
182             this.onSuccess(
183               result,
184               this.multiple
185                 ? this.filelist
186                 : this.filelist[this.filelist.length - 1]
187             );
188           }
189         })
190         .catch((err) => {
191           console.error(err);
192           this.onError(err);
193         });
194     },
195   },
196 };
197 </script>
198 
199 <style scoped>
200 .oss-upload img {
201   display: block;
202 }
203 .flex-wrap {
204   display: inline-flex;
205   align-items: center;
206 }
207 .oss-upload {
208   display: inline-block;
209   position: relative;
210   margin-right: 10px;
211 }
212 .hand {
213   z-index: 99;
214   cursor: pointer;
215   position: absolute;
216   top: 0;
217   left: 0;
218   right: 0;
219   bottom: 0;
220 }
221 .hidden {
222   display: none;
223 }
224 
225 .el-icon-error {
226   position: absolute;
227   right: -7px;
228   top: -7px;
229   font-size: 18px;
230   cursor: pointer;
231   color: #f56c6c;
232 }
233 .drag-list {
234   display: flex;
235   flex-wrap: wrap;
236   padding: 20px 0;
237 }
238 .drag-item {
239   position: relative;
240   margin-right: 10px;
241 }
242 
243 .drag-item-img {
244   object-fit: contain;
245   width: 100px;
246   height: 100px;
247   border: 1px solid #ddd;
248   border-radius: 4px;
249 }
250 
251 .tips {
252   font-size: 12px;
253   color: #999;
254 }
255 </style>

 

posted @ 2022-05-13 14:18  豆浆不要油条  阅读(115)  评论(0编辑  收藏  举报