-
Notifications
You must be signed in to change notification settings - Fork 9
/
page.go
244 lines (204 loc) · 5.81 KB
/
page.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
package page
import (
"fmt"
"sort"
"math"
"strconv"
"net/url"
)
// 构造函数
func New() *Pagination {
return &Pagination{}
}
// 分页
type Pagination struct {
// 当前页
CurrentPage int
// 最后一页
LastPage int
// 数据总数
Total int
// 每页数量
ListRows int
// 当前开始位置
NowStart int
// 是否有下一页
HasMore bool
// 链接
UrlPath string
// url中参数
Parameters url.Values
// 生成链接
PageHtml string
}
// 每页数量
// listRows 每页数量
// total 总数量,
// urlPath 链接,
// config 配置参数
// page:当前页,
// path:url路径,
// query:url额外参数,
// fragment:url锚点,
func (this *Pagination) Paginate(
listRows int,
total int,
urlPath string,
parameters url.Values,
) *Pagination {
this.UrlPath = urlPath
this.Parameters = parameters
// 当前页
var page int
pageStr := this.Parameters.Get("page")
if pageStr == "" {
page = 1
} else {
page, _ = strconv.Atoi(pageStr)
}
if page < 1 {
page = 1
}
this.CurrentPage = page
this.ListRows = listRows
this.Total = total
this.LastPage = int(math.Ceil(float64(this.Total) / float64(this.ListRows)))
this.HasMore = this.CurrentPage < this.LastPage
// 开始位置
this.NowStart = (this.CurrentPage - 1) * this.ListRows
this.PageHtml = this.render()
return this
}
// 渲染分页html
func (this *Pagination) render() string {
if !this.hasPages() {
return ""
}
return fmt.Sprintf(
`<ul class="pagination">%s %s %s</ul>`,
this.getPreviousButton(),
this.getLinks(),
this.getNextButton(),
)
}
// 上一页按钮
func (this *Pagination) getPreviousButton() string {
text := `<span aria-hidden="true">«</span>`
if this.CurrentPage <= 1 {
return this.getDisabledTextWrapper(text)
}
url := this.url(this.CurrentPage - 1)
return this.getPageLinkWrapper(url, text)
}
// 下一页按钮
func (this *Pagination) getNextButton() string {
text := `<span aria-hidden="true">»</span>`
if !this.HasMore {
return this.getDisabledTextWrapper(text)
}
url := this.url(this.CurrentPage + 1)
return this.getPageLinkWrapper(url, text)
}
// 页码按钮
func (this *Pagination) getLinks() string {
block := map[string]map[int]string{
"first": nil,
"slider": nil,
"last": nil,
}
side := 3
window := side * 2
// 判断
switch {
case this.LastPage < window+6:
block["first"] = this.getUrlRange(1, this.LastPage)
case this.CurrentPage <= window:
block["first"] = this.getUrlRange(1, window+2)
block["last"] = this.getUrlRange(this.LastPage-1, this.LastPage)
case this.CurrentPage > (this.LastPage - window):
block["first"] = this.getUrlRange(1, 2)
block["last"] = this.getUrlRange(this.LastPage-(window+2), this.LastPage)
default:
block["first"] = this.getUrlRange(1, 2)
block["slider"] = this.getUrlRange(this.CurrentPage-side, this.CurrentPage+side)
block["last"] = this.getUrlRange(this.LastPage-1, this.LastPage)
}
html := ""
if len(block["first"]) > 0 {
html += this.getUrlLinks(block["first"])
}
if len(block["slider"]) > 0 {
html += this.getDots()
html += this.getUrlLinks(block["slider"])
}
if len(block["last"]) > 0 {
html += this.getDots()
html += this.getUrlLinks(block["last"])
}
return html
}
// 创建一组分页链接
func (this *Pagination) getUrlRange(start, end int) map[int]string {
urls := map[int]string{}
for page := start; page <= end; page++ {
urls[page] = this.url(page)
}
return urls
}
// 获取页码对应的链接
func (this *Pagination) url(page int) string {
urlPath := this.UrlPath
parameters := this.Parameters
if len(parameters) > 0 {
// 复制值
parameters.Set("page", strconv.Itoa(page))
urlStr := parameters.Encode()
return urlPath + "?" + urlStr
}
return urlPath + "?page=" + strconv.Itoa(page)
}
// 生成一个可点击的按钮
func (this *Pagination) getAvailablePageWrapper(url string, page string) string {
return `<li class="page-item"><a class="page-link" href="` + url + `">` + page + `</a></li>`
}
// 生成一个禁用的按钮
func (this *Pagination) getDisabledTextWrapper(text string) string {
return `<li class="page-item disabled"><a class="page-link">` + text + `</a></li>`
}
// 生成一个激活的按钮
func (this *Pagination) getActivePageWrapper(text string) string {
return `<li class="page-item active"><a class="page-link">` + text + `</a></li>`
}
// 生成省略号按钮
func (this *Pagination) getDots() string {
return this.getDisabledTextWrapper("...")
}
// 批量生成页码按钮
func (this *Pagination) getUrlLinks(urls map[int]string) string {
html := ""
var sortKeys []int
for page, _ := range urls {
sortKeys = append(sortKeys, page)
}
sort.Ints(sortKeys)
for _, page := range sortKeys {
html += this.getPageLinkWrapper(urls[page], page)
}
return html
}
// 生成普通页码按钮
func (this *Pagination) getPageLinkWrapper(url string, page interface{}) string {
pageInt, ok := page.(int)
if ok {
if this.CurrentPage == pageInt {
return this.getActivePageWrapper(strconv.Itoa(pageInt))
}
return this.getAvailablePageWrapper(url, strconv.Itoa(pageInt))
}
pageStr := page.(string)
return this.getAvailablePageWrapper(url, pageStr)
}
// 数据是否足够分页
func (this *Pagination) hasPages() bool {
return !(1 == this.CurrentPage && !this.HasMore)
}