From 12bf36cd153eab7c420e422607213e1488a22f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=9F=E5=B8=85?= <133814250@qq.com> Date: Wed, 26 Jul 2023 16:49:09 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=9B=86=E7=BE=A4?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E6=94=AF=E6=8C=81=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E5=88=86=E7=BB=84=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=90=8E=E9=80=89=E9=A1=B9=E4=B8=8D=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/internal/consts/pubsub.go | 12 + server/internal/global/cluster.go | 60 ++ server/internal/global/global.go | 2 - server/internal/global/init.go | 3 + server/internal/library/hgrds/lock/consts.go | 59 ++ server/internal/library/hgrds/lock/lock.go | 155 ++++ .../internal/library/hgrds/lock/lock_test.go | 118 ++++ .../internal/library/hgrds/pubsub/publish.go | 16 + .../library/hgrds/pubsub/subscribe.go | 68 ++ .../library/network/tcp/client_cron.go | 3 + server/internal/library/queue/queue.go | 2 +- server/internal/logic/admin/member.go | 44 +- .../logic/middleware/limit_blacklist.go | 15 +- server/internal/logic/sys/blacklist.go | 34 +- server/internal/logic/sys/config.go | 39 +- server/internal/service/admin.go | 383 ++++++---- server/internal/service/sys.go | 668 +++++++++--------- server/manifest/config/config.example.yaml | 2 + web/src/views/system/cron/columns.ts | 8 +- web/src/views/system/cron/index.vue | 6 +- web/src/views/system/cron/modal/index.vue | 10 +- web/src/views/system/cron/modal/modal.vue | 7 +- 22 files changed, 1185 insertions(+), 529 deletions(-) create mode 100644 server/internal/consts/pubsub.go create mode 100644 server/internal/global/cluster.go create mode 100644 server/internal/library/hgrds/lock/consts.go create mode 100644 server/internal/library/hgrds/lock/lock.go create mode 100644 server/internal/library/hgrds/lock/lock_test.go create mode 100644 server/internal/library/hgrds/pubsub/publish.go create mode 100644 server/internal/library/hgrds/pubsub/subscribe.go diff --git a/server/internal/consts/pubsub.go b/server/internal/consts/pubsub.go new file mode 100644 index 0000000..eff5e9c --- /dev/null +++ b/server/internal/consts/pubsub.go @@ -0,0 +1,12 @@ +// Package consts +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2023 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +package consts + +const ( + ClusterSyncSysconfig = "cluster.sync.sysConfig" // 系统配置 + ClusterSyncSysBlacklist = "cluster.sync.sysBlacklist" // 系统黑名单 + ClusterSyncSysSuperAdmin = "cluster.sync.superAdmin" // 超管 +) diff --git a/server/internal/global/cluster.go b/server/internal/global/cluster.go new file mode 100644 index 0000000..0a2fe8f --- /dev/null +++ b/server/internal/global/cluster.go @@ -0,0 +1,60 @@ +// Package consts +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2023 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +package global + +import ( + "context" + "fmt" + "github.com/gogf/gf/v2/frame/g" + "hotgo/internal/consts" + "hotgo/internal/library/hgrds/lock" + "hotgo/internal/library/hgrds/pubsub" + "hotgo/internal/service" +) + +// SubscribeClusterSync 订阅集群同步,可以用来集中同步数据、状态等 +func SubscribeClusterSync(ctx context.Context) { + isCluster := g.Cfg().MustGet(ctx, "hotgo.isCluster").Bool() + if !isCluster { + return + } + + // 系统配置 + if err := pubsub.Subscribe(consts.ClusterSyncSysconfig, service.SysConfig().ClusterSync); err != nil { + g.Log().Fatal(ctx, err) + } + + // 系统黑名单 + if err := pubsub.Subscribe(consts.ClusterSyncSysBlacklist, service.SysBlacklist().ClusterSync); err != nil { + g.Log().Fatal(ctx, err) + } + + // 超管 + if err := pubsub.Subscribe(consts.ClusterSyncSysSuperAdmin, service.AdminMember().ClusterSyncSuperAdmin); err != nil { + g.Log().Fatal(ctx, err) + } + +} + +// PublishClusterSync 推送集群同步消息,如果没有开启集群部署,则不进行推送 +func PublishClusterSync(ctx context.Context, channel string, message interface{}) { + isCluster := g.Cfg().MustGet(ctx, "hotgo.isCluster").Bool() + if !isCluster { + return + } + + mutex := lock.Mutex(fmt.Sprintf("%s:%s", "lock", channel)) + if err := mutex.Lock(ctx); err != nil { + g.Log().Warningf(ctx, "PublishClusterSync %v lock err:%v", channel, err) + return + } + _ = mutex.Unlock(ctx) + + if _, err := pubsub.Publish(ctx, channel, message); err != nil { + g.Log().Warningf(ctx, "PublishClusterSync %v err:%v", channel, err) + } + return +} diff --git a/server/internal/global/global.go b/server/internal/global/global.go index 034132d..de88cb8 100644 --- a/server/internal/global/global.go +++ b/server/internal/global/global.go @@ -14,8 +14,6 @@ var ( RootPtah string // SysType 操作系统类型 windows | linux SysType = runtime.GOOS - // Blacklists 黑名单列表 - Blacklists map[string]struct{} // JaegerSwitch 链路追踪开关 JaegerSwitch bool ) diff --git a/server/internal/global/init.go b/server/internal/global/init.go index 0cc3c31..f0804c5 100644 --- a/server/internal/global/init.go +++ b/server/internal/global/init.go @@ -51,6 +51,9 @@ func Init(ctx context.Context) { // 加载超管数据 service.AdminMember().LoadSuperAdmin(ctx) + + // 订阅集群同步 + SubscribeClusterSync(ctx) } // LoggingServeLogHandler 服务日志处理 diff --git a/server/internal/library/hgrds/lock/consts.go b/server/internal/library/hgrds/lock/consts.go new file mode 100644 index 0000000..8d4df60 --- /dev/null +++ b/server/internal/library/hgrds/lock/consts.go @@ -0,0 +1,59 @@ +// Package lock +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2023 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +package lock + +import ( + "github.com/gogf/gf/v2/errors/gerror" + "time" +) + +const ( + // 加锁脚本 + lockScript = ` + local token = redis.call('get', KEYS[1]) + if token then + return 0 + else + local setResult = redis.call('setex', KEYS[1], ARGV[2], ARGV[1]) + return setResult + end +` + + // 续约脚本 + renewalScript = ` + if redis.call('get',KEYS[1])==ARGV[2] then + return redis.call('expire',KEYS[1],ARGV[1]) + end + return 0 +` + + // 解锁脚本 + unlockScript = ` + if redis.call("get",KEYS[1]) == ARGV[1] then + return redis.call("del",KEYS[1]) + else + return 2 + end +` +) + +const ( + // DefaultTTL 锁默认过期时间 + DefaultTTL = time.Second * 10 + // DefaultTryLockInterval 默认重试获取锁间隔时间 + DefaultTryLockInterval = time.Millisecond * 100 +) + +var ( + // ErrLockFailed 加锁失败 + ErrLockFailed = gerror.New("lock failed") + // ErrTimeout 加锁超时 + ErrTimeout = gerror.New("timeout") + // ErrNotCaller 锁持有者不是当前实例 + ErrNotCaller = gerror.New("lock not held by the caller") + // ErrNotExist 锁不存在 + ErrNotExist = gerror.New("lock does not exist") +) diff --git a/server/internal/library/hgrds/lock/lock.go b/server/internal/library/hgrds/lock/lock.go new file mode 100644 index 0000000..87c9e6a --- /dev/null +++ b/server/internal/library/hgrds/lock/lock.go @@ -0,0 +1,155 @@ +// Package lock +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2023 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +package lock + +// 分布式锁 + +import ( + "context" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/util/guid" + "sync" + "time" +) + +// Config 锁配置 +type Config struct { + ttl time.Duration // 过期时间 + tryLockInterval time.Duration // 重新获取锁间隔 +} + +// Lock 一把锁 不可重复使用 +type Lock struct { + resource string // 锁定的资源 + randomValue string // 随机值 + watchDog chan struct{} // 看门狗 + ttl time.Duration // 过期时间 + tryLockInterval time.Duration // 重新获取锁间隔 + wg sync.WaitGroup +} + +// NewConfig 初始化一个锁配置 +func NewConfig(ttl, tryLockInterval time.Duration) *Config { + return &Config{ + ttl: ttl, + tryLockInterval: tryLockInterval, + } +} + +// Mutex 根据配置创建一把锁 +func (lc *Config) Mutex(resource string) *Lock { + return &Lock{ + resource: resource, + randomValue: guid.S(), + watchDog: make(chan struct{}), + ttl: lc.ttl, + tryLockInterval: lc.tryLockInterval, + } +} + +// Lock 阻塞加锁 +func (l *Lock) Lock(ctx context.Context) error { + // 尝试加锁 + err := l.TryLock(ctx) + if err == nil { + return nil + } + if !gerror.Is(err, ErrLockFailed) { + return err + } + // 加锁失败,不断尝试 + ticker := time.NewTicker(l.tryLockInterval) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + // 超时 + return ErrTimeout + case <-ticker.C: + // 重新尝试加锁 + err = l.TryLock(ctx) + if err == nil { + return nil + } + if !gerror.Is(err, ErrLockFailed) { + return err + } + } + } +} + +// TryLock 尝试加锁,如果失败立即返回错误,而不会阻塞等待锁 +func (l *Lock) TryLock(ctx context.Context) error { + var args = []interface{}{l.randomValue, l.ttl.Seconds()} + eval, err := g.Redis().GroupScript().Eval(ctx, lockScript, 1, []string{l.resource}, args) + if err != nil { + return err + } + + if eval.String() != "OK" { + return ErrLockFailed + } + + go l.startWatchDog() + return nil +} + +// Unlock 解锁 +func (l *Lock) Unlock(ctx context.Context) error { + var args []interface{} + args = append(args, l.randomValue) + eval, err := g.Redis().GroupScript().Eval(ctx, unlockScript, 1, []string{l.resource}, args) + + if eval.Int() == 2 { + return ErrNotCaller + } + + if eval.Int() == 0 { + return ErrNotExist + } + + close(l.watchDog) + return err +} + +// startWatchDog 看门狗 +func (l *Lock) startWatchDog() { + resetTTLInterval := l.ttl / 3 + ticker := time.NewTicker(resetTTLInterval) + defer ticker.Stop() + + l.wg.Add(1) + defer l.wg.Wait() + + conn := g.Redis() + for { + select { + case <-ticker.C: + // 延长锁的过期时间 + ctx, cancel := context.WithTimeout(context.Background(), resetTTLInterval) + var args = []interface{}{l.ttl.Seconds(), l.randomValue} + eval, err := conn.GroupScript().Eval(ctx, renewalScript, 1, []string{l.resource}, args) + cancel() + + // 异常或锁已经不存在则不再续期 + if err != nil || eval.Int() < 1 { + return + } + case <-l.watchDog: + // 已经解锁 + return + } + } +} + +// defaultMutex 一个默认配置锁 +var defaultMutex = NewConfig(DefaultTTL, DefaultTryLockInterval) + +// Mutex 获取默认锁 +func Mutex(resource string) *Lock { + return defaultMutex.Mutex(resource) +} diff --git a/server/internal/library/hgrds/lock/lock_test.go b/server/internal/library/hgrds/lock/lock_test.go new file mode 100644 index 0000000..f338cba --- /dev/null +++ b/server/internal/library/hgrds/lock/lock_test.go @@ -0,0 +1,118 @@ +// Package lock_test +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2023 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +package lock_test + +import ( + "context" + "github.com/gogf/gf/v2/errors/gerror" + "hotgo/internal/library/hgrds/lock" + "sync" + "testing" + "time" +) + +func TestDefaultLock(t *testing.T) { + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + l := lock.Mutex("test") + err := l.TryLock(context.Background()) + if err != nil { + t.Error(err) + } + time.Sleep(lock.DefaultTTL) + err = l.Unlock(context.Background()) + if err != nil { + t.Error(err) + } + }() + + time.Sleep(time.Second) + + go func() { + defer wg.Done() + l := lock.Mutex("test") + err := l.TryLock(context.Background()) + if err != nil && !gerror.Is(err, lock.ErrLockFailed) { + t.Error(err) + } + }() + wg.Wait() +} + +func TestNewLock(t *testing.T) { + locker := lock.NewConfig(time.Second*30, time.Second) + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + l := locker.Mutex("test") + err := l.TryLock(context.Background()) + if err != nil { + t.Error(err) + } + time.Sleep(lock.DefaultTTL) + err = l.Unlock(context.Background()) + if err != nil { + t.Error(err) + } + }() + + time.Sleep(time.Second) + + go func() { + defer wg.Done() + l := lock.Mutex("test") + err := l.TryLock(context.Background()) + if err != nil && !gerror.Is(err, lock.ErrLockFailed) { + t.Error(err) + } + }() + wg.Wait() +} + +func TestNewLock2(t *testing.T) { + locker := lock.NewConfig(time.Second*30, time.Second) + var wg sync.WaitGroup + wg.Add(2) + count := 0 + times := 1000 + go func() { + defer wg.Done() + for i := 0; i < times; i++ { + l := locker.Mutex("test") + err := l.Lock(context.Background()) + if err != nil { + t.Error(err) + } + count++ + err = l.Unlock(context.Background()) + if err != nil { + t.Error(err) + } + } + }() + go func() { + defer wg.Done() + for i := 0; i < times; i++ { + l := lock.Mutex("test") + err := l.Lock(context.Background()) + if err != nil { + t.Error(err) + } + count++ + err = l.Unlock(context.Background()) + if err != nil { + t.Error(err) + } + } + }() + wg.Wait() + if count != times*2 { + t.Errorf("count = %d", count) + } +} diff --git a/server/internal/library/hgrds/pubsub/publish.go b/server/internal/library/hgrds/pubsub/publish.go new file mode 100644 index 0000000..e41a437 --- /dev/null +++ b/server/internal/library/hgrds/pubsub/publish.go @@ -0,0 +1,16 @@ +// Package pubsub +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2023 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +package pubsub + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" +) + +// Publish 推送消息 +func Publish(ctx context.Context, channel string, message interface{}) (int64, error) { + return g.Redis().Publish(ctx, channel, message) +} diff --git a/server/internal/library/hgrds/pubsub/subscribe.go b/server/internal/library/hgrds/pubsub/subscribe.go new file mode 100644 index 0000000..6977ca6 --- /dev/null +++ b/server/internal/library/hgrds/pubsub/subscribe.go @@ -0,0 +1,68 @@ +// Package pubsub +// @Link https://github.com/bufanyun/hotgo +// @Copyright Copyright (c) 2023 HotGo CLI +// @Author Ms <133814250@qq.com> +// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE +package pubsub + +import ( + "context" + "github.com/gogf/gf/v2/database/gredis" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" + "hotgo/utility/simple" + "sync" +) + +type SubHandler func(ctx context.Context, message *gredis.Message) + +type subscribeManager struct { + mutex sync.RWMutex + List map[string]SubHandler +} + +var subscribes = &subscribeManager{ + List: make(map[string]SubHandler), +} + +// Subscribe 订阅消息 +func Subscribe(channel string, hr SubHandler) (err error) { + subscribes.mutex.Lock() + defer subscribes.mutex.Unlock() + + if _, ok := subscribes.List[channel]; ok { + err = gerror.Newf("repeat the subscribe:%v register", channel) + return + } + subscribes.List[channel] = hr + go doSubscribe(channel, hr) + return +} + +func doSubscribe(channel string, hr SubHandler) { + ctx := gctx.New() + conn, err := g.Redis().Conn(ctx) + if err != nil { + return + } + defer conn.Close(ctx) + + _, err = conn.Subscribe(ctx, channel) + for { + msg, err := conn.ReceiveMessage(ctx) + if err != nil { + g.Log().Warningf(ctx, "subscribe quit, err:%v", err) + return + } + handleMessage(hr, msg) + } +} + +func handleMessage(hr SubHandler, message *gredis.Message) { + simple.SafeGo(gctx.New(), func(ctx context.Context) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + hr(ctx, message) + }) +} diff --git a/server/internal/library/network/tcp/client_cron.go b/server/internal/library/network/tcp/client_cron.go index 87115a7..bc70f09 100644 --- a/server/internal/library/network/tcp/client_cron.go +++ b/server/internal/library/network/tcp/client_cron.go @@ -19,6 +19,9 @@ func (client *Client) getCronKey(s string) string { // stopCron 停止定时任务 func (client *Client) stopCron() { + if client.conn == nil { + return + } gcron.Remove(client.getCronKey(CronHeartbeatVerify)) gcron.Remove(client.getCronKey(CronHeartbeat)) } diff --git a/server/internal/library/queue/queue.go b/server/internal/library/queue/queue.go index c1967f8..412f088 100644 --- a/server/internal/library/queue/queue.go +++ b/server/internal/library/queue/queue.go @@ -68,7 +68,7 @@ type MqMsg struct { } var ( - ctx = gctx.New() + ctx = gctx.GetInitCtx() mqProducerInstanceMap map[string]MqProducer mqConsumerInstanceMap map[string]MqConsumer mutex sync.Mutex diff --git a/server/internal/logic/admin/member.go b/server/internal/logic/admin/member.go index 9cddb07..067e42a 100644 --- a/server/internal/logic/admin/member.go +++ b/server/internal/logic/admin/member.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/gogf/gf/v2/crypto/gmd5" "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/database/gredis" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" @@ -18,6 +19,7 @@ import ( "github.com/gogf/gf/v2/util/grand" "hotgo/internal/consts" "hotgo/internal/dao" + "hotgo/internal/global" "hotgo/internal/library/contexts" "hotgo/internal/library/hgorm" "hotgo/internal/library/hgorm/handler" @@ -467,6 +469,16 @@ func (s *sAdminMember) Edit(ctx context.Context, in *adminin.MemberEditInp) (err return } + needLoadSuperAdmin := false + defer func() { + if needLoadSuperAdmin { + // 本地先更新 + s.LoadSuperAdmin(ctx) + // 推送消息让所有集群再同步一次 + global.PublishClusterSync(ctx, consts.ClusterSyncSysSuperAdmin, nil) + } + }() + // 修改 if in.Id > 0 { if s.VerifySuperId(ctx, in.Id) { @@ -503,9 +515,7 @@ func (s *sAdminMember) Edit(ctx context.Context, in *adminin.MemberEditInp) (err err = gerror.Wrap(err, "更新用户岗位失败,请稍后重试!") } - if in.RoleId == s.superAdmin.RoleId { - s.LoadSuperAdmin(ctx) - } + needLoadSuperAdmin = in.RoleId == s.superAdmin.RoleId return }) } @@ -541,9 +551,7 @@ func (s *sAdminMember) Edit(ctx context.Context, in *adminin.MemberEditInp) (err err = gerror.Wrap(err, "新增用户岗位失败,请稍后重试!") } - if in.RoleId == s.superAdmin.RoleId { - s.LoadSuperAdmin(ctx) - } + needLoadSuperAdmin = in.RoleId == s.superAdmin.RoleId return }) } @@ -690,8 +698,7 @@ func (s *sAdminMember) MemberLoginStat(ctx context.Context, in *adminin.MemberLo cols = dao.SysLoginLog.Columns() ) - err = dao.SysLoginLog.Ctx(ctx). - Fields(cols.LoginAt, cols.LoginIp). + err = dao.SysLoginLog.Ctx(ctx).Fields(cols.LoginAt, cols.LoginIp). Where(cols.MemberId, in.MemberId). Where(cols.Status, consts.StatusEnabled). OrderDesc(cols.Id). @@ -725,8 +732,7 @@ func (s *sAdminMember) GetIdByCode(ctx context.Context, in *adminin.GetIdByCodeI // Select 获取可选的用户选项 func (s *sAdminMember) Select(ctx context.Context, in *adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) { - err = dao.AdminMember.Ctx(ctx). - Fields("id as value,real_name as label,username,avatar"). + err = dao.AdminMember.Ctx(ctx).Fields("id as value,real_name as label,username,avatar"). Handler(handler.FilterAuthWithField("id")). Scan(&res) if err != nil { @@ -737,23 +743,20 @@ func (s *sAdminMember) Select(ctx context.Context, in *adminin.MemberSelectInp) // VerifySuperId 验证是否为超管 func (s *sAdminMember) VerifySuperId(ctx context.Context, verifyId int64) bool { + s.superAdmin.RLock() + defer s.superAdmin.RUnlock() + if s.superAdmin == nil || s.superAdmin.MemberIds == nil { g.Log().Error(ctx, "superAdmin is not initialized.") return false } - s.superAdmin.RLock() - defer s.superAdmin.RUnlock() - _, ok := s.superAdmin.MemberIds[verifyId] return ok } // LoadSuperAdmin 加载超管数据 func (s *sAdminMember) LoadSuperAdmin(ctx context.Context) { - s.superAdmin.Lock() - defer s.superAdmin.Unlock() - value, err := dao.AdminRole.Ctx(ctx).Where(dao.AdminRole.Columns().Key, consts.SuperRoleKey).Value() if err != nil { g.Log().Errorf(ctx, "LoadSuperAdmin AdminRole err:%+v", err) @@ -771,6 +774,9 @@ func (s *sAdminMember) LoadSuperAdmin(ctx context.Context) { return } + s.superAdmin.Lock() + defer s.superAdmin.Unlock() + s.superAdmin.MemberIds = make(map[int64]struct{}, len(array)) for _, v := range array { s.superAdmin.MemberIds[v.Int64()] = struct{}{} @@ -778,6 +784,12 @@ func (s *sAdminMember) LoadSuperAdmin(ctx context.Context) { s.superAdmin.RoleId = value.Int64() } +// ClusterSyncSuperAdmin 集群同步 +func (s *sAdminMember) ClusterSyncSuperAdmin(ctx context.Context, message *gredis.Message) { + s.LoadSuperAdmin(ctx) +} + +// FilterAuthModel 过滤查询权限,如果不是超管则排除掉自己 func (s *sAdminMember) FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model { m := dao.AdminMember.Ctx(ctx) if !s.VerifySuperId(ctx, memberId) { diff --git a/server/internal/logic/middleware/limit_blacklist.go b/server/internal/logic/middleware/limit_blacklist.go index b07cf1d..b62c5e9 100644 --- a/server/internal/logic/middleware/limit_blacklist.go +++ b/server/internal/logic/middleware/limit_blacklist.go @@ -1,23 +1,16 @@ package middleware import ( - "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/net/ghttp" - "hotgo/internal/global" - "hotgo/internal/library/location" "hotgo/internal/library/response" + "hotgo/internal/service" ) // Blacklist IP黑名单限制中间件 func (s *sMiddleware) Blacklist(r *ghttp.Request) { - if global.Blacklists != nil { - if _, ok := global.Blacklists[location.GetClientIp(r)]; ok { - response.JsonExit(r, gcode.CodeServerBusy.Code(), "请求异常,已被封禁,如有疑问请联系管理员!") - } - } else { - g.Log().Info(r.Context(), "blacklists uninitialized") + if err := service.SysBlacklist().VerifyRequest(r); err != nil { + response.JsonExit(r, gerror.Code(err).Code(), err.Error()) } - r.Middleware.Next() } diff --git a/server/internal/logic/sys/blacklist.go b/server/internal/logic/sys/blacklist.go index e242634..5c71e7a 100644 --- a/server/internal/logic/sys/blacklist.go +++ b/server/internal/logic/sys/blacklist.go @@ -7,12 +7,16 @@ package sys import ( "context" + "github.com/gogf/gf/v2/database/gredis" + "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gtime" "hotgo/internal/consts" "hotgo/internal/dao" "hotgo/internal/global" + "hotgo/internal/library/location" "hotgo/internal/model/input/sysin" "hotgo/internal/service" "hotgo/utility/convert" @@ -21,10 +25,13 @@ import ( type sSysBlacklist struct { sync.RWMutex + list map[string]struct{} } func NewSysBlacklist() *sSysBlacklist { - return &sSysBlacklist{} + return &sSysBlacklist{ + list: make(map[string]struct{}), + } } func init() { @@ -111,6 +118,7 @@ func (s *sSysBlacklist) List(ctx context.Context, in *sysin.BlacklistListInp) (l func (s *sSysBlacklist) VariableLoad(ctx context.Context, err error) { if err == nil { s.Load(ctx) + global.PublishClusterSync(ctx, consts.ClusterSyncSysBlacklist, nil) } } @@ -119,14 +127,14 @@ func (s *sSysBlacklist) Load(ctx context.Context) { s.RLock() defer s.RUnlock() - global.Blacklists = make(map[string]struct{}) + s.list = make(map[string]struct{}) array, err := dao.SysBlacklist.Ctx(ctx). Fields(dao.SysBlacklist.Columns().Ip). Where(dao.SysBlacklist.Columns().Status, consts.StatusEnabled). Array() if err != nil { - g.Log().Fatalf(ctx, "load blacklist fail:%+v", err) + g.Log().Errorf(ctx, "load blacklist fail:%+v", err) return } @@ -134,8 +142,26 @@ func (s *sSysBlacklist) Load(ctx context.Context) { list := convert.IpFilterStrategy(v.String()) if len(list) > 0 { for k := range list { - global.Blacklists[k] = struct{}{} + s.list[k] = struct{}{} } } } } + +// VerifyRequest 验证请求的访问IP是否在黑名单,如果存在则返回错误 +func (s *sSysBlacklist) VerifyRequest(r *ghttp.Request) (err error) { + if len(s.list) == 0 { + return + } + + if _, ok := s.list[location.GetClientIp(r)]; ok { + err = gerror.NewCode(gcode.New(gcode.CodeServerBusy.Code(), "请求异常,已被封禁,如有疑问请联系管理员!", nil)) + return + } + return +} + +// ClusterSync 集群同步 +func (s *sSysBlacklist) ClusterSync(ctx context.Context, message *gredis.Message) { + s.Load(ctx) +} diff --git a/server/internal/logic/sys/config.go b/server/internal/logic/sys/config.go index 088da82..291e2b8 100644 --- a/server/internal/logic/sys/config.go +++ b/server/internal/logic/sys/config.go @@ -9,12 +9,14 @@ import ( "context" "fmt" "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/database/gredis" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/gconv" "hotgo/internal/consts" "hotgo/internal/dao" + "hotgo/internal/global" "hotgo/internal/library/payment" "hotgo/internal/library/sms" "hotgo/internal/library/storager" @@ -37,37 +39,48 @@ func init() { service.RegisterSysConfig(NewSysConfig()) } -// InitConfig 初始化一些系统启动就需要用到的配置 +// InitConfig 初始化系统配置 func (s *sSysConfig) InitConfig(ctx context.Context) { + if err := s.LoadConfig(ctx); err != nil { + g.Log().Fatalf(ctx, "InitConfig fail:%+v", err) + } +} + +// LoadConfig 加载系统配置 +func (s *sSysConfig) LoadConfig(ctx context.Context) (err error) { wx, err := s.GetWechat(ctx) if err != nil { - g.Log().Fatalf(ctx, "init wechat conifg fail:%+v", err) + return } wechat.SetConfig(wx) pay, err := s.GetPay(ctx) if err != nil { - g.Log().Fatalf(ctx, "init pay conifg fail:%+v", err) + return } payment.SetConfig(pay) upload, err := s.GetUpload(ctx) if err != nil { - g.Log().Fatalf(ctx, "init upload conifg fail:%+v", err) + return } storager.SetConfig(upload) sm, err := s.GetSms(ctx) if err != nil { - g.Log().Fatalf(ctx, "init sms conifg fail:%+v", err) + return } sms.SetConfig(sm) tk, err := s.GetLoadToken(ctx) if err != nil { - g.Log().Fatalf(ctx, "init token conifg fail:%+v", err) + return } token.SetConfig(tk) + + // 更多 + // ... + return } // GetLogin 获取登录配置 @@ -259,9 +272,14 @@ func (s *sSysConfig) UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateCo return } } - return s.syncUpdate(ctx, in) }) + + if err != nil { + return + } + + global.PublishClusterSync(ctx, consts.ClusterSyncSysconfig, nil) return } @@ -308,3 +326,10 @@ func (s *sSysConfig) syncUpdate(ctx context.Context, in *sysin.UpdateConfigInp) } return } + +// ClusterSync 集群同步 +func (s *sSysConfig) ClusterSync(ctx context.Context, message *gredis.Message) { + if err := s.LoadConfig(ctx); err != nil { + g.Log().Errorf(ctx, "ClusterSync fail:%+v", err) + } +} diff --git a/server/internal/service/admin.go b/server/internal/service/admin.go index 230472c..bda4c71 100644 --- a/server/internal/service/admin.go +++ b/server/internal/service/admin.go @@ -1,5 +1,5 @@ // ================================================================================ -// Code generated by GoFrame CLI tool. DO NOT EDIT. +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. // You can delete these comments if you wish manually maintain this interface file. // ================================================================================ @@ -15,185 +15,254 @@ import ( "hotgo/internal/model/input/payin" "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/database/gredis" ) type ( - IAdminNotice interface { - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - Delete(ctx context.Context, in *adminin.NoticeDeleteInp) (err error) - Edit(ctx context.Context, in *adminin.NoticeEditInp) (err error) - Status(ctx context.Context, in *adminin.NoticeStatusInp) (err error) - MaxSort(ctx context.Context, in *adminin.NoticeMaxSortInp) (res *adminin.NoticeMaxSortModel, err error) - View(ctx context.Context, in *adminin.NoticeViewInp) (res *adminin.NoticeViewModel, err error) - List(ctx context.Context, in *adminin.NoticeListInp) (list []*adminin.NoticeListModel, totalCount int, err error) - PullMessages(ctx context.Context, in *adminin.PullMessagesInp) (res *adminin.PullMessagesModel, err error) - UnreadCount(ctx context.Context, in *adminin.NoticeUnreadCountInp) (res *adminin.NoticeUnreadCountModel, err error) - UpRead(ctx context.Context, in *adminin.NoticeUpReadInp) (err error) - ReadAll(ctx context.Context, in *adminin.NoticeReadAllInp) (err error) - MessageList(ctx context.Context, in *adminin.NoticeMessageListInp) (list []*adminin.NoticeMessageListModel, totalCount int, err error) - } - IAdminOrder interface { - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - AcceptRefund(ctx context.Context, in *adminin.OrderAcceptRefundInp) (err error) - ApplyRefund(ctx context.Context, in *adminin.OrderApplyRefundInp) (err error) - PayNotify(ctx context.Context, in *payin.NotifyCallFuncInp) (err error) - Create(ctx context.Context, in *adminin.OrderCreateInp) (res *adminin.OrderCreateModel, err error) - List(ctx context.Context, in *adminin.OrderListInp) (list []*adminin.OrderListModel, totalCount int, err error) - Export(ctx context.Context, in *adminin.OrderListInp) (err error) - Edit(ctx context.Context, in *adminin.OrderEditInp) (err error) - Delete(ctx context.Context, in *adminin.OrderDeleteInp) (err error) - View(ctx context.Context, in *adminin.OrderViewInp) (res *adminin.OrderViewModel, err error) - Status(ctx context.Context, in *adminin.OrderStatusInp) (err error) - } IAdminRole interface { + // Verify 验证权限 Verify(ctx context.Context, path, method string) bool + // List 获取列表 List(ctx context.Context, in *adminin.RoleListInp) (res *adminin.RoleListModel, totalCount int, err error) + // GetName 获取指定角色的名称 GetName(ctx context.Context, id int64) (name string, err error) + // GetMemberList 获取指定用户的岗位列表 GetMemberList(ctx context.Context, id int64) (list []*adminin.RoleListModel, err error) + // GetPermissions 更改角色菜单权限 GetPermissions(ctx context.Context, in *adminin.GetPermissionsInp) (res *adminin.GetPermissionsModel, err error) + // UpdatePermissions 更改角色菜单权限 UpdatePermissions(ctx context.Context, in *adminin.UpdatePermissionsInp) (err error) Edit(ctx context.Context, in *adminin.RoleEditInp) (err error) Delete(ctx context.Context, in *adminin.RoleDeleteInp) (err error) DataScopeSelect() (res form.Selects) DataScopeEdit(ctx context.Context, in *adminin.DataScopeEditInp) (err error) } + IAdminCash interface { + // View 获取指定提现信息 + View(ctx context.Context, in *adminin.CashViewInp) (res *adminin.CashViewModel, err error) + // List 获取列表 + List(ctx context.Context, in *adminin.CashListInp) (list []*adminin.CashListModel, totalCount int, err error) + // Apply 申请提现 + Apply(ctx context.Context, in *adminin.CashApplyInp) (err error) + // Payment 提现打款处理 + Payment(ctx context.Context, in *adminin.CashPaymentInp) (err error) + } IAdminCreditsLog interface { + // Model 资产变动ORM模型 Model(ctx context.Context, option ...*handler.Option) *gdb.Model + // SaveBalance 更新余额 SaveBalance(ctx context.Context, in *adminin.CreditsLogSaveBalanceInp) (res *adminin.CreditsLogSaveBalanceModel, err error) + // SaveIntegral 更新积分 SaveIntegral(ctx context.Context, in *adminin.CreditsLogSaveIntegralInp) (res *adminin.CreditsLogSaveIntegralModel, err error) + // List 获取资产变动列表 List(ctx context.Context, in *adminin.CreditsLogListInp) (list []*adminin.CreditsLogListModel, totalCount int, err error) + // Export 导出资产变动 Export(ctx context.Context, in *adminin.CreditsLogListInp) (err error) } - IAdminMenu interface { - Delete(ctx context.Context, in *adminin.MenuDeleteInp) (err error) - VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error) - Edit(ctx context.Context, in *adminin.MenuEditInp) (err error) - List(ctx context.Context, in *adminin.MenuListInp) (res *adminin.MenuListModel, err error) - GetMenuList(ctx context.Context, memberId int64) (res *role.DynamicRes, err error) - LoginPermissions(ctx context.Context, memberId int64) (lists adminin.MemberLoginPermissions, err error) - } - IAdminMember interface { - AddBalance(ctx context.Context, in *adminin.MemberAddBalanceInp) (err error) - AddIntegral(ctx context.Context, in *adminin.MemberAddIntegralInp) (err error) - UpdateCash(ctx context.Context, in *adminin.MemberUpdateCashInp) (err error) - UpdateEmail(ctx context.Context, in *adminin.MemberUpdateEmailInp) (err error) - UpdateMobile(ctx context.Context, in *adminin.MemberUpdateMobileInp) (err error) - UpdateProfile(ctx context.Context, in *adminin.MemberUpdateProfileInp) (err error) - UpdatePwd(ctx context.Context, in *adminin.MemberUpdatePwdInp) (err error) - ResetPwd(ctx context.Context, in *adminin.MemberResetPwdInp) (err error) - VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error) - Delete(ctx context.Context, in *adminin.MemberDeleteInp) (err error) - Edit(ctx context.Context, in *adminin.MemberEditInp) (err error) - View(ctx context.Context, in *adminin.MemberViewInp) (res *adminin.MemberViewModel, err error) - List(ctx context.Context, in *adminin.MemberListInp) (list []*adminin.MemberListModel, totalCount int, err error) - Status(ctx context.Context, in *adminin.MemberStatusInp) (err error) - GenTree(ctx context.Context, pid int64) (level int, newTree string, err error) - LoginMemberInfo(ctx context.Context) (res *adminin.LoginMemberInfoModel, err error) - MemberLoginStat(ctx context.Context, in *adminin.MemberLoginStatInp) (res *adminin.MemberLoginStatModel, err error) - GetIdByCode(ctx context.Context, in *adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error) - Select(ctx context.Context, in *adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) - VerifySuperId(ctx context.Context, verifyId int64) bool - LoadSuperAdmin(ctx context.Context) - FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model - } IAdminMemberPost interface { + // UpdatePostIds 更新用户岗位 UpdatePostIds(ctx context.Context, memberId int64, postIds []int64) (err error) } + IAdminMenu interface { + // Delete 删除 + Delete(ctx context.Context, in *adminin.MenuDeleteInp) (err error) + // VerifyUnique 验证菜单唯一属性 + VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error) + // Edit 修改/新增 + Edit(ctx context.Context, in *adminin.MenuEditInp) (err error) + // List 获取菜单列表 + List(ctx context.Context, in *adminin.MenuListInp) (res *adminin.MenuListModel, err error) + // GetMenuList 获取菜单列表 + GetMenuList(ctx context.Context, memberId int64) (res *role.DynamicRes, err error) + // LoginPermissions 获取登录成功后的细粒度权限 + LoginPermissions(ctx context.Context, memberId int64) (lists adminin.MemberLoginPermissions, err error) + } IAdminMonitor interface { + // StartMonitor 启动服务监控 StartMonitor(ctx context.Context) + // GetMeta 获取监控元数据 GetMeta(ctx context.Context) *model.MonitorData } IAdminPost interface { + // Delete 删除 Delete(ctx context.Context, in *adminin.PostDeleteInp) (err error) + // VerifyUnique 验证部门唯一属性 VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error) + // Edit 修改/新增 Edit(ctx context.Context, in *adminin.PostEditInp) (err error) + // MaxSort 最大排序 MaxSort(ctx context.Context, in *adminin.PostMaxSortInp) (res *adminin.PostMaxSortModel, err error) + // View 获取指定岗位信息 View(ctx context.Context, in *adminin.PostViewInp) (res *adminin.PostViewModel, err error) + // List 获取列表 List(ctx context.Context, in *adminin.PostListInp) (list []*adminin.PostListModel, totalCount int, err error) + // GetMemberByStartName 获取指定用户的第一岗位 GetMemberByStartName(ctx context.Context, memberId int64) (name string, err error) + // Status 更新状态 Status(ctx context.Context, in *adminin.PostStatusInp) (err error) } - IAdminSite interface { - Register(ctx context.Context, in *adminin.RegisterInp) (err error) - AccountLogin(ctx context.Context, in *adminin.AccountLoginInp) (res *adminin.LoginModel, err error) - MobileLogin(ctx context.Context, in *adminin.MobileLoginInp) (res *adminin.LoginModel, err error) - } - IAdminCash interface { - View(ctx context.Context, in *adminin.CashViewInp) (res *adminin.CashViewModel, err error) - List(ctx context.Context, in *adminin.CashListInp) (list []*adminin.CashListModel, totalCount int, err error) - Apply(ctx context.Context, in *adminin.CashApplyInp) (err error) - Payment(ctx context.Context, in *adminin.CashPaymentInp) (err error) - } IAdminDept interface { + // Delete 删除 Delete(ctx context.Context, in *adminin.DeptDeleteInp) (err error) + // VerifyUnique 验证部门唯一属性 VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error) + // Edit 修改/新增 Edit(ctx context.Context, in *adminin.DeptEditInp) (err error) + // Status 更新部门状态 Status(ctx context.Context, in *adminin.DeptStatusInp) (err error) + // MaxSort 最大排序 MaxSort(ctx context.Context, in *adminin.DeptMaxSortInp) (res *adminin.DeptMaxSortModel, err error) + // View 获取指定部门信息 View(ctx context.Context, in *adminin.DeptViewInp) (res *adminin.DeptViewModel, err error) + // Option 选项 Option(ctx context.Context, in *adminin.DeptOptionInp) (res *adminin.DeptOptionModel, totalCount int, err error) + // List 获取列表 List(ctx context.Context, in *adminin.DeptListInp) (res *adminin.DeptListModel, err error) + // GetName 获取部门名称 GetName(ctx context.Context, id int64) (name string, err error) } + IAdminMember interface { + // AddBalance 增加余额 + AddBalance(ctx context.Context, in *adminin.MemberAddBalanceInp) (err error) + // AddIntegral 增加积分 + AddIntegral(ctx context.Context, in *adminin.MemberAddIntegralInp) (err error) + // UpdateCash 修改提现信息 + UpdateCash(ctx context.Context, in *adminin.MemberUpdateCashInp) (err error) + // UpdateEmail 换绑邮箱 + UpdateEmail(ctx context.Context, in *adminin.MemberUpdateEmailInp) (err error) + // UpdateMobile 换绑手机号 + UpdateMobile(ctx context.Context, in *adminin.MemberUpdateMobileInp) (err error) + // UpdateProfile 更新用户资料 + UpdateProfile(ctx context.Context, in *adminin.MemberUpdateProfileInp) (err error) + // UpdatePwd 修改登录密码 + UpdatePwd(ctx context.Context, in *adminin.MemberUpdatePwdInp) (err error) + // ResetPwd 重置密码 + ResetPwd(ctx context.Context, in *adminin.MemberResetPwdInp) (err error) + // VerifyUnique 验证管理员唯一属性 + VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error) + // Delete 删除 + Delete(ctx context.Context, in *adminin.MemberDeleteInp) (err error) + // Edit 修改/新增 + Edit(ctx context.Context, in *adminin.MemberEditInp) (err error) + // View 获取用户信息 + View(ctx context.Context, in *adminin.MemberViewInp) (res *adminin.MemberViewModel, err error) + // List 获取列表 + List(ctx context.Context, in *adminin.MemberListInp) (list []*adminin.MemberListModel, totalCount int, err error) + // Status 更新状态 + Status(ctx context.Context, in *adminin.MemberStatusInp) (err error) + // GenTree 生成关系树 + GenTree(ctx context.Context, pid int64) (level int, newTree string, err error) + // LoginMemberInfo 获取登录用户信息 + LoginMemberInfo(ctx context.Context) (res *adminin.LoginMemberInfoModel, err error) + // MemberLoginStat 用户登录统计 + MemberLoginStat(ctx context.Context, in *adminin.MemberLoginStatInp) (res *adminin.MemberLoginStatModel, err error) + // GetIdByCode 通过邀请码获取用户ID + GetIdByCode(ctx context.Context, in *adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error) + // Select 获取可选的用户选项 + Select(ctx context.Context, in *adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) + // VerifySuperId 验证是否为超管 + VerifySuperId(ctx context.Context, verifyId int64) bool + // LoadSuperAdmin 加载超管数据 + LoadSuperAdmin(ctx context.Context) + // ClusterSyncSuperAdmin 集群同步 + ClusterSyncSuperAdmin(ctx context.Context, message *gredis.Message) + FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model + } + IAdminNotice interface { + // Model Orm模型 + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + // Delete 删除 + Delete(ctx context.Context, in *adminin.NoticeDeleteInp) (err error) + // Edit 修改/新增 + Edit(ctx context.Context, in *adminin.NoticeEditInp) (err error) + // Status 更新部门状态 + Status(ctx context.Context, in *adminin.NoticeStatusInp) (err error) + // MaxSort 最大排序 + MaxSort(ctx context.Context, in *adminin.NoticeMaxSortInp) (res *adminin.NoticeMaxSortModel, err error) + // View 获取指定字典类型信息 + View(ctx context.Context, in *adminin.NoticeViewInp) (res *adminin.NoticeViewModel, err error) + // List 获取列表 + List(ctx context.Context, in *adminin.NoticeListInp) (list []*adminin.NoticeListModel, totalCount int, err error) + // PullMessages 拉取未读消息列表 + PullMessages(ctx context.Context, in *adminin.PullMessagesInp) (res *adminin.PullMessagesModel, err error) + // UnreadCount 获取所有类型消息的未读数量 + UnreadCount(ctx context.Context, in *adminin.NoticeUnreadCountInp) (res *adminin.NoticeUnreadCountModel, err error) + // UpRead 更新已读 + UpRead(ctx context.Context, in *adminin.NoticeUpReadInp) (err error) + // ReadAll 已读全部 + ReadAll(ctx context.Context, in *adminin.NoticeReadAllInp) (err error) + // MessageList 我的消息列表 + MessageList(ctx context.Context, in *adminin.NoticeMessageListInp) (list []*adminin.NoticeMessageListModel, totalCount int, err error) + } + IAdminOrder interface { + // Model 充值订单ORM模型 + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + // AcceptRefund 受理申请退款 + AcceptRefund(ctx context.Context, in *adminin.OrderAcceptRefundInp) (err error) + // ApplyRefund 申请退款 + ApplyRefund(ctx context.Context, in *adminin.OrderApplyRefundInp) (err error) + // PayNotify 支付成功通知 + PayNotify(ctx context.Context, in *payin.NotifyCallFuncInp) (err error) + // Create 创建充值订单 + Create(ctx context.Context, in *adminin.OrderCreateInp) (res *adminin.OrderCreateModel, err error) + // List 获取充值订单列表 + List(ctx context.Context, in *adminin.OrderListInp) (list []*adminin.OrderListModel, totalCount int, err error) + // Export 导出充值订单 + Export(ctx context.Context, in *adminin.OrderListInp) (err error) + // Edit 修改/新增充值订单 + Edit(ctx context.Context, in *adminin.OrderEditInp) (err error) + // Delete 删除充值订单 + Delete(ctx context.Context, in *adminin.OrderDeleteInp) (err error) + // View 获取充值订单指定信息 + View(ctx context.Context, in *adminin.OrderViewInp) (res *adminin.OrderViewModel, err error) + // Status 更新充值订单状态 + Status(ctx context.Context, in *adminin.OrderStatusInp) (err error) + } + IAdminSite interface { + // Register 账号注册 + Register(ctx context.Context, in *adminin.RegisterInp) (err error) + // AccountLogin 账号登录 + AccountLogin(ctx context.Context, in *adminin.AccountLoginInp) (res *adminin.LoginModel, err error) + // MobileLogin 手机号登录 + MobileLogin(ctx context.Context, in *adminin.MobileLoginInp) (res *adminin.LoginModel, err error) + } ) var ( - localAdminCreditsLog IAdminCreditsLog - localAdminMenu IAdminMenu - localAdminNotice IAdminNotice - localAdminOrder IAdminOrder - localAdminRole IAdminRole localAdminCash IAdminCash - localAdminDept IAdminDept - localAdminMember IAdminMember + localAdminCreditsLog IAdminCreditsLog localAdminMemberPost IAdminMemberPost + localAdminMenu IAdminMenu localAdminMonitor IAdminMonitor localAdminPost IAdminPost + localAdminRole IAdminRole + localAdminDept IAdminDept + localAdminMember IAdminMember + localAdminNotice IAdminNotice + localAdminOrder IAdminOrder localAdminSite IAdminSite ) -func AdminCreditsLog() IAdminCreditsLog { - if localAdminCreditsLog == nil { - panic("implement not found for interface IAdminCreditsLog, forgot register?") +func AdminMonitor() IAdminMonitor { + if localAdminMonitor == nil { + panic("implement not found for interface IAdminMonitor, forgot register?") } - return localAdminCreditsLog + return localAdminMonitor } -func RegisterAdminCreditsLog(i IAdminCreditsLog) { - localAdminCreditsLog = i +func RegisterAdminMonitor(i IAdminMonitor) { + localAdminMonitor = i } -func AdminMenu() IAdminMenu { - if localAdminMenu == nil { - panic("implement not found for interface IAdminMenu, forgot register?") +func AdminPost() IAdminPost { + if localAdminPost == nil { + panic("implement not found for interface IAdminPost, forgot register?") } - return localAdminMenu + return localAdminPost } -func RegisterAdminMenu(i IAdminMenu) { - localAdminMenu = i -} - -func AdminNotice() IAdminNotice { - if localAdminNotice == nil { - panic("implement not found for interface IAdminNotice, forgot register?") - } - return localAdminNotice -} - -func RegisterAdminNotice(i IAdminNotice) { - localAdminNotice = i -} - -func AdminOrder() IAdminOrder { - if localAdminOrder == nil { - panic("implement not found for interface IAdminOrder, forgot register?") - } - return localAdminOrder -} - -func RegisterAdminOrder(i IAdminOrder) { - localAdminOrder = i +func RegisterAdminPost(i IAdminPost) { + localAdminPost = i } func AdminRole() IAdminRole { @@ -218,6 +287,50 @@ func RegisterAdminCash(i IAdminCash) { localAdminCash = i } +func AdminCreditsLog() IAdminCreditsLog { + if localAdminCreditsLog == nil { + panic("implement not found for interface IAdminCreditsLog, forgot register?") + } + return localAdminCreditsLog +} + +func RegisterAdminCreditsLog(i IAdminCreditsLog) { + localAdminCreditsLog = i +} + +func AdminMemberPost() IAdminMemberPost { + if localAdminMemberPost == nil { + panic("implement not found for interface IAdminMemberPost, forgot register?") + } + return localAdminMemberPost +} + +func RegisterAdminMemberPost(i IAdminMemberPost) { + localAdminMemberPost = i +} + +func AdminMenu() IAdminMenu { + if localAdminMenu == nil { + panic("implement not found for interface IAdminMenu, forgot register?") + } + return localAdminMenu +} + +func RegisterAdminMenu(i IAdminMenu) { + localAdminMenu = i +} + +func AdminSite() IAdminSite { + if localAdminSite == nil { + panic("implement not found for interface IAdminSite, forgot register?") + } + return localAdminSite +} + +func RegisterAdminSite(i IAdminSite) { + localAdminSite = i +} + func AdminDept() IAdminDept { if localAdminDept == nil { panic("implement not found for interface IAdminDept, forgot register?") @@ -240,46 +353,24 @@ func RegisterAdminMember(i IAdminMember) { localAdminMember = i } -func AdminMemberPost() IAdminMemberPost { - if localAdminMemberPost == nil { - panic("implement not found for interface IAdminMemberPost, forgot register?") +func AdminNotice() IAdminNotice { + if localAdminNotice == nil { + panic("implement not found for interface IAdminNotice, forgot register?") } - return localAdminMemberPost + return localAdminNotice } -func RegisterAdminMemberPost(i IAdminMemberPost) { - localAdminMemberPost = i +func RegisterAdminNotice(i IAdminNotice) { + localAdminNotice = i } -func AdminMonitor() IAdminMonitor { - if localAdminMonitor == nil { - panic("implement not found for interface IAdminMonitor, forgot register?") +func AdminOrder() IAdminOrder { + if localAdminOrder == nil { + panic("implement not found for interface IAdminOrder, forgot register?") } - return localAdminMonitor + return localAdminOrder } -func RegisterAdminMonitor(i IAdminMonitor) { - localAdminMonitor = i -} - -func AdminPost() IAdminPost { - if localAdminPost == nil { - panic("implement not found for interface IAdminPost, forgot register?") - } - return localAdminPost -} - -func RegisterAdminPost(i IAdminPost) { - localAdminPost = i -} - -func AdminSite() IAdminSite { - if localAdminSite == nil { - panic("implement not found for interface IAdminSite, forgot register?") - } - return localAdminSite -} - -func RegisterAdminSite(i IAdminSite) { - localAdminSite = i +func RegisterAdminOrder(i IAdminOrder) { + localAdminOrder = i } diff --git a/server/internal/service/sys.go b/server/internal/service/sys.go index ddf539b..5f19b28 100644 --- a/server/internal/service/sys.go +++ b/server/internal/service/sys.go @@ -13,12 +13,104 @@ import ( "hotgo/internal/model/input/sysin" "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/database/gredis" + "github.com/gogf/gf/v2/net/ghttp" ) type ( + ISysLoginLog interface { + // Model 登录日志Orm模型 + Model(ctx context.Context) *gdb.Model + // List 获取登录日志列表 + List(ctx context.Context, in *sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error) + // Export 导出登录日志 + Export(ctx context.Context, in *sysin.LoginLogListInp) (err error) + // Delete 删除登录日志 + Delete(ctx context.Context, in *sysin.LoginLogDeleteInp) (err error) + // View 获取登录日志指定信息 + View(ctx context.Context, in *sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error) + // Push 推送登录日志 + Push(ctx context.Context, in *sysin.LoginLogPushInp) + // RealWrite 真实写入 + RealWrite(ctx context.Context, models entity.SysLoginLog) (err error) + } + ISysAddons interface { + // List 获取列表 + List(ctx context.Context, in *sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error) + // Selects 选项 + Selects(ctx context.Context, in *sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error) + // Build 提交生成 + Build(ctx context.Context, in *sysin.AddonsBuildInp) (err error) + // Install 安装模块 + Install(ctx context.Context, in *sysin.AddonsInstallInp) (err error) + // Upgrade 更新模块 + Upgrade(ctx context.Context, in *sysin.AddonsUpgradeInp) (err error) + // UnInstall 卸载模块 + UnInstall(ctx context.Context, in *sysin.AddonsUnInstallInp) (err error) + } + ISysAddonsConfig interface { + // GetConfigByGroup 获取指定分组的配置 + GetConfigByGroup(ctx context.Context, in *sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error) + // ConversionType 转换类型 + ConversionType(ctx context.Context, models *entity.SysAddonsConfig) (value interface{}, err error) + // UpdateConfigByGroup 更新指定分组的配置 + UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateAddonsConfigInp) (err error) + } + ISysCurdDemo interface { + // Model 生成演示ORM模型 + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + // List 获取生成演示列表 + List(ctx context.Context, in *sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error) + // Export 导出生成演示 + Export(ctx context.Context, in *sysin.CurdDemoListInp) (err error) + // Edit 修改/新增生成演示 + Edit(ctx context.Context, in *sysin.CurdDemoEditInp) (err error) + // Delete 删除生成演示 + Delete(ctx context.Context, in *sysin.CurdDemoDeleteInp) (err error) + // MaxSort 获取生成演示最大排序 + MaxSort(ctx context.Context, in *sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error) + // View 获取生成演示指定信息 + View(ctx context.Context, in *sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error) + // Status 更新生成演示状态 + Status(ctx context.Context, in *sysin.CurdDemoStatusInp) (err error) + // Switch 更新生成演示开关 + Switch(ctx context.Context, in *sysin.CurdDemoSwitchInp) (err error) + } + ISysDictData interface { + // Delete 删除 + Delete(ctx context.Context, in *sysin.DictDataDeleteInp) error + // Edit 修改/新增 + Edit(ctx context.Context, in *sysin.DictDataEditInp) (err error) + // List 获取列表 + List(ctx context.Context, in *sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error) + // Select 获取列表 + Select(ctx context.Context, in *sysin.DataSelectInp) (list sysin.DataSelectModel, err error) + } + ISysEmsLog interface { + // Delete 删除 + Delete(ctx context.Context, in *sysin.EmsLogDeleteInp) (err error) + // Edit 修改/新增 + Edit(ctx context.Context, in *sysin.EmsLogEditInp) (err error) + // Status 更新部门状态 + Status(ctx context.Context, in *sysin.EmsLogStatusInp) (err error) + // View 获取指定字典类型信息 + View(ctx context.Context, in *sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error) + // List 获取列表 + List(ctx context.Context, in *sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error) + // Send 发送邮件 + Send(ctx context.Context, in *sysin.SendEmsInp) (err error) + // GetTemplate 获取指定邮件模板 + GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error) + // AllowSend 是否允许发送 + AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error) + // VerifyCode 效验验证码 + VerifyCode(ctx context.Context, in *sysin.VerifyEmsCodeInp) (err error) + } ISysConfig interface { - // InitConfig 初始化一些系统启动就需要用到的配置 + // InitConfig 初始化系统配置 InitConfig(ctx context.Context) + // LoadConfig 加载系统配置 + LoadConfig(ctx context.Context) (err error) // GetLogin 获取登录配置 GetLogin(ctx context.Context) (conf *model.LoginConfig, err error) // GetWechat 获取微信配置 @@ -53,6 +145,36 @@ type ( ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error) // UpdateConfigByGroup 更新指定分组的配置 UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateConfigInp) (err error) + // ClusterSync 集群同步 + ClusterSync(ctx context.Context, message *gredis.Message) + } + ISysServeLicense interface { + // Model 服务许可证ORM模型 + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + // List 获取服务许可证列表 + List(ctx context.Context, in *sysin.ServeLicenseListInp) (list []*sysin.ServeLicenseListModel, totalCount int, err error) + // Export 导出服务许可证 + Export(ctx context.Context, in *sysin.ServeLicenseListInp) (err error) + // Edit 修改/新增服务许可证 + Edit(ctx context.Context, in *sysin.ServeLicenseEditInp) (err error) + // Delete 删除服务许可证 + Delete(ctx context.Context, in *sysin.ServeLicenseDeleteInp) (err error) + // View 获取服务许可证指定信息 + View(ctx context.Context, in *sysin.ServeLicenseViewInp) (res *sysin.ServeLicenseViewModel, err error) + // Status 更新服务许可证状态 + Status(ctx context.Context, in *sysin.ServeLicenseStatusInp) (err error) + // AssignRouter 分配服务许可证路由 + AssignRouter(ctx context.Context, in *sysin.ServeLicenseAssignRouterInp) (err error) + } + ISysDictType interface { + // Tree 树 + Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error) + // Delete 删除 + Delete(ctx context.Context, in *sysin.DictTypeDeleteInp) (err error) + // Edit 修改/新增 + Edit(ctx context.Context, in *sysin.DictTypeEditInp) (err error) + // TreeSelect 获取类型关系树选项 + TreeSelect(ctx context.Context, in *sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error) } ISysServeLog interface { // Model 服务日志Orm模型 @@ -68,31 +190,25 @@ type ( // RealWrite 真实写入 RealWrite(ctx context.Context, models entity.SysServeLog) (err error) } - ISysAddons interface { + ISysSmsLog interface { + // Delete 删除 + Delete(ctx context.Context, in *sysin.SmsLogDeleteInp) (err error) + // Edit 修改/新增 + Edit(ctx context.Context, in *sysin.SmsLogEditInp) (err error) + // Status 更新短信状态 + Status(ctx context.Context, in *sysin.SmsLogStatusInp) (err error) + // View 获取指定字典类型信息 + View(ctx context.Context, in *sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error) // List 获取列表 - List(ctx context.Context, in *sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error) - // Selects 选项 - Selects(ctx context.Context, in *sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error) - // Build 提交生成 - Build(ctx context.Context, in *sysin.AddonsBuildInp) (err error) - // Install 安装模块 - Install(ctx context.Context, in *sysin.AddonsInstallInp) (err error) - // Upgrade 更新模块 - Upgrade(ctx context.Context, in *sysin.AddonsUpgradeInp) (err error) - // UnInstall 卸载模块 - UnInstall(ctx context.Context, in *sysin.AddonsUnInstallInp) (err error) - } - ISysAttachment interface { - // Model ORM模型 - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - // Delete 删除附件 - Delete(ctx context.Context, in *sysin.AttachmentDeleteInp) (err error) - // View 获取附件信息 - View(ctx context.Context, in *sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error) - // List 获取附件列表 - List(ctx context.Context, in *sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error) - // ClearKind 清空上传类型 - ClearKind(ctx context.Context, in *sysin.AttachmentClearKindInp) (err error) + List(ctx context.Context, in *sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error) + // SendCode 发送验证码 + SendCode(ctx context.Context, in *sysin.SendCodeInp) (err error) + // GetTemplate 获取指定短信模板 + GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error) + // AllowSend 是否允许发送 + AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error) + // VerifyCode 效验验证码 + VerifyCode(ctx context.Context, in *sysin.VerifyCodeInp) (err error) } ISysLog interface { // Export 导出 @@ -110,21 +226,59 @@ type ( // List 列表 List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error) } - ISysLoginLog interface { - // Model 登录日志Orm模型 - Model(ctx context.Context) *gdb.Model - // List 获取登录日志列表 - List(ctx context.Context, in *sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error) - // Export 导出登录日志 - Export(ctx context.Context, in *sysin.LoginLogListInp) (err error) - // Delete 删除登录日志 - Delete(ctx context.Context, in *sysin.LoginLogDeleteInp) (err error) - // View 获取登录日志指定信息 - View(ctx context.Context, in *sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error) - // Push 推送登录日志 - Push(ctx context.Context, in *sysin.LoginLogPushInp) - // RealWrite 真实写入 - RealWrite(ctx context.Context, models entity.SysLoginLog) (err error) + ISysProvinces interface { + // Tree 关系树选项列表 + Tree(ctx context.Context) (list []*sysin.ProvincesTree, err error) + // Delete 删除省市区数据 + Delete(ctx context.Context, in *sysin.ProvincesDeleteInp) (err error) + // Edit 修改/新增省市区数据 + Edit(ctx context.Context, in *sysin.ProvincesEditInp) (err error) + // Status 更新省市区状态 + Status(ctx context.Context, in *sysin.ProvincesStatusInp) (err error) + // MaxSort 最大排序 + MaxSort(ctx context.Context, in *sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error) + // View 获取省市区信息 + View(ctx context.Context, in *sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error) + // List 获取列表 + List(ctx context.Context, in *sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error) + // ChildrenList 获取省市区下级列表 + ChildrenList(ctx context.Context, in *sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error) + // UniqueId 获取省市区下级列表 + UniqueId(ctx context.Context, in *sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error) + // Select 省市区选项 + Select(ctx context.Context, in *sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error) + } + ISysAttachment interface { + // Model ORM模型 + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + // Delete 删除附件 + Delete(ctx context.Context, in *sysin.AttachmentDeleteInp) (err error) + // View 获取附件信息 + View(ctx context.Context, in *sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error) + // List 获取附件列表 + List(ctx context.Context, in *sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error) + // ClearKind 清空上传类型 + ClearKind(ctx context.Context, in *sysin.AttachmentClearKindInp) (err error) + } + ISysBlacklist interface { + // Delete 删除 + Delete(ctx context.Context, in *sysin.BlacklistDeleteInp) (err error) + // Edit 修改/新增 + Edit(ctx context.Context, in *sysin.BlacklistEditInp) (err error) + // Status 更新部门状态 + Status(ctx context.Context, in *sysin.BlacklistStatusInp) (err error) + // View 获取指定字典类型信息 + View(ctx context.Context, in *sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error) + // List 获取列表 + List(ctx context.Context, in *sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error) + // VariableLoad 变化加载 + VariableLoad(ctx context.Context, err error) + // Load 加载黑名单 + Load(ctx context.Context) + // VerifyRequest 验证请求的访问IP是否在黑名单,如果存在则返回错误 + VerifyRequest(r *ghttp.Request) (err error) + // ClusterSync 集群同步 + ClusterSync(ctx context.Context, message *gredis.Message) } ISysCron interface { StartCron(ctx context.Context) @@ -143,6 +297,22 @@ type ( // OnlineExec 在线执行 OnlineExec(ctx context.Context, in *sysin.OnlineExecInp) (err error) } + ISysCronGroup interface { + // Delete 删除 + Delete(ctx context.Context, in *sysin.CronGroupDeleteInp) (err error) + // Edit 修改/新增 + Edit(ctx context.Context, in *sysin.CronGroupEditInp) (err error) + // Status 更新状态 + Status(ctx context.Context, in *sysin.CronGroupStatusInp) (err error) + // MaxSort 最大排序 + MaxSort(ctx context.Context, in *sysin.CronGroupMaxSortInp) (res *sysin.CronGroupMaxSortModel, err error) + // View 获取指定信息 + View(ctx context.Context, in *sysin.CronGroupViewInp) (res *sysin.CronGroupViewModel, err error) + // List 获取列表 + List(ctx context.Context, in *sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error) + // Select 选项 + Select(ctx context.Context, in *sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error) + } ISysGenCodes interface { // Delete 删除 Delete(ctx context.Context, in *sysin.GenCodesDeleteInp) (err error) @@ -169,264 +339,38 @@ type ( // Build 提交生成 Build(ctx context.Context, in *sysin.GenCodesBuildInp) (err error) } - ISysCurdDemo interface { - // Model 生成演示ORM模型 - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - // List 获取生成演示列表 - List(ctx context.Context, in *sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error) - // Export 导出生成演示 - Export(ctx context.Context, in *sysin.CurdDemoListInp) (err error) - // Edit 修改/新增生成演示 - Edit(ctx context.Context, in *sysin.CurdDemoEditInp) (err error) - // Delete 删除生成演示 - Delete(ctx context.Context, in *sysin.CurdDemoDeleteInp) (err error) - // MaxSort 获取生成演示最大排序 - MaxSort(ctx context.Context, in *sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error) - // View 获取生成演示指定信息 - View(ctx context.Context, in *sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error) - // Status 更新生成演示状态 - Status(ctx context.Context, in *sysin.CurdDemoStatusInp) (err error) - // Switch 更新生成演示开关 - Switch(ctx context.Context, in *sysin.CurdDemoSwitchInp) (err error) - } - ISysDictData interface { - // Delete 删除 - Delete(ctx context.Context, in *sysin.DictDataDeleteInp) error - // Edit 修改/新增 - Edit(ctx context.Context, in *sysin.DictDataEditInp) (err error) - // List 获取列表 - List(ctx context.Context, in *sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error) - // Select 获取列表 - Select(ctx context.Context, in *sysin.DataSelectInp) (list sysin.DataSelectModel, err error) - } - ISysProvinces interface { - // Tree 关系树选项列表 - Tree(ctx context.Context) (list []*sysin.ProvincesTree, err error) - // Delete 删除省市区数据 - Delete(ctx context.Context, in *sysin.ProvincesDeleteInp) (err error) - // Edit 修改/新增省市区数据 - Edit(ctx context.Context, in *sysin.ProvincesEditInp) (err error) - // Status 更新省市区状态 - Status(ctx context.Context, in *sysin.ProvincesStatusInp) (err error) - // MaxSort 最大排序 - MaxSort(ctx context.Context, in *sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error) - // View 获取省市区信息 - View(ctx context.Context, in *sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error) - // List 获取列表 - List(ctx context.Context, in *sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error) - // ChildrenList 获取省市区下级列表 - ChildrenList(ctx context.Context, in *sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error) - // UniqueId 获取省市区下级列表 - UniqueId(ctx context.Context, in *sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error) - // Select 省市区选项 - Select(ctx context.Context, in *sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error) - } - ISysServeLicense interface { - // Model 服务许可证ORM模型 - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - // List 获取服务许可证列表 - List(ctx context.Context, in *sysin.ServeLicenseListInp) (list []*sysin.ServeLicenseListModel, totalCount int, err error) - // Export 导出服务许可证 - Export(ctx context.Context, in *sysin.ServeLicenseListInp) (err error) - // Edit 修改/新增服务许可证 - Edit(ctx context.Context, in *sysin.ServeLicenseEditInp) (err error) - // Delete 删除服务许可证 - Delete(ctx context.Context, in *sysin.ServeLicenseDeleteInp) (err error) - // View 获取服务许可证指定信息 - View(ctx context.Context, in *sysin.ServeLicenseViewInp) (res *sysin.ServeLicenseViewModel, err error) - // Status 更新服务许可证状态 - Status(ctx context.Context, in *sysin.ServeLicenseStatusInp) (err error) - // AssignRouter 分配服务许可证路由 - AssignRouter(ctx context.Context, in *sysin.ServeLicenseAssignRouterInp) (err error) - } - ISysSmsLog interface { - // Delete 删除 - Delete(ctx context.Context, in *sysin.SmsLogDeleteInp) (err error) - // Edit 修改/新增 - Edit(ctx context.Context, in *sysin.SmsLogEditInp) (err error) - // Status 更新短信状态 - Status(ctx context.Context, in *sysin.SmsLogStatusInp) (err error) - // View 获取指定字典类型信息 - View(ctx context.Context, in *sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error) - // List 获取列表 - List(ctx context.Context, in *sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error) - // SendCode 发送验证码 - SendCode(ctx context.Context, in *sysin.SendCodeInp) (err error) - // GetTemplate 获取指定短信模板 - GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error) - // AllowSend 是否允许发送 - AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error) - // VerifyCode 效验验证码 - VerifyCode(ctx context.Context, in *sysin.VerifyCodeInp) (err error) - } - ISysBlacklist interface { - // Delete 删除 - Delete(ctx context.Context, in *sysin.BlacklistDeleteInp) (err error) - // Edit 修改/新增 - Edit(ctx context.Context, in *sysin.BlacklistEditInp) (err error) - // Status 更新部门状态 - Status(ctx context.Context, in *sysin.BlacklistStatusInp) (err error) - // View 获取指定字典类型信息 - View(ctx context.Context, in *sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error) - // List 获取列表 - List(ctx context.Context, in *sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error) - // VariableLoad 变化加载 - VariableLoad(ctx context.Context, err error) - // Load 加载黑名单 - Load(ctx context.Context) - } - ISysCronGroup interface { - // Delete 删除 - Delete(ctx context.Context, in *sysin.CronGroupDeleteInp) (err error) - // Edit 修改/新增 - Edit(ctx context.Context, in *sysin.CronGroupEditInp) (err error) - // Status 更新状态 - Status(ctx context.Context, in *sysin.CronGroupStatusInp) (err error) - // MaxSort 最大排序 - MaxSort(ctx context.Context, in *sysin.CronGroupMaxSortInp) (res *sysin.CronGroupMaxSortModel, err error) - // View 获取指定信息 - View(ctx context.Context, in *sysin.CronGroupViewInp) (res *sysin.CronGroupViewModel, err error) - // List 获取列表 - List(ctx context.Context, in *sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error) - // Select 选项 - Select(ctx context.Context, in *sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error) - } - ISysEmsLog interface { - // Delete 删除 - Delete(ctx context.Context, in *sysin.EmsLogDeleteInp) (err error) - // Edit 修改/新增 - Edit(ctx context.Context, in *sysin.EmsLogEditInp) (err error) - // Status 更新部门状态 - Status(ctx context.Context, in *sysin.EmsLogStatusInp) (err error) - // View 获取指定字典类型信息 - View(ctx context.Context, in *sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error) - // List 获取列表 - List(ctx context.Context, in *sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error) - // Send 发送邮件 - Send(ctx context.Context, in *sysin.SendEmsInp) (err error) - // GetTemplate 获取指定邮件模板 - GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error) - // AllowSend 是否允许发送 - AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error) - // VerifyCode 效验验证码 - VerifyCode(ctx context.Context, in *sysin.VerifyEmsCodeInp) (err error) - } - ISysAddonsConfig interface { - // GetConfigByGroup 获取指定分组的配置 - GetConfigByGroup(ctx context.Context, in *sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error) - // ConversionType 转换类型 - ConversionType(ctx context.Context, models *entity.SysAddonsConfig) (value interface{}, err error) - // UpdateConfigByGroup 更新指定分组的配置 - UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateAddonsConfigInp) (err error) - } - ISysDictType interface { - // Tree 树 - Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error) - // Delete 删除 - Delete(ctx context.Context, in *sysin.DictTypeDeleteInp) (err error) - // Edit 修改/新增 - Edit(ctx context.Context, in *sysin.DictTypeEditInp) (err error) - // TreeSelect 获取类型关系树选项 - TreeSelect(ctx context.Context, in *sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error) - } ) var ( - localSysAddonsConfig ISysAddonsConfig - localSysDictType ISysDictType - localSysEmsLog ISysEmsLog - localSysAddons ISysAddons - localSysAttachment ISysAttachment localSysConfig ISysConfig + localSysServeLicense ISysServeLicense + localSysDictType ISysDictType localSysServeLog ISysServeLog + localSysSmsLog ISysSmsLog + localSysAttachment ISysAttachment + localSysBlacklist ISysBlacklist localSysCron ISysCron + localSysCronGroup ISysCronGroup localSysGenCodes ISysGenCodes localSysLog ISysLog - localSysLoginLog ISysLoginLog - localSysBlacklist ISysBlacklist - localSysCronGroup ISysCronGroup + localSysProvinces ISysProvinces + localSysAddons ISysAddons + localSysAddonsConfig ISysAddonsConfig localSysCurdDemo ISysCurdDemo localSysDictData ISysDictData - localSysProvinces ISysProvinces - localSysServeLicense ISysServeLicense - localSysSmsLog ISysSmsLog + localSysEmsLog ISysEmsLog + localSysLoginLog ISysLoginLog ) -func SysAddons() ISysAddons { - if localSysAddons == nil { - panic("implement not found for interface ISysAddons, forgot register?") +func SysEmsLog() ISysEmsLog { + if localSysEmsLog == nil { + panic("implement not found for interface ISysEmsLog, forgot register?") } - return localSysAddons + return localSysEmsLog } -func RegisterSysAddons(i ISysAddons) { - localSysAddons = i -} - -func SysAttachment() ISysAttachment { - if localSysAttachment == nil { - panic("implement not found for interface ISysAttachment, forgot register?") - } - return localSysAttachment -} - -func RegisterSysAttachment(i ISysAttachment) { - localSysAttachment = i -} - -func SysConfig() ISysConfig { - if localSysConfig == nil { - panic("implement not found for interface ISysConfig, forgot register?") - } - return localSysConfig -} - -func RegisterSysConfig(i ISysConfig) { - localSysConfig = i -} - -func SysServeLog() ISysServeLog { - if localSysServeLog == nil { - panic("implement not found for interface ISysServeLog, forgot register?") - } - return localSysServeLog -} - -func RegisterSysServeLog(i ISysServeLog) { - localSysServeLog = i -} - -func SysCron() ISysCron { - if localSysCron == nil { - panic("implement not found for interface ISysCron, forgot register?") - } - return localSysCron -} - -func RegisterSysCron(i ISysCron) { - localSysCron = i -} - -func SysGenCodes() ISysGenCodes { - if localSysGenCodes == nil { - panic("implement not found for interface ISysGenCodes, forgot register?") - } - return localSysGenCodes -} - -func RegisterSysGenCodes(i ISysGenCodes) { - localSysGenCodes = i -} - -func SysLog() ISysLog { - if localSysLog == nil { - panic("implement not found for interface ISysLog, forgot register?") - } - return localSysLog -} - -func RegisterSysLog(i ISysLog) { - localSysLog = i +func RegisterSysEmsLog(i ISysEmsLog) { + localSysEmsLog = i } func SysLoginLog() ISysLoginLog { @@ -440,37 +384,26 @@ func RegisterSysLoginLog(i ISysLoginLog) { localSysLoginLog = i } -func SysSmsLog() ISysSmsLog { - if localSysSmsLog == nil { - panic("implement not found for interface ISysSmsLog, forgot register?") +func SysAddons() ISysAddons { + if localSysAddons == nil { + panic("implement not found for interface ISysAddons, forgot register?") } - return localSysSmsLog + return localSysAddons } -func RegisterSysSmsLog(i ISysSmsLog) { - localSysSmsLog = i +func RegisterSysAddons(i ISysAddons) { + localSysAddons = i } -func SysBlacklist() ISysBlacklist { - if localSysBlacklist == nil { - panic("implement not found for interface ISysBlacklist, forgot register?") +func SysAddonsConfig() ISysAddonsConfig { + if localSysAddonsConfig == nil { + panic("implement not found for interface ISysAddonsConfig, forgot register?") } - return localSysBlacklist + return localSysAddonsConfig } -func RegisterSysBlacklist(i ISysBlacklist) { - localSysBlacklist = i -} - -func SysCronGroup() ISysCronGroup { - if localSysCronGroup == nil { - panic("implement not found for interface ISysCronGroup, forgot register?") - } - return localSysCronGroup -} - -func RegisterSysCronGroup(i ISysCronGroup) { - localSysCronGroup = i +func RegisterSysAddonsConfig(i ISysAddonsConfig) { + localSysAddonsConfig = i } func SysCurdDemo() ISysCurdDemo { @@ -495,15 +428,15 @@ func RegisterSysDictData(i ISysDictData) { localSysDictData = i } -func SysProvinces() ISysProvinces { - if localSysProvinces == nil { - panic("implement not found for interface ISysProvinces, forgot register?") +func SysConfig() ISysConfig { + if localSysConfig == nil { + panic("implement not found for interface ISysConfig, forgot register?") } - return localSysProvinces + return localSysConfig } -func RegisterSysProvinces(i ISysProvinces) { - localSysProvinces = i +func RegisterSysConfig(i ISysConfig) { + localSysConfig = i } func SysServeLicense() ISysServeLicense { @@ -517,17 +450,6 @@ func RegisterSysServeLicense(i ISysServeLicense) { localSysServeLicense = i } -func SysAddonsConfig() ISysAddonsConfig { - if localSysAddonsConfig == nil { - panic("implement not found for interface ISysAddonsConfig, forgot register?") - } - return localSysAddonsConfig -} - -func RegisterSysAddonsConfig(i ISysAddonsConfig) { - localSysAddonsConfig = i -} - func SysDictType() ISysDictType { if localSysDictType == nil { panic("implement not found for interface ISysDictType, forgot register?") @@ -539,13 +461,101 @@ func RegisterSysDictType(i ISysDictType) { localSysDictType = i } -func SysEmsLog() ISysEmsLog { - if localSysEmsLog == nil { - panic("implement not found for interface ISysEmsLog, forgot register?") +func SysServeLog() ISysServeLog { + if localSysServeLog == nil { + panic("implement not found for interface ISysServeLog, forgot register?") } - return localSysEmsLog + return localSysServeLog } -func RegisterSysEmsLog(i ISysEmsLog) { - localSysEmsLog = i +func RegisterSysServeLog(i ISysServeLog) { + localSysServeLog = i +} + +func SysSmsLog() ISysSmsLog { + if localSysSmsLog == nil { + panic("implement not found for interface ISysSmsLog, forgot register?") + } + return localSysSmsLog +} + +func RegisterSysSmsLog(i ISysSmsLog) { + localSysSmsLog = i +} + +func SysGenCodes() ISysGenCodes { + if localSysGenCodes == nil { + panic("implement not found for interface ISysGenCodes, forgot register?") + } + return localSysGenCodes +} + +func RegisterSysGenCodes(i ISysGenCodes) { + localSysGenCodes = i +} + +func SysLog() ISysLog { + if localSysLog == nil { + panic("implement not found for interface ISysLog, forgot register?") + } + return localSysLog +} + +func RegisterSysLog(i ISysLog) { + localSysLog = i +} + +func SysProvinces() ISysProvinces { + if localSysProvinces == nil { + panic("implement not found for interface ISysProvinces, forgot register?") + } + return localSysProvinces +} + +func RegisterSysProvinces(i ISysProvinces) { + localSysProvinces = i +} + +func SysAttachment() ISysAttachment { + if localSysAttachment == nil { + panic("implement not found for interface ISysAttachment, forgot register?") + } + return localSysAttachment +} + +func RegisterSysAttachment(i ISysAttachment) { + localSysAttachment = i +} + +func SysBlacklist() ISysBlacklist { + if localSysBlacklist == nil { + panic("implement not found for interface ISysBlacklist, forgot register?") + } + return localSysBlacklist +} + +func RegisterSysBlacklist(i ISysBlacklist) { + localSysBlacklist = i +} + +func SysCron() ISysCron { + if localSysCron == nil { + panic("implement not found for interface ISysCron, forgot register?") + } + return localSysCron +} + +func RegisterSysCron(i ISysCron) { + localSysCron = i +} + +func SysCronGroup() ISysCronGroup { + if localSysCronGroup == nil { + panic("implement not found for interface ISysCronGroup, forgot register?") + } + return localSysCronGroup +} + +func RegisterSysCronGroup(i ISysCronGroup) { + localSysCronGroup = i } diff --git a/server/manifest/config/config.example.yaml b/server/manifest/config/config.example.yaml index ced6812..c87ddd4 100644 --- a/server/manifest/config/config.example.yaml +++ b/server/manifest/config/config.example.yaml @@ -10,6 +10,8 @@ hotgo: ipMethod: "whois" # 是否为演示系统 false|true isDemo: false + # 是否为集群部署 false|true ,默认为false。开启集群必须配置redis,通过redis发布订阅进行集群之间的数据同步 + isCluster: true # 全局请求日志 log: switch: true # 日志开关,默认为true diff --git a/web/src/views/system/cron/columns.ts b/web/src/views/system/cron/columns.ts index 8c4b634..b7217b1 100644 --- a/web/src/views/system/cron/columns.ts +++ b/web/src/views/system/cron/columns.ts @@ -51,10 +51,10 @@ export const columns = [ title: '表达式', key: 'pattern', }, - { - title: '执行次数', - key: 'count', - }, + // { + // title: '执行次数', + // key: 'count', + // }, { title: '状态', key: 'status', diff --git a/web/src/views/system/cron/index.vue b/web/src/views/system/cron/index.vue index e1315e9..346f91a 100644 --- a/web/src/views/system/cron/index.vue +++ b/web/src/views/system/cron/index.vue @@ -144,7 +144,7 @@ - + @@ -450,7 +450,7 @@ openDrawer(); } - async function setDictSelect() { + async function reloadGroupOption() { const tmp = await getSelect({}); optionTreeData.value = tmp.list; if (optionTreeData.value === undefined || optionTreeData.value === null) { @@ -467,7 +467,7 @@ } onBeforeMount(async () => { - await setDictSelect(); + await reloadGroupOption(); }); // 处理选项更新 diff --git a/web/src/views/system/cron/modal/index.vue b/web/src/views/system/cron/modal/index.vue index a4dd2d4..4d4af93 100644 --- a/web/src/views/system/cron/modal/index.vue +++ b/web/src/views/system/cron/modal/index.vue @@ -40,6 +40,7 @@ :default-value="formParams.pid" @update:value="handleUpdateValue" /> + @@ -78,13 +79,14 @@ diff --git a/web/src/views/system/cron/modal/modal.vue b/web/src/views/system/cron/modal/modal.vue index d29aa51..1e457b0 100644 --- a/web/src/views/system/cron/modal/modal.vue +++ b/web/src/views/system/cron/modal/modal.vue @@ -7,7 +7,7 @@ preset="dialog" :title="title" > - + @@ -16,6 +16,7 @@ import { ref } from 'vue'; import Index from './index.vue'; + const emit = defineEmits(['reloadGroupOption']); const showModal = ref(false); const title = ref('管理分组'); @@ -23,6 +24,10 @@ showModal.value = true; } + function reloadGroupOption() { + emit('reloadGroupOption'); + } + defineExpose({ openDrawer }); From 471f0692955f3e292be5eee4dc1aa7e7dc1e6cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=9F=E5=B8=85?= <133814250@qq.com> Date: Wed, 26 Jul 2023 17:03:34 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/manifest/config/config.example.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/manifest/config/config.example.yaml b/server/manifest/config/config.example.yaml index c87ddd4..784dd9a 100644 --- a/server/manifest/config/config.example.yaml +++ b/server/manifest/config/config.example.yaml @@ -11,7 +11,7 @@ hotgo: # 是否为演示系统 false|true isDemo: false # 是否为集群部署 false|true ,默认为false。开启集群必须配置redis,通过redis发布订阅进行集群之间的数据同步 - isCluster: true + isCluster: false # 全局请求日志 log: switch: true # 日志开关,默认为true