Industrial-image-management.../src/views/system/user/index.vue

419 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<GiPageLayout>
<template #left>
<DeptTree @node-click="handleSelectDept" />
</template>
<GiTable
row-key="userId"
:data="dataList"
:columns="columns"
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1500 }"
:pagination="pagination"
:disabled-tools="['size']"
:disabled-column-keys="['name']"
@page-change="handlePageChange"
@page-size-change="handlePageSizeChange"
@refresh="search"
>
<template #top>
<GiForm v-model="queryForm" search :columns="queryFormColumns" size="medium" @search="search" @reset="reset"></GiForm>
</template>
<template #toolbar-left>
<a-button v-permission="['system:user:create']" type="primary" @click="onAdd">
<template #icon><icon-plus /></template>
<template #default>新增</template>
</a-button>
<a-button v-permission="['system:user:import']" @click="onImport">
<template #icon><icon-upload /></template>
<template #default>导入</template>
</a-button>
</template>
<template #toolbar-right>
<a-button v-permission="['system:user:export']" @click="onExport">
<template #icon><icon-download /></template>
<template #default>导出</template>
</a-button>
</template>
<template #name="{ record }">
<GiCellAvatar :avatar="record.avatar" :name="record.name" />
</template>
<template #gender="{ record }">
<GiCellGender :gender="record.gender" />
</template>
<template #roleIds="{ record }">
<GiCellTags :data="record.roleIds" />
</template>
<template #status="{ record }">
<GiCellStatus :status="record.status" />
</template>
<template #userStatus="{ record }">
<a-tag :color="record.userStatus === 'ENABLED' ? 'green' : 'red'" size="small">
{{ record.userStatusLabel || record.userStatus }}
</a-tag>
</template>
<template #userType="{ record }">
<a-tag color="blue" size="small">
{{ record.userTypeLabel || record.userType }}
</a-tag>
</template>
<template #action="{ record }">
<a-space>
<a-link v-permission="['system:user:get']" title="详情" @click="onDetail(record)">详情</a-link>
<a-link v-permission="['system:user:update']" title="修改" @click="onUpdate(record)">修改</a-link>
<a-link
v-permission="['system:user:delete']"
status="danger"
:title="'删除'"
@click="onDelete(record)"
>
删除
</a-link>
<a-dropdown>
<a-button v-if="has.hasPermOr(['system:user:resetPwd', 'system:user:updateRole'])" type="text" size="mini" title="更多">
<template #icon>
<icon-more :size="16" />
</template>
</a-button>
<template #content>
<a-doption v-permission="['system:user:resetPwd']" title="重置密码" @click="onResetPwd(record)">重置密码</a-doption>
<a-doption v-permission="['system:user:updateRole']" title="分配角色" @click="onUpdateRole(record)">分配角色</a-doption>
</template>
</a-dropdown>
</a-space>
</template>
</GiTable>
<UserAddDrawer ref="UserAddDrawerRef" @save-success="search" />
<UserImportDrawer ref="UserImportDrawerRef" @save-success="search" />
<UserDetailDrawer ref="UserDetailDrawerRef" />
<UserResetPwdModal ref="UserResetPwdModalRef" />
<UserUpdateRoleModal ref="UserUpdateRoleModalRef" @save-success="search" />
</GiPageLayout>
</template>
<script setup lang="ts">
import type { TableInstance } from '@arco-design/web-vue'
import { Modal, Message } from '@arco-design/web-vue'
import DeptTree from './dept/index.vue'
import UserAddDrawer from './UserAddDrawer.vue'
import UserImportDrawer from './UserImportDrawer.vue'
import UserDetailDrawer from './UserDetailDrawer.vue'
import UserResetPwdModal from './UserResetPwdModal.vue'
import UserUpdateRoleModal from './UserUpdateRoleModal.vue'
import {
deleteUserNew,
listUserNew,
pageUserNew
} from '@/apis/system/user-new'
import { exportUser } from '@/apis/system/user'
import type { UserNewResp, UserNewPageQuery, UserNewQuery } from '@/apis/system/type'
import { DisEnableStatusList } from '@/constant/common'
import { useDownload, useResetReactive, useTable } from '@/hooks'
import { isMobile } from '@/utils'
import has from '@/utils/has'
import type { ColumnItem } from '@/components/GiForm'
import { onMounted } from 'vue'
defineOptions({ name: 'SystemUser' })
const [queryForm, resetForm] = useResetReactive({
account: undefined,
name: undefined,
userStatus: undefined,
})
const queryFormColumns: ColumnItem[] = reactive([
{
type: 'input',
label: '用户名',
field: 'account',
span: { xs: 24, sm: 8, xxl: 8 },
props: {
placeholder: '账号/姓名/手机号',
},
},
{
type: 'input',
label: '姓名',
field: 'name',
span: { xs: 24, sm: 8, xxl: 8 },
props: {
placeholder: '请输入姓名',
},
},
{
type: 'select',
label: '在职状态',
field: 'userStatus',
span: { xs: 24, sm: 8, xxl: 8 },
props: {
options: [
{ label: '在职', value: 'ENABLED' },
{ label: '离职', value: 'DISABLED' }
],
placeholder: '请选择在职状态',
},
},
])
// 保存所有用户数据和筛选后的用户数据
const allUsers = ref<UserNewResp[]>([])
const filteredUsers = ref<UserNewResp[]>([])
const loading = ref(false)
// 当前选中的部门名称
const selectedDeptName = ref<string>('')
// 分页配置
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
showTotal: true,
showJumper: true,
showPageSize: true,
})
// 获取所有用户数据
const fetchAllUsers = async () => {
try {
loading.value = true
// 直接使用 /user/list 接口获取所有用户
const { data } = await listUserNew({
account: queryForm.account,
name: queryForm.name,
userStatus: queryForm.userStatus,
sort: undefined
} as UserNewQuery)
console.log(data)
allUsers.value = data || []
// 根据当前筛选条件过滤用户
filterUsersByDept()
} catch (error) {
console.error('获取用户列表失败:', error)
} finally {
loading.value = false
}
}
// 根据部门名称筛选用户
const filterUsersByDept = () => {
if (!selectedDeptName.value) {
// 没有选择部门,显示所有用户
filteredUsers.value = [...allUsers.value]
} else {
// 有部门名称,筛选该部门的用户
filteredUsers.value = allUsers.value.filter(user => user.deptName === selectedDeptName.value)
}
// 更新分页总数
pagination.total = filteredUsers.value.length
}
// 当前页数据
const dataList = computed(() => {
const start = (pagination.current - 1) * pagination.pageSize
const end = start + pagination.pageSize
return filteredUsers.value.slice(start, end)
})
// 处理分页变化
const handlePageChange = (current: number) => {
pagination.current = current
}
// 处理每页条数变化
const handlePageSizeChange = (pageSize: number) => {
pagination.pageSize = pageSize
pagination.current = 1
}
// 重置
const reset = () => {
resetForm()
fetchAllUsers()
}
// 搜索
const search = () => {
pagination.current = 1
fetchAllUsers()
}
// 删除
const handleDelete = (callback: () => Promise<any>, options: { content?: string; showModal?: boolean } = {}) => {
const { content, showModal = false } = options
const doDelete = async () => {
loading.value = true
try {
await callback()
// 删除成功后重新获取数据
fetchAllUsers()
Message.success('删除成功')
return true
} catch (error) {
console.error('删除失败:', error)
Message.error('删除失败')
return false
} finally {
loading.value = false
}
}
if (showModal) {
Modal.confirm({
title: '确认删除',
content: content || '确定要删除此记录吗?',
okText: '确认',
cancelText: '取消',
onOk: () => doDelete()
})
return
}
return doDelete()
}
// 删除用户
const onDelete = (record: UserNewResp) => {
if (!record || !record.userId) {
return Message.warning('用户ID不存在无法删除')
}
return handleDelete(
() => deleteUserNew(record.userId),
{
content: `是否确定删除用户「${record.name || ''}(${record.account || ''})」?`,
showModal: true
}
)
}
// 导出
const onExport = () => {
useDownload(() => exportUser({...queryForm, sort: undefined}))
}
const columns: TableInstance['columns'] = [
{
title: '序号',
width: 66,
align: 'center',
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
fixed: !isMobile() ? 'left' : undefined,
},
{
title: '姓名',
dataIndex: 'name',
slotName: 'name',
minWidth: 140,
ellipsis: true,
tooltip: true,
fixed: !isMobile() ? 'left' : undefined,
},
{ title: '账号', dataIndex: 'account', minWidth: 140, ellipsis: true, tooltip: true },
{ title: '员工编码', dataIndex: 'userCode', minWidth: 120, ellipsis: true, tooltip: true },
{ title: '性别', dataIndex: 'gender', slotName: 'gender', align: 'center', width: 80 },
{ title: '手机号', dataIndex: 'mobile', minWidth: 170, ellipsis: true, tooltip: true },
{ title: '所属部门', dataIndex: 'deptName', minWidth: 180, ellipsis: true, tooltip: true },
{ title: '学历', dataIndex: 'educationLabel', width: 100, ellipsis: true, tooltip: true, show: false },
{ title: '专业', dataIndex: 'majorField', width: 120, ellipsis: true, tooltip: true, show: false },
{ title: '在职状态', dataIndex: 'userStatus', slotName: 'userStatus', align: 'center', width: 100 },
{ title: '员工性质', dataIndex: 'userType', slotName: 'userType', align: 'center', width: 100 },
{ title: '角色', dataIndex: 'roleName', slotName: 'roleName', minWidth: 185 },
{ title: '邮箱', dataIndex: 'email', slotName: 'email', minWidth: 170, ellipsis: true, tooltip: true },
{ title: '入职日期', dataIndex: 'hiredate', width: 120, ellipsis: true, tooltip: true },
{ title: '出生日期', dataIndex: 'birthdate', width: 120, ellipsis: true, tooltip: true, show: false },
{ title: '工作方向', dataIndex: 'workField', width: 120, ellipsis: true, tooltip: true, show: false },
{ title: '身份证', dataIndex: 'identityCard', width: 180, ellipsis: true, tooltip: true, show: false },
{
title: '操作',
dataIndex: 'action',
slotName: 'action',
width: 190,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr([
'system:user:get',
'system:user:update',
'system:user:delete',
'system:user:resetPwd',
'system:user:updateRole',
]),
},
]
// 根据选中部门查询
const handleSelectDept = (keys: Array<any>, node?: any) => {
// 如果选择"all",则设置部门名称为空字符串,查询全部
if (keys.length === 1 && keys[0] === 'all') {
selectedDeptName.value = ''
} else if (node && node.title) {
// 设置选中的部门名称
selectedDeptName.value = node.title
} else {
selectedDeptName.value = ''
}
// 仅在本地过滤数据不重新请求API
filterUsersByDept()
// 重置分页到第一页
pagination.current = 1
}
const UserImportDrawerRef = ref<InstanceType<typeof UserImportDrawer>>()
// 导入
const onImport = () => {
UserImportDrawerRef.value?.onOpen()
}
const UserAddDrawerRef = ref<InstanceType<typeof UserAddDrawer>>()
// 新增
const onAdd = () => {
UserAddDrawerRef.value?.onAdd()
}
// 修改
const onUpdate = (record: UserNewResp) => {
UserAddDrawerRef.value?.onUpdate(record.userId)
}
const UserDetailDrawerRef = ref<InstanceType<typeof UserDetailDrawer>>()
// 详情
const onDetail = (record: UserNewResp) => {
UserDetailDrawerRef.value?.onOpen(record.userId)
}
const UserResetPwdModalRef = ref<InstanceType<typeof UserResetPwdModal>>()
// 重置密码
const onResetPwd = (record: UserNewResp) => {
UserResetPwdModalRef.value?.onOpen(record.userId)
}
const UserUpdateRoleModalRef = ref<InstanceType<typeof UserUpdateRoleModal>>()
// 分配角色
const onUpdateRole = (record: UserNewResp) => {
UserUpdateRoleModalRef.value?.onOpen(record.userId)
}
// 声明是否首次加载,首次加载时展示所有用户
const isFirstLoad = ref(true)
// 初始加载
onMounted(() => {
// 初始加载所有用户数据
fetchAllUsers()
})
</script>
<style scoped lang="scss">
.page_header {
flex: 0 0 auto;
}
.page_content {
flex: 1;
overflow: auto;
}
</style>