增加团队管理页面
This commit is contained in:
parent
75d8935ac3
commit
4a4da47253
@ -2,14 +2,23 @@ import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
interface TableProps extends React.HTMLAttributes<HTMLTableElement> {
|
||||
/**
|
||||
* 最小宽度,当表格内容超过容器宽度时启用横向滚动
|
||||
* 例如: "1200px" 或 undefined(不启用)
|
||||
*/
|
||||
minWidth?: string;
|
||||
}
|
||||
|
||||
const Table = React.forwardRef<
|
||||
HTMLTableElement,
|
||||
React.HTMLTableProps<HTMLTableElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
TableProps
|
||||
>(({ className, minWidth, style, ...props }, ref) => (
|
||||
<div className="relative w-full overflow-auto">
|
||||
<table
|
||||
ref={ref}
|
||||
className={cn("w-full caption-bottom text-sm", className)}
|
||||
style={{ ...style, ...(minWidth ? { minWidth } : {}) }}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
@ -18,7 +27,7 @@ Table.displayName = "Table"
|
||||
|
||||
const TableHeader = React.forwardRef<
|
||||
HTMLTableSectionElement,
|
||||
React.HTMLTableSectionProps
|
||||
React.HTMLAttributes<HTMLTableSectionElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
||||
))
|
||||
@ -26,7 +35,7 @@ TableHeader.displayName = "TableHeader"
|
||||
|
||||
const TableBody = React.forwardRef<
|
||||
HTMLTableSectionElement,
|
||||
React.HTMLTableSectionProps
|
||||
React.HTMLAttributes<HTMLTableSectionElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<tbody
|
||||
ref={ref}
|
||||
@ -38,7 +47,7 @@ TableBody.displayName = "TableBody"
|
||||
|
||||
const TableFooter = React.forwardRef<
|
||||
HTMLTableSectionElement,
|
||||
React.HTMLTableSectionProps
|
||||
React.HTMLAttributes<HTMLTableSectionElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<tfoot
|
||||
ref={ref}
|
||||
@ -50,7 +59,7 @@ TableFooter.displayName = "TableFooter"
|
||||
|
||||
const TableRow = React.forwardRef<
|
||||
HTMLTableRowElement,
|
||||
React.HTMLTableRowProps
|
||||
React.HTMLAttributes<HTMLTableRowElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<tr
|
||||
ref={ref}
|
||||
@ -63,28 +72,59 @@ const TableRow = React.forwardRef<
|
||||
))
|
||||
TableRow.displayName = "TableRow"
|
||||
|
||||
interface TableHeadProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
|
||||
/**
|
||||
* 是否固定列(通常用于操作列)
|
||||
* 启用后该列会固定在右侧,即使横向滚动也始终可见
|
||||
*/
|
||||
sticky?: boolean;
|
||||
/**
|
||||
* 列宽度,例如: "120px", "200px"
|
||||
*/
|
||||
width?: string;
|
||||
}
|
||||
|
||||
const TableHead = React.forwardRef<
|
||||
HTMLTableCellElement,
|
||||
React.ThHTMLAttributes<HTMLTableCellElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
TableHeadProps
|
||||
>(({ className, sticky, width, style, ...props }, ref) => (
|
||||
<th
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
||||
sticky && "sticky right-0 bg-background shadow-[-2px_0_4px_rgba(0,0,0,0.05)]",
|
||||
className
|
||||
)}
|
||||
style={{ ...style, ...(width ? { width } : {}) }}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TableHead.displayName = "TableHead"
|
||||
|
||||
interface TableCellProps extends React.TdHTMLAttributes<HTMLTableCellElement> {
|
||||
/**
|
||||
* 是否固定列(通常用于操作列)
|
||||
* 启用后该列会固定在右侧,即使横向滚动也始终可见
|
||||
*/
|
||||
sticky?: boolean;
|
||||
/**
|
||||
* 列宽度,例如: "120px", "200px"
|
||||
*/
|
||||
width?: string;
|
||||
}
|
||||
|
||||
const TableCell = React.forwardRef<
|
||||
HTMLTableCellElement,
|
||||
React.TdHTMLAttributes<HTMLTableCellElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
TableCellProps
|
||||
>(({ className, sticky, width, style, ...props }, ref) => (
|
||||
<td
|
||||
ref={ref}
|
||||
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
|
||||
className={cn(
|
||||
"p-4 align-middle [&:has([role=checkbox])]:pr-0",
|
||||
sticky && "sticky right-0 bg-background shadow-[-2px_0_4px_rgba(0,0,0,0.05)]",
|
||||
className
|
||||
)}
|
||||
style={{ ...style, ...(width ? { width } : {}) }}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
||||
@ -263,18 +263,18 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
|
||||
</div>
|
||||
|
||||
{/* 表格 */}
|
||||
<div className="overflow-x-auto">
|
||||
<Table>
|
||||
<div className="rounded-md border">
|
||||
<Table minWidth="890px">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[160px]">分类名称</TableHead>
|
||||
<TableHead className="w-[140px]">分类代码</TableHead>
|
||||
<TableHead className="w-[60px]">图标</TableHead>
|
||||
<TableHead className="w-[120px]">应用数量</TableHead>
|
||||
<TableHead className="w-[80px]">排序</TableHead>
|
||||
<TableHead className="w-[80px]">状态</TableHead>
|
||||
<TableHead className="min-w-[150px]">描述</TableHead>
|
||||
<TableHead className="w-[100px] sticky right-0 bg-background shadow-[-2px_0_4px_rgba(0,0,0,0.05)]">操作</TableHead>
|
||||
<TableHead width="160px">分类名称</TableHead>
|
||||
<TableHead width="140px">分类代码</TableHead>
|
||||
<TableHead width="60px">图标</TableHead>
|
||||
<TableHead width="120px">应用数量</TableHead>
|
||||
<TableHead width="80px">排序</TableHead>
|
||||
<TableHead width="80px">状态</TableHead>
|
||||
<TableHead width="150px">描述</TableHead>
|
||||
<TableHead width="100px" sticky>操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@ -290,15 +290,15 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
|
||||
) : data?.content && data.content.length > 0 ? (
|
||||
data.content.map((record) => (
|
||||
<TableRow key={record.id}>
|
||||
<TableCell className="font-medium">
|
||||
<TableCell width="160px" className="font-medium">
|
||||
{record.name}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="140px">
|
||||
<code className="text-xs bg-muted px-2 py-0.5 rounded whitespace-nowrap">
|
||||
{record.code}
|
||||
</code>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="60px">
|
||||
{record.icon ? (
|
||||
<div className="flex items-center justify-center">
|
||||
<DynamicIcon name={record.icon} className="h-5 w-5" />
|
||||
@ -307,21 +307,21 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
|
||||
<span className="text-muted-foreground text-sm">-</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="text-center">
|
||||
<TableCell width="120px" className="text-center">
|
||||
<span className="text-sm font-medium">{record.applicationCount || 0}</span>
|
||||
</TableCell>
|
||||
<TableCell className="text-center">{record.sort}</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="80px" className="text-center">{record.sort}</TableCell>
|
||||
<TableCell width="80px">
|
||||
{record.enabled ? (
|
||||
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
||||
) : (
|
||||
<XCircle className="h-4 w-4 text-gray-400" />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="max-w-[200px] truncate" title={record.description}>
|
||||
<TableCell width="150px" className="max-w-[150px] truncate" title={record.description}>
|
||||
{record.description || '-'}
|
||||
</TableCell>
|
||||
<TableCell className="sticky right-0 bg-background shadow-[-2px_0_4px_rgba(0,0,0,0.05)]">
|
||||
<TableCell width="100px" sticky>
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
<Button
|
||||
variant="ghost"
|
||||
|
||||
@ -459,13 +459,14 @@ const ApplicationList: React.FC = () => {
|
||||
|
||||
{/* 数据表格 */}
|
||||
<div className="rounded-md border">
|
||||
<Table>
|
||||
<Table minWidth="1400px">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{columns.map((column) => (
|
||||
<TableHead
|
||||
key={column.accessorKey || column.id}
|
||||
style={{ width: column.size }}
|
||||
width={column.size ? `${column.size}px` : undefined}
|
||||
sticky={column.id === 'actions'}
|
||||
>
|
||||
{column.header}
|
||||
</TableHead>
|
||||
@ -473,7 +474,16 @@ const ApplicationList: React.FC = () => {
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{list.length === 0 ? (
|
||||
{loading ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<div className="h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" />
|
||||
<span className="text-muted-foreground">加载中...</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : list.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
暂无数据
|
||||
@ -493,7 +503,11 @@ const ApplicationList: React.FC = () => {
|
||||
cellContent = '';
|
||||
}
|
||||
return (
|
||||
<TableCell key={column.accessorKey || column.id}>
|
||||
<TableCell
|
||||
key={column.accessorKey || column.id}
|
||||
width={column.size ? `${column.size}px` : undefined}
|
||||
sticky={column.id === 'actions'}
|
||||
>
|
||||
{cellContent}
|
||||
</TableCell>
|
||||
);
|
||||
|
||||
@ -319,15 +319,15 @@ const ApplicationManageDialog: React.FC<ApplicationManageDialogProps> = ({
|
||||
|
||||
{/* 表格 */}
|
||||
<div className="border rounded-lg overflow-hidden">
|
||||
<div className="overflow-x-auto max-h-[50vh]">
|
||||
<Table>
|
||||
<div className="max-h-[50vh] overflow-y-auto">
|
||||
<Table minWidth="690px">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">应用ID</TableHead>
|
||||
<TableHead className="w-[150px]">应用编码</TableHead>
|
||||
<TableHead className="w-[200px]">应用名称</TableHead>
|
||||
<TableHead className="w-[160px]">创建时间</TableHead>
|
||||
<TableHead className="w-[80px] text-right">操作</TableHead>
|
||||
<TableHead width="100px">应用ID</TableHead>
|
||||
<TableHead width="150px">应用编码</TableHead>
|
||||
<TableHead width="200px">应用名称</TableHead>
|
||||
<TableHead width="160px">创建时间</TableHead>
|
||||
<TableHead width="80px" sticky>操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@ -343,19 +343,19 @@ const ApplicationManageDialog: React.FC<ApplicationManageDialogProps> = ({
|
||||
) : data?.content && data.content.length > 0 ? (
|
||||
data.content.map((record) => (
|
||||
<TableRow key={record.id}>
|
||||
<TableCell className="font-medium">
|
||||
<TableCell width="100px" className="font-medium">
|
||||
{record.applicationId}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="150px">
|
||||
{record.applicationCode || '-'}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="200px">
|
||||
{record.applicationName || '-'}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="160px">
|
||||
{record.createTime || '-'}
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<TableCell width="80px" sticky>
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
<Button
|
||||
variant="ghost"
|
||||
|
||||
@ -367,15 +367,15 @@ const MemberManageDialog: React.FC<MemberManageDialogProps> = ({
|
||||
|
||||
{/* 表格 */}
|
||||
<div className="border rounded-lg overflow-hidden">
|
||||
<div className="overflow-x-auto max-h-[50vh]">
|
||||
<Table>
|
||||
<div className="max-h-[50vh] overflow-y-auto">
|
||||
<Table minWidth="680px">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">用户ID</TableHead>
|
||||
<TableHead className="w-[150px]">用户名</TableHead>
|
||||
<TableHead className="w-[150px]">团队角色</TableHead>
|
||||
<TableHead className="w-[160px]">加入时间</TableHead>
|
||||
<TableHead className="w-[120px] text-right">操作</TableHead>
|
||||
<TableHead width="100px">用户ID</TableHead>
|
||||
<TableHead width="150px">用户名</TableHead>
|
||||
<TableHead width="150px">团队角色</TableHead>
|
||||
<TableHead width="160px">加入时间</TableHead>
|
||||
<TableHead width="120px" sticky>操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@ -391,19 +391,19 @@ const MemberManageDialog: React.FC<MemberManageDialogProps> = ({
|
||||
) : data?.content && data.content.length > 0 ? (
|
||||
data.content.map((record) => (
|
||||
<TableRow key={record.id}>
|
||||
<TableCell className="font-medium">
|
||||
<TableCell width="100px" className="font-medium">
|
||||
{record.userId}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="150px">
|
||||
{record.userName || '-'}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="150px">
|
||||
{record.roleInTeam || '-'}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell width="160px">
|
||||
{record.joinTime || '-'}
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<TableCell width="120px" sticky>
|
||||
<div className="flex items-center justify-end gap-1">
|
||||
<Button
|
||||
variant="ghost"
|
||||
|
||||
@ -193,28 +193,28 @@ const TeamList: React.FC = () => {
|
||||
{
|
||||
accessorKey: 'teamCode',
|
||||
header: '团队编码',
|
||||
size: 150,
|
||||
size: 180,
|
||||
},
|
||||
{
|
||||
accessorKey: 'teamName',
|
||||
header: '团队名称',
|
||||
size: 150,
|
||||
size: 180,
|
||||
},
|
||||
{
|
||||
accessorKey: 'description',
|
||||
header: '团队描述',
|
||||
size: 200,
|
||||
size: 260,
|
||||
},
|
||||
{
|
||||
accessorKey: 'ownerName',
|
||||
header: '负责人',
|
||||
size: 120,
|
||||
size: 140,
|
||||
cell: ({ row }) => row.original.ownerName || '-',
|
||||
},
|
||||
{
|
||||
id: 'memberCount',
|
||||
header: '成员数量',
|
||||
size: 100,
|
||||
size: 120,
|
||||
cell: ({ row }) => (
|
||||
<div className="text-center">
|
||||
<span className="font-medium">{row.original.memberCount || 0}</span>
|
||||
@ -224,7 +224,7 @@ const TeamList: React.FC = () => {
|
||||
{
|
||||
id: 'applicationCount',
|
||||
header: '应用数量',
|
||||
size: 100,
|
||||
size: 120,
|
||||
cell: ({ row }) => (
|
||||
<div className="text-center">
|
||||
<span className="font-medium">{row.original.applicationCount || 0}</span>
|
||||
@ -244,12 +244,12 @@ const TeamList: React.FC = () => {
|
||||
{
|
||||
accessorKey: 'sort',
|
||||
header: '排序',
|
||||
size: 80,
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
header: '操作',
|
||||
size: 200,
|
||||
size: 260,
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="ghost" size="sm" onClick={() => handleManageMembers(row.original)}>
|
||||
@ -368,13 +368,14 @@ const TeamList: React.FC = () => {
|
||||
|
||||
{/* 数据表格 */}
|
||||
<div className="rounded-md border">
|
||||
<Table>
|
||||
<Table minWidth="1460px">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{columns.map((column) => (
|
||||
<TableHead
|
||||
key={column.accessorKey || column.id}
|
||||
style={{ width: column.size }}
|
||||
width={column.size ? `${column.size}px` : undefined}
|
||||
sticky={column.id === 'actions'}
|
||||
>
|
||||
{column.header}
|
||||
</TableHead>
|
||||
@ -402,7 +403,11 @@ const TeamList: React.FC = () => {
|
||||
cellContent = '';
|
||||
}
|
||||
return (
|
||||
<TableCell key={column.accessorKey || column.id}>
|
||||
<TableCell
|
||||
key={column.accessorKey || column.id}
|
||||
width={column.size ? `${column.size}px` : undefined}
|
||||
sticky={column.id === 'actions'}
|
||||
>
|
||||
{cellContent}
|
||||
</TableCell>
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user