diff --git a/config/reader/json/json.go b/config/reader/json/json.go
index 588258f5..9150ae96 100644
--- a/config/reader/json/json.go
+++ b/config/reader/json/json.go
@@ -4,11 +4,11 @@ import (
 	"errors"
 	"time"
 
+	"dario.cat/mergo"
 	"github.com/go-admin-team/go-admin-core/config/encoder"
 	"github.com/go-admin-team/go-admin-core/config/encoder/json"
 	"github.com/go-admin-team/go-admin-core/config/reader"
 	"github.com/go-admin-team/go-admin-core/config/source"
-	"github.com/imdario/mergo"
 )
 
 const readerTyp = "json"
diff --git a/config/source/env/env.go b/config/source/env/env.go
index bdabcfc5..a5a588c6 100644
--- a/config/source/env/env.go
+++ b/config/source/env/env.go
@@ -6,8 +6,8 @@ import (
 	"strings"
 	"time"
 
+	"dario.cat/mergo"
 	"github.com/go-admin-team/go-admin-core/config/source"
-	"github.com/imdario/mergo"
 )
 
 var (
@@ -117,15 +117,16 @@ func (e *env) String() string {
 // Underscores are delimiters for nesting, and all keys are lowercased.
 //
 // Example:
-//      "DATABASE_SERVER_HOST=localhost" will convert to
 //
-//      {
-//          "database": {
-//              "server": {
-//                  "host": "localhost"
-//              }
-//          }
-//      }
+//	"DATABASE_SERVER_HOST=localhost" will convert to
+//
+//	{
+//	    "database": {
+//	        "server": {
+//	            "host": "localhost"
+//	        }
+//	    }
+//	}
 func NewSource(opts ...source.Option) source.Source {
 	options := source.NewOptions(opts...)
 
diff --git a/config/source/flag/flag.go b/config/source/flag/flag.go
index cd233e2d..acb36cca 100644
--- a/config/source/flag/flag.go
+++ b/config/source/flag/flag.go
@@ -1,10 +1,10 @@
 package flag
 
 import (
+	"dario.cat/mergo"
 	"errors"
 	"flag"
 	"github.com/go-admin-team/go-admin-core/config/source"
-	"github.com/imdario/mergo"
 	"strings"
 	"time"
 )
@@ -89,13 +89,14 @@ func (fs *flagsrc) String() string {
 // Hyphens are delimiters for nesting, and all keys are lowercased.
 //
 // Example:
-//      dbhost := flag.String("database-host", "localhost", "the db host name")
 //
-//      {
-//          "database": {
-//              "host": "localhost"
-//          }
-//      }
+//	dbhost := flag.String("database-host", "localhost", "the db host name")
+//
+//	{
+//	    "database": {
+//	        "host": "localhost"
+//	    }
+//	}
 func NewSource(opts ...source.Option) source.Source {
 	return &flagsrc{opts: source.NewOptions(opts...)}
 }
diff --git a/debug/writer/file.go b/debug/writer/file.go
index eafb2aa7..2a8bb8ed 100644
--- a/debug/writer/file.go
+++ b/debug/writer/file.go
@@ -14,6 +14,8 @@ import (
 // 用于文件名称格式
 const timeFormat = "2006-01-02"
 
+const MB = 1024 * 1024
+
 // FileWriter 文件写入结构体
 type FileWriter struct {
 	file         *os.File
@@ -78,9 +80,9 @@ func (p *FileWriter) write() {
 func (p *FileWriter) checkFile() {
 	info, _ := p.file.Stat()
 	if strings.Index(p.file.Name(), time.Now().Format(timeFormat)) < 0 ||
-		(p.opts.cap > 0 && uint(info.Size()) > p.opts.cap) {
+		(p.opts.cap > 0 && uint(info.Size()) > p.opts.cap*MB) {
 		//生成新文件
-		if uint(info.Size()) > p.opts.cap {
+		if uint(info.Size()) > p.opts.cap*MB {
 			p.num++
 		} else {
 			p.num = 0
@@ -88,6 +90,34 @@ func (p *FileWriter) checkFile() {
 		filename := p.getFilename()
 		_ = p.file.Close()
 		p.file, _ = os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
+
+		dir := filepath.Dir(p.file.Name())
+		files, err := os.ReadDir(dir)
+		if err != nil {
+			fmt.Println("Error reading log directory:", err)
+			return
+		}
+
+		for _, file := range files {
+			if !file.IsDir() && strings.HasSuffix(file.Name(), p.opts.suffix) {
+				filePath := filepath.Join(dir, file.Name())
+				fileInfo, err := file.Info()
+				if err != nil {
+					fmt.Println("Error get Info file:", err)
+					break
+				}
+				fileModTime := fileInfo.ModTime()
+				daysSinceMod := uint(time.Since(fileModTime).Hours() / 24)
+				if daysSinceMod > p.opts.daysToKeep {
+					err := os.Remove(filePath)
+					if err != nil {
+						fmt.Println("Error deleting file:", err)
+					} else {
+						fmt.Println("Deleted file:", filePath)
+					}
+				}
+			}
+		}
 	}
 }
 
diff --git a/debug/writer/options.go b/debug/writer/options.go
index f745cfab..580a05ff 100644
--- a/debug/writer/options.go
+++ b/debug/writer/options.go
@@ -9,29 +9,31 @@ package writer
 
 // Options 可配置参数
 type Options struct {
-	path   string
-	suffix string //文件扩展名
-	cap    uint
+	path       string //文件路径
+	suffix     string //文件扩展名
+	daysToKeep uint   //保存天数
+	cap        uint   //文件大小
 }
 
 func setDefault() Options {
 	return Options{
-		path:   "/tmp/go-admin",
-		suffix: "log",
+		path:       "/tmp/go-admin",
+		suffix:     "log",
+		daysToKeep: 7,
 	}
 }
 
 // Option set options
 type Option func(*Options)
 
-// WithPath set path
+// WithPath 设置文件路径
 func WithPath(s string) Option {
 	return func(o *Options) {
 		o.path = s
 	}
 }
 
-// WithSuffix set suffix
+// WithSuffix 设置文件扩展名
 func WithSuffix(s string) Option {
 	return func(o *Options) {
 		o.suffix = s
@@ -44,3 +46,10 @@ func WithCap(n uint) Option {
 		o.cap = n
 	}
 }
+
+// WithDaysToKeep 设置文件保留天数
+func WithDaysToKeep(n uint) Option {
+	return func(o *Options) {
+		o.daysToKeep = n
+	}
+}
diff --git a/go.mod b/go.mod
index 258f930c..e968b8dc 100644
--- a/go.mod
+++ b/go.mod
@@ -1,84 +1,94 @@
 module github.com/go-admin-team/go-admin-core
 
-go 1.18
+go 1.21
 
 require (
-	github.com/BurntSushi/toml v0.3.1
-	github.com/bitly/go-simplejson v0.5.0
-	github.com/bsm/redislock v0.8.2
-	github.com/fsnotify/fsnotify v1.4.9
+	dario.cat/mergo v1.0.0
+	github.com/BurntSushi/toml v1.3.2
+	github.com/bitly/go-simplejson v0.5.1
+	github.com/bsm/redislock v0.9.4
+	github.com/fsnotify/fsnotify v1.7.0
 	github.com/ghodss/yaml v1.0.0
-	github.com/gin-gonic/gin v1.7.7
+	github.com/gin-gonic/gin v1.9.1
 	github.com/go-admin-team/redisqueue/v2 v2.0.0
-	github.com/go-redis/redis/v9 v9.0.0-rc.1
 	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
-	github.com/google/uuid v1.3.0
-	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
+	github.com/google/uuid v1.5.0
+	github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
-	github.com/imdario/mergo v0.3.9
-	github.com/json-iterator/go v1.1.11
-	github.com/nsqio/go-nsq v1.0.8
+	github.com/json-iterator/go v1.1.12
+	github.com/nsqio/go-nsq v1.1.0
 	github.com/pkg/errors v0.9.1
-	github.com/prometheus/client_golang v1.11.0
+	github.com/prometheus/client_golang v1.17.0
+	github.com/redis/go-redis/v9 v9.3.1
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
-	github.com/smartystreets/goconvey v1.6.4
-	github.com/spf13/cast v1.3.1
-	github.com/xuri/excelize/v2 v2.6.1
-	golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8
-	google.golang.org/grpc v1.29.1
-	google.golang.org/protobuf v1.28.0
-	gorm.io/driver/mysql v1.4.4
-	gorm.io/gorm v1.24.2
-	gorm.io/plugin/dbresolver v1.3.0
+	github.com/smartystreets/goconvey v1.8.1
+	github.com/spf13/cast v1.5.1
+	github.com/xuri/excelize/v2 v2.8.0
+	golang.org/x/crypto v0.14.0
+	google.golang.org/grpc v1.59.0
+	google.golang.org/protobuf v1.31.0
+	gorm.io/driver/mysql v1.5.2
+	gorm.io/gorm v1.25.5
+	gorm.io/plugin/dbresolver v1.4.7
 )
 
 require (
 	github.com/beorn7/perks v1.0.1 // indirect
-	github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
-	github.com/cespare/xxhash/v2 v2.1.2 // indirect
+	github.com/bytedance/sonic v1.10.2 // indirect
+	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
+	github.com/chenzhuoyu/iasm v0.9.0 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/fatih/color v1.7.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
 	github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f // indirect
-	github.com/go-playground/locales v0.13.0 // indirect
-	github.com/go-playground/universal-translator v0.17.0 // indirect
-	github.com/go-playground/validator/v10 v10.4.1 // indirect
-	github.com/go-sql-driver/mysql v1.6.0 // indirect
-	github.com/golang/protobuf v1.5.2 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.14.0 // indirect
+	github.com/go-sql-driver/mysql v1.7.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
+	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/golang/snappy v0.0.1 // indirect
-	github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
+	github.com/gopherjs/gopherjs v1.17.2 // indirect
+	github.com/imdario/mergo v0.3.7 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/jinzhu/now v1.1.5 // indirect
 	github.com/jtolds/gls v4.20.0+incompatible // indirect
 	github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
-	github.com/leodido/go-urn v1.2.0 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+	github.com/leodido/go-urn v1.2.4 // indirect
 	github.com/mattn/go-colorable v0.1.7 // indirect
-	github.com/mattn/go-isatty v0.0.12 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
 	github.com/mattn/goveralls v0.0.2 // indirect
-	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
+	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
-	github.com/modern-go/reflect2 v1.0.1 // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 	github.com/opentracing/opentracing-go v1.1.0 // indirect
-	github.com/prometheus/client_model v0.2.0 // indirect
-	github.com/prometheus/common v0.26.0 // indirect
-	github.com/prometheus/procfs v0.6.0 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
+	github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
+	github.com/prometheus/common v0.44.0 // indirect
+	github.com/prometheus/procfs v0.11.1 // indirect
 	github.com/richardlehane/mscfb v1.0.4 // indirect
 	github.com/richardlehane/msoleps v1.0.3 // indirect
-	github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
+	github.com/smarty/assertions v1.15.0 // indirect
 	github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df // indirect
-	github.com/ugorji/go/codec v1.1.7 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.11 // indirect
 	github.com/urfave/cli v1.20.0 // indirect
-	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
-	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
-	golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
-	golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect
-	golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
-	golang.org/x/text v0.3.7 // indirect
-	golang.org/x/tools v0.1.12 // indirect
-	google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
+	github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca // indirect
+	github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a // indirect
+	golang.org/x/arch v0.3.0 // indirect
+	golang.org/x/image v0.11.0 // indirect
+	golang.org/x/net v0.14.0 // indirect
+	golang.org/x/sys v0.13.0 // indirect
+	golang.org/x/text v0.13.0 // indirect
+	golang.org/x/tools v0.7.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
 	gopkg.in/AlecAivazis/survey.v1 v1.8.5 // indirect
 	gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/logger/default.go b/logger/default.go
index 1cb71dfe..51c7bffb 100644
--- a/logger/default.go
+++ b/logger/default.go
@@ -97,7 +97,7 @@ func (l *defaultLogger) logf(level Level, format string, v ...interface{}) {
 	fields := copyFields(l.opts.Fields)
 	l.RUnlock()
 
-	fields["level"] = level.String()
+	//fields["level"] = level.String()
 
 	if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok && level.String() == "error" {
 		fields["file"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line)
@@ -134,16 +134,16 @@ func (l *defaultLogger) logf(level Level, format string, v ...interface{}) {
 	if l.opts.Name != "" {
 		name = "[" + l.opts.Name + "]"
 	}
-	t := rec.Timestamp.Format("2006-01-02 15:04:05.000Z0700")
-	//fmt.Printf("%s\n", t)
-	//fmt.Printf("%s\n", name)
-	//fmt.Printf("%s\n", metadata)
-	//fmt.Printf("%v\n", rec.Message)
+	timeFormat := "2006-01-02 15:04:05"
+	if l.opts.TimeFormat != "" {
+		timeFormat = l.opts.TimeFormat
+	}
+	t := rec.Timestamp.Format(timeFormat)
 	logStr := ""
 	if name == "" {
-		logStr = fmt.Sprintf("%s %s %v\n", t, metadata, rec.Message)
+		logStr = fmt.Sprintf("%s %s %s %v\n", t, level.String(), metadata, rec.Message)
 	} else {
-		logStr = fmt.Sprintf("%s %s %s %v\n", name, t, metadata, rec.Message)
+		logStr = fmt.Sprintf("%s %s %s %s %v\n", name, t, level.String(), metadata, rec.Message)
 	}
 	_, err := l.opts.Out.Write([]byte(logStr))
 	if err != nil {
diff --git a/logger/options.go b/logger/options.go
index edfc41ce..dcfbfa0a 100644
--- a/logger/options.go
+++ b/logger/options.go
@@ -20,6 +20,8 @@ type Options struct {
 	Context context.Context
 	// Name logger name
 	Name string
+	// Timestamp.Format
+	TimeFormat string
 }
 
 // WithFields set default fields for the logger
@@ -29,6 +31,12 @@ func WithFields(fields map[string]interface{}) Option {
 	}
 }
 
+func RemoveFieldByKey(key string) Option {
+	return func(args *Options) {
+		delete(args.Fields, key)
+	}
+}
+
 // WithLevel set default level for the logger
 func WithLevel(level Level) Option {
 	return func(args *Options) {
@@ -57,6 +65,13 @@ func WithName(name string) Option {
 	}
 }
 
+// WithTimeFormat set time format for logger eg. 2006-01-02 15:04:05.000Z0700
+func WithTimeFormat(TimeFormat string) Option {
+	return func(args *Options) {
+		args.TimeFormat = TimeFormat
+	}
+}
+
 func SetOption(k, v interface{}) Option {
 	return func(o *Options) {
 		if o.Context == nil {
diff --git a/plugins/logger/logrus/go.mod b/plugins/logger/logrus/go.mod
index 5503fb31..5490be74 100644
--- a/plugins/logger/logrus/go.mod
+++ b/plugins/logger/logrus/go.mod
@@ -1,15 +1,12 @@
 module github.com/go-admin-team/go-admin-core/plugins/logger/logrus
 
-go 1.18
+go 1.21
 
 require (
-	github.com/go-admin-team/go-admin-core v1.3.11
-	github.com/sirupsen/logrus v1.8.0
+	github.com/go-admin-team/go-admin-core v1.5.2
+	github.com/sirupsen/logrus v1.9.3
 )
 
-require (
-	github.com/magefile/mage v1.10.0 // indirect
-	golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 // indirect
-)
+require golang.org/x/sys v0.15.0 // indirect
 
 //replace github.com/go-admin-team/go-admin-core => ../../../
diff --git a/plugins/logger/zap/go.mod b/plugins/logger/zap/go.mod
index 43ce2f8a..91daca07 100644
--- a/plugins/logger/zap/go.mod
+++ b/plugins/logger/zap/go.mod
@@ -1,10 +1,12 @@
 module github.com/go-admin-team/go-admin-core/plugins/logger/zap
 
-go 1.18
+go 1.21
 
 require (
-	github.com/go-admin-team/go-admin-core v1.3.11
-	go.uber.org/zap v1.10.0
+	github.com/go-admin-team/go-admin-core v1.5.2
+	go.uber.org/zap v1.26.0
 )
 
-//replace github.com/go-admin-team/go-admin-core => ../../../
+require go.uber.org/multierr v1.11.0 // indirect
+
+//replace github.com/go-admin-team/go-admin-core v1.3.11 => ../../../
diff --git a/plugins/logger/zap/zap_test.go b/plugins/logger/zap/zap_test.go
index 3e7fc442..8634578c 100644
--- a/plugins/logger/zap/zap_test.go
+++ b/plugins/logger/zap/zap_test.go
@@ -67,7 +67,7 @@ func TestFields(t *testing.T) {
 }
 
 func TestFile(t *testing.T) {
-	output, err := writer.NewFileWriter("testdata", "log")
+	output, err := writer.NewFileWriter(writer.WithPath("testdata"), writer.WithSuffix("log"))
 	if err != nil {
 		t.Errorf("logger setup error: %s", err.Error())
 	}
@@ -82,3 +82,18 @@ func TestFile(t *testing.T) {
 	fmt.Println(logger.DefaultLogger)
 	logger.DefaultLogger.Log(logger.InfoLevel, "hello")
 }
+
+//func TestFileKeep(t *testing.T) {
+//	output, err := writer.NewFileWriter(writer.WithPath("testdata"), writer.WithSuffix("log"))
+//	if err != nil {
+//		t.Errorf("logger setup error: %s", err.Error())
+//	}
+//	//var err error
+//	logger.DefaultLogger, err = NewLogger(logger.WithLevel(logger.TraceLevel), WithOutput(output))
+//	if err != nil {
+//		t.Errorf("logger setup error: %s", err.Error())
+//	}
+//
+//	fmt.Println(logger.DefaultLogger)
+//	logger.
+//}
diff --git a/sdk/config/application.go b/sdk/config/application.go
index af1402e2..bccd85b5 100644
--- a/sdk/config/application.go
+++ b/sdk/config/application.go
@@ -6,7 +6,6 @@ type Application struct {
 	Host          string
 	Port          int64
 	Name          string
-	JwtSecret     string
 	Mode          string
 	DemoMsg       string
 	EnableDP      bool
diff --git a/sdk/config/locker.go b/sdk/config/locker.go
index 5b1a335b..71a12d4c 100644
--- a/sdk/config/locker.go
+++ b/sdk/config/locker.go
@@ -3,7 +3,7 @@ package config
 import (
 	"github.com/go-admin-team/go-admin-core/storage"
 	"github.com/go-admin-team/go-admin-core/storage/locker"
-	"github.com/go-redis/redis/v9"
+	"github.com/redis/go-redis/v9"
 )
 
 var LockerConfig = new(Locker)
diff --git a/sdk/config/logger.go b/sdk/config/logger.go
index dbfc3b45..bfd061e4 100644
--- a/sdk/config/logger.go
+++ b/sdk/config/logger.go
@@ -3,12 +3,13 @@ package config
 import "github.com/go-admin-team/go-admin-core/sdk/pkg/logger"
 
 type Logger struct {
-	Type      string
-	Path      string
-	Level     string
-	Stdout    string
-	EnabledDB bool
-	Cap       uint
+	Type       string
+	Path       string
+	Level      string
+	Stdout     string
+	EnabledDB  bool
+	Cap        uint
+	DaysToKeep uint
 }
 
 // Setup 设置logger
@@ -19,6 +20,7 @@ func (e Logger) Setup() {
 		logger.WithLevel(e.Level),
 		logger.WithStdout(e.Stdout),
 		logger.WithCap(e.Cap),
+		logger.WithDaysToKeep(e.DaysToKeep),
 	)
 }
 
diff --git a/sdk/config/option_redis.go b/sdk/config/option_redis.go
index af6c5390..0490f9a4 100644
--- a/sdk/config/option_redis.go
+++ b/sdk/config/option_redis.go
@@ -5,9 +5,8 @@ import (
 	"crypto/tls"
 	"crypto/x509"
 	"fmt"
+	"github.com/redis/go-redis/v9"
 	"io/ioutil"
-
-	"github.com/go-redis/redis/v9"
 )
 
 var _redis *redis.Client
diff --git a/sdk/config/queue.go b/sdk/config/queue.go
index b4be3a4f..c137f66b 100644
--- a/sdk/config/queue.go
+++ b/sdk/config/queue.go
@@ -4,7 +4,7 @@ import (
 	"github.com/go-admin-team/go-admin-core/storage"
 	"github.com/go-admin-team/go-admin-core/storage/queue"
 	"github.com/go-admin-team/redisqueue/v2"
-	"github.com/go-redis/redis/v9"
+	"github.com/redis/go-redis/v9"
 	"time"
 )
 
diff --git a/sdk/go.mod b/sdk/go.mod
index 57e96de4..6287107a 100644
--- a/sdk/go.mod
+++ b/sdk/go.mod
@@ -1,107 +1,132 @@
 module github.com/go-admin-team/go-admin-core/sdk
 
-go 1.18
+go 1.21
 
 require (
-	github.com/bsm/redislock v0.8.2
-	github.com/bytedance/go-tagexpr/v2 v2.7.12
-	github.com/casbin/casbin/v2 v2.54.0
-	github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd
-	github.com/gin-gonic/gin v1.7.7
-	github.com/go-admin-team/go-admin-core v1.3.12-0.20221121065133-27b7dbe27a8f
-	github.com/go-admin-team/go-admin-core/plugins/logger/zap v0.0.0-20210610020726-2db73adb505d
+	github.com/bsm/redislock v0.9.4
+	github.com/bytedance/go-tagexpr/v2 v2.9.11
+	github.com/casbin/casbin/v2 v2.80.0
+	github.com/chanxuehong/wechat v0.0.0-20230222024006-36f0325263cd
+	github.com/gin-gonic/gin v1.9.1
+	github.com/go-admin-team/go-admin-core v1.5.2
+	github.com/go-admin-team/go-admin-core/plugins/logger/zap v1.5.2
 	github.com/go-admin-team/gorm-adapter/v3 v3.2.1-0.20210902112335-4148cb356a24
-	github.com/go-admin-team/redis-watcher/v2 v2.0.0-20221121052608-058cebff72c2
-	github.com/go-admin-team/redisqueue/v2 v2.0.0-20221119141731-97c556b0d5b7
-	github.com/go-playground/locales v0.13.0
-	github.com/go-playground/universal-translator v0.17.0
-	github.com/go-playground/validator/v10 v10.4.1
-	github.com/go-redis/redis/v9 v9.0.0-rc.1
-	github.com/golang-jwt/jwt/v4 v4.4.2
-	github.com/google/uuid v1.3.0
-	github.com/gorilla/websocket v1.4.2
-	github.com/mojocn/base64Captcha v1.3.1
-	github.com/nsqio/go-nsq v1.0.8
+	github.com/go-admin-team/redis-watcher/v2 v2.0.0-20231102130416-bfe327cac940
+	github.com/go-admin-team/redisqueue/v2 v2.0.1-0.20231102124201-508101cc789a
+	github.com/go-playground/locales v0.14.1
+	github.com/go-playground/universal-translator v0.18.1
+	github.com/go-playground/validator/v10 v10.15.5
+	github.com/golang-jwt/jwt/v4 v4.5.0
+	github.com/google/uuid v1.5.0
+	github.com/gorilla/websocket v1.5.0
+	github.com/mojocn/base64Captcha v1.3.6
+	github.com/nsqio/go-nsq v1.1.0
+	github.com/redis/go-redis/v9 v9.3.1
 	github.com/robfig/cron/v3 v3.0.1
 	github.com/shamsher31/goimgext v1.0.0
-	github.com/slok/go-http-metrics v0.9.0
-	github.com/smartystreets/goconvey v1.6.4
-	golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b
-	gorm.io/gorm v1.24.2
+	github.com/slok/go-http-metrics v0.11.0
+	github.com/smartystreets/goconvey v1.8.1
+	golang.org/x/crypto v0.14.0
+	gorm.io/gorm v1.25.5
 )
 
 require (
-	github.com/BurntSushi/toml v0.3.1 // indirect
-	github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
+	dario.cat/mergo v1.0.0 // indirect
+	github.com/AlecAivazis/survey/v2 v2.3.6 // indirect
+	github.com/BurntSushi/toml v1.3.2 // indirect
+	github.com/Masterminds/goutils v1.1.1 // indirect
+	github.com/Masterminds/semver/v3 v3.2.0 // indirect
+	github.com/Masterminds/sprig/v3 v3.2.3 // indirect
+	github.com/andeya/ameda v1.5.3 // indirect
+	github.com/andeya/goutil v1.0.1 // indirect
+	github.com/andygrunwald/go-jira v1.16.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
-	github.com/bitly/go-simplejson v0.5.0 // indirect
-	github.com/casbin/redis-watcher/v2 v2.3.0 // indirect
-	github.com/cespare/xxhash/v2 v2.1.2 // indirect
-	github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973 // indirect
+	github.com/bitly/go-simplejson v0.5.1 // indirect
+	github.com/bytedance/sonic v1.10.2 // indirect
+	github.com/casbin/govaluate v1.1.0 // indirect
+	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/chanxuehong/rand v0.0.0-20211009035549-2f07823e8e99 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
+	github.com/chenzhuoyu/iasm v0.9.0 // indirect
+	github.com/coreos/go-semver v0.3.1 // indirect
+	github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
-	github.com/fatih/color v1.7.0 // indirect
-	github.com/fsnotify/fsnotify v1.4.9 // indirect
+	github.com/fatih/color v1.15.0 // indirect
+	github.com/fatih/structs v1.1.0 // indirect
+	github.com/fsnotify/fsnotify v1.7.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
 	github.com/ghodss/yaml v1.0.0 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
-	github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f // indirect
-	github.com/go-redis/redis/v8 v8.11.5 // indirect
-	github.com/go-sql-driver/mysql v1.6.0 // indirect
+	github.com/git-chglog/git-chglog v0.15.4 // indirect
+	github.com/go-sql-driver/mysql v1.7.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
 	github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
 	github.com/golang-sql/sqlexp v0.1.0 // indirect
 	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
-	github.com/golang/protobuf v1.5.2 // indirect
-	github.com/golang/snappy v0.0.1 // indirect
-	github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
-	github.com/henrylee2cn/ameda v1.4.10 // indirect
-	github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect
-	github.com/imdario/mergo v0.3.9 // indirect
+	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/golang/snappy v0.0.4 // indirect
+	github.com/google/go-querystring v1.1.0 // indirect
+	github.com/gopherjs/gopherjs v1.17.2 // indirect
+	github.com/huandu/xstrings v1.3.3 // indirect
+	github.com/imdario/mergo v0.3.13 // indirect
 	github.com/jackc/chunkreader/v2 v2.0.1 // indirect
 	github.com/jackc/pgconn v1.13.0 // indirect
 	github.com/jackc/pgio v1.0.0 // indirect
 	github.com/jackc/pgpassfile v1.0.0 // indirect
 	github.com/jackc/pgproto3/v2 v2.3.1 // indirect
-	github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
+	github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
 	github.com/jackc/pgtype v1.12.0 // indirect
 	github.com/jackc/pgx/v4 v4.17.2 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/jinzhu/now v1.1.5 // indirect
-	github.com/json-iterator/go v1.1.11 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/jtolds/gls v4.20.0+incompatible // indirect
 	github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
-	github.com/leodido/go-urn v1.2.0 // indirect
-	github.com/mattn/go-colorable v0.1.7 // indirect
-	github.com/mattn/go-isatty v0.0.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+	github.com/kyokomi/emoji/v2 v2.2.11 // indirect
+	github.com/leodido/go-urn v1.2.4 // indirect
+	github.com/mattn/go-colorable v0.1.13 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
 	github.com/mattn/go-sqlite3 v1.14.15 // indirect
-	github.com/mattn/goveralls v0.0.2 // indirect
-	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
+	github.com/mattn/goveralls v0.0.12 // indirect
+	github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
 	github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
 	github.com/microsoft/go-mssqldb v0.17.0 // indirect
+	github.com/mitchellh/copystructure v1.0.0 // indirect
+	github.com/mitchellh/reflectwalk v1.0.0 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
-	github.com/modern-go/reflect2 v1.0.1 // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/nyaruka/phonenumbers v1.0.55 // indirect
+	github.com/pelletier/go-toml/v2 v2.1.0 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
-	github.com/prometheus/client_golang v1.11.0 // indirect
-	github.com/prometheus/client_model v0.2.0 // indirect
-	github.com/prometheus/common v0.26.0 // indirect
-	github.com/prometheus/procfs v0.6.0 // indirect
-	github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
-	github.com/spf13/cast v1.3.1 // indirect
+	github.com/prometheus/client_golang v1.17.0 // indirect
+	github.com/prometheus/client_model v0.5.0 // indirect
+	github.com/prometheus/common v0.45.0 // indirect
+	github.com/prometheus/procfs v0.12.0 // indirect
+	github.com/russross/blackfriday/v2 v2.1.0 // indirect
+	github.com/shopspring/decimal v1.2.0 // indirect
+	github.com/smarty/assertions v1.15.0 // indirect
+	github.com/spf13/cast v1.5.1 // indirect
+	github.com/trivago/tgo v1.0.7 // indirect
 	github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df // indirect
-	github.com/ugorji/go/codec v1.1.7 // indirect
-	github.com/urfave/cli v1.20.0 // indirect
-	go.uber.org/atomic v1.6.0 // indirect
-	go.uber.org/multierr v1.5.0 // indirect
-	go.uber.org/zap v1.13.0 // indirect
-	golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
-	golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect
-	golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
-	golang.org/x/text v0.3.7 // indirect
-	golang.org/x/tools v0.1.12 // indirect
-	google.golang.org/protobuf v1.28.0 // indirect
-	gopkg.in/AlecAivazis/survey.v1 v1.8.5 // indirect
-	gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.11 // indirect
+	github.com/urfave/cli/v2 v2.24.3 // indirect
+	github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
+	go.uber.org/multierr v1.11.0 // indirect
+	go.uber.org/zap v1.26.0 // indirect
+	golang.org/x/arch v0.3.0 // indirect
+	golang.org/x/image v0.13.0 // indirect
+	golang.org/x/mod v0.10.0 // indirect
+	golang.org/x/net v0.17.0 // indirect
+	golang.org/x/sys v0.13.0 // indirect
+	golang.org/x/term v0.13.0 // indirect
+	golang.org/x/text v0.13.0 // indirect
+	golang.org/x/tools v0.8.0 // indirect
+	google.golang.org/protobuf v1.31.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
-	gorm.io/driver/mysql v1.4.4 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+	gorm.io/driver/mysql v1.5.2 // indirect
 	gorm.io/driver/postgres v1.4.5 // indirect
 	gorm.io/driver/sqlite v1.4.3 // indirect
 	gorm.io/driver/sqlserver v1.4.1 // indirect
diff --git a/sdk/pkg/captcha/captcha.go b/sdk/pkg/captcha/captcha.go
index af359e81..491fcc5b 100644
--- a/sdk/pkg/captcha/captcha.go
+++ b/sdk/pkg/captcha/captcha.go
@@ -12,7 +12,7 @@ func SetStore(s base64Captcha.Store) {
 	base64Captcha.DefaultMemStore = s
 }
 
-//configJsonBody json request body.
+// configJsonBody json request body.
 type configJsonBody struct {
 	Id            string
 	CaptchaType   string
@@ -24,22 +24,22 @@ type configJsonBody struct {
 	DriverDigit   *base64Captcha.DriverDigit
 }
 
-func DriverStringFunc() (id, b64s string, err error) {
+func DriverStringFunc() (id, b64s, answer string, err error) {
 	e := configJsonBody{}
 	e.Id = uuid.New().String()
-	e.DriverString = base64Captcha.NewDriverString(46, 140, 2, 2, 4, "234567890abcdefghjkmnpqrstuvwxyz", &color.RGBA{240, 240, 246, 246}, []string{"wqy-microhei.ttc"})
+	e.DriverString = base64Captcha.NewDriverString(46, 140, 2, 2, 4, "234567890abcdefghjkmnpqrstuvwxyz", &color.RGBA{240, 240, 246, 246}, nil, []string{"wqy-microhei.ttc"})
 	driver := e.DriverString.ConvertFonts()
-	cap := base64Captcha.NewCaptcha(driver, base64Captcha.DefaultMemStore)
-	return cap.Generate()
+	captcha := base64Captcha.NewCaptcha(driver, base64Captcha.DefaultMemStore)
+	return captcha.Generate()
 }
 
-func DriverDigitFunc() (id, b64s string, err error) {
+func DriverDigitFunc() (id, b64s, answer string, err error) {
 	e := configJsonBody{}
 	e.Id = uuid.New().String()
 	e.DriverDigit = base64Captcha.NewDriverDigit(80, 240, 4, 0.7, 80)
 	driver := e.DriverDigit
-	cap := base64Captcha.NewCaptcha(driver, base64Captcha.DefaultMemStore)
-	return cap.Generate()
+	captcha := base64Captcha.NewCaptcha(driver, base64Captcha.DefaultMemStore)
+	return captcha.Generate()
 }
 
 // Verify 校验验证码
diff --git a/sdk/pkg/captcha/store.go b/sdk/pkg/captcha/store.go
index 707b1d4e..15142fe5 100644
--- a/sdk/pkg/captcha/store.go
+++ b/sdk/pkg/captcha/store.go
@@ -21,8 +21,8 @@ func NewCacheStore(cache storage.AdapterCache, expiration int) base64Captcha.Sto
 }
 
 // Set sets the digits for the captcha id.
-func (e *cacheStore) Set(id string, value string) {
-	_ = e.cache.Set(id, value, e.expiration)
+func (e *cacheStore) Set(id string, value string) error {
+	return e.cache.Set(id, value, e.expiration)
 }
 
 // Get returns stored digits for the captcha id. Clear indicates
@@ -38,7 +38,7 @@ func (e *cacheStore) Get(id string, clear bool) string {
 	return ""
 }
 
-//Verify captcha's answer directly
+// Verify captcha's answer directly
 func (e *cacheStore) Verify(id, answer string, clear bool) bool {
 	return e.Get(id, clear) == answer
 }
diff --git a/sdk/pkg/casbin/log.go b/sdk/pkg/casbin/log.go
index 6498c24d..b34e5b1f 100644
--- a/sdk/pkg/casbin/log.go
+++ b/sdk/pkg/casbin/log.go
@@ -1,9 +1,9 @@
 package mycasbin
 
 import (
-	"sync/atomic"
-
 	"github.com/go-admin-team/go-admin-core/logger"
+	"log/slog"
+	"sync/atomic"
 )
 
 // Logger is the implementation for a Logger using golang log.
@@ -11,6 +11,10 @@ type Logger struct {
 	enable int32
 }
 
+func (l *Logger) LogError(err error, msg ...string) {
+	slog.Error(err.Error(), msg, err)
+}
+
 // EnableLog controls whether print the message.
 func (l *Logger) EnableLog(enable bool) {
 	i := 0
diff --git a/sdk/pkg/casbin/mycasbin.go b/sdk/pkg/casbin/mycasbin.go
index e4f5bf93..7bf6309a 100644
--- a/sdk/pkg/casbin/mycasbin.go
+++ b/sdk/pkg/casbin/mycasbin.go
@@ -10,7 +10,7 @@ import (
 	"github.com/go-admin-team/go-admin-core/sdk"
 	"github.com/go-admin-team/go-admin-core/sdk/config"
 	redisWatcher "github.com/go-admin-team/redis-watcher/v2"
-	"github.com/go-redis/redis/v9"
+	"github.com/redis/go-redis/v9"
 	"gorm.io/gorm"
 
 	gormAdapter "github.com/go-admin-team/gorm-adapter/v3"
@@ -38,7 +38,7 @@ var (
 
 func Setup(db *gorm.DB, _ string) *casbin.SyncedEnforcer {
 	once.Do(func() {
-		Apter, err := gormAdapter.NewAdapterByDBUseTableName(db, "sys", "casbin_rule")
+		Apter, err := gormAdapter.NewAdapterByDBUseTableName(db, "", "casbin_rule")
 		if err != nil && err.Error() != "invalid DDL" {
 			panic(err)
 		}
diff --git a/sdk/pkg/logger/options.go b/sdk/pkg/logger/options.go
index 60395698..193df49a 100644
--- a/sdk/pkg/logger/options.go
+++ b/sdk/pkg/logger/options.go
@@ -55,3 +55,9 @@ func WithCap(n uint) Option {
 		o.cap = n
 	}
 }
+
+func WithDaysToKeep(n uint) Option {
+	return func(o *options) {
+		o.cap = n
+	}
+}
diff --git a/sdk/runtime/application.go b/sdk/runtime/application.go
index c8190308..306a2e36 100644
--- a/sdk/runtime/application.go
+++ b/sdk/runtime/application.go
@@ -14,21 +14,23 @@ import (
 )
 
 type Application struct {
-	dbs         map[string]*gorm.DB
-	casbins     map[string]*casbin.SyncedEnforcer
-	engine      http.Handler
-	crontab     map[string]*cron.Cron
-	mux         sync.RWMutex
-	middlewares map[string]interface{}
-	cache       storage.AdapterCache
-	queue       storage.AdapterQueue
-	locker      storage.AdapterLocker
-	memoryQueue storage.AdapterQueue
-	handler     map[string][]func(r *gin.RouterGroup, hand ...*gin.HandlerFunc)
-	routers     []Router
-	configs     map[string]interface{} // 系统参数
-	appRouters  []func()               // app路由
-
+	dbs           map[string]*gorm.DB
+	casbins       map[string]*casbin.SyncedEnforcer
+	engine        http.Handler
+	crontab       map[string]*cron.Cron
+	mux           sync.RWMutex
+	middlewares   map[string]interface{}
+	cache         storage.AdapterCache
+	queue         storage.AdapterQueue
+	locker        storage.AdapterLocker
+	memoryQueue   storage.AdapterQueue
+	handler       map[string][]func(r *gin.RouterGroup, hand ...*gin.HandlerFunc)
+	routers       []Router
+	configs       map[string]map[string]interface{} // 系统参数
+	appRouters    []func()                          // app路由
+	casbinExclude map[string]interface{}            // casbin排除
+	before        []func()                          // 启动前执行
+	app           map[string]interface{}            // app
 }
 
 type Router struct {
@@ -39,6 +41,62 @@ type Routers struct {
 	List []Router
 }
 
+func (e *Application) SetBefore(f func()) {
+	e.before = append(e.before, f)
+}
+
+func (e *Application) GetBefore() []func() {
+	return e.before
+}
+
+// SetCasbinExclude 设置对应key的Exclude
+func (e *Application) SetCasbinExclude(key string, list interface{}) {
+	e.mux.Lock()
+	defer e.mux.Unlock()
+	e.casbinExclude[key] = list
+}
+
+// GetCasbinExclude 获取所有map里的Exclude数据
+func (e *Application) GetCasbinExclude() map[string]interface{} {
+	e.mux.Lock()
+	defer e.mux.Unlock()
+	return e.casbinExclude
+}
+
+// GetCasbinExcludeByKey 根据key获取Exclude
+func (e *Application) GetCasbinExcludeByKey(key string) interface{} {
+	e.mux.Lock()
+	defer e.mux.Unlock()
+	if exclude, ok := e.casbinExclude["*"]; ok {
+		return exclude
+	}
+	return e.casbinExclude[key]
+}
+
+// SetApp 设置对应key的app
+func (e *Application) SetApp(key string, app interface{}) {
+	e.mux.Lock()
+	defer e.mux.Unlock()
+	e.app[key] = app
+}
+
+// GetApp 获取所有map里的app数据
+func (e *Application) GetApp() map[string]interface{} {
+	e.mux.Lock()
+	defer e.mux.Unlock()
+	return e.app
+}
+
+// GetAppByKey 根据key获取app
+func (e *Application) GetAppByKey(key string) interface{} {
+	e.mux.Lock()
+	defer e.mux.Unlock()
+	if app, ok := e.app["*"]; ok {
+		return app
+	}
+	return e.app[key]
+}
+
 // SetDb 设置对应key的db
 func (e *Application) SetDb(key string, db *gorm.DB) {
 	e.mux.Lock()
@@ -123,14 +181,15 @@ func (e *Application) GetLogger() logger.Logger {
 // NewConfig 默认值
 func NewConfig() *Application {
 	return &Application{
-		dbs:         make(map[string]*gorm.DB),
-		casbins:     make(map[string]*casbin.SyncedEnforcer),
-		crontab:     make(map[string]*cron.Cron),
-		middlewares: make(map[string]interface{}),
-		memoryQueue: queue.NewMemory(10000),
-		handler:     make(map[string][]func(r *gin.RouterGroup, hand ...*gin.HandlerFunc)),
-		routers:     make([]Router, 0),
-		configs:     make(map[string]interface{}),
+		dbs:           make(map[string]*gorm.DB),
+		casbins:       make(map[string]*casbin.SyncedEnforcer),
+		crontab:       make(map[string]*cron.Cron),
+		middlewares:   make(map[string]interface{}),
+		memoryQueue:   queue.NewMemory(10000),
+		handler:       make(map[string][]func(r *gin.RouterGroup, hand ...*gin.HandlerFunc)),
+		routers:       make([]Router, 0),
+		configs:       make(map[string]map[string]interface{}),
+		casbinExclude: make(map[string]interface{}),
 	}
 }
 
@@ -252,18 +311,35 @@ func (e *Application) GetMemoryQueue(prefix string) storage.AdapterQueue {
 	return NewQueue(prefix, e.memoryQueue)
 }
 
+// SetConfigByTenant 设置对应租户的config
+func (e *Application) SetConfigByTenant(tenant string, value map[string]interface{}) {
+	e.mux.Lock()
+	defer e.mux.Unlock()
+	e.configs[tenant] = value
+}
+
 // SetConfig 设置对应key的config
-func (e *Application) SetConfig(key string, value interface{}) {
+func (e *Application) SetConfig(tenant, key string, value interface{}) {
 	e.mux.Lock()
 	defer e.mux.Unlock()
-	e.configs[key] = value
+	if _, ok := e.configs[tenant]; !ok {
+		e.configs[tenant] = make(map[string]interface{})
+	}
+	e.configs[tenant][key] = value
 }
 
 // GetConfig 获取对应key的config
-func (e *Application) GetConfig(key string) interface{} {
+func (e *Application) GetConfig(tenant, key string) interface{} {
+	e.mux.Lock()
+	defer e.mux.Unlock()
+	return e.configs[tenant][key]
+}
+
+// GetConfigByTenant 获取对应租户的config
+func (e *Application) GetConfigByTenant(tenant string) interface{} {
 	e.mux.Lock()
 	defer e.mux.Unlock()
-	return e.configs[key]
+	return e.configs[tenant]
 }
 
 // SetAppRouters 设置app的路由
diff --git a/sdk/runtime/queue_test.go b/sdk/runtime/queue_test.go
index d68dd5bd..903fbc32 100644
--- a/sdk/runtime/queue_test.go
+++ b/sdk/runtime/queue_test.go
@@ -3,7 +3,7 @@ package runtime
 import (
 	"fmt"
 	"github.com/go-admin-team/redisqueue/v2"
-	"github.com/go-redis/redis/v9"
+	"github.com/redis/go-redis/v9"
 	"reflect"
 	"testing"
 	"time"
diff --git a/sdk/runtime/type.go b/sdk/runtime/type.go
index c44a9df0..74302ad9 100644
--- a/sdk/runtime/type.go
+++ b/sdk/runtime/type.go
@@ -17,6 +17,17 @@ type Runtime interface {
 	GetDb() map[string]*gorm.DB
 	GetDbByKey(key string) *gorm.DB
 
+	SetApp(key string, app interface{})
+	GetApp() map[string]interface{}
+	GetAppByKey(key string) interface{}
+
+	SetBefore(f func())
+	GetBefore() []func()
+
+	SetCasbinExclude(key string, list interface{})
+	GetCasbinExclude() map[string]interface{}
+	GetCasbinExcludeByKey(key string) interface{}
+
 	SetCasbin(key string, enforcer *casbin.SyncedEnforcer)
 	GetCasbin() map[string]*casbin.SyncedEnforcer
 	GetCasbinKey(key string) *casbin.SyncedEnforcer
@@ -61,8 +72,10 @@ type Runtime interface {
 
 	GetStreamMessage(id, stream string, value map[string]interface{}) (storage.Messager, error)
 
-	GetConfig(key string) interface{}
-	SetConfig(key string, value interface{})
+	GetConfigByTenant(tenant string) interface{}
+	GetConfig(tenant, key string) interface{}
+	SetConfigByTenant(tenant string, value map[string]interface{})
+	SetConfig(tenant, key string, value interface{})
 
 	// SetAppRouters set AppRouter
 	SetAppRouters(appRouters func())
diff --git a/storage/cache/redis.go b/storage/cache/redis.go
index 104a9d91..31412714 100644
--- a/storage/cache/redis.go
+++ b/storage/cache/redis.go
@@ -2,7 +2,7 @@ package cache
 
 import (
 	"context"
-	"github.com/go-redis/redis/v9"
+	"github.com/redis/go-redis/v9"
 	"time"
 )
 
diff --git a/storage/locker/redis.go b/storage/locker/redis.go
index 3e6742a8..2705b814 100644
--- a/storage/locker/redis.go
+++ b/storage/locker/redis.go
@@ -2,7 +2,7 @@ package locker
 
 import (
 	"context"
-	"github.com/go-redis/redis/v9"
+	"github.com/redis/go-redis/v9"
 	"time"
 
 	"github.com/bsm/redislock"
diff --git a/storage/queue/redis.go b/storage/queue/redis.go
index 36fccdf6..6b0ed843 100644
--- a/storage/queue/redis.go
+++ b/storage/queue/redis.go
@@ -3,7 +3,7 @@ package queue
 import (
 	"github.com/go-admin-team/go-admin-core/storage"
 	"github.com/go-admin-team/redisqueue/v2"
-	"github.com/go-redis/redis/v9"
+	"github.com/redis/go-redis/v9"
 )
 
 // NewRedis redis模式
diff --git a/storage/queue/redis_test.go b/storage/queue/redis_test.go
index 42a98e28..144e521c 100644
--- a/storage/queue/redis_test.go
+++ b/storage/queue/redis_test.go
@@ -3,7 +3,7 @@ package queue
 import (
 	"fmt"
 	"github.com/go-admin-team/redisqueue/v2"
-	"github.com/go-redis/redis/v9"
+	"github.com/redis/go-redis/v9"
 	"sync"
 	"testing"
 	"time"
diff --git a/tools/gorm/logger/logger.go b/tools/gorm/logger/logger.go
index 7964dc55..d578c453 100644
--- a/tools/gorm/logger/logger.go
+++ b/tools/gorm/logger/logger.go
@@ -138,18 +138,18 @@ func New(config logger.Config) logger.Interface {
 		infoStr      = "%s\n[info] "
 		warnStr      = "%s\n[warn] "
 		errStr       = "%s\n[error] "
-		traceStr     = "%s [%.3fms] [rows:%v] %s"
-		traceWarnStr = "%s %s [%.3fms] [rows:%v] %s"
-		traceErrStr  = "%s %s [%.3fms] [rows:%v] %s"
+		traceStr     = "%s\n[%.3fms] [rows:%v] %s\n"
+		traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s\n"
+		traceErrStr  = "%s %s\n[%.3fms] [rows:%v] %s\n"
 	)
 
 	if config.Colorful {
-		infoStr = Green + "%s " + Reset + Green + "[info] " + Reset
-		warnStr = BlueBold + "%s " + Reset + Magenta + "[warn] " + Reset
-		errStr = Magenta + "%s " + Reset + Red + "[error] " + Reset
-		traceStr = Green + "%s " + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
-		traceWarnStr = Green + "%s " + Yellow + "%s " + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset
-		traceErrStr = RedBold + "%s " + MagentaBold + "%s " + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
+		infoStr = Green + "%s\n" + Reset + Green + "[info] " + Reset
+		warnStr = BlueBold + "%s\n" + Reset + Magenta + "[warn] " + Reset
+		errStr = Magenta + "%s\n" + Reset + Red + "[error] " + Reset
+		traceStr = Green + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s\n"
+		traceWarnStr = Green + "%s " + Yellow + "%s\n" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset
+		traceErrStr = RedBold + "%s " + MagentaBold + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
 	}
 
 	return &gormLogger{
diff --git a/tools/search/query.go b/tools/search/query.go
index ff56f1ac..503768f2 100644
--- a/tools/search/query.go
+++ b/tools/search/query.go
@@ -34,10 +34,10 @@ func ResolveSearchQuery(driver string, q interface{}, condition Condition) {
 	var ok bool
 	var t *resolveSearchTag
 
-	var sep = "`"
-	if driver == Postgres {
-		sep = "\""
-	}
+	//var sep = "`"
+	//if driver == Postgres {
+	//	sep = "\""
+	//}
 
 	for i := 0; i < qType.NumField(); i++ {
 		tag, ok = "", false
@@ -74,6 +74,8 @@ func pgSql(driver string, t *resolveSearchTag, condition Condition, qValue refle
 		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 "glt":
+		condition.SetWhere(fmt.Sprintf("%s.%s <> ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
 	case "icontains":
 		condition.SetWhere(fmt.Sprintf("%s.%s ilike ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"})
 	case "contains":
diff --git a/tools/utils/excel.go b/tools/utils/excel.go
index 49e9db26..2e037aa7 100644
--- a/tools/utils/excel.go
+++ b/tools/utils/excel.go
@@ -11,9 +11,9 @@ var Cols = []string{"", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "
 
 // WriteXlsx 填充excel
 func WriteXlsx(sheet string, records interface{}) *excelize.File {
-	xlsx := excelize.NewFile()    // new file
-	index := xlsx.NewSheet(sheet) // new sheet
-	xlsx.SetActiveSheet(index)    // set active (default) sheet
+	xlsx := excelize.NewFile()       // new file
+	index, _ := xlsx.NewSheet(sheet) // new sheet
+	xlsx.SetActiveSheet(index)       // set active (default) sheet
 	t := reflect.TypeOf(records)
 
 	if t.Kind() != reflect.Slice {