-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathpagination.go
198 lines (175 loc) · 5.18 KB
/
pagination.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
package paginator
import (
"github.com/MQEnergy/gin-framework/global"
"github.com/MQEnergy/gin-framework/pkg/util"
"github.com/samber/lo"
"gorm.io/gorm"
"math"
)
type PageBuilder struct {
DB *gorm.DB
Model interface{} // model struct
Preloads []string // 预加载
Fields []string // 查询字段
}
type OnJoins struct {
LeftTableField, RightTableField JoinTableField // LeftTableField:如:主表.ID RightTableField:如:关联表.主表ID
}
type JoinTableField struct {
Table, Field string
}
type SelectTableField struct {
Model interface{}
Table string
Field []string
}
type Page struct {
List interface{} `json:"list"` // 查询的列表
CurrentPage int `json:"current_page"` // 当前页
Total int64 `json:"total"` // 查询记录总数
LastPage int `json:"last_page"` // 最后一页
PerPage int `json:"per_page"` // 每页条数
}
func NewBuilder() *PageBuilder {
return &PageBuilder{}
}
// WithDB db连接
func (pb *PageBuilder) WithDB(db *gorm.DB) *PageBuilder {
pb.DB = db
return pb
}
// NewDB 对接原生查询方式
func (pb *PageBuilder) NewDB() *gorm.DB {
return pb.DB
}
// WithField 查询单表的字段 和 过滤字段 不能与WithFields方法同用
func (pb *PageBuilder) WithField(fields []string) *PageBuilder {
fieldList := filterFields(pb.Model, fields)
pb.Fields = fieldList
pb.DB.Select(pb.Fields)
return pb
}
// WithFields 单多表字段查询字段(或过滤某些字段不查询 最后一个参数默认为select(不传或者传),如传omit为过滤前面传输的字段)
func (pb *PageBuilder) WithFields(model interface{}, table string, fields []string) *PageBuilder {
fieldList := filterFields(model, fields)
for i, _field := range fieldList {
fieldList[i] = table + "." + _field
}
pb.Fields = append(pb.Fields, fieldList...)
pb.DB.Select(pb.Fields)
return pb
}
// filterFields 过滤查询字段
func filterFields(model interface{}, fields []string) []string {
var fieldList []string
if len(fields) == 1 {
if fields[0] != "_omit" && fields[0] != "_select" {
fieldList = fields
}
} else {
switch fields[len(fields)-1] {
case "_omit":
fields = fields[:len(fields)-1]
_fields, _ := util.GetStructColumnName(model, 1)
fieldList, _ = lo.Difference[string](_fields, fields)
case "_select":
fieldList = fields[:len(fields)-1]
default:
fieldList = fields[:]
}
}
return fieldList
}
// WithMultiFields 多表多字段查询
func (pb *PageBuilder) WithMultiFields(fields []SelectTableField) *PageBuilder {
for _, field := range fields {
pb.WithFields(field.Model, field.Table, field.Field)
}
return pb
}
// WithModel 查询的model struct
func (pb *PageBuilder) WithModel(model interface{}) *PageBuilder {
pb.Model = model
pb.DB = pb.DB.Model(&model)
return pb
}
// WithOrderBy 排序
func (pb *PageBuilder) WithOrderBy(orderBy interface{}) *PageBuilder {
pb.DB = pb.DB.Order(orderBy)
return pb
}
// WithJoins join查询
func (pb *PageBuilder) WithJoins(joinType string, joinFields []OnJoins) *PageBuilder {
var joins string
for _, field := range joinFields {
joins += " " + joinType + " JOIN " + field.RightTableField.Table
joins += " ON " + field.LeftTableField.Table + "." + field.LeftTableField.Field + " = "
joins += field.RightTableField.Table + "." + field.RightTableField.Field
}
pb.DB.Joins(joins)
return pb
}
// WithPreloads 多表关联查询主动预加载(无条件)
func (pb *PageBuilder) WithPreloads(querys []string) *PageBuilder {
pb.Preloads = querys
return pb
}
// WithPreload 关联查询主动预加载(可传条件)
func (pb *PageBuilder) WithPreload(query string, args ...interface{}) *PageBuilder {
pb.DB.Preload(query, args...)
return pb
}
// WithCondition 查询条件
func (pb *PageBuilder) WithCondition(query interface{}, args ...interface{}) *PageBuilder {
pb.DB.Where(query, args...)
return pb
}
// Pagination 分页查询
func (pb *PageBuilder) Pagination(dst interface{}, currentPage, pageSize int) (Page, error) {
query := pb.DB
page := pb.ParsePage(currentPage, pageSize)
offset := (page.CurrentPage - 1) * page.PerPage
// 查询总数
if err := query.Count(&page.Total).Error; err != nil {
return page, err
}
// 预加载
if len(pb.Preloads) > 0 {
for _, preload := range pb.Preloads {
query.Preload(preload)
}
}
// 计算总页数
if page.Total > int64(page.PerPage) {
page.LastPage = int(math.Ceil(float64(page.Total) / float64(page.PerPage)))
}
// 判断总数跟最后一页的关系
if page.CurrentPage <= page.LastPage {
if err := query.Limit(page.PerPage).Offset(offset).Find(dst).Error; err != nil {
return page, err
}
}
page.List = dst
return page, nil
}
// ParsePage 分页超限设置和格式化
func (pb *PageBuilder) ParsePage(currentPage, pageSize int) Page {
var page Page
// 返回每页数量
page.PerPage = pageSize
// 返回当前页码
page.CurrentPage = currentPage
if currentPage < 1 {
page.CurrentPage = 1
}
if pageSize < 1 {
page.PerPage = global.Cfg.Server.DefaultPageSize
}
if pageSize > global.Cfg.Server.MaxPageSize {
page.PerPage = global.Cfg.Server.MaxPageSize
}
if page.LastPage < 1 {
page.LastPage = 1
}
return page
}