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
d9e27df9
Commit
d9e27df9
authored
Dec 23, 2025
by
shaw
Browse files
feat: 账号列表显示所属分组
- Account模型新增Groups虚拟字段 - 账号列表API预加载Group信息 - 账号管理页面新增分组列,使用GroupBadge展示
parent
f0fabf89
Changes
6
Show whitespace changes
Inline
Side-by-side
backend/internal/model/account.go
View file @
d9e27df9
...
@@ -69,6 +69,7 @@ type Account struct {
...
@@ -69,6 +69,7 @@ type Account struct {
// 虚拟字段 (不存储到数据库)
// 虚拟字段 (不存储到数据库)
GroupIDs
[]
int64
`gorm:"-" json:"group_ids,omitempty"`
GroupIDs
[]
int64
`gorm:"-" json:"group_ids,omitempty"`
Groups
[]
*
Group
`gorm:"-" json:"groups,omitempty"`
}
}
func
(
Account
)
TableName
()
string
{
func
(
Account
)
TableName
()
string
{
...
...
backend/internal/repository/account_repo.go
View file @
d9e27df9
...
@@ -78,15 +78,19 @@ func (r *AccountRepository) ListWithFilters(ctx context.Context, params paginati
...
@@ -78,15 +78,19 @@ func (r *AccountRepository) ListWithFilters(ctx context.Context, params paginati
return
nil
,
nil
,
err
return
nil
,
nil
,
err
}
}
if
err
:=
db
.
Preload
(
"Proxy"
)
.
Preload
(
"AccountGroups"
)
.
Offset
(
params
.
Offset
())
.
Limit
(
params
.
Limit
())
.
Order
(
"id DESC"
)
.
Find
(
&
accounts
)
.
Error
;
err
!=
nil
{
if
err
:=
db
.
Preload
(
"Proxy"
)
.
Preload
(
"AccountGroups
.Group
"
)
.
Offset
(
params
.
Offset
())
.
Limit
(
params
.
Limit
())
.
Order
(
"id DESC"
)
.
Find
(
&
accounts
)
.
Error
;
err
!=
nil
{
return
nil
,
nil
,
err
return
nil
,
nil
,
err
}
}
// 填充每个 Account 的
GroupIDs
虚拟字段
// 填充每个 Account 的
虚拟字段(
GroupIDs
和 Groups)
for
i
:=
range
accounts
{
for
i
:=
range
accounts
{
accounts
[
i
]
.
GroupIDs
=
make
([]
int64
,
0
,
len
(
accounts
[
i
]
.
AccountGroups
))
accounts
[
i
]
.
GroupIDs
=
make
([]
int64
,
0
,
len
(
accounts
[
i
]
.
AccountGroups
))
accounts
[
i
]
.
Groups
=
make
([]
*
model
.
Group
,
0
,
len
(
accounts
[
i
]
.
AccountGroups
))
for
_
,
ag
:=
range
accounts
[
i
]
.
AccountGroups
{
for
_
,
ag
:=
range
accounts
[
i
]
.
AccountGroups
{
accounts
[
i
]
.
GroupIDs
=
append
(
accounts
[
i
]
.
GroupIDs
,
ag
.
GroupID
)
accounts
[
i
]
.
GroupIDs
=
append
(
accounts
[
i
]
.
GroupIDs
,
ag
.
GroupID
)
if
ag
.
Group
!=
nil
{
accounts
[
i
]
.
Groups
=
append
(
accounts
[
i
]
.
Groups
,
ag
.
Group
)
}
}
}
}
}
...
...
frontend/src/i18n/locales/en.ts
View file @
d9e27df9
...
@@ -666,6 +666,7 @@ export default {
...
@@ -666,6 +666,7 @@ export default {
status
:
'
Status
'
,
status
:
'
Status
'
,
schedulable
:
'
Schedule
'
,
schedulable
:
'
Schedule
'
,
todayStats
:
"
Today's Stats
"
,
todayStats
:
"
Today's Stats
"
,
groups
:
'
Groups
'
,
usageWindows
:
'
Usage Windows
'
,
usageWindows
:
'
Usage Windows
'
,
priority
:
'
Priority
'
,
priority
:
'
Priority
'
,
lastUsed
:
'
Last Used
'
,
lastUsed
:
'
Last Used
'
,
...
...
frontend/src/i18n/locales/zh.ts
View file @
d9e27df9
...
@@ -721,6 +721,9 @@ export default {
...
@@ -721,6 +721,9 @@ export default {
weight
:
'
权重
'
,
weight
:
'
权重
'
,
status
:
'
状态
'
,
status
:
'
状态
'
,
schedulable
:
'
调度
'
,
schedulable
:
'
调度
'
,
todayStats
:
'
今日统计
'
,
groups
:
'
分组
'
,
usageWindows
:
'
用量窗口
'
,
lastUsed
:
'
最近使用
'
,
lastUsed
:
'
最近使用
'
,
actions
:
'
操作
'
,
actions
:
'
操作
'
,
},
},
...
...
frontend/src/types/index.ts
View file @
d9e27df9
...
@@ -324,6 +324,7 @@ export interface Account {
...
@@ -324,6 +324,7 @@ export interface Account {
updated_at
:
string
;
updated_at
:
string
;
proxy
?:
Proxy
;
proxy
?:
Proxy
;
group_ids
?:
number
[];
// Groups this account belongs to
group_ids
?:
number
[];
// Groups this account belongs to
groups
?:
Group
[];
// Preloaded group objects
// Rate limit & scheduling fields
// Rate limit & scheduling fields
schedulable
:
boolean
;
schedulable
:
boolean
;
...
...
frontend/src/views/admin/AccountsView.vue
View file @
d9e27df9
...
@@ -123,6 +123,21 @@
...
@@ -123,6 +123,21 @@
<AccountTodayStatsCell
:account=
"row"
/>
<AccountTodayStatsCell
:account=
"row"
/>
</
template
>
</
template
>
<
template
#cell-groups=
"{ row }"
>
<div
v-if=
"row.groups && row.groups.length > 0"
class=
"flex flex-wrap gap-1.5"
>
<GroupBadge
v-for=
"group in row.groups"
:key=
"group.id"
:name=
"group.name"
:platform=
"group.platform"
:subscription-type=
"group.subscription_type"
:rate-multiplier=
"group.rate_multiplier"
:show-rate=
"false"
/>
</div>
<span
v-else
class=
"text-sm text-gray-400 dark:text-dark-500"
>
-
</span>
</
template
>
<
template
#cell-usage=
"{ row }"
>
<
template
#cell-usage=
"{ row }"
>
<AccountUsageCell
:account=
"row"
/>
<AccountUsageCell
:account=
"row"
/>
</
template
>
</
template
>
...
@@ -301,6 +316,7 @@ import AccountStatusIndicator from '@/components/account/AccountStatusIndicator.
...
@@ -301,6 +316,7 @@ import AccountStatusIndicator from '@/components/account/AccountStatusIndicator.
import
AccountUsageCell
from
'
@/components/account/AccountUsageCell.vue
'
import
AccountUsageCell
from
'
@/components/account/AccountUsageCell.vue
'
import
AccountTodayStatsCell
from
'
@/components/account/AccountTodayStatsCell.vue
'
import
AccountTodayStatsCell
from
'
@/components/account/AccountTodayStatsCell.vue
'
import
AccountTestModal
from
'
@/components/account/AccountTestModal.vue
'
import
AccountTestModal
from
'
@/components/account/AccountTestModal.vue
'
import
GroupBadge
from
'
@/components/common/GroupBadge.vue
'
import
{
formatRelativeTime
}
from
'
@/utils/format
'
import
{
formatRelativeTime
}
from
'
@/utils/format
'
const
{
t
}
=
useI18n
()
const
{
t
}
=
useI18n
()
...
@@ -314,6 +330,7 @@ const columns = computed<Column[]>(() => [
...
@@ -314,6 +330,7 @@ const columns = computed<Column[]>(() => [
{
key
:
'
status
'
,
label
:
t
(
'
admin.accounts.columns.status
'
),
sortable
:
true
},
{
key
:
'
status
'
,
label
:
t
(
'
admin.accounts.columns.status
'
),
sortable
:
true
},
{
key
:
'
schedulable
'
,
label
:
t
(
'
admin.accounts.columns.schedulable
'
),
sortable
:
true
},
{
key
:
'
schedulable
'
,
label
:
t
(
'
admin.accounts.columns.schedulable
'
),
sortable
:
true
},
{
key
:
'
today_stats
'
,
label
:
t
(
'
admin.accounts.columns.todayStats
'
),
sortable
:
false
},
{
key
:
'
today_stats
'
,
label
:
t
(
'
admin.accounts.columns.todayStats
'
),
sortable
:
false
},
{
key
:
'
groups
'
,
label
:
t
(
'
admin.accounts.columns.groups
'
),
sortable
:
false
},
{
key
:
'
usage
'
,
label
:
t
(
'
admin.accounts.columns.usageWindows
'
),
sortable
:
false
},
{
key
:
'
usage
'
,
label
:
t
(
'
admin.accounts.columns.usageWindows
'
),
sortable
:
false
},
{
key
:
'
priority
'
,
label
:
t
(
'
admin.accounts.columns.priority
'
),
sortable
:
true
},
{
key
:
'
priority
'
,
label
:
t
(
'
admin.accounts.columns.priority
'
),
sortable
:
true
},
{
key
:
'
last_used_at
'
,
label
:
t
(
'
admin.accounts.columns.lastUsed
'
),
sortable
:
true
},
{
key
:
'
last_used_at
'
,
label
:
t
(
'
admin.accounts.columns.lastUsed
'
),
sortable
:
true
},
...
...
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