diff --git a/apps/web-antd/src/api/infra/codegen/index.ts b/apps/web-antd/src/api/infra/codegen/index.ts index c09ab425f..c72f3ff1b 100644 --- a/apps/web-antd/src/api/infra/codegen/index.ts +++ b/apps/web-antd/src/api/infra/codegen/index.ts @@ -146,3 +146,10 @@ export function deleteCodegenTable(tableId: number) { params: { tableId }, }); } + +/** 批量删除代码生成表定义 */ +export function deleteCodegenTableList(tableIds: number[]) { + return requestClient.delete( + `/infra/codegen/delete-list?tableIds=${tableIds.join(',')}`, + ); +} diff --git a/apps/web-antd/src/api/infra/config/index.ts b/apps/web-antd/src/api/infra/config/index.ts index 3911e01c7..521e957a2 100644 --- a/apps/web-antd/src/api/infra/config/index.ts +++ b/apps/web-antd/src/api/infra/config/index.ts @@ -54,6 +54,11 @@ export function deleteConfig(id: number) { return requestClient.delete(`/infra/config/delete?id=${id}`); } +/** 批量删除参数 */ +export function deleteConfigList(ids: number[]) { + return requestClient.delete(`/infra/config/delete-list?ids=${ids.join(',')}`); +} + /** 导出参数 */ export function exportConfig(params: any) { return requestClient.download('/infra/config/export', { diff --git a/apps/web-antd/src/api/infra/file-config/index.ts b/apps/web-antd/src/api/infra/file-config/index.ts index a16cf2bc0..20a0ab3fa 100644 --- a/apps/web-antd/src/api/infra/file-config/index.ts +++ b/apps/web-antd/src/api/infra/file-config/index.ts @@ -69,6 +69,13 @@ export function deleteFileConfig(id: number) { return requestClient.delete(`/infra/file-config/delete?id=${id}`); } +/** 批量删除文件配置 */ +export function deleteFileConfigList(ids: number[]) { + return requestClient.delete( + `/infra/file-config/delete-list?ids=${ids.join(',')}`, + ); +} + /** 测试文件配置 */ export function testFileConfig(id: number) { return requestClient.get(`/infra/file-config/test?id=${id}`); diff --git a/apps/web-antd/src/api/infra/file/index.ts b/apps/web-antd/src/api/infra/file/index.ts index 982789885..e7dc78915 100644 --- a/apps/web-antd/src/api/infra/file/index.ts +++ b/apps/web-antd/src/api/infra/file/index.ts @@ -45,6 +45,11 @@ export function deleteFile(id: number) { return requestClient.delete(`/infra/file/delete?id=${id}`); } +/** 批量删除文件 */ +export function deleteFileList(ids: number[]) { + return requestClient.delete(`/infra/file/delete-list?ids=${ids.join(',')}`); +} + /** 获取文件预签名地址 */ export function getFilePresignedUrl(name: string, directory?: string) { return requestClient.get( diff --git a/apps/web-antd/src/api/infra/job/index.ts b/apps/web-antd/src/api/infra/job/index.ts index bacdbc4a1..05f6a727f 100644 --- a/apps/web-antd/src/api/infra/job/index.ts +++ b/apps/web-antd/src/api/infra/job/index.ts @@ -46,6 +46,11 @@ export function deleteJob(id: number) { return requestClient.delete(`/infra/job/delete?id=${id}`); } +/** 批量删除定时任务调度 */ +export function deleteJobList(ids: number[]) { + return requestClient.delete(`/infra/job/delete-list?ids=${ids.join(',')}`); +} + /** 导出定时任务调度 */ export function exportJob(params: any) { return requestClient.download('/infra/job/export-excel', { params }); diff --git a/apps/web-antd/src/api/system/dept/index.ts b/apps/web-antd/src/api/system/dept/index.ts index d2677a793..d6403d72a 100644 --- a/apps/web-antd/src/api/system/dept/index.ts +++ b/apps/web-antd/src/api/system/dept/index.ts @@ -45,3 +45,8 @@ export async function updateDept(data: SystemDeptApi.Dept) { export async function deleteDept(id: number) { return requestClient.delete(`/system/dept/delete?id=${id}`); } + +/** 批量删除部门 */ +export async function deleteDeptList(ids: number[]) { + return requestClient.delete(`/system/dept/delete-list?ids=${ids.join(',')}`); +} diff --git a/apps/web-antd/src/api/system/dict/data/index.ts b/apps/web-antd/src/api/system/dict/data/index.ts index a64330cda..6bf7473ce 100644 --- a/apps/web-antd/src/api/system/dict/data/index.ts +++ b/apps/web-antd/src/api/system/dict/data/index.ts @@ -48,6 +48,13 @@ export function deleteDictData(id: number) { return requestClient.delete(`/system/dict-data/delete?id=${id}`); } +// 批量删除字典数据 +export function deleteDictDataList(ids: number[]) { + return requestClient.delete( + `/system/dict-data/delete-list?ids=${ids.join(',')}`, + ); +} + // 导出字典类型数据 export function exportDictData(params: any) { return requestClient.download('/system/dict-data/export', { params }); diff --git a/apps/web-antd/src/api/system/dict/type/index.ts b/apps/web-antd/src/api/system/dict/type/index.ts index 612fe1052..8c2951cc1 100644 --- a/apps/web-antd/src/api/system/dict/type/index.ts +++ b/apps/web-antd/src/api/system/dict/type/index.ts @@ -42,6 +42,13 @@ export function deleteDictType(id: number) { return requestClient.delete(`/system/dict-type/delete?id=${id}`); } +// 批量删除字典 +export function deleteDictTypeList(ids: number[]) { + return requestClient.delete( + `/system/dict-type/delete-list?ids=${ids.join(',')}`, + ); +} + // 导出字典类型 export function exportDictType(params: any) { return requestClient.download('/system/dict-type/export', { params }); diff --git a/apps/web-antd/src/api/system/mail/account/index.ts b/apps/web-antd/src/api/system/mail/account/index.ts index 8a43a3326..7f506fd87 100644 --- a/apps/web-antd/src/api/system/mail/account/index.ts +++ b/apps/web-antd/src/api/system/mail/account/index.ts @@ -49,6 +49,13 @@ export function deleteMailAccount(id: number) { return requestClient.delete(`/system/mail-account/delete?id=${id}`); } +/** 批量删除邮箱账号 */ +export function deleteMailAccountList(ids: number[]) { + return requestClient.delete( + `/system/mail-account/delete-list?ids=${ids.join(',')}`, + ); +} + /** 获得邮箱账号精简列表 */ export function getSimpleMailAccountList() { return requestClient.get( diff --git a/apps/web-antd/src/api/system/mail/template/index.ts b/apps/web-antd/src/api/system/mail/template/index.ts index 7bae8e91b..d1bd075f1 100644 --- a/apps/web-antd/src/api/system/mail/template/index.ts +++ b/apps/web-antd/src/api/system/mail/template/index.ts @@ -56,6 +56,13 @@ export function deleteMailTemplate(id: number) { return requestClient.delete(`/system/mail-template/delete?id=${id}`); } +/** 批量删除邮件模板 */ +export function deleteMailTemplateList(ids: number[]) { + return requestClient.delete( + `/system/mail-template/delete-list?ids=${ids.join(',')}`, + ); +} + /** 发送邮件 */ export function sendMail(data: SystemMailTemplateApi.MailSendReq) { return requestClient.post('/system/mail-template/send-mail', data); diff --git a/apps/web-antd/src/api/system/menu/index.ts b/apps/web-antd/src/api/system/menu/index.ts index 5d23e5230..b296d815b 100644 --- a/apps/web-antd/src/api/system/menu/index.ts +++ b/apps/web-antd/src/api/system/menu/index.ts @@ -52,3 +52,8 @@ export async function updateMenu(data: SystemMenuApi.Menu) { export async function deleteMenu(id: number) { return requestClient.delete(`/system/menu/delete?id=${id}`); } + +/** 批量删除菜单 */ +export async function deleteMenuList(ids: number[]) { + return requestClient.delete(`/system/menu/delete-list?ids=${ids.join(',')}`); +} diff --git a/apps/web-antd/src/api/system/notice/index.ts b/apps/web-antd/src/api/system/notice/index.ts index dac9ec708..5ae888538 100644 --- a/apps/web-antd/src/api/system/notice/index.ts +++ b/apps/web-antd/src/api/system/notice/index.ts @@ -46,6 +46,13 @@ export function deleteNotice(id: number) { return requestClient.delete(`/system/notice/delete?id=${id}`); } +/** 批量删除公告 */ +export function deleteNoticeList(ids: number[]) { + return requestClient.delete( + `/system/notice/delete-list?ids=${ids.join(',')}`, + ); +} + /** 推送公告 */ export function pushNotice(id: number) { return requestClient.post(`/system/notice/push?id=${id}`); diff --git a/apps/web-antd/src/api/system/notify/template/index.ts b/apps/web-antd/src/api/system/notify/template/index.ts index 18b44124d..5eab6fa44 100644 --- a/apps/web-antd/src/api/system/notify/template/index.ts +++ b/apps/web-antd/src/api/system/notify/template/index.ts @@ -59,6 +59,13 @@ export function deleteNotifyTemplate(id: number) { return requestClient.delete(`/system/notify-template/delete?id=${id}`); } +/** 批量删除站内信模板 */ +export function deleteNotifyTemplateList(ids: number[]) { + return requestClient.delete( + `/system/notify-template/delete-list?ids=${ids.join(',')}`, + ); +} + /** 导出站内信模板 */ export function exportNotifyTemplate(params: any) { return requestClient.download('/system/notify-template/export-excel', { diff --git a/apps/web-antd/src/api/system/oauth2/token/index.ts b/apps/web-antd/src/api/system/oauth2/token/index.ts index bd3697915..9209fd713 100644 --- a/apps/web-antd/src/api/system/oauth2/token/index.ts +++ b/apps/web-antd/src/api/system/oauth2/token/index.ts @@ -32,3 +32,10 @@ export function deleteOAuth2Token(accessToken: string) { `/system/oauth2-token/delete?accessToken=${accessToken}`, ); } + +/** 批量删除 OAuth2.0 令牌 */ +export function deleteOAuth2TokenList(accessTokens: string[]) { + return requestClient.delete( + `/system/oauth2-token/delete-list?accessTokens=${accessTokens.join(',')}`, + ); +} diff --git a/apps/web-antd/src/api/system/post/index.ts b/apps/web-antd/src/api/system/post/index.ts index a82f58155..06df146c3 100644 --- a/apps/web-antd/src/api/system/post/index.ts +++ b/apps/web-antd/src/api/system/post/index.ts @@ -50,6 +50,11 @@ export function deletePost(id: number) { return requestClient.delete(`/system/post/delete?id=${id}`); } +/** 批量删除岗位 */ +export function deletePostList(ids: number[]) { + return requestClient.delete(`/system/post/delete-list?ids=${ids.join(',')}`); +} + /** 导出岗位 */ export function exportPost(params: any) { return requestClient.download('/system/post/export', { diff --git a/apps/web-antd/src/api/system/role/index.ts b/apps/web-antd/src/api/system/role/index.ts index 07824c43e..23d5ade98 100644 --- a/apps/web-antd/src/api/system/role/index.ts +++ b/apps/web-antd/src/api/system/role/index.ts @@ -50,6 +50,11 @@ export function deleteRole(id: number) { return requestClient.delete(`/system/role/delete?id=${id}`); } +/** 批量删除角色 */ +export function deleteRoleList(ids: number[]) { + return requestClient.delete(`/system/role/delete-list?ids=${ids.join(',')}`); +} + /** 导出角色 */ export function exportRole(params: any) { return requestClient.download('/system/role/export-excel', { diff --git a/apps/web-antd/src/api/system/sms/channel/index.ts b/apps/web-antd/src/api/system/sms/channel/index.ts index 56890bea5..575c92447 100644 --- a/apps/web-antd/src/api/system/sms/channel/index.ts +++ b/apps/web-antd/src/api/system/sms/channel/index.ts @@ -54,6 +54,13 @@ export function deleteSmsChannel(id: number) { return requestClient.delete(`/system/sms-channel/delete?id=${id}`); } +/** 批量删除短信渠道 */ +export function deleteSmsChannelList(ids: number[]) { + return requestClient.delete( + `/system/sms-channel/delete-list?ids=${ids.join(',')}`, + ); +} + /** 导出短信渠道 */ export function exportSmsChannel(params: any) { return requestClient.download('/system/sms-channel/export', { params }); diff --git a/apps/web-antd/src/api/system/sms/template/index.ts b/apps/web-antd/src/api/system/sms/template/index.ts index 0ea7425a1..8f8e4c8c7 100644 --- a/apps/web-antd/src/api/system/sms/template/index.ts +++ b/apps/web-antd/src/api/system/sms/template/index.ts @@ -57,6 +57,13 @@ export function deleteSmsTemplate(id: number) { return requestClient.delete(`/system/sms-template/delete?id=${id}`); } +/** 批量删除短信模板 */ +export function deleteSmsTemplateList(ids: number[]) { + return requestClient.delete( + `/system/sms-template/delete-list?ids=${ids.join(',')}`, + ); +} + /** 导出短信模板 */ export function exportSmsTemplate(params: any) { return requestClient.download('/system/sms-template/export-excel', { diff --git a/apps/web-antd/src/api/system/tenant-package/index.ts b/apps/web-antd/src/api/system/tenant-package/index.ts index 5066cea98..53be78f73 100644 --- a/apps/web-antd/src/api/system/tenant-package/index.ts +++ b/apps/web-antd/src/api/system/tenant-package/index.ts @@ -49,6 +49,13 @@ export function deleteTenantPackage(id: number) { return requestClient.delete(`/system/tenant-package/delete?id=${id}`); } +/** 批量删除租户套餐 */ +export function deleteTenantPackageList(ids: number[]) { + return requestClient.delete( + `/system/tenant-package/delete-list?ids=${ids.join(',')}`, + ); +} + /** 获取租户套餐精简信息列表 */ export function getTenantPackageList() { return requestClient.get( diff --git a/apps/web-antd/src/api/system/tenant/index.ts b/apps/web-antd/src/api/system/tenant/index.ts index 3bed9249c..c18a4dfab 100644 --- a/apps/web-antd/src/api/system/tenant/index.ts +++ b/apps/web-antd/src/api/system/tenant/index.ts @@ -61,6 +61,13 @@ export function deleteTenant(id: number) { return requestClient.delete(`/system/tenant/delete?id=${id}`); } +/** 批量删除租户 */ +export function deleteTenantList(ids: number[]) { + return requestClient.delete( + `/system/tenant/delete-list?ids=${ids.join(',')}`, + ); +} + /** 导出租户 */ export function exportTenant(params: any) { return requestClient.download('/system/tenant/export-excel', { diff --git a/apps/web-antd/src/api/system/user/index.ts b/apps/web-antd/src/api/system/user/index.ts index 52d8cdd2e..1f51a5bc7 100644 --- a/apps/web-antd/src/api/system/user/index.ts +++ b/apps/web-antd/src/api/system/user/index.ts @@ -49,6 +49,11 @@ export function deleteUser(id: number) { return requestClient.delete(`/system/user/delete?id=${id}`); } +/** 批量删除用户 */ +export function deleteUserList(ids: number[]) { + return requestClient.delete(`/system/user/delete-list?ids=${ids.join(',')}`); +} + /** 导出用户 */ export function exportUser(params: any) { return requestClient.download('/system/user/export', params); diff --git a/apps/web-antd/src/views/infra/codegen/data.ts b/apps/web-antd/src/views/infra/codegen/data.ts index a2b50d9c3..928f27009 100644 --- a/apps/web-antd/src/views/infra/codegen/data.ts +++ b/apps/web-antd/src/views/infra/codegen/data.ts @@ -394,6 +394,7 @@ export function useGridColumns( getDataSourceConfigName?: (dataSourceConfigId: number) => string | undefined, ): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'dataSourceConfigId', title: '数据源', diff --git a/apps/web-antd/src/views/infra/codegen/index.vue b/apps/web-antd/src/views/infra/codegen/index.vue index 467b84fb6..1e113acec 100644 --- a/apps/web-antd/src/views/infra/codegen/index.vue +++ b/apps/web-antd/src/views/infra/codegen/index.vue @@ -7,12 +7,14 @@ import { ref } from 'vue'; import { useRouter } from 'vue-router'; import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; +import { isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteCodegenTable, + deleteCodegenTableList, downloadCodegen, getCodegenTablePage, syncCodegenFromDB, @@ -82,6 +84,31 @@ async function handleDelete(row: InfraCodegenApi.CodegenTable) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: InfraCodegenApi.CodegenTable[]; +}) { + checkedIds.value = records.map((item) => item.id); +} + +/** 批量删除代码生成配置 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteCodegenTableList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + /** 同步数据库 */ async function handleSync(row: InfraCodegenApi.CodegenTable) { const hideLoading = message.loading({ @@ -145,12 +172,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); /** 获取数据源配置列表 */ @@ -196,6 +228,15 @@ initDataSourceConfig(); auth: ['infra:codegen:create'], onClick: handleImport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['infra:codegen:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/infra/config/data.ts b/apps/web-antd/src/views/infra/config/data.ts index ae886c47f..612b00cec 100644 --- a/apps/web-antd/src/views/infra/config/data.ts +++ b/apps/web-antd/src/views/infra/config/data.ts @@ -119,6 +119,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '参数主键', diff --git a/apps/web-antd/src/views/infra/config/index.vue b/apps/web-antd/src/views/infra/config/index.vue index 9d4d6d0ca..b1950e6ac 100644 --- a/apps/web-antd/src/views/infra/config/index.vue +++ b/apps/web-antd/src/views/infra/config/index.vue @@ -2,13 +2,20 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { InfraConfigApi } from '#/api/infra/config'; +import { ref } from 'vue'; + import { Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; -import { deleteConfig, exportConfig, getConfigPage } from '#/api/infra/config'; +import { + deleteConfig, + deleteConfigList, + exportConfig, + getConfigPage, +} from '#/api/infra/config'; import { $t } from '#/locales'; import { useGridColumns, useGridFormSchema } from './data'; @@ -59,6 +66,31 @@ async function handleDelete(row: InfraConfigApi.Config) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: InfraConfigApi.Config[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除参数 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteConfigList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -80,12 +112,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -110,6 +147,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['infra:config:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['infra:config:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/infra/file/data.ts b/apps/web-antd/src/views/infra/file/data.ts index 3b9eecb1e..532939559 100644 --- a/apps/web-antd/src/views/infra/file/data.ts +++ b/apps/web-antd/src/views/infra/file/data.ts @@ -54,6 +54,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'name', title: '文件名', diff --git a/apps/web-antd/src/views/infra/file/index.vue b/apps/web-antd/src/views/infra/file/index.vue index 6d55c4098..b9df5e8a6 100644 --- a/apps/web-antd/src/views/infra/file/index.vue +++ b/apps/web-antd/src/views/infra/file/index.vue @@ -2,14 +2,16 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { InfraFileApi } from '#/api/infra/file'; +import { ref } from 'vue'; + import { Page, useVbenModal } from '@vben/common-ui'; -import { openWindow } from '@vben/utils'; +import { isEmpty, openWindow } from '@vben/utils'; import { useClipboard } from '@vueuse/core'; import { Button, Image, message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; -import { deleteFile, getFilePage } from '#/api/infra/file'; +import { deleteFile, deleteFileList, getFilePage } from '#/api/infra/file'; import { $t } from '#/locales'; import { useGridColumns, useGridFormSchema } from './data'; @@ -64,6 +66,31 @@ async function handleDelete(row: InfraFileApi.File) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: InfraFileApi.File[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除文件 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteFileList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -85,12 +112,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -108,6 +140,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['infra:file:create'], onClick: handleUpload, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['infra:file:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/infra/fileConfig/data.ts b/apps/web-antd/src/views/infra/fileConfig/data.ts index 84d1178ea..58cc4cd93 100644 --- a/apps/web-antd/src/views/infra/fileConfig/data.ts +++ b/apps/web-antd/src/views/infra/fileConfig/data.ts @@ -262,6 +262,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '编号', diff --git a/apps/web-antd/src/views/infra/fileConfig/index.vue b/apps/web-antd/src/views/infra/fileConfig/index.vue index 9f0c53326..06418759e 100644 --- a/apps/web-antd/src/views/infra/fileConfig/index.vue +++ b/apps/web-antd/src/views/infra/fileConfig/index.vue @@ -2,14 +2,17 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { InfraFileConfigApi } from '#/api/infra/file-config'; +import { ref } from 'vue'; + import { confirm, Page, useVbenModal } from '@vben/common-ui'; -import { openWindow } from '@vben/utils'; +import { isEmpty, openWindow } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteFileConfig, + deleteFileConfigList, getFileConfigPage, testFileConfig, updateFileConfigMaster, @@ -97,6 +100,31 @@ async function handleDelete(row: InfraFileConfigApi.FileConfig) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: InfraFileConfigApi.FileConfig[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除文件配置 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteFileConfigList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -118,12 +146,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -141,6 +174,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['infra:file-config:create'], onClick: handleCreate, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['infra:file-config:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/infra/job/data.ts b/apps/web-antd/src/views/infra/job/data.ts index 982ee9f9b..0f1e663d7 100644 --- a/apps/web-antd/src/views/infra/job/data.ts +++ b/apps/web-antd/src/views/infra/job/data.ts @@ -129,6 +129,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 表格列配置 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '任务编号', diff --git a/apps/web-antd/src/views/infra/job/index.vue b/apps/web-antd/src/views/infra/job/index.vue index 8830573b2..c3b630029 100644 --- a/apps/web-antd/src/views/infra/job/index.vue +++ b/apps/web-antd/src/views/infra/job/index.vue @@ -2,16 +2,18 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { InfraJobApi } from '#/api/infra/job'; +import { ref } from 'vue'; import { useRouter } from 'vue-router'; import { confirm, DocAlert, Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteJob, + deleteJobList, exportJob, getJobPage, runJob, @@ -114,6 +116,27 @@ async function handleDelete(row: InfraJobApi.Job) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ records }: { records: InfraJobApi.Job[] }) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除任务 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteJobList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -135,12 +158,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -177,7 +205,16 @@ const [Grid, gridApi] = useVbenVxeGrid({ type: 'primary', icon: 'lucide:history', auth: ['infra:job:export'], - onClick: handleExport, + onClick: handleLog, + }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['infra:job:delete'], + onClick: handleDeleteBatch, }, ]" /> diff --git a/apps/web-antd/src/views/system/dept/data.ts b/apps/web-antd/src/views/system/dept/data.ts index 155f60f21..0da23687b 100644 --- a/apps/web-antd/src/views/system/dept/data.ts +++ b/apps/web-antd/src/views/system/dept/data.ts @@ -113,6 +113,7 @@ export function useGridColumns( getLeaderName?: (userId: number) => string | undefined, ): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'name', title: '部门名称', diff --git a/apps/web-antd/src/views/system/dept/index.vue b/apps/web-antd/src/views/system/dept/index.vue index f62e6db7a..638865004 100644 --- a/apps/web-antd/src/views/system/dept/index.vue +++ b/apps/web-antd/src/views/system/dept/index.vue @@ -6,11 +6,12 @@ import type { SystemUserApi } from '#/api/system/user'; import { onMounted, ref } from 'vue'; import { Page, useVbenModal } from '@vben/common-ui'; +import { isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; -import { deleteDept, getDeptList } from '#/api/system/dept'; +import { deleteDept, deleteDeptList, getDeptList } from '#/api/system/dept'; import { getSimpleUserList } from '#/api/system/user'; import { $t } from '#/locales'; @@ -74,35 +75,62 @@ async function handleDelete(row: SystemDeptApi.Dept) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemDeptApi.Dept[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除部门 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteDeptList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ gridOptions: { columns: useGridColumns(getLeaderName), height: 'auto', - keepSource: true, - pagerConfig: { - enabled: false, - }, proxyConfig: { ajax: { - query: async (_params) => { + query: async () => { return await getDeptList(); }, }, }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, + search: true, }, treeConfig: { - parentField: 'parentId', - rowField: 'id', transform: true, + rowField: 'id', + parentField: 'parentId', expandAll: true, - reserve: true, + accordion: false, }, - } as VxeTableGridOptions, + } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); /** 初始化 */ @@ -130,6 +158,15 @@ onMounted(async () => { type: 'primary', onClick: toggleExpand, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:dept:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/dict/data.ts b/apps/web-antd/src/views/system/dict/data.ts index 28586f169..f1d46c2f8 100644 --- a/apps/web-antd/src/views/system/dict/data.ts +++ b/apps/web-antd/src/views/system/dict/data.ts @@ -101,6 +101,7 @@ export function useTypeGridFormSchema(): VbenFormSchema[] { /** 类型列表的字段 */ export function useTypeGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '字典编号', @@ -288,6 +289,7 @@ export function useDataGridFormSchema(): VbenFormSchema[] { */ export function useDataGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '字典编码', diff --git a/apps/web-antd/src/views/system/dict/modules/data-grid.vue b/apps/web-antd/src/views/system/dict/modules/data-grid.vue index 22d4d5cc7..7079c8adb 100644 --- a/apps/web-antd/src/views/system/dict/modules/data-grid.vue +++ b/apps/web-antd/src/views/system/dict/modules/data-grid.vue @@ -2,16 +2,17 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemDictDataApi } from '#/api/system/dict/data'; -import { watch } from 'vue'; +import { ref, watch } from 'vue'; import { useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteDictData, + deleteDictDataList, exportDictData, getDictDataPage, } from '#/api/system/dict/data'; @@ -71,6 +72,31 @@ async function handleDelete(row: SystemDictDataApi.DictData) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemDictDataApi.DictData[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除字典数据 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteDictDataList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useDataGridFormSchema(), @@ -93,12 +119,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); /** 监听 dictType 变化,重新查询 */ @@ -134,6 +165,15 @@ watch( auth: ['system:dict:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:dict:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/dict/modules/type-grid.vue b/apps/web-antd/src/views/system/dict/modules/type-grid.vue index 0caa4afc5..98600900c 100644 --- a/apps/web-antd/src/views/system/dict/modules/type-grid.vue +++ b/apps/web-antd/src/views/system/dict/modules/type-grid.vue @@ -5,14 +5,17 @@ import type { } from '#/adapter/vxe-table'; import type { SystemDictTypeApi } from '#/api/system/dict/type'; +import { ref } from 'vue'; + import { useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteDictType, + deleteDictTypeList, exportDictType, getDictTypePage, } from '#/api/system/dict/type'; @@ -67,11 +70,38 @@ async function handleDelete(row: SystemDictTypeApi.DictType) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemDictTypeApi.DictType[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除字典类型 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteDictTypeList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + /** 表格事件 */ const gridEvents: VxeGridListeners = { cellClick: ({ row }) => { emit('select', row.type); }, + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, }; const [Grid, gridApi] = useVbenVxeGrid({ @@ -81,7 +111,6 @@ const [Grid, gridApi] = useVbenVxeGrid({ gridOptions: { columns: useTypeGridColumns(), height: 'auto', - keepSource: true, proxyConfig: { ajax: { query: async ({ page }, formValues) => { @@ -96,6 +125,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ rowConfig: { keyField: 'id', isCurrent: true, + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, @@ -128,6 +158,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:dict:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:dict:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/mail/account/data.ts b/apps/web-antd/src/views/system/mail/account/data.ts index e4cbbec40..dfe9775a5 100644 --- a/apps/web-antd/src/views/system/mail/account/data.ts +++ b/apps/web-antd/src/views/system/mail/account/data.ts @@ -122,6 +122,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '编号', diff --git a/apps/web-antd/src/views/system/mail/account/index.vue b/apps/web-antd/src/views/system/mail/account/index.vue index c67a4d0a6..e7344f424 100644 --- a/apps/web-antd/src/views/system/mail/account/index.vue +++ b/apps/web-antd/src/views/system/mail/account/index.vue @@ -2,13 +2,17 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemMailAccountApi } from '#/api/system/mail/account'; +import { ref } from 'vue'; + import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; +import { isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteMailAccount, + deleteMailAccountList, getMailAccountPage, } from '#/api/system/mail/account'; import { $t } from '#/locales'; @@ -54,6 +58,31 @@ async function handleDelete(row: SystemMailAccountApi.MailAccount) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemMailAccountApi.MailAccount[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除邮箱账号 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteMailAccountList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -75,12 +104,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -121,7 +164,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ icon: ACTION_ICON.DELETE, auth: ['system:mail-account:delete'], popConfirm: { - title: $t('ui.actionMessage.deleteConfirm', [row.name]), + title: $t('ui.actionMessage.deleteConfirm', [row.mail]), confirm: handleDelete.bind(null, row), }, }, diff --git a/apps/web-antd/src/views/system/mail/template/data.ts b/apps/web-antd/src/views/system/mail/template/data.ts index 06f03457a..7b46a9e60 100644 --- a/apps/web-antd/src/views/system/mail/template/data.ts +++ b/apps/web-antd/src/views/system/mail/template/data.ts @@ -192,6 +192,7 @@ export function useGridColumns( getAccountMail?: (accountId: number) => string | undefined, ): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '编号', diff --git a/apps/web-antd/src/views/system/mail/template/index.vue b/apps/web-antd/src/views/system/mail/template/index.vue index 35a894ef0..c45b3e714 100644 --- a/apps/web-antd/src/views/system/mail/template/index.vue +++ b/apps/web-antd/src/views/system/mail/template/index.vue @@ -6,6 +6,7 @@ import type { SystemMailTemplateApi } from '#/api/system/mail/template'; import { onMounted, ref } from 'vue'; import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; +import { isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; @@ -13,6 +14,7 @@ import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { getSimpleMailAccountList } from '#/api/system/mail/account'; import { deleteMailTemplate, + deleteMailTemplateList, getMailTemplatePage, } from '#/api/system/mail/template'; import { $t } from '#/locales'; @@ -68,6 +70,31 @@ async function handleDelete(row: SystemMailTemplateApi.MailTemplate) { onRefresh(); } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemMailTemplateApi.MailTemplate[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除邮件模板 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteMailTemplateList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + /** 获取邮箱账号 */ function getAccountMail(accountId: number) { return accountList.value.find((account) => account.id === accountId)?.mail; @@ -94,12 +121,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); /** 初始化 */ @@ -126,6 +158,15 @@ onMounted(async () => { auth: ['system:mail-template:create'], onClick: handleCreate, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:mail-template:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/notice/data.ts b/apps/web-antd/src/views/system/notice/data.ts index 7704f69c3..c00fb0d55 100644 --- a/apps/web-antd/src/views/system/notice/data.ts +++ b/apps/web-antd/src/views/system/notice/data.ts @@ -88,6 +88,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '公告编号', diff --git a/apps/web-antd/src/views/system/notice/index.vue b/apps/web-antd/src/views/system/notice/index.vue index 18983b49b..a7131bf82 100644 --- a/apps/web-antd/src/views/system/notice/index.vue +++ b/apps/web-antd/src/views/system/notice/index.vue @@ -2,12 +2,20 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemNoticeApi } from '#/api/system/notice'; +import { ref } from 'vue'; + import { Page, useVbenModal } from '@vben/common-ui'; +import { isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; -import { deleteNotice, getNoticePage, pushNotice } from '#/api/system/notice'; +import { + deleteNotice, + deleteNoticeList, + getNoticePage, + pushNotice, +} from '#/api/system/notice'; import { $t } from '#/locales'; import { useGridColumns, useGridFormSchema } from './data'; @@ -51,6 +59,31 @@ async function handleDelete(row: SystemNoticeApi.Notice) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemNoticeApi.Notice[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除公告 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteNoticeList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + /** 推送公告 */ async function handlePush(row: SystemNoticeApi.Notice) { const hideLoading = message.loading({ @@ -89,12 +122,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -112,6 +150,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:notice:create'], onClick: handleCreate, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:notice:delete'], + onClick: handleDeleteBatch, + }, ]" /> @@ -139,7 +186,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ icon: ACTION_ICON.DELETE, auth: ['system:notice:delete'], popConfirm: { - title: $t('ui.actionMessage.deleteConfirm', [row.name]), + title: $t('ui.actionMessage.deleteConfirm', [row.title]), confirm: handleDelete.bind(null, row), }, }, diff --git a/apps/web-antd/src/views/system/notify/template/data.ts b/apps/web-antd/src/views/system/notify/template/data.ts index fd0a63f09..1a828b3b8 100644 --- a/apps/web-antd/src/views/system/notify/template/data.ts +++ b/apps/web-antd/src/views/system/notify/template/data.ts @@ -226,6 +226,7 @@ export function useSendNotifyFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '编号', diff --git a/apps/web-antd/src/views/system/notify/template/index.vue b/apps/web-antd/src/views/system/notify/template/index.vue index bdd1f409e..54601ec57 100644 --- a/apps/web-antd/src/views/system/notify/template/index.vue +++ b/apps/web-antd/src/views/system/notify/template/index.vue @@ -2,14 +2,17 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; +import { ref } from 'vue'; + import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteNotifyTemplate, + deleteNotifyTemplateList, exportNotifyTemplate, getNotifyTemplatePage, } from '#/api/system/notify/template'; @@ -73,6 +76,31 @@ async function handleDelete(row: SystemNotifyTemplateApi.NotifyTemplate) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemNotifyTemplateApi.NotifyTemplate[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除站内信模板 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteNotifyTemplateList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -94,12 +122,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -129,6 +162,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:notify-template:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:notify-template:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/oauth2/token/data.ts b/apps/web-antd/src/views/system/oauth2/token/data.ts index d990000c6..3222c8731 100644 --- a/apps/web-antd/src/views/system/oauth2/token/data.ts +++ b/apps/web-antd/src/views/system/oauth2/token/data.ts @@ -37,6 +37,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'accessToken', title: '访问令牌', diff --git a/apps/web-antd/src/views/system/post/data.ts b/apps/web-antd/src/views/system/post/data.ts index cfb1ceb79..1016871a6 100644 --- a/apps/web-antd/src/views/system/post/data.ts +++ b/apps/web-antd/src/views/system/post/data.ts @@ -83,6 +83,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '岗位编号', diff --git a/apps/web-antd/src/views/system/post/index.vue b/apps/web-antd/src/views/system/post/index.vue index c17270606..126d7fd3d 100644 --- a/apps/web-antd/src/views/system/post/index.vue +++ b/apps/web-antd/src/views/system/post/index.vue @@ -2,13 +2,20 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemPostApi } from '#/api/system/post'; +import { ref } from 'vue'; + import { Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; -import { deletePost, exportPost, getPostPage } from '#/api/system/post'; +import { + deletePost, + deletePostList, + exportPost, + getPostPage, +} from '#/api/system/post'; import { $t } from '#/locales'; import { useGridColumns, useGridFormSchema } from './data'; @@ -58,6 +65,31 @@ async function handleDelete(row: SystemPostApi.Post) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemPostApi.Post[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除岗位 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deletePostList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -79,12 +111,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -109,6 +146,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:post:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:post:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/role/data.ts b/apps/web-antd/src/views/system/role/data.ts index 30ee7a3d8..1eb3ef155 100644 --- a/apps/web-antd/src/views/system/role/data.ts +++ b/apps/web-antd/src/views/system/role/data.ts @@ -186,6 +186,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '角色编号', diff --git a/apps/web-antd/src/views/system/role/index.vue b/apps/web-antd/src/views/system/role/index.vue index dcd3b5a82..3e64e8eb3 100644 --- a/apps/web-antd/src/views/system/role/index.vue +++ b/apps/web-antd/src/views/system/role/index.vue @@ -2,13 +2,20 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemRoleApi } from '#/api/system/role'; +import { ref } from 'vue'; + import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; -import { deleteRole, exportRole, getRolePage } from '#/api/system/role'; +import { + deleteRole, + deleteRoleList, + exportRole, + getRolePage, +} from '#/api/system/role'; import { $t } from '#/locales'; import { useGridColumns, useGridFormSchema } from './data'; @@ -71,6 +78,31 @@ async function handleDelete(row: SystemRoleApi.Role) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemRoleApi.Role[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除角色 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteRoleList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + /** 分配角色的数据权限 */ function handleAssignDataPermission(row: SystemRoleApi.Role) { assignDataPermissionFormApi.setData(row).open(); @@ -93,7 +125,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ ajax: { query: async ({ page }, formValues) => { return await getRolePage({ - page: page.currentPage, + pageNo: page.currentPage, pageSize: page.pageSize, ...formValues, }); @@ -102,12 +134,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -142,6 +179,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:role:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:role:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/sms/channel/data.ts b/apps/web-antd/src/views/system/sms/channel/data.ts index 18efe62f0..f00ea26d5 100644 --- a/apps/web-antd/src/views/system/sms/channel/data.ts +++ b/apps/web-antd/src/views/system/sms/channel/data.ts @@ -132,6 +132,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '编号', diff --git a/apps/web-antd/src/views/system/sms/channel/index.vue b/apps/web-antd/src/views/system/sms/channel/index.vue index bb9cbcfcf..f172f155f 100644 --- a/apps/web-antd/src/views/system/sms/channel/index.vue +++ b/apps/web-antd/src/views/system/sms/channel/index.vue @@ -2,14 +2,17 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemSmsChannelApi } from '#/api/system/sms/channel'; +import { ref } from 'vue'; + import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteSmsChannel, + deleteSmsChannelList, exportSmsChannel, getSmsChannelPage, } from '#/api/system/sms/channel'; @@ -62,6 +65,39 @@ async function handleDelete(row: SystemSmsChannelApi.SmsChannel) { } } +// 选中的短信渠道ID +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemSmsChannelApi.SmsChannel[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除处理 */ +async function handleDeleteBatch() { + if (checkedIds.value.length === 0) { + message.warning('请至少选择一条数据'); + return; + } + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting', ['短信渠道']), + key: 'action_key_msg', + }); + try { + await deleteSmsChannelList(checkedIds.value); + message.success({ + content: $t('ui.actionMessage.deleteSuccess', ['短信渠道']), + key: 'action_key_msg', + }); + checkedIds.value = []; + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -83,12 +119,20 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, + checkboxConfig: { + checkField: 'checked', + }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -117,6 +161,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:sms-channel:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:sms-channel:delete'], + onClick: handleDeleteBatch, + }, ]" /> @@ -137,7 +190,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ icon: ACTION_ICON.DELETE, auth: ['system:sms-channel:delete'], popConfirm: { - title: $t('ui.actionMessage.deleteConfirm', [row.name]), + title: $t('ui.actionMessage.deleteConfirm', [row.signature]), confirm: handleDelete.bind(null, row), }, }, diff --git a/apps/web-antd/src/views/system/sms/template/data.ts b/apps/web-antd/src/views/system/sms/template/data.ts index f56273cdb..d7f12f64a 100644 --- a/apps/web-antd/src/views/system/sms/template/data.ts +++ b/apps/web-antd/src/views/system/sms/template/data.ts @@ -202,6 +202,7 @@ export function useSendSmsFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '编号', diff --git a/apps/web-antd/src/views/system/sms/template/index.vue b/apps/web-antd/src/views/system/sms/template/index.vue index 1f229df98..0c0d349c9 100644 --- a/apps/web-antd/src/views/system/sms/template/index.vue +++ b/apps/web-antd/src/views/system/sms/template/index.vue @@ -2,14 +2,17 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemSmsTemplateApi } from '#/api/system/sms/template'; +import { ref } from 'vue'; + import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteSmsTemplate, + deleteSmsTemplateList, exportSmsTemplate, getSmsTemplatePage, } from '#/api/system/sms/template'; @@ -73,6 +76,31 @@ async function handleDelete(row: SystemSmsTemplateApi.SmsTemplate) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemSmsTemplateApi.SmsTemplate[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除短信模板 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteSmsTemplateList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -94,12 +122,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -129,6 +162,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:sms-template:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:sms-template:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/tenant/data.ts b/apps/web-antd/src/views/system/tenant/data.ts index 30b2a79d5..cdc5e2c6a 100644 --- a/apps/web-antd/src/views/system/tenant/data.ts +++ b/apps/web-antd/src/views/system/tenant/data.ts @@ -161,6 +161,7 @@ export function useGridColumns( getPackageName?: (packageId: number) => string | undefined, ): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '租户编号', diff --git a/apps/web-antd/src/views/system/tenant/index.vue b/apps/web-antd/src/views/system/tenant/index.vue index d57148ade..383f3293a 100644 --- a/apps/web-antd/src/views/system/tenant/index.vue +++ b/apps/web-antd/src/views/system/tenant/index.vue @@ -6,12 +6,17 @@ import type { SystemTenantPackageApi } from '#/api/system/tenant-package'; import { onMounted, ref } from 'vue'; import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; -import { deleteTenant, exportTenant, getTenantPage } from '#/api/system/tenant'; +import { + deleteTenant, + deleteTenantList, + exportTenant, + getTenantPage, +} from '#/api/system/tenant'; import { getTenantPackageList } from '#/api/system/tenant-package'; import { $t } from '#/locales'; @@ -72,6 +77,31 @@ async function handleDelete(row: SystemTenantApi.Tenant) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemTenantApi.Tenant[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除租户 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteTenantList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -91,12 +121,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); /** 初始化 */ @@ -129,6 +164,15 @@ onMounted(async () => { auth: ['system:tenant:export'], onClick: handleExport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:tenant:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/tenantPackage/data.ts b/apps/web-antd/src/views/system/tenantPackage/data.ts index 66775f892..7826f9c7b 100644 --- a/apps/web-antd/src/views/system/tenantPackage/data.ts +++ b/apps/web-antd/src/views/system/tenantPackage/data.ts @@ -88,6 +88,7 @@ export function useGridFormSchema(): VbenFormSchema[] { /** 列表的字段 */ export function useGridColumns(): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '套餐编号', diff --git a/apps/web-antd/src/views/system/tenantPackage/index.vue b/apps/web-antd/src/views/system/tenantPackage/index.vue index 3cee7fbb1..28287d303 100644 --- a/apps/web-antd/src/views/system/tenantPackage/index.vue +++ b/apps/web-antd/src/views/system/tenantPackage/index.vue @@ -2,13 +2,17 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { SystemTenantPackageApi } from '#/api/system/tenant-package'; +import { ref } from 'vue'; + import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; +import { isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteTenantPackage, + deleteTenantPackageList, getTenantPackagePage, } from '#/api/system/tenant-package'; import { $t } from '#/locales'; @@ -54,6 +58,31 @@ async function handleDelete(row: SystemTenantPackageApi.TenantPackage) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemTenantPackageApi.TenantPackage[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除租户套餐 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteTenantPackageList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { schema: useGridFormSchema(), @@ -75,12 +104,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -102,6 +136,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:tenant-package:create'], onClick: handleCreate, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:tenant-package:delete'], + onClick: handleDeleteBatch, + }, ]" /> diff --git a/apps/web-antd/src/views/system/user/data.ts b/apps/web-antd/src/views/system/user/data.ts index ae2c06ff0..8ec46607d 100644 --- a/apps/web-antd/src/views/system/user/data.ts +++ b/apps/web-antd/src/views/system/user/data.ts @@ -265,6 +265,7 @@ export function useGridColumns( ) => PromiseLike, ): VxeTableGridOptions['columns'] { return [ + { type: 'checkbox', width: 40 }, { field: 'id', title: '用户编号', diff --git a/apps/web-antd/src/views/system/user/index.vue b/apps/web-antd/src/views/system/user/index.vue index 2cd7d060b..9a296f572 100644 --- a/apps/web-antd/src/views/system/user/index.vue +++ b/apps/web-antd/src/views/system/user/index.vue @@ -6,13 +6,14 @@ import type { SystemUserApi } from '#/api/system/user'; import { ref } from 'vue'; import { confirm, DocAlert, Page, useVbenModal } from '@vben/common-ui'; -import { downloadFileFromBlobPart } from '@vben/utils'; +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { deleteUser, + deleteUserList, exportUser, getUserPage, updateUserStatus, @@ -99,6 +100,31 @@ async function handleDelete(row: SystemUserApi.User) { } } +const checkedIds = ref([]); +function handleRowCheckboxChange({ + records, +}: { + records: SystemUserApi.User[]; +}) { + checkedIds.value = records.map((item) => item.id as number); +} + +/** 批量删除用户 */ +async function handleDeleteBatch() { + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting'), + duration: 0, + key: 'action_process_msg', + }); + try { + await deleteUserList(checkedIds.value); + message.success($t('ui.actionMessage.deleteSuccess')); + onRefresh(); + } finally { + hideLoading(); + } +} + /** 重置密码 */ function handleResetPassword(row: SystemUserApi.User) { resetPasswordModalApi.setData(row).open(); @@ -157,12 +183,17 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, search: true, }, } as VxeTableGridOptions, + gridEvents: { + checkboxAll: handleRowCheckboxChange, + checkboxChange: handleRowCheckboxChange, + }, }); @@ -214,6 +245,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ auth: ['system:user:import'], onClick: handleImport, }, + { + label: '批量删除', + type: 'primary', + danger: true, + disabled: isEmpty(checkedIds), + icon: ACTION_ICON.DELETE, + auth: ['system:user:delete'], + onClick: handleDeleteBatch, + }, ]" />