feat(dataset): 支持数据任务批量删除
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user