forked from admin/hair-keeper
Hair Keeper v1.0.0:一个高度集成、深度定制、约定优于配置的全栈Web应用模板,旨在保持灵活性的同时提供一套基于成熟架构的开发底座,自带身份认证、权限控制、丰富前端组件、文件上传、后台任务、智能体开发等丰富功能,提供AI开发辅助,免于纠结功能如何实现,可快速上手专注于业务逻辑
This commit is contained in:
150
src/app/(main)/users/page.tsx
Normal file
150
src/app/(main)/users/page.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState, useCallback, useMemo, Suspense } from 'react'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { UserCreateDialog } from './components/UserCreateDialog'
|
||||
import { UserUpdateDialog } from './components/UserUpdateDialog'
|
||||
import { UserDeleteDialog } from './components/UserDeleteDialog'
|
||||
import { RoleManagementDialog } from './components/RoleManagementDialog'
|
||||
import { BatchAuthorizationDialog } from './components/BatchAuthorizationDialog'
|
||||
import { DataTable } from '@/components/data-table/data-table'
|
||||
import { DataTableToolbar } from '@/components/data-table/toolbar'
|
||||
import { createUserColumns, type UserColumnsOptions } from './columns'
|
||||
import type { User } from '@/server/routers/users'
|
||||
import { useDataTable } from '@/hooks/use-data-table'
|
||||
import { keepPreviousData } from '@tanstack/react-query'
|
||||
import { DataTableSortList } from '@/components/data-table/sort-list'
|
||||
import { toast } from 'sonner'
|
||||
import { DataTableSkeleton } from '@/components/data-table/table-skeleton'
|
||||
|
||||
interface UsersPageDataTableProps {
|
||||
onEdit: (userId: string) => void
|
||||
onDelete: (userId: string) => void
|
||||
}
|
||||
|
||||
function UsersPageDataTable({ onEdit, onDelete }: UsersPageDataTableProps) {
|
||||
// 获取角色、权限和部门列表用于过滤器选项
|
||||
const { data: roles } = trpc.users.getRoles.useQuery()
|
||||
const { data: permissions } = trpc.users.getPermissions.useQuery()
|
||||
const { data: depts } = trpc.common.getDepts.useQuery()
|
||||
|
||||
// 创建表格列定义选项
|
||||
const columnsOptions: UserColumnsOptions = useMemo(() => ({
|
||||
roles: roles || [],
|
||||
permissions: permissions || [],
|
||||
depts: depts || [],
|
||||
}), [roles, permissions, depts])
|
||||
|
||||
// 创建表格列定义
|
||||
const columns = useMemo(() => createUserColumns({
|
||||
onEdit,
|
||||
onDelete,
|
||||
}, columnsOptions), [onEdit, onDelete, columnsOptions])
|
||||
|
||||
// 使用 useDataTable hook,传入 queryFn
|
||||
const { table, queryResult } = useDataTable<User>({
|
||||
columns,
|
||||
initialState: {
|
||||
pagination: { pageIndex: 1, pageSize: 10 },
|
||||
columnPinning: { left: ["select"], right: ["actions"] },
|
||||
},
|
||||
getRowId: (row) => row.id,
|
||||
queryFn: useCallback((params) => {
|
||||
const result = trpc.users.list.useQuery(params, {
|
||||
placeholderData: keepPreviousData,
|
||||
})
|
||||
if (result.error) {
|
||||
toast.error("获取用户数据失败:" + result.error.toString().substring(0, 100))
|
||||
}
|
||||
return result
|
||||
}, []),
|
||||
})
|
||||
|
||||
return (
|
||||
<DataTable table={table} isLoading={queryResult.isLoading}>
|
||||
<DataTableToolbar table={table}>
|
||||
<DataTableSortList table={table} />
|
||||
</DataTableToolbar>
|
||||
</DataTable>
|
||||
)
|
||||
}
|
||||
|
||||
export default function UsersPage() {
|
||||
// 更新用户对话框状态
|
||||
const [updateUserId, setUpdateUserId] = useState<string | null>(null)
|
||||
const [isUpdateDialogOpen, setIsUpdateDialogOpen] = useState(false)
|
||||
|
||||
// 删除用户对话框状态
|
||||
const [deleteUserId, setDeleteUserId] = useState<string | null>(null)
|
||||
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false)
|
||||
|
||||
// 用于刷新数据的 utils
|
||||
const utils = trpc.useUtils()
|
||||
|
||||
// 处理编辑用户
|
||||
const handleEditUser = useCallback((userId: string) => {
|
||||
setUpdateUserId(userId)
|
||||
setIsUpdateDialogOpen(true)
|
||||
}, [])
|
||||
|
||||
// 关闭更新对话框
|
||||
const handleCloseUpdateDialog = useCallback(() => {
|
||||
setIsUpdateDialogOpen(false)
|
||||
setUpdateUserId(null)
|
||||
}, [])
|
||||
|
||||
// 处理删除用户
|
||||
const handleDeleteUser = useCallback((userId: string) => {
|
||||
setDeleteUserId(userId)
|
||||
setIsDeleteDialogOpen(true)
|
||||
}, [])
|
||||
|
||||
// 关闭删除对话框
|
||||
const handleCloseDeleteDialog = useCallback(() => {
|
||||
setIsDeleteDialogOpen(false)
|
||||
setDeleteUserId(null)
|
||||
}, [])
|
||||
|
||||
// 刷新用户列表
|
||||
const handleRefreshUsers = useCallback(() => {
|
||||
utils.users.list.invalidate()
|
||||
}, [utils])
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* 用户列表和创建按钮 */}
|
||||
<Card>
|
||||
<CardHeader className="flex items-center justify-between">
|
||||
<CardTitle className="text-lg">用户列表</CardTitle>
|
||||
<div className="flex items-center gap-2">
|
||||
<RoleManagementDialog />
|
||||
<BatchAuthorizationDialog />
|
||||
<UserCreateDialog onUserCreated={handleRefreshUsers} />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Suspense fallback={<DataTableSkeleton columnCount={8} rowCount={10} />}>
|
||||
<UsersPageDataTable onEdit={handleEditUser} onDelete={handleDeleteUser} />
|
||||
</Suspense>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 更新用户对话框 */}
|
||||
<UserUpdateDialog
|
||||
userId={updateUserId}
|
||||
isOpen={isUpdateDialogOpen}
|
||||
onClose={handleCloseUpdateDialog}
|
||||
onUserUpdated={handleRefreshUsers}
|
||||
/>
|
||||
|
||||
{/* 删除用户对话框 */}
|
||||
<UserDeleteDialog
|
||||
userId={deleteUserId}
|
||||
isOpen={isDeleteDialogOpen}
|
||||
onClose={handleCloseDeleteDialog}
|
||||
onUserDeleted={handleRefreshUsers}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user