generator.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package rest
  2. import (
  3. "gorm.io/gorm/schema"
  4. "reflect"
  5. "strings"
  6. "time"
  7. )
  8. var (
  9. timeKind = reflect.TypeOf(time.Time{}).Kind()
  10. timePtrKind = reflect.TypeOf(&time.Time{}).Kind()
  11. )
  12. //dataTypeOf 推断数据的类型
  13. func dataTypeOf(field *schema.Field) string {
  14. var dataType string
  15. reflectType := field.FieldType
  16. for reflectType.Kind() == reflect.Ptr {
  17. reflectType = reflectType.Elem()
  18. }
  19. dataValue := reflect.Indirect(reflect.New(reflectType))
  20. switch dataValue.Kind() {
  21. case reflect.Bool:
  22. dataType = TypeBoolean
  23. case reflect.Int8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  24. dataType = TypeInteger
  25. case reflect.Float32, reflect.Float64:
  26. dataType = TypeFloat
  27. default:
  28. dataType = TypeString
  29. }
  30. return dataType
  31. }
  32. //dataFormatOf 推断数据的格式
  33. func dataFormatOf(field *schema.Field) string {
  34. var format string
  35. format = field.Tag.Get("format")
  36. if format != "" {
  37. return format
  38. }
  39. //如果有枚举值,直接设置为下拉类型
  40. enum := field.Tag.Get("enum")
  41. if enum != "" {
  42. return FormatDropdown
  43. }
  44. reflectType := field.FieldType
  45. for reflectType.Kind() == reflect.Ptr {
  46. reflectType = reflectType.Elem()
  47. }
  48. //时间处理
  49. dataValue := reflect.Indirect(reflect.New(reflectType))
  50. if field.Name == "CreatedAt" || field.Name == "UpdatedAt" || field.Name == "DeletedAt" {
  51. switch dataValue.Kind() {
  52. case reflect.Int8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  53. return FormatTimestamp
  54. default:
  55. return FormatDatetime
  56. }
  57. }
  58. if strings.Contains(strings.ToLower(field.Name), "pass") {
  59. return FormatPassword
  60. }
  61. switch dataValue.Kind() {
  62. case timeKind, timePtrKind:
  63. format = FormatDatetime
  64. case reflect.Bool:
  65. format = FormatBoolean
  66. case reflect.Int8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  67. format = FormatInteger
  68. case reflect.Float32, reflect.Float64:
  69. format = FormatFloat
  70. case reflect.Struct:
  71. if _, ok := dataValue.Interface().(time.Time); ok {
  72. format = FormatDatetime
  73. }
  74. default:
  75. if field.Size >= 1024 {
  76. format = FormatText
  77. } else {
  78. format = FormatString
  79. }
  80. }
  81. return format
  82. }
  83. //generateFieldName 生成字段名称
  84. func generateFieldName(name string) string {
  85. tokens := strings.Split(name, "_")
  86. for i, s := range tokens {
  87. tokens[i] = strings.Title(s)
  88. }
  89. return strings.Join(tokens, " ")
  90. }
  91. //generateFieldScenario 生成数据的显示场景
  92. func generateFieldScenario(index int, field *schema.Field) Scenarios {
  93. var ss Scenarios
  94. if v, ok := field.Tag.Lookup("scenarios"); ok {
  95. v = strings.TrimSpace(v)
  96. if v != "" {
  97. ss = strings.Split(v, ";")
  98. }
  99. } else {
  100. if field.PrimaryKey {
  101. ss = []string{ScenarioList, ScenarioView, ScenarioExport}
  102. } else if field.Name == "CreatedAt" || field.Name == "UpdatedAt" {
  103. ss = []string{ScenarioList}
  104. } else if field.Name == "DeletedAt" || field.Name == "Namespace" {
  105. //不添加任何显示场景
  106. ss = []string{}
  107. } else {
  108. if index < 10 {
  109. //高级字段只配置一些简单的场景
  110. ss = []string{ScenarioSearch, ScenarioList, ScenarioCreate, ScenarioUpdate, ScenarioView, ScenarioExport}
  111. } else {
  112. //高级字段只配置一些简单的场景
  113. ss = []string{ScenarioCreate, ScenarioUpdate, ScenarioView, ScenarioExport}
  114. }
  115. }
  116. }
  117. return ss
  118. }
  119. //generateFieldRule 生成字段的规则
  120. func generateFieldRule(field *schema.Field) Rule {
  121. r := Rule{
  122. Required: []string{},
  123. }
  124. if field.GORMDataType == schema.String {
  125. r.Max = field.Size
  126. }
  127. if field.GORMDataType == schema.Int || field.GORMDataType == schema.Float || field.GORMDataType == schema.Uint {
  128. r.Max = field.Scale
  129. }
  130. if field.NotNull {
  131. r.Required = []string{ScenarioCreate, ScenarioUpdate}
  132. }
  133. if field.PrimaryKey {
  134. r.Unique = true
  135. }
  136. return r
  137. }
  138. // generateFieldAttribute 生成数据属性
  139. func generateFieldAttribute(field *schema.Field) Attribute {
  140. attr := Attribute{
  141. Match: MatchFuzzy,
  142. PrimaryKey: field.PrimaryKey,
  143. DefaultValue: field.DefaultValue,
  144. Readonly: []string{},
  145. Disable: []string{},
  146. Visible: make([]VisibleCondition, 0),
  147. Values: make([]EnumValue, 0),
  148. Live: LiveValue{},
  149. Description: "",
  150. }
  151. //赋值属性
  152. props := field.Tag.Get("props")
  153. if props != "" {
  154. vs := strings.Split(props, ";")
  155. for _, str := range vs {
  156. kv := strings.SplitN(str, ":", 2)
  157. if len(kv) != 2 {
  158. continue
  159. }
  160. switch strings.ToLower(kv[0]) {
  161. case "icon":
  162. attr.Icon = kv[1]
  163. case "suffix":
  164. attr.Suffix = kv[1]
  165. case "tooltip":
  166. attr.Tooltip = kv[1]
  167. case "description":
  168. attr.Description = kv[1]
  169. case "live":
  170. //在线数据解析
  171. ss := strings.Split(kv[1], ",")
  172. for _, s := range ss {
  173. if len(s) == 0 {
  174. continue
  175. }
  176. attr.Live.Enable = true
  177. if s == LiveTypeDropdown || s == LiveTypeCascader {
  178. attr.Live.Type = s
  179. } else if s[0] == '/' || strings.HasPrefix(s, "http") {
  180. attr.Live.Url = s
  181. } else {
  182. if strings.IndexByte(s, '.') > -1 {
  183. attr.Live.Columns = strings.Split(s, ".")
  184. }
  185. }
  186. }
  187. }
  188. }
  189. }
  190. //赋值枚举值
  191. enumns := field.Tag.Get("enum")
  192. if enumns != "" {
  193. vs := strings.Split(enumns, ";")
  194. for _, str := range vs {
  195. kv := strings.SplitN(str, ":", 2)
  196. if len(kv) != 2 {
  197. continue
  198. }
  199. fv := EnumValue{Value: kv[0]}
  200. //颜色分隔符
  201. if pos := strings.IndexByte(kv[1], '#'); pos > -1 {
  202. fv.Label = kv[1][:pos]
  203. fv.Color = kv[1][pos:]
  204. } else {
  205. fv.Label = kv[1]
  206. }
  207. attr.Values = append(attr.Values, fv)
  208. }
  209. }
  210. if !field.Creatable {
  211. attr.Disable = append(attr.Disable, ScenarioCreate)
  212. }
  213. if !field.Updatable {
  214. attr.Disable = append(attr.Disable, ScenarioUpdate)
  215. }
  216. attr.Tooltip = field.Comment
  217. return attr
  218. }