Files
financial-admin/src/components/table/table-base.vue

124 lines
3.2 KiB
Vue

<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import type { DataTableColumns, PaginationProps } from 'naive-ui';
import { useI18n } from 'vue-i18n';
import {
type TableBaseColumns,
type TableFetchData,
type TableFilterColumns,
transformColumns,
transformHeaderColumns
} from '.';
import type { TableColumnCheck } from '~/packages/hooks/src';
const route = useRoute();
const { t } = useI18n();
const title = t(route.meta.i18nKey as string);
const props = withDefaults(
defineProps<{
fetchData: TableFetchData;
columns: TableBaseColumns;
showHeaderOperation?: boolean;
filterColumns?: TableFilterColumns;
}>(),
{
filterColumns: () => []
}
);
const emit = defineEmits<{
(e: 'add'): void;
(e: 'delete'): void;
}>();
const tableData = ref<any[]>([]);
const dataTableColumns = ref<DataTableColumns>(transformColumns(props.columns));
const headerTableColumns = ref<NaiveUI.TableColumnCheck[]>(transformHeaderColumns(props.columns));
const pagination = ref<PaginationProps>({
page: 1,
pageSize: 10,
itemCount: 0,
showSizePicker: true,
pageSizes: [10, 20, 50, 100]
});
async function loadData(query?: Record<string, any>) {
const page = pagination.value.page || 1;
const pageSize = pagination.value.pageSize || 10;
const { data } = await props.fetchData({
pagination: {
pageIndex: page,
pageSize
},
filter: query
});
tableData.value = (data.value as any).data;
pagination.value.itemCount = (data.value as any).pagination.total;
}
function handlePageChange(curPage: number) {
pagination.value.page = curPage;
loadData();
}
function handlePageSizeChange(curPageSize: number) {
pagination.value.pageSize = curPageSize;
loadData();
}
function handleSearch(form: Record<string, any>) {
pagination.value.page = 1;
loadData(form);
}
function handleUpdateColumns(columns: TableColumnCheck[]) {
headerTableColumns.value = columns;
const sortKeys = columns.map(col => col.key);
const currentColumns: DataTableColumns = [...dataTableColumns.value];
const sortedColumns = sortKeys.map(key => currentColumns.find(col => (col as any).key === key)).filter(Boolean);
dataTableColumns.value = sortedColumns as DataTableColumns;
}
onMounted(() => {
loadData();
});
defineExpose({
reload: loadData
});
</script>
<template>
<div class="space-y-5">
<TableFilter v-if="filterColumns.length > 0" :columns="filterColumns" @confirm="handleSearch" />
<div class="rounded-lg bg-white p-5 space-y-5">
<TableHeaderOperation
v-if="showHeaderOperation"
:columns="headerTableColumns"
@update:columns="handleUpdateColumns"
@add="emit('add')"
@refresh="loadData()"
@delete="emit('delete')"
>
<template #prefix>
<div class="text-lg font-bold">{{ title }}</div>
</template>
</TableHeaderOperation>
<NDataTable
:scroll-x="2000"
:columns="dataTableColumns"
:data="tableData"
:pagination="pagination"
:bordered="false"
:on-update:page="handlePageChange"
:on-update:page-size="handlePageSizeChange"
/>
</div>
</div>
</template>
<style lang="css" scoped></style>