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
642432cf
Unverified
Commit
642432cf
authored
Mar 05, 2026
by
Wesley Liddick
Committed by
GitHub
Mar 05, 2026
Browse files
Merge pull request #777 from guoyongchang/feature-schedule-test-support
feat: 支持基于 crontab 的定时账号测试
parents
9d70c385
d4e34c75
Changes
23
Hide whitespace changes
Inline
Side-by-side
frontend/src/i18n/locales/zh.ts
View file @
642432cf
...
...
@@ -2520,6 +2520,34 @@ export default {
}
},
// Scheduled Tests
scheduledTests
:
{
title
:
'
定时测试
'
,
addPlan
:
'
添加计划
'
,
editPlan
:
'
编辑计划
'
,
deletePlan
:
'
删除计划
'
,
model
:
'
模型
'
,
cronExpression
:
'
Cron 表达式
'
,
enabled
:
'
启用
'
,
lastRun
:
'
上次运行
'
,
nextRun
:
'
下次运行
'
,
maxResults
:
'
最大结果数
'
,
noPlans
:
'
暂无定时测试计划
'
,
confirmDelete
:
'
确定要删除此计划吗?
'
,
createSuccess
:
'
计划创建成功
'
,
updateSuccess
:
'
计划更新成功
'
,
deleteSuccess
:
'
计划删除成功
'
,
results
:
'
测试结果
'
,
noResults
:
'
暂无测试结果
'
,
responseText
:
'
响应
'
,
errorMessage
:
'
错误
'
,
success
:
'
成功
'
,
failed
:
'
失败
'
,
running
:
'
运行中
'
,
schedule
:
'
定时测试
'
,
cronHelp
:
'
标准 5 字段 cron 表达式(例如 */30 * * * *)
'
},
// Proxies Management
proxies
:
{
title
:
'
IP管理
'
,
...
...
frontend/src/types/index.ts
View file @
642432cf
...
...
@@ -1457,3 +1457,45 @@ export interface TotpLogin2FARequest {
temp_token
:
string
totp_code
:
string
}
// ==================== Scheduled Test Types ====================
export
interface
ScheduledTestPlan
{
id
:
number
account_id
:
number
model_id
:
string
cron_expression
:
string
enabled
:
boolean
max_results
:
number
last_run_at
:
string
|
null
next_run_at
:
string
|
null
created_at
:
string
updated_at
:
string
}
export
interface
ScheduledTestResult
{
id
:
number
plan_id
:
number
status
:
string
response_text
:
string
error_message
:
string
latency_ms
:
number
started_at
:
string
finished_at
:
string
created_at
:
string
}
export
interface
CreateScheduledTestPlanRequest
{
account_id
:
number
model_id
:
string
cron_expression
:
string
enabled
?:
boolean
max_results
?:
number
}
export
interface
UpdateScheduledTestPlanRequest
{
model_id
?:
string
cron_expression
?:
string
enabled
?:
boolean
max_results
?:
number
}
frontend/src/views/admin/AccountsView.vue
View file @
642432cf
...
...
@@ -260,7 +260,8 @@
<
ReAuthAccountModal
:
show
=
"
showReAuth
"
:
account
=
"
reAuthAcc
"
@
close
=
"
closeReAuthModal
"
@
reauthorized
=
"
handleAccountUpdated
"
/>
<
AccountTestModal
:
show
=
"
showTest
"
:
account
=
"
testingAcc
"
@
close
=
"
closeTestModal
"
/>
<
AccountStatsModal
:
show
=
"
showStats
"
:
account
=
"
statsAcc
"
@
close
=
"
closeStatsModal
"
/>
<
AccountActionMenu
:
show
=
"
menu.show
"
:
account
=
"
menu.acc
"
:
position
=
"
menu.pos
"
@
close
=
"
menu.show = false
"
@
test
=
"
handleTest
"
@
stats
=
"
handleViewStats
"
@
reauth
=
"
handleReAuth
"
@
refresh
-
token
=
"
handleRefresh
"
@
reset
-
status
=
"
handleResetStatus
"
@
clear
-
rate
-
limit
=
"
handleClearRateLimit
"
/>
<
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
"
@
reset
-
status
=
"
handleResetStatus
"
@
clear
-
rate
-
limit
=
"
handleClearRateLimit
"
/>
<
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
"
/>
...
...
@@ -298,6 +299,8 @@ import ImportDataModal from '@/components/admin/account/ImportDataModal.vue'
import
ReAuthAccountModal
from
'
@/components/admin/account/ReAuthAccountModal.vue
'
import
AccountTestModal
from
'
@/components/admin/account/AccountTestModal.vue
'
import
AccountStatsModal
from
'
@/components/admin/account/AccountStatsModal.vue
'
import
ScheduledTestsPanel
from
'
@/components/admin/account/ScheduledTestsPanel.vue
'
import
type
{
SelectOption
}
from
'
@/components/common/Select.vue
'
import
AccountStatusIndicator
from
'
@/components/account/AccountStatusIndicator.vue
'
import
AccountUsageCell
from
'
@/components/account/AccountUsageCell.vue
'
import
AccountTodayStatsCell
from
'
@/components/account/AccountTodayStatsCell.vue
'
...
...
@@ -307,7 +310,7 @@ import PlatformTypeBadge from '@/components/common/PlatformTypeBadge.vue'
import
Icon
from
'
@/components/icons/Icon.vue
'
import
ErrorPassthroughRulesModal
from
'
@/components/admin/ErrorPassthroughRulesModal.vue
'
import
{
formatDateTime
,
formatRelativeTime
}
from
'
@/utils/format
'
import
type
{
Account
,
AccountPlatform
,
AccountType
,
Proxy
,
AdminGroup
,
WindowStats
}
from
'
@/types
'
import
type
{
Account
,
AccountPlatform
,
AccountType
,
Proxy
,
AdminGroup
,
WindowStats
,
ClaudeModel
}
from
'
@/types
'
const
{
t
}
=
useI18n
()
const
appStore
=
useAppStore
()
...
...
@@ -351,6 +354,9 @@ const deletingAcc = ref<Account | null>(null)
const
reAuthAcc
=
ref
<
Account
|
null
>
(
null
)
const
testingAcc
=
ref
<
Account
|
null
>
(
null
)
const
statsAcc
=
ref
<
Account
|
null
>
(
null
)
const
showSchedulePanel
=
ref
(
false
)
const
scheduleAcc
=
ref
<
Account
|
null
>
(
null
)
const
scheduleModelOptions
=
ref
<
SelectOption
[]
>
([])
const
togglingSchedulable
=
ref
<
number
|
null
>
(
null
)
const
menu
=
reactive
<
{
show
:
boolean
,
acc
:
Account
|
null
,
pos
:{
top
:
number
,
left
:
number
}
|
null
}
>
({
show
:
false
,
acc
:
null
,
pos
:
null
}
)
const
exportingData
=
ref
(
false
)
...
...
@@ -621,6 +627,7 @@ const isAnyModalOpen = computed(() => {
showReAuth
.
value
||
showTest
.
value
||
showStats
.
value
||
showSchedulePanel
.
value
||
showErrorPassthrough
.
value
)
}
)
...
...
@@ -1076,6 +1083,18 @@ const closeStatsModal = () => { showStats.value = false; statsAcc.value = null }
const
closeReAuthModal
=
()
=>
{
showReAuth
.
value
=
false
;
reAuthAcc
.
value
=
null
}
const
handleTest
=
(
a
:
Account
)
=>
{
testingAcc
.
value
=
a
;
showTest
.
value
=
true
}
const
handleViewStats
=
(
a
:
Account
)
=>
{
statsAcc
.
value
=
a
;
showStats
.
value
=
true
}
const
handleSchedule
=
async
(
a
:
Account
)
=>
{
scheduleAcc
.
value
=
a
scheduleModelOptions
.
value
=
[]
showSchedulePanel
.
value
=
true
try
{
const
models
=
await
adminAPI
.
accounts
.
getAvailableModels
(
a
.
id
)
scheduleModelOptions
.
value
=
models
.
map
((
m
:
ClaudeModel
)
=>
({
value
:
m
.
id
,
label
:
m
.
display_name
||
m
.
id
}
))
}
catch
{
scheduleModelOptions
.
value
=
[]
}
}
const
closeSchedulePanel
=
()
=>
{
showSchedulePanel
.
value
=
false
;
scheduleAcc
.
value
=
null
;
scheduleModelOptions
.
value
=
[]
}
const
handleReAuth
=
(
a
:
Account
)
=>
{
reAuthAcc
.
value
=
a
;
showReAuth
.
value
=
true
}
const
handleRefresh
=
async
(
a
:
Account
)
=>
{
try
{
...
...
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