Merge pull request #38 from bufanyun/v2.0

增加集群部署支持,修复定时任务分组添加后选项不显示
This commit is contained in:
maxbad 2023-07-26 17:35:12 +08:00 committed by GitHub
commit 755e95b0a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1185 additions and 529 deletions

View File

@ -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" // 超管
)

View File

@ -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
}

View File

@ -14,8 +14,6 @@ var (
RootPtah string RootPtah string
// SysType 操作系统类型 windows | linux // SysType 操作系统类型 windows | linux
SysType = runtime.GOOS SysType = runtime.GOOS
// Blacklists 黑名单列表
Blacklists map[string]struct{}
// JaegerSwitch 链路追踪开关 // JaegerSwitch 链路追踪开关
JaegerSwitch bool JaegerSwitch bool
) )

View File

@ -51,6 +51,9 @@ func Init(ctx context.Context) {
// 加载超管数据 // 加载超管数据
service.AdminMember().LoadSuperAdmin(ctx) service.AdminMember().LoadSuperAdmin(ctx)
// 订阅集群同步
SubscribeClusterSync(ctx)
} }
// LoggingServeLogHandler 服务日志处理 // LoggingServeLogHandler 服务日志处理

View File

@ -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")
)

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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)
})
}

View File

@ -19,6 +19,9 @@ func (client *Client) getCronKey(s string) string {
// stopCron 停止定时任务 // stopCron 停止定时任务
func (client *Client) stopCron() { func (client *Client) stopCron() {
if client.conn == nil {
return
}
gcron.Remove(client.getCronKey(CronHeartbeatVerify)) gcron.Remove(client.getCronKey(CronHeartbeatVerify))
gcron.Remove(client.getCronKey(CronHeartbeat)) gcron.Remove(client.getCronKey(CronHeartbeat))
} }

View File

@ -68,7 +68,7 @@ type MqMsg struct {
} }
var ( var (
ctx = gctx.New() ctx = gctx.GetInitCtx()
mqProducerInstanceMap map[string]MqProducer mqProducerInstanceMap map[string]MqProducer
mqConsumerInstanceMap map[string]MqConsumer mqConsumerInstanceMap map[string]MqConsumer
mutex sync.Mutex mutex sync.Mutex

View File

@ -10,6 +10,7 @@ import (
"fmt" "fmt"
"github.com/gogf/gf/v2/crypto/gmd5" "github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/database/gdb" "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/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
@ -18,6 +19,7 @@ import (
"github.com/gogf/gf/v2/util/grand" "github.com/gogf/gf/v2/util/grand"
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/dao" "hotgo/internal/dao"
"hotgo/internal/global"
"hotgo/internal/library/contexts" "hotgo/internal/library/contexts"
"hotgo/internal/library/hgorm" "hotgo/internal/library/hgorm"
"hotgo/internal/library/hgorm/handler" "hotgo/internal/library/hgorm/handler"
@ -467,6 +469,16 @@ func (s *sAdminMember) Edit(ctx context.Context, in *adminin.MemberEditInp) (err
return return
} }
needLoadSuperAdmin := false
defer func() {
if needLoadSuperAdmin {
// 本地先更新
s.LoadSuperAdmin(ctx)
// 推送消息让所有集群再同步一次
global.PublishClusterSync(ctx, consts.ClusterSyncSysSuperAdmin, nil)
}
}()
// 修改 // 修改
if in.Id > 0 { if in.Id > 0 {
if s.VerifySuperId(ctx, in.Id) { 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, "更新用户岗位失败,请稍后重试!") err = gerror.Wrap(err, "更新用户岗位失败,请稍后重试!")
} }
if in.RoleId == s.superAdmin.RoleId { needLoadSuperAdmin = in.RoleId == s.superAdmin.RoleId
s.LoadSuperAdmin(ctx)
}
return return
}) })
} }
@ -541,9 +551,7 @@ func (s *sAdminMember) Edit(ctx context.Context, in *adminin.MemberEditInp) (err
err = gerror.Wrap(err, "新增用户岗位失败,请稍后重试!") err = gerror.Wrap(err, "新增用户岗位失败,请稍后重试!")
} }
if in.RoleId == s.superAdmin.RoleId { needLoadSuperAdmin = in.RoleId == s.superAdmin.RoleId
s.LoadSuperAdmin(ctx)
}
return return
}) })
} }
@ -690,8 +698,7 @@ func (s *sAdminMember) MemberLoginStat(ctx context.Context, in *adminin.MemberLo
cols = dao.SysLoginLog.Columns() cols = dao.SysLoginLog.Columns()
) )
err = dao.SysLoginLog.Ctx(ctx). err = dao.SysLoginLog.Ctx(ctx).Fields(cols.LoginAt, cols.LoginIp).
Fields(cols.LoginAt, cols.LoginIp).
Where(cols.MemberId, in.MemberId). Where(cols.MemberId, in.MemberId).
Where(cols.Status, consts.StatusEnabled). Where(cols.Status, consts.StatusEnabled).
OrderDesc(cols.Id). OrderDesc(cols.Id).
@ -725,8 +732,7 @@ func (s *sAdminMember) GetIdByCode(ctx context.Context, in *adminin.GetIdByCodeI
// Select 获取可选的用户选项 // Select 获取可选的用户选项
func (s *sAdminMember) Select(ctx context.Context, in *adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) { func (s *sAdminMember) Select(ctx context.Context, in *adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) {
err = dao.AdminMember.Ctx(ctx). err = dao.AdminMember.Ctx(ctx).Fields("id as value,real_name as label,username,avatar").
Fields("id as value,real_name as label,username,avatar").
Handler(handler.FilterAuthWithField("id")). Handler(handler.FilterAuthWithField("id")).
Scan(&res) Scan(&res)
if err != nil { if err != nil {
@ -737,23 +743,20 @@ func (s *sAdminMember) Select(ctx context.Context, in *adminin.MemberSelectInp)
// VerifySuperId 验证是否为超管 // VerifySuperId 验证是否为超管
func (s *sAdminMember) VerifySuperId(ctx context.Context, verifyId int64) bool { 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 { if s.superAdmin == nil || s.superAdmin.MemberIds == nil {
g.Log().Error(ctx, "superAdmin is not initialized.") g.Log().Error(ctx, "superAdmin is not initialized.")
return false return false
} }
s.superAdmin.RLock()
defer s.superAdmin.RUnlock()
_, ok := s.superAdmin.MemberIds[verifyId] _, ok := s.superAdmin.MemberIds[verifyId]
return ok return ok
} }
// LoadSuperAdmin 加载超管数据 // LoadSuperAdmin 加载超管数据
func (s *sAdminMember) LoadSuperAdmin(ctx context.Context) { 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() value, err := dao.AdminRole.Ctx(ctx).Where(dao.AdminRole.Columns().Key, consts.SuperRoleKey).Value()
if err != nil { if err != nil {
g.Log().Errorf(ctx, "LoadSuperAdmin AdminRole err:%+v", err) g.Log().Errorf(ctx, "LoadSuperAdmin AdminRole err:%+v", err)
@ -771,6 +774,9 @@ func (s *sAdminMember) LoadSuperAdmin(ctx context.Context) {
return return
} }
s.superAdmin.Lock()
defer s.superAdmin.Unlock()
s.superAdmin.MemberIds = make(map[int64]struct{}, len(array)) s.superAdmin.MemberIds = make(map[int64]struct{}, len(array))
for _, v := range array { for _, v := range array {
s.superAdmin.MemberIds[v.Int64()] = struct{}{} s.superAdmin.MemberIds[v.Int64()] = struct{}{}
@ -778,6 +784,12 @@ func (s *sAdminMember) LoadSuperAdmin(ctx context.Context) {
s.superAdmin.RoleId = value.Int64() 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 { func (s *sAdminMember) FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model {
m := dao.AdminMember.Ctx(ctx) m := dao.AdminMember.Ctx(ctx)
if !s.VerifySuperId(ctx, memberId) { if !s.VerifySuperId(ctx, memberId) {

View File

@ -1,23 +1,16 @@
package middleware package middleware
import ( import (
"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/net/ghttp"
"hotgo/internal/global"
"hotgo/internal/library/location"
"hotgo/internal/library/response" "hotgo/internal/library/response"
"hotgo/internal/service"
) )
// Blacklist IP黑名单限制中间件 // Blacklist IP黑名单限制中间件
func (s *sMiddleware) Blacklist(r *ghttp.Request) { func (s *sMiddleware) Blacklist(r *ghttp.Request) {
if global.Blacklists != nil { if err := service.SysBlacklist().VerifyRequest(r); err != nil {
if _, ok := global.Blacklists[location.GetClientIp(r)]; ok { response.JsonExit(r, gerror.Code(err).Code(), err.Error())
response.JsonExit(r, gcode.CodeServerBusy.Code(), "请求异常,已被封禁,如有疑问请联系管理员!")
} }
} else {
g.Log().Info(r.Context(), "blacklists uninitialized")
}
r.Middleware.Next() r.Middleware.Next()
} }

View File

@ -7,12 +7,16 @@ package sys
import ( import (
"context" "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/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/dao" "hotgo/internal/dao"
"hotgo/internal/global" "hotgo/internal/global"
"hotgo/internal/library/location"
"hotgo/internal/model/input/sysin" "hotgo/internal/model/input/sysin"
"hotgo/internal/service" "hotgo/internal/service"
"hotgo/utility/convert" "hotgo/utility/convert"
@ -21,10 +25,13 @@ import (
type sSysBlacklist struct { type sSysBlacklist struct {
sync.RWMutex sync.RWMutex
list map[string]struct{}
} }
func NewSysBlacklist() *sSysBlacklist { func NewSysBlacklist() *sSysBlacklist {
return &sSysBlacklist{} return &sSysBlacklist{
list: make(map[string]struct{}),
}
} }
func init() { 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) { func (s *sSysBlacklist) VariableLoad(ctx context.Context, err error) {
if err == nil { if err == nil {
s.Load(ctx) s.Load(ctx)
global.PublishClusterSync(ctx, consts.ClusterSyncSysBlacklist, nil)
} }
} }
@ -119,14 +127,14 @@ func (s *sSysBlacklist) Load(ctx context.Context) {
s.RLock() s.RLock()
defer s.RUnlock() defer s.RUnlock()
global.Blacklists = make(map[string]struct{}) s.list = make(map[string]struct{})
array, err := dao.SysBlacklist.Ctx(ctx). array, err := dao.SysBlacklist.Ctx(ctx).
Fields(dao.SysBlacklist.Columns().Ip). Fields(dao.SysBlacklist.Columns().Ip).
Where(dao.SysBlacklist.Columns().Status, consts.StatusEnabled). Where(dao.SysBlacklist.Columns().Status, consts.StatusEnabled).
Array() Array()
if err != nil { if err != nil {
g.Log().Fatalf(ctx, "load blacklist fail%+v", err) g.Log().Errorf(ctx, "load blacklist fail%+v", err)
return return
} }
@ -134,8 +142,26 @@ func (s *sSysBlacklist) Load(ctx context.Context) {
list := convert.IpFilterStrategy(v.String()) list := convert.IpFilterStrategy(v.String())
if len(list) > 0 { if len(list) > 0 {
for k := range list { 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)
}

View File

@ -9,12 +9,14 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/gogf/gf/v2/database/gdb" "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/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/dao" "hotgo/internal/dao"
"hotgo/internal/global"
"hotgo/internal/library/payment" "hotgo/internal/library/payment"
"hotgo/internal/library/sms" "hotgo/internal/library/sms"
"hotgo/internal/library/storager" "hotgo/internal/library/storager"
@ -37,37 +39,48 @@ func init() {
service.RegisterSysConfig(NewSysConfig()) service.RegisterSysConfig(NewSysConfig())
} }
// InitConfig 初始化一些系统启动就需要用到的配置 // InitConfig 初始化系统配置
func (s *sSysConfig) InitConfig(ctx context.Context) { 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) wx, err := s.GetWechat(ctx)
if err != nil { if err != nil {
g.Log().Fatalf(ctx, "init wechat conifg fail%+v", err) return
} }
wechat.SetConfig(wx) wechat.SetConfig(wx)
pay, err := s.GetPay(ctx) pay, err := s.GetPay(ctx)
if err != nil { if err != nil {
g.Log().Fatalf(ctx, "init pay conifg fail%+v", err) return
} }
payment.SetConfig(pay) payment.SetConfig(pay)
upload, err := s.GetUpload(ctx) upload, err := s.GetUpload(ctx)
if err != nil { if err != nil {
g.Log().Fatalf(ctx, "init upload conifg fail%+v", err) return
} }
storager.SetConfig(upload) storager.SetConfig(upload)
sm, err := s.GetSms(ctx) sm, err := s.GetSms(ctx)
if err != nil { if err != nil {
g.Log().Fatalf(ctx, "init sms conifg fail%+v", err) return
} }
sms.SetConfig(sm) sms.SetConfig(sm)
tk, err := s.GetLoadToken(ctx) tk, err := s.GetLoadToken(ctx)
if err != nil { if err != nil {
g.Log().Fatalf(ctx, "init token conifg fail%+v", err) return
} }
token.SetConfig(tk) token.SetConfig(tk)
// 更多
// ...
return
} }
// GetLogin 获取登录配置 // GetLogin 获取登录配置
@ -259,9 +272,14 @@ func (s *sSysConfig) UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateCo
return return
} }
} }
return s.syncUpdate(ctx, in) return s.syncUpdate(ctx, in)
}) })
if err != nil {
return
}
global.PublishClusterSync(ctx, consts.ClusterSyncSysconfig, nil)
return return
} }
@ -308,3 +326,10 @@ func (s *sSysConfig) syncUpdate(ctx context.Context, in *sysin.UpdateConfigInp)
} }
return 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)
}
}

View File

@ -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. // You can delete these comments if you wish manually maintain this interface file.
// ================================================================================ // ================================================================================
@ -15,185 +15,254 @@ import (
"hotgo/internal/model/input/payin" "hotgo/internal/model/input/payin"
"github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/database/gredis"
) )
type ( 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 { IAdminRole interface {
// Verify 验证权限
Verify(ctx context.Context, path, method string) bool Verify(ctx context.Context, path, method string) bool
// List 获取列表
List(ctx context.Context, in *adminin.RoleListInp) (res *adminin.RoleListModel, totalCount int, err error) 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) GetName(ctx context.Context, id int64) (name string, err error)
// GetMemberList 获取指定用户的岗位列表
GetMemberList(ctx context.Context, id int64) (list []*adminin.RoleListModel, err error) GetMemberList(ctx context.Context, id int64) (list []*adminin.RoleListModel, err error)
// GetPermissions 更改角色菜单权限
GetPermissions(ctx context.Context, in *adminin.GetPermissionsInp) (res *adminin.GetPermissionsModel, err error) GetPermissions(ctx context.Context, in *adminin.GetPermissionsInp) (res *adminin.GetPermissionsModel, err error)
// UpdatePermissions 更改角色菜单权限
UpdatePermissions(ctx context.Context, in *adminin.UpdatePermissionsInp) (err error) UpdatePermissions(ctx context.Context, in *adminin.UpdatePermissionsInp) (err error)
Edit(ctx context.Context, in *adminin.RoleEditInp) (err error) Edit(ctx context.Context, in *adminin.RoleEditInp) (err error)
Delete(ctx context.Context, in *adminin.RoleDeleteInp) (err error) Delete(ctx context.Context, in *adminin.RoleDeleteInp) (err error)
DataScopeSelect() (res form.Selects) DataScopeSelect() (res form.Selects)
DataScopeEdit(ctx context.Context, in *adminin.DataScopeEditInp) (err error) 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 { IAdminCreditsLog interface {
// Model 资产变动ORM模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model Model(ctx context.Context, option ...*handler.Option) *gdb.Model
// SaveBalance 更新余额
SaveBalance(ctx context.Context, in *adminin.CreditsLogSaveBalanceInp) (res *adminin.CreditsLogSaveBalanceModel, err error) 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) 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) List(ctx context.Context, in *adminin.CreditsLogListInp) (list []*adminin.CreditsLogListModel, totalCount int, err error)
// Export 导出资产变动
Export(ctx context.Context, in *adminin.CreditsLogListInp) (err error) 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 { IAdminMemberPost interface {
// UpdatePostIds 更新用户岗位
UpdatePostIds(ctx context.Context, memberId int64, postIds []int64) (err error) 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 { IAdminMonitor interface {
// StartMonitor 启动服务监控
StartMonitor(ctx context.Context) StartMonitor(ctx context.Context)
// GetMeta 获取监控元数据
GetMeta(ctx context.Context) *model.MonitorData GetMeta(ctx context.Context) *model.MonitorData
} }
IAdminPost interface { IAdminPost interface {
// Delete 删除
Delete(ctx context.Context, in *adminin.PostDeleteInp) (err error) Delete(ctx context.Context, in *adminin.PostDeleteInp) (err error)
// VerifyUnique 验证部门唯一属性
VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error) VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error)
// Edit 修改/新增
Edit(ctx context.Context, in *adminin.PostEditInp) (err error) Edit(ctx context.Context, in *adminin.PostEditInp) (err error)
// MaxSort 最大排序
MaxSort(ctx context.Context, in *adminin.PostMaxSortInp) (res *adminin.PostMaxSortModel, err error) 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) 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) 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) GetMemberByStartName(ctx context.Context, memberId int64) (name string, err error)
// Status 更新状态
Status(ctx context.Context, in *adminin.PostStatusInp) (err error) 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 { IAdminDept interface {
// Delete 删除
Delete(ctx context.Context, in *adminin.DeptDeleteInp) (err error) Delete(ctx context.Context, in *adminin.DeptDeleteInp) (err error)
// VerifyUnique 验证部门唯一属性
VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error) VerifyUnique(ctx context.Context, in *adminin.VerifyUniqueInp) (err error)
// Edit 修改/新增
Edit(ctx context.Context, in *adminin.DeptEditInp) (err error) Edit(ctx context.Context, in *adminin.DeptEditInp) (err error)
// Status 更新部门状态
Status(ctx context.Context, in *adminin.DeptStatusInp) (err error) Status(ctx context.Context, in *adminin.DeptStatusInp) (err error)
// MaxSort 最大排序
MaxSort(ctx context.Context, in *adminin.DeptMaxSortInp) (res *adminin.DeptMaxSortModel, err error) 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) 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) 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) List(ctx context.Context, in *adminin.DeptListInp) (res *adminin.DeptListModel, err error)
// GetName 获取部门名称
GetName(ctx context.Context, id int64) (name string, err error) 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 ( var (
localAdminCreditsLog IAdminCreditsLog
localAdminMenu IAdminMenu
localAdminNotice IAdminNotice
localAdminOrder IAdminOrder
localAdminRole IAdminRole
localAdminCash IAdminCash localAdminCash IAdminCash
localAdminDept IAdminDept localAdminCreditsLog IAdminCreditsLog
localAdminMember IAdminMember
localAdminMemberPost IAdminMemberPost localAdminMemberPost IAdminMemberPost
localAdminMenu IAdminMenu
localAdminMonitor IAdminMonitor localAdminMonitor IAdminMonitor
localAdminPost IAdminPost localAdminPost IAdminPost
localAdminRole IAdminRole
localAdminDept IAdminDept
localAdminMember IAdminMember
localAdminNotice IAdminNotice
localAdminOrder IAdminOrder
localAdminSite IAdminSite localAdminSite IAdminSite
) )
func AdminCreditsLog() IAdminCreditsLog { func AdminMonitor() IAdminMonitor {
if localAdminCreditsLog == nil { if localAdminMonitor == nil {
panic("implement not found for interface IAdminCreditsLog, forgot register?") panic("implement not found for interface IAdminMonitor, forgot register?")
} }
return localAdminCreditsLog return localAdminMonitor
} }
func RegisterAdminCreditsLog(i IAdminCreditsLog) { func RegisterAdminMonitor(i IAdminMonitor) {
localAdminCreditsLog = i localAdminMonitor = i
} }
func AdminMenu() IAdminMenu { func AdminPost() IAdminPost {
if localAdminMenu == nil { if localAdminPost == nil {
panic("implement not found for interface IAdminMenu, forgot register?") panic("implement not found for interface IAdminPost, forgot register?")
} }
return localAdminMenu return localAdminPost
} }
func RegisterAdminMenu(i IAdminMenu) { func RegisterAdminPost(i IAdminPost) {
localAdminMenu = i localAdminPost = 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 AdminRole() IAdminRole { func AdminRole() IAdminRole {
@ -218,6 +287,50 @@ func RegisterAdminCash(i IAdminCash) {
localAdminCash = i 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 { func AdminDept() IAdminDept {
if localAdminDept == nil { if localAdminDept == nil {
panic("implement not found for interface IAdminDept, forgot register?") panic("implement not found for interface IAdminDept, forgot register?")
@ -240,46 +353,24 @@ func RegisterAdminMember(i IAdminMember) {
localAdminMember = i localAdminMember = i
} }
func AdminMemberPost() IAdminMemberPost { func AdminNotice() IAdminNotice {
if localAdminMemberPost == nil { if localAdminNotice == nil {
panic("implement not found for interface IAdminMemberPost, forgot register?") panic("implement not found for interface IAdminNotice, forgot register?")
} }
return localAdminMemberPost return localAdminNotice
} }
func RegisterAdminMemberPost(i IAdminMemberPost) { func RegisterAdminNotice(i IAdminNotice) {
localAdminMemberPost = i localAdminNotice = i
} }
func AdminMonitor() IAdminMonitor { func AdminOrder() IAdminOrder {
if localAdminMonitor == nil { if localAdminOrder == nil {
panic("implement not found for interface IAdminMonitor, forgot register?") panic("implement not found for interface IAdminOrder, forgot register?")
} }
return localAdminMonitor return localAdminOrder
} }
func RegisterAdminMonitor(i IAdminMonitor) { func RegisterAdminOrder(i IAdminOrder) {
localAdminMonitor = i localAdminOrder = 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
} }

View File

@ -13,12 +13,104 @@ import (
"hotgo/internal/model/input/sysin" "hotgo/internal/model/input/sysin"
"github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/database/gredis"
"github.com/gogf/gf/v2/net/ghttp"
) )
type ( 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 { ISysConfig interface {
// InitConfig 初始化一些系统启动就需要用到的配置 // InitConfig 初始化系统配置
InitConfig(ctx context.Context) InitConfig(ctx context.Context)
// LoadConfig 加载系统配置
LoadConfig(ctx context.Context) (err error)
// GetLogin 获取登录配置 // GetLogin 获取登录配置
GetLogin(ctx context.Context) (conf *model.LoginConfig, err error) GetLogin(ctx context.Context) (conf *model.LoginConfig, err error)
// GetWechat 获取微信配置 // GetWechat 获取微信配置
@ -53,6 +145,36 @@ type (
ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error) ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
// UpdateConfigByGroup 更新指定分组的配置 // UpdateConfigByGroup 更新指定分组的配置
UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateConfigInp) (err error) 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 { ISysServeLog interface {
// Model 服务日志Orm模型 // Model 服务日志Orm模型
@ -68,31 +190,25 @@ type (
// RealWrite 真实写入 // RealWrite 真实写入
RealWrite(ctx context.Context, models entity.SysServeLog) (err error) 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 获取列表
List(ctx context.Context, in *sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error) List(ctx context.Context, in *sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error)
// Selects 选项 // SendCode 发送验证码
Selects(ctx context.Context, in *sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error) SendCode(ctx context.Context, in *sysin.SendCodeInp) (err error)
// Build 提交生成 // GetTemplate 获取指定短信模板
Build(ctx context.Context, in *sysin.AddonsBuildInp) (err error) GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error)
// Install 安装模块 // AllowSend 是否允许发送
Install(ctx context.Context, in *sysin.AddonsInstallInp) (err error) AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error)
// Upgrade 更新模块 // VerifyCode 效验验证码
Upgrade(ctx context.Context, in *sysin.AddonsUpgradeInp) (err error) VerifyCode(ctx context.Context, in *sysin.VerifyCodeInp) (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)
} }
ISysLog interface { ISysLog interface {
// Export 导出 // Export 导出
@ -110,21 +226,59 @@ type (
// List 列表 // List 列表
List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error) List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
} }
ISysLoginLog interface { ISysProvinces interface {
// Model 登录日志Orm模型 // Tree 关系树选项列表
Model(ctx context.Context) *gdb.Model Tree(ctx context.Context) (list []*sysin.ProvincesTree, err error)
// List 获取登录日志列表 // Delete 删除省市区数据
List(ctx context.Context, in *sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error) Delete(ctx context.Context, in *sysin.ProvincesDeleteInp) (err error)
// Export 导出登录日志 // Edit 修改/新增省市区数据
Export(ctx context.Context, in *sysin.LoginLogListInp) (err error) Edit(ctx context.Context, in *sysin.ProvincesEditInp) (err error)
// Delete 删除登录日志 // Status 更新省市区状态
Delete(ctx context.Context, in *sysin.LoginLogDeleteInp) (err error) Status(ctx context.Context, in *sysin.ProvincesStatusInp) (err error)
// View 获取登录日志指定信息 // MaxSort 最大排序
View(ctx context.Context, in *sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error) MaxSort(ctx context.Context, in *sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error)
// Push 推送登录日志 // View 获取省市区信息
Push(ctx context.Context, in *sysin.LoginLogPushInp) View(ctx context.Context, in *sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error)
// RealWrite 真实写入 // List 获取列表
RealWrite(ctx context.Context, models entity.SysLoginLog) (err error) 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 { ISysCron interface {
StartCron(ctx context.Context) StartCron(ctx context.Context)
@ -143,6 +297,22 @@ type (
// OnlineExec 在线执行 // OnlineExec 在线执行
OnlineExec(ctx context.Context, in *sysin.OnlineExecInp) (err error) 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 { ISysGenCodes interface {
// Delete 删除 // Delete 删除
Delete(ctx context.Context, in *sysin.GenCodesDeleteInp) (err error) Delete(ctx context.Context, in *sysin.GenCodesDeleteInp) (err error)
@ -169,264 +339,38 @@ type (
// Build 提交生成 // Build 提交生成
Build(ctx context.Context, in *sysin.GenCodesBuildInp) (err error) 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 ( var (
localSysAddonsConfig ISysAddonsConfig
localSysDictType ISysDictType
localSysEmsLog ISysEmsLog
localSysAddons ISysAddons
localSysAttachment ISysAttachment
localSysConfig ISysConfig localSysConfig ISysConfig
localSysServeLicense ISysServeLicense
localSysDictType ISysDictType
localSysServeLog ISysServeLog localSysServeLog ISysServeLog
localSysSmsLog ISysSmsLog
localSysAttachment ISysAttachment
localSysBlacklist ISysBlacklist
localSysCron ISysCron localSysCron ISysCron
localSysCronGroup ISysCronGroup
localSysGenCodes ISysGenCodes localSysGenCodes ISysGenCodes
localSysLog ISysLog localSysLog ISysLog
localSysLoginLog ISysLoginLog localSysProvinces ISysProvinces
localSysBlacklist ISysBlacklist localSysAddons ISysAddons
localSysCronGroup ISysCronGroup localSysAddonsConfig ISysAddonsConfig
localSysCurdDemo ISysCurdDemo localSysCurdDemo ISysCurdDemo
localSysDictData ISysDictData localSysDictData ISysDictData
localSysProvinces ISysProvinces localSysEmsLog ISysEmsLog
localSysServeLicense ISysServeLicense localSysLoginLog ISysLoginLog
localSysSmsLog ISysSmsLog
) )
func SysAddons() ISysAddons { func SysEmsLog() ISysEmsLog {
if localSysAddons == nil { if localSysEmsLog == nil {
panic("implement not found for interface ISysAddons, forgot register?") panic("implement not found for interface ISysEmsLog, forgot register?")
} }
return localSysAddons return localSysEmsLog
} }
func RegisterSysAddons(i ISysAddons) { func RegisterSysEmsLog(i ISysEmsLog) {
localSysAddons = i localSysEmsLog = 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 SysLoginLog() ISysLoginLog { func SysLoginLog() ISysLoginLog {
@ -440,37 +384,26 @@ func RegisterSysLoginLog(i ISysLoginLog) {
localSysLoginLog = i localSysLoginLog = i
} }
func SysSmsLog() ISysSmsLog { func SysAddons() ISysAddons {
if localSysSmsLog == nil { if localSysAddons == nil {
panic("implement not found for interface ISysSmsLog, forgot register?") panic("implement not found for interface ISysAddons, forgot register?")
} }
return localSysSmsLog return localSysAddons
} }
func RegisterSysSmsLog(i ISysSmsLog) { func RegisterSysAddons(i ISysAddons) {
localSysSmsLog = i localSysAddons = i
} }
func SysBlacklist() ISysBlacklist { func SysAddonsConfig() ISysAddonsConfig {
if localSysBlacklist == nil { if localSysAddonsConfig == nil {
panic("implement not found for interface ISysBlacklist, forgot register?") panic("implement not found for interface ISysAddonsConfig, forgot register?")
} }
return localSysBlacklist return localSysAddonsConfig
} }
func RegisterSysBlacklist(i ISysBlacklist) { func RegisterSysAddonsConfig(i ISysAddonsConfig) {
localSysBlacklist = i localSysAddonsConfig = 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 SysCurdDemo() ISysCurdDemo { func SysCurdDemo() ISysCurdDemo {
@ -495,15 +428,15 @@ func RegisterSysDictData(i ISysDictData) {
localSysDictData = i localSysDictData = i
} }
func SysProvinces() ISysProvinces { func SysConfig() ISysConfig {
if localSysProvinces == nil { if localSysConfig == nil {
panic("implement not found for interface ISysProvinces, forgot register?") panic("implement not found for interface ISysConfig, forgot register?")
} }
return localSysProvinces return localSysConfig
} }
func RegisterSysProvinces(i ISysProvinces) { func RegisterSysConfig(i ISysConfig) {
localSysProvinces = i localSysConfig = i
} }
func SysServeLicense() ISysServeLicense { func SysServeLicense() ISysServeLicense {
@ -517,17 +450,6 @@ func RegisterSysServeLicense(i ISysServeLicense) {
localSysServeLicense = i 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 { func SysDictType() ISysDictType {
if localSysDictType == nil { if localSysDictType == nil {
panic("implement not found for interface ISysDictType, forgot register?") panic("implement not found for interface ISysDictType, forgot register?")
@ -539,13 +461,101 @@ func RegisterSysDictType(i ISysDictType) {
localSysDictType = i localSysDictType = i
} }
func SysEmsLog() ISysEmsLog { func SysServeLog() ISysServeLog {
if localSysEmsLog == nil { if localSysServeLog == nil {
panic("implement not found for interface ISysEmsLog, forgot register?") panic("implement not found for interface ISysServeLog, forgot register?")
} }
return localSysEmsLog return localSysServeLog
} }
func RegisterSysEmsLog(i ISysEmsLog) { func RegisterSysServeLog(i ISysServeLog) {
localSysEmsLog = i 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
} }

View File

@ -10,6 +10,8 @@ hotgo:
ipMethod: "whois" ipMethod: "whois"
# 是否为演示系统 false|true # 是否为演示系统 false|true
isDemo: false isDemo: false
# 是否为集群部署 false|true 默认为false开启集群必须配置redis通过redis发布订阅进行集群之间的数据同步
isCluster: false
# 全局请求日志 # 全局请求日志
log: log:
switch: true # 日志开关默认为true switch: true # 日志开关默认为true

View File

@ -51,10 +51,10 @@ export const columns = [
title: '表达式', title: '表达式',
key: 'pattern', key: 'pattern',
}, },
{ // {
title: '执行次数', // title: '执行次数',
key: 'count', // key: 'count',
}, // },
{ {
title: '状态', title: '状态',
key: 'status', key: 'status',

View File

@ -144,7 +144,7 @@
</n-modal> </n-modal>
</n-card> </n-card>
<GroupModal ref="GroupModalRef" /> <GroupModal ref="GroupModalRef" @reloadGroupOption="reloadGroupOption"/>
</div> </div>
</template> </template>
@ -450,7 +450,7 @@
openDrawer(); openDrawer();
} }
async function setDictSelect() { async function reloadGroupOption() {
const tmp = await getSelect({}); const tmp = await getSelect({});
optionTreeData.value = tmp.list; optionTreeData.value = tmp.list;
if (optionTreeData.value === undefined || optionTreeData.value === null) { if (optionTreeData.value === undefined || optionTreeData.value === null) {
@ -467,7 +467,7 @@
} }
onBeforeMount(async () => { onBeforeMount(async () => {
await setDictSelect(); await reloadGroupOption();
}); });
// //

View File

@ -40,6 +40,7 @@
:default-value="formParams.pid" :default-value="formParams.pid"
@update:value="handleUpdateValue" @update:value="handleUpdateValue"
/> />
<template #feedback>不选视为顶级分组</template>
</n-form-item> </n-form-item>
<n-form-item label="分组名称" path="name"> <n-form-item label="分组名称" path="name">
<n-input placeholder="请输入分组名称" v-model:value="formParams.name" /> <n-input placeholder="请输入分组名称" v-model:value="formParams.name" />
@ -78,13 +79,14 @@
<script lang="ts" setup> <script lang="ts" setup>
import { h, reactive, ref, onMounted } from 'vue'; import { h, reactive, ref, onMounted } from 'vue';
import { TreeSelectOption, useDialog, useMessage } from 'naive-ui'; import { useDialog, useMessage } from 'naive-ui';
import { BasicTable, TableAction } from '@/components/Table'; import { BasicTable, TableAction } from '@/components/Table';
import { columns } from './columns'; import { columns } from './columns';
import { PlusOutlined } from '@vicons/antd'; import { PlusOutlined } from '@vicons/antd';
import { GroupDelete, GroupEdit, GroupList, getSelect } from '@/api/sys/cron'; import { GroupDelete, GroupEdit, GroupList, getSelect } from '@/api/sys/cron';
import { statusOptions } from '@/enums/optionsiEnum'; import { statusOptions } from '@/enums/optionsiEnum';
const emit = defineEmits(['reloadGroupOption']);
const optionTreeData = ref([]); const optionTreeData = ref([]);
const message = useMessage(); const message = useMessage();
const statusValue = ref(1); const statusValue = ref(1);
@ -206,6 +208,7 @@
function reloadTable() { function reloadTable() {
actionRef.value.reload(); actionRef.value.reload();
emit('reloadGroupOption');
} }
async function setDictSelect() { async function setDictSelect() {
@ -221,10 +224,7 @@
}); });
// //
function handleUpdateValue( function handleUpdateValue(value: string | number | Array<string | number> | null) {
value: string | number | Array<string | number> | null,
_option: TreeSelectOption | null | Array<TreeSelectOption | null>
) {
formParams.value.pid = value; formParams.value.pid = value;
} }
</script> </script>

View File

@ -7,7 +7,7 @@
preset="dialog" preset="dialog"
:title="title" :title="title"
> >
<Index /> <Index @reloadGroupOption="reloadGroupOption" />
</n-modal> </n-modal>
</div> </div>
</template> </template>
@ -16,6 +16,7 @@
import { ref } from 'vue'; import { ref } from 'vue';
import Index from './index.vue'; import Index from './index.vue';
const emit = defineEmits(['reloadGroupOption']);
const showModal = ref(false); const showModal = ref(false);
const title = ref('管理分组'); const title = ref('管理分组');
@ -23,6 +24,10 @@
showModal.value = true; showModal.value = true;
} }
function reloadGroupOption() {
emit('reloadGroupOption');
}
defineExpose({ openDrawer }); defineExpose({ openDrawer });
</script> </script>