Skip to content

Commit

Permalink
feat(usePagination): init
Browse files Browse the repository at this point in the history
  • Loading branch information
nemo-shen committed Feb 26, 2024
1 parent b1606b3 commit b2bfa49
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './useProgress'
export * from './useCalendar'
export * from './useCountdown'
export * from './useUpload'
export * from './usePagination'
127 changes: 124 additions & 3 deletions packages/core/usePagination/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,130 @@
interface UsePaginationOption {
import { ref, computed, type ComputedRef, type Ref } from 'vue'

interface PageItem {
value: number
isCurrent: boolean
type: 'page' | 'ellipsis'
}

interface usePaginationReturn {
interface UsePaginationOption {
total: number
pageSize?: number
currentPage?: number
maxPageCount?: number
ellipsis?: boolean
}

interface UsePaginationReturn {
currentPage: Ref<number>
isFirstPage: ComputedRef<boolean>
isLastPage: ComputedRef<boolean>
pages: ComputedRef<Page[]>
totalPage: ComputedRef<number>
gotoPage: (page: number) => void
nextPage: () => void
previousPage: () => void
setPageSize: (pageSize: number) => void
gotoFirstPage: () => void
gotoLastPage: () => void
}

export const usePagination = (options: UsePaginationOption): usePaginationReturn => { }
export const usePagination = (
options: UsePaginationOption
): UsePaginationReturn => {
const { total, ellipsis = false } = options

const currentPage = ref(options.currentPage || 1)
const pageSize = ref(options.pageSize || 10)
const isFirstPage = computed(() => currentPage.value === 1)
const totalPage = computed(() => Math.ceil(total / pageSize.value))
const maxPageCount =
(options.maxPageCount || 5) > totalPage.value
? totalPage.value
: options.maxPageCount || 5
const isLastPage = computed(() => currentPage.value === totalPage.value)
const pages = computed(() =>
Array.from({ length: maxPageCount }, (_, index) => {
if (!ellipsis) {
return {
text: index + 1,
value: index + 1,
isCurrent: index + 1 === currentPage.value,
type: 'page',
}
}
if (maxPageCount % 2 === 0) {
if (
index + 1 <= maxPageCount / 2 ||
totalPage.value - (index + 1) < maxPageCount / 2
) {
return {
text: index + 1,
value: index + 1,
isCurrent: index + 1 === currentPage.value,
type: 'page',
}
}
return {
text: '...',
value: 0,
isCurrent: false,
type: 'ellipsis',
}
}
if (Math.floor(maxPageCount / 2) + 1 === index + 1) {
return {
text: '...',
value: 0,
isCurrent: false,
type: 'ellipsis',
}
}
return {
text: index + 1,
value: index + 1,
isCurrent: index + 1 === currentPage.value,
type: 'page',
}
})
)

const gotoPage = (page: number) => {
currentPage.value = page
}

const nextPage = () => {
if (currentPage.value === totalPage.value) return
currentPage.value += 1
}

const previousPage = () => {
if (currentPage.value === 1) return
currentPage.value -= 1
}

const setPageSize = (newPageSize: number) => {
pageSize.value = newPageSize
}

const gotoFirstPage = () => {
currentPage.value = 1
}

const gotoLastPage = () => {
currentPage.value = totalPage.value
}

return {
currentPage,
isFirstPage,
isLastPage,
totalPage,
pages,
gotoPage,
nextPage,
previousPage,
setPageSize,
gotoFirstPage,
gotoLastPage,
}
}
6 changes: 4 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
// import UseProgress from './demo/UseProgress.vue'
// import UseCalendar from './demo/UseCalendar.vue'
// import UseCountdown from './demo/UseCountdown.vue'
import UseUpload from './demo/UseUpload.vue'
// import UseUpload from './demo/UseUpload.vue'
import UsePagination from './demo/UsePagination.vue'
</script>

<template>
Expand All @@ -13,5 +14,6 @@ import UseUpload from './demo/UseUpload.vue'
<!-- <UseProgress /> -->
<!-- <UseCalendar /> -->
<!-- <UseCountdown /> -->
<UseUpload />
<!-- <UseUpload /> -->
<UsePagination />
</template>
93 changes: 93 additions & 0 deletions src/demo/UsePagination.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<script setup lang="ts">
import { usePagination } from '@noi/core'
const {
totalPage,
pages,
gotoPage,
setPageSize,
gotoFirstPage,
gotoLastPage,
previousPage,
nextPage,
currentPage,
} = usePagination({
total: 100,
ellipsis: true,
})
</script>

<template>
<div @click="gotoFirstPage">首页</div>
<div @click="gotoPage(page)" :key="page" v-for="page in pages">
{{ page }}
</div>
<div @click="gotoLastPage">尾页</div>
// 重新设置 pageSize
<div>总计: {{ totalPage }}</div>
<nav
class="isolate inline-flex -space-x-px rounded-md shadow-sm"
aria-label="Pagination"
>
<a
href="#"
class="relative inline-flex items-center rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>
<span class="sr-only" @click="previousPage">上一页</span>
<svg
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
clip-rule="evenodd"
/>
</svg>
</a>
<template v-for="page in pages" :key="page.value">
<a
v-if="page.type === 'page'"
v-show="page.value === currentPage"
@click="gotoPage(page.value)"
href="#"
aria-current="page"
class="relative inline-flex items-center z-10 bg-indigo-600 px-4 py-2 text-sm font-semibold text-white focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>{{ page.text }}</a
>
<span
v-if="page.type === 'ellipsis'"
class="relative inline-flex items-center px-4 py-2 text-sm font-semibold text-gray-700 ring-1 ring-inset ring-gray-300 focus:outline-offset-0"
>...</span
>
<a
v-if="page.type === 'page'"
v-show="page.value !== currentPage"
@click="gotoPage(page.value)"
href="#"
class="relative inline-flex items-center px-4 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>{{ page.text }}</a
>
</template>
<a
href="#"
class="relative inline-flex items-center rounded-r-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0"
>
<span class="sr-only" @click="nextPage">下一页</span>
<svg
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
clip-rule="evenodd"
/>
</svg>
</a>
</nav>
</template>

0 comments on commit b2bfa49

Please sign in to comment.