<template>
  <div w-full>
    <el-table border :data="fileList" w-full>
      <el-table-column align="center" :label="label1">
        <template #default="{ row }">
          <template v-if="row.createdBy">
            {{ row.name }}
          </template>
          <el-input
            v-else v-model.trim="allName[`${row.id}`]" clearable :loading="allLoading[`${row.id}`]"
            placeholder="不填则为默认文件名称"
          />
        </template>
      </el-table-column>
      <el-table-column align="center" :label="label2">
        <template #default="{ row, $index }">
          <download-link v-if="row.createdBy" :src="row" :file-name="row.name">
            {{ row.name }}
          </download-link>
          <upload-single-file
            v-else
            :accept="accept"
            :auto-upload="allLoading[`${row.id}`]"
            :max-size="20"
            :file-name="allName[`${row.id}`]"
            :request="request"
            @on-change="$event => onChange($event, row.id)"
            @on-success="$event => onSuccess($event, row, $index)"
            @on-error="onError(row.id)"
          />
        </template>
      </el-table-column>
      <el-table-column align="center" :label="label3" width="200px">
        <template #default="{ row, $index }">
          <el-popconfirm v-if="allowReplace" :title="replacePopconfirm" :disabled="disabled" @confirm="remove($index)">
            <template #reference>
              <el-button type="danger" :disabled="disabled" link>
                重新上传
              </el-button>
            </template>
          </el-popconfirm>
          <el-popconfirm v-if="allowDelete && row.createdBy" :title="deletePopconfirm" :disabled="disabled" @confirm="remove($index)">
            <template #reference>
              <el-button type="danger" :disabled="disabled" link>
                删除
              </el-button>
            </template>
          </el-popconfirm>
          <template v-else>
            <el-button type="primary" :loading="allLoading[`${row.id}`]" link @click="save(row.id)">
              保存
            </el-button>
            <el-button type="danger" :loading="allLoading[`${row.id}`]" link @click="remove($index)">
              取消
            </el-button>
          </template>
        </template>
      </el-table-column>
    </el-table>
    <div v-if="!hideAdd" w-full text-center>
      <el-button :disabled="disabled" type="primary" plain @click="add">
        {{ addText }}
      </el-button>
    </div>
  </div>
</template>

<script lang="ts" setup name="ThUploadTable">
const props = withDefaults(defineProps<{
  /** 上传格式 */
  accept?: string
  /** 列1的文字 */
  label1?: string
  /** 列2的文字 */
  label2?: string
  /** 列3的文字 */
  label3?: string
  /** 文件列表，支持v-model */
  fileList?: FileVO[]
  /** 再次上传确认的提示文字 */
  replacePopconfirm?: string
  /** 删除确认的提示文字 */
  deletePopconfirm?: string
  /** 新增按钮的提示文字 */
  addText?: string
  /** 允许替换，用再次上传覆盖之前已上传的文件 */
  allowReplace?: boolean
  /** 允许删除已上传的文件 */
  allowDelete?: boolean
  /** 表格禁用，支持v-model */
  disabled?: boolean
  /** 隐藏新增按钮 */
  hideAdd?: boolean
  /** 文件上传的请求函数 */
  request?: (formData: FormData) => Promise<FileVO>
}>(), {
  accept: '.jpeg,.jpg,.png,.bmp',
  addText: '新增一行',
  allowDelete: true,
  allowReplace: false,
  disabled: false,
  hideAdd: false,
  label1: '文件名称',
  label2: '图片上传',
  label3: '操作',
  fileList: () => [],
  replacePopconfirm: '是否重新本行文件？',
  deletePopconfirm: '是否删除本行？',
})

const emit = defineEmits<{
  (event: 'update:disabled', disabled: boolean): void
  (event: 'update:fileList', fileList?: FileVO[]): void
}>()

const allName = reactive<Record<string, string | undefined>>({})

const allLoading = reactive<Record<string, boolean | undefined>>({})

function onSuccess(file: FileVO, row: FileVO, index: number) {
  const indexKey = `${row.id}`
  const newList = [...props.fileList.slice(0, index), file, ...props.fileList.slice(index + 1)]
  emit('update:fileList', newList)
  ElMessage.success('上传成功')
  allLoading[indexKey] = false
}

function onError(id: number) {
  const indexKey = `${id}`
  allLoading[indexKey] = false
}

// 自动设置文件名
function onChange(uploadFile: File, id: number) {
  const indexKey = `${id}`

  if (allName[indexKey])
    return

  const arr = uploadFile.name.split('.')
  arr.pop()
  /** 去除拓展名的文件名 */
  const newFilename = arr.join('.')
  // 特殊情况时例如：.npmrc 使用原始文件名
  allName[indexKey] = newFilename || uploadFile.name
}

function save(id: number) {
  const indexKey = `${id}`
  allLoading[indexKey] = true
}

function add() {
  const id = Date.now() // 生成一个id
  allName[id] = ''
  allLoading[id] = false
  emit('update:fileList', [...props.fileList, { id }])
}

function remove(index: number) {
  const newList = [...props.fileList.slice(0, index), ...props.fileList.slice(index + 1)]
  emit('update:fileList', newList)
}
</script>
