123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- package rest
- import (
- "fmt"
- "git.nspix.com/golang/micro/gateway/http"
- "git.nspix.com/golang/rest/v3/cache"
- "gorm.io/gorm"
- "time"
- )
- type (
- Api struct {
- crud *CRUD
- svr *http.Server
- exists []string
- middleware []http.Middleware
- }
- 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" yaml:"label"`
- Value interface{} `json:"value" yaml:"value"`
- }
- )
- func (f *feedRequest) cacheID() string {
- return "feed:" + f.ModuleName + f.TableName + f.ValueField + f.LabelField
- }
- func (api *Api) handleListSchema(httpCtx *http.Context) (err error) {
- var (
- schemas []*Schema
- )
- ns := httpCtx.FormValue(NamespaceVariable)
- if ns == "" {
- ns = DefaultNamespace
- }
- if schemas, err = api.crud.GetSchemas(httpCtx.Request().Context(), ns, httpCtx.ParamValue("module"), httpCtx.ParamValue("table")); err == nil {
- return httpCtx.Success(schemas)
- } else {
- return httpCtx.Error(HttpDatabaseQueryFailed, err.Error())
- }
- }
- //handleSaveSchema 保存schema
- func (api *Api) handleSaveSchema(httpCtx *http.Context) (err error) {
- var (
- rest *Restful
- )
- ns := httpCtx.FormValue(NamespaceVariable)
- if ns == "" {
- ns = DefaultNamespace
- }
- moduleName := httpCtx.ParamValue("module")
- tableName := httpCtx.ParamValue("table")
- for _, row := range api.crud.modules {
- if row.model.ModuleName() == moduleName && row.model.TableName() == tableName {
- rest = row
- break
- }
- }
- if rest == nil {
- return httpCtx.Error(HTTPUnknownFailed, fmt.Sprintf("module %s table %s schema not found", moduleName, tableName))
- }
- schemas := make([]*Schema, 0)
- if err = httpCtx.Bind(&schemas); err != nil {
- return httpCtx.Error(HttpInvalidPayload, err.Error())
- }
- if err = api.crud.db.Transaction(func(tx *gorm.DB) error {
- var (
- errTx error
- )
- for _, scm := range schemas {
- if errTx = tx.Save(scm).Error; errTx != nil {
- return errTx
- }
- }
- return nil
- }); err == nil {
- if api.crud.enableCache {
- cache.Delete(fmt.Sprintf("schema:%s:%s:%s", ns, moduleName, tableName))
- }
- return httpCtx.Success(map[string]interface{}{
- "count": len(schemas),
- "state": "success",
- })
- } else {
- return httpCtx.Error(HTTPUnknownFailed, err.Error())
- }
- }
- //handleListSchemas 查看表schema
- func (api *Api) handleListSchemas(httpCtx *http.Context) (err error) {
- var (
- moduleLabel string
- )
- ts := make([]*treeValue, 0)
- isHandled := false
- for _, e := range api.crud.modules {
- isHandled = false
- for _, tv := range ts {
- if tv.Value == e.model.ModuleName() {
- tv.Append(&treeValue{Value: e.model.TableName(), Label: e.model.TableName(), Type: TypeTable})
- isHandled = true
- break
- }
- }
- if isHandled {
- continue
- }
- moduleLabel = e.model.ModuleName()
- tv := &treeValue{Label: moduleLabel, Value: e.model.ModuleName(), Type: TypeModule}
- tv.Append(&treeValue{Value: e.model.TableName(), Label: e.model.TableName(), Type: TypeTable})
- ts = append(ts, tv)
- }
- return httpCtx.Success(ts)
- }
- //handleDeleteSchema 删除指定的表结构
- func (api *Api) handleDeleteSchema(httpCtx *http.Context) (err error) {
- id := httpCtx.ParamValue("id")
- model := &Schema{}
- if err = api.crud.db.Where("id=?", id).First(model).Error; err == nil {
- if err = api.crud.db.Where("id=?", id).Delete(&Schema{}).Error; err == nil {
- if api.crud.enableCache {
- cache.Delete(fmt.Sprintf("schema:%s:%s:%s", model.Namespace, model.ModuleName, model.TableName))
- }
- return httpCtx.Success(map[string]string{
- "id": id,
- "state": "success",
- })
- } else {
- return httpCtx.Error(HttpDatabaseDeleteFailed, err.Error())
- }
- } else {
- return httpCtx.Error(HttpDatabaseFindFailed, 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())
- }
- if !api.isExists(req.TableName + "@" + req.ModuleName) {
- return httpCtx.Error(HTTPUnknownFailed, fmt.Sprintf("model %s not register", req.TableName))
- }
- if api.crud.enableCache {
- if v, ok := cache.Get(req.cacheID()); ok {
- return httpCtx.Success(v)
- }
- }
- result := make([]map[string]interface{}, 0, 10)
- query := api.crud.db.Table(req.TableName).Select(req.LabelField, req.ValueField)
- if req.Condition != "" {
- query = query.Where(req.Condition)
- }
- if req.Limit > 0 {
- query = query.Limit(req.Limit)
- }
- if err = query.Scan(&result).Error; err == nil {
- feeds := make([]feedResponse, 0, len(result))
- for _, pairs := range result {
- feed := feedResponse{}
- for k, v := range pairs {
- if k == req.LabelField {
- feed.Label = v
- }
- if k == req.ValueField {
- feed.Value = v
- }
- }
- feeds = append(feeds, feed)
- }
- if api.crud.enableCache {
- cache.SetEx(req.cacheID(), feeds, time.Second*10)
- }
- return httpCtx.Success(feeds)
- } else {
- return httpCtx.Error(HttpDatabaseFindFailed, 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 {
- api.Attach(rest, ms...)
- }
- }
|