Files
stu-ai-demo/src/app/(main)/users/page.tsx

151 lines
5.0 KiB
TypeScript
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.
'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>
)
}