UNPKG

@_lan/web-libs

Version:

<div align="center"> <img src="./public/favicon.svg" width="160" /> <h1>SoybeanAdmin AntDesign</h1> <span>中文 | <a href="./README.en_US.md">English</a></span> </div>

264 lines (220 loc) 6.33 kB
import { computed, effectScope, onScopeDispose, reactive, ref, shallowRef, toValue, watch } from 'vue'; import type { MaybeRef, Ref } from 'vue'; import { useElementSize } from '@vueuse/core'; import type { TablePaginationConfig } from 'ant-design-vue'; import type { TableRowSelection } from 'ant-design-vue/es/table/interface'; import { useBoolean, useHookTable } from '@sa/hooks'; import { jsonClone } from '@sa/utils'; import { useAppStore } from '@/store/modules/app'; import { $t } from '@/locales'; type TableData = AntDesign.TableData; type GetTableData<A extends AntDesign.TableApiFn> = AntDesign.GetTableData<A>; type TableColumn<T> = AntDesign.TableColumn<T>; export function useTable<A extends AntDesign.TableApiFn>(config: AntDesign.AntDesignTableConfig<A>) { const scope = effectScope(); const appStore = useAppStore(); const { apiFn, apiParams, immediate } = config; const { loading, empty, data, columns, columnChecks, reloadColumns, getData, searchParams, updateSearchParams, resetSearchParams } = useHookTable<A, GetTableData<A>, TableColumn<AntDesign.TableDataWithIndex<GetTableData<A>>>>({ apiFn, apiParams, columns: config.columns, transformer: res => { const { records = [], current = 1, size = 10, total = 0 } = res.data || {}; // Ensure that the size is greater than 0, If it is less than 0, it will cause paging calculation errors. const pageSize = size <= 0 ? 10 : size; const recordsWithIndex = records.map((item, index) => { return { ...item, index: (current - 1) * pageSize + index + 1 }; }); return { data: recordsWithIndex, pageNum: current, pageSize, total }; }, getColumnChecks: cols => { const checks: AntDesign.TableColumnCheck[] = []; cols.forEach(column => { if (column.key) { checks.push({ key: column.key as string, title: column.title as string, checked: true }); } }); return checks; }, getColumns: (cols, checks) => { const columnMap = new Map<string, TableColumn<GetTableData<A>>>(); cols.forEach(column => { if (column.key) { columnMap.set(column.key as string, column); } }); const filteredColumns = checks .filter(item => item.checked) .map(check => columnMap.get(check.key) as TableColumn<GetTableData<A>>); return filteredColumns; }, onFetched: async transformed => { const { pageNum, pageSize, total } = transformed; updatePagination({ current: pageNum, pageSize, total }); }, immediate }); const pagination: TablePaginationConfig = reactive({ current: 1, pageSize: 10, showSizeChanger: true, pageSizeOptions: ['10', '15', '20', '25', '30'], total: 0, onChange: async (current: number, size: number) => { pagination.current = current; updateSearchParams({ current, size }); 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); } /** * get data by page number * * @param pageNum the page number. default is 1 */ async function getDataByPage(pageNum: number = 1) { updatePagination({ current: pageNum }); updateSearchParams({ current: pageNum, size: pagination.pageSize! }); await getData(); } scope.run(() => { watch( () => appStore.locale, () => { reloadColumns(); } ); }); onScopeDispose(() => { scope.stop(); }); return { loading, empty, data, columns, columnChecks, reloadColumns, pagination, mobilePagination, updatePagination, getData, getDataByPage, searchParams, updateSearchParams, resetSearchParams }; } export function useTableOperate<T extends TableData = TableData>(data: Ref<T[]>, getData: () => Promise<void>) { const { bool: drawerVisible, setTrue: openDrawer, setFalse: closeDrawer } = useBoolean(); const operateType = ref<AntDesign.TableOperateType>('add'); function handleAdd() { operateType.value = 'add'; openDrawer(); } /** the editing row data */ const editingData: Ref<T | null> = ref(null); function handleEdit(id: T['id']) { operateType.value = 'edit'; const findItem = data.value.find(item => item.id === id) || null; editingData.value = jsonClone(findItem); openDrawer(); } /** the checked row keys of table */ const checkedRowKeys: Ref<T['id'][]> = ref([]); function onSelectChange(keys: (string | number)[]) { checkedRowKeys.value = keys as T['id'][]; } const rowSelection = computed<TableRowSelection<T>>(() => { return { columnWidth: 48, type: 'checkbox', selectedRowKeys: checkedRowKeys.value, onChange: onSelectChange }; }); /** the hook after the batch delete operation is completed */ async function onBatchDeleted() { window.$message?.success($t('common.deleteSuccess')); checkedRowKeys.value = []; await getData(); } /** the hook after the delete operation is completed */ async function onDeleted() { window.$message?.success($t('common.deleteSuccess')); await getData(); } return { drawerVisible, openDrawer, closeDrawer, operateType, handleAdd, editingData, handleEdit, checkedRowKeys, onSelectChange, rowSelection, onBatchDeleted, onDeleted }; } export function useTableScroll(scrollX: MaybeRef<number> = 702) { const tableWrapperRef = shallowRef<HTMLElement | null>(null); const { height: wrapperElHeight } = useElementSize(tableWrapperRef); const scrollConfig = computed(() => { return { y: wrapperElHeight.value - 72, x: toValue(scrollX) }; }); return { tableWrapperRef, scrollConfig }; }