feat: 增强表格交互体验和数据展示

- 新增每页数量localStorage缓存,刷新后保持用户选择
- 增加表格显示高度从600px到800px,显示更多数据
- 支持点击表格行进行选择,提升操作便利性
- 格式化创建时间显示为详细时间(年/月/日 时:分)
- 优化复选框和操作按钮的点击事件冲突

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-24 05:36:37 +08:00
parent 8d02855249
commit 43a828a2c6
2 changed files with 42 additions and 16 deletions

View File

@@ -134,8 +134,8 @@ export function AccountTable({
{/* 分页器 - 移到顶部 */} {/* 分页器 - 移到顶部 */}
{renderPagination()} {renderPagination()}
{/* 表格区域 - 直接使用原生table确保sticky正常工作 */} {/* 表格区域 - 增加高度以显示更多数据 */}
<div className="border rounded-lg max-h-[600px] overflow-auto"> <div className="border rounded-lg max-h-[800px] overflow-auto">
<table className="w-full caption-bottom text-sm"> <table className="w-full caption-bottom text-sm">
<thead className="sticky top-0 bg-background z-20 border-b shadow-sm"> <thead className="sticky top-0 bg-background z-20 border-b shadow-sm">
<tr className="hover:bg-muted/50 border-b transition-colors"> <tr className="hover:bg-muted/50 border-b transition-colors">
@@ -170,8 +170,12 @@ export function AccountTable({
</tr> </tr>
) : ( ) : (
accounts.map((account) => ( accounts.map((account) => (
<tr key={account.id} className="hover:bg-muted/50 border-b transition-colors"> <tr
<td className="p-2 align-middle w-12"> key={account.id}
className="hover:bg-muted/50 border-b transition-colors cursor-pointer"
onClick={() => onSelectOne(account.id, !selectedIds.includes(account.id))}
>
<td className="p-2 align-middle w-12" onClick={(e) => e.stopPropagation()}>
<Checkbox <Checkbox
checked={selectedIds.includes(account.id)} checked={selectedIds.includes(account.id)}
onCheckedChange={(checked) => onSelectOne(account.id, checked as boolean)} onCheckedChange={(checked) => onSelectOne(account.id, checked as boolean)}
@@ -184,9 +188,15 @@ export function AccountTable({
<td className="p-2 align-middle">{getStatusBadge(account.status)}</td> <td className="p-2 align-middle">{getStatusBadge(account.status)}</td>
<td className="p-2 align-middle max-w-[200px] truncate">{account.notes || '-'}</td> <td className="p-2 align-middle max-w-[200px] truncate">{account.notes || '-'}</td>
<td className="p-2 align-middle text-sm text-muted-foreground"> <td className="p-2 align-middle text-sm text-muted-foreground">
{new Date(account.createdAt).toLocaleDateString('zh-CN')} {new Date(account.createdAt).toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
})}
</td> </td>
<td className="p-2 align-middle w-[120px]"> <td className="p-2 align-middle w-[120px]" onClick={(e) => e.stopPropagation()}>
<div className="flex items-center space-x-1"> <div className="flex items-center space-x-1">
{onView && ( {onView && (
<Button <Button

View File

@@ -58,9 +58,24 @@ export function useAccounts(): UseAccountsReturn {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [selectedIds, setSelectedIds] = useState<number[]>([]); const [selectedIds, setSelectedIds] = useState<number[]>([]);
// 从 localStorage 获取缓存的分页大小,默认为 20
const getInitialPageSize = () => {
if (typeof window !== 'undefined') {
const saved = localStorage.getItem('accounts-page-size');
if (saved) {
const pageSize = parseInt(saved, 10);
// 验证是否为有效值
if ([20, 100, 1000, 10000].includes(pageSize)) {
return pageSize;
}
}
}
return 20;
};
const [pagination, setPagination] = useState({ const [pagination, setPagination] = useState({
page: 1, page: 1,
pageSize: 20, pageSize: getInitialPageSize(),
total: 0, total: 0,
totalPages: 0 totalPages: 0
}); });
@@ -92,7 +107,6 @@ export function useAccounts(): UseAccountsReturn {
// 获取账户列表 // 获取账户列表
const fetchAccounts = useCallback(async () => { const fetchAccounts = useCallback(async () => {
console.log('fetchAccounts called with pagination:', pagination);
setLoading(true); setLoading(true);
try { try {
const body: ListAccountsBody = { const body: ListAccountsBody = {
@@ -104,10 +118,8 @@ export function useAccounts(): UseAccountsReturn {
sort sort
}; };
console.log('Sending request with body:', body);
const response = await apiClient.getAccountsList(body); const response = await apiClient.getAccountsList(body);
if (response.code === BusinessCode.Success && response.data) { if (response.code === BusinessCode.Success && response.data) {
console.log('Response received:', response.data.list.length, 'accounts');
setAccounts(response.data.list); setAccounts(response.data.list);
setPagination(prev => ({ setPagination(prev => ({
...prev, ...prev,
@@ -136,12 +148,16 @@ export function useAccounts(): UseAccountsReturn {
// 处理每页大小变化 // 处理每页大小变化
const handlePageSizeChange = (pageSize: number) => { const handlePageSizeChange = (pageSize: number) => {
console.log('handlePageSizeChange called with:', pageSize); // 保存到 localStorage
setPagination(prev => { if (typeof window !== 'undefined') {
const newPagination = { ...prev, pageSize, page: 1 }; localStorage.setItem('accounts-page-size', pageSize.toString());
console.log('Setting new pagination:', newPagination); }
return newPagination;
}); setPagination(prev => ({
...prev,
pageSize,
page: 1
}));
}; };
// 处理排序 // 处理排序