paging.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package utils
  2. import (
  3. "fmt"
  4. "log"
  5. "math"
  6. "reflect"
  7. "sort"
  8. "strings"
  9. )
  10. type PageForm struct {
  11. Start int `form:"start"`
  12. Limit int `form:"limit"`
  13. Q string `form:"q"`
  14. Sort string `form:"sort"`
  15. Order string `form:"order"`
  16. }
  17. func (p PageForm) String() string {
  18. return fmt.Sprintf("PageForm[Start=%d, Limit=%d, Q=%s, Sort=%s, Order=%s]", p.Start, p.Limit, p.Q, p.Sort, p.Order)
  19. }
  20. func NewPageForm() *PageForm {
  21. return &PageForm{
  22. Start: 0,
  23. Limit: math.MaxInt32,
  24. }
  25. }
  26. type PageResult struct {
  27. Total int `json:"total"`
  28. Rows interface{} `json:"rows"`
  29. }
  30. func NewPageResult(rows interface{}) *PageResult {
  31. v := reflect.ValueOf(rows)
  32. if v.Kind() == reflect.Slice {
  33. return &PageResult{
  34. Total: v.Len(),
  35. Rows: rows,
  36. }
  37. } else {
  38. return &PageResult{
  39. Total: 1,
  40. Rows: []interface{}{rows},
  41. }
  42. }
  43. }
  44. func (pr *PageResult) Slice(start, limit int) *PageResult {
  45. if limit < 0 || start < 0 {
  46. return pr
  47. }
  48. if pr.Rows == nil {
  49. return pr
  50. }
  51. v := reflect.ValueOf(pr.Rows)
  52. if v.Kind() != reflect.Slice {
  53. return pr
  54. }
  55. _start := start
  56. if _start > pr.Total {
  57. _start = pr.Total
  58. }
  59. _end := start + limit
  60. if _end > pr.Total {
  61. _end = pr.Total
  62. }
  63. size := _end - _start
  64. _rows := make([]interface{}, size)
  65. for i := 0; i < size; i++ {
  66. _rows[i] = v.Index(_start + i).Interface()
  67. }
  68. pr.Rows = _rows
  69. return pr
  70. }
  71. func (pr *PageResult) Sort(by, order string) *PageResult {
  72. if by == "" {
  73. return pr
  74. }
  75. if reflect.TypeOf(pr.Rows).Kind() != reflect.Slice {
  76. return pr
  77. }
  78. if reflect.ValueOf(pr.Rows).Len() == 0 {
  79. return pr
  80. }
  81. te := reflect.TypeOf(pr.Rows).Elem()
  82. for te.Kind() == reflect.Array || te.Kind() == reflect.Chan || te.Kind() == reflect.Map || te.Kind() == reflect.Ptr || te.Kind() == reflect.Slice {
  83. te = te.Elem()
  84. }
  85. if te.Kind() == reflect.Interface {
  86. va := reflect.ValueOf(pr.Rows).Index(0)
  87. for va.Kind() == reflect.Interface || va.Kind() == reflect.Ptr {
  88. va = va.Elem()
  89. }
  90. te = va.Type()
  91. }
  92. byIdx := -1
  93. if te.Kind() == reflect.Struct {
  94. for i := 0; i < te.NumField(); i++ {
  95. if strings.EqualFold(te.Field(i).Name, by) {
  96. // log.Printf("%v field name[%s] find field[%s] index[%d], case insensitive", te, by, te.Field(i).Name, i)
  97. byIdx = i
  98. break
  99. }
  100. }
  101. if byIdx == -1 {
  102. log.Printf("%v field name[%s] not found, case insensitive", te, by)
  103. return pr
  104. }
  105. }
  106. sort.Slice(pr.Rows, func(i, j int) (ret bool) {
  107. va := reflect.ValueOf(pr.Rows).Index(i)
  108. vb := reflect.ValueOf(pr.Rows).Index(j)
  109. for va.Kind() == reflect.Interface || va.Kind() == reflect.Ptr {
  110. va = va.Elem()
  111. }
  112. for vb.Kind() == reflect.Interface || vb.Kind() == reflect.Ptr {
  113. vb = vb.Elem()
  114. }
  115. if va.Kind() == reflect.Struct && vb.Kind() == reflect.Struct {
  116. switch va.Field(byIdx).Kind() {
  117. case reflect.Float32, reflect.Float64:
  118. ret = va.Field(byIdx).Float() < vb.Field(byIdx).Float()
  119. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  120. ret = va.Field(byIdx).Int() < vb.Field(byIdx).Int()
  121. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  122. ret = va.Field(byIdx).Uint() < vb.Field(byIdx).Uint()
  123. default:
  124. ret = fmt.Sprintf("%v", va.Field(byIdx)) < fmt.Sprintf("%v", vb.Field(byIdx))
  125. }
  126. } else if va.Kind() == reflect.Map && vb.Kind() == reflect.Map {
  127. ret = fmt.Sprintf("%v", va.MapIndex(reflect.ValueOf(by))) < fmt.Sprintf("%v", vb.MapIndex(reflect.ValueOf(by)))
  128. }
  129. if strings.HasPrefix(strings.ToLower(order), "desc") {
  130. ret = !ret
  131. }
  132. return
  133. })
  134. return pr
  135. }