56 lines
1.8 KiB
TypeScript
56 lines
1.8 KiB
TypeScript
import { ReactNode } from 'react'
|
|
|
|
export interface Column {
|
|
key: string
|
|
title: string
|
|
width?: string
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
render?: (record: any, index: number) => ReactNode
|
|
}
|
|
|
|
interface TableProps {
|
|
columns: Column[]
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
data: any[]
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
rowKey: (record: any) => string
|
|
}
|
|
|
|
export default function Table({ columns, data, rowKey }: TableProps) {
|
|
return (
|
|
<div className="overflow-x-auto rounded-xl border border-slate-200 dark:border-slate-700">
|
|
<table className="w-full text-sm">
|
|
<thead className="bg-slate-50 dark:bg-slate-800">
|
|
<tr>
|
|
{columns.map((col) => (
|
|
<th
|
|
key={col.key}
|
|
className="px-4 py-3 text-left font-medium text-slate-600 dark:text-slate-300"
|
|
style={col.width ? { width: col.width } : undefined}
|
|
>
|
|
{col.title}
|
|
</th>
|
|
))}
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-slate-200 dark:divide-slate-700">
|
|
{data.map((record, index) => (
|
|
<tr key={rowKey(record)} className="hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors">
|
|
{columns.map((col) => (
|
|
<td key={col.key} className="px-4 py-3">
|
|
{col.render ? col.render(record, index) : String(record[col.key] ?? '')}
|
|
</td>
|
|
))}
|
|
</tr>
|
|
))}
|
|
{data.length === 0 && (
|
|
<tr>
|
|
<td colSpan={columns.length} className="px-4 py-12 text-center text-slate-500">暂无数据</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)
|
|
}
|