Browse Source

实现模型动态添加

fancl 2 years ago
parent
commit
8429425603
3 changed files with 75 additions and 24 deletions
  1. 55 20
      api.go
  2. 6 2
      crud.go
  3. 14 2
      instance.go

+ 55 - 20
api.go

@@ -9,7 +9,10 @@ import (
 
 type (
 	Api struct {
-		crud *CRUD
+		crud       *CRUD
+		svr        *http.Server
+		exists     []string
+		middleware []http.Middleware
 	}
 
 	feedRequest struct {
@@ -143,6 +146,9 @@ func (api *Api) handleFeed(httpCtx *http.Context) (err error) {
 	if err = httpCtx.Bind(req); err != nil {
 		return httpCtx.Error(HttpInvalidPayload, err.Error())
 	}
+	if !api.isExists(req.TableName + "@" + req.ModuleName) {
+		return httpCtx.Error(HTTPUnknownFailed, fmt.Sprintf("model %s not register", req.TableName))
+	}
 	result := make([]feedResponse, 0, 10)
 	query := api.crud.db.Table(req.TableName).Select(req.LabelField+" AS label", req.ValueField+" AS value")
 	if req.Condition != "" {
@@ -158,31 +164,60 @@ func (api *Api) handleFeed(httpCtx *http.Context) (err error) {
 	}
 }
 
+func (api *Api) isExists(id string) bool {
+	if api.exists == nil {
+		return false
+	}
+	for _, s := range api.exists {
+		if s == id {
+			return true
+		}
+	}
+	return false
+}
+
+func (api *Api) Attach(rest *Restful, ms ...http.Middleware) {
+	if api.svr == nil {
+		return
+	}
+	id := rest.model.TableName() + "@" + rest.model.ModuleName()
+	if api.isExists(id) {
+		return
+	}
+	if len(ms) == 0 {
+		ms = api.middleware
+	}
+	if rest.hasScenario(ScenarioList) {
+		api.svr.Handle("GET", rest.getScenarioUrl(ScenarioList), rest.getScenarioHandle(ScenarioList), ms...)
+	}
+	if rest.hasScenario(ScenarioCreate) {
+		api.svr.Handle("POST", rest.getScenarioUrl(ScenarioCreate), rest.getScenarioHandle(ScenarioCreate), ms...)
+	}
+	if rest.hasScenario(ScenarioUpdate) {
+		api.svr.Handle("PUT", rest.getScenarioUrl(ScenarioUpdate), rest.getScenarioHandle(ScenarioUpdate), ms...)
+	}
+	if rest.hasScenario(ScenarioDelete) {
+		api.svr.Handle("DELETE", rest.getScenarioUrl(ScenarioDelete), rest.getScenarioHandle(ScenarioDelete), ms...)
+	}
+	if rest.hasScenario(ScenarioExport) {
+		api.svr.Handle("GET", rest.getScenarioUrl(ScenarioExport), rest.getScenarioHandle(ScenarioExport), ms...)
+	}
+	if rest.hasScenario(ScenarioView) {
+		api.svr.Handle("GET", rest.getScenarioUrl(ScenarioView), rest.getScenarioHandle(ScenarioView), ms...)
+	}
+	api.exists = append(api.exists, id)
+}
+
 func (api *Api) Router(svr *http.Server, ms ...http.Middleware) {
+	api.svr = svr
+	api.middleware = ms
 	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...)
-
+	api.exists = make([]string, 0, 10)
 	for _, rest := range api.crud.modules {
-		if rest.hasScenario(ScenarioList) {
-			svr.Handle("GET", rest.getScenarioUrl(ScenarioList), rest.getScenarioHandle(ScenarioList), ms...)
-		}
-		if rest.hasScenario(ScenarioCreate) {
-			svr.Handle("POST", rest.getScenarioUrl(ScenarioCreate), rest.getScenarioHandle(ScenarioCreate), ms...)
-		}
-		if rest.hasScenario(ScenarioUpdate) {
-			svr.Handle("PUT", rest.getScenarioUrl(ScenarioUpdate), rest.getScenarioHandle(ScenarioUpdate), ms...)
-		}
-		if rest.hasScenario(ScenarioDelete) {
-			svr.Handle("DELETE", rest.getScenarioUrl(ScenarioDelete), rest.getScenarioHandle(ScenarioDelete), ms...)
-		}
-		if rest.hasScenario(ScenarioExport) {
-			svr.Handle("GET", rest.getScenarioUrl(ScenarioExport), rest.getScenarioHandle(ScenarioExport), ms...)
-		}
-		if rest.hasScenario(ScenarioView) {
-			svr.Handle("GET", rest.getScenarioUrl(ScenarioView), rest.getScenarioHandle(ScenarioView), ms...)
-		}
+		api.Attach(rest, ms...)
 	}
 }

+ 6 - 2
crud.go

@@ -88,7 +88,7 @@ func (r *CRUD) RegisterDelegate(d Delegate) {
 	r.delegate.Register(d)
 }
 
-//Attach 注册一个
+//Attach 注册一个模型
 func (r *CRUD) Attach(ctx context.Context, model Model, cbs ...Option) (err error) {
 	var (
 		opts *Options
@@ -108,7 +108,11 @@ func (r *CRUD) Attach(ctx context.Context, model Model, cbs ...Option) (err erro
 	}
 	opts.Delegate = r.delegate
 	opts.LookupFunc = r.VisibleSchemas
-	r.modules = append(r.modules, newRestful(model, opts))
+	rt := newRestful(model, opts)
+	r.modules = append(r.modules, rt)
+	if r.api != nil {
+		r.api.Attach(rt)
+	}
 	return
 }
 

+ 14 - 2
instance.go

@@ -31,13 +31,24 @@ func DB() (db *gorm.DB, err error) {
 	return std.db, nil
 }
 
-func Attach(ctx context.Context, model Model, cbs ...Option) (err error) {
+//WithDelegate 添加一个观察者
+func WithDelegate(ctx context.Context, d Delegate) (err error) {
+	if std == nil {
+		return ErrUninitializedComponent
+	}
+	std.RegisterDelegate(d)
+	return nil
+}
+
+//AttachModel 添加一个模块
+func AttachModel(ctx context.Context, model Model, cbs ...Option) (err error) {
 	if std == nil {
 		return ErrUninitializedComponent
 	}
 	return std.Attach(ctx, model, cbs...)
 }
 
+//GetSchemas 获取模块的schema
 func GetSchemas(ctx context.Context, model Model) ([]*Schema, error) {
 	if std == nil {
 		return nil, ErrUninitializedComponent
@@ -45,7 +56,8 @@ func GetSchemas(ctx context.Context, model Model) ([]*Schema, error) {
 	return std.GetSchemas(ctx, DefaultNamespace, model.ModuleName(), model.TableName())
 }
 
-func Router(hs *http.Server, ms ...http.Middleware) (err error) {
+//UseRouter 绑定路由
+func UseRouter(hs *http.Server, ms ...http.Middleware) (err error) {
 	if std == nil {
 		return ErrUninitializedComponent
 	}