feat(dataset): 支持数据任务批量删除

This commit is contained in:
caoxiaozhu
2026-07-27 11:36:30 +08:00
parent d6e325fe9e
commit e486d36a80
3 changed files with 155 additions and 26 deletions

View File

@@ -1,6 +1,6 @@
<script setup lang="ts" generic="T extends Record<string, any>">
import { ref, computed, watch } from 'vue'
import { ElMessageBox } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { TableInstance } from 'element-plus'
import { useRouter } from 'vue-router'
@@ -19,6 +19,8 @@ const props = withDefaults(
searchFields?: string[]
/** 是否支持多选 */
multiSelect?: boolean
/** 选中后是否展示组件内置的批量操作栏 */
showBatchBar?: boolean
/** 创建按钮文本,不传则不显示 */
createText?: string
/** 创建按钮跳转路径 */
@@ -38,6 +40,7 @@ const props = withDefaults(
loading: false,
searchable: false,
multiSelect: false,
showBatchBar: true,
rowKey: 'id',
emptyText: '暂无数据',
pageSize: 10,
@@ -49,6 +52,7 @@ const emit = defineEmits<{
create: []
refresh: []
expandChange: [row: T, expandedRows: T[]]
selectionChange: [rows: T[]]
}>()
const router = useRouter()
@@ -57,6 +61,7 @@ const selectedIds = ref<Set<string | number>>(new Set())
const keyword = ref('')
const currentPage = ref(1)
const currentPageSize = ref(props.pageSize)
const batchDeleting = ref(false)
/** 行唯一标识取值 */
function rowId(row: T): string | number {
@@ -81,6 +86,7 @@ const pagedData = computed(() => {
/** 处理多选变化 */
function handleSelectionChange(rows: T[]) {
selectedIds.value = new Set(rows.map(rowId))
emit('selectionChange', rows)
}
/** 单个删除(子组件或操作列调用) */
@@ -100,14 +106,25 @@ async function handleDelete(row: any, confirmText = '确定要删除这条记录
}
/** 批量删除 */
async function handleBatchDelete() {
if (selectedIds.value.size === 0 || !props.deleteFn) return
async function handleBatchDelete(): Promise<boolean> {
if (selectedIds.value.size === 0 || !props.deleteFn || batchDeleting.value) return false
try {
await ElMessageBox.confirm(
`确定删除选中的 ${selectedIds.value.size} 条记录吗?`,
'批量删除',
{ type: 'warning' },
`确定删除选中的 ${selectedIds.value.size} 条记录吗?删除后无法恢复。`,
'确认批量删除',
{
type: 'warning',
confirmButtonText: '删除',
cancelButtonText: '取消',
confirmButtonClass: 'el-button--danger',
},
)
} catch {
return false
}
batchDeleting.value = true
try {
const rows = props.data.filter((row) => selectedIds.value.has(rowId(row)))
let ok = 0
let fail = 0
@@ -119,21 +136,23 @@ async function handleBatchDelete() {
fail++
}
}
selectedIds.value.clear()
clearSelection()
emit('refresh')
if (fail === 0) {
ElMessageBox.alert(`成功删除 ${ok} 条记录`, '成功', { type: 'success' })
ElMessage.success(`成功删除 ${ok} 条记录`)
} else {
ElMessageBox.alert(`成功 ${ok} 条,失败 ${fail}`, '部分失败', { type: 'warning' })
ElMessage.warning(`批量删除完成:成功 ${ok} 条,失败 ${fail}`)
}
} catch {
// 取消
return true
} finally {
batchDeleting.value = false
}
}
function clearSelection() {
selectedIds.value.clear()
tableRef.value?.clearSelection()
emit('selectionChange', [])
}
function handleCreate() {
@@ -152,20 +171,27 @@ function handleExpandChange(row: T, expandedRows: T[] | boolean) {
watch(
() => props.data,
() => {
selectedIds.value.clear()
clearSelection()
currentPage.value = 1
tableRef.value?.clearSelection()
},
)
watch(
() => props.multiSelect,
(enabled) => {
if (!enabled) clearSelection()
},
)
watch(
() => keyword.value,
() => {
if (selectedIds.value.size > 0) clearSelection()
currentPage.value = 1
},
)
defineExpose({ handleDelete, clearSelection })
defineExpose({ handleDelete, handleBatchDelete, clearSelection })
</script>
<template>
@@ -196,12 +222,12 @@ defineExpose({ handleDelete, clearSelection })
<!-- 批量操作栏 -->
<transition name="el-zoom-in-top">
<div v-if="multiSelect && selectedIds.size > 0" class="batch-bar">
<div v-if="multiSelect && showBatchBar && selectedIds.size > 0" class="batch-bar">
<span class="batch-info">
已选择 <strong>{{ selectedIds.size }}</strong>
<el-button link type="primary" @click="clearSelection">取消选择</el-button>
</span>
<el-button type="danger" size="small" @click="handleBatchDelete">
<el-button type="danger" size="small" :loading="batchDeleting" @click="handleBatchDelete">
<i class="fa fa-trash" style="margin-right: 4px" />
批量删除 ({{ selectedIds.size }})
</el-button>