deploy-ease-platform/frontend/src/hooks/useTableData.ts
2024-12-03 00:29:08 +08:00

202 lines
4.9 KiB
TypeScript

import { useState, useCallback, useEffect } from 'react';
import { message, Modal } from 'antd';
import type { Page } from '@/types/base/page';
import type { TablePaginationConfig } from 'antd/es/table';
import type { FilterValue, SorterResult } from 'antd/es/table/interface';
// 表格服务接口
export interface TableService<T, Q = any, C = Partial<T>, U = Partial<T>> {
list: (params: Q & { pageNum?: number; pageSize?: number }) => Promise<Page<T>>;
create?: (data: C) => Promise<T>;
update?: (id: number, data: U) => Promise<T>;
delete?: (id: number) => Promise<void>;
}
// 表格状态
interface TableState<T> {
list: T[];
pagination: TablePaginationConfig;
loading: boolean;
selectedRowKeys?: React.Key[];
selectedRows?: T[];
}
// 表格配置
interface TableConfig {
defaultPageSize?: number;
selection?: boolean;
message?: {
createSuccess?: string;
updateSuccess?: string;
deleteSuccess?: string;
};
}
export function useTableData<
T extends { id: number },
Q extends Record<string, any> = any,
C = any,
U = any
>({
service,
defaultParams,
config = {}
}: {
service: TableService<T, Q, C, U>;
defaultParams?: Partial<Q>;
config?: TableConfig;
}) {
// 初始化状态
const [state, setState] = useState<TableState<T>>({
list: [],
pagination: {
current: 1,
pageSize: config.defaultPageSize || 10,
total: 0,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total) => `${total}`
},
loading: false
});
// 加载数据
const loadData = useCallback(async (params?: Partial<Q>) => {
setState(prev => ({ ...prev, loading: true }));
try {
const pageData = await service.list({
...defaultParams,
...params,
pageNum: state.pagination.current,
pageSize: state.pagination.pageSize
});
setState(prev => ({
...prev,
list: pageData.content || [],
pagination: {
...prev.pagination,
total: pageData.totalElements || 0
},
loading: false
}));
} catch (error) {
setState(prev => ({ ...prev, loading: false }));
throw error;
}
}, [service, defaultParams, state.pagination]);
// 表格变化处理
const handleTableChange = (
pagination: TablePaginationConfig,
filters: Record<string, FilterValue | null>,
sorter: SorterResult<T> | SorterResult<T>[]
) => {
const { current, pageSize } = pagination;
setState(prev => ({
...prev,
pagination: {
...prev.pagination,
current,
pageSize
}
}));
const params: Record<string, any> = {};
// 处理排序
if (!Array.isArray(sorter)) {
const { field, order } = sorter;
if (field && order) {
params.sortField = field as string;
params.sortOrder = order === 'ascend' ? 'asc' : 'desc';
}
}
// 处理筛选
Object.entries(filters).forEach(([key, value]) => {
if (value) {
params[key] = value;
}
});
loadData(params as Partial<Q>);
};
// 创建
const handleCreate = async (data: C) => {
if (!service.create) return false;
try {
await service.create(data);
message.success(config.message?.createSuccess || '创建成功');
loadData();
return true;
} catch (error) {
throw error;
}
};
// 更新
const handleUpdate = async (id: number, data: U) => {
if (!service.update) return false;
try {
await service.update(id, data);
message.success(config.message?.updateSuccess || '更新成功');
loadData();
return true;
} catch (error) {
throw error;
}
};
// 删除
const handleDelete = async (id: number) => {
if (!service.delete) return false;
return new Promise<boolean>((resolve, reject) => {
Modal.confirm({
title: '确认删除',
content: '确定要删除该记录吗?',
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk: async () => {
try {
await service.delete(id);
message.success(config.message?.deleteSuccess || '删除成功');
loadData();
resolve(true);
} catch (error) {
reject(error);
}
},
onCancel: () => resolve(false)
});
});
};
// 选择行
const handleSelectChange = (selectedRowKeys: React.Key[], selectedRows: T[]) => {
if (!config.selection) return;
setState(prev => ({
...prev,
selectedRowKeys,
selectedRows
}));
};
// 监听分页变化自动加载数据
useEffect(() => {
loadData();
}, [state.pagination.current, state.pagination.pageSize]);
return {
...state,
loadData,
handleTableChange,
handleCreate,
handleUpdate,
handleDelete,
handleSelectChange,
refresh: () => loadData()
};
}