pagination.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package pagination
  2. import (
  3. "fmt"
  4. "math"
  5. "net/http"
  6. "net/url"
  7. "strconv"
  8. "strings"
  9. "html/template"
  10. )
  11. //Pagination 分页器
  12. type Pagination struct {
  13. Request *http.Request
  14. Total int
  15. Pernum int
  16. }
  17. //NewPagination 新建分页器
  18. func NewPagination(req *http.Request, total int, pernum int) *Pagination {
  19. return &Pagination{
  20. Request: req,
  21. Total: total,
  22. Pernum: pernum,
  23. }
  24. }
  25. func (p *Pagination) HtmlPages() template.HTML {
  26. return template.HTML(p.Pages())
  27. }
  28. //Pages 渲染生成html分页标签
  29. func (p *Pagination) Pages() string {
  30. queryParams := p.Request.URL.Query()
  31. //从当前请求中获取page
  32. page := queryParams.Get("page")
  33. if page == "" {
  34. page = "1"
  35. }
  36. //将页码转换成整型,以便计算
  37. pagenum, _ := strconv.Atoi(page)
  38. if pagenum == 0 {
  39. return ""
  40. }
  41. //计算总页数
  42. var totalPageNum = int(math.Ceil(float64(p.Total) / float64(p.Pernum)))
  43. //首页链接
  44. var firstLink string
  45. //上一页链接
  46. var prevLink string
  47. //下一页链接
  48. var nextLink string
  49. //末页链接
  50. var lastLink string
  51. //中间页码链接
  52. var pageLinks []string
  53. //首页和上一页链接
  54. if pagenum > 1 {
  55. firstLink = fmt.Sprintf(`<li><a href="%s">首页</a></li>`, p.pageURL("1"))
  56. prevLink = fmt.Sprintf(`<li><a href="%s">上一页</a></li>`, p.pageURL(strconv.Itoa(pagenum-1)))
  57. } else {
  58. firstLink = `<li class="disabled"><a href="#">首页</a></li>`
  59. prevLink = `<li class="disabled"><a href="#">上一页</a></li>`
  60. }
  61. //末页和下一页
  62. if pagenum < totalPageNum {
  63. lastLink = fmt.Sprintf(`<li><a href="%s">末页</a></li>`, p.pageURL(strconv.Itoa(totalPageNum)))
  64. nextLink = fmt.Sprintf(`<li><a href="%s">下一页</a></li>`, p.pageURL(strconv.Itoa(pagenum+1)))
  65. } else {
  66. lastLink = `<li class="disabled"><a href="#">末页</a></li>`
  67. nextLink = `<li class="disabled"><a href="#">下一页</a></li>`
  68. }
  69. //生成中间页码链接
  70. pageLinks = make([]string, 0, 10)
  71. startPos := pagenum - 3
  72. endPos := pagenum + 3
  73. if startPos < 1 {
  74. endPos = endPos + int(math.Abs(float64(startPos))) + 1
  75. startPos = 1
  76. }
  77. if endPos > totalPageNum {
  78. endPos = totalPageNum
  79. }
  80. for i := startPos; i <= endPos; i++ {
  81. var s string
  82. if i == pagenum {
  83. s = fmt.Sprintf(`<li class="active"><a href="%s">%d</a></li>`, p.pageURL(strconv.Itoa(i)), i)
  84. } else {
  85. s = fmt.Sprintf(`<li><a href="%s">%d</a></li>`, p.pageURL(strconv.Itoa(i)), i)
  86. }
  87. pageLinks = append(pageLinks, s)
  88. }
  89. return fmt.Sprintf(`<ul class="pagination">%s%s%s%s%s</ul>`, firstLink, prevLink, strings.Join(pageLinks, ""), nextLink, lastLink)
  90. }
  91. //pageURL 生成分页url
  92. func (p *Pagination) pageURL(page string) string {
  93. //基于当前url新建一个url对象
  94. u, _ := url.Parse(p.Request.URL.String())
  95. q := u.Query()
  96. q.Set("page", page)
  97. u.RawQuery = q.Encode()
  98. return u.String()
  99. }