image-upload.vue 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. <template>
  2. <div>
  3. <el-upload
  4. class="uploader"
  5. :action="oss_url"
  6. :data="dataObj"
  7. :multiple="multiple"
  8. name="file"
  9. :accept="accept"
  10. :show-file-list="false"
  11. :on-success="uploadSuccess"
  12. :before-upload="beforeUpload"
  13. />
  14. <div class="images">
  15. <div v-for="(item, index) in fileList" :key="index" class="item">
  16. <div v-if="item.url" class="img" @mouseover="item.hover = true;" @mouseout="item.hover = false;">
  17. <el-image v-if="checkFileType(item.url) == 'image'" ref="img" :src="imageURL + item.url" :preview-src-list="previewImages" style="width: 120px; height: 120px" fit="cover" />
  18. <el-image v-else ref="img" :src="imageURL + item.url" style="width: 120px; height: 120px" fit="cover">
  19. <div slot="error" class="image-slot">
  20. <img v-if="checkFileType(item.url) == 'word'" class="file" src="@/assets/common/word.png">
  21. <img v-if="checkFileType(item.url) == 'excel'" class="file" src="@/assets/common/excel.png">
  22. <img v-if="checkFileType(item.url) == 'ppt'" class="file" src="@/assets/common/ppt.png">
  23. <img v-if="checkFileType(item.url) == 'pdf'" class="file" src="@/assets/common/pdf.png">
  24. <img v-if="checkFileType(item.url) == 'file'" class="file" src="@/assets/common/zip.jpeg">
  25. </div>
  26. </el-image>
  27. <div v-show="item.hover" class="mask">
  28. <i v-if="checkFileType(item.url) == 'image'" class="el-icon-zoom-in" @click="previewImage(item.url)" />
  29. <i class="el-icon-upload2" @click="uploadImage(item.url)" />
  30. <i class="el-icon-delete" @click="deleteImage(item.url)" />
  31. </div>
  32. </div>
  33. </div>
  34. <div v-if="multiple || (!multiple && fileList.length < 1)" class="add" @click="uploadImage()"><i class="el-icon-plus" /></div>
  35. </div>
  36. </div>
  37. </template>
  38. <script>
  39. import { getOssConfig } from '@/api/common'
  40. import { findElem } from '@/utils/util'
  41. export default {
  42. name: 'FileUpload',
  43. props: {
  44. // 接受上传的文件列表
  45. fileList: Array,
  46. // 接受上传的文件类型
  47. fileType: {
  48. type: Array,
  49. default: () => ['image', 'word', 'excel', 'ppt', 'pdf', 'file']
  50. },
  51. // 是否支持多选文件
  52. multiple: {
  53. type: Boolean,
  54. default: false
  55. },
  56. startRestricting: {
  57. type: Boolean,
  58. default: false
  59. },
  60. restrictFilename: {
  61. type: Array,
  62. default: () => {
  63. return []
  64. }
  65. }
  66. },
  67. data() {
  68. return {
  69. imageURL: this.$imageUrl,
  70. oss_url: '',
  71. dataObj: {},
  72. uploadImageUrl: '',
  73. waitUploadList: [],
  74. fileName: ''
  75. }
  76. },
  77. computed: {
  78. isShowFileList: {
  79. get: function() {
  80. if (this.fileList.length > 0 && this.fileList[0].url) {
  81. return true
  82. } else {
  83. return false
  84. }
  85. },
  86. set: function(newValue) {}
  87. },
  88. accept() {
  89. const imageList = ['.jpg', '.jpeg', '.png']
  90. const videoList = ['.mp4']
  91. const wordList = ['.doc', '.docx', '.dot', '.wps', '.wpt']
  92. const excelList = ['.xls', '.xlsx', '.xlt', '.et', '.ett']
  93. const pptList = ['.ppt', '.pptx', '.dps', '.dpt', '.pot', '.pps']
  94. const pdfList = ['.pdf']
  95. const fileList = ['.zip', '.rar', '.gz', '.apk']
  96. let whiteList = []
  97. this.fileType.includes('image') && (whiteList = whiteList.concat(imageList))
  98. this.fileType.includes('video') && (whiteList = whiteList.concat(videoList))
  99. this.fileType.includes('word') && (whiteList = whiteList.concat(wordList))
  100. this.fileType.includes('excel') && (whiteList = whiteList.concat(excelList))
  101. this.fileType.includes('ppt') && (whiteList = whiteList.concat(pptList))
  102. this.fileType.includes('pdf') && (whiteList = whiteList.concat(pdfList))
  103. this.fileType.includes('file') && (whiteList = whiteList.concat(fileList))
  104. return whiteList.join(',')
  105. },
  106. previewImages() {
  107. const fileList = []
  108. if (this.fileList && this.fileList.length > 0) {
  109. this.fileList.forEach(item => {
  110. if (this.checkFileType(item.url) == 'image') {
  111. fileList.push(this.imageURL + item.url)
  112. }
  113. })
  114. }
  115. return fileList
  116. }
  117. },
  118. created() {
  119. getOssConfig().then(res => {
  120. this.oss_url = res.data.host
  121. })
  122. },
  123. methods: {
  124. getUUID() {
  125. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
  126. return (c === 'x' ? (Math.random() * 16) | 0 : 'r&0x3' | '0x8').toString(16)
  127. })
  128. },
  129. createName(name) {
  130. const date = Date.now()
  131. const uuid = this.getUUID()
  132. const fileSuffix = name.substring(name.lastIndexOf('.') + 1)
  133. return `${date}${uuid}.${fileSuffix}`
  134. },
  135. // 检查文件类型
  136. checkFileType(url) {
  137. if (!url) return ''
  138. const fileSuffix = url.substring(url.lastIndexOf('.') + 1)
  139. if (['jpg', 'jpeg', 'png'].includes(fileSuffix)) {
  140. return 'image'
  141. } else if (['doc', 'docx', 'dot', 'wps', 'wpt'].includes(fileSuffix)) {
  142. return 'word'
  143. } else if (['xls', 'xlsx', 'xlt', 'et', 'ett'].includes(fileSuffix)) {
  144. return 'excel'
  145. } else if (['ppt', 'pptx', 'dps', 'dpt', 'pot', 'pps'].includes(fileSuffix)) {
  146. return 'ppt'
  147. } else if (['pdf'].includes(fileSuffix)) {
  148. return 'pdf'
  149. } else if (['zip', 'rar', 'gz', 'apk'].includes(fileSuffix)) {
  150. return 'file'
  151. } {
  152. return 'pdf'
  153. }
  154. },
  155. // 获取oss配置
  156. async getOssConfig(fileName) {
  157. const result = await new Promise((resolve, reject) => {
  158. getOssConfig().then(res => {
  159. const fileKey = this.createName(fileName)
  160. res.data.name = fileName
  161. res.data.key = res.data.dir + fileKey
  162. resolve(res.data)
  163. }).catch(res => {
  164. resolve({})
  165. })
  166. })
  167. return result
  168. },
  169. // 预览图片
  170. previewImage(url) {
  171. const index = findElem(this.fileList, 'url', url)
  172. this.$refs.img[index].showViewer = true
  173. },
  174. // 删除图片
  175. deleteImage(url) {
  176. const index = findElem(this.fileList, 'url', url)
  177. this.fileList.splice(index, 1)
  178. },
  179. // 点击上传
  180. uploadImage(url) {
  181. this.uploadImageUrl = url
  182. document.querySelector('.uploader input').click()
  183. },
  184. // 上传文件之前
  185. async beforeUpload(file) {
  186. const loading = this.$loading({
  187. lock: true,
  188. text: 'Loading',
  189. spinner: 'el-icon-loading',
  190. background: 'rgba(0, 0, 0, 0.7)'
  191. })
  192. this.getFileName(file.name)
  193. this.$emit('handleIsFileName',this.fileName)
  194. this.dataObj = await this.getOssConfig( this.fileName)
  195. console.log(this.dataObj,'ppp');
  196. this.waitUploadList.push(this.dataObj)
  197. },
  198. // 文件上传成功
  199. uploadSuccess(res, file) {
  200. const loading = this.$loading({
  201. lock: true,
  202. text: 'Loading',
  203. spinner: 'el-icon-loading',
  204. background: 'rgba(0, 0, 0, 0.7)'
  205. })
  206. if (this.uploadImageUrl) {
  207. const index = findElem(this.fileList, 'url', this.uploadImageUrl)
  208. this.$set(this.fileList, index, {
  209. name: this.dataObj.name,
  210. url: this.dataObj.key,
  211. hover: false
  212. })
  213. this.waitUploadList = []
  214. } else {
  215. this.getFileName(file.name)
  216. const index = findElem(this.waitUploadList, 'name',this.fileName)
  217. this.fileList.push({
  218. name: this.waitUploadList[index].name,
  219. url: this.waitUploadList[index].key,
  220. hover: false
  221. })
  222. this.waitUploadList.splice(index, 1)
  223. }
  224. this.showFileList = true
  225. loading.close()
  226. },
  227. getFileName(name){
  228. const fileName = name.substring(0, name.lastIndexOf('.'))
  229. let suffix = name.match(/.[^.]+$/)[0]
  230. console.log(suffix,fileName);
  231. // 押金申请上传限制
  232. this.fileName = name
  233. if (this.startRestricting) {
  234. const filterKeywords = this.restrictFilename.filter(k => fileName.includes(k))
  235. console.log(filterKeywords)
  236. if (!filterKeywords.length || suffix.includes('zip', 'rar', 'gz', 'apk')) {
  237. this.fileName = `其他文件${suffix}`
  238. }
  239. // if(filterKeywords.length ){
  240. // }
  241. }
  242. }
  243. }
  244. }
  245. </script>
  246. <style scoped lang="scss">
  247. .images {
  248. display: flex;
  249. flex-wrap: wrap;
  250. .item {
  251. margin-right: 20px;
  252. .img {
  253. width: 120px;
  254. height: 120px;
  255. border-radius: 5px;
  256. overflow: hidden;
  257. position: relative;
  258. border: 1px dashed #eaeaea;
  259. display: flex;
  260. .el-image {
  261. display: block;
  262. }
  263. .file {
  264. width: 120px;
  265. height: 120px;
  266. display: block;
  267. padding: 30px;
  268. }
  269. .mask {
  270. position: absolute;
  271. left: 0;
  272. top: 0;
  273. width: 120px;
  274. height: 120px;
  275. background: rgba($color: #000000, $alpha: 0.3);
  276. display: flex;
  277. align-items: center;
  278. justify-content: center;
  279. i {
  280. font-size: 20px;
  281. color: #ffffff;
  282. cursor: pointer;
  283. margin: 0 8px;
  284. }
  285. }
  286. }
  287. }
  288. .add {
  289. width: 120px;
  290. height: 120px;
  291. border: 1px dashed #eaeaea;
  292. border-radius: 5px;
  293. cursor: pointer;
  294. display: flex;
  295. align-items: center;
  296. justify-content: center;
  297. i {
  298. font-size: 30px;
  299. color: #999;
  300. }
  301. }
  302. }
  303. .uploader {
  304. height: 0;
  305. }
  306. </style>