This commit is contained in:
2025-12-16 20:20:53 +07:00
commit 2e651f1c89
315 changed files with 33529 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue';
import type { DataTableColumns, PaginationProps } from 'naive-ui';
const props = defineProps<{
fetchData: (pagination: PaginationProps) => Promise<{ data: any[]; itemCount: number }>;
columns: DataTableColumns;
pagination: PaginationProps;
}>();
const data = ref<any[]>([]);
const headerColumns = computed(() => {
return props.columns
.filter(col => {
return !col.fixed;
})
.map(col => {
return {
key: col.key,
title: col.title,
checked: true,
visible: true
};
});
});
async function loadData() {
const result = await props.fetchData(props.pagination);
data.value = result.data;
props.pagination!.itemCount = result.itemCount;
}
onMounted(() => {
loadData();
});
</script>
<template>
<div class="space-y-5">
<TableHeaderOperation :columns="headerColumns" />
<NDataTable :columns="columns" :data="data!" :pagination="pagination" :bordered="false" />
</div>
</template>
<style lang="css" scoped></style>

View File

@@ -0,0 +1,43 @@
<script setup lang="ts" generic="T extends Record<string, unknown>, K = never">
import { VueDraggable } from 'vue-draggable-plus';
import { $t } from '@/locales';
defineOptions({
name: 'TableColumnSetting'
});
const columns = defineModel<NaiveUI.TableColumnCheck[]>('columns', {
required: true
});
</script>
<template>
<NPopover placement="bottom-end" trigger="click">
<template #trigger>
<NButton size="small">
<template #icon>
<icon-ant-design-setting-outlined class="text-icon" />
</template>
{{ $t('common.columnSetting') }}
</NButton>
</template>
<VueDraggable v-model="columns" :animation="150" filter=".none_draggable">
<div
v-for="item in columns"
:key="item.key"
class="h-36px flex-y-center rd-4px hover:(bg-primary bg-opacity-20)"
:class="{ hidden: !item.visible }"
>
<icon-mdi-drag class="mr-8px h-full cursor-move text-icon" />
<NCheckbox v-model:checked="item.checked" class="none_draggable flex-1">
<template v-if="typeof item.title === 'function'">
<component :is="item.title" />
</template>
<template v-else>{{ item.title }}</template>
</NCheckbox>
</div>
</VueDraggable>
</NPopover>
</template>
<style scoped></style>

View File

@@ -0,0 +1,74 @@
<script setup lang="ts">
import { $t } from '@/locales';
defineOptions({
name: 'TableHeaderOperation'
});
interface Props {
itemAlign?: NaiveUI.Align;
disabledDelete?: boolean;
loading?: boolean;
}
defineProps<Props>();
interface Emits {
(e: 'add'): void;
(e: 'delete'): void;
(e: 'refresh'): void;
}
const emit = defineEmits<Emits>();
const columns = defineModel<NaiveUI.TableColumnCheck[]>('columns', {
default: () => []
});
function add() {
emit('add');
}
function batchDelete() {
emit('delete');
}
function refresh() {
emit('refresh');
}
</script>
<template>
<NSpace :align="itemAlign" wrap justify="end" class="lt-sm:w-200px">
<slot name="prefix"></slot>
<slot name="default">
<NButton size="small" ghost type="primary" @click="add">
<template #icon>
<icon-ic-round-plus class="text-icon" />
</template>
{{ $t('common.add') }}
</NButton>
<NPopconfirm @positive-click="batchDelete">
<template #trigger>
<NButton size="small" ghost type="error" :disabled="disabledDelete">
<template #icon>
<icon-ic-round-delete class="text-icon" />
</template>
{{ $t('common.batchDelete') }}
</NButton>
</template>
{{ $t('common.confirmDelete') }}
</NPopconfirm>
</slot>
<NButton size="small" @click="refresh">
<template #icon>
<icon-mdi-refresh class="text-icon" :class="{ 'animate-spin': loading }" />
</template>
{{ $t('common.refresh') }}
</NButton>
<TableColumnSetting v-model:columns="columns" />
<slot name="suffix"></slot>
</NSpace>
</template>
<style scoped></style>