add Paginator
parent
25c582735f
commit
afa04cb1f6
|
|
@ -1,116 +1,166 @@
|
|||
package paginator
|
||||
|
||||
// Paginator
|
||||
type Paginator struct {
|
||||
page int
|
||||
limit int
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Paginator[T any] struct {
|
||||
rawTtems []T // 当前页的数据
|
||||
curPage int // 当前页
|
||||
limit int // 每页数量
|
||||
pageCount int // 最多显示的总页数
|
||||
}
|
||||
|
||||
// New
|
||||
func New(page, limit int) *Paginator {
|
||||
return &Paginator{page: page, limit: limit}
|
||||
}
|
||||
// Cut 按分页切割数据
|
||||
// @param items 原始数据
|
||||
// @param page 当前页
|
||||
// @param limit 每页数量, 0 表示不分页
|
||||
// @param pageCount 最多显示的总页数, 0 表示不限制
|
||||
func Cut[T any](items []T, page int, limit int, pageCount int) *Paginator[T] {
|
||||
// 参数校验
|
||||
page = max(page, 1)
|
||||
limit = max(limit, 0)
|
||||
pageCount = max(pageCount, 0)
|
||||
|
||||
// Offset
|
||||
func (p *Paginator) Offset() int {
|
||||
if p.page < 1 {
|
||||
p.page = 1
|
||||
return &Paginator[T]{
|
||||
rawTtems: items,
|
||||
curPage: page,
|
||||
limit: limit,
|
||||
pageCount: pageCount,
|
||||
}
|
||||
offset := p.limit * (p.page - 1)
|
||||
return int(offset)
|
||||
}
|
||||
|
||||
// Limit
|
||||
func (p *Paginator) Limit() int {
|
||||
return p.limit
|
||||
func (p *Paginator[T]) Items() []T {
|
||||
// 计算起始索引和结束索引
|
||||
startIdx := (p.curPage - 1) * p.limit
|
||||
endIdx := startIdx + p.limit
|
||||
endIdx = min(endIdx, len(p.rawTtems))
|
||||
|
||||
items := p.rawTtems[startIdx:endIdx]
|
||||
return items
|
||||
}
|
||||
|
||||
// Pagination
|
||||
func (p *Paginator) Pagination(totalCount int) *Pagination {
|
||||
pg := Pagination{}
|
||||
|
||||
total := (totalCount / p.limit)
|
||||
|
||||
// Calculator Total Page
|
||||
remainder := totalCount % p.limit
|
||||
if remainder == 0 {
|
||||
pg.totalPage = total
|
||||
} else {
|
||||
pg.totalPage = total + 1
|
||||
// TotalPage 总页数
|
||||
func (p *Paginator[T]) TotalPage() int {
|
||||
if p.limit == 0 {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Set current/record per page meta data
|
||||
pg.currentPage = p.page
|
||||
pg.recordPerPage = p.limit
|
||||
|
||||
// Calculator the Next/Previous Page
|
||||
if p.page <= 0 {
|
||||
pg.next = p.page + 1
|
||||
} else if p.page < pg.totalPage {
|
||||
pg.previous = p.page - 1
|
||||
pg.next = p.page + 1
|
||||
} else if p.page == pg.totalPage {
|
||||
pg.previous = p.page - 1
|
||||
pg.next = 0
|
||||
// 计算总页数
|
||||
total := (len(p.rawTtems) / p.limit)
|
||||
if len(p.rawTtems)%p.limit != 0 {
|
||||
total++
|
||||
}
|
||||
|
||||
return &pg
|
||||
return total
|
||||
}
|
||||
|
||||
// Pagination Object
|
||||
type Pagination struct {
|
||||
next int
|
||||
previous int
|
||||
recordPerPage int
|
||||
currentPage int
|
||||
totalPage int
|
||||
func (p *Paginator[T]) pageRangeIdx() (int, int) {
|
||||
if p.limit == 0 {
|
||||
return 1, 1
|
||||
}
|
||||
|
||||
total := p.TotalPage()
|
||||
|
||||
if p.pageCount == 0 || total <= p.pageCount {
|
||||
return 1, total
|
||||
}
|
||||
|
||||
if p.curPage > total {
|
||||
p.curPage = total
|
||||
}
|
||||
|
||||
// 计算起始页和结束页
|
||||
offset := p.pageCount / 2
|
||||
startPage := p.curPage - offset
|
||||
endPage := p.curPage + offset
|
||||
if startPage < 1 {
|
||||
endPage = endPage - startPage + 1
|
||||
startPage = 1
|
||||
}
|
||||
|
||||
if endPage > total {
|
||||
startPage = startPage - (endPage - total)
|
||||
endPage = total
|
||||
}
|
||||
|
||||
return startPage, endPage
|
||||
}
|
||||
|
||||
// FirstPage 第一页, 如果limit为0, 表示不显示
|
||||
func (p *Paginator[T]) FirstPage() int {
|
||||
if p.limit == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
start, _ := p.pageRangeIdx()
|
||||
if start > 1 {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// FirstPage 第一页, 如果limit为0, 表示不显示
|
||||
func (p *Paginator[T]) LastPage() int {
|
||||
if p.limit == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
_, end := p.pageRangeIdx()
|
||||
if end == p.TotalPage() {
|
||||
return 0
|
||||
}
|
||||
|
||||
return p.TotalPage()
|
||||
}
|
||||
|
||||
// PreviewPage 上一页, 如果为0, 表示不显示
|
||||
func (p *Paginator[T]) PreviewPage() int {
|
||||
preview := p.curPage - 1
|
||||
if preview <= 1 {
|
||||
preview = 0
|
||||
}
|
||||
|
||||
return preview
|
||||
}
|
||||
|
||||
// PreviewPage 下一页, 如果为0, 表示不显示
|
||||
func (p *Paginator[T]) NextPage() int {
|
||||
next := p.curPage + 1
|
||||
if next >= p.TotalPage() {
|
||||
next = 0
|
||||
}
|
||||
|
||||
return next
|
||||
}
|
||||
|
||||
// PageRange 迭代页码
|
||||
func (p *Pagination) PageRange() []int {
|
||||
func (p *Paginator[T]) PageRange() []int {
|
||||
pages := []int{}
|
||||
for i := 1; i <= p.totalPage; i++ {
|
||||
|
||||
start, end := p.pageRangeIdx()
|
||||
for i := start; i <= end; i++ {
|
||||
pages = append(pages, i)
|
||||
}
|
||||
|
||||
return pages
|
||||
}
|
||||
|
||||
// NumPages 页码数量
|
||||
func (p *Pagination) NumPages() int {
|
||||
return p.totalPage
|
||||
}
|
||||
func (p *Paginator[T]) String() string {
|
||||
pages := p.PageRange()
|
||||
|
||||
// HasPrevious 是否有上一页
|
||||
func (p *Pagination) HasPrevious() bool {
|
||||
return p.previous > 0
|
||||
}
|
||||
buf := make([]string, len(pages))
|
||||
for i, k := range pages {
|
||||
if k == p.curPage {
|
||||
buf[i] = fmt.Sprintf("[%d]", k)
|
||||
} else {
|
||||
buf[i] = fmt.Sprintf("%d", k)
|
||||
}
|
||||
|
||||
// PreviousPageNumber 上一页的页码
|
||||
func (p *Pagination) PreviousPageNumber() int {
|
||||
return p.previous
|
||||
}
|
||||
}
|
||||
pageStr := strings.Join(buf, " ")
|
||||
|
||||
// HasNext 是否有下一页
|
||||
func (p *Pagination) HasNext() bool {
|
||||
return p.next > 0
|
||||
}
|
||||
|
||||
// NextPageNumber 下一页的页码
|
||||
func (p *Pagination) NextPageNumber() int {
|
||||
return p.next
|
||||
}
|
||||
|
||||
// Number 当前页码
|
||||
func (p *Pagination) Number() int {
|
||||
return p.currentPage
|
||||
}
|
||||
|
||||
// Number 当前页码
|
||||
func (p *Pagination) IsFirstPage() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Number 当前页码
|
||||
func (p *Pagination) IsLastPage() bool {
|
||||
return false
|
||||
return fmt.Sprintf("items=%v\nfirst=%d, preview=%d pages=%s, next=%d, last=%d", p.Items(), p.FirstPage(), p.PreviewPage(), pageStr, p.NextPage(), p.LastPage())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package paginator
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCut(t *testing.T) {
|
||||
items := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
page := 3
|
||||
limit := 3
|
||||
pageCount := 3
|
||||
pag := Cut(items, page, limit, pageCount)
|
||||
t.Logf("pag: %s", pag)
|
||||
}
|
||||
Loading…
Reference in New Issue