Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
25c7b0d9
"frontend/src/components/vscode:/vscode.git/clone" did not exist on "3b7a5fff3123ce7b82cf24aa633f7d6194c4d267"
Commit
25c7b0d9
authored
Apr 27, 2026
by
KnowSky404
Browse files
feat: support filter-target account bulk update
parent
f422ac6d
Changes
2
Show whitespace changes
Inline
Side-by-side
backend/internal/handler/admin/account_handler.go
View file @
25c7b0d9
...
...
@@ -134,7 +134,8 @@ type UpdateAccountRequest struct {
// BulkUpdateAccountsRequest represents the payload for bulk editing accounts
type
BulkUpdateAccountsRequest
struct
{
AccountIDs
[]
int64
`json:"account_ids" binding:"required,min=1"`
AccountIDs
[]
int64
`json:"account_ids"`
Filters
*
BulkUpdateAccountFilters
`json:"filters"`
Name
string
`json:"name"`
ProxyID
*
int64
`json:"proxy_id"`
Concurrency
*
int
`json:"concurrency"`
...
...
@@ -149,6 +150,15 @@ type BulkUpdateAccountsRequest struct {
ConfirmMixedChannelRisk
*
bool
`json:"confirm_mixed_channel_risk"`
// 用户确认混合渠道风险
}
type
BulkUpdateAccountFilters
struct
{
Platform
string
`json:"platform"`
Type
string
`json:"type"`
Status
string
`json:"status"`
Group
string
`json:"group"`
Search
string
`json:"search"`
PrivacyMode
string
`json:"privacy_mode"`
}
// CheckMixedChannelRequest represents check mixed channel risk request
type
CheckMixedChannelRequest
struct
{
Platform
string
`json:"platform" binding:"required"`
...
...
@@ -1369,6 +1379,10 @@ func (h *AccountHandler) BulkUpdate(c *gin.Context) {
response
.
BadRequest
(
c
,
"rate_multiplier must be >= 0"
)
return
}
if
len
(
req
.
AccountIDs
)
==
0
&&
req
.
Filters
==
nil
{
response
.
BadRequest
(
c
,
"account_ids or filters is required"
)
return
}
// base_rpm 输入校验:负值归零,超过 10000 截断
sanitizeExtraBaseRPM
(
req
.
Extra
)
...
...
@@ -1394,6 +1408,7 @@ func (h *AccountHandler) BulkUpdate(c *gin.Context) {
result
,
err
:=
h
.
adminService
.
BulkUpdateAccounts
(
c
.
Request
.
Context
(),
&
service
.
BulkUpdateAccountsInput
{
AccountIDs
:
req
.
AccountIDs
,
Filters
:
toServiceBulkUpdateAccountFilters
(
req
.
Filters
),
Name
:
req
.
Name
,
ProxyID
:
req
.
ProxyID
,
Concurrency
:
req
.
Concurrency
,
...
...
@@ -1429,6 +1444,20 @@ func (h *AccountHandler) BulkUpdate(c *gin.Context) {
response
.
Success
(
c
,
result
)
}
func
toServiceBulkUpdateAccountFilters
(
filters
*
BulkUpdateAccountFilters
)
*
service
.
BulkUpdateAccountFilters
{
if
filters
==
nil
{
return
nil
}
return
&
service
.
BulkUpdateAccountFilters
{
Platform
:
filters
.
Platform
,
Type
:
filters
.
Type
,
Status
:
filters
.
Status
,
Group
:
filters
.
Group
,
Search
:
filters
.
Search
,
PrivacyMode
:
filters
.
PrivacyMode
,
}
}
// ========== OAuth Handlers ==========
// GenerateAuthURLRequest represents the request for generating auth URL
...
...
backend/internal/service/admin_service.go
View file @
25c7b0d9
...
...
@@ -9,6 +9,7 @@ import (
"log/slog"
"net/http"
"sort"
"strconv"
"strings"
"time"
...
...
@@ -291,6 +292,7 @@ type UpdateAccountInput struct {
// BulkUpdateAccountsInput describes the payload for bulk updating accounts.
type
BulkUpdateAccountsInput
struct
{
AccountIDs
[]
int64
Filters
*
BulkUpdateAccountFilters
Name
string
ProxyID
*
int64
Concurrency
*
int
...
...
@@ -307,6 +309,15 @@ type BulkUpdateAccountsInput struct {
SkipMixedChannelCheck
bool
}
type
BulkUpdateAccountFilters
struct
{
Platform
string
Type
string
Status
string
Group
string
Search
string
PrivacyMode
string
}
// BulkUpdateAccountResult captures the result for a single account update.
type
BulkUpdateAccountResult
struct
{
AccountID
int64
`json:"account_id"`
...
...
@@ -2286,6 +2297,14 @@ func (s *adminServiceImpl) UpdateAccount(ctx context.Context, id int64, input *U
// BulkUpdateAccounts updates multiple accounts in one request.
// It merges credentials/extra keys instead of overwriting the whole object.
func
(
s
*
adminServiceImpl
)
BulkUpdateAccounts
(
ctx
context
.
Context
,
input
*
BulkUpdateAccountsInput
)
(
*
BulkUpdateAccountsResult
,
error
)
{
if
len
(
input
.
AccountIDs
)
==
0
&&
input
.
Filters
!=
nil
{
accountIDs
,
err
:=
s
.
resolveBulkUpdateTargetIDs
(
ctx
,
input
.
Filters
)
if
err
!=
nil
{
return
nil
,
err
}
input
.
AccountIDs
=
accountIDs
}
result
:=
&
BulkUpdateAccountsResult
{
SuccessIDs
:
make
([]
int64
,
0
,
len
(
input
.
AccountIDs
)),
FailedIDs
:
make
([]
int64
,
0
,
len
(
input
.
AccountIDs
)),
...
...
@@ -2401,6 +2420,55 @@ func (s *adminServiceImpl) BulkUpdateAccounts(ctx context.Context, input *BulkUp
return
result
,
nil
}
func
(
s
*
adminServiceImpl
)
resolveBulkUpdateTargetIDs
(
ctx
context
.
Context
,
filters
*
BulkUpdateAccountFilters
)
([]
int64
,
error
)
{
if
filters
==
nil
{
return
nil
,
nil
}
groupID
:=
int64
(
0
)
switch
strings
.
TrimSpace
(
filters
.
Group
)
{
case
""
:
case
"ungrouped"
:
groupID
=
AccountListGroupUngrouped
default
:
parsedGroupID
,
err
:=
strconv
.
ParseInt
(
strings
.
TrimSpace
(
filters
.
Group
),
10
,
64
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid group filter: %w"
,
err
)
}
groupID
=
parsedGroupID
}
const
pageSize
=
500
page
:=
1
accountIDs
:=
make
([]
int64
,
0
,
pageSize
)
for
{
accounts
,
total
,
err
:=
s
.
ListAccounts
(
ctx
,
page
,
pageSize
,
filters
.
Platform
,
filters
.
Type
,
filters
.
Status
,
filters
.
Search
,
groupID
,
filters
.
PrivacyMode
,
""
,
""
,
)
if
err
!=
nil
{
return
nil
,
err
}
for
_
,
account
:=
range
accounts
{
accountIDs
=
append
(
accountIDs
,
account
.
ID
)
}
if
int64
(
len
(
accountIDs
))
>=
total
||
len
(
accounts
)
==
0
{
return
accountIDs
,
nil
}
page
++
}
}
func
(
s
*
adminServiceImpl
)
DeleteAccount
(
ctx
context
.
Context
,
id
int64
)
error
{
if
err
:=
s
.
accountRepo
.
Delete
(
ctx
,
id
);
err
!=
nil
{
return
err
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment