generator.go 5.7 KB

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