<template>
  <div class="w-upload">
    <input class="w-upload-file" @change="uploadChange" type="file" ref="uploadRef" :accept="accept" />
    <div @click="open">
      <slot>
        <el-button :loading="loading" :type="props.type">{{ props.text }}</el-button>
      </slot>
    </div>
  </div>
</template>
<script setup>
import { getCurrentInstance, ref } from 'vue';
import { upload } from '@/api/upload'
import { ElMessage } from 'element-plus';

const emits = defineEmits(["update:modelValue", "uploadStart", "uploadProgress", "uploadEnd", "uploadSuccess", "uploadError"]);

const { proxy } = getCurrentInstance();

const loading = ref(false);

const props = defineProps({
  modelValue: {
    type: String,
    required: true
  },
  type: {
    type: String,
    default: "default"
  },
  text: {
    type: String,
    default: "上传文件"
  },
  accept: {
    type: String,
    default: "*/*"
  },
  timeout: {
    type: Number,
    default: 60000
  },
  loading: {
    type: Boolean,
    default: false
  },
  successMessage: {
    type: String,
    default: ""
  },
  before: {
    type: Function,
    default: () => true
  },
  after: {
    type: Function,
    default: (response)=>response.data.ossId
  },
  url:{
    type:String,
    default:"/upload"
  },
  params:{
    type:Object
  }
});

const open = () => {
  proxy.$refs.uploadRef.click();
}

const uploadChange = async () => {
  let fileInput = proxy.$refs.uploadRef;
  if (fileInput.files.length == 0) {
    return;
  }
  let file = fileInput.files[0];
  fileInput.value = "";

  if (!props.before(file)) {
    return;
  }

  emits("uploadStart", file);

  try {
    loading.value=true;
    let formData = new FormData();
    formData.append("file", file);
    if(props.params){
      for(let name in props.params) {
        formData.append(name,props.params[name]);
      }
    }
    let r = await upload(props.url,formData, (event) => {
      emits("uploadProgress", event);
    }, props.loading, props.timeout);
    if (r.code=200) {
      if (props.successMessage) {
        ElMessage.success(props.successMessage);
      }
      emits("update:modelValue",props.after(r));
      emits("uploadSuccess", r, file);

    } else {
      emits("uploadError", r.msg || r.message, file);
    }
  } catch (e) {
    emits("uploadError", e, file);
  } finally {
    loading.value=false;
    emits("uploadEnd", file);
  }
}

defineExpose({
  open
})

</script>
<style lang="scss" scoped>
.w-upload {
  display: inline-block;
  padding: 0;
  margin: 0;
  vertical-align: middle;
  line-height: 1;

  &-file {
    position: fixed;
    top: -100vh;
  }
  &>div {
    width: 100%;
    height: 100%;
  }
}
</style>