<script lang="ts" setup>
import { useUserStore } from '@/stores/user'
import { ACCESS_TOKEN } from '@/utils/constants'
import { ElMessage } from 'element-plus'
import { isAbsolutePath, ossUpload } from '@/utils/utils'
import config from '@/config/defaultSetting'
import type { UploadProps, UploadFile } from 'element-plus'
import type { BasicFormItem } from '@/types/form'

interface Props {
  modelValue: any
  item?: BasicFormItem
  fileSize?: number | string
  uploadApi?: string
  oss?: boolean
}
const props = withDefaults(defineProps<Props>(), {
  uploadApi: config.uploadApi,
  fileSize: 100,
  oss: config.oss
})
const emits = defineEmits(['update:modelValue'])

const modelValue = computed({
  get: () => props.modelValue,
  set: value => emits('update:modelValue', value)
})

const user = useUserStore()
const baseApi = import.meta.env.VITE_BASE_API
const headers = reactive({
  [ACCESS_TOKEN]: user.token
})

// 在上传之前对文件进行验证
const fileSize = Number(props.fileSize) || 100
const beforeUpload: UploadProps['beforeUpload'] = rawFile => {
  if (rawFile.size / 1024 / 1024 > fileSize) {
    ElMessage.error(`文件大小不能超过${fileSize}MB!`)
    return false
  }
  return true
}

// 上传成功
const uploadList = ref([...props.modelValue])
const handleUploadSuccess: UploadProps['onSuccess'] = (response, uploadFile: UploadFile, uploadFiles: UploadFile[]) => {
  if (response.success || response.code === 200) {
    // 附加oss路径
    uploadList.value = uploadFiles
  } else {
    ElMessage.error(response.msg)
  }
}

// 删除文件
const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
  uploadList.value = uploadFiles
}

// 动态属性
const attrs: any = props.oss ? { 'http-request': ossUpload } : {}
if (props.item) {
  // 接口需要的属性
  props.item.extra = computed(() =>
    uploadList.value.map((item: any) => ({
      name: item.name,
      url: item.response?.url || item.url
    }))
  )
  if (!props.item.props?.onSuccess) {
    attrs['on-success'] = handleUploadSuccess
  }
}
</script>

<template>
  <el-upload
    v-model:file-list="modelValue"
    :action="isAbsolutePath(props.uploadApi) ? props.uploadApi : baseApi + props.uploadApi"
    :headers="headers"
    :before-upload="beforeUpload"
    :on-remove="handleRemove"
    v-bind="{ ...attrs, ...$attrs }"
  >
    <template #[slot.name]="slotProps" v-for="slot in item?.slots" :key="slot.alias">
      <slot :name="slot.alias" v-bind="slotProps">
        <el-button type="primary">上传</el-button>
      </slot>
    </template>
  </el-upload>
</template>

<style lang="scss" scoped></style>
