/*
* @Description: 删除确认 Hook - 统一管理单删/批量删除的确认弹窗与执行
* @Version: 1.0.0
*/
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { getImageUrl } from '@/utils/image'
interface DeleteableItem {
id?: number | string
nickName?: string
realName?: string
[key: string]: any
}
export function useDelete<TRow extends DeleteableItem>(
deleteSingleApi: (params: { id: number }) => Promise<any>,
deleteBatchApi: (ids: string[]) => Promise<any>,
/** 资源名称,用于提示文案,默认"用户" */
resourceName: string = '用户',
/** 确认弹窗图标路径,默认 /info-circle-filled.png */
iconPath: string = '/info-circle-filled.png',
) {
const tipsShow = ref(false)
const titleValve = ref('')
const tips = ref('')
const iconUrl = ref('')
const selectedRows = ref<TRow[]>([])
const currentRow = ref<TRow | null>(null)
/** 区分单删 / 批量删 */
const isBatchMode = ref(false)
/** 单条删除确认 */
const confirmSingleDelete = (row: TRow) => {
currentRow.value = row
isBatchMode.value = false
tipsShow.value = true
iconUrl.value = getImageUrl(iconPath)
titleValve.value = `你确定要删除${resourceName}:${row.nickName}吗?`
tips.value = `删除${resourceName}:${row.nickName}后无法恢复,请谨慎操作!`
}
/** 批量删除确认 */
const confirmBatchDelete = () => {
if (selectedRows.value.length === 0) {
ElMessage.warning(`请选择${resourceName}后再进行删除操作`)
return
}
isBatchMode.value = true
tipsShow.value = true
iconUrl.value = getImageUrl(iconPath)
titleValve.value = `你确定要删除选中${resourceName}吗?`
tips.value = '删除后无法恢复,请谨慎操作!'
}
/** 确定删除 */
const handleConfirm = async (onSuccess?: () => void) => {
try {
if (isBatchMode.value) {
const ids = selectedRows.value
.map(item => String(item.id!))
await deleteBatchApi(ids)
ElMessage.success(`成功删除 ${ids.length} 条${resourceName}信息`)
} else {
await deleteSingleApi({ id: Number(currentRow.value!.id!) })
ElMessage.success(`${resourceName}:${currentRow.value?.realName}已删除`)
}
tipsShow.value = false
onSuccess?.()
} catch (error: any) {
ElMessage.error(error.msg)
}
}
/** 取消删除 */
const handleCancel = () => {
tipsShow.value = false
}
return {
tipsShow,
titleValve,
tips,
iconUrl,
selectedRows,
currentRow,
confirmSingleDelete,
confirmBatchDelete,
handleConfirm,
handleCancel,
}
}
//useDelete --- 删除确认 Hook
function useDelete<TRow extends DeleteableItem>(
deleteSingleApi: (params: { id: number }) => Promise<any>,
deleteBatchApi: (ids: string[]) => Promise<any>,
resourceName?: string, // 默认 '用户'
iconPath?: string, // 默认 '/info-circle-filled.png'
)
参数
|-----------------|---------------------------------------------|----|-------------------------------------|
| 参数 | 类型 | 必填 | 说明 |
| deleteSingleApi | (params: { id: number }) => Promise<any> | 是 | 单条删除的 API 方法 |
| deleteBatchApi | (ids: string\[\]) => Promise<any> | 是 | 批量删除的 API 方法 |
| resourceName | string | 是 | 资源名称,用于自动生成提示文案(如 '角色' 、 '商品' ) |
| iconPath | string | 是 | 确认弹窗图标路径,默认 /info-circle-filled.png |
返回值
|---------------------|------------------------------------|----------------------------------------|
| 属性 | 类型 | 说明 |
| tipsShow | Ref<boolean> | 删除确认弹窗可见性,绑定到 MessageBoxTisp 的 v-model |
| titleValve | Ref<string> | 弹窗标题 |
| tips | Ref<string> | 弹窗提示文案 |
| iconUrl | Ref<string> | 弹窗图标 |
| selectedRows | Ref<TRow\[\]> | 被选中的行数据,批量删除前需赋值 |
| currentRow | Ref<TRow | null> | 当前操作的单个行数据 |
| confirmSingleDelete | (row: TRow) => void | 触发单条删除确认 |
| confirmBatchDelete | () => void | 触发批量删除确认 |
| handleConfirm | (onSuccess?: () => void) => void | 确认删除,传入删除成功后的回调 |
| handleCancel | () => void | 取消删除 |
使用示例
场景一:同时支持单删和批量删除
<template>
<CustomTable @selection-change="onSelectionChange">
<template #action="{ row }">
<CustomButtons @click="deleteHandler.confirmSingleDelete(row)">删除</CustomButtons>
</template>
</CustomTable>
<CustomButtons @click="deleteHandler.confirmBatchDelete">批量删除</CustomButtons>
<MessageBoxTisp
v-model="deleteHandler.tipsShow.value"
:titleValve="deleteHandler.titleValve.value"
:tips="deleteHandler.tips.value"
:iconUrl="deleteHandler.iconUrl.value"
@confirm="deleteHandler.handleConfirm(onSubmit)"
@cancel="deleteHandler.handleCancel"
/>
</template>
<script setup lang="ts">
import { useDelete } from '@/hooks/useDelete'
import { deleteUser, deleteUserAll } from '@/api/login/user'
const deleteHandler = useDelete<Request>(deleteUser, deleteUserAll)
const onSelectionChange = (selection: Request[]) => {
deleteHandler.selectedRows.value = selection
}
</script>
场景二:仅批量删除
const deleteHandler = useDelete<TreeNode>(
async () => {}, // 单删不可用,传空函数
deleteRoleAll,
'角色', // 提示文案自动适配
'/del_icon.png', // 自定义图标
)
// 同步勾选数据到 selectedRows
const handleCheckChange = (data: TreeNode, checked: boolean) => {
// ...维护 checkedNodes
deleteHandler.selectedRows.value = checkedNodes.value as any
}
// 删除时调用
const handleDelete = () => {
deleteHandler.selectedRows.value = checkedNodes.value as any
deleteHandler.confirmBatchDelete()
}
// 确认后执行清理
const handleConfirm = () => {
deleteHandler.handleConfirm(async () => {
checkedNodes.value = []
await getRole()
})
}
自动生成的提示文案
|---------------------|---------------|----------------|---|
| 方法 | 资源名= '用户' | 资源名= '角色' | |
| confirmSingleDelete | 你确定要删除用户:张三吗? | 你确定要删除角色:管理员吗? | |
| confirmBatchDelete | 你确定要删除选中用户吗? | 你确定要删除选中角色吗? | |
| handleConfirm (批量) | 成功删除 3 条用户信息 | 成功删除 3 条角色信息 | |