新功能(#69): 支持用户级限速覆盖

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
2026-05-26 11:26:27 -07:00
parent 22d9773f1b
commit f30b7cded7
9 changed files with 95 additions and 42 deletions
@@ -36,6 +36,10 @@ func (l *GetUserSubscribeByIdLogic) GetUserSubscribeById(req *types.GetUserSubsc
}
var subscribeDetails types.UserSubscribeDetail
tool.DeepCopy(&subscribeDetails, sub)
subscribeDetails.SpeedLimit = sub.SpeedLimit
if sub.TrafficLimit != nil {
subscribeDetails.TrafficLimit = *sub.TrafficLimit
}
// 填充分组名
if sub.NodeGroupId > 0 {
@@ -47,7 +51,17 @@ func (l *GetUserSubscribeByIdLogic) GetUserSubscribeById(req *types.GetUserSubsc
// Calculate speed limit status
if sub.Subscribe != nil && sub.Status == 1 {
result := speedlimit.Calculate(l.ctx, l.svcCtx.DB, sub.UserId, sub.Id, sub.Subscribe.SpeedLimit, sub.Subscribe.TrafficLimit)
baseSpeed := sub.Subscribe.SpeedLimit
if sub.SpeedLimit > 0 {
baseSpeed = sub.SpeedLimit
}
trafficLimit := sub.Subscribe.TrafficLimit
if sub.TrafficLimit != nil && *sub.TrafficLimit != "" {
trafficLimit = *sub.TrafficLimit
}
result := speedlimit.Calculate(l.ctx, l.svcCtx.DB, sub.UserId, sub.Id, baseSpeed, trafficLimit)
subscribeDetails.EffectiveSpeed = result.EffectiveSpeed
subscribeDetails.IsThrottled = result.IsThrottled
subscribeDetails.ThrottleRule = result.ThrottleRule
@@ -40,21 +40,32 @@ func (l *UpdateUserSubscribeLogic) UpdateUserSubscribe(req *types.UpdateUserSubs
userSub.Status = 1
}
speedLimit := userSub.SpeedLimit
if req.SpeedLimit != nil {
speedLimit = *req.SpeedLimit
}
trafficLimit := userSub.TrafficLimit
if req.TrafficLimit != nil {
trafficLimit = req.TrafficLimit
}
err = l.svcCtx.UserModel.UpdateSubscribe(l.ctx, &user.Subscribe{
Id: userSub.Id,
UserId: userSub.UserId,
OrderId: userSub.OrderId,
SubscribeId: req.SubscribeId,
StartTime: userSub.StartTime,
ExpireTime: time.UnixMilli(req.ExpiredAt),
Traffic: req.Traffic,
Download: req.Download,
Upload: req.Upload,
Token: userSub.Token,
UUID: userSub.UUID,
Status: userSub.Status,
NodeGroupId: userSub.NodeGroupId,
GroupLocked: userSub.GroupLocked,
Id: userSub.Id,
UserId: userSub.UserId,
OrderId: userSub.OrderId,
SubscribeId: req.SubscribeId,
StartTime: userSub.StartTime,
ExpireTime: time.UnixMilli(req.ExpiredAt),
Traffic: req.Traffic,
Download: req.Download,
Upload: req.Upload,
SpeedLimit: speedLimit,
TrafficLimit: trafficLimit,
Token: userSub.Token,
UUID: userSub.UUID,
Status: userSub.Status,
NodeGroupId: userSub.NodeGroupId,
GroupLocked: userSub.GroupLocked,
})
if err != nil {
@@ -307,14 +307,24 @@ func (l *GetServerUserListLogic) canUseExpiredNodeGroup(userSub *user.Subscribe,
// calculateEffectiveSpeedLimit 计算用户的实际限速值(考虑按量限速规则)
func (l *GetServerUserListLogic) calculateEffectiveSpeedLimit(sub *subscribe.Subscribe, userSub *user.Subscribe) int64 {
baseSpeed := sub.SpeedLimit
if userSub.SpeedLimit > 0 {
baseSpeed = userSub.SpeedLimit
}
trafficLimit := sub.TrafficLimit
if userSub.TrafficLimit != nil && *userSub.TrafficLimit != "" {
trafficLimit = *userSub.TrafficLimit
}
result := speedlimit.CalculateWithCache(
l.ctx.Request.Context(),
l.svcCtx.Redis,
l.svcCtx.DB,
userSub.UserId,
userSub.Id,
sub.SpeedLimit,
sub.TrafficLimit,
baseSpeed,
trafficLimit,
30*time.Second,
)
return result.EffectiveSpeed