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
d367d1cd
Commit
d367d1cd
authored
Feb 09, 2026
by
yangjianbo
Browse files
Merge branch 'main' into test-sora
parents
d7011163
3c46f7d2
Changes
104
Show whitespace changes
Inline
Side-by-side
frontend/src/views/admin/ProxiesView.vue
View file @
d367d1cd
...
...
@@ -2,9 +2,42 @@
<AppLayout>
<TablePageLayout>
<template
#filters
>
<div
class=
"space-y-3"
>
<!-- Row 1: Actions -->
<div
class=
"flex flex-wrap items-center gap-3"
>
<!-- Left: Search + Filters -->
<div
class=
"relative w-full sm:w-64"
>
<Icon
name=
"search"
size=
"md"
class=
"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 dark:text-gray-500"
/>
<input
v-model=
"searchQuery"
type=
"text"
:placeholder=
"t('admin.proxies.searchProxies')"
class=
"input pl-10"
@
input=
"handleSearch"
/>
</div>
<div
class=
"w-full sm:w-40"
>
<Select
v-model=
"filters.protocol"
:options=
"protocolOptions"
:placeholder=
"t('admin.proxies.allProtocols')"
@
change=
"loadProxies"
/>
</div>
<div
class=
"w-full sm:w-36"
>
<Select
v-model=
"filters.status"
:options=
"statusOptions"
:placeholder=
"t('admin.proxies.allStatus')"
@
change=
"loadProxies"
/>
</div>
<!-- Right: All action buttons -->
<div
class=
"flex flex-1 flex-wrap items-center justify-end gap-2"
>
<button
@
click=
"loadProxies"
:disabled=
"loading"
...
...
@@ -42,41 +75,6 @@
{{
t
(
'
admin.proxies.createProxy
'
)
}}
</button>
</div>
<!-- Row 2: Search + Filters -->
<div
class=
"flex flex-wrap items-center gap-3"
>
<div
class=
"relative w-full sm:w-64"
>
<Icon
name=
"search"
size=
"md"
class=
"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 dark:text-gray-500"
/>
<input
v-model=
"searchQuery"
type=
"text"
:placeholder=
"t('admin.proxies.searchProxies')"
class=
"input pl-10"
@
input=
"handleSearch"
/>
</div>
<div
class=
"w-full sm:w-40"
>
<Select
v-model=
"filters.protocol"
:options=
"protocolOptions"
:placeholder=
"t('admin.proxies.allProtocols')"
@
change=
"loadProxies"
/>
</div>
<div
class=
"w-full sm:w-36"
>
<Select
v-model=
"filters.status"
:options=
"statusOptions"
:placeholder=
"t('admin.proxies.allStatus')"
@
change=
"loadProxies"
/>
</div>
</div>
</div>
</
template
>
...
...
frontend/src/views/admin/RedeemView.vue
View file @
d367d1cd
<
template
>
<AppLayout>
<TablePageLayout>
<template
#actions
>
<div
class=
"flex justify-end gap-3"
>
<button
@
click=
"loadCodes"
:disabled=
"loading"
class=
"btn btn-secondary"
:title=
"t('common.refresh')"
>
<Icon
name=
"refresh"
size=
"md"
:class=
"loading ? 'animate-spin' : ''"
/>
</button>
<button
@
click=
"showGenerateDialog = true"
class=
"btn btn-primary"
>
{{
t
(
'
admin.redeem.generateCodes
'
)
}}
</button>
</div>
</
template
>
<template
#filters
>
<div
class=
"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"
>
<div
class=
"max-w-md flex-1"
>
<div
class=
"flex flex-wrap items-center gap-3"
>
<!-- Left: Search + Filters -->
<div
class=
"flex-1 sm:max-w-64"
>
<input
v-model=
"searchQuery"
type=
"text"
...
...
@@ -28,7 +13,6 @@
@
input=
"handleSearch"
/>
</div>
<div
class=
"flex gap-2"
>
<Select
v-model=
"filters.type"
:options=
"filterTypeOptions"
...
...
@@ -41,9 +25,23 @@
class=
"w-36"
@
change=
"loadCodes"
/>
<!-- Right: Action buttons -->
<div
class=
"flex flex-1 flex-wrap items-center justify-end gap-2"
>
<button
@
click=
"loadCodes"
:disabled=
"loading"
class=
"btn btn-secondary"
:title=
"t('common.refresh')"
>
<Icon
name=
"refresh"
size=
"md"
:class=
"loading ? 'animate-spin' : ''"
/>
</button>
<button
@
click=
"handleExportCodes"
class=
"btn btn-secondary"
>
{{
t
(
'
admin.redeem.exportCsv
'
)
}}
</button>
<button
@
click=
"showGenerateDialog = true"
class=
"btn btn-primary"
>
{{
t
(
'
admin.redeem.generateCodes
'
)
}}
</button>
</div>
</div>
</
template
>
...
...
frontend/src/views/admin/UsersView.vue
View file @
d367d1cd
...
...
@@ -3,9 +3,9 @@
<TablePageLayout>
<!-- Single Row: Search, Filters, and Actions -->
<template
#filters
>
<div
class=
"flex
w-full flex-col gap-3 md:flex-row md:flex-wrap-reverse md:items-center md:justify-between md:
gap-
4
"
>
<div
class=
"flex
flex-wrap items-center
gap-
3
"
>
<!-- Left: Search + Active Filters -->
<div
class=
"flex
min-w-[280px]
flex-1 flex-wrap
content-start
items-center gap-3
md:order-1
"
>
<div
class=
"flex flex-1 flex-wrap items-center gap-3"
>
<!-- Search Box -->
<div
class=
"relative w-full md:w-64"
>
<Icon
...
...
@@ -100,7 +100,7 @@
</div>
<!-- Right: Actions and Settings -->
<div
class=
"flex
w-full
items-center justify-
between gap-2 md:order-2 md:ml-auto md:max-w-full md:flex-wrap md:justify-end md:
gap-
3
"
>
<div
class=
"flex
flex-wrap
items-center justify-
end
gap-
2
"
>
<!-- Mobile: Secondary buttons (icon only) -->
<div
class=
"flex items-center gap-2 md:contents"
>
<!-- Refresh Button -->
...
...
@@ -342,8 +342,11 @@
</div>
</
template
>
<
template
#cell-concurrency=
"{ value }"
>
<span
class=
"text-sm text-gray-700 dark:text-gray-300"
>
{{
value
}}
</span>
<
template
#cell-concurrency=
"{ row }"
>
<UserConcurrencyCell
:current=
"row.current_concurrency ?? 0"
:max=
"row.concurrency"
/>
</
template
>
<
template
#cell-status=
"{ value }"
>
...
...
@@ -535,6 +538,7 @@ import EmptyState from '@/components/common/EmptyState.vue'
import
GroupBadge
from
'
@/components/common/GroupBadge.vue
'
import
Select
from
'
@/components/common/Select.vue
'
import
UserAttributesConfigModal
from
'
@/components/user/UserAttributesConfigModal.vue
'
import
UserConcurrencyCell
from
'
@/components/user/UserConcurrencyCell.vue
'
import
UserCreateModal
from
'
@/components/admin/user/UserCreateModal.vue
'
import
UserEditModal
from
'
@/components/admin/user/UserEditModal.vue
'
import
UserApiKeysModal
from
'
@/components/admin/user/UserApiKeysModal.vue
'
...
...
frontend/src/views/admin/ops/components/OpsConcurrencyCard.vue
View file @
d367d1cd
...
...
@@ -56,7 +56,6 @@ interface SummaryRow {
total_accounts
:
number
available_accounts
:
number
rate_limited_accounts
:
number
scope_rate_limit_count
?:
Record
<
string
,
number
>
error_accounts
:
number
// 并发统计
total_concurrency
:
number
...
...
@@ -122,7 +121,7 @@ const platformRows = computed((): SummaryRow[] => {
total_accounts
:
totalAccounts
,
available_accounts
:
availableAccounts
,
rate_limited_accounts
:
safeNumber
(
avail
.
rate_limit_count
),
scope_rate_limit_count
:
avail
.
scope_rate_limit_count
,
error_accounts
:
safeNumber
(
avail
.
error_count
),
total_concurrency
:
totalConcurrency
,
used_concurrency
:
usedConcurrency
,
...
...
@@ -162,7 +161,7 @@ const groupRows = computed((): SummaryRow[] => {
total_accounts
:
totalAccounts
,
available_accounts
:
availableAccounts
,
rate_limited_accounts
:
safeNumber
(
avail
.
rate_limit_count
),
scope_rate_limit_count
:
avail
.
scope_rate_limit_count
,
error_accounts
:
safeNumber
(
avail
.
error_count
),
total_concurrency
:
totalConcurrency
,
used_concurrency
:
usedConcurrency
,
...
...
@@ -329,14 +328,6 @@ function formatDuration(seconds: number): string {
return
`
${
hours
}
h`
}
function
formatScopeName
(
scope
:
string
):
string
{
const
names
:
Record
<
string
,
string
>
=
{
claude
:
'
Claude
'
,
gemini_text
:
'
Gemini
'
,
gemini_image
:
'
Image
'
}
return
names
[
scope
]
||
scope
}
watch
(
()
=>
realtimeEnabled
.
value
,
...
...
@@ -505,18 +496,6 @@ watch(
{{
t
(
'
admin.ops.concurrency.rateLimited
'
,
{
count
:
row
.
rate_limited_accounts
}
)
}}
<
/span
>
<!--
Scope
限流
(
仅
Antigravity
)
-->
<
template
v
-
if
=
"
row.scope_rate_limit_count && Object.keys(row.scope_rate_limit_count).length > 0
"
>
<
span
v
-
for
=
"
(count, scope) in row.scope_rate_limit_count
"
:
key
=
"
scope
"
class
=
"
rounded-full bg-orange-100 px-1.5 py-0.5 font-semibold text-orange-700 dark:bg-orange-900/30 dark:text-orange-400
"
:
title
=
"
t('admin.ops.concurrency.scopeRateLimitedTooltip', { scope, count
}
)
"
>
{{
formatScopeName
(
scope
as
string
)
}}
{{
count
}}
<
/span
>
<
/template
>
<!--
异常账号
-->
<
span
v
-
if
=
"
row.error_accounts > 0
"
...
...
Prev
1
2
3
4
5
6
Next
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