<template>
  <el-upload
    ref="uploadRef"
    class="bg-upload"
    v-bind="$attrs"
    :file-list="fileList"
    :action="action"
    :data="{
      directory: 'image',
      uniqueCode: false,
    }"
    :auto-upload="autoUpload"
    :list-type="listType"
    :limit="limit"
    :accept="acceptTypes"
    :before-upload="handleBeforeUpload"
    :on-success="handleSuccess"
    :on-remove="handleRemove"
    :on-preview="handlePreview"
    :multiple="multiple">
    <template v-slot:trigger>
      <el-icon v-if="listType === 'picture-card'"><Plus /></el-icon>
      <!-- <i class="el-icon-plus" v-if="listType === 'picture-card'"></i> -->
      <el-button type="primary" :icon="UploadFilled" v-else>
        {{ triggerText }}
      </el-button>
    </template>

    <template v-if="!autoUpload">
      <el-button type="success" icon="el-icon-position" @click="submitUpload" style="margin-left: 16px">
        上传到服务器
      </el-button>
    </template>

    <template v-slot:tip v-if="showTips && tips">
      <div class="el-upload__tip" style="color: #909bb6">
        {{ customTips || tips }}
      </div>
    </template>
  </el-upload>

  <el-dialog title="图片预览" v-model="dialogVisible" class="bg-upload-image-dialog">
    <img style="margin: 30px 0; width: 600px" :src="dialogImageUrl" alt="Preview Image" />
  </el-dialog>
</template>

<script setup>
import { UploadFilled } from "@element-plus/icons-vue";
import { computed, watch, nextTick, onMounted, reactive, ref, toRefs } from "vue";
import { ElMessage } from "element-plus";

const props = defineProps({
  modelValue: {
    type: Array,
    default: () => [],
  },
  action: {
    type: String,
    default: "/apaas/common/image/upload",
  },
  autoUpload: {
    type: Boolean,
    default: true,
  },
  listType: {
    type: String,
    default: "text",
  },
  limit: {
    type: Number,
  },
  multiple: {
    type: Boolean,
    default: false,
  },

  accept: {
    type: [Array, String],
  }, // 接受类型
  fileSize: {
    type: Number,
  }, // 文件大小
  fileSizeUnit: {
    type: String,
    default: "MB",
  }, // 文件单位 KB/MB/GB
  triggerText: {
    type: String,
    default: "点击上传",
  }, // 按钮文字
  showTips: {
    type: Boolean,
    default: false,
  }, // 显示提示
  customTips: {
    type: String,
    default: "",
  }, // 自定义提示内容
});

const emit = defineEmits(["update:modelValue", "change"]);

const uploadRef = ref(null);

const state = reactive({
  fileList: [],
  dialogImageUrl: "",
  dialogVisible: false,
});

const acceptTypes = computed(() => {
  if (Array.isArray(props.accept)) {
    return props.accept.join(",");
  } else {
    return props.accept;
  }
});

const types = computed(() => {
  return acceptTypes.value.split(",").filter((v) => v !== "");
});

const tips = computed(() => {
  let str = "";
  if (types.value.length > 0) {
    str += `后缀为${types.value.join("、")}`;
  }
  if (props.fileSize) {
    if (str) str += "且";
    str += `大小不超过${props.fileSize}${props.fileSizeUnit}`;
  }
  if (str) str += "的文件";

  if (props.limit) {
    str += `，最多上传 ${props.limit} 个文件`;
  }
  if (str) {
    str = "支持" + str;
  }
  return str;
});

const checkLimit = (filelist) => {
  const limit = props.limit;
  const uploadDom = uploadRef.value;
  const length = uploadDom.$el.children[0].children.length;
  if (filelist.length === limit) {
    uploadDom.$el.children[0].children[length - 1].style.display = "none";
  } else {
    uploadDom.$el.children[0].children[length - 1]
      ? (uploadDom.$el.children[0].children[length - 1].style.display = "")
      : "";
  }
};

watch(
  () => props.modelValue,
  () => {
    let newStr = props.modelValue.map((v) => v.url).join(",");
    let oldStr = state.fileList.map((v) => (v.response && v.response.data) || v.url).join(",");
    if (newStr !== oldStr) {
      state.fileList = [...props.modelValue];
    }
    nextTick().then(() => {
      checkLimit(props.modelValue);
    });
  }
);

const handleBeforeUpload = (file) => {
  let units = {
    KB: 1024,
    MB: 1024 * 1024,
    GB: 1024 * 1024 * 1024,
  };
  let temp = file.name.split(".");
  let type = "." + temp[temp.length - 1].toLocaleLowerCase();
  let fileTypeIsOk = types.value.length === 0 || types.value.indexOf(type) > -1;
  let fileSizeIsOk =
    props.fileSize === 0 || props.fileSize === undefined || file.size / units[props.fileSizeUnit] <= props.fileSize;
  let checked = fileTypeIsOk && fileSizeIsOk;

  if (!checked) {
    ElMessage.error(tips.value);
  }

  return checked;
};
const handleSuccess = (response, file, fileList) => {
  updateFileList(fileList);
  checkLimit(fileList);
};
const handleRemove = (file, fileList) => {
  updateFileList(fileList);
  checkLimit(fileList);
};
const handlePreview = ({ name, url }) => {
  state.dialogImageUrl = url;
  state.dialogVisible = true;
  // let a = document.createElement("a"); // 生成一个a元素
  // let event = new MouseEvent("click"); // 创建一个单击事件
  // a.download = name; // 设置图片名称
  // a.href = url; // 将生成的URL设置为a.href属性
  // a.dispatchEvent(event); // 触发a的单击事件
};
const updateFileList = (fileList) => {
  let values = fileList.map((v) => {
    return {
      name: v.name,
      url: (v.response && v.response.data) || v.url,
    };
  });

  state.fileList = fileList;

  emit("update:modelValue", values);
  emit("change", values);
};
const submitUpload = () => {
  uploadRef.value.submit();
};
onMounted(() => {
  state.fileList = [...props.modelValue];
  nextTick().then(() => {
    checkLimit(props.modelValue);
  });
});
const { fileList, dialogImageUrl, dialogVisible } = toRefs(state);
</script>
