Files
vue3/packages/upload-table/index.vue
2023-07-21 03:58:45 +08:00

165 lines
5.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>