feat: 封装表格分页hooks
This commit is contained in:
87
src/hooks/useTableSelectionWithPagination.ts
Normal file
87
src/hooks/useTableSelectionWithPagination.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { ref, computed } from 'vue';
|
||||
|
||||
interface UseTableSelectionWithPaginationOptions {
|
||||
rowKey?: string; // 主键字段名,默认 'id'
|
||||
pageInfo?: {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
total?: number;
|
||||
};
|
||||
onPageChange?: (page: number) => void;
|
||||
onPageSizeChange?: (size: number) => void;
|
||||
}
|
||||
|
||||
const DEFAULT_PAGE_INFO = {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
};
|
||||
|
||||
export function useTableSelectionWithPagination(options: UseTableSelectionWithPaginationOptions = {}) {
|
||||
const rowKey = options.rowKey || 'id';
|
||||
|
||||
const selectedRowKeys = ref<Array<string | number>>([]);
|
||||
const selectedRows = ref<any[]>([]);
|
||||
|
||||
const pageInfo = ref(merge({}, DEFAULT_PAGE_INFO, options.pageInfo));
|
||||
|
||||
const dataSource = ref<any[]>([]);
|
||||
|
||||
// 单行选择
|
||||
const handleSelect = (selectedKeys: (string | number)[], rowKeyValue: string | number, record: any) => {
|
||||
const select = selectedKeys.includes(rowKeyValue);
|
||||
selectedRowKeys.value = selectedKeys;
|
||||
|
||||
if (select) {
|
||||
if (!selectedRows.value.some((v) => v[rowKey] === record[rowKey])) {
|
||||
selectedRows.value.push(record);
|
||||
}
|
||||
} else {
|
||||
selectedRows.value = selectedRows.value.filter((v) => v[rowKey] !== record[rowKey]);
|
||||
}
|
||||
};
|
||||
|
||||
// 全选/取消全选
|
||||
const handleSelectAll = (checked: boolean) => {
|
||||
const currentPageRows = dataSource.value;
|
||||
const currentPageKeys = currentPageRows.map((v) => v[rowKey]);
|
||||
|
||||
if (checked) {
|
||||
selectedRowKeys.value = Array.from(new Set([...selectedRowKeys.value, ...currentPageKeys]));
|
||||
const allRows = [...selectedRows.value, ...currentPageRows];
|
||||
const map = new Map();
|
||||
allRows.forEach((row) => map.set(row[rowKey], row));
|
||||
selectedRows.value = Array.from(map.values());
|
||||
} else {
|
||||
selectedRowKeys.value = selectedRowKeys.value.filter((key) => !currentPageKeys.includes(key));
|
||||
selectedRows.value = selectedRows.value.filter((row) => !currentPageKeys.includes(row[rowKey]));
|
||||
}
|
||||
};
|
||||
|
||||
const onPageChange = (page: number) => {
|
||||
pageInfo.value.page = page;
|
||||
options.onPageChange?.(page);
|
||||
};
|
||||
const onPageSizeChange = (size: number) => {
|
||||
pageInfo.value.page_size = size;
|
||||
pageInfo.value.page = 1;
|
||||
options.onPageSizeChange?.(size);
|
||||
};
|
||||
|
||||
const rowSelection = computed(() => ({
|
||||
type: 'checkbox',
|
||||
showCheckedAll: true,
|
||||
}));
|
||||
|
||||
return {
|
||||
selectedRowKeys,
|
||||
selectedRows,
|
||||
dataSource,
|
||||
pageInfo,
|
||||
onPageChange,
|
||||
onPageSizeChange,
|
||||
rowSelection,
|
||||
handleSelect,
|
||||
handleSelectAll,
|
||||
};
|
||||
}
|
||||
@ -44,16 +44,12 @@
|
||||
ref="tableRef"
|
||||
:data="dataSource"
|
||||
column-resizable
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
showCheckedAll: true,
|
||||
width: 48,
|
||||
}"
|
||||
row-key="account_id"
|
||||
:selected-keys="selectedRowKeys"
|
||||
:row-selection="rowSelection"
|
||||
:row-key="ROW_KEY"
|
||||
:pagination="false"
|
||||
:scroll="{ x: '100%', y: '100%' }"
|
||||
class="w-100% flex-1 overflow-hidden"
|
||||
:selected-keys="selectedRowKeys"
|
||||
bordered
|
||||
@select="handleSelect"
|
||||
@select-all="handleSelectAll"
|
||||
@ -97,7 +93,7 @@
|
||||
show-jumper
|
||||
show-page-size
|
||||
:current="pageInfo.page"
|
||||
:page-size="pageInfo.pageSize"
|
||||
:page-size="pageInfo.page_size"
|
||||
@change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
/>
|
||||
@ -126,6 +122,7 @@
|
||||
import { INITIAL_FORM, INITIAL_PAGE_INFO, TABLE_COLUMNS } from './constants';
|
||||
import { formatTableField } from '@/utils/tools';
|
||||
import { postSubAccount, postAddSubAccount } from '@/api/all/propertyMarketing';
|
||||
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
||||
|
||||
const emits = defineEmits('confirm');
|
||||
const update = inject('update');
|
||||
@ -133,13 +130,29 @@ const closeAddAccountModal = inject('closeAddAccountModal');
|
||||
const closeAuthorizeAccountModal = inject('closeAuthorizeAccountModal');
|
||||
|
||||
const visible = ref(false);
|
||||
const dataSource = ref([]);
|
||||
const query = ref(cloneDeep(INITIAL_FORM));
|
||||
const pageInfo = ref(cloneDeep(INITIAL_PAGE_INFO));
|
||||
const form = ref(null);
|
||||
|
||||
const selectedAccounts = ref([]);
|
||||
const selectedRowKeys = ref([]);
|
||||
const ROW_KEY = 'account_id';
|
||||
const {
|
||||
selectedRowKeys,
|
||||
selectedRows: selectedAccounts,
|
||||
dataSource,
|
||||
pageInfo,
|
||||
onPageChange,
|
||||
onPageSizeChange,
|
||||
rowSelection,
|
||||
handleSelect,
|
||||
handleSelectAll,
|
||||
} = useTableSelectionWithPagination({
|
||||
rowKey: ROW_KEY,
|
||||
onPageChange: () => {
|
||||
getData();
|
||||
},
|
||||
onPageSizeChange: () => {
|
||||
getData();
|
||||
},
|
||||
});
|
||||
|
||||
const open = (formData) => {
|
||||
const { platform, account, password } = formData;
|
||||
@ -152,16 +165,15 @@ const open = (formData) => {
|
||||
};
|
||||
|
||||
getData();
|
||||
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
form.value = null;
|
||||
selectedAccounts.value = [];
|
||||
selectedRowKeys.value = [];
|
||||
query.value = cloneDeep(INITIAL_FORM);
|
||||
pageInfo.value = cloneDeep(INITIAL_PAGE_INFO);
|
||||
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
@ -181,12 +193,6 @@ const getData = async () => {
|
||||
...query.value,
|
||||
page,
|
||||
page_size,
|
||||
// platform: 0,
|
||||
// account: '543366265@qq.com',
|
||||
// password: 'Xiaoti2025@',
|
||||
// // page: 1,
|
||||
// // page_size: 10,
|
||||
// account_id: '',
|
||||
});
|
||||
if (code === 200) {
|
||||
dataSource.value = data?.data ?? [];
|
||||
@ -199,43 +205,6 @@ const reload = () => {
|
||||
getData();
|
||||
};
|
||||
|
||||
const handleSelect = (selectedKeys, rowKey, record) => {
|
||||
const select = selectedKeys.includes(rowKey);
|
||||
selectedRowKeys.value = selectedKeys;
|
||||
|
||||
if (select) {
|
||||
selectedAccounts.value.push(record);
|
||||
} else {
|
||||
selectedAccounts.value = selectedAccounts.value.filter((v) => v.account_id !== record.account_id);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectAll = (checked) => {
|
||||
const currentPageAccounts = dataSource.value;
|
||||
const currentPageKeys = currentPageAccounts.map((v) => v.account_id);
|
||||
|
||||
if (checked) {
|
||||
selectedRowKeys.value = Array.from(new Set([...selectedRowKeys.value, ...currentPageKeys]));
|
||||
|
||||
const allAccounts = [...selectedAccounts.value, ...currentPageAccounts];
|
||||
const map = new Map();
|
||||
allAccounts.forEach((acc) => map.set(acc.account_id, acc));
|
||||
selectedAccounts.value = Array.from(map.values());
|
||||
} else {
|
||||
selectedRowKeys.value = selectedRowKeys.value.filter((key) => !currentPageKeys.includes(key));
|
||||
selectedAccounts.value = selectedAccounts.value.filter((acc) => !currentPageKeys.includes(acc.account_id));
|
||||
}
|
||||
};
|
||||
|
||||
const onPageChange = (current) => {
|
||||
pageInfo.value.page = current;
|
||||
getData();
|
||||
};
|
||||
const onPageSizeChange = (pageSize) => {
|
||||
pageInfo.value.page_size = pageSize;
|
||||
reload();
|
||||
};
|
||||
|
||||
defineExpose({ open });
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user