formatter.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package rest
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "gorm.io/gorm"
  7. "reflect"
  8. "strconv"
  9. "sync"
  10. "time"
  11. )
  12. var (
  13. DefaultFormatter = NewFormatter()
  14. DefaultNullDisplay = ""
  15. )
  16. type FormatFunc func(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{}
  17. type Formatter struct {
  18. callbacks sync.Map
  19. }
  20. func (formatter *Formatter) Register(f string, fun FormatFunc) {
  21. formatter.callbacks.Store(f, fun)
  22. }
  23. func (formatter *Formatter) Format(ctx context.Context, format string, value interface{}, model interface{}, scm *Schema) interface{} {
  24. v, ok := formatter.callbacks.Load(format)
  25. if ok {
  26. return v.(FormatFunc)(ctx, value, model, scm)
  27. }
  28. return value
  29. }
  30. func (formatter *Formatter) formatModel(ctx context.Context, val interface{}, schemas []*Schema, stmt *gorm.Statement) interface{} {
  31. values := make(map[string]interface{})
  32. refVal := reflect.Indirect(reflect.ValueOf(val))
  33. for _, field := range schemas {
  34. f := stmt.Schema.LookUpField(field.Column)
  35. values[field.Column] = formatter.Format(ctx, field.Format, refVal.FieldByName(f.Name).Interface(), val, field)
  36. }
  37. return values
  38. }
  39. func (formatter *Formatter) formatModels(ctx context.Context, val interface{}, schemas []*Schema, stmt *gorm.Statement) interface{} {
  40. reflectValue := reflect.Indirect(reflect.ValueOf(val))
  41. if reflectValue.Type().Kind() != reflect.Slice {
  42. return nil
  43. }
  44. length := reflectValue.Len()
  45. values := make([]interface{}, length)
  46. for i := 0; i < length; i++ {
  47. values[i] = formatter.formatModel(ctx, reflectValue.Index(i).Interface(), schemas, stmt)
  48. }
  49. return values
  50. }
  51. func stringFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  52. return fmt.Sprint(value)
  53. }
  54. func integerFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  55. var (
  56. n int
  57. )
  58. switch value.(type) {
  59. case float32, float64:
  60. n = int(reflect.ValueOf(value).Float())
  61. case int, int8, int16, int32, int64:
  62. n = int(reflect.ValueOf(value).Int())
  63. case uint, uint8, uint16, uint32, uint64:
  64. n = int(reflect.ValueOf(value).Uint())
  65. case string:
  66. n, _ = strconv.Atoi(reflect.ValueOf(value).String())
  67. case []byte:
  68. n, _ = strconv.Atoi(string(reflect.ValueOf(value).Bytes()))
  69. }
  70. return n
  71. }
  72. func decimalFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  73. var (
  74. n float64
  75. )
  76. switch value.(type) {
  77. case float32, float64:
  78. n = float64(reflect.ValueOf(value).Float())
  79. case int, int8, int16, int32, int64:
  80. n = float64(reflect.ValueOf(value).Int())
  81. case uint, uint8, uint16, uint32, uint64:
  82. n = float64(reflect.ValueOf(value).Uint())
  83. case string:
  84. n, _ = strconv.ParseFloat(reflect.ValueOf(value).String(), 64)
  85. case []byte:
  86. n, _ = strconv.ParseFloat(string(reflect.ValueOf(value).Bytes()), 64)
  87. }
  88. return n
  89. }
  90. func dateFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  91. if t, ok := value.(time.Time); ok {
  92. return t.Format("2006-01-02")
  93. }
  94. if t, ok := value.(*sql.NullTime); ok {
  95. if t != nil && t.Valid {
  96. return t.Time.Format("2006-01-02")
  97. }
  98. }
  99. if t, ok := value.(int64); ok {
  100. tm := time.Unix(t, 0)
  101. return tm.Format("2006-01-02")
  102. }
  103. return DefaultNullDisplay
  104. }
  105. func timeFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  106. if t, ok := value.(time.Time); ok {
  107. return t.Format("15:04:05")
  108. }
  109. if t, ok := value.(*sql.NullTime); ok {
  110. if t != nil && t.Valid {
  111. return t.Time.Format("15:04:05")
  112. }
  113. }
  114. if t, ok := value.(int64); ok {
  115. tm := time.Unix(t, 0)
  116. return tm.Format("15:04:05")
  117. }
  118. return DefaultNullDisplay
  119. }
  120. func datetimeFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  121. if t, ok := value.(time.Time); ok {
  122. return t.Format("2006-01-02 15:04:05")
  123. }
  124. if t, ok := value.(*sql.NullTime); ok {
  125. if t != nil && t.Valid {
  126. return t.Time.Format("2006-01-02 15:04:05")
  127. }
  128. }
  129. if t, ok := value.(int64); ok {
  130. if t > 0 {
  131. tm := time.Unix(t, 0)
  132. return tm.Format("2006-01-02 15:04:05")
  133. }
  134. }
  135. return DefaultNullDisplay
  136. }
  137. func durationFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  138. var (
  139. hour int
  140. min int
  141. sec int
  142. )
  143. n := integerFormat(ctx, value, model, scm).(int)
  144. hour = n / 3600
  145. min = (n - hour*3600) / 60
  146. sec = n - hour*3600 - min*60
  147. return fmt.Sprintf("%02d:%02d:%02d", hour, min, sec)
  148. }
  149. func dropdownFormat(ctx context.Context, value interface{}, model interface{}, scm *Schema) interface{} {
  150. attributes := scm.getProperties()
  151. if attributes != nil && attributes.Values != nil {
  152. for _, v := range attributes.Values {
  153. if v.Value == value {
  154. return v.Label
  155. }
  156. }
  157. }
  158. return value
  159. }
  160. func NewFormatter() *Formatter {
  161. formatter := &Formatter{}
  162. formatter.Register("string", stringFormat)
  163. formatter.Register("integer", integerFormat)
  164. formatter.Register("decimal", decimalFormat)
  165. formatter.Register("date", dateFormat)
  166. formatter.Register("time", timeFormat)
  167. formatter.Register("datetime", datetimeFormat)
  168. formatter.Register("duration", durationFormat)
  169. formatter.Register("dropdown", dropdownFormat)
  170. return formatter
  171. }