新功能(#65): 添加用户订阅限速数据层字段
Build docker and publish / build (20.15.1) (push) Failing after 8m30s
Build docker and publish / build (20.15.1) (pull_request) Successful in 7m58s

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
2026-05-26 11:16:43 -07:00
parent 22d9773f1b
commit 5ebfe0a981
6 changed files with 135 additions and 74 deletions
+14 -33
View File
@@ -76,29 +76,6 @@ type (
GiftAmount int64 `json:"gift_amount"` GiftAmount int64 `json:"gift_amount"`
IsAdmin bool `json:"is_admin"` IsAdmin bool `json:"is_admin"`
} }
UserSubscribeDetail {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
User User `json:"user"`
OrderId int64 `json:"order_id"`
SubscribeId int64 `json:"subscribe_id"`
Subscribe Subscribe `json:"subscribe"`
NodeGroupId int64 `json:"node_group_id"`
GroupLocked bool `json:"group_locked"`
StartTime int64 `json:"start_time"`
ExpireTime int64 `json:"expire_time"`
ResetTime int64 `json:"reset_time"`
Traffic int64 `json:"traffic"`
Download int64 `json:"download"`
Upload int64 `json:"upload"`
Token string `json:"token"`
Status uint8 `json:"status"`
EffectiveSpeed int64 `json:"effective_speed"`
IsThrottled bool `json:"is_throttled"`
ThrottleRule string `json:"throttle_rule,omitempty"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
BatchDeleteUserRequest { BatchDeleteUserRequest {
Ids []int64 `json:"ids" validate:"required"` Ids []int64 `json:"ids" validate:"required"`
} }
@@ -158,18 +135,22 @@ type (
Total int64 `json:"total"` Total int64 `json:"total"`
} }
CreateUserSubscribeRequest { CreateUserSubscribeRequest {
UserId int64 `json:"user_id"` UserId int64 `json:"user_id"`
ExpiredAt int64 `json:"expired_at"` ExpiredAt int64 `json:"expired_at"`
Traffic int64 `json:"traffic"` Traffic int64 `json:"traffic"`
SubscribeId int64 `json:"subscribe_id"` SubscribeId int64 `json:"subscribe_id"`
SpeedLimit int64 `json:"speed_limit,optional"`
TrafficLimit string `json:"traffic_limit,optional"`
} }
UpdateUserSubscribeRequest { UpdateUserSubscribeRequest {
UserSubscribeId int64 `json:"user_subscribe_id"` UserSubscribeId int64 `json:"user_subscribe_id"`
SubscribeId int64 `json:"subscribe_id"` SubscribeId int64 `json:"subscribe_id"`
Traffic int64 `json:"traffic"` Traffic int64 `json:"traffic"`
ExpiredAt int64 `json:"expired_at"` ExpiredAt int64 `json:"expired_at"`
Upload int64 `json:"upload"` Upload int64 `json:"upload"`
Download int64 `json:"download"` Download int64 `json:"download"`
SpeedLimit *int64 `json:"speed_limit,omitempty"`
TrafficLimit *string `json:"traffic_limit,omitempty"`
} }
GetUserLoginLogsRequest { GetUserLoginLogsRequest {
Page int `form:"page"` Page int `form:"page"`
+36 -7
View File
@@ -171,13 +171,13 @@ type (
DeviceLimit int64 `json:"device_limit"` DeviceLimit int64 `json:"device_limit"`
} }
VerifyConfig { VerifyConfig {
CaptchaType string `json:"captcha_type"` // local or turnstile CaptchaType string `json:"captcha_type"` // local or turnstile
TurnstileSiteKey string `json:"turnstile_site_key"` TurnstileSiteKey string `json:"turnstile_site_key"`
TurnstileSecret string `json:"turnstile_secret"` TurnstileSecret string `json:"turnstile_secret"`
EnableUserLoginCaptcha bool `json:"enable_user_login_captcha"` // User login captcha EnableUserLoginCaptcha bool `json:"enable_user_login_captcha"` // User login captcha
EnableUserRegisterCaptcha bool `json:"enable_user_register_captcha"` // User register captcha EnableUserRegisterCaptcha bool `json:"enable_user_register_captcha"` // User register captcha
EnableAdminLoginCaptcha bool `json:"enable_admin_login_captcha"` // Admin login captcha EnableAdminLoginCaptcha bool `json:"enable_admin_login_captcha"` // Admin login captcha
EnableUserResetPasswordCaptcha bool `json:"enable_user_reset_password_captcha"` // User reset password captcha EnableUserResetPasswordCaptcha bool `json:"enable_user_reset_password_captcha"` // User reset password captcha
} }
NodeConfig { NodeConfig {
NodeSecret string `json:"node_secret"` NodeSecret string `json:"node_secret"`
@@ -536,6 +536,35 @@ type (
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
} }
UserSubscribeDetail {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
User User `json:"user"`
OrderId int64 `json:"order_id"`
SubscribeId int64 `json:"subscribe_id"`
Subscribe Subscribe `json:"subscribe"`
NodeGroupId int64 `json:"node_group_id"`
NodeGroupName string `json:"node_group_name"`
GroupLocked bool `json:"group_locked"`
StartTime int64 `json:"start_time"`
ExpireTime int64 `json:"expire_time"`
ResetTime int64 `json:"reset_time"`
Traffic int64 `json:"traffic"`
Download int64 `json:"download"`
Upload int64 `json:"upload"`
SpeedLimit int64 `json:"speed_limit"`
TrafficLimit []TrafficLimit `json:"user_traffic_limit"`
PlanSpeedLimit int64 `json:"plan_speed_limit"`
Token string `json:"token"`
Status uint8 `json:"status"`
EffectiveSpeed int64 `json:"effective_speed"`
IsThrottled bool `json:"is_throttled"`
ThrottleRule string `json:"throttle_rule,omitempty"`
ThrottleStart int64 `json:"throttle_start,omitempty"`
ThrottleEnd int64 `json:"throttle_end,omitempty"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
UserAffiliate { UserAffiliate {
Avatar string `json:"avatar"` Avatar string `json:"avatar"`
Identifier string `json:"identifier"` Identifier string `json:"identifier"`
@@ -0,0 +1,5 @@
-- Purpose: Rollback user-level speed limit overrides from user_subscribe
ALTER TABLE `user_subscribe`
DROP COLUMN IF EXISTS `traffic_limit`,
DROP COLUMN IF EXISTS `speed_limit`;
@@ -0,0 +1,37 @@
-- Purpose: Add user-level speed limit overrides to user_subscribe
SET @column_exists = (
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'user_subscribe'
AND COLUMN_NAME = 'speed_limit'
);
SET @sql = IF(
@column_exists = 0,
'ALTER TABLE `user_subscribe` ADD COLUMN `speed_limit` int NOT NULL DEFAULT 0 COMMENT ''User-level speed limit override (Mbps, 0=use plan default)'' AFTER `upload`',
'SELECT ''Column speed_limit already exists in user_subscribe table'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @column_exists = (
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'user_subscribe'
AND COLUMN_NAME = 'traffic_limit'
);
SET @sql = IF(
@column_exists = 0,
'ALTER TABLE `user_subscribe` ADD COLUMN `traffic_limit` text DEFAULT NULL COMMENT ''User-level traffic limit rules override (JSON, NULL=use plan default)'' AFTER `speed_limit`',
'SELECT ''Column traffic_limit already exists in user_subscribe table'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
+2
View File
@@ -101,6 +101,8 @@ type Subscribe struct {
Traffic int64 `gorm:"default:0;comment:Traffic"` Traffic int64 `gorm:"default:0;comment:Traffic"`
Download int64 `gorm:"default:0;comment:Download Traffic"` Download int64 `gorm:"default:0;comment:Download Traffic"`
Upload int64 `gorm:"default:0;comment:Upload Traffic"` Upload int64 `gorm:"default:0;comment:Upload Traffic"`
SpeedLimit int64 `gorm:"default:0;comment:User-level speed limit override (Mbps, 0=use plan default)"`
TrafficLimit string `gorm:"type:text;default:null;comment:User-level traffic limit rules override (JSON)"`
ExpiredDownload int64 `gorm:"default:0;comment:Expired period download traffic (bytes)"` ExpiredDownload int64 `gorm:"default:0;comment:Expired period download traffic (bytes)"`
ExpiredUpload int64 `gorm:"default:0;comment:Expired period upload traffic (bytes)"` ExpiredUpload int64 `gorm:"default:0;comment:Expired period upload traffic (bytes)"`
Token string `gorm:"index:idx_token;unique;type:varchar(255);default:'';comment:Token"` Token string `gorm:"index:idx_token;unique;type:varchar(255);default:'';comment:Token"`
+41 -34
View File
@@ -541,10 +541,12 @@ type CreateUserRequest struct {
} }
type CreateUserSubscribeRequest struct { type CreateUserSubscribeRequest struct {
UserId int64 `json:"user_id"` UserId int64 `json:"user_id"`
ExpiredAt int64 `json:"expired_at"` ExpiredAt int64 `json:"expired_at"`
Traffic int64 `json:"traffic"` Traffic int64 `json:"traffic"`
SubscribeId int64 `json:"subscribe_id"` SubscribeId int64 `json:"subscribe_id"`
SpeedLimit int64 `json:"speed_limit,optional"`
TrafficLimit string `json:"traffic_limit,optional"`
} }
type CreateUserTicketFollowRequest struct { type CreateUserTicketFollowRequest struct {
@@ -3317,12 +3319,14 @@ type UpdateUserSubscribeNoteRequest struct {
} }
type UpdateUserSubscribeRequest struct { type UpdateUserSubscribeRequest struct {
UserSubscribeId int64 `json:"user_subscribe_id"` UserSubscribeId int64 `json:"user_subscribe_id"`
SubscribeId int64 `json:"subscribe_id"` SubscribeId int64 `json:"subscribe_id"`
Traffic int64 `json:"traffic"` Traffic int64 `json:"traffic"`
ExpiredAt int64 `json:"expired_at"` ExpiredAt int64 `json:"expired_at"`
Upload int64 `json:"upload"` Upload int64 `json:"upload"`
Download int64 `json:"download"` Download int64 `json:"download"`
SpeedLimit *int64 `json:"speed_limit,omitempty"`
TrafficLimit *string `json:"traffic_limit,omitempty"`
} }
type UpdateUserTicketStatusRequest struct { type UpdateUserTicketStatusRequest struct {
@@ -3474,30 +3478,33 @@ type UserSubscribe struct {
} }
type UserSubscribeDetail struct { type UserSubscribeDetail struct {
Id int64 `json:"id"` Id int64 `json:"id"`
UserId int64 `json:"user_id"` UserId int64 `json:"user_id"`
User User `json:"user"` User User `json:"user"`
OrderId int64 `json:"order_id"` OrderId int64 `json:"order_id"`
SubscribeId int64 `json:"subscribe_id"` SubscribeId int64 `json:"subscribe_id"`
Subscribe Subscribe `json:"subscribe"` Subscribe Subscribe `json:"subscribe"`
NodeGroupId int64 `json:"node_group_id"` NodeGroupId int64 `json:"node_group_id"`
NodeGroupName string `json:"node_group_name"` NodeGroupName string `json:"node_group_name"`
GroupLocked bool `json:"group_locked"` GroupLocked bool `json:"group_locked"`
StartTime int64 `json:"start_time"` StartTime int64 `json:"start_time"`
ExpireTime int64 `json:"expire_time"` ExpireTime int64 `json:"expire_time"`
ResetTime int64 `json:"reset_time"` ResetTime int64 `json:"reset_time"`
Traffic int64 `json:"traffic"` Traffic int64 `json:"traffic"`
Download int64 `json:"download"` Download int64 `json:"download"`
Upload int64 `json:"upload"` Upload int64 `json:"upload"`
Token string `json:"token"` SpeedLimit int64 `json:"speed_limit"`
Status uint8 `json:"status"` TrafficLimit []TrafficLimit `json:"user_traffic_limit"`
EffectiveSpeed int64 `json:"effective_speed"` PlanSpeedLimit int64 `json:"plan_speed_limit"`
IsThrottled bool `json:"is_throttled"` Token string `json:"token"`
ThrottleRule string `json:"throttle_rule,omitempty"` Status uint8 `json:"status"`
ThrottleStart int64 `json:"throttle_start,omitempty"` EffectiveSpeed int64 `json:"effective_speed"`
ThrottleEnd int64 `json:"throttle_end,omitempty"` IsThrottled bool `json:"is_throttled"`
CreatedAt int64 `json:"created_at"` ThrottleRule string `json:"throttle_rule,omitempty"`
UpdatedAt int64 `json:"updated_at"` ThrottleStart int64 `json:"throttle_start,omitempty"`
ThrottleEnd int64 `json:"throttle_end,omitempty"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
} }
type UserSubscribeInfo struct { type UserSubscribeInfo struct {