pkg/paginator/paginator.go

192 lines
3.4 KiB
Go

package paginator
import (
"fmt"
"strings"
)
type Paginator[T any] struct {
rawTtems []T // 原始数据
curPage int // 当前页
limit int // 每页数量, 至少为1
pageCount int // 最多显示的总页数, 0表示不限制
}
// New 按分页切割数据
// @param items 原始数据
// @param page 当前页
// @param limit 每页数量, 至少为1
// @param pageCount 最多显示的总页数, 0表示不限制
func New[T any](items []T, page int, limit int, pageCount int) *Paginator[T] {
// 参数校验
page = max(page, 1)
limit = max(limit, 1)
pageCount = max(pageCount, 0)
p := &Paginator[T]{
rawTtems: items,
limit: limit,
pageCount: pageCount,
}
total := p.TotalPage()
p.curPage = min(page, total)
return p
}
func (p *Paginator[T]) Items() []T {
// 计算起始索引和结束索引
startIdx := (p.curPage - 1) * p.limit
startIdx = min(startIdx, len(p.rawTtems))
endIdx := startIdx + p.limit
endIdx = min(endIdx, len(p.rawTtems))
items := p.rawTtems[startIdx:endIdx]
return items
}
// TotalCount rawItems 总数量
func (p *Paginator[T]) TotalCount() int {
return len(p.rawTtems)
}
// CurPage 当前页
func (p *Paginator[T]) CurPage() int {
return p.curPage
}
// TotalPage 总页数
func (p *Paginator[T]) TotalPage() int {
if p.limit == 0 {
return 1
}
// 计算总页数
total := (len(p.rawTtems) / p.limit)
if len(p.rawTtems)%p.limit != 0 {
total++
}
return total
}
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 {
endPage = total
}
}
if endPage > total {
startPage = startPage - (endPage - total)
endPage = total
if startPage < 1 {
startPage = 1
}
}
return startPage, endPage
}
// FirstPage 第一页, 如果为0, 表示不显示
func (p *Paginator[T]) FirstPage() int {
if p.limit == 0 {
return 0
}
start, _ := p.pageRangeIdx()
if start > 1 {
return 1
}
return 0
}
// LastPage 最后一页, 如果为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 *Paginator[T]) PageRange() []int {
pages := []int{}
start, end := p.pageRangeIdx()
for i := start; i <= end; i++ {
pages = append(pages, i)
}
return pages
}
// String 打印分页信息
func (p *Paginator[T]) String() string {
pages := p.PageRange()
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)
}
}
pageStr := strings.Join(buf, " ")
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())
}