Initial project setup with Next.js accounts manager

- Set up Next.js project structure
- Added UI components and styling
- Configured package dependencies
- Added feature documentation

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Your Name
2025-09-23 01:40:14 +08:00
parent 75900a7dcf
commit 0b95ca36f1
37 changed files with 4004 additions and 115 deletions

View File

@@ -0,0 +1,181 @@
"use client";
import { useState } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Account } from '@/lib/types';
import { useAccounts } from '@/lib/hooks/use-accounts';
// 组件导入
import { StatsCards } from './accounts/stats-cards';
import { AccountFilters } from './accounts/account-filters';
import { BatchOperations } from './accounts/batch-operations';
import { AccountUpload } from './accounts/account-upload';
import { AccountTable } from './accounts/account-table';
import { AccountDetails } from './accounts/account-details';
export function AccountsManager() {
const {
accounts,
stats,
loading,
selectedIds,
pagination,
filters,
fetchAccounts,
fetchStats,
handleFilterChange,
handlePageChange,
handlePageSizeChange,
handleSelectAll,
handleSelectOne,
handleBatchDelete,
handleBatchUpdate,
handleUploadAccounts,
setSelectedIds
} = useAccounts();
// 账户详情状态
const [detailsDialog, setDetailsDialog] = useState(false);
const [detailsMode, setDetailsMode] = useState<'view' | 'edit'>('view');
const [selectedAccount, setSelectedAccount] = useState<Account | null>(null);
// 处理查看详情
const handleViewAccount = (account: Account) => {
setSelectedAccount(account);
setDetailsMode('view');
setDetailsDialog(true);
};
// 处理编辑账户
const handleEditAccount = (account: Account) => {
setSelectedAccount(account);
setDetailsMode('edit');
setDetailsDialog(true);
};
// 处理删除单个账户
const handleDeleteAccount = async (account: Account) => {
if (!confirm('确认删除此账户?')) return;
try {
// 设置选中的账户ID
setSelectedIds([account.id]);
// 执行删除
await handleBatchDelete();
} catch (error) {
console.error('Failed to delete account:', error);
}
};
// 处理保存编辑
const handleSaveAccount = async (account: Account) => {
try {
console.log('开始保存账户:', account);
// 构建payload将null/undefined转换为空字符串
const payload: Partial<Pick<Account, 'status' | 'ownerId' | 'notes' | 'platform'>> = {};
if (account.status !== null && account.status !== undefined) {
payload.status = account.status;
}
if (account.ownerId !== null && account.ownerId !== undefined) {
payload.ownerId = account.ownerId;
}
if (account.notes !== null && account.notes !== undefined) {
payload.notes = account.notes || ''; // 将null转换为空字符串
}
if (account.platform !== null && account.platform !== undefined) {
payload.platform = account.platform;
}
console.log('更新payload:', payload);
console.log('账户ID:', account.id);
if (Object.keys(payload).length === 0) {
console.log('没有有效的字段需要更新');
return;
}
// 直接传递账户ID数组避免状态竞态条件
await handleBatchUpdate(payload, [account.id]);
console.log('账户保存完成');
} catch (error) {
console.error('Failed to save account:', error);
}
};
return (
<div className="flex flex-col">
<div className="container mx-auto p-6 flex flex-col">
{/* 页面标题 */}
<div className="flex justify-between items-center mb-6">
<div>
<h1 className="text-3xl font-bold tracking-tight"></h1>
<p className="text-muted-foreground"></p>
</div>
<AccountUpload onUpload={handleUploadAccounts} stats={stats} />
</div>
{/* 统计卡片 */}
<div className="mb-6">
<StatsCards stats={stats} loading={loading} />
</div>
{/* 账户管理区域 */}
<Card className="flex flex-col">
<CardHeader className="pb-4">
<CardTitle></CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent className="flex flex-col space-y-4">
{/* 筛选条件 */}
<AccountFilters
filters={filters}
stats={stats}
onFilterChange={handleFilterChange}
/>
{/* 批量操作 */}
<BatchOperations
selectedCount={selectedIds.length}
selectedAccounts={accounts.filter(account => selectedIds.includes(account.id))}
stats={stats}
onBatchUpdate={handleBatchUpdate}
onBatchDelete={handleBatchDelete}
/>
{/* 账户表格 - 移除高度限制 */}
<div className="">
<AccountTable
accounts={accounts}
loading={loading}
selectedIds={selectedIds}
pagination={pagination}
onSelectAll={handleSelectAll}
onSelectOne={handleSelectOne}
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
onRefresh={fetchAccounts}
onView={handleViewAccount}
onEdit={handleEditAccount}
onDelete={handleDeleteAccount}
/>
</div>
</CardContent>
</Card>
</div>
{/* 账户详情对话框 */}
<AccountDetails
account={selectedAccount}
open={detailsDialog}
mode={detailsMode}
stats={stats}
onOpenChange={setDetailsDialog}
onSave={handleSaveAccount}
onDelete={handleDeleteAccount}
/>
</div>
);
}