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
faf64416
Unverified
Commit
faf64416
authored
Mar 09, 2026
by
Wesley Liddick
Committed by
GitHub
Mar 09, 2026
Browse files
Merge pull request #854 from james-6-23/main
feat(admin): 支持定时测试自动恢复并统一账号恢复入口
parents
00c151b4
34aad82a
Changes
23
Hide whitespace changes
Inline
Side-by-side
frontend/src/types/index.ts
View file @
faf64416
...
...
@@ -1491,6 +1491,7 @@ export interface ScheduledTestPlan {
cron_expression
:
string
enabled
:
boolean
max_results
:
number
auto_recover
:
boolean
last_run_at
:
string
|
null
next_run_at
:
string
|
null
created_at
:
string
...
...
@@ -1515,6 +1516,7 @@ export interface CreateScheduledTestPlanRequest {
cron_expression
:
string
enabled
?:
boolean
max_results
?:
number
auto_recover
?:
boolean
}
export
interface
UpdateScheduledTestPlanRequest
{
...
...
@@ -1522,4 +1524,5 @@ export interface UpdateScheduledTestPlanRequest {
cron_expression
?:
string
enabled
?:
boolean
max_results
?:
number
auto_recover
?:
boolean
}
frontend/src/views/admin/AccountsView.vue
View file @
faf64416
...
...
@@ -263,7 +263,7 @@
<
AccountTestModal
:
show
=
"
showTest
"
:
account
=
"
testingAcc
"
@
close
=
"
closeTestModal
"
/>
<
AccountStatsModal
:
show
=
"
showStats
"
:
account
=
"
statsAcc
"
@
close
=
"
closeStatsModal
"
/>
<
ScheduledTestsPanel
:
show
=
"
showSchedulePanel
"
:
account
-
id
=
"
scheduleAcc?.id ?? null
"
:
model
-
options
=
"
scheduleModelOptions
"
@
close
=
"
closeSchedulePanel
"
/>
<
AccountActionMenu
:
show
=
"
menu.show
"
:
account
=
"
menu.acc
"
:
position
=
"
menu.pos
"
@
close
=
"
menu.show = false
"
@
test
=
"
handleTest
"
@
stats
=
"
handleViewStats
"
@
schedule
=
"
handleSchedule
"
@
reauth
=
"
handleReAuth
"
@
refresh
-
token
=
"
handleRefresh
"
@
re
set
-
stat
us
=
"
handleRe
setStatus
"
@
clear
-
rate
-
limit
=
"
handleClearRateLimit
"
@
reset
-
quota
=
"
handleResetQuota
"
/>
<
AccountActionMenu
:
show
=
"
menu.show
"
:
account
=
"
menu.acc
"
:
position
=
"
menu.pos
"
@
close
=
"
menu.show = false
"
@
test
=
"
handleTest
"
@
stats
=
"
handleViewStats
"
@
schedule
=
"
handleSchedule
"
@
reauth
=
"
handleReAuth
"
@
refresh
-
token
=
"
handleRefresh
"
@
re
cover
-
stat
e
=
"
handleRe
coverState
"
@
reset
-
quota
=
"
handleResetQuota
"
/>
<
SyncFromCrsModal
:
show
=
"
showSync
"
@
close
=
"
showSync = false
"
@
synced
=
"
reload
"
/>
<
ImportDataModal
:
show
=
"
showImportData
"
@
close
=
"
showImportData = false
"
@
imported
=
"
handleDataImported
"
/>
<
BulkEditAccountModal
:
show
=
"
showBulkEdit
"
:
account
-
ids
=
"
selIds
"
:
selected
-
platforms
=
"
selPlatforms
"
:
selected
-
types
=
"
selTypes
"
:
proxies
=
"
proxies
"
:
groups
=
"
groups
"
@
close
=
"
showBulkEdit = false
"
@
updated
=
"
handleBulkUpdated
"
/>
...
...
@@ -572,16 +572,17 @@ const resetAutoRefreshCache = () => {
const
isFirstLoad
=
ref
(
true
)
const
load
=
async
()
=>
{
const
requestParams
=
params
as
any
hasPendingListSync
.
value
=
false
resetAutoRefreshCache
()
pendingTodayStatsRefresh
.
value
=
false
if
(
isFirstLoad
.
value
)
{
;(
params
as
any
)
.
lite
=
'
1
'
requestParams
.
lite
=
'
1
'
}
await
baseLoad
()
if
(
isFirstLoad
.
value
)
{
isFirstLoad
.
value
=
false
delete
(
params
as
any
)
.
lite
delete
requestParams
.
lite
}
await
refreshTodayStatsBatch
()
}
...
...
@@ -1116,24 +1117,15 @@ const handleRefresh = async (a: Account) => {
console
.
error
(
'
Failed to refresh credentials:
'
,
error
)
}
}
const
handleRe
set
Stat
us
=
async
(
a
:
Account
)
=>
{
const
handleRe
cover
Stat
e
=
async
(
a
:
Account
)
=>
{
try
{
const
updated
=
await
adminAPI
.
accounts
.
clearError
(
a
.
id
)
const
updated
=
await
adminAPI
.
accounts
.
recoverState
(
a
.
id
)
patchAccountInList
(
updated
)
enterAutoRefreshSilentWindow
()
appStore
.
showSuccess
(
t
(
'
common.success
'
))
}
catch
(
error
)
{
console
.
error
(
'
Failed to reset status:
'
,
error
)
}
}
const
handleClearRateLimit
=
async
(
a
:
Account
)
=>
{
try
{
const
updated
=
await
adminAPI
.
accounts
.
clearRateLimit
(
a
.
id
)
patchAccountInList
(
updated
)
enterAutoRefreshSilentWindow
()
appStore
.
showSuccess
(
t
(
'
common.success
'
))
}
catch
(
error
)
{
console
.
error
(
'
Failed to clear rate limit:
'
,
error
)
appStore
.
showSuccess
(
t
(
'
admin.accounts.recoverStateSuccess
'
))
}
catch
(
error
:
any
)
{
console
.
error
(
'
Failed to recover account state:
'
,
error
)
appStore
.
showError
(
error
?.
message
||
t
(
'
admin.accounts.recoverStateFailed
'
))
}
}
const
handleResetQuota
=
async
(
a
:
Account
)
=>
{
...
...
@@ -1163,17 +1155,11 @@ const handleToggleSchedulable = async (a: Account) => {
}
}
const
handleShowTempUnsched
=
(
a
:
Account
)
=>
{
tempUnschedAcc
.
value
=
a
;
showTempUnsched
.
value
=
true
}
const
handleTempUnschedReset
=
async
()
=>
{
if
(
!
tempUnschedAcc
.
value
)
return
try
{
const
updated
=
await
adminAPI
.
accounts
.
clearError
(
tempUnschedAcc
.
value
.
id
)
showTempUnsched
.
value
=
false
tempUnschedAcc
.
value
=
null
patchAccountInList
(
updated
)
enterAutoRefreshSilentWindow
()
}
catch
(
error
)
{
console
.
error
(
'
Failed to reset temp unscheduled:
'
,
error
)
}
const
handleTempUnschedReset
=
async
(
updated
:
Account
)
=>
{
showTempUnsched
.
value
=
false
tempUnschedAcc
.
value
=
null
patchAccountInList
(
updated
)
enterAutoRefreshSilentWindow
()
}
const
formatExpiresAt
=
(
value
:
number
|
null
)
=>
{
if
(
!
value
)
return
'
-
'
...
...
frontend/src/views/admin/DashboardView.vue
View file @
faf64416
...
...
@@ -552,9 +552,10 @@ const loadDashboardSnapshot = async (includeStats: boolean) => {
appStore
.
showError
(
t
(
'
admin.dashboard.failedToLoad
'
))
console
.
error
(
'
Error loading dashboard snapshot:
'
,
error
)
}
finally
{
if
(
currentSeq
!==
chartLoadSeq
)
return
loading
.
value
=
false
chartsLoading
.
value
=
false
if
(
currentSeq
===
chartLoadSeq
)
{
loading
.
value
=
false
chartsLoading
.
value
=
false
}
}
}
...
...
@@ -575,8 +576,9 @@ const loadUsersTrend = async () => {
console
.
error
(
'
Error loading users trend:
'
,
error
)
userTrend
.
value
=
[]
}
finally
{
if
(
currentSeq
!==
usersTrendLoadSeq
)
return
userTrendLoading
.
value
=
false
if
(
currentSeq
===
usersTrendLoadSeq
)
{
userTrendLoading
.
value
=
false
}
}
}
...
...
Prev
1
2
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