192 lines
3.4 KiB
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())
|
|
}
|