| | |
| | | <template #left> |
| | | <ElSpace wrap> |
| | | <ElButton v-auth="'add'" @click="showDialog('add')" v-ripple>新增用户</ElButton> |
| | | <ElButton |
| | | v-auth="'delete'" |
| | | type="danger" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="handleBatchDelete" |
| | | v-ripple |
| | | > |
| | | 批量删除 |
| | | </ElButton> |
| | | <ElButton v-auth="'query'" :loading="exportLoading" @click="handleExport" v-ripple |
| | | >导出</ElButton |
| | | > |
| | | </ElSpace> |
| | | </template> |
| | | </ArtTableHeader> |
| | |
| | | :data="data" |
| | | :columns="columns" |
| | | :pagination="pagination" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination:size-change="handleSizeChange" |
| | | @pagination:current-change="handleCurrentChange" |
| | | /> |
| | |
| | | <script setup> |
| | | import request from '@/utils/http' |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { useUserStore } from '@/store/modules/user' |
| | | import { |
| | | fetchDeleteUser, |
| | | fetchExportUserReport, |
| | | fetchGetDeptTree, |
| | | fetchGetRoleOptions, |
| | | fetchGetUserDetail, |
| | |
| | | const detailDrawerVisible = ref(false) |
| | | const detailLoading = ref(false) |
| | | const detailUserData = ref({}) |
| | | const selectedRows = ref([]) |
| | | const roleOptions = ref([]) |
| | | const deptTreeOptions = ref([]) |
| | | const exportLoading = ref(false) |
| | | const RESET_PASSWORD = '123456' |
| | | const { hasAuth } = useAuth() |
| | | const userStore = useUserStore() |
| | | |
| | | const fetchUserPage = (params = {}) => { |
| | | return request.post({ |
| | |
| | | apiParams: buildUserPageQueryParams(searchForm.value), |
| | | paginationKey: getUserPaginationKey(), |
| | | columnsFactory: () => [ |
| | | { |
| | | type: 'selection', |
| | | width: 52, |
| | | fixed: 'left', |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'username', |
| | | label: '用户名', |
| | |
| | | getData() |
| | | } |
| | | |
| | | const handleSelectionChange = (rows) => { |
| | | selectedRows.value = Array.isArray(rows) ? rows : [] |
| | | } |
| | | |
| | | const handleReset = () => { |
| | | Object.assign(searchForm.value, createUserSearchState()) |
| | | resetSearchParams() |
| | |
| | | |
| | | const handleDelete = async (row) => { |
| | | try { |
| | | await ElMessageBox.confirm(`确定要删除用户「${row.username || row.nickname || row.id}」吗?`, '删除确认', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }) |
| | | await ElMessageBox.confirm( |
| | | `确定要删除用户「${row.username || row.nickname || row.id}」吗?`, |
| | | '删除确认', |
| | | { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | } |
| | | ) |
| | | await fetchDeleteUser(row.id) |
| | | ElMessage.success('删除成功') |
| | | await refreshRemove() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error(error?.message || '删除失败') |
| | | } |
| | | } |
| | | } |
| | | |
| | | const handleBatchDelete = async () => { |
| | | if (!selectedRows.value.length) return |
| | | const ids = selectedRows.value |
| | | .map((item) => item?.id) |
| | | .filter((id) => id !== void 0 && id !== null) |
| | | |
| | | if (!ids.length) return |
| | | |
| | | try { |
| | | await ElMessageBox.confirm(`确定要批量删除选中的 ${ids.length} 个用户吗?`, '批量删除确认', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }) |
| | | await fetchDeleteUser(ids.join(',')) |
| | | ElMessage.success('批量删除成功') |
| | | selectedRows.value = [] |
| | | await refreshRemove() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error(error?.message || '批量删除失败') |
| | | } |
| | | } |
| | | } |
| | |
| | | row._statusLoading = false |
| | | } |
| | | } |
| | | |
| | | const handleExport = async () => { |
| | | exportLoading.value = true |
| | | try { |
| | | const response = await guardRequestWithMessage( |
| | | fetchExportUserReport(buildUserSearchParams(searchForm.value), { |
| | | headers: { |
| | | Authorization: userStore.accessToken || '' |
| | | } |
| | | }), |
| | | null, |
| | | { |
| | | timeoutMessage: '用户导出超时,已停止等待' |
| | | } |
| | | ) |
| | | if (!response) { |
| | | return |
| | | } |
| | | if (!response.ok) { |
| | | throw new Error(`导出失败,状态码:${response.status}`) |
| | | } |
| | | const blob = await response.blob() |
| | | const downloadUrl = window.URL.createObjectURL(blob) |
| | | const link = document.createElement('a') |
| | | link.href = downloadUrl |
| | | link.download = 'user.xlsx' |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | link.remove() |
| | | window.URL.revokeObjectURL(downloadUrl) |
| | | ElMessage.success('导出成功') |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '导出失败') |
| | | } finally { |
| | | exportLoading.value = false |
| | | } |
| | | } |
| | | </script> |