Browse Source

规范化数据类型和格式

fancl 2 years ago
parent
commit
8e7fc18d38
4 changed files with 86 additions and 23 deletions
  1. 44 3
      api.go
  2. 1 1
      crud.go
  3. 20 19
      generator.go
  4. 21 0
      schema.go

+ 44 - 3
api.go

@@ -7,9 +7,25 @@ import (
 	"gorm.io/gorm"
 )
 
-type Api struct {
-	crud *CRUD
-}
+type (
+	Api struct {
+		crud *CRUD
+	}
+
+	feedRequest struct {
+		ModuleName string `json:"module_name"`
+		TableName  string `json:"table_name"`
+		ValueField string `json:"value_field"`
+		LabelField string `json:"label_field"`
+		Condition  string `json:"condition,omitempty"`
+		Limit      int    `json:"limit,omitempty"`
+	}
+
+	feedResponse struct {
+		Label interface{} `json:"label"`
+		Value interface{} `json:"value"`
+	}
+)
 
 func (api *Api) handleListSchema(httpCtx *http.Context) (err error) {
 	var (
@@ -26,6 +42,7 @@ func (api *Api) handleListSchema(httpCtx *http.Context) (err error) {
 	}
 }
 
+//handleSaveSchema 保存schema
 func (api *Api) handleSaveSchema(httpCtx *http.Context) (err error) {
 	var (
 		rest *Restful
@@ -72,6 +89,7 @@ func (api *Api) handleSaveSchema(httpCtx *http.Context) (err error) {
 	}
 }
 
+//handleListSchemas 查看表schema
 func (api *Api) handleListSchemas(httpCtx *http.Context) (err error) {
 	var (
 		moduleLabel string
@@ -98,6 +116,7 @@ func (api *Api) handleListSchemas(httpCtx *http.Context) (err error) {
 	return httpCtx.Success(ts)
 }
 
+//handleDeleteSchema 删除指定的表结构
 func (api *Api) handleDeleteSchema(httpCtx *http.Context) (err error) {
 	id := httpCtx.ParamValue("id")
 	model := &Schema{}
@@ -118,11 +137,33 @@ func (api *Api) handleDeleteSchema(httpCtx *http.Context) (err error) {
 	}
 }
 
+//handleFeed 订阅指定模块数据
+func (api *Api) handleFeed(httpCtx *http.Context) (err error) {
+	req := &feedRequest{}
+	if err = httpCtx.Bind(req); err != nil {
+		return httpCtx.Error(HttpInvalidPayload, err.Error())
+	}
+	result := make([]feedResponse, 0, 10)
+	query := api.crud.db.Table(req.TableName).Select(req.LabelField+" AS label", req.ValueField+" AS value")
+	if req.Condition != "" {
+		query = query.Where(req.Condition)
+	}
+	if req.Limit > 0 {
+		query = query.Limit(req.Limit)
+	}
+	if err = query.Find(&result).Error; err == nil {
+		return httpCtx.Success(result)
+	} else {
+		return httpCtx.Error(HttpDatabaseFindFailed, err.Error())
+	}
+}
+
 func (api *Api) Router(svr *http.Server, ms ...http.Middleware) {
 	svr.Handle("GET", "/rest/schemas", api.handleListSchemas, ms...)
 	svr.Handle("GET", "/rest/schema/:module/:table", api.handleListSchema, ms...)
 	svr.Handle("PUT", "/rest/schema/:module/:table", api.handleSaveSchema, ms...)
 	svr.Handle("DELETE", "/rest/schema/:id", api.handleDeleteSchema, ms...)
+	svr.Handle("POST", "/rest/feed", api.handleFeed, ms...)
 
 	for _, rest := range api.crud.modules {
 		if rest.hasScenario(ScenarioList) {

+ 1 - 1
crud.go

@@ -39,7 +39,7 @@ type (
 		delegate    *delegate
 		enableCache bool
 	}
-	
+
 	treeValue struct {
 		Label    string       `json:"label"`
 		Value    string       `json:"value"`

+ 20 - 19
generator.go

@@ -22,17 +22,13 @@ func dataTypeOf(field *schema.Field) string {
 	dataValue := reflect.Indirect(reflect.New(reflectType))
 	switch dataValue.Kind() {
 	case reflect.Bool:
-		dataType = "boolean"
+		dataType = TypeBoolean
 	case reflect.Int8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		dataType = "integer"
+		dataType = TypeInteger
 	case reflect.Float32, reflect.Float64:
-		dataType = "double"
-	case reflect.Struct:
-		if _, ok := dataValue.Interface().(time.Time); ok {
-			dataType = "string"
-		}
+		dataType = TypeFloat
 	default:
-		dataType = "string"
+		dataType = TypeString
 	}
 	return dataType
 }
@@ -47,38 +43,43 @@ func dataFormatOf(field *schema.Field) string {
 	//如果有枚举值,直接设置为下拉类型
 	enum := field.Tag.Get("enum")
 	if enum != "" {
-		return "dropdown"
+		return FormatDropdown
 	}
 	reflectType := field.FieldType
 	for reflectType.Kind() == reflect.Ptr {
 		reflectType = reflectType.Elem()
 	}
 	//时间处理
+	dataValue := reflect.Indirect(reflect.New(reflectType))
 	if field.Name == "CreatedAt" || field.Name == "UpdatedAt" || field.Name == "DeletedAt" {
-		return "datetime"
+		switch dataValue.Kind() {
+		case reflect.Int8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+			return FormatTimestamp
+		default:
+			return FormatDatetime
+		}
 	}
 	if strings.Contains(strings.ToLower(field.Name), "pass") {
-		return "password"
+		return FormatPassword
 	}
-	dataValue := reflect.Indirect(reflect.New(reflectType))
 	switch dataValue.Kind() {
 	case timeKind, timePtrKind:
-		format = "datetime"
+		format = FormatDatetime
 	case reflect.Bool:
-		format = "boolean"
+		format = FormatBoolean
 	case reflect.Int8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		format = "integer"
+		format = FormatInteger
 	case reflect.Float32, reflect.Float64:
-		format = "decimal"
+		format = FormatFloat
 	case reflect.Struct:
 		if _, ok := dataValue.Interface().(time.Time); ok {
-			format = "datetime"
+			format = FormatDatetime
 		}
 	default:
 		if field.Size >= 1024 {
-			format = "text"
+			format = FormatText
 		} else {
-			format = "string"
+			format = FormatString
 		}
 	}
 	return format

+ 21 - 0
schema.go

@@ -31,6 +31,27 @@ const (
 	LiveTypeCascader = "cascader"
 )
 
+const (
+	TypeInteger = "integer"
+	TypeFloat   = "float"
+	TypeBoolean = "boolean"
+	TypeString  = "string"
+)
+
+const (
+	FormatInteger   = "integer"
+	FormatFloat     = "float"
+	FormatBoolean   = "boolean"
+	FormatString    = "string"
+	FormatText      = "text"
+	FormatDropdown  = "dropdown"
+	FormatDatetime  = "datetime"
+	FormatDate      = "date"
+	FormatTime      = "time"
+	FormatTimestamp = "timestamp"
+	FormatPassword  = "password"
+)
+
 type (
 	LiveValue struct {
 		Enable  bool     `json:"enable"`