<template>
  <div class="upload-box">
    <n-upload
      :style="{ width: width }"
      action="#"
      :id="uuid"
      :class="['upload', self_disabled ? 'disabled' : '', drag ? 'no-border' : '']"
      :multiple="false"
      :disabled="loading ? true : self_disabled"
      :show-file-list="false"
      :custom-request="handleHttpUpload"
      @before-upload="beforeUpload"
      @error="uploadError"
      :accept="fileType.join(',')"
    >
      <template v-if="imageUrl">
        <img v-if="imageUrl.indexOf('.pdf') < 0" :src="imageUrl" class="upload-image" />
        <div v-else class="upload-image">{{ imageUrl }}</div>
        <div class="upload-handle" @click.stop>
          <div class="handle-icon" @click="editImg" v-if="!self_disabled">
            <n-icon size="20">
              <EditOutlined/>
            </n-icon>
          </div>
          <div class="handle-icon" @click="viewImg">
            <n-icon size="20">
              <ZoomInOutlined/>
            </n-icon>
          </div>
          <div class="handle-icon" @click="deleteImg" v-if="!self_disabled">
            <n-icon size="20">
              <DeleteOutlined/>
            </n-icon>
          </div>
        </div>
      </template>
      <template v-else>
        <div class="upload-empty">
          <slot name="empty">
            <n-icon size="40" color="#666666" v-if="!loading">
              <PlusOutlined/>
            </n-icon>
            <span v-else>上传中{{ progress }}%</span>
          </slot>
        </div>
      </template>
    </n-upload>
    <div class="n-upload__tip">
      <slot name="tip"></slot>
    </div>
  </div>
</template>

<script setup lang="ts" name="UploadImg">
  import { ref, computed, inject } from 'vue';
  import { generateUUID } from '@/utils/auth';
  import { upload } from '@/api/common';
  import {
    PlusOutlined,
    EditOutlined,
    DeleteOutlined,
    ZoomInOutlined,
  } from '@vicons/antd';
import { useNotification } from 'naive-ui'

  interface UploadFileProps {
    imageUrl?: string; // 图片地址 ==> 必传
    uploadFileUrl?: string; // 上传图片的 api 方法，一般项目上传都是同一个 api 方法，在组件里直接引入即可 ==> 非必传
    drag?: boolean; // 是否支持拖拽上传 ==> 非必传（默认为 true）
    disabled?: boolean; // 是否禁用上传组件 ==> 非必传（默认为 false）
    fileSize?: number; // 图片大小限制 ==> 非必传（默认为 5M）
    fileType?: File.ImageMimeType[]; // 图片类型限制 ==> 非必传（默认为 ["image/jpeg", "image/png", "image/gif"]）
    height?: string; // 组件高度 ==> 非必传（默认为 150px）
    width?: string; // 组件宽度 ==> 非必传（默认为 150px）
    borderRadius?: string; // 组件边框圆角 ==> 非必传（默认为 8px）
    iconSize?: number;
    name?: string;
  }

  // 接受父组件参数
  const props = withDefaults(defineProps<UploadFileProps>(), {
    imageUrl: '',
    uploadFileUrl: '/admin/file/upload',
    drag: true,
    disabled: false,
    fileSize: 5,
    fileType: () => ['image/jpeg', 'image/png', 'image/jpg', 'image/gif'],
    height: '120px',
    width: '120px',
    borderRadius: '8px',
    name: ''
  });

  // 生成组件唯一id
  const uuid = ref('id-' + generateUUID());
  const notification = useNotification()
  const viewImg = () => {
    window.open(props.imageUrl);
  };

  // 查看图片

  // 判断是否禁用上传和删除
  const self_disabled = computed(() => {
    return props.disabled;
  });

  /**
   * @description 图片上传
   * @param options upload 所有配置项
   * */
  interface UploadEmits {
    (e: 'update:imageUrl', value: string): void;
    (e: 'changeFileName', value: string): void;
  }

  const fileName = ref('');
  const oImg = ref('');
  const emit = defineEmits<UploadEmits>();
  const loading = ref(false);
  const progress = ref(0);

  const actionFile = async (fileChild: any) => {
    loading.value = true;
    try {
      const formData = new FormData();
      formData.append('file', fileChild);
      formData.append('name', props.name);
      const res = await upload(formData);
      console.log(res);
      emit('update:imageUrl', res.fileUrl);
      emit('changeFileName', res.originalName);
    } catch (error) {
      emit('update:imageUrl', '');
      emit('changeFileName', '');
    } finally {
      progress.value = 0;
      loading.value = false;
    }
  };

  const handleHttpUpload = async (options) => {
    actionFile(options.file.file);
  };

  /**
   * @description 删除图片
   * */
  const deleteImg = () => {
    emit('update:imageUrl', '');
    emit('changeFileName', '');
  };

  /**
   * @description 编辑图片
   * */
  const editImg = () => {
    const dom = document.querySelector(`#${uuid.value} .n-upload-file-input`);
    dom && dom.dispatchEvent(new MouseEvent('click'));
  };

  /**
   * @description 文件上传之前判断
   * @param rawFile 选择的文件
   * */
  const beforeUpload = (rawFile) => {
    console.log(rawFile)
    const imgSize = rawFile.file.file.size / 1024 / 1024 < props.fileSize;
    const imgType = props.fileType.includes(rawFile.file.file.type as File.ImageMimeType);
    if (!imgType)
      notification.warning({
        content: '温馨提示',
        duration:2000,
        meta: '上传图片不符合所需的格式！',
      });
    if (!imgSize)
      setTimeout(() => {
        notification.warning({
          content: '温馨提示',
          duration:2000,
          meta: `上传图片大小不能超过 ${props.fileSize}M！`,
        });
      }, 0);
    return imgType && imgSize;
  };

  /**
   * @description 图片上传错误
   * */
  const uploadError = () => {
    notification.error({
      content: '温馨提示',
      duration:2000,
      meta: '图片上传失败，请您重新上传！',
    });
  };
</script>
<style scoped lang="less">
  .upload-box {
    .no-border {
      :deep(.n-upload) {
        border: none !important;
      }
    }
    :deep {
      .n-upload {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        width: v-bind(width);
        height: v-bind(height);
        overflow: hidden;
        border-radius: 4px;
        padding: 0;
        padding: 5px;
        border:1px dashed #d9d9d9;
        cursor: pointer;
        .n-upload-trigger {
          width:100%;
          height: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
        }
        &:hover {
          .upload-handle {
            opacity: 1;
          }
        }
        .upload-image {
          width: 100%;
          height: 100%;
          object-fit: contain;
        }
        .upload-empty {
          position: relative;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          font-size: 12px;
          line-height: 30px;
          color: #d0d0d0;
        }
        .upload-handle {
          position: absolute;
          top: 0;
          right: 0;
          box-sizing: border-box;
          display: flex;
          align-items: center;
          justify-content: center;
          width: 100%;
          height: 100%;
          cursor: pointer;
          background: rgb(0 0 0 / 60%);
          opacity: 0;
          .handle-icon {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 0 6%;
            color: aliceblue;
            span {
              font-size: 85%;
              line-height: 85%;
            }
          }
        }
      }
    }
    .n-upload__tip {
      line-height: 18px;
      font-size: 12px;
      margin-top: 7px;
    }
  }
</style>
