From 6f2307721bb57a403609d9c4daef639690efb510 Mon Sep 17 00:00:00 2001 From: shaw Date: Sat, 11 Oct 2025 11:34:13 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Ddroid=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E8=B0=83=E5=BA=A6=E6=8E=A5=E5=8F=A3404=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/admin.js | 47 +++++++++++++++++++++++++++++ src/services/droidAccountService.js | 30 ++++++++++++++---- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/routes/admin.js b/src/routes/admin.js index 559c98bc..b0aad407 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -8821,6 +8821,53 @@ router.put('/droid-accounts/:id', authenticateAdmin, async (req, res) => { } }) +// 切换 Droid 账户调度状态 +router.put('/droid-accounts/:id/toggle-schedulable', authenticateAdmin, async (req, res) => { + try { + const { id } = req.params + + const account = await droidAccountService.getAccount(id) + if (!account) { + return res.status(404).json({ error: 'Droid account not found' }) + } + + const currentSchedulable = account.schedulable === true || account.schedulable === 'true' + const newSchedulable = !currentSchedulable + + await droidAccountService.updateAccount(id, { schedulable: newSchedulable ? 'true' : 'false' }) + + const updatedAccount = await droidAccountService.getAccount(id) + const actualSchedulable = updatedAccount + ? updatedAccount.schedulable === true || updatedAccount.schedulable === 'true' + : newSchedulable + + if (!actualSchedulable) { + await webhookNotifier.sendAccountAnomalyNotification({ + accountId: account.id, + accountName: account.name || 'Droid Account', + platform: 'droid', + status: 'disabled', + errorCode: 'DROID_MANUALLY_DISABLED', + reason: '账号已被管理员手动禁用调度', + timestamp: new Date().toISOString() + }) + } + + logger.success( + `🔄 Admin toggled Droid account schedulable status: ${id} -> ${ + actualSchedulable ? 'schedulable' : 'not schedulable' + }` + ) + + return res.json({ success: true, schedulable: actualSchedulable }) + } catch (error) { + logger.error('❌ Failed to toggle Droid account schedulable status:', error) + return res + .status(500) + .json({ error: 'Failed to toggle schedulable status', message: error.message }) + } +}) + // 删除 Droid 账户 router.delete('/droid-accounts/:id', authenticateAdmin, async (req, res) => { try { diff --git a/src/services/droidAccountService.js b/src/services/droidAccountService.js index 8a98db74..08251ccd 100644 --- a/src/services/droidAccountService.js +++ b/src/services/droidAccountService.js @@ -65,6 +65,26 @@ class DroidAccountService { return 'anthropic' } + _isTruthy(value) { + if (value === undefined || value === null) { + return false + } + if (typeof value === 'boolean') { + return value + } + if (typeof value === 'string') { + const normalized = value.trim().toLowerCase() + if (normalized === 'true') { + return true + } + if (normalized === 'false') { + return false + } + return normalized.length > 0 && normalized !== '0' && normalized !== 'no' + } + return Boolean(value) + } + /** * 生成加密密钥(缓存优化) */ @@ -1158,13 +1178,11 @@ class DroidAccountService { return allAccounts .filter((account) => { - // 基本过滤条件 - const isSchedulable = - account.isActive === 'true' && - account.schedulable === 'true' && - account.status === 'active' + const isActive = this._isTruthy(account.isActive) + const isSchedulable = this._isTruthy(account.schedulable) + const status = typeof account.status === 'string' ? account.status.toLowerCase() : '' - if (!isSchedulable) { + if (!isActive || !isSchedulable || status !== 'active') { return false }