|
|
@ -1,5 +1,6 @@ |
|
|
|
<script setup lang="ts"> |
|
|
|
<script setup lang="ts"> |
|
|
|
import NcTooltip from '~/components/nc/Tooltip.vue' |
|
|
|
import NcTooltip from '~/components/nc/Tooltip.vue' |
|
|
|
|
|
|
|
import { NC_GRID_VIEW_PAGE_SIZE_KEY } from '#imports' |
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{ |
|
|
|
const props = defineProps<{ |
|
|
|
current: number |
|
|
|
current: number |
|
|
@ -11,19 +12,41 @@ const props = defineProps<{ |
|
|
|
nextPageTooltip?: string |
|
|
|
nextPageTooltip?: string |
|
|
|
firstPageTooltip?: string |
|
|
|
firstPageTooltip?: string |
|
|
|
lastPageTooltip?: string |
|
|
|
lastPageTooltip?: string |
|
|
|
|
|
|
|
showSizeChanger?: boolean |
|
|
|
}>() |
|
|
|
}>() |
|
|
|
|
|
|
|
|
|
|
|
const emits = defineEmits(['update:current', 'update:pageSize']) |
|
|
|
const emits = defineEmits(['update:current', 'update:pageSize']) |
|
|
|
|
|
|
|
|
|
|
|
const { total } = toRefs(props) |
|
|
|
const { total, showSizeChanger } = toRefs(props) |
|
|
|
|
|
|
|
|
|
|
|
const current = useVModel(props, 'current', emits) |
|
|
|
const current = useVModel(props, 'current', emits) |
|
|
|
|
|
|
|
|
|
|
|
const pageSize = useVModel(props, 'pageSize', emits) |
|
|
|
const pageSize = useVModel(props, 'pageSize', emits) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const localPageSize = computed({ |
|
|
|
|
|
|
|
get: () => { |
|
|
|
|
|
|
|
if (!showSizeChanger.value) return pageSize.value |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const storedPageSize = !isNaN(parseInt(localStorage.getItem(NC_GRID_VIEW_PAGE_SIZE_KEY) ?? '')) |
|
|
|
|
|
|
|
? parseInt(localStorage.getItem(NC_GRID_VIEW_PAGE_SIZE_KEY) ?? '') |
|
|
|
|
|
|
|
: 25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pageSize.value !== storedPageSize) { |
|
|
|
|
|
|
|
pageSize.value = storedPageSize |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return pageSize.value |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
set: (val) => { |
|
|
|
|
|
|
|
localStorage.setItem(NC_GRID_VIEW_PAGE_SIZE_KEY, `${val}`) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pageSize.value = val |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
const entityName = computed(() => props.entityName || 'item') |
|
|
|
const entityName = computed(() => props.entityName || 'item') |
|
|
|
|
|
|
|
|
|
|
|
const totalPages = computed(() => Math.max(Math.ceil(total.value / pageSize.value), 1)) |
|
|
|
const totalPages = computed(() => Math.max(Math.ceil(total.value / localPageSize.value), 1)) |
|
|
|
|
|
|
|
|
|
|
|
const { isMobileMode } = useGlobal() |
|
|
|
const { isMobileMode } = useGlobal() |
|
|
|
|
|
|
|
|
|
|
@ -53,10 +76,44 @@ const pagesList = computed(() => { |
|
|
|
label: i + 1, |
|
|
|
label: i + 1, |
|
|
|
})) |
|
|
|
})) |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const pageSizeOptions = [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
value: 25, |
|
|
|
|
|
|
|
label: '25 / page', |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
value: 50, |
|
|
|
|
|
|
|
label: '50 / page', |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
value: 75, |
|
|
|
|
|
|
|
label: '75 / page', |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
value: 100, |
|
|
|
|
|
|
|
label: '100 / page', |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const pageListRef = ref() |
|
|
|
|
|
|
|
const pageSizeRef = ref() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const pageListDropdownVisibleChange = (value: boolean) => { |
|
|
|
|
|
|
|
if (!value && pageListRef.value) { |
|
|
|
|
|
|
|
pageListRef.value?.blur() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
const pageSizeDropdownVisibleChange = (value: boolean) => { |
|
|
|
|
|
|
|
if (!value && pageSizeRef.value) { |
|
|
|
|
|
|
|
pageSizeRef.value?.blur() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
</script> |
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
|
|
<template> |
|
|
|
<template> |
|
|
|
<div v-if="totalPages > 1" class="nc-pagination flex flex-row items-center gap-x-2"> |
|
|
|
<div class="nc-pagination flex flex-row items-center gap-x-2"> |
|
|
|
|
|
|
|
<template v-if="totalPages > 1"> |
|
|
|
<component :is="props.firstPageTooltip && mode === 'full' ? NcTooltip : 'div'" v-if="mode === 'full'"> |
|
|
|
<component :is="props.firstPageTooltip && mode === 'full' ? NcTooltip : 'div'" v-if="mode === 'full'"> |
|
|
|
<template v-if="props.firstPageTooltip" #title> |
|
|
|
<template v-if="props.firstPageTooltip" #title> |
|
|
|
{{ props.firstPageTooltip }} |
|
|
|
{{ props.firstPageTooltip }} |
|
|
@ -65,11 +122,11 @@ const pagesList = computed(() => { |
|
|
|
v-e="[`a:pagination:${entityName}:first-page`]" |
|
|
|
v-e="[`a:pagination:${entityName}:first-page`]" |
|
|
|
class="first-page" |
|
|
|
class="first-page" |
|
|
|
type="secondary" |
|
|
|
type="secondary" |
|
|
|
size="small" |
|
|
|
size="xsmall" |
|
|
|
:disabled="current === 1" |
|
|
|
:disabled="current === 1" |
|
|
|
@click="goToFirstPage" |
|
|
|
@click="goToFirstPage" |
|
|
|
> |
|
|
|
> |
|
|
|
<GeneralIcon icon="doubleLeftArrow" /> |
|
|
|
<GeneralIcon icon="doubleLeftArrow" class="nc-pagination-icon" /> |
|
|
|
</NcButton> |
|
|
|
</NcButton> |
|
|
|
</component> |
|
|
|
</component> |
|
|
|
|
|
|
|
|
|
|
@ -81,16 +138,24 @@ const pagesList = computed(() => { |
|
|
|
v-e="[`a:pagination:${entityName}:prev-page`]" |
|
|
|
v-e="[`a:pagination:${entityName}:prev-page`]" |
|
|
|
class="prev-page" |
|
|
|
class="prev-page" |
|
|
|
type="secondary" |
|
|
|
type="secondary" |
|
|
|
size="small" |
|
|
|
size="xsmall" |
|
|
|
:disabled="current === 1" |
|
|
|
:disabled="current === 1" |
|
|
|
@click="changePage({ increase: false })" |
|
|
|
@click="changePage({ increase: false })" |
|
|
|
> |
|
|
|
> |
|
|
|
<GeneralIcon icon="arrowLeft" /> |
|
|
|
<GeneralIcon icon="arrowLeft" class="nc-pagination-icon" /> |
|
|
|
</NcButton> |
|
|
|
</NcButton> |
|
|
|
</component> |
|
|
|
</component> |
|
|
|
|
|
|
|
|
|
|
|
<div v-if="!isMobileMode" class="text-gray-600"> |
|
|
|
<div v-if="!isMobileMode" class="text-gray-500"> |
|
|
|
<a-select v-model:value="current" class="!mr-[2px]" :options="pagesList"> |
|
|
|
<a-select |
|
|
|
|
|
|
|
ref="pageListRef" |
|
|
|
|
|
|
|
v-model:value="current" |
|
|
|
|
|
|
|
class="!mr-[2px]" |
|
|
|
|
|
|
|
:options="pagesList" |
|
|
|
|
|
|
|
size="small" |
|
|
|
|
|
|
|
dropdown-class-name="nc-pagination-dropdown" |
|
|
|
|
|
|
|
@dropdown-visible-change="pageListDropdownVisibleChange" |
|
|
|
|
|
|
|
> |
|
|
|
<template #suffixIcon> |
|
|
|
<template #suffixIcon> |
|
|
|
<GeneralIcon icon="arrowDown" class="text-gray-500 nc-select-expand-btn" /> |
|
|
|
<GeneralIcon icon="arrowDown" class="text-gray-500 nc-select-expand-btn" /> |
|
|
|
</template> |
|
|
|
</template> |
|
|
@ -109,11 +174,11 @@ const pagesList = computed(() => { |
|
|
|
v-e="[`a:pagination:${entityName}:next-page`]" |
|
|
|
v-e="[`a:pagination:${entityName}:next-page`]" |
|
|
|
class="next-page" |
|
|
|
class="next-page" |
|
|
|
type="secondary" |
|
|
|
type="secondary" |
|
|
|
size="small" |
|
|
|
size="xsmall" |
|
|
|
:disabled="current === totalPages" |
|
|
|
:disabled="current === totalPages" |
|
|
|
@click="changePage({ increase: true })" |
|
|
|
@click="changePage({ increase: true })" |
|
|
|
> |
|
|
|
> |
|
|
|
<GeneralIcon icon="arrowRight" /> |
|
|
|
<GeneralIcon icon="arrowRight" class="nc-pagination-icon" /> |
|
|
|
</NcButton> |
|
|
|
</NcButton> |
|
|
|
</component> |
|
|
|
</component> |
|
|
|
|
|
|
|
|
|
|
@ -125,22 +190,50 @@ const pagesList = computed(() => { |
|
|
|
v-e="[`a:pagination:${entityName}:last-page`]" |
|
|
|
v-e="[`a:pagination:${entityName}:last-page`]" |
|
|
|
class="last-page" |
|
|
|
class="last-page" |
|
|
|
type="secondary" |
|
|
|
type="secondary" |
|
|
|
size="small" |
|
|
|
size="xsmall" |
|
|
|
:disabled="current === totalPages" |
|
|
|
:disabled="current === totalPages" |
|
|
|
@click="goToLastPage" |
|
|
|
@click="goToLastPage" |
|
|
|
> |
|
|
|
> |
|
|
|
<GeneralIcon icon="doubleRightArrow" /> |
|
|
|
<GeneralIcon icon="doubleRightArrow" class="nc-pagination-icon" /> |
|
|
|
</NcButton> |
|
|
|
</NcButton> |
|
|
|
</component> |
|
|
|
</component> |
|
|
|
|
|
|
|
</template> |
|
|
|
|
|
|
|
<div v-if="showSizeChanger && !isMobileMode" class="text-gray-500"> |
|
|
|
|
|
|
|
<a-select |
|
|
|
|
|
|
|
ref="pageSizeRef" |
|
|
|
|
|
|
|
v-model:value="localPageSize" |
|
|
|
|
|
|
|
class="!min-w-[110px]" |
|
|
|
|
|
|
|
:options="pageSizeOptions" |
|
|
|
|
|
|
|
size="small" |
|
|
|
|
|
|
|
dropdown-class-name="nc-pagination-dropdown" |
|
|
|
|
|
|
|
@dropdown-visible-change="pageSizeDropdownVisibleChange" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<template #suffixIcon> |
|
|
|
|
|
|
|
<GeneralIcon icon="arrowDown" class="text-gray-500 nc-select-page-size-expand-btn" /> |
|
|
|
|
|
|
|
</template> |
|
|
|
|
|
|
|
</a-select> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped> |
|
|
|
<style lang="scss" scoped> |
|
|
|
:deep(.ant-select-selector) { |
|
|
|
:deep(.ant-select-selector) { |
|
|
|
@apply !border-gray-200 !rounded-lg; |
|
|
|
@apply !border-gray-200 !rounded-lg !h-[25px]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.nc-pagination-icon { |
|
|
|
|
|
|
|
@apply w-4 h-4; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
:deep(.ant-select-dropdown) { |
|
|
|
:deep(.nc-button:not(:disabled)) { |
|
|
|
@apply !rounded-lg !overflow-hidden; |
|
|
|
.nc-pagination-icon { |
|
|
|
|
|
|
|
@apply !text-gray-500; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
</style> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss"> |
|
|
|
|
|
|
|
.nc-pagination-dropdown { |
|
|
|
|
|
|
|
@apply !rounded-lg; |
|
|
|
} |
|
|
|
} |
|
|
|
</style> |
|
|
|
</style> |
|
|
|