mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
Merge branch 'pr-485' into dev
This commit is contained in:
@@ -547,6 +547,7 @@ router.post('/api-keys', authenticateAdmin, async (req, res) => {
|
||||
weeklyOpusCostLimit,
|
||||
tags,
|
||||
activationDays, // 新增:激活后有效天数
|
||||
activationUnit, // 新增:激活时间单位 (hours/days)
|
||||
expirationMode, // 新增:过期模式
|
||||
icon // 新增:图标
|
||||
} = req.body
|
||||
@@ -643,14 +644,23 @@ router.post('/api-keys', authenticateAdmin, async (req, res) => {
|
||||
}
|
||||
|
||||
if (expirationMode === 'activation') {
|
||||
// 验证激活时间单位
|
||||
if (!activationUnit || !['hours', 'days'].includes(activationUnit)) {
|
||||
return res.status(400).json({
|
||||
error: 'Activation unit must be either "hours" or "days" when using activation mode'
|
||||
})
|
||||
}
|
||||
|
||||
// 验证激活时间数值
|
||||
if (
|
||||
!activationDays ||
|
||||
!Number.isInteger(Number(activationDays)) ||
|
||||
Number(activationDays) < 1
|
||||
) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({ error: 'Activation days must be a positive integer when using activation mode' })
|
||||
const unitText = activationUnit === 'hours' ? 'hours' : 'days'
|
||||
return res.status(400).json({
|
||||
error: `Activation ${unitText} must be a positive integer when using activation mode`
|
||||
})
|
||||
}
|
||||
// 激活模式下不应该设置固定过期时间
|
||||
if (expiresAt) {
|
||||
@@ -684,6 +694,7 @@ router.post('/api-keys', authenticateAdmin, async (req, res) => {
|
||||
weeklyOpusCostLimit,
|
||||
tags,
|
||||
activationDays,
|
||||
activationUnit,
|
||||
expirationMode,
|
||||
icon
|
||||
})
|
||||
@@ -724,6 +735,7 @@ router.post('/api-keys/batch', authenticateAdmin, async (req, res) => {
|
||||
weeklyOpusCostLimit,
|
||||
tags,
|
||||
activationDays,
|
||||
activationUnit,
|
||||
expirationMode,
|
||||
icon
|
||||
} = req.body
|
||||
@@ -774,6 +786,7 @@ router.post('/api-keys/batch', authenticateAdmin, async (req, res) => {
|
||||
weeklyOpusCostLimit,
|
||||
tags,
|
||||
activationDays,
|
||||
activationUnit,
|
||||
expirationMode,
|
||||
icon
|
||||
})
|
||||
|
||||
@@ -37,6 +37,7 @@ class ApiKeyService {
|
||||
weeklyOpusCostLimit = 0,
|
||||
tags = [],
|
||||
activationDays = 0, // 新增:激活后有效天数(0表示不使用此功能)
|
||||
activationUnit = 'days', // 新增:激活时间单位 'hours' 或 'days'
|
||||
expirationMode = 'fixed', // 新增:过期模式 'fixed'(固定时间) 或 'activation'(首次使用后激活)
|
||||
icon = '' // 新增:图标(base64编码)
|
||||
} = options
|
||||
@@ -73,6 +74,7 @@ class ApiKeyService {
|
||||
weeklyOpusCostLimit: String(weeklyOpusCostLimit || 0),
|
||||
tags: JSON.stringify(tags || []),
|
||||
activationDays: String(activationDays || 0), // 新增:激活后有效天数
|
||||
activationUnit: activationUnit || 'days', // 新增:激活时间单位
|
||||
expirationMode: expirationMode || 'fixed', // 新增:过期模式
|
||||
isActivated: expirationMode === 'fixed' ? 'true' : 'false', // 根据模式决定激活状态
|
||||
activatedAt: expirationMode === 'fixed' ? new Date().toISOString() : '', // 激活时间
|
||||
@@ -117,6 +119,7 @@ class ApiKeyService {
|
||||
weeklyOpusCostLimit: parseFloat(keyData.weeklyOpusCostLimit || 0),
|
||||
tags: JSON.parse(keyData.tags || '[]'),
|
||||
activationDays: parseInt(keyData.activationDays || 0),
|
||||
activationUnit: keyData.activationUnit || 'days',
|
||||
expirationMode: keyData.expirationMode || 'fixed',
|
||||
isActivated: keyData.isActivated === 'true',
|
||||
activatedAt: keyData.activatedAt,
|
||||
@@ -152,8 +155,18 @@ class ApiKeyService {
|
||||
if (keyData.expirationMode === 'activation' && keyData.isActivated !== 'true') {
|
||||
// 首次使用,需要激活
|
||||
const now = new Date()
|
||||
const activationDays = parseInt(keyData.activationDays || 30) // 默认30天
|
||||
const expiresAt = new Date(now.getTime() + activationDays * 24 * 60 * 60 * 1000)
|
||||
const activationPeriod = parseInt(keyData.activationDays || 30) // 默认30
|
||||
const activationUnit = keyData.activationUnit || 'days' // 默认天
|
||||
|
||||
// 根据单位计算过期时间
|
||||
let milliseconds
|
||||
if (activationUnit === 'hours') {
|
||||
milliseconds = activationPeriod * 60 * 60 * 1000 // 小时转毫秒
|
||||
} else {
|
||||
milliseconds = activationPeriod * 24 * 60 * 60 * 1000 // 天转毫秒
|
||||
}
|
||||
|
||||
const expiresAt = new Date(now.getTime() + milliseconds)
|
||||
|
||||
// 更新激活状态和过期时间
|
||||
keyData.isActivated = 'true'
|
||||
@@ -167,7 +180,7 @@ class ApiKeyService {
|
||||
logger.success(
|
||||
`🔓 API key activated: ${keyData.id} (${
|
||||
keyData.name
|
||||
}), will expire in ${activationDays} days at ${expiresAt.toISOString()}`
|
||||
}), will expire in ${activationPeriod} ${activationUnit} at ${expiresAt.toISOString()}`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -361,6 +374,7 @@ class ApiKeyService {
|
||||
expirationMode: keyData.expirationMode || 'fixed',
|
||||
isActivated: keyData.isActivated === 'true',
|
||||
activationDays: parseInt(keyData.activationDays || 0),
|
||||
activationUnit: keyData.activationUnit || 'days',
|
||||
activatedAt: keyData.activatedAt || null,
|
||||
claudeAccountId: keyData.claudeAccountId,
|
||||
claudeConsoleAccountId: keyData.claudeConsoleAccountId,
|
||||
@@ -432,6 +446,7 @@ class ApiKeyService {
|
||||
key.dailyCost = (await redis.getDailyCost(key.id)) || 0
|
||||
key.weeklyOpusCost = (await redis.getWeeklyOpusCost(key.id)) || 0
|
||||
key.activationDays = parseInt(key.activationDays || 0)
|
||||
key.activationUnit = key.activationUnit || 'days'
|
||||
key.expirationMode = key.expirationMode || 'fixed'
|
||||
key.isActivated = key.isActivated === 'true'
|
||||
key.activatedAt = key.activatedAt || null
|
||||
@@ -541,6 +556,7 @@ class ApiKeyService {
|
||||
'permissions',
|
||||
'expiresAt',
|
||||
'activationDays', // 新增:激活后有效天数
|
||||
'activationUnit', // 新增:激活时间单位
|
||||
'expirationMode', // 新增:过期模式
|
||||
'isActivated', // 新增:是否已激活
|
||||
'activatedAt', // 新增:激活时间
|
||||
|
||||
Reference in New Issue
Block a user