mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
fix: 修复账号过期时间的一系列bug
This commit is contained in:
@@ -2795,7 +2795,14 @@ router.put('/claude-console-accounts/:accountId', authenticateAdmin, async (req,
|
||||
}
|
||||
}
|
||||
|
||||
await claudeConsoleAccountService.updateAccount(accountId, updates)
|
||||
// 映射字段名:前端的expiresAt -> 后端的subscriptionExpiresAt
|
||||
const mappedUpdates = { ...updates }
|
||||
if ('expiresAt' in mappedUpdates) {
|
||||
mappedUpdates.subscriptionExpiresAt = mappedUpdates.expiresAt
|
||||
delete mappedUpdates.expiresAt
|
||||
}
|
||||
|
||||
await claudeConsoleAccountService.updateAccount(accountId, mappedUpdates)
|
||||
|
||||
logger.success(`📝 Admin updated Claude Console account: ${accountId}`)
|
||||
return res.json({ success: true, message: 'Claude Console account updated successfully' })
|
||||
@@ -3205,7 +3212,14 @@ router.put('/ccr-accounts/:accountId', authenticateAdmin, async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
await ccrAccountService.updateAccount(accountId, updates)
|
||||
// 映射字段名:前端的expiresAt -> 后端的subscriptionExpiresAt
|
||||
const mappedUpdates = { ...updates }
|
||||
if ('expiresAt' in mappedUpdates) {
|
||||
mappedUpdates.subscriptionExpiresAt = mappedUpdates.expiresAt
|
||||
delete mappedUpdates.expiresAt
|
||||
}
|
||||
|
||||
await ccrAccountService.updateAccount(accountId, mappedUpdates)
|
||||
|
||||
logger.success(`📝 Admin updated CCR account: ${accountId}`)
|
||||
return res.json({ success: true, message: 'CCR account updated successfully' })
|
||||
@@ -3566,7 +3580,14 @@ router.put('/bedrock-accounts/:accountId', authenticateAdmin, async (req, res) =
|
||||
})
|
||||
}
|
||||
|
||||
const result = await bedrockAccountService.updateAccount(accountId, updates)
|
||||
// 映射字段名:前端的expiresAt -> 后端的subscriptionExpiresAt
|
||||
const mappedUpdates = { ...updates }
|
||||
if ('expiresAt' in mappedUpdates) {
|
||||
mappedUpdates.subscriptionExpiresAt = mappedUpdates.expiresAt
|
||||
delete mappedUpdates.expiresAt
|
||||
}
|
||||
|
||||
const result = await bedrockAccountService.updateAccount(accountId, mappedUpdates)
|
||||
|
||||
if (!result.success) {
|
||||
return res
|
||||
@@ -3891,6 +3912,8 @@ router.get('/gemini-accounts', authenticateAdmin, async (req, res) => {
|
||||
|
||||
return {
|
||||
...account,
|
||||
// 映射字段:使用 subscriptionExpiresAt 作为前端显示的 expiresAt
|
||||
expiresAt: account.subscriptionExpiresAt || null,
|
||||
groupInfos,
|
||||
usage: {
|
||||
daily: usageStats.daily,
|
||||
@@ -3908,6 +3931,8 @@ router.get('/gemini-accounts', authenticateAdmin, async (req, res) => {
|
||||
const groupInfos = await accountGroupService.getAccountGroups(account.id)
|
||||
return {
|
||||
...account,
|
||||
// 映射字段:使用 subscriptionExpiresAt 作为前端显示的 expiresAt
|
||||
expiresAt: account.subscriptionExpiresAt || null,
|
||||
groupInfos,
|
||||
usage: {
|
||||
daily: { tokens: 0, requests: 0, allTokens: 0 },
|
||||
@@ -4032,7 +4057,14 @@ router.put('/gemini-accounts/:accountId', authenticateAdmin, async (req, res) =>
|
||||
}
|
||||
}
|
||||
|
||||
const updatedAccount = await geminiAccountService.updateAccount(accountId, updates)
|
||||
// 映射字段名:前端的expiresAt -> 后端的subscriptionExpiresAt
|
||||
const mappedUpdates = { ...updates }
|
||||
if ('expiresAt' in mappedUpdates) {
|
||||
mappedUpdates.subscriptionExpiresAt = mappedUpdates.expiresAt
|
||||
delete mappedUpdates.expiresAt
|
||||
}
|
||||
|
||||
const updatedAccount = await geminiAccountService.updateAccount(accountId, mappedUpdates)
|
||||
|
||||
logger.success(`📝 Admin updated Gemini account: ${accountId}`)
|
||||
return res.json({ success: true, data: updatedAccount })
|
||||
@@ -7539,6 +7571,13 @@ router.put('/openai-accounts/:id', authenticateAdmin, async (req, res) => {
|
||||
: currentAccount.emailVerified
|
||||
}
|
||||
|
||||
// 映射字段名:前端的expiresAt -> 后端的subscriptionExpiresAt (订阅过期时间)
|
||||
// 注意:这里不影响上面 OAuth token 的 expiresAt 字段
|
||||
if ('expiresAt' in updates && !updates.openaiOauth?.expires_in) {
|
||||
updateData.subscriptionExpiresAt = updates.expiresAt
|
||||
delete updateData.expiresAt
|
||||
}
|
||||
|
||||
const updatedAccount = await openaiAccountService.updateAccount(id, updateData)
|
||||
|
||||
// 如果需要刷新但不强制成功(非关键更新)
|
||||
@@ -7925,7 +7964,14 @@ router.put('/azure-openai-accounts/:id', authenticateAdmin, async (req, res) =>
|
||||
const { id } = req.params
|
||||
const updates = req.body
|
||||
|
||||
const account = await azureOpenaiAccountService.updateAccount(id, updates)
|
||||
// 映射字段名:前端的expiresAt -> 后端的subscriptionExpiresAt
|
||||
const mappedUpdates = { ...updates }
|
||||
if ('expiresAt' in mappedUpdates) {
|
||||
mappedUpdates.subscriptionExpiresAt = mappedUpdates.expiresAt
|
||||
delete mappedUpdates.expiresAt
|
||||
}
|
||||
|
||||
const account = await azureOpenaiAccountService.updateAccount(id, mappedUpdates)
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
@@ -8298,7 +8344,14 @@ router.put('/openai-responses-accounts/:id', authenticateAdmin, async (req, res)
|
||||
updates.priority = priority.toString()
|
||||
}
|
||||
|
||||
const result = await openaiResponsesAccountService.updateAccount(id, updates)
|
||||
// 映射字段名:前端的expiresAt -> 后端的subscriptionExpiresAt
|
||||
const mappedUpdates = { ...updates }
|
||||
if ('expiresAt' in mappedUpdates) {
|
||||
mappedUpdates.subscriptionExpiresAt = mappedUpdates.expiresAt
|
||||
delete mappedUpdates.expiresAt
|
||||
}
|
||||
|
||||
const result = await openaiResponsesAccountService.updateAccount(id, mappedUpdates)
|
||||
|
||||
if (!result.success) {
|
||||
return res.status(400).json(result)
|
||||
@@ -8664,6 +8717,9 @@ router.get('/droid-accounts', authenticateAdmin, async (req, res) => {
|
||||
|
||||
return {
|
||||
...account,
|
||||
// 映射字段:使用 subscriptionExpiresAt 作为前端显示的 expiresAt
|
||||
// OAuth token 的原始 expiresAt 保留在内部使用
|
||||
expiresAt: account.subscriptionExpiresAt || null,
|
||||
schedulable: account.schedulable === 'true',
|
||||
boundApiKeysCount,
|
||||
groupInfos,
|
||||
@@ -8677,6 +8733,8 @@ router.get('/droid-accounts', authenticateAdmin, async (req, res) => {
|
||||
logger.warn(`Failed to get stats for Droid account ${account.id}:`, error.message)
|
||||
return {
|
||||
...account,
|
||||
// 映射字段:使用 subscriptionExpiresAt 作为前端显示的 expiresAt
|
||||
expiresAt: account.subscriptionExpiresAt || null,
|
||||
boundApiKeysCount: 0,
|
||||
groupInfos: [],
|
||||
usage: {
|
||||
@@ -8791,7 +8849,14 @@ router.put('/droid-accounts/:id', authenticateAdmin, async (req, res) => {
|
||||
updates.accountType = targetAccountType
|
||||
}
|
||||
|
||||
const account = await droidAccountService.updateAccount(id, updates)
|
||||
// 映射字段名:前端的expiresAt -> 后端的subscriptionExpiresAt
|
||||
const mappedUpdates = { ...updates }
|
||||
if ('expiresAt' in mappedUpdates) {
|
||||
mappedUpdates.subscriptionExpiresAt = mappedUpdates.expiresAt
|
||||
delete mappedUpdates.expiresAt
|
||||
}
|
||||
|
||||
const account = await droidAccountService.updateAccount(id, mappedUpdates)
|
||||
|
||||
try {
|
||||
if (currentAccount.accountType === 'group' && targetAccountType !== 'group') {
|
||||
|
||||
@@ -3724,20 +3724,55 @@ const closeAccountExpiryEdit = () => {
|
||||
editingExpiryAccount.value = null
|
||||
}
|
||||
|
||||
// 根据账户平台解析更新端点
|
||||
const resolveAccountUpdateEndpoint = (account) => {
|
||||
switch (account.platform) {
|
||||
case 'claude':
|
||||
return `/admin/claude-accounts/${account.id}`
|
||||
case 'claude-console':
|
||||
return `/admin/claude-console-accounts/${account.id}`
|
||||
case 'bedrock':
|
||||
return `/admin/bedrock-accounts/${account.id}`
|
||||
case 'openai':
|
||||
return `/admin/openai-accounts/${account.id}`
|
||||
case 'azure_openai':
|
||||
return `/admin/azure-openai-accounts/${account.id}`
|
||||
case 'openai-responses':
|
||||
return `/admin/openai-responses-accounts/${account.id}`
|
||||
case 'ccr':
|
||||
return `/admin/ccr-accounts/${account.id}`
|
||||
case 'gemini':
|
||||
return `/admin/gemini-accounts/${account.id}`
|
||||
case 'droid':
|
||||
return `/admin/droid-accounts/${account.id}`
|
||||
default:
|
||||
throw new Error(`Unsupported platform: ${account.platform}`)
|
||||
}
|
||||
}
|
||||
|
||||
// 保存账户过期时间
|
||||
const handleSaveAccountExpiry = async ({ accountId, expiresAt }) => {
|
||||
try {
|
||||
const data = await apiClient.put(`/admin/claude-accounts/${accountId}`, {
|
||||
// 找到对应的账户以获取平台信息
|
||||
const account = accounts.value.find((acc) => acc.id === accountId)
|
||||
if (!account) {
|
||||
showToast('账户不存在', 'error')
|
||||
if (expiryEditModalRef.value) {
|
||||
expiryEditModalRef.value.resetSaving()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 根据平台动态选择端点
|
||||
const endpoint = resolveAccountUpdateEndpoint(account)
|
||||
const data = await apiClient.put(endpoint, {
|
||||
expiresAt: expiresAt || null
|
||||
})
|
||||
|
||||
if (data.success) {
|
||||
showToast('账户到期时间已更新', 'success')
|
||||
// 更新本地数据
|
||||
const account = accounts.value.find((acc) => acc.id === accountId)
|
||||
if (account) {
|
||||
account.expiresAt = expiresAt || null
|
||||
}
|
||||
closeAccountExpiryEdit()
|
||||
} else {
|
||||
showToast(data.message || '更新失败', 'error')
|
||||
@@ -3747,7 +3782,7 @@ const handleSaveAccountExpiry = async ({ accountId, expiresAt }) => {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
showToast('更新失败', 'error')
|
||||
showToast(error.message || '更新失败', 'error')
|
||||
// 重置保存状态
|
||||
if (expiryEditModalRef.value) {
|
||||
expiryEditModalRef.value.resetSaving()
|
||||
|
||||
Reference in New Issue
Block a user