<template>
  <div class="upload-file">
    <el-upload
      ref="uploadRef"
      :action="uploadFileUrl"
      v-model:file-list="_fileList"
      class="upload-file-uploader"
      :show-file-list="false"
      :multiple="true"
      :disabled="self_disabled"
      :limit="limit"
      :before-upload="beforeUpload"
      :on-exceed="handleExceed"
      :on-success="uploadSuccess"
      :on-error="uploadError"
      :accept="fileType.join(',')"
      :headers="headers"
    >
      <el-button :icon="icon" type="primary">{{ text }}</el-button>
    </el-upload>
    <!-- 上传提示 -->
    <div class="el-upload__tip" v-if="showTip">
      请上传
      <template v-if="fileSize">
        大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
      </template>
      <template v-if="fileType">
        格式为 <b style="color: #f56c6c">{{ fileType.join('/') }}</b>
      </template>
      的文件
    </div>
    <!-- 文件列表 -->
    <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
      <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in _fileList">
        <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
          <span class="document">
            {{ getFileName(file.name) }}
          </span>
        </el-link>
        <div class="ele-upload-list__item-content-action">
          <el-link :underline="false" @click="handleRemove(index)" type="danger">删除</el-link>
        </div>
      </li>
    </transition-group>
  </div>
</template>

<script setup lang="ts" name="UploadImgs">
import { ref, computed, inject, watch } from 'vue'
import type { UploadProps, UploadFile, UploadUserFile } from 'element-plus'
import { ElNotification, ElMessage, formContextKey, formItemContextKey, UploadInstance } from 'element-plus'
import { getToken } from '@/utils/token'
interface UploadFileProps {
  modelValue?: any
  disabled?: boolean // 是否禁用上传组件 ==> 非必传（默认为 false）
  drag?: boolean // 是否支持拖拽上传 ==> 非必传（默认为 true）
  limit?: number // 最大图片上传数 ==> 非必传（默认为 5张）
  fileSize?: number // 图片大小限制 ==> 非必传（默认为 5M）
  height?: string // 组件高度 ==> 非必传（默认为 150px）
  width?: string // 组件宽度 ==> 非必传（默认为 150px）
  borderRadius?: string // 组件边框圆角 ==> 非必传（默认为 8px）
  isShowTip?: boolean // 是否显示提示信息 ==> 非必传（默认为 true）
  text?: string // 按钮文字
  icon?: string
  fileList?: UploadUserFile[]
  fileType?: Array<any>
}
// const emit = defineEmits(['update:modelValue'])
const emit = defineEmits<{
  'update:modelValue': [value: any]
}>()
const baseUrl = import.meta.env.VITE_API_URL
const uploadFileUrl = ref(import.meta.env.VITE_API_URL + '/common/upload') // 上传文件服务器地址
const headers = ref({ Authorization: 'Bearer ' + getToken() })
const uploadRef = ref<UploadInstance>()
const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize))
const props = withDefaults(defineProps<UploadFileProps>(), {
  fileList: () => [],
  drag: true,
  disabled: false,
  limit: 1,
  fileSize: 500,
  fileType: () => ['doc', 'xls', 'xlsx', 'ppt', 'txt', 'pdf'],
  height: '150px',
  width: '150px',
  borderRadius: '8px',
  text: '文件上传',
  isShowTip: false
})

// 获取 el-form 组件上下文
const formContext = inject(formContextKey, void 0)
// 获取 el-form-item 组件上下文
const formItemContext = inject(formItemContextKey, void 0)
// 判断是否禁用上传和删除
const self_disabled = computed(() => {
  return props.disabled || formContext?.disabled
})

const _fileList = ref<UploadUserFile[]>(props.fileList)

// 获取文件名称
const getFileName = name => {
  if (name.lastIndexOf('/') > -1) {
    return name.slice(name.lastIndexOf('/') + 1)
  } else {
    return ''
  }
}

// 监听 props.fileList 列表默认值改变
watch(
  () => props.fileList,
  (n: UploadUserFile[]) => {
    _fileList.value = n
  }
)

/**
 * @description 文件上传之前判断
 * @param rawFile 选择的文件
 * */
const beforeUpload: UploadProps['beforeUpload'] = rawFile => {
  // 校验文件格式
  const fileName = rawFile.name.split('.')
  const fileExt = fileName[fileName.length - 1]
  const isTypeOk = props.fileType.indexOf(fileExt) >= 0
  // 校检文件大小
  const isLt = rawFile.size / 1024 / 1024 < props.fileSize

  if (!isTypeOk)
    ElNotification({
      title: '温馨提示',
      message: '上传文件不符合所需的格式！',
      type: 'warning'
    })
  if (!isLt)
    setTimeout(() => {
      ElNotification({
        title: '温馨提示',
        message: `上传文件大小不能超过 ${props.fileSize}M！`,
        type: 'warning'
      })
    }, 0)
  return isTypeOk && isLt
}

/**
 * @description 文件上传成功
 * @param response 上传响应结果
 * @param uploadFile 上传的文件
 * */
const uploadSuccess = (response: any | undefined, uploadFile: UploadFile) => {
  if (response.code === 200) {
    uploadFile.url = response.url
    uploadFile.name = response.fileName
    emit('update:modelValue', _fileList.value)
    // 调用 el-form 内部的校验方法（可自动校验）
    formItemContext?.prop && formContext?.validateField([formItemContext.prop as string])
    ElNotification({
      title: '温馨提示',
      message: '文件上传成功！',
      type: 'success'
    })
  } else {
    ElMessage.error(response.msg)
    uploadRef.value?.handleRemove(uploadFile)
  }
  //   code: 200
  // fileName: "/profile/upload/2024/04/19/demo_20240419154324A003.txt"
  // msg: "操作成功"
  // newFileName: "demo_20240419154324A003.txt"
  // originalFilename: "demo.txt"
  // url: "http://localhost:8080/profile/upload/2024/04/19/demo_20240419154324A003.txt"
  // uploadList.push({ name: res.fileName, url: res.fileName });
}

/**
 * @description 删除图片
 * @param file 删除的文件
 * */
const handleRemove = (index: number) => {
  // _fileList.value = _fileList.value.filter(item => item.url !== file.url || item.name !== file.name)
  _fileList.value.splice(index, 1)
  emit('update:modelValue', _fileList.value)
}

/**
 * @description 文件上传错误
 * */
const uploadError = () => {
  ElNotification({
    title: '温馨提示',
    message: '文件上传失败，请您重新上传！',
    type: 'error'
  })
}

/**
 * @description 文件数超出
 * */
const handleExceed = () => {
  ElNotification({
    title: '温馨提示',
    message: `当前最多只能上传 ${props.limit} 个文件 ，请移除后上传！`,
    type: 'warning'
  })
}

/**
 * @description 图片预览
 * @param file 预览的文件
 * */
// const viewImageUrl = ref('')
// const imgViewVisible = ref(false)
// const handlePictureCardPreview: UploadProps['onPreview'] = file => {
//   viewImageUrl.value = file.url!
//   imgViewVisible.value = true
// }
</script>

<style scoped lang="scss">
// .upload-file-uploader {
//   margin-bottom: 5px;
// }
// .upload-file-list .el-upload-list__item {
//   position: relative;
//   margin-bottom: 10px;
//   line-height: 2;
//   border: 1px solid #e4e7ed;
// }
// .upload-file-list .ele-upload-list__item-content {
//   display: flex;
//   align-items: center;
//   justify-content: space-between;
//   color: inherit;
// }
// .ele-upload-list__item-content-action .el-link {
//   margin-right: 10px;
// }
// .is-error {
//   .upload {
//     :deep(.el-upload--picture-card),
//     :deep(.el-upload-dragger) {
//       border: 1px dashed var(--el-color-danger) !important;
//       &:hover {
//         border-color: var(--el-color-primary) !important;
//       }
//     }
//   }
// }
// :deep(.disabled) {
//   .el-upload--picture-card,
//   .el-upload-dragger {
//     cursor: not-allowed;
//     background: var(--el-disabled-bg-color) !important;
//     border: 1px dashed var(--el-border-color-darker);
//     &:hover {
//       border-color: var(--el-border-color-darker) !important;
//     }
//   }
// }
// .upload-box {
//   .no-border {
//     :deep(.el-upload--picture-card) {
//       border: none !important;
//     }
//   }
//   :deep(.upload) {
//     .el-upload-dragger {
//       display: flex;
//       align-items: center;
//       justify-content: center;
//       width: 100%;
//       height: 100%;
//       padding: 0;
//       overflow: hidden;
//       border: 1px dashed var(--el-border-color-darker);
//       border-radius: v-bind(borderRadius);
//       &:hover {
//         border: 1px dashed var(--el-color-primary);
//       }
//     }
//     .el-upload-dragger.is-dragover {
//       background-color: var(--el-color-primary-light-9);
//       border: 2px dashed var(--el-color-primary) !important;
//     }
//     .el-upload-list__item,
//     .el-upload--picture-card {
//       width: v-bind(width);
//       height: v-bind(height);
//       background-color: transparent;
//       border-radius: v-bind(borderRadius);
//     }
//     .upload-image {
//       width: 100%;
//       height: 100%;
//       object-fit: contain;
//     }
//     .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;
//       transition: var(--el-transition-duration-fast);
//       .handle-icon {
//         display: flex;
//         flex-direction: column;
//         align-items: center;
//         justify-content: center;
//         padding: 0 6%;
//         color: aliceblue;
//         .el-icon {
//           margin-bottom: 15%;
//           font-size: 140%;
//         }
//         span {
//           font-size: 100%;
//         }
//       }
//     }
//     .el-upload-list__item {
//       &:hover {
//         .upload-handle {
//           opacity: 1;
//         }
//       }
//     }
//     .upload-empty {
//       display: flex;
//       flex-direction: column;
//       align-items: center;
//       font-size: 12px;
//       line-height: 30px;
//       color: var(--el-color-info);
//       .el-icon {
//         font-size: 28px;
//         color: var(--el-text-color-secondary);
//       }
//     }
//   }
//   .el-upload__tip {
//     line-height: 15px;
//     text-align: center;
//   }
// }
.upload-file-uploader {
  margin-bottom: 5px;
}
.upload-file-list .el-upload-list__item {
  position: relative;
  margin-bottom: 10px;
  line-height: 2;
  border: 1px solid #e4e7ed;
}
.upload-file-list .ele-upload-list__item-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: inherit;
}
.ele-upload-list__item-content-action .el-link {
  margin-right: 10px;
}
</style>
