From de67c5dc465569433d0bd7fd6856eab22060258c Mon Sep 17 00:00:00 2001 From: linwenxiang <991154416@qq.com> Date: Thu, 27 Aug 2020 21:44:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81search?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apis/sysjob/sysjob.go | 19 ++++--- dto/sysjob.go | 10 ++++ models/sysjob.go | 48 ++++++++--------- pkg/search/condition.go | 111 ++++++++++++++++++++++++++++++++++++++++ pkg/search/query.go | 104 +++++++++++++++++++++++++++++++++++++ tools/dto.go | 48 +++++++++++++++++ 6 files changed, 310 insertions(+), 30 deletions(-) create mode 100644 dto/sysjob.go create mode 100644 pkg/search/condition.go create mode 100644 pkg/search/query.go create mode 100644 tools/dto.go diff --git a/apis/sysjob/sysjob.go b/apis/sysjob/sysjob.go index 5c487cdd..da22ecc2 100644 --- a/apis/sysjob/sysjob.go +++ b/apis/sysjob/sysjob.go @@ -2,6 +2,7 @@ package sysjob import ( "github.com/gin-gonic/gin" + "go-admin/dto" "go-admin/jobs" "go-admin/models" "go-admin/tools" @@ -23,15 +24,19 @@ func GetSysJobList(c *gin.Context) { pageIndex = tools.StrToInt(err, index) } - data.JobId, _ = tools.StringToInt(c.Request.FormValue("jobId")) - data.JobName = c.Request.FormValue("jobName") - data.JobGroup = c.Request.FormValue("jobGroup") - data.CronExpression = c.Request.FormValue("cronExpression") - data.InvokeTarget = c.Request.FormValue("invokeTarget") - data.Status, _ = tools.StringToInt(c.Request.FormValue("status")) + var v dto.SysJobSearch + err = c.Bind(&v) + tools.HasError(err, "数据解析失败", 422) + + //data.JobId, _ = tools.StringToInt(c.Request.FormValue("jobId")) + //data.JobName = c.Request.FormValue("jobName") + //data.JobGroup = c.Request.FormValue("jobGroup") + //data.CronExpression = c.Request.FormValue("cronExpression") + //data.InvokeTarget = c.Request.FormValue("invokeTarget") + //data.Status, _ = tools.StringToInt(c.Request.FormValue("status")) data.DataScope = tools.GetUserIdStr(c) - result, count, err := data.GetPage(pageSize, pageIndex) + result, count, err := data.GetPage(pageSize, pageIndex, v) tools.HasError(err, "", -1) app.PageOK(c, result, count, pageIndex, pageSize, "") diff --git a/dto/sysjob.go b/dto/sysjob.go new file mode 100644 index 00000000..149ed54a --- /dev/null +++ b/dto/sysjob.go @@ -0,0 +1,10 @@ +package dto + +type SysJobSearch struct { + JobId int `form:"jobId" search:"type:exact;column:job_id;table:sys_job"` + JobName string `form:"jobName" search:"type:icontains;column:job_name;table:sys_job"` + JobGroup string `form:"jobGroup" search:"type:exact;column:job_group;table:sys_job"` + CronExpression string `form:"cronExpression" search:"type:exact;column:cron_expression;table:sys_job"` + InvokeTarget string `form:"invokeTarget" search:"type:exact;column:invoke_target;table:sys_job"` + Status int `form:"status" search:"type:exact;column:status;table:sys_job"` +} diff --git a/models/sysjob.go b/models/sysjob.go index 26847be9..7b74f4c8 100644 --- a/models/sysjob.go +++ b/models/sysjob.go @@ -75,34 +75,36 @@ func (e *SysJob) Get() (SysJob, error) { } // 获取SysJob带分页 -func (e *SysJob) GetPage(pageSize int, pageIndex int) ([]SysJob, int, error) { +func (e *SysJob) GetPage(pageSize int, pageIndex int, v interface{}) ([]SysJob, int, error) { var doc []SysJob table := orm.Eloquent.Select("*").Table(e.TableName()) - if e.JobId != 0 { - table = table.Where("job_id = ?", e.JobId) - } + table = tools.SetQuery(table, v) - if e.JobName != "" { - table = table.Where("job_name like ?", "%"+e.JobName+"%") - } - - if e.JobGroup != "" { - table = table.Where("job_group = ?", e.JobGroup) - } - - if e.CronExpression != "" { - table = table.Where("cron_expression = ?", e.CronExpression) - } - - if e.InvokeTarget != "" { - table = table.Where("invoke_target = ?", e.InvokeTarget) - } - - if e.Status != 0 { - table = table.Where("status = ?", e.Status) - } + //if e.JobId != 0 { + // table = table.Where("job_id = ?", e.JobId) + //} + // + //if e.JobName != "" { + // table = table.Where("job_name like ?", "%"+e.JobName+"%") + //} + // + //if e.JobGroup != "" { + // table = table.Where("job_group = ?", e.JobGroup) + //} + // + //if e.CronExpression != "" { + // table = table.Where("cron_expression = ?", e.CronExpression) + //} + // + //if e.InvokeTarget != "" { + // table = table.Where("invoke_target = ?", e.InvokeTarget) + //} + // + //if e.Status != 0 { + // table = table.Where("status = ?", e.Status) + //} // 数据权限控制(如果不需要数据权限请将此处去掉) dataPermission := new(DataPermission) diff --git a/pkg/search/condition.go b/pkg/search/condition.go new file mode 100644 index 00000000..f556c588 --- /dev/null +++ b/pkg/search/condition.go @@ -0,0 +1,111 @@ +package search + +import "strings" + +type Condition interface { + SetWhere(k string, v []interface{}) + SetOr(k string, v []interface{}) + SetOrder(k string) + SetJoinOn(t, on string) Condition +} + +type GormCondition struct { + GormPublic + Join []*GormJoin +} + +type GormPublic struct { + Where map[string][]interface{} + Order []string + Or map[string][]interface{} +} + +type GormJoin struct { + Type string + JoinOn string + GormPublic +} + +func (e *GormJoin) SetJoinOn(t, on string) Condition { + return nil +} + +func (e *GormPublic) SetWhere(k string, v []interface{}) { + if e.Where == nil { + e.Where = make(map[string][]interface{}) + } + e.Where[k] = v +} + +func (e *GormPublic) SetOr(k string, v []interface{}) { + if e.Or == nil { + e.Or = make(map[string][]interface{}) + } + e.Or[k] = v +} + +func (e *GormPublic) SetOrder(k string) { + if e.Order == nil { + e.Order = make([]string, 0) + } + e.Order = append(e.Order, k) +} + +func (e *GormCondition) SetJoinOn(t, on string) Condition { + if e.Join == nil { + e.Join = make([]*GormJoin, 0) + } + join := &GormJoin{ + Type: t, + JoinOn: on, + GormPublic: GormPublic{}, + } + e.Join = append(e.Join, join) + return join +} + +type resolveSearchTag struct { + Type string + Column string + Table string + On []string + Join string +} + +/** + * 解析search的tag标签 + */ +func resolveTagValue(tag string) resolveSearchTag { + var r resolveSearchTag + tags := strings.Split(tag, ";") + var ts []string + for _, t := range tags { + ts = strings.Split(t, ":") + if len(ts) == 0 { + continue + } + switch ts[0] { + case "type": + if len(ts) > 1 { + r.Type = ts[1] + } + case "column": + if len(ts) > 1 { + r.Column = ts[1] + } + case "table": + if len(ts) > 1 { + r.Table = ts[1] + } + case "on": + if len(ts) > 1 { + r.On = ts[1:] + } + case "join": + if len(ts) > 1 { + r.Join = ts[1] + } + } + } + return r +} diff --git a/pkg/search/query.go b/pkg/search/query.go new file mode 100644 index 00000000..ecdf7e55 --- /dev/null +++ b/pkg/search/query.go @@ -0,0 +1,104 @@ +package search + +import ( + "fmt" + "reflect" + "strings" +) + +const ( + FromQueryTag = "search" + Mysql = "mysql" //mysql数据库标识 + Postgres = "postgres" //postgres数据库标识 +) + +/** + * exact / iexact 等于 + * contains / icontains 包含 + * gt / gte 大于 / 大于等于 + * lt / lte 小于 / 小于等于 + * startswith / istartswith 以…起始 + * endswith / iendswith 以…结束 + * in + * isnull + * order 排序 e.g. order[key]=desc order[key]=asc + */ +func ResolveSearchQuery(driver string, q interface{}, condition Condition) { + qType := reflect.TypeOf(q) + qValue := reflect.ValueOf(q) + var tag string + var ok bool + var t resolveSearchTag + for i := 0; i < qType.NumField(); i++ { + tag, ok = "", false + tag, ok = qType.Field(i).Tag.Lookup(FromQueryTag) + if !ok { + //递归调用 + ResolveSearchQuery(driver, qValue.Field(i).Interface(), condition) + continue + } + switch tag { + case "-": + continue + } + t = resolveTagValue(tag) + if qValue.Field(i).IsZero() { + continue + } + //解析 + switch t.Type { + case "left": + //左关联 + join := condition.SetJoinOn(t.Type, fmt.Sprintf( + "left join `%s` on `%s`.`%s` = `%s`.`%s`", + t.Join, + t.Join, + t.On[0], + t.Table, + t.On[1], + )) + ResolveSearchQuery(driver, qValue.Field(i).Interface(), join) + case "exact", "iexact": + condition.SetWhere(fmt.Sprintf("`%s`.`%s` = ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()}) + case "contains", "icontains": + //注意:mysql不支持ilike + if driver == Postgres && t.Type == "icontains" { + condition.SetWhere(fmt.Sprintf("`%s`.`%s` ilike ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"}) + } else { + condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"}) + } + case "gt": + condition.SetWhere(fmt.Sprintf("`%s`.`%s` > ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()}) + case "gte": + condition.SetWhere(fmt.Sprintf("`%s`.`%s` >= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()}) + case "lt": + condition.SetWhere(fmt.Sprintf("`%s`.`%s` < ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()}) + case "lte": + condition.SetWhere(fmt.Sprintf("`%s`.`%s` <= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()}) + case "startswith", "istartswith": + if driver == Postgres && t.Type == "istartswith" { + condition.SetWhere(fmt.Sprintf("`%s`.`%s` ilike ?", t.Table, t.Column), []interface{}{qValue.Field(i).String() + "%"}) + } else { + condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{qValue.Field(i).String() + "%"}) + } + case "endswith", "iendswith": + if driver == Postgres && t.Type == "iendswith" { + condition.SetWhere(fmt.Sprintf("`%s`.`%s` ilike ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String()}) + } else { + condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String()}) + } + case "in": + condition.SetWhere(fmt.Sprintf("`%s`.`%s` in (?)", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()}) + case "isnull": + if !(qValue.Field(i).IsZero() && qValue.Field(i).IsNil()) { + condition.SetWhere(fmt.Sprintf("`%s`.`%s` isnull", t.Table, t.Column), make([]interface{}, 0)) + } + case "order": + switch strings.ToLower(qValue.Field(i).String()) { + case "desc", "asc": + condition.SetOrder(fmt.Sprintf("`%s`.`%s` %s", t.Table, t.Column, qValue.Field(i).String())) + } + } + } + //return condition, order +} diff --git a/tools/dto.go b/tools/dto.go new file mode 100644 index 00000000..0a55aae6 --- /dev/null +++ b/tools/dto.go @@ -0,0 +1,48 @@ +package tools + +import ( + "go-admin/pkg/search" + "go-admin/tools/config" + + "gorm.io/gorm" +) + +type GeneralDelDto struct { + Id string `uri:"id" json:"id" validate:"required"` +} +type GeneralGetDto struct { + Id string `uri:"id" json:"id" validate:"required"` +} + +func SetQuery(db *gorm.DB, q interface{}) *gorm.DB { + condition := &search.GormCondition{ + GormPublic: search.GormPublic{}, + Join: make([]*search.GormJoin, 0), + } + search.ResolveSearchQuery(config.DatabaseConfig.Driver, q, condition) + for _, join := range condition.Join { + if join == nil { + continue + } + db = db.Joins(join.JoinOn) + for k, v := range join.Where { + db = db.Where(k, v...) + } + for k, v := range join.Or { + db = db.Or(k, v...) + } + for _, o := range join.Order { + db = db.Order(o) + } + } + for k, v := range condition.Where { + db = db.Where(k, v...) + } + for k, v := range condition.Or { + db = db.Or(k, v...) + } + for _, o := range condition.Order { + db = db.Order(o) + } + return db +}