Files
accounts-manager-web/lib/hooks/use-accounts.ts
cloud370 700f252454 fix: 修复handleBatchUpdate函数类型定义不匹配问题
- 更新UseAccountsReturn接口中handleBatchUpdate的类型签名,添加可选的targetIds参数
- 更新BatchOperationsProps接口中onBatchUpdate的类型定义以匹配实际函数签名
- 修复response.data可能为null的TypeScript严格检查错误

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 08:57:45 +08:00

265 lines
7.4 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.

import { useState, useEffect } from 'react';
import {
Account,
ListAccountsBody,
ListAccountsResponse,
StatsOverview,
BusinessCode,
BatchUpdateBody,
BatchDeleteBody,
ScriptUploadItem
} from '@/lib/types';
import { apiClient } from '@/lib/api';
import { toast } from 'sonner';
export interface UseAccountsReturn {
// 数据状态
accounts: Account[];
stats: StatsOverview | null;
loading: boolean;
selectedIds: number[];
// 分页和筛选
pagination: {
page: number;
pageSize: number;
total: number;
totalPages: number;
};
filters: {
platform: string;
status: string[];
ownerId: string;
search: string;
};
sort: {
field: keyof Account;
order: 'asc' | 'desc';
};
// 操作方法
fetchAccounts: () => Promise<void>;
fetchStats: () => Promise<void>;
handleFilterChange: (key: string, value: any) => void;
handlePageChange: (page: number) => void;
handlePageSizeChange: (pageSize: number) => void;
handleSortChange: (field: keyof Account, order: 'asc' | 'desc') => void;
handleSelectAll: (checked: boolean) => void;
handleSelectOne: (id: number, checked: boolean) => void;
handleBatchDelete: () => Promise<void>;
handleBatchUpdate: (payload: Partial<Pick<Account, 'status' | 'ownerId' | 'notes' | 'platform'>>, targetIds?: number[]) => Promise<void>;
handleUploadAccounts: (accounts: ScriptUploadItem[], ownerId: string) => Promise<void>;
setSelectedIds: (ids: number[]) => void;
}
export function useAccounts(): UseAccountsReturn {
const [accounts, setAccounts] = useState<Account[]>([]);
const [stats, setStats] = useState<StatsOverview | null>(null);
const [loading, setLoading] = useState(false);
const [selectedIds, setSelectedIds] = useState<number[]>([]);
const [pagination, setPagination] = useState({
page: 1,
pageSize: 20,
total: 0,
totalPages: 0
});
const [filters, setFilters] = useState({
platform: '',
status: [] as string[],
ownerId: '',
search: ''
});
const [sort, setSort] = useState({
field: 'id' as keyof Account,
order: 'desc' as 'asc' | 'desc'
});
// 获取统计数据
const fetchStats = async () => {
try {
const response = await apiClient.getStatsOverview();
if (response.code === BusinessCode.Success && response.data) {
setStats(response.data);
}
} catch (error) {
console.error('Failed to fetch stats:', error);
toast.error('获取统计数据失败');
}
};
// 获取账户列表
const fetchAccounts = async () => {
setLoading(true);
try {
const body: ListAccountsBody = {
filters,
pagination: {
page: pagination.page,
pageSize: pagination.pageSize
},
sort
};
const response = await apiClient.getAccountsList(body);
if (response.code === BusinessCode.Success && response.data) {
setAccounts(response.data.list);
setPagination(prev => ({
...prev,
total: response.data!.pagination.total,
totalPages: response.data!.pagination.totalPages
}));
}
} catch (error) {
console.error('Failed to fetch accounts:', error);
toast.error('获取账户列表失败');
} finally {
setLoading(false);
}
};
// 处理筛选变化
const handleFilterChange = (key: string, value: any) => {
setFilters({ ...filters, [key]: value });
setPagination({ ...pagination, page: 1 });
};
// 处理分页
const handlePageChange = (page: number) => {
setPagination({ ...pagination, page });
};
// 处理每页大小变化
const handlePageSizeChange = (pageSize: number) => {
setPagination({ ...pagination, pageSize, page: 1 });
};
// 处理排序
const handleSortChange = (field: keyof Account, order: 'asc' | 'desc') => {
setSort({ field, order });
};
// 处理全选
const handleSelectAll = (checked: boolean) => {
if (checked) {
setSelectedIds(accounts.map(account => account.id));
} else {
setSelectedIds([]);
}
};
// 处理单选
const handleSelectOne = (id: number, checked: boolean) => {
if (checked) {
setSelectedIds([...selectedIds, id]);
} else {
setSelectedIds(selectedIds.filter(selectedId => selectedId !== id));
}
};
// 批量删除
const handleBatchDelete = async () => {
if (selectedIds.length === 0) return;
if (!confirm(`确认删除 ${selectedIds.length} 个账户?`)) return;
try {
const response = await apiClient.batchDeleteAccounts({ ids: selectedIds });
if (response.code === BusinessCode.Success) {
setSelectedIds([]);
await fetchAccounts();
await fetchStats();
toast.success(`成功删除 ${response.data?.deletedCount || 0} 个账户`);
}
} catch (error) {
console.error('Failed to delete accounts:', error);
toast.error('删除失败,请检查网络连接后重试');
}
};
// 批量更新
const handleBatchUpdate = async (payload: Partial<Pick<Account, 'status' | 'ownerId' | 'notes' | 'platform'>>, targetIds?: number[]) => {
const idsToUpdate = targetIds || selectedIds;
console.log('handleBatchUpdate 被调用, idsToUpdate:', idsToUpdate);
console.log('payload:', payload);
if (idsToUpdate.length === 0) {
console.log('idsToUpdate为空直接返回');
return;
}
if (Object.keys(payload).length === 0) {
toast.warning('请至少选择一个字段进行更新');
return;
}
try {
console.log('发送批量更新请求...');
const response = await apiClient.batchUpdateAccounts({ ids: idsToUpdate, payload });
console.log('批量更新响应:', response);
if (response.code === BusinessCode.Success) {
if (!targetIds) {
// 只有在没有指定目标ID时才清空选中状态批量操作时
setSelectedIds([]);
}
await fetchAccounts();
await fetchStats();
toast.success(`成功更新 ${response.data?.updatedCount || 0} 个账户`);
}
} catch (error) {
console.error('Failed to update accounts:', error);
toast.error('更新失败,请检查网络连接后重试');
}
};
// 上传账户
const handleUploadAccounts = async (uploadAccounts: ScriptUploadItem[], ownerId: string) => {
try {
const response = await apiClient.uploadAccounts(uploadAccounts, ownerId);
if (response.code === BusinessCode.Success) {
await fetchAccounts();
await fetchStats();
toast.success(`成功处理 ${response.data?.processedCount || 0} 个账户 (${response.data?.createdCount || 0} 个新建, ${response.data?.updatedCount || 0} 个更新)`);
return;
}
} catch (error) {
console.error('Failed to upload accounts:', error);
toast.error('上传失败,请检查网络连接后重试');
}
};
// 初始化数据
useEffect(() => {
fetchAccounts();
}, [filters, pagination.page, pagination.pageSize, sort]);
// 只在开始时获取统计数据
useEffect(() => {
fetchStats();
}, []);
return {
accounts,
stats,
loading,
selectedIds,
pagination,
filters,
sort,
fetchAccounts,
fetchStats,
handleFilterChange,
handlePageChange,
handlePageSizeChange,
handleSortChange,
handleSelectAll,
handleSelectOne,
handleBatchDelete,
handleBatchUpdate,
handleUploadAccounts,
setSelectedIds
};
}