HcFileUpload.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <template>
  2. <el-upload ref="uploadRef" class="hc-file-upload-box" :action="api + action" :headers="getTokenHeader()" :data="uploadData" :accept="accept" :disabled="uploadDisabled" multiple :show-file-list="false"
  3. :on-success="uploadSuccess" :on-exceed="uploadExceed" :on-error="uploadError" :before-upload="beforeUpload" :on-progress="uploadprogress">
  4. <slot></slot>
  5. </el-upload>
  6. </template>
  7. <script setup>
  8. import {ref,watch,onMounted} from "vue";
  9. import {getTokenHeader} from '~src/api/request/header';
  10. import {isSize, deepClone, getObjValue} from "vue-utils-plus"
  11. const props = defineProps({
  12. datas: {
  13. type: Object,
  14. default: () => ({})
  15. },
  16. api: {
  17. type: String,
  18. default: "/api/blade-resource/oss/endpoint/"
  19. },
  20. action: {
  21. type: String,
  22. default: "upload-file"
  23. },
  24. accept: {
  25. type: String,
  26. default: "image/png,image/jpg,image/jpeg,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/pdf,.doc,.docx,application/msword"
  27. },
  28. size: {
  29. type: Number,
  30. default: 60
  31. }
  32. })
  33. //变量
  34. const uploadRef = ref(null)
  35. const uploadData = ref(props.datas)
  36. const uploadDisabled = ref(false)
  37. //监听
  38. watch(() => [
  39. props.datas,
  40. ], ([datas]) => {
  41. uploadData.value = datas
  42. })
  43. //渲染完成
  44. onMounted(()=> {
  45. beforeFileNum.value = 0
  46. finishFileNum.value = 0
  47. errorFileNum.value = 0
  48. })
  49. //事件
  50. const emit = defineEmits(['change', 'progress'])
  51. //上传前
  52. const beforeFileNum = ref(0)
  53. const beforeUpload = async (file) => {
  54. if (isSize(file?.size, props.size)) {
  55. beforeFileNum.value ++;
  56. return true;
  57. } else {
  58. beforeFileNum.value = 0;
  59. window?.$message?.warning(`文件大小, 不能过${props.size}M!`);
  60. return false;
  61. }
  62. }
  63. //超出限制时
  64. const uploadExceed = () => {
  65. window?.$message?.warning(`请上传 ${props.accept} 格式的文件,文件大小不超过${props.size}M`);
  66. }
  67. //上传中
  68. const uploadprogress = () => {
  69. uploadDisabled.value = true
  70. emit('progress', true)
  71. }
  72. //上传完成
  73. const finishFileNum = ref(0)
  74. const uploadSuccess = (response, uploadFile, uploadFiles) => {
  75. finishFileNum.value ++;
  76. if (beforeFileNum.value === finishFileNum.value) {
  77. const fileList = getUploadFile(deepClone(uploadFiles))
  78. uploadClearFiles()
  79. emit('change', {type: 'success', fileList})
  80. emit('progress', false)
  81. }
  82. }
  83. //上传失败
  84. const errorFileNum = ref(0)
  85. const uploadError = (error,uploadFile,uploadFiles) => {
  86. errorFileNum.value ++;
  87. window?.$message?.error('上传失败');
  88. const num = finishFileNum.value + errorFileNum.value;
  89. if (beforeFileNum.value === num) {
  90. const fileList = getUploadFile(deepClone(uploadFiles))
  91. uploadClearFiles()
  92. emit('change', {type: 'error', fileList})
  93. emit('progress', false)
  94. }
  95. }
  96. const uploadClearFiles = () => {
  97. finishFileNum.value = 0
  98. beforeFileNum.value = 0
  99. errorFileNum.value = 0
  100. uploadDisabled.value = false
  101. uploadRef.value?.clearFiles()
  102. }
  103. //获取文件
  104. const getUploadFile = (fileList) => {
  105. let fileArr = [];
  106. for (let i = 0; i < fileList.length; i++) {
  107. const item = getObjValue(fileList[i]?.response?.data)
  108. fileArr.push(item)
  109. }
  110. return fileArr
  111. }
  112. </script>
  113. <style lang="scss">
  114. .hc-file-upload-box .el-upload-list .el-upload-list__item {
  115. .el-upload-list__item-status-label, .el-icon--close-tip {
  116. display: none;
  117. }
  118. }
  119. </style>