fix: 1. 修复调度优先级以及手动禁止调度逻辑的问题

2. 优化列表优先级显示
This commit is contained in:
KevinLiao
2025-07-30 09:30:11 +08:00
parent 89f9f48576
commit 34dca961ef
6 changed files with 140 additions and 15 deletions

View File

@@ -793,6 +793,29 @@ router.post('/claude-accounts/:accountId/refresh', authenticateAdmin, async (req
}
});
// 切换Claude账户调度状态
router.put('/claude-accounts/:accountId/toggle-schedulable', authenticateAdmin, async (req, res) => {
try {
const { accountId } = req.params;
const accounts = await claudeAccountService.getAllAccounts();
const account = accounts.find(acc => acc.id === accountId);
if (!account) {
return res.status(404).json({ error: 'Account not found' });
}
const newSchedulable = !account.schedulable;
await claudeAccountService.updateAccount(accountId, { schedulable: newSchedulable });
logger.success(`🔄 Admin toggled Claude account schedulable status: ${accountId} -> ${newSchedulable ? 'schedulable' : 'not schedulable'}`);
res.json({ success: true, schedulable: newSchedulable });
} catch (error) {
logger.error('❌ Failed to toggle Claude account schedulable status:', error);
res.status(500).json({ error: 'Failed to toggle schedulable status', message: error.message });
}
});
// 🎮 Claude Console 账户管理
// 获取所有Claude Console账户
@@ -941,6 +964,27 @@ router.put('/claude-console-accounts/:accountId/toggle', authenticateAdmin, asyn
}
});
// 切换Claude Console账户调度状态
router.put('/claude-console-accounts/:accountId/toggle-schedulable', authenticateAdmin, async (req, res) => {
try {
const { accountId } = req.params;
const account = await claudeConsoleAccountService.getAccount(accountId);
if (!account) {
return res.status(404).json({ error: 'Account not found' });
}
const newSchedulable = !account.schedulable;
await claudeConsoleAccountService.updateAccount(accountId, { schedulable: newSchedulable });
logger.success(`🔄 Admin toggled Claude Console account schedulable status: ${accountId} -> ${newSchedulable ? 'schedulable' : 'not schedulable'}`);
res.json({ success: true, schedulable: newSchedulable });
} catch (error) {
logger.error('❌ Failed to toggle Claude Console account schedulable status:', error);
res.status(500).json({ error: 'Failed to toggle schedulable status', message: error.message });
}
});
// 🤖 Gemini 账户管理
// 生成 Gemini OAuth 授权 URL

View File

@@ -38,7 +38,8 @@ class ClaudeAccountService {
proxy = null, // { type: 'socks5', host: 'localhost', port: 1080, username: '', password: '' }
isActive = true,
accountType = 'shared', // 'dedicated' or 'shared'
priority = 50 // 调度优先级 (1-100数字越小优先级越高)
priority = 50, // 调度优先级 (1-100数字越小优先级越高)
schedulable = true // 是否可被调度
} = options;
const accountId = uuidv4();
@@ -66,7 +67,8 @@ class ClaudeAccountService {
lastUsedAt: '',
lastRefreshAt: '',
status: 'active', // 有OAuth数据的账户直接设为active
errorMessage: ''
errorMessage: '',
schedulable: schedulable.toString() // 是否可被调度
};
} else {
// 兼容旧格式
@@ -88,7 +90,8 @@ class ClaudeAccountService {
lastUsedAt: '',
lastRefreshAt: '',
status: 'created', // created, active, expired, error
errorMessage: ''
errorMessage: '',
schedulable: schedulable.toString() // 是否可被调度
};
}
@@ -328,7 +331,9 @@ class ClaudeAccountService {
progress: 0,
remainingTime: null,
lastRequestTime: null
}
},
// 添加调度状态
schedulable: account.schedulable !== 'false' // 默认为true兼容历史数据
};
}));
@@ -348,7 +353,7 @@ class ClaudeAccountService {
throw new Error('Account not found');
}
const allowedUpdates = ['name', 'description', 'email', 'password', 'refreshToken', 'proxy', 'isActive', 'claudeAiOauth', 'accountType', 'priority'];
const allowedUpdates = ['name', 'description', 'email', 'password', 'refreshToken', 'proxy', 'isActive', 'claudeAiOauth', 'accountType', 'priority', 'schedulable'];
const updatedData = { ...accountData };
// 检查是否新增了 refresh token

View File

@@ -30,7 +30,8 @@ class ClaudeConsoleAccountService {
rateLimitDuration = 60, // 限流时间(分钟)
proxy = null,
isActive = true,
accountType = 'shared' // 'dedicated' or 'shared'
accountType = 'shared', // 'dedicated' or 'shared'
schedulable = true // 是否可被调度
} = options;
// 验证必填字段
@@ -60,7 +61,9 @@ class ClaudeConsoleAccountService {
errorMessage: '',
// 限流相关
rateLimitedAt: '',
rateLimitStatus: ''
rateLimitStatus: '',
// 调度控制
schedulable: schedulable.toString()
};
const client = redis.getClientSafe();
@@ -126,7 +129,8 @@ class ClaudeConsoleAccountService {
errorMessage: accountData.errorMessage,
createdAt: accountData.createdAt,
lastUsedAt: accountData.lastUsedAt,
rateLimitStatus: rateLimitInfo
rateLimitStatus: rateLimitInfo,
schedulable: accountData.schedulable !== 'false' // 默认为true只有明确设置为false才不可调度
});
}
}
@@ -166,6 +170,7 @@ class ClaudeConsoleAccountService {
accountData.priority = parseInt(accountData.priority) || 50;
accountData.rateLimitDuration = parseInt(accountData.rateLimitDuration) || 60;
accountData.isActive = accountData.isActive === 'true';
accountData.schedulable = accountData.schedulable !== 'false'; // 默认为true
if (accountData.proxy) {
accountData.proxy = JSON.parse(accountData.proxy);
@@ -210,6 +215,7 @@ class ClaudeConsoleAccountService {
if (updates.rateLimitDuration !== undefined) updatedData.rateLimitDuration = updates.rateLimitDuration.toString();
if (updates.proxy !== undefined) updatedData.proxy = updates.proxy ? JSON.stringify(updates.proxy) : '';
if (updates.isActive !== undefined) updatedData.isActive = updates.isActive.toString();
if (updates.schedulable !== undefined) updatedData.schedulable = updates.schedulable.toString();
// 处理账户类型变更
if (updates.accountType && updates.accountType !== existingAccount.accountType) {

View File

@@ -107,7 +107,8 @@ class UnifiedClaudeScheduler {
if (account.isActive === 'true' &&
account.status !== 'error' &&
account.status !== 'blocked' &&
(account.accountType === 'shared' || !account.accountType)) { // 兼容旧数据
(account.accountType === 'shared' || !account.accountType) && // 兼容旧数据
account.schedulable !== 'false') { // 检查是否可调度
// 检查是否被限流
const isRateLimited = await claudeAccountService.isAccountRateLimited(account.id);
@@ -128,12 +129,13 @@ class UnifiedClaudeScheduler {
logger.info(`📋 Found ${consoleAccounts.length} total Claude Console accounts`);
for (const account of consoleAccounts) {
logger.info(`🔍 Checking Claude Console account: ${account.name} - isActive: ${account.isActive}, status: ${account.status}, accountType: ${account.accountType}`);
logger.info(`🔍 Checking Claude Console account: ${account.name} - isActive: ${account.isActive}, status: ${account.status}, accountType: ${account.accountType}, schedulable: ${account.schedulable}`);
// 注意getAllAccounts返回的isActive是布尔值
if (account.isActive === true &&
account.status === 'active' &&
account.accountType === 'shared') {
account.accountType === 'shared' &&
account.schedulable !== false) { // 检查是否可调度
// 检查模型支持(如果有请求的模型)
if (requestedModel && account.supportedModels && account.supportedModels.length > 0) {
@@ -158,7 +160,7 @@ class UnifiedClaudeScheduler {
logger.warn(`⚠️ Claude Console account ${account.name} is rate limited`);
}
} else {
logger.info(`❌ Claude Console account ${account.name} not eligible - isActive: ${account.isActive}, status: ${account.status}, accountType: ${account.accountType}`);
logger.info(`❌ Claude Console account ${account.name} not eligible - isActive: ${account.isActive}, status: ${account.status}, accountType: ${account.accountType}, schedulable: ${account.schedulable}`);
}
}
@@ -189,12 +191,22 @@ class UnifiedClaudeScheduler {
if (!account || account.isActive !== 'true' || account.status === 'error') {
return false;
}
// 检查是否可调度
if (account.schedulable === 'false') {
logger.info(`🚫 Account ${accountId} is not schedulable`);
return false;
}
return !(await claudeAccountService.isAccountRateLimited(accountId));
} else if (accountType === 'claude-console') {
const account = await claudeConsoleAccountService.getAccount(accountId);
if (!account || !account.isActive || account.status !== 'active') {
return false;
}
// 检查是否可调度
if (account.schedulable === false) {
logger.info(`🚫 Claude Console account ${accountId} is not schedulable`);
return false;
}
return !(await claudeConsoleAccountService.isAccountRateLimited(accountId));
}
return false;