2
0
Files
fe.wfc/src/hooks/common/table.ts
2024-12-13 19:14:32 +08:00

200 lines
4.4 KiB
TypeScript

import { computed, effectScope, onScopeDispose, reactive, ref, watch } from 'vue';
import type { Ref } from 'vue';
import type { TablePaginationConfig } from 'ant-design-vue';
import { useBoolean, useHookTable } from '@sa/hooks';
import { useAppStore } from '@/store/modules/app';
import { $t } from '@/locales';
type TableData<T = object> = AntDesign.TableData<T>;
export function useTable(config: any) {
const scope = effectScope();
const appStore = useAppStore();
const { apiFn, apiParams, immediate, rowKey } = config;
const {
loading,
empty,
data,
columns,
columnChecks,
reloadColumns,
getData,
searchParams,
updateSearchParams,
resetSearchParams
} = useHookTable({
apiFn,
apiParams,
columns: config.columns,
transformer: (res:any) => {
const { rows = [], total = 0 } = res.data || {};
return {
rows: rows.map((row:any, index:any) => ({ ...row, id: rowKey ? row[rowKey] : index })),
total
};
},
getColumnChecks: (cols:any) => {
const checks: AntDesign.TableColumnCheck[] = [];
cols.forEach((column:any) => {
if (column.key) {
checks.push({
key: column.key as string,
title: column.title as string,
checked: true
});
}
});
return checks;
},
getColumns: (cols:any, checks:any) => {
const columnMap = new Map<string, any>();
cols.forEach((column:any) => {
if (column.key) {
columnMap.set(column.key as string, column);
}
});
const filteredColumns = checks
.filter((item:any) => item.checked)
.map((check:any) => columnMap.get(check.key) );
return filteredColumns;
},
onFetched: async (transformed:any) => {
const { total } = transformed;
updatePagination({
total
});
},
immediate
});
const pagination: TablePaginationConfig = reactive({
showSizeChanger: true,
pageSizeOptions: [10, 15, 20, 25, 30],
total: 0,
simple: false,
// size: 'f',
current: 1,
pageSize: 10,
onChange: async (current: number, pageSize: number) => {
pagination.current = current;
updateSearchParams({
pageNum: current,
pageSize
});
getData();
}
});
// this is for mobile, if the system does not support mobile, you can use `pagination` directly
const mobilePagination = computed(() => {
const p: TablePaginationConfig = {
...pagination,
simple: appStore.isMobile
};
return p;
});
function updatePagination(update: Partial<TablePaginationConfig>) {
Object.assign(pagination, update);
}
scope.run(() => {
watch(
() => appStore.locale,
() => {
reloadColumns();
}
);
});
onScopeDispose(() => {
scope.stop();
});
return {
loading,
empty,
data,
columns,
columnChecks,
reloadColumns,
pagination,
mobilePagination,
updatePagination,
getData,
searchParams,
updateSearchParams,
resetSearchParams
};
}
export function useTableOperate<T extends TableData<{ [key: string]: any }>>(
data: Ref<T[]>,
options: {
getData: () => Promise<void>;
idKey?: string;
}
) {
const { bool: drawerVisible, setTrue: openDrawer, setFalse: closeDrawer } = useBoolean();
const operateType = ref<any>('add');
const { getData, idKey = 'id' } = options;
/** the editing row data */
const editingData: Ref<T | null> = ref(null);
function handleAdd() {
operateType.value = 'add';
editingData.value = null;
openDrawer();
}
function handleEdit(id: any) {
operateType.value = 'edit';
editingData.value = data.value.find(item => item[idKey] === id) || null;
openDrawer();
}
/** the checked row keys of table */
const checkedRowKeys = ref<number[]>([]);
/** the hook after the batch delete operation is completed */
async function onBatchDeleted() {
$message?.success($t('common.deleteSuccess'));
checkedRowKeys.value = [];
await getData();
}
/** the hook after the delete operation is completed */
async function onDeleted() {
$message?.success($t('common.deleteSuccess'));
await getData();
}
return {
drawerVisible,
openDrawer,
closeDrawer,
operateType,
handleAdd,
editingData,
handleEdit,
checkedRowKeys,
onBatchDeleted,
onDeleted
};
}