add Paginator
parent
25c582735f
commit
afa04cb1f6
|
|
@ -1,116 +1,166 @@
|
||||||
package paginator
|
package paginator
|
||||||
|
|
||||||
// Paginator
|
import (
|
||||||
type Paginator struct {
|
"fmt"
|
||||||
page int
|
"strings"
|
||||||
limit int
|
)
|
||||||
|
|
||||||
|
type Paginator[T any] struct {
|
||||||
|
rawTtems []T // 当前页的数据
|
||||||
|
curPage int // 当前页
|
||||||
|
limit int // 每页数量
|
||||||
|
pageCount int // 最多显示的总页数
|
||||||
}
|
}
|
||||||
|
|
||||||
// New
|
// Cut 按分页切割数据
|
||||||
func New(page, limit int) *Paginator {
|
// @param items 原始数据
|
||||||
return &Paginator{page: page, limit: limit}
|
// @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)
|
||||||
|
|
||||||
|
return &Paginator[T]{
|
||||||
|
rawTtems: items,
|
||||||
|
curPage: page,
|
||||||
|
limit: limit,
|
||||||
|
pageCount: pageCount,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset
|
func (p *Paginator[T]) Items() []T {
|
||||||
func (p *Paginator) Offset() int {
|
// 计算起始索引和结束索引
|
||||||
if p.page < 1 {
|
startIdx := (p.curPage - 1) * p.limit
|
||||||
p.page = 1
|
endIdx := startIdx + p.limit
|
||||||
}
|
endIdx = min(endIdx, len(p.rawTtems))
|
||||||
offset := p.limit * (p.page - 1)
|
|
||||||
return int(offset)
|
items := p.rawTtems[startIdx:endIdx]
|
||||||
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit
|
// TotalPage 总页数
|
||||||
func (p *Paginator) Limit() int {
|
func (p *Paginator[T]) TotalPage() int {
|
||||||
return p.limit
|
if p.limit == 0 {
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pagination
|
// 计算总页数
|
||||||
func (p *Paginator) Pagination(totalCount int) *Pagination {
|
total := (len(p.rawTtems) / p.limit)
|
||||||
pg := Pagination{}
|
if len(p.rawTtems)%p.limit != 0 {
|
||||||
|
total++
|
||||||
total := (totalCount / p.limit)
|
|
||||||
|
|
||||||
// Calculator Total Page
|
|
||||||
remainder := totalCount % p.limit
|
|
||||||
if remainder == 0 {
|
|
||||||
pg.totalPage = total
|
|
||||||
} else {
|
|
||||||
pg.totalPage = total + 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set current/record per page meta data
|
return total
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pg
|
func (p *Paginator[T]) pageRangeIdx() (int, int) {
|
||||||
|
if p.limit == 0 {
|
||||||
|
return 1, 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pagination Object
|
total := p.TotalPage()
|
||||||
type Pagination struct {
|
|
||||||
next int
|
if p.pageCount == 0 || total <= p.pageCount {
|
||||||
previous int
|
return 1, total
|
||||||
recordPerPage int
|
}
|
||||||
currentPage int
|
|
||||||
totalPage int
|
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 迭代页码
|
// PageRange 迭代页码
|
||||||
func (p *Pagination) PageRange() []int {
|
func (p *Paginator[T]) PageRange() []int {
|
||||||
pages := []int{}
|
pages := []int{}
|
||||||
for i := 1; i <= p.totalPage; i++ {
|
|
||||||
|
start, end := p.pageRangeIdx()
|
||||||
|
for i := start; i <= end; i++ {
|
||||||
pages = append(pages, i)
|
pages = append(pages, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pages
|
return pages
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumPages 页码数量
|
func (p *Paginator[T]) String() string {
|
||||||
func (p *Pagination) NumPages() int {
|
pages := p.PageRange()
|
||||||
return p.totalPage
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasPrevious 是否有上一页
|
|
||||||
func (p *Pagination) HasPrevious() bool {
|
|
||||||
return p.previous > 0
|
|
||||||
}
|
}
|
||||||
|
pageStr := strings.Join(buf, " ")
|
||||||
|
|
||||||
// PreviousPageNumber 上一页的页码
|
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())
|
||||||
func (p *Pagination) PreviousPageNumber() int {
|
|
||||||
return p.previous
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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