ElFileUpload.vue 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. <script lang="ts" setup>
  2. import { useUserStore } from '@/stores/user'
  3. import { ACCESS_TOKEN } from '@/utils/constants'
  4. import { ElMessage } from 'element-plus'
  5. import { isAbsolutePath, ossUpload } from '@/utils/utils'
  6. import config from '@/config/defaultSetting'
  7. import type { UploadProps, UploadFile } from 'element-plus'
  8. import type { BasicFormItem } from '@/types/form'
  9. interface Props {
  10. modelValue: any
  11. item?: BasicFormItem
  12. fileSize?: number | string
  13. uploadApi?: string
  14. oss?: boolean
  15. }
  16. const props = withDefaults(defineProps<Props>(), {
  17. uploadApi: config.uploadApi,
  18. fileSize: 100,
  19. oss: config.oss
  20. })
  21. const emits = defineEmits(['update:modelValue'])
  22. const modelValue = computed({
  23. get: () => props.modelValue,
  24. set: value => emits('update:modelValue', value)
  25. })
  26. const user = useUserStore()
  27. const baseApi = import.meta.env.VITE_BASE_API
  28. const headers = reactive({
  29. [ACCESS_TOKEN]: user.token
  30. })
  31. // 在上传之前对文件进行验证
  32. const fileSize = Number(props.fileSize) || 100
  33. const beforeUpload: UploadProps['beforeUpload'] = rawFile => {
  34. if (rawFile.size / 1024 / 1024 > fileSize) {
  35. ElMessage.error(`文件大小不能超过${fileSize}MB!`)
  36. return false
  37. }
  38. return true
  39. }
  40. // 上传成功
  41. const uploadList = ref([...props.modelValue])
  42. const handleUploadSuccess: UploadProps['onSuccess'] = (response, uploadFile: UploadFile, uploadFiles: UploadFile[]) => {
  43. if (response.success || response.code === 200) {
  44. // 附加oss路径
  45. uploadList.value = uploadFiles
  46. } else {
  47. ElMessage.error(response.msg)
  48. }
  49. }
  50. // 删除文件
  51. const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
  52. uploadList.value = uploadFiles
  53. }
  54. // 动态属性
  55. const attrs: any = props.oss ? { 'http-request': ossUpload } : {}
  56. if (props.item) {
  57. // 接口需要的属性
  58. props.item.extra = computed(() =>
  59. uploadList.value.map((item: any) => ({
  60. name: item.name,
  61. url: item.response?.url || item.url
  62. }))
  63. )
  64. if (!props.item.props?.onSuccess) {
  65. attrs['on-success'] = handleUploadSuccess
  66. }
  67. }
  68. </script>
  69. <template>
  70. <el-upload
  71. v-model:file-list="modelValue"
  72. :action="isAbsolutePath(props.uploadApi) ? props.uploadApi : baseApi + props.uploadApi"
  73. :headers="headers"
  74. :before-upload="beforeUpload"
  75. :on-remove="handleRemove"
  76. v-bind="{ ...attrs, ...$attrs }"
  77. >
  78. <template #[slot.name]="slotProps" v-for="slot in item?.slots" :key="slot.alias">
  79. <slot :name="slot.alias" v-bind="slotProps">
  80. <el-button type="primary">上传</el-button>
  81. </slot>
  82. </template>
  83. </el-upload>
  84. </template>
  85. <style lang="scss" scoped></style>