Commit 116d2ab72cb69a1993bad957a3e8cb603f28ff14
1 parent
11a65483
Exists in
master
and in
3 other branches
feat: 优化Upload组件
Showing
2 changed files
with
611 additions
and
30 deletions
Show diff stats
examples/views/docs/component/upload.md
| @@ -4,14 +4,55 @@ | @@ -4,14 +4,55 @@ | ||
| 4 | 4 | ||
| 5 | ## 基础用法 | 5 | ## 基础用法 |
| 6 | 6 | ||
| 7 | -默认为图片上传 | 7 | +默认支持图片和图片一起上传 |
| 8 | 8 | ||
| 9 | -::: snippet 图片上传 | 9 | +::: snippet 配置项`action`、`headers`、`data`与**Element**中的**el-upload**相同,值的格式为逗号分隔的字符串 |
| 10 | + | ||
| 11 | +```html | ||
| 12 | +<template> | ||
| 13 | + <z-upload v-model="model" action="http://47.98.245.217:7070/tms-web-api/upload/image" :headers="headers" :data="uploadData"></z-upload> | ||
| 14 | +</template> | ||
| 15 | + | ||
| 16 | +<script> | ||
| 17 | +export default { | ||
| 18 | + data() { | ||
| 19 | + return { | ||
| 20 | + model: 'https://zeyi-tms-test.oss-cn-hangzhou.aliyuncs.com/image/null/3a3d0bb1-a5eb-4957-aa7a-54d004769be6.png,https://zeyi-tms-test.oss-cn-hangzhou.aliyuncs.com/image/null/a1a7e2fe-5896-44ed-9935-549050e9444c.png', | ||
| 21 | + headers: { | ||
| 22 | + 'Authorization': 'Bearer 2a6238c6-5a87-4f3f-893b-14aef14b9539' | ||
| 23 | + }, | ||
| 24 | + uploadData: { | ||
| 25 | + module: 'tms' | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + }, | ||
| 29 | +} | ||
| 30 | +</script> | ||
| 31 | +``` | ||
| 32 | + | ||
| 33 | +::: | ||
| 34 | + | ||
| 35 | +## 限制上传 | ||
| 36 | + | ||
| 37 | +可以限制图片上传或者文件上传 | ||
| 38 | + | ||
| 39 | +::: snippet `type`设置上传模式,`limit`限制上传数量,`file-type`限制文件上传格式 | ||
| 10 | 40 | ||
| 11 | ```html | 41 | ```html |
| 12 | <template> | 42 | <template> |
| 13 | <div> | 43 | <div> |
| 14 | - <z-upload v-model="model"></z-upload> | 44 | + <div> |
| 45 | + <div>文件上传:</div> | ||
| 46 | + <z-upload v-model="file" type="file" action="http://47.98.245.217:7070/tms-web-api/upload/image" :limit="1" :headers="headers" size="mini"></z-upload> | ||
| 47 | + </div> | ||
| 48 | + <div> | ||
| 49 | + <div>图片上传:</div> | ||
| 50 | + <z-upload v-model="image" type="image" action="http://47.98.245.217:7070/tms-web-api/upload/image" :limit="2" :headers="headers" size="mini"></z-upload> | ||
| 51 | + </div> | ||
| 52 | + <div> | ||
| 53 | + <div>限制文件格式:</div> | ||
| 54 | + <z-upload v-model="fileType" type="file" file-type="pdf" action="http://47.98.245.217:7070/tms-web-api/upload/image" :limit="1" :headers="headers" size="mini"></z-upload> | ||
| 55 | + </div> | ||
| 15 | </div> | 56 | </div> |
| 16 | </template> | 57 | </template> |
| 17 | 58 | ||
| @@ -19,9 +60,68 @@ | @@ -19,9 +60,68 @@ | ||
| 19 | export default { | 60 | export default { |
| 20 | data() { | 61 | data() { |
| 21 | return { | 62 | return { |
| 63 | + file: '', | ||
| 64 | + image: '', | ||
| 65 | + fileType: '', | ||
| 66 | + headers: { | ||
| 67 | + 'Authorization': 'Bearer 2a6238c6-5a87-4f3f-893b-14aef14b9539' | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + }, | ||
| 71 | +} | ||
| 72 | +</script> | ||
| 73 | +``` | ||
| 74 | + | ||
| 75 | +::: | ||
| 76 | + | ||
| 77 | +## 多选与拖拽 | ||
| 78 | + | ||
| 79 | +可以多选上传及拖拽上传 | ||
| 80 | + | ||
| 81 | +::: snippet `multiple`设置多选上传,`drag`设置拖拽上传 | ||
| 82 | + | ||
| 83 | +```html | ||
| 84 | +<template> | ||
| 85 | + <z-upload v-model="model" action="http://47.98.245.217:7070/tms-web-api/upload/image" :headers="headers" multiple drag :limit="3"></z-upload> | ||
| 86 | +</template> | ||
| 87 | + | ||
| 88 | +<script> | ||
| 89 | +export default { | ||
| 90 | + data() { | ||
| 91 | + return { | ||
| 22 | model: '', | 92 | model: '', |
| 93 | + headers: { | ||
| 94 | + 'Authorization': 'Bearer 2a6238c6-5a87-4f3f-893b-14aef14b9539' | ||
| 95 | + }, | ||
| 96 | + } | ||
| 97 | + }, | ||
| 98 | +} | ||
| 99 | +</script> | ||
| 100 | +``` | ||
| 101 | + | ||
| 102 | +::: | ||
| 103 | + | ||
| 104 | +## 角标删除与提醒 | ||
| 105 | + | ||
| 106 | +默认支持角标删除样式,以及配置删除前确认提示 | ||
| 107 | + | ||
| 108 | +::: snippet `corner-close`开启角标删除,`delete-confirm`设置删除确认提示 | ||
| 109 | + | ||
| 110 | +```html | ||
| 111 | +<template> | ||
| 112 | + <z-upload v-model="model" action="http://47.98.245.217:7070/tms-web-api/upload/image" :headers="headers" multiple drag corner-close delete-confirm :limit="3"></z-upload> | ||
| 113 | +</template> | ||
| 114 | + | ||
| 115 | +<script> | ||
| 116 | +export default { | ||
| 117 | + data() { | ||
| 118 | + return { | ||
| 119 | + model: 'https://zeyi-tms-test.oss-cn-hangzhou.aliyuncs.com/image/null/3a3d0bb1-a5eb-4957-aa7a-54d004769be6.png,https://zeyi-tms-test.oss-cn-hangzhou.aliyuncs.com/image/null/a1a7e2fe-5896-44ed-9935-549050e9444c.png', | ||
| 120 | + headers: { | ||
| 121 | + 'Authorization': 'Bearer 2a6238c6-5a87-4f3f-893b-14aef14b9539' | ||
| 122 | + }, | ||
| 23 | } | 123 | } |
| 24 | - } | 124 | + }, |
| 25 | } | 125 | } |
| 26 | </script> | 126 | </script> |
| 27 | ``` | 127 | ``` |
| @@ -35,9 +135,33 @@ export default { | @@ -35,9 +135,33 @@ export default { | ||
| 35 | 参数|说明|类型|可选值|默认值 | 135 | 参数|说明|类型|可选值|默认值 |
| 36 | -|-|-|-|- | 136 | -|-|-|-|- |
| 37 | value | 值 | String | - | - | 137 | value | 值 | String | - | - |
| 138 | +type | 上传类型 | String | all,image,file | all | ||
| 139 | +file-type | 上传文件类型限制,仅在type为file时生效 | String | - | - | ||
| 140 | +disabled | 是否禁用 | Boolean | - | false | ||
| 141 | +multiple | 是否支持多选文件 | Boolean | - | false | ||
| 142 | +limit | 最大上传数量 | Number | - | - | ||
| 143 | +drag | 是否启用拖拽上传 | Boolean | - | false | ||
| 144 | +draggable | 是否启用拖拽改变顺序(需要项目安装vuedraggable并注册为draggable) | Boolean | - | false | ||
| 145 | +action | 上传地址 | String | - | - | ||
| 146 | +headers | 自定义请求头 | Object | - | {} | ||
| 147 | +delete-confirm | 删除图片时弹出确认框 | Boolean | - | false | ||
| 148 | +data | 上传时附带的额外参数 | Object | - | {} | ||
| 149 | +name | 上传文件字段名 | String | - | file | ||
| 150 | +response-filter | 返回值处理函数 | Function | - | - | ||
| 151 | +before-upload | 上传文件之前的钩子 | Function | - | - | ||
| 152 | +size | 大小 | String | mini, small, large | large | ||
| 153 | +http | HTTP请求库 | Function | - | - | ||
| 154 | +http-request | 自定义请求方法 | Function | - | - | ||
| 155 | +corner-close | 是否开启角标删除按钮 | Boolean | - | false | ||
| 38 | 156 | ||
| 39 | ## Events 事件 | 157 | ## Events 事件 |
| 40 | 158 | ||
| 41 | 事件名称|说明|回调参数 | 159 | 事件名称|说明|回调参数 |
| 42 | -|-|- | 160 | -|-|- |
| 43 | -change | 改变选中 | 值,选中项数据 | ||
| 44 | \ No newline at end of file | 161 | \ No newline at end of file |
| 162 | +upload | 单个文件上传成功后的事件 | 请求response | ||
| 163 | + | ||
| 164 | +## Slots 插槽 | ||
| 165 | + | ||
| 166 | +名称|说明|方法 | ||
| 167 | +-|-|- | ||
| 168 | +image-viewer | 自定义图片查看器 | show, index, list, close, open |
packages/upload/index.vue
| 1 | <template> | 1 | <template> |
| 2 | - <div class="zee-upload"> | ||
| 3 | - <el-button type="text" @click="openViewer">查看图片</el-button> | ||
| 4 | - <el-image-viewer :z-index="zIndex" :initial-index="imageIndex" v-if="showViewer" :on-close="closeViewer" :url-list="previewSrcList" /> | 2 | + <div class="z-upload" :class="[size]"> |
| 3 | + <ul class="el-upload-list el-upload-list--picture-card"> | ||
| 4 | + <!-- 已上传图片列表,支持拖拽改变顺序 --> | ||
| 5 | + <drag-field v-model="imageList" @change="onDragFile" :draggable="draggable"> | ||
| 6 | + <div v-for="(url, index) in imageList" :key="index" class="el-upload-list__item-wrapper"> | ||
| 7 | + <li class="el-upload-list__item"> | ||
| 8 | + <template v-if="type === 'all'"> | ||
| 9 | + <img v-if="isImage(url)" :src="url" alt class="el-upload-list__item-thumbnail" /> | ||
| 10 | + <div v-else alt class="el-upload-list__item-thumbnail--file" :class="url | fileTypeFilter"></div> | ||
| 11 | + </template> | ||
| 12 | + <template v-else> | ||
| 13 | + <img v-if="type === 'image'" :src="url" alt class="el-upload-list__item-thumbnail" /> | ||
| 14 | + <div v-else alt class="el-upload-list__item-thumbnail--file" :class="url | fileTypeFilter"></div> | ||
| 15 | + </template> | ||
| 16 | + <div v-if="!cornerClose" class="el-upload-list__item-actions"> | ||
| 17 | + <span v-if="isImage(url)" class="el-upload-list__item-preview" @click="onPreview(url, index)"> | ||
| 18 | + <i class="el-icon-zoom-in"></i> | ||
| 19 | + </span> | ||
| 20 | + <span v-else class="el-upload-list__item-preview" @click="onDownload(url)"> | ||
| 21 | + <i class="el-icon-download"></i> | ||
| 22 | + </span> | ||
| 23 | + <span v-if="!disabled" class="el-upload-list__item-delete" @click="onRemove(index)"> | ||
| 24 | + <i class="el-icon-delete"></i> | ||
| 25 | + </span> | ||
| 26 | + </div> | ||
| 27 | + <div v-else class="el-upload-list__item-actions"> | ||
| 28 | + <div v-if="isImage(url)" class="block-preview" @click="onPreview(url, index)"> | ||
| 29 | + <i class="el-icon-view"></i> | ||
| 30 | + </div> | ||
| 31 | + <div v-else class="block-download" @click="onDownload(url)"> | ||
| 32 | + <i class="el-icon-download"></i> | ||
| 33 | + </div> | ||
| 34 | + </div> | ||
| 35 | + </li> | ||
| 36 | + <div v-if="cornerClose && !disabled" class="corner-close" @click="onRemove(index)"> | ||
| 37 | + <i class="el-icon-close"></i> | ||
| 38 | + </div> | ||
| 39 | + </div> | ||
| 40 | + </drag-field> | ||
| 41 | + <!-- 默认上传按钮 --> | ||
| 42 | + <el-upload | ||
| 43 | + v-if="!limit || imageList.length < limit" | ||
| 44 | + :action="action" | ||
| 45 | + :data="data" | ||
| 46 | + :name="name" | ||
| 47 | + :headers="headers" | ||
| 48 | + :file-list="fileList" | ||
| 49 | + :disabled="disabled" | ||
| 50 | + :multiple="multiple" | ||
| 51 | + :limit="limit" | ||
| 52 | + :drag="drag" | ||
| 53 | + :show-file-list="false" | ||
| 54 | + list-type="picture-card" | ||
| 55 | + :on-exceed="onExceed" | ||
| 56 | + :on-success="onSuccess" | ||
| 57 | + :on-error="onError" | ||
| 58 | + :before-upload="onBeforeUpload" | ||
| 59 | + :http-request="isCustomRequest ? onHttpRequest : undefined" | ||
| 60 | + > | ||
| 61 | + <i class="el-icon-plus"></i> | ||
| 62 | + </el-upload> | ||
| 63 | + </ul> | ||
| 64 | + <!-- 图片查看器 --> | ||
| 65 | + <slot | ||
| 66 | + v-if="$scopedSlots['image-viewer'] || $slots['image-viewer']" | ||
| 67 | + name="image-viewer" | ||
| 68 | + :show="isImageViewerShow" | ||
| 69 | + :index="defaultIndex" | ||
| 70 | + :list="filteredImageList" | ||
| 71 | + :close="closeViewer" | ||
| 72 | + :open="openViewer" | ||
| 73 | + ></slot> | ||
| 74 | + <template v-else> | ||
| 75 | + <el-image-viewer v-if="isImageViewerShow" :initial-index="defaultIndex" :on-close="closeViewer" :url-list="filteredImageList" /> | ||
| 76 | + </template> | ||
| 5 | </div> | 77 | </div> |
| 6 | </template> | 78 | </template> |
| 7 | 79 | ||
| 8 | <script> | 80 | <script> |
| 9 | -// import ElImageViewer from 'element-ui/packages/image/src/image-viewer'; | ||
| 10 | import ElImageViewer from './image-viewer'; | 81 | import ElImageViewer from './image-viewer'; |
| 11 | 82 | ||
| 83 | +const imgExtensions = ['.bmp', '.jpg', '.png', '.tif', '.gif', '.pcx', '.tga', '.exif', '.fpx', '.svg']; | ||
| 84 | + | ||
| 85 | +// 获取文件类型 | ||
| 86 | +const getFileType = function(url) { | ||
| 87 | + return `${/\.[^.]+$/.exec(url)[0]}`.toLowerCase(); | ||
| 88 | +}; | ||
| 89 | + | ||
| 12 | export default { | 90 | export default { |
| 13 | name: 'Upload', | 91 | name: 'Upload', |
| 14 | components: { | 92 | components: { |
| 15 | ElImageViewer, | 93 | ElImageViewer, |
| 94 | + DragField: { | ||
| 95 | + props: { value: Array, draggable: Boolean }, | ||
| 96 | + render(h) { | ||
| 97 | + // 是否开启可拖拽改变图片顺序,需要项目安装vuedraggable | ||
| 98 | + if (this.draggable) { | ||
| 99 | + return h( | ||
| 100 | + 'draggable', | ||
| 101 | + { | ||
| 102 | + props: { value: this.value }, | ||
| 103 | + on: { | ||
| 104 | + input: e => this.$emit('input', e), | ||
| 105 | + change: e => this.$emit('change', e), | ||
| 106 | + }, | ||
| 107 | + }, | ||
| 108 | + this.$slots.default, | ||
| 109 | + ); | ||
| 110 | + } else { | ||
| 111 | + return h('div', this.$slots.default); | ||
| 112 | + } | ||
| 113 | + }, | ||
| 114 | + }, | ||
| 16 | }, | 115 | }, |
| 17 | props: { | 116 | props: { |
| 18 | - zIndex: { | ||
| 19 | - type: Number, | ||
| 20 | - default: 2000, | 117 | + value: String, |
| 118 | + // 是否禁用 | ||
| 119 | + disabled: Boolean, | ||
| 120 | + // 是否支持多选文件 | ||
| 121 | + multiple: Boolean, | ||
| 122 | + // 最大上传数量 | ||
| 123 | + limit: Number, | ||
| 124 | + // 是否启用拖拽上传 | ||
| 125 | + drag: Boolean, | ||
| 126 | + // 是否启用拖拽改变顺序 | ||
| 127 | + draggable: Boolean, | ||
| 128 | + // 上传地址 | ||
| 129 | + action: String, | ||
| 130 | + // 自定义请求头 | ||
| 131 | + headers: { | ||
| 132 | + type: Object, | ||
| 133 | + default: () => ({}), | ||
| 134 | + }, | ||
| 135 | + // 删除图片时确认提示 | ||
| 136 | + deleteConfirm: Boolean, | ||
| 137 | + // 上传时附带的额外参数 | ||
| 138 | + data: { | ||
| 139 | + type: Object, | ||
| 140 | + default: () => ({}), | ||
| 21 | }, | 141 | }, |
| 142 | + // 上传文件字段名 | ||
| 143 | + name: { | ||
| 144 | + type: String, | ||
| 145 | + default: 'file', | ||
| 146 | + }, | ||
| 147 | + // 返回值处理 | ||
| 148 | + responseFilter: Function, | ||
| 149 | + // 上传文件之前的钩子 | ||
| 150 | + beforeUpload: Function, | ||
| 151 | + // 上传类型 | ||
| 152 | + type: { | ||
| 153 | + type: String, | ||
| 154 | + default: 'all', // all, image, file | ||
| 155 | + }, | ||
| 156 | + // 上传文件类型限制 | ||
| 157 | + fileType: String, | ||
| 158 | + // 大小 | ||
| 159 | + size: { | ||
| 160 | + type: String, | ||
| 161 | + default: 'large', // mini, small, large | ||
| 162 | + }, | ||
| 163 | + // HTTP请求库 | ||
| 164 | + http: Function, | ||
| 165 | + // 自定义请求方法 | ||
| 166 | + httpRequest: Function, | ||
| 167 | + // 是否开启角标删除按钮 | ||
| 168 | + cornerClose: Boolean, | ||
| 22 | }, | 169 | }, |
| 23 | data() { | 170 | data() { |
| 24 | return { | 171 | return { |
| 25 | - showViewer: false, | ||
| 26 | - src: 'https://zeyi-tms-test.oss-cn-hangzhou.aliyuncs.com/image/vehicle/e1612ad0-3c6f-465b-ac83-cec291d3013d.jpg', | ||
| 27 | - previewSrcList: [ | ||
| 28 | - 'https://zeyi-tms-test.oss-cn-hangzhou.aliyuncs.com/image/vehicle/48655e39-31cf-42ca-849d-c4a5245d005b.jpg', | ||
| 29 | - 'https://zeyi-tms-test.oss-cn-hangzhou.aliyuncs.com/image/vehicle/e1612ad0-3c6f-465b-ac83-cec291d3013d.jpg', | ||
| 30 | - 'https://zeyi-tms-test.oss-cn-hangzhou.aliyuncs.com/image/vehicle/4511c610-4f73-4f04-8e26-62e87d3cb5b1.jpg', | ||
| 31 | - ], | 172 | + fileList: [], // ElementUI Upload 默认文件列表 |
| 173 | + imageList: [], // 图片url列表 | ||
| 174 | + isImageViewerShow: false, // 图片预览显示状态 | ||
| 175 | + currentIndex: 0, // 当前预览图片下标 | ||
| 32 | }; | 176 | }; |
| 33 | }, | 177 | }, |
| 34 | computed: { | 178 | computed: { |
| 35 | - imageIndex() { | ||
| 36 | - let previewIndex = 0; | ||
| 37 | - const srcIndex = this.previewSrcList.indexOf(this.src); | ||
| 38 | - if (srcIndex >= 0) { | ||
| 39 | - previewIndex = srcIndex; | 179 | + // 请求自定义 |
| 180 | + isCustomRequest() { | ||
| 181 | + return Boolean(this.http) || Boolean(this.httpRequest) || Boolean(this.$axios); | ||
| 182 | + }, | ||
| 183 | + // 预览图片列表,去除文件 | ||
| 184 | + filteredImageList() { | ||
| 185 | + if (this.type === 'all') { | ||
| 186 | + return this.imageList.filter(url => imgExtensions.some(key => `${url}`.toLowerCase().includes(key))); | ||
| 187 | + } | ||
| 188 | + return this.imageList; | ||
| 189 | + }, | ||
| 190 | + // 预览文件列表默认下标 | ||
| 191 | + defaultIndex() { | ||
| 192 | + if (this.type === 'all') { | ||
| 193 | + const currentUrl = this.imageList[this.currentIndex]; | ||
| 194 | + return this.filteredImageList.findIndex(url => url === currentUrl); | ||
| 195 | + } else { | ||
| 196 | + return this.currentIndex; | ||
| 197 | + } | ||
| 198 | + }, | ||
| 199 | + }, | ||
| 200 | + filters: { | ||
| 201 | + // 处理文件拓展名对应的class | ||
| 202 | + fileTypeFilter(val) { | ||
| 203 | + const fileType = getFileType(val); | ||
| 204 | + if (['.doc', '.docx'].includes(fileType)) { | ||
| 205 | + return 'word'; | ||
| 206 | + } | ||
| 207 | + if (['.xls', '.xlsx', '.csv'].includes(fileType)) { | ||
| 208 | + return 'excel'; | ||
| 40 | } | 209 | } |
| 41 | - return previewIndex; | 210 | + if (['.ppt', '.pptx'].includes(fileType)) { |
| 211 | + return 'ppt'; | ||
| 212 | + } | ||
| 213 | + if (['.pdf'].includes(fileType)) { | ||
| 214 | + return 'pdf'; | ||
| 215 | + } | ||
| 216 | + if (['.zip', '.rar', '.7z'].includes(fileType)) { | ||
| 217 | + return 'zip'; | ||
| 218 | + } | ||
| 219 | + return ''; | ||
| 220 | + }, | ||
| 221 | + }, | ||
| 222 | + watch: { | ||
| 223 | + value: { | ||
| 224 | + handler(val) { | ||
| 225 | + if (val) { | ||
| 226 | + let imageList = []; | ||
| 227 | + let fileList = []; | ||
| 228 | + val.split(',').forEach(url => { | ||
| 229 | + imageList.push(url); | ||
| 230 | + fileList.push({ url }); | ||
| 231 | + }); | ||
| 232 | + this.imageList = imageList; | ||
| 233 | + this.fileList = fileList; | ||
| 234 | + } else { | ||
| 235 | + this.fileList = []; | ||
| 236 | + this.imageList = []; | ||
| 237 | + } | ||
| 238 | + }, | ||
| 239 | + immediate: true, | ||
| 42 | }, | 240 | }, |
| 43 | }, | 241 | }, |
| 44 | methods: { | 242 | methods: { |
| 45 | - closeViewer() { | ||
| 46 | - this.showViewer = false; | 243 | + // 判断url是否为图片 |
| 244 | + isImage(url) { | ||
| 245 | + return imgExtensions.some(key => `${url}`.toLowerCase().includes(key)); | ||
| 246 | + }, | ||
| 247 | + // 删除图片 | ||
| 248 | + onRemove(index) { | ||
| 249 | + if (this.deleteConfirm) { | ||
| 250 | + this.$confirm('确定删除当前图片吗?', '提示', { | ||
| 251 | + confirmButtonText: '确定', | ||
| 252 | + cancelButtonText: '取消', | ||
| 253 | + type: 'warning', | ||
| 254 | + }) | ||
| 255 | + .then(() => { | ||
| 256 | + this.removeImage(index); | ||
| 257 | + }) | ||
| 258 | + .catch(() => {}); | ||
| 259 | + } else { | ||
| 260 | + this.removeImage(index); | ||
| 261 | + } | ||
| 262 | + }, | ||
| 263 | + // 移除图片 | ||
| 264 | + removeImage(index) { | ||
| 265 | + this.imageList.splice(index, 1); | ||
| 266 | + this.fileList.splice(index, 1); | ||
| 267 | + this.$emit('input', this.imageList.join(',')); | ||
| 268 | + }, | ||
| 269 | + // 预览图片 | ||
| 270 | + onPreview(url, index) { | ||
| 271 | + this.currentIndex = index; | ||
| 272 | + this.$nextTick(this.openViewer); | ||
| 47 | }, | 273 | }, |
| 274 | + // 打开图片预览 | ||
| 48 | openViewer() { | 275 | openViewer() { |
| 49 | - this.showViewer = true; | 276 | + this.isImageViewerShow = true; |
| 277 | + }, | ||
| 278 | + // 关闭图片预览 | ||
| 279 | + closeViewer() { | ||
| 280 | + this.isImageViewerShow = false; | ||
| 281 | + }, | ||
| 282 | + // 下载文件 | ||
| 283 | + onDownload(url) { | ||
| 284 | + window.open(url); | ||
| 285 | + }, | ||
| 286 | + // 上传之前校验 | ||
| 287 | + onBeforeUpload(file) { | ||
| 288 | + if (this.type === 'all') { | ||
| 289 | + if (this.beforeUpload) { | ||
| 290 | + return this.beforeUpload(file); | ||
| 291 | + } | ||
| 292 | + return true; | ||
| 293 | + } | ||
| 294 | + const fileType = getFileType(file.name); | ||
| 295 | + if (this.type === 'image') { | ||
| 296 | + if (!`${file.type}`.toLowerCase().includes('image')) { | ||
| 297 | + this.$message.warning('请上传图片'); | ||
| 298 | + return false; | ||
| 299 | + } | ||
| 300 | + } else if (this.type === 'file') { | ||
| 301 | + if (`${file.type}`.toLowerCase().includes('image') || (this.fileType && !fileType.includes(this.fileType))) { | ||
| 302 | + this.$message.warning(`请上传${this.fileType || ''}文件`); | ||
| 303 | + return false; | ||
| 304 | + } | ||
| 305 | + } | ||
| 306 | + if (this.beforeUpload) { | ||
| 307 | + return this.beforeUpload(file); | ||
| 308 | + } | ||
| 309 | + return true; | ||
| 310 | + }, | ||
| 311 | + // 自定义上传 | ||
| 312 | + onHttpRequest(option) { | ||
| 313 | + const formData = new FormData(); | ||
| 314 | + if (option.data) { | ||
| 315 | + Object.keys(option.data).forEach(key => { | ||
| 316 | + formData.append(key, option.data[key]); | ||
| 317 | + }); | ||
| 318 | + } | ||
| 319 | + formData.append(option.filename, option.file, option.file.name); | ||
| 320 | + if (this.httpRequest) { | ||
| 321 | + this.httpRequest({ ...option, formData }); | ||
| 322 | + } else { | ||
| 323 | + const request = this.http || this.$axios; | ||
| 324 | + if (request && request.post) { | ||
| 325 | + request | ||
| 326 | + .post(option.action, formData, { headers: option.headers }) | ||
| 327 | + .then(response => { | ||
| 328 | + this.onSuccess(response.data); | ||
| 329 | + }) | ||
| 330 | + .catch(error => { | ||
| 331 | + this.onError(error); | ||
| 332 | + }); | ||
| 333 | + } | ||
| 334 | + } | ||
| 335 | + }, | ||
| 336 | + // 上传失败 | ||
| 337 | + onError(err) { | ||
| 338 | + this.$message.error('上传失败, 系统异常!'); | ||
| 339 | + }, | ||
| 340 | + // 上传成功 | ||
| 341 | + onSuccess(response) { | ||
| 342 | + if (response.success) { | ||
| 343 | + const { result } = response || {}; | ||
| 344 | + if (this.responseFilter) { | ||
| 345 | + this.imageList.push(this.responseFilter(response)); | ||
| 346 | + } else if (result) { | ||
| 347 | + this.imageList.push(result[0]); | ||
| 348 | + } | ||
| 349 | + this.$emit('input', this.imageList.join(',')); | ||
| 350 | + } else { | ||
| 351 | + if (response.businessException) { | ||
| 352 | + this.$message.error('上传失败!' + response.message); | ||
| 353 | + } else { | ||
| 354 | + this.$message.error('上传失败!'); | ||
| 355 | + } | ||
| 356 | + } | ||
| 357 | + this.$emit('upload', response); | ||
| 358 | + }, | ||
| 359 | + // 文件超出个数限制 | ||
| 360 | + onExceed() { | ||
| 361 | + this.$message.warning('文件个数超出限制!'); | ||
| 362 | + }, | ||
| 363 | + // 拖动图片 | ||
| 364 | + onDragFile() { | ||
| 365 | + this.$emit('input', this.imageList.join(',')); | ||
| 50 | }, | 366 | }, |
| 51 | }, | 367 | }, |
| 52 | }; | 368 | }; |
| 53 | </script> | 369 | </script> |
| 54 | 370 | ||
| 55 | <style lang="scss"> | 371 | <style lang="scss"> |
| 56 | -.zee-upload { | ||
| 57 | - display: inline-flex; | 372 | +.z-upload { |
| 373 | + &, | ||
| 374 | + .el-upload-list.el-upload-list--picture-card { | ||
| 375 | + display: inline-flex; | ||
| 376 | + flex-wrap: wrap; | ||
| 377 | + } | ||
| 378 | + /* 当上传内容为文件时,默认显示对应的图标 */ | ||
| 379 | + .el-upload-list__item-thumbnail--file { | ||
| 380 | + height: 100%; | ||
| 381 | + width: 100%; | ||
| 382 | + background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='60' height='60'%3E%3Cpath d='M176 160h304a472.432 472.432 0 0 1 64 64l128 208a64 64 0 0 1-64 64H176a64 64 0 0 1-64-64V224a64 64 0 0 1 64-64z' fill='%23A1CBFE'/%3E%3Cpath d='M176 288h688q64 0 64 64v432q0 64-64 64H176q-64 0-64-64V352q0-64 64-64z' fill='%234799FE'/%3E%3Cpath d='M336 688h368q32 0 32 32t-32 32H336q-32 0-32-32t32-32z' fill='%23FFF'/%3E%3Cpath d='M832 336h16q32 0 32 32v16q0 32-32 32h-16q-32 0-32-32v-16q0-32 32-32z' fill='%23A1CBFE'/%3E%3C/svg%3E"); | ||
| 383 | + background-repeat: no-repeat; | ||
| 384 | + background-position: center; | ||
| 385 | + background-size: 60%; | ||
| 386 | + &.word { | ||
| 387 | + background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='81' height='81'%3E%3Cpath d='M665.6 0l256 256v716.8a51.2 51.2 0 0 1-51.2 51.2H153.6a51.2 51.2 0 0 1-51.2-51.2V51.2A51.2 51.2 0 0 1 153.6 0zM284.16 360.96l94.72 330.24h56.32l64-248.32h2.56l64 248.32h56.32l94.72-330.24h-61.44l-61.44 250.88h-2.56l-64-250.88h-56.32L409.6 611.84h-2.56L345.6 360.96z' fill='%234E97FF'/%3E%3Cpath d='M665.6 0l256 256h-256z' fill='%23A4D2FF'/%3E%3C/svg%3E"); | ||
| 388 | + } | ||
| 389 | + &.excel { | ||
| 390 | + background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='81' height='81'%3E%3Cpath d='M139.456 0c-8.896 0-22.24 4.48-35.616 13.344-13.344 8.928-13.344 26.72-13.344 35.616v921.6c0 13.376 4.48 26.72 13.344 35.648 13.376 13.344 26.72 17.792 35.616 17.792h752.448c13.344 0 26.688-4.48 35.616-13.344 8.896-8.928 8.896-22.272 8.896-35.616V289.376L651.488 0h-512z' fill='%235ACC9B'/%3E%3Cpath d='M936.416 289.376h-231.52c-13.344 0-26.72-4.448-35.616-13.344-8.896-8.896-13.344-22.272-13.344-35.616V0l280.48 289.376z' fill='%23BDEBD7'/%3E%3Cpath d='M477.824 538.72L362.08 378.432h80.128l75.712 115.776 80.128-115.776h75.68L557.984 538.72l124.64 173.632H598.08L517.952 587.68l-84.608 124.672h-80.16z' fill='%23FFF'/%3E%3C/svg%3E"); | ||
| 391 | + } | ||
| 392 | + &.ppt { | ||
| 393 | + background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='81' height='81'%3E%3Cpath d='M880.085 1017.43h-736.17a58.539 58.539 0 0 1-58.582-58.283V58.283C85.333 26.368 111.445 0 143.915 0h513.024l281.728 288.768v670.379c0 32.298-26.112 58.282-58.582 58.282z' fill='%23FF9540'/%3E%3Cpath d='M644.437 0a15.36 15.36 0 0 0-1.152 6.059v229.888c0 32.554 27.179 59.434 60.928 59.434h234.454v-.384L645.632 0h-1.195z' fill='%23FFF' fill-opacity='.496'/%3E%3Cpath d='M511.403 573.355h-55.51v115.882h-75.178V361.045h137.898c80.086 2.219 121.6 36.608 124.63 103.894 1.152 72.149-42.667 108.373-131.84 108.373zm-6.016-154.368h-49.494v97.92h49.494c38.912-.768 58.922-17.195 60.074-48.982-1.152-31.744-21.162-47.829-60.074-48.938z' fill='%23FFF'/%3E%3C/svg%3E"); | ||
| 394 | + } | ||
| 395 | + &.pdf { | ||
| 396 | + background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='81' height='81'%3E%3Cpath d='M136.533 0a49.12 49.12 0 0 0-35.84 15.36C91.307 25.6 85.333 38.4 85.333 51.2v921.6a49.12 49.12 0 0 0 15.36 35.84 50.547 50.547 0 0 0 35.84 15.36h750.933a49.12 49.12 0 0 0 35.84-15.36 50.547 50.547 0 0 0 15.36-35.84V290.133L648.533 0z' fill='%23FF5562'/%3E%3Cpath d='M938.666 290.133H699.733a52.493 52.493 0 0 1-51.2-51.2V0z' fill='%23FFBBC0'/%3E%3Cpath d='M708.266 865.333c-53.76 0-101.6-92.213-127.146-152-42.667-17.92-89.6-34.133-134.827-45.226-40.106 26.56-107.52 65.76-159.626 65.76-32.427 0-55.467-16.214-64-44.374-6.827-23.04-.854-39.253 5.973-47.786q20.48-28.16 84.48-28.16c34.133 0 77.653 5.973 126.293 17.92a762.026 762.026 0 0 0 91.307-75.094c-12.8-59.733-26.453-156.16 8.533-200.533 17.067-21.333 43.52-28.16 75.094-18.773 34.986 10.24 47.786 31.573 52 47.786 14.506 58.027-52 136.534-97.334 182.667 10.24 40.107 23.04 81.92 39.254 120.32 65.066 28.96 141.813 71.627 150.4 118.56 3.413 16.213-1.707 31.573-14.507 44.373-11.094 9.333-23.04 14.507-35.84 14.507zm-79.36-129.706C661.334 801.333 692 832 708.267 832c2.56 0 5.974-.853 11.094-5.12 5.973-5.973 5.973-10.24 5.12-13.653-3.414-17.067-30.667-45.227-95.573-77.654zm-315.733-87.894c-41.813 0-53.76 10.24-57.173 14.507-.853 1.707-4.267 5.973-.853 17.92 2.56 10.24 9.333 20.48 31.573 20.48 27.307 0 66.56-15.36 112.64-42.667-33.333-6.826-62.293-10.24-86.187-10.24zm168.96-5.12a921.586 921.586 0 0 1 81.92 27.307c-9.333-24.747-17.066-50.347-23.893-75.093-18.773 16.213-38.4 32.426-58.027 47.786zM588 366.933c-9.333 0-16.213 3.414-22.187 10.24-17.92 22.187-19.626 78.507-5.973 150.187 52-55.467 80.213-106.667 73.333-133.973-.853-4.267-4.266-16.214-28.16-23.04A46.413 46.413 0 0 0 588 366.933z' fill='%23FFF'/%3E%3C/svg%3E"); | ||
| 397 | + } | ||
| 398 | + &.zip { | ||
| 399 | + background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='81' height='81'%3E%3Cpath d='M61.156 685.511h910.222V921.6c0 28.444-24.178 52.622-52.622 52.622H113.778c-28.445 0-52.622-24.178-52.622-52.622V685.511z' fill='%2389D543'/%3E%3Cpath d='M61.156 352.711h910.222v332.8H61.156z' fill='%23FA6A68'/%3E%3Cpath d='M113.778 64h804.978c28.444 0 52.622 24.178 52.622 52.622v236.09H61.156v-236.09C61.156 88.178 85.333 64 113.778 64z' fill='%2360CEF8'/%3E%3Cpath d='M391.111 64H652.8v910.222H391.111z' fill='%23FDB84B'/%3E%3Cpath d='M760.889 442.311v-28.444H270.222v193.422H760.89V442.31zm-35.556 8.533v122.312H305.778V450.844h419.555z' fill='%23FFF'/%3E%3C/svg%3E"); | ||
| 400 | + } | ||
| 401 | + } | ||
| 402 | + /* 上传项外部类,用于撑开布局,显示角标按钮 */ | ||
| 403 | + .el-upload-list__item-wrapper { | ||
| 404 | + position: relative; | ||
| 405 | + display: inline-block; | ||
| 406 | + margin-right: 10px; | ||
| 407 | + } | ||
| 408 | + /* 自定义角标删除按钮样式 */ | ||
| 409 | + .el-upload-list__item { | ||
| 410 | + margin-right: 0 !important; | ||
| 411 | + } | ||
| 412 | + /* 自定义角标删除按钮样式 */ | ||
| 413 | + .corner-close { | ||
| 414 | + position: absolute; | ||
| 415 | + top: 0; | ||
| 416 | + right: 0; | ||
| 417 | + transform: translateX(50%) translateY(-50%); | ||
| 418 | + height: 30px; | ||
| 419 | + width: 30px; | ||
| 420 | + min-width: 30px; | ||
| 421 | + display: flex; | ||
| 422 | + align-items: center; | ||
| 423 | + justify-content: center; | ||
| 424 | + background-color: rgba(lighten($red, 15%), 0.5); | ||
| 425 | + color: #fff; | ||
| 426 | + border-radius: 50%; | ||
| 427 | + z-index: 20; | ||
| 428 | + font-size: 16px; | ||
| 429 | + cursor: pointer; | ||
| 430 | + &:hover { | ||
| 431 | + background-color: $red; | ||
| 432 | + } | ||
| 433 | + } | ||
| 434 | + /* 修改卡片样式 */ | ||
| 435 | + .el-upload--picture-card { | ||
| 436 | + line-height: 1.5; | ||
| 437 | + display: flex; | ||
| 438 | + align-items: center; | ||
| 439 | + justify-content: center; | ||
| 440 | + } | ||
| 441 | + /* 修改图片按钮样式 */ | ||
| 442 | + .el-upload-list--picture-card .el-upload-list__item-actions { | ||
| 443 | + display: flex; | ||
| 444 | + align-items: center; | ||
| 445 | + justify-content: space-around; | ||
| 446 | + .el-upload-list__item-preview, | ||
| 447 | + .el-upload-list__item-delete { | ||
| 448 | + display: inline-flex; | ||
| 449 | + align-items: center; | ||
| 450 | + justify-content: center; | ||
| 451 | + } | ||
| 452 | + span + span { | ||
| 453 | + margin-left: 0; | ||
| 454 | + } | ||
| 455 | + &::after { | ||
| 456 | + display: none; | ||
| 457 | + } | ||
| 458 | + .block-preview, | ||
| 459 | + .block-download { | ||
| 460 | + height: 100%; | ||
| 461 | + width: 100%; | ||
| 462 | + display: flex; | ||
| 463 | + align-items: center; | ||
| 464 | + justify-content: center; | ||
| 465 | + cursor: pointer; | ||
| 466 | + } | ||
| 467 | + } | ||
| 468 | + /* 修改拖拽上传的默认样式 */ | ||
| 469 | + .el-upload-dragger { | ||
| 470 | + height: 100%; | ||
| 471 | + width: 100%; | ||
| 472 | + display: inline-flex; | ||
| 473 | + align-items: center; | ||
| 474 | + justify-content: center; | ||
| 475 | + border: none; | ||
| 476 | + background-color: transparent; | ||
| 477 | + &.is-dragover { | ||
| 478 | + border-color: transparent; | ||
| 479 | + } | ||
| 480 | + } | ||
| 481 | + /* 修改图片上传组件卡片模式默认样式 */ | ||
| 482 | + &.mini { | ||
| 483 | + .el-upload--picture-card, | ||
| 484 | + .el-upload-list--picture-card .el-upload-list__item { | ||
| 485 | + height: 60px; | ||
| 486 | + width: 60px; | ||
| 487 | + } | ||
| 488 | + .el-upload--picture-card i { | ||
| 489 | + font-size: 20px; | ||
| 490 | + } | ||
| 491 | + .corner-close { | ||
| 492 | + height: 20px; | ||
| 493 | + width: 20px; | ||
| 494 | + min-width: 20px; | ||
| 495 | + font-size: 12px; | ||
| 496 | + } | ||
| 497 | + } | ||
| 498 | + &.small { | ||
| 499 | + .el-upload--picture-card, | ||
| 500 | + .el-upload-list--picture-card .el-upload-list__item { | ||
| 501 | + height: 100px; | ||
| 502 | + width: 100px; | ||
| 503 | + } | ||
| 504 | + .corner-close { | ||
| 505 | + height: 24px; | ||
| 506 | + width: 24px; | ||
| 507 | + min-width: 24px; | ||
| 508 | + font-size: 14px; | ||
| 509 | + } | ||
| 510 | + } | ||
| 511 | + /* 图片缩略图 */ | ||
| 512 | + .el-upload-list--picture-card .el-upload-list__item-thumbnail { | ||
| 513 | + object-fit: cover; | ||
| 514 | + } | ||
| 58 | } | 515 | } |
| 59 | </style> | 516 | </style> |