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()) }