<template>
  <div class="gm__upload--image">
    <n-space class="images--wrap">
      <div
        v-for="(item, index) in filePathList"
        :key="index"
        class="image__wrap w-120px h-120px border-1px border-solid rounded-md overflow-hidden"
      >
        <n-image class="w-full h-full" :object-fit="props.imgMode" :src="item" />
        <div v-if="!disabled" class="mask" @click="handleDelImage(index)">
          <Icon class="text-24px" icon="ic:baseline-delete-outline" />
        </div>
      </div>
      <div v-if="!isGreaterThenMaximum && !props.disabled" class="upload--button" @click="handleOpenChooseFile">
        <Icon class="text-24px" icon="ic:baseline-add" />
      </div>
    </n-space>

    <input
      ref="upload"
      :accept="acceptTypes"
      multiple
      type="file"
      name="upload"
      style="display: none"
      @change="handleGetFileData"
    />
  </div>
</template>
<script setup lang="ts">
import { ref, nextTick, computed, watch } from 'vue';
import { Icon } from '@iconify/vue';
import { fetchUploadImgFile } from '@/service';

const emits = defineEmits(['update:file', 'update:files']);

interface Props {
  file?: string /** 单个文件 */;
  files?: any /** 多个文件 */;
  acceptTypes?: string /** 允许上传的图片类型 默认 'image/jpeg, image/jpg, image/png' */;
  max?: number /** 最多允许上传多少张图 */;
  disabled: boolean /** 是否禁用 */;
  imgMode: 'fill' | 'none' | 'contain' | 'cover' | 'scale-down';
  /** 场景 */
  scene: string;
}

const props = withDefaults(defineProps<Props>(), {
  acceptTypes: 'image/jpeg, image/jpg, image/png, image/gif',
  max: 3,
  file: '',
  files: null,
  disabled: false,
  imgMode: 'cover',
  scene: ''
});

const filePathList = ref<string[]>([]);
const upload = ref();

watch(
  () => props.file,
  async val => {
    if (val) {
      filePathList.value.length = 0;
      filePathList.value.push(val);
    }
  },
  {
    immediate: true,
    deep: true
  }
);

/** 是否超出最大值 */
const isGreaterThenMaximum = computed(() => {
  return filePathList.value.length >= props.max || props.file !== '';
});

/** 选择文件 */
function handleOpenChooseFile() {
  if (props.disabled) return;
  upload.value.click();
}
/** 获取文件数据 */
function handleGetFileData() {
  nextTick(() => {
    const files = [...upload.value.files];
    files.forEach(file => {
      const isOk = beforeUpload(file);
      if (isOk) hanldeUpload(file);
    });
  });
}
/** 上传前的校验 */
function beforeUpload(file: File) {
  const isAccept = props.acceptTypes.includes(file.type);
  if (!isAccept) {
    window.$message?.error(`${file.name} 格式有误！`);
    return false;
  }

  const maxFileSize = 5 * 1024 * 1024;
  if (file.size > maxFileSize) {
    window.$message?.error(`请上传5M以内的图片！`);
    return false;
  }
  return true;
}

/** 处理上传 */
async function hanldeUpload(file: File) {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('scene', props.scene);
  const res = await fetchUploadImgFile(formData);
  if (res.data?.ok) {
    filePathList.value.push(res.data.data.fullUrl);
    onUpdate();
  }
}

/** 删除图片 */
function handleDelImage(index: number) {
  window.$dialog?.info({
    title: '提示',
    content: '您确定要删除这个图片吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      filePathList.value.splice(index, 1);
      onUpdate();
    }
  });
}

/** 更新 */
function onUpdate() {
  if (props.max === 1) {
    emits('update:file', filePathList.value[0]);
  } else {
    emits('update:files', filePathList.value);
  }
}
</script>
<style lang="scss">
.upload--button {
  background-color: #f7f9f8;
  border: 1px dashed #ccc;
  border-radius: 6px;
  box-sizing: border-box;
  width: 120px;
  height: 120px;
  cursor: pointer;
  vertical-align: top;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  transition: border 0.4s;
  position: relative;
  > svg {
    color: gray;
  }
  &:hover {
    border: 1px dashed #666;
  }
  .disabled {
    position: absolute;
    left: 0;
    right: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(204, 204, 204, 0.5);
  }
}
.image__wrap {
  position: relative;
  cursor: pointer;
  &:hover {
    .mask {
      opacity: 1 !important;
    }
  }
  .mask {
    opacity: 0;
    width: 35px;
    transition: all 0.3s;
    height: 35px;
    position: absolute;
    right: 0;
    top: 0;
    border-radius: 0 0 0 50%;
    background-color: #f56c6c;
    display: flex;
    justify-content: center;
    align-items: center;
    > svg {
      color: #f7f7f7;
    }
  }
}
</style>
