diff --git a/middleware/apollo/search.go b/middleware/apollo/search.go index f067ce3..2b7072d 100644 --- a/middleware/apollo/search.go +++ b/middleware/apollo/search.go @@ -10,6 +10,12 @@ package apollo import ( "encoding/json" "errors" + "fmt" + "regexp" + "strings" + "sync" + + "git.zhangdeman.cn/zhangdeman/gopkg/convert" "git.zhangdeman.cn/zhangdeman/gopkg/util" ) @@ -29,8 +35,24 @@ const ( OperateLt = "lt" // OperateLte 小于等于 OperateLte = "lte" + // OperateTypeContains 包含 + OperateTypeContains = "contains" + // OperateTypeRegular 正则匹配 + OperateTypeRegular = "regular" ) +var ( + // hasCompilerRegula 已编译正则,不进行重复编辑 + hasCompilerRegula map[string]*regexp.Regexp + // regulaLock 编译正则用的锁 + regulaLock *sync.RWMutex +) + +func init() { + regulaLock = &sync.RWMutex{} + hasCompilerRegula = make(map[string]*regexp.Regexp) +} + // Rule 数据过滤规则 // // Author : go_developer@163.com<白茶清欢> @@ -95,5 +117,165 @@ func Search(key string, inputData map[string]interface{}, receiver interface{}) // // Date : 10:59 下午 2021/11/24 func checkRule(rule Rule, inputData map[string]interface{}) bool { + for _, cond := range rule.ConditionList { + val, exist := inputData[cond.InputKey] + if !exist { + // 输入的key 不存在, 不符合规则 + return false + } + switch cond.Operate { + case OperateTypeIs: + if !is(val, cond.TargetValue) { + return false + } + case OperateTypeIn: + if !in(val, cond.TargetValue) { + return false + } + case OperateTypeNotIn: + if !notIn(val, cond.TargetValue) { + return false + } + case OperateTypeContains: + if !contains(val, cond.TargetValue) { + return false + } + case OperateGt: + if !compareNumber(val, cond.TargetValue, OperateGt) { + return false + } + case OperateGte: + if !compareNumber(val, cond.TargetValue, OperateGte) { + return false + } + case OperateLt: + if !compareNumber(val, cond.TargetValue, OperateLt) { + return false + } + case OperateLte: + if !compareNumber(val, cond.TargetValue, OperateLte) { + return false + } + default: + return false + } + } return true } + +// is 判断是否相等 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:28 上午 2021/11/25 +func is(inputVal interface{}, targetValue string) bool { + return fmt.Sprintf("%v", inputVal) == targetValue +} + +// in ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:47 上午 2021/11/25 +func in(inputValue interface{}, targetValue string) bool { + if nil == inputValue { + return false + } + inputStr := fmt.Sprintf("%v", inputValue) + targetList := strings.Split(targetValue, ",") + for _, item := range targetList { + if inputStr == item { + return true + } + } + return false +} + +// notIn ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:47 上午 2021/11/25 +func notIn(inputValue interface{}, targetValue string) bool { + if nil == inputValue { + return false + } + inputStr := fmt.Sprintf("%v", inputValue) + targetList := strings.Split(targetValue, ",") + for _, item := range targetList { + if inputStr == item { + return false + } + } + return true +} + +// compareNumber ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:56 上午 2021/11/25 +func compareNumber(inputValue interface{}, targetValue string, operateType string) bool { + if inputValue == nil || len(targetValue) == 0 { + return false + } + var ( + err error + inputFloat float64 + targetFloat float64 + ) + if err = convert.ConvertAssign(&inputFloat, inputValue); nil != err { + return false + } + + if err = convert.ConvertAssign(&targetFloat, targetValue); nil != err { + return false + } + switch operateType { + case OperateGt: + return inputFloat > targetFloat + case OperateGte: + return inputFloat >= targetFloat + case OperateLt: + return inputFloat < targetFloat + case OperateLte: + return inputFloat <= targetFloat + } + return false +} + +// contains ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:03 下午 2021/11/25 +func contains(inputValue interface{}, targetValue string) bool { + return strings.Contains(fmt.Sprintf("%v", inputValue), targetValue) +} + +// regula 正则匹配 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:15 下午 2021/11/25 +func regula(inputValue interface{}, targetValue string) bool { + var ( + reg *regexp.Regexp + err error + ) + regulaLock.Lock() + if _, exist := hasCompilerRegula[targetValue]; !exist { + if reg, err = regexp.Compile(targetValue); nil != err { + regulaLock.Unlock() + return false + } + hasCompilerRegula[targetValue] = reg + } else { + reg = hasCompilerRegula[targetValue] + } + regulaLock.Unlock() + + // 判断是否匹配到数据 + result := reg.FindAllStringSubmatch(fmt.Sprintf("%v", inputValue), -1) + return len(result) > 0 +}