This commit is contained in:
@@ -202,27 +202,36 @@ func (m *customServerModel) ClearServerAllCache(ctx context.Context) error {
|
||||
|
||||
// CountNodesByIdsAndTags 根据节点ID和标签计算启用的节点数量
|
||||
func (m *customServerModel) CountNodesByIdsAndTags(ctx context.Context, nodeIds []int64, tags []string) (int64, error) {
|
||||
tags = normalizeNodeTags(tags)
|
||||
if len(nodeIds) == 0 && len(tags) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var count int64
|
||||
query := m.WithContext(ctx).Model(&Node{}).Where("enabled = ?", true)
|
||||
|
||||
if len(nodeIds) > 0 || len(tags) > 0 {
|
||||
subQuery := m.WithContext(ctx).Model(&Node{}).Where("enabled = ?", true)
|
||||
|
||||
if len(nodeIds) > 0 && len(tags) > 0 {
|
||||
subQuery = subQuery.Where("id IN ? OR ?", nodeIds, InSet("tags", tags))
|
||||
} else if len(nodeIds) > 0 {
|
||||
subQuery = subQuery.Where("id IN ?", nodeIds)
|
||||
} else {
|
||||
subQuery = subQuery.Scopes(InSet("tags", tags))
|
||||
}
|
||||
|
||||
query = subQuery
|
||||
if len(nodeIds) > 0 {
|
||||
query = query.Where("id IN ?", nodeIds)
|
||||
}
|
||||
if len(tags) > 0 {
|
||||
query = query.Scopes(InSet("tags", tags))
|
||||
}
|
||||
|
||||
err := query.Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
func normalizeNodeTags(tags []string) []string {
|
||||
cleaned := make([]string, 0, len(tags))
|
||||
for _, tag := range tags {
|
||||
trimmed := strings.TrimSpace(tag)
|
||||
if trimmed == "" {
|
||||
continue
|
||||
}
|
||||
cleaned = append(cleaned, trimmed)
|
||||
}
|
||||
return tool.RemoveDuplicateElements(cleaned...)
|
||||
}
|
||||
|
||||
// InSet 支持多值 OR 查询
|
||||
func InSet(field string, values []string) func(db *gorm.DB) *gorm.DB {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNormalizeNodeTags(t *testing.T) {
|
||||
tags := normalizeNodeTags([]string{"美国", " 日本 ", "", "美国", " ", "日本"})
|
||||
require.Equal(t, []string{"美国", "日本"}, tags)
|
||||
}
|
||||
@@ -15,7 +15,8 @@ import (
|
||||
|
||||
var _ Model = (*customSubscribeModel)(nil)
|
||||
var (
|
||||
cacheSubscribeIdPrefix = "cache:subscribe:id:"
|
||||
cacheSubscribeIdPrefix = "cache:subscribe:id:"
|
||||
cacheUserSubscribeUserPrefix = "cache:user:subscribe:user:"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -119,13 +120,31 @@ func (m *defaultSubscribeModel) Update(ctx context.Context, data *Subscribe, tx
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
var userIds []int64
|
||||
err = m.QueryNoCacheCtx(ctx, &userIds, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Table("user_subscribe").
|
||||
Where("subscribe_id = ? AND status IN (0, 1)", data.Id).
|
||||
Distinct("user_id").
|
||||
Pluck("user_id", &userIds).Error
|
||||
})
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
userSubscribeCacheKeys := make([]string, 0, len(userIds))
|
||||
for _, userId := range userIds {
|
||||
userSubscribeCacheKeys = append(userSubscribeCacheKeys, fmt.Sprintf("%s%d", cacheUserSubscribeUserPrefix, userId))
|
||||
}
|
||||
allCacheKeys := append(m.getCacheKeys(old), userSubscribeCacheKeys...)
|
||||
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
if len(tx) > 0 {
|
||||
db = tx[0]
|
||||
}
|
||||
return db.Save(data).Error
|
||||
}, m.getCacheKeys(old)...)
|
||||
}, allCacheKeys...)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -137,13 +156,31 @@ func (m *defaultSubscribeModel) Delete(ctx context.Context, id int64, tx ...*gor
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
var userIds []int64
|
||||
err = m.QueryNoCacheCtx(ctx, &userIds, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Table("user_subscribe").
|
||||
Where("subscribe_id = ? AND status IN (0, 1)", id).
|
||||
Distinct("user_id").
|
||||
Pluck("user_id", &userIds).Error
|
||||
})
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
userSubscribeCacheKeys := make([]string, 0, len(userIds))
|
||||
for _, userId := range userIds {
|
||||
userSubscribeCacheKeys = append(userSubscribeCacheKeys, fmt.Sprintf("%s%d", cacheUserSubscribeUserPrefix, userId))
|
||||
}
|
||||
allCacheKeys := append(m.getCacheKeys(data), userSubscribeCacheKeys...)
|
||||
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
if len(tx) > 0 {
|
||||
db = tx[0]
|
||||
}
|
||||
return db.Delete(&Subscribe{}, id).Error
|
||||
}, m.getCacheKeys(data)...)
|
||||
}, allCacheKeys...)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ type customSystemLogicModel interface {
|
||||
GetTosConfig(ctx context.Context) ([]*System, error)
|
||||
GetCurrencyConfig(ctx context.Context) ([]*System, error)
|
||||
GetVerifyCodeConfig(ctx context.Context) ([]*System, error)
|
||||
GetSignatureConfig(ctx context.Context) ([]*System, error)
|
||||
GetLogConfig(ctx context.Context) ([]*System, error)
|
||||
UpdateNodeMultiplierConfig(ctx context.Context, config string) error
|
||||
FindNodeMultiplierConfig(ctx context.Context) (*System, error)
|
||||
@@ -154,6 +155,15 @@ func (m *customSystemModel) GetVerifyCodeConfig(ctx context.Context) ([]*System,
|
||||
return configs, err
|
||||
}
|
||||
|
||||
// GetSignatureConfig returns the signature config.
|
||||
func (m *customSystemModel) GetSignatureConfig(ctx context.Context) ([]*System, error) {
|
||||
var configs []*System
|
||||
err := m.QueryCtx(ctx, &configs, config.SignatureConfigKey, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Where("`category` = ?", "signature").Find(v).Error
|
||||
})
|
||||
return configs, err
|
||||
}
|
||||
|
||||
// GetLogConfig returns the log config.
|
||||
func (m *customSystemModel) GetLogConfig(ctx context.Context) ([]*System, error) {
|
||||
var configs []*System
|
||||
|
||||
Reference in New Issue
Block a user