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