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 {
...
@@ -1491,6 +1491,7 @@ export interface ScheduledTestPlan {
cron_expression
:
string
cron_expression
:
string
enabled
:
boolean
enabled
:
boolean
max_results
:
number
max_results
:
number
auto_recover
:
boolean
last_run_at
:
string
|
null
last_run_at
:
string
|
null
next_run_at
:
string
|
null
next_run_at
:
string
|
null
created_at
:
string
created_at
:
string
...
@@ -1515,6 +1516,7 @@ export interface CreateScheduledTestPlanRequest {
...
@@ -1515,6 +1516,7 @@ export interface CreateScheduledTestPlanRequest {
cron_expression
:
string
cron_expression
:
string
enabled
?:
boolean
enabled
?:
boolean
max_results
?:
number
max_results
?:
number
auto_recover
?:
boolean
}
}
export
interface
UpdateScheduledTestPlanRequest
{
export
interface
UpdateScheduledTestPlanRequest
{
...
@@ -1522,4 +1524,5 @@ export interface UpdateScheduledTestPlanRequest {
...
@@ -1522,4 +1524,5 @@ export interface UpdateScheduledTestPlanRequest {
cron_expression
?:
string
cron_expression
?:
string
enabled
?:
boolean
enabled
?:
boolean
max_results
?:
number
max_results
?:
number
auto_recover
?:
boolean
}
}
frontend/src/views/admin/AccountsView.vue
View file @
faf64416
...
@@ -263,7 +263,7 @@
...
@@ -263,7 +263,7 @@
<
AccountTestModal
:
show
=
"
showTest
"
:
account
=
"
testingAcc
"
@
close
=
"
closeTestModal
"
/>
<
AccountTestModal
:
show
=
"
showTest
"
:
account
=
"
testingAcc
"
@
close
=
"
closeTestModal
"
/>
<
AccountStatsModal
:
show
=
"
showStats
"
:
account
=
"
statsAcc
"
@
close
=
"
closeStatsModal
"
/>
<
AccountStatsModal
:
show
=
"
showStats
"
:
account
=
"
statsAcc
"
@
close
=
"
closeStatsModal
"
/>
<
ScheduledTestsPanel
:
show
=
"
showSchedulePanel
"
:
account
-
id
=
"
scheduleAcc?.id ?? null
"
:
model
-
options
=
"
scheduleModelOptions
"
@
close
=
"
closeSchedulePanel
"
/>
<
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
"
/>
<
SyncFromCrsModal
:
show
=
"
showSync
"
@
close
=
"
showSync = false
"
@
synced
=
"
reload
"
/>
<
ImportDataModal
:
show
=
"
showImportData
"
@
close
=
"
showImportData = false
"
@
imported
=
"
handleDataImported
"
/>
<
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
"
/>
<
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 = () => {
...
@@ -572,16 +572,17 @@ const resetAutoRefreshCache = () => {
const
isFirstLoad
=
ref
(
true
)
const
isFirstLoad
=
ref
(
true
)
const
load
=
async
()
=>
{
const
load
=
async
()
=>
{
const
requestParams
=
params
as
any
hasPendingListSync
.
value
=
false
hasPendingListSync
.
value
=
false
resetAutoRefreshCache
()
resetAutoRefreshCache
()
pendingTodayStatsRefresh
.
value
=
false
pendingTodayStatsRefresh
.
value
=
false
if
(
isFirstLoad
.
value
)
{
if
(
isFirstLoad
.
value
)
{
;(
params
as
any
)
.
lite
=
'
1
'
requestParams
.
lite
=
'
1
'
}
}
await
baseLoad
()
await
baseLoad
()
if
(
isFirstLoad
.
value
)
{
if
(
isFirstLoad
.
value
)
{
isFirstLoad
.
value
=
false
isFirstLoad
.
value
=
false
delete
(
params
as
any
)
.
lite
delete
requestParams
.
lite
}
}
await
refreshTodayStatsBatch
()
await
refreshTodayStatsBatch
()
}
}
...
@@ -1116,24 +1117,15 @@ const handleRefresh = async (a: Account) => {
...
@@ -1116,24 +1117,15 @@ const handleRefresh = async (a: Account) => {
console
.
error
(
'
Failed to refresh credentials:
'
,
error
)
console
.
error
(
'
Failed to refresh credentials:
'
,
error
)
}
}
}
}
const
handleRe
set
Stat
us
=
async
(
a
:
Account
)
=>
{
const
handleRe
cover
Stat
e
=
async
(
a
:
Account
)
=>
{
try
{
try
{
const
updated
=
await
adminAPI
.
accounts
.
clearError
(
a
.
id
)
const
updated
=
await
adminAPI
.
accounts
.
recoverState
(
a
.
id
)
patchAccountInList
(
updated
)
patchAccountInList
(
updated
)
enterAutoRefreshSilentWindow
()
enterAutoRefreshSilentWindow
()
appStore
.
showSuccess
(
t
(
'
common.success
'
))
appStore
.
showSuccess
(
t
(
'
admin.accounts.recoverStateSuccess
'
))
}
catch
(
error
)
{
}
catch
(
error
:
any
)
{
console
.
error
(
'
Failed to reset status:
'
,
error
)
console
.
error
(
'
Failed to recover account state:
'
,
error
)
}
appStore
.
showError
(
error
?.
message
||
t
(
'
admin.accounts.recoverStateFailed
'
))
}
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
)
}
}
}
}
const
handleResetQuota
=
async
(
a
:
Account
)
=>
{
const
handleResetQuota
=
async
(
a
:
Account
)
=>
{
...
@@ -1163,17 +1155,11 @@ const handleToggleSchedulable = async (a: Account) => {
...
@@ -1163,17 +1155,11 @@ const handleToggleSchedulable = async (a: Account) => {
}
}
}
}
const
handleShowTempUnsched
=
(
a
:
Account
)
=>
{
tempUnschedAcc
.
value
=
a
;
showTempUnsched
.
value
=
true
}
const
handleShowTempUnsched
=
(
a
:
Account
)
=>
{
tempUnschedAcc
.
value
=
a
;
showTempUnsched
.
value
=
true
}
const
handleTempUnschedReset
=
async
()
=>
{
const
handleTempUnschedReset
=
async
(
updated
:
Account
)
=>
{
if
(
!
tempUnschedAcc
.
value
)
return
showTempUnsched
.
value
=
false
try
{
tempUnschedAcc
.
value
=
null
const
updated
=
await
adminAPI
.
accounts
.
clearError
(
tempUnschedAcc
.
value
.
id
)
patchAccountInList
(
updated
)
showTempUnsched
.
value
=
false
enterAutoRefreshSilentWindow
()
tempUnschedAcc
.
value
=
null
patchAccountInList
(
updated
)
enterAutoRefreshSilentWindow
()
}
catch
(
error
)
{
console
.
error
(
'
Failed to reset temp unscheduled:
'
,
error
)
}
}
}
const
formatExpiresAt
=
(
value
:
number
|
null
)
=>
{
const
formatExpiresAt
=
(
value
:
number
|
null
)
=>
{
if
(
!
value
)
return
'
-
'
if
(
!
value
)
return
'
-
'
...
...
frontend/src/views/admin/DashboardView.vue
View file @
faf64416
...
@@ -552,9 +552,10 @@ const loadDashboardSnapshot = async (includeStats: boolean) => {
...
@@ -552,9 +552,10 @@ const loadDashboardSnapshot = async (includeStats: boolean) => {
appStore
.
showError
(
t
(
'
admin.dashboard.failedToLoad
'
))
appStore
.
showError
(
t
(
'
admin.dashboard.failedToLoad
'
))
console
.
error
(
'
Error loading dashboard snapshot:
'
,
error
)
console
.
error
(
'
Error loading dashboard snapshot:
'
,
error
)
}
finally
{
}
finally
{
if
(
currentSeq
!==
chartLoadSeq
)
return
if
(
currentSeq
===
chartLoadSeq
)
{
loading
.
value
=
false
loading
.
value
=
false
chartsLoading
.
value
=
false
chartsLoading
.
value
=
false
}
}
}
}
}
...
@@ -575,8 +576,9 @@ const loadUsersTrend = async () => {
...
@@ -575,8 +576,9 @@ const loadUsersTrend = async () => {
console
.
error
(
'
Error loading users trend:
'
,
error
)
console
.
error
(
'
Error loading users trend:
'
,
error
)
userTrend
.
value
=
[]
userTrend
.
value
=
[]
}
finally
{
}
finally
{
if
(
currentSeq
!==
usersTrendLoadSeq
)
return
if
(
currentSeq
===
usersTrendLoadSeq
)
{
userTrendLoading
.
value
=
false
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