165 lines
5.1 KiB
Vue
165 lines
5.1 KiB
Vue
<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>
|