feat(admin): 添加临时不可调度功能

当账号触发特定错误码和关键词匹配时,自动临时禁用调度:

后端:
- 新增 TempUnschedCache Redis 缓存层
- RateLimitService 支持规则匹配和状态管理
- 添加 GET/DELETE /accounts/:id/temp-unschedulable API
- 数据库迁移添加 temp_unschedulable_until/reason 字段

前端:
- 账号状态指示器显示临时不可调度状态
- 新增 TempUnschedStatusModal 详情弹窗
- 创建/编辑账号时支持配置规则和预设模板
- 完整的中英文国际化支持
This commit is contained in:
ianshaw
2026-01-03 06:34:00 -08:00
parent acb718d355
commit 09da6904f5
18 changed files with 1829 additions and 199 deletions

View File

@@ -216,7 +216,7 @@
</template>
<template #cell-status="{ row }">
<AccountStatusIndicator :account="row" />
<AccountStatusIndicator :account="row" @show-temp-unsched="handleShowTempUnsched" />
</template>
<template #cell-schedulable="{ row }">
@@ -400,6 +400,14 @@
<!-- Account Stats Modal -->
<AccountStatsModal :show="showStatsModal" :account="statsAccount" @close="closeStatsModal" />
<!-- Temp Unschedulable Status Modal -->
<TempUnschedStatusModal
:show="showTempUnschedModal"
:account="tempUnschedAccount"
@close="closeTempUnschedModal"
@reset="handleTempUnschedReset"
/>
<!-- Delete Confirmation Dialog -->
<ConfirmDialog
:show="showDeleteDialog"
@@ -512,6 +520,7 @@ import {
BulkEditAccountModal,
ReAuthAccountModal,
AccountStatsModal,
TempUnschedStatusModal,
SyncFromCrsModal
} from '@/components/account'
import AccountStatusIndicator from '@/components/account/AccountStatusIndicator.vue'
@@ -604,6 +613,7 @@ const showDeleteDialog = ref(false)
const showBulkDeleteDialog = ref(false)
const showTestModal = ref(false)
const showStatsModal = ref(false)
const showTempUnschedModal = ref(false)
const showCrsSyncModal = ref(false)
const showBulkEditModal = ref(false)
const editingAccount = ref<Account | null>(null)
@@ -611,6 +621,7 @@ const reAuthAccount = ref<Account | null>(null)
const deletingAccount = ref<Account | null>(null)
const testingAccount = ref<Account | null>(null)
const statsAccount = ref<Account | null>(null)
const tempUnschedAccount = ref<Account | null>(null)
const togglingSchedulable = ref<number | null>(null)
const bulkDeleting = ref(false)
@@ -775,6 +786,21 @@ const closeReAuthModal = () => {
reAuthAccount.value = null
}
// Temp unschedulable modal
const handleShowTempUnsched = (account: Account) => {
tempUnschedAccount.value = account
showTempUnschedModal.value = true
}
const closeTempUnschedModal = () => {
showTempUnschedModal.value = false
tempUnschedAccount.value = null
}
const handleTempUnschedReset = () => {
loadAccounts()
}
// Token refresh
const handleRefreshToken = async (account: Account) => {
try {