124 lines
3.2 KiB
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>
|