mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 00:53:33 +00:00
feat: 新增Claude账号订阅类型设置
1. OAuth可自动判断订阅类型,Setup Token请自行选择。无论那种类型都可以自己改 2. 优化调度,Pro账号不再接受opus模型请求的调度
This commit is contained in:
@@ -555,6 +555,44 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Claude 订阅类型选择 -->
|
||||
<div v-if="form.platform === 'claude'">
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700">订阅类型</label>
|
||||
<div class="flex gap-4">
|
||||
<label class="flex cursor-pointer items-center">
|
||||
<input
|
||||
v-model="form.subscriptionType"
|
||||
class="mr-2"
|
||||
type="radio"
|
||||
value="claude_max"
|
||||
/>
|
||||
<span class="text-sm text-gray-700">Claude Max</span>
|
||||
</label>
|
||||
<label class="flex cursor-pointer items-center">
|
||||
<input
|
||||
v-model="form.subscriptionType"
|
||||
class="mr-2"
|
||||
type="radio"
|
||||
value="claude_pro"
|
||||
/>
|
||||
<span class="text-sm text-gray-700">Claude Pro</span>
|
||||
</label>
|
||||
<label class="flex cursor-pointer items-center">
|
||||
<input
|
||||
v-model="form.subscriptionType"
|
||||
class="mr-2"
|
||||
type="radio"
|
||||
value="claude_free"
|
||||
/>
|
||||
<span class="text-sm text-gray-700">Claude Free</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="mt-2 text-xs text-gray-500">
|
||||
<i class="fas fa-info-circle mr-1" />
|
||||
Pro 和 Free 账号不支持 Claude Opus 4 模型
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Claude、Claude Console和Bedrock的优先级设置 -->
|
||||
<div
|
||||
v-if="
|
||||
@@ -961,6 +999,44 @@
|
||||
<p class="mt-2 text-xs text-gray-500">Google Cloud/Workspace 账号可能需要提供项目 ID</p>
|
||||
</div>
|
||||
|
||||
<!-- Claude 订阅类型选择(编辑模式) -->
|
||||
<div v-if="form.platform === 'claude'">
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700">订阅类型</label>
|
||||
<div class="flex gap-4">
|
||||
<label class="flex cursor-pointer items-center">
|
||||
<input
|
||||
v-model="form.subscriptionType"
|
||||
class="mr-2"
|
||||
type="radio"
|
||||
value="claude_max"
|
||||
/>
|
||||
<span class="text-sm text-gray-700">Claude Max</span>
|
||||
</label>
|
||||
<label class="flex cursor-pointer items-center">
|
||||
<input
|
||||
v-model="form.subscriptionType"
|
||||
class="mr-2"
|
||||
type="radio"
|
||||
value="claude_pro"
|
||||
/>
|
||||
<span class="text-sm text-gray-700">Claude Pro</span>
|
||||
</label>
|
||||
<label class="flex cursor-pointer items-center">
|
||||
<input
|
||||
v-model="form.subscriptionType"
|
||||
class="mr-2"
|
||||
type="radio"
|
||||
value="claude_free"
|
||||
/>
|
||||
<span class="text-sm text-gray-700">Claude Free</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="mt-2 text-xs text-gray-500">
|
||||
<i class="fas fa-info-circle mr-1" />
|
||||
Pro 和 Free 账号不支持 Claude Opus 4 模型
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Claude、Claude Console和Bedrock的优先级设置(编辑模式) -->
|
||||
<div
|
||||
v-if="
|
||||
@@ -1419,6 +1495,7 @@ const form = ref({
|
||||
name: props.account?.name || '',
|
||||
description: props.account?.description || '',
|
||||
accountType: props.account?.accountType || 'shared',
|
||||
subscriptionType: 'claude_max', // 默认为 Claude Max,兼容旧数据
|
||||
groupId: '',
|
||||
projectId: props.account?.projectId || '',
|
||||
idToken: '',
|
||||
@@ -1678,6 +1755,13 @@ const handleOAuthSuccess = async (tokenInfo) => {
|
||||
// Claude使用claudeAiOauth字段
|
||||
data.claudeAiOauth = tokenInfo.claudeAiOauth || tokenInfo
|
||||
data.priority = form.value.priority || 50
|
||||
// 添加订阅类型信息
|
||||
data.subscriptionInfo = {
|
||||
accountType: form.value.subscriptionType || 'claude_max',
|
||||
hasClaudeMax: form.value.subscriptionType === 'claude_max',
|
||||
hasClaudePro: form.value.subscriptionType === 'claude_pro',
|
||||
manuallySet: true // 标记为手动设置
|
||||
}
|
||||
} else if (form.value.platform === 'gemini') {
|
||||
// Gemini使用geminiOauth字段
|
||||
data.geminiOauth = tokenInfo.tokens || tokenInfo
|
||||
@@ -1806,6 +1890,13 @@ const createAccount = async () => {
|
||||
scopes: ['user:inference']
|
||||
}
|
||||
data.priority = form.value.priority || 50
|
||||
// 添加订阅类型信息
|
||||
data.subscriptionInfo = {
|
||||
accountType: form.value.subscriptionType || 'claude_max',
|
||||
hasClaudeMax: form.value.subscriptionType === 'claude_max',
|
||||
hasClaudePro: form.value.subscriptionType === 'claude_pro',
|
||||
manuallySet: true // 标记为手动设置
|
||||
}
|
||||
} else if (form.value.platform === 'gemini') {
|
||||
// Gemini手动模式需要构建geminiOauth对象
|
||||
const expiresInMs = form.value.refreshToken
|
||||
@@ -2019,9 +2110,16 @@ const updateAccount = async () => {
|
||||
data.projectId = form.value.projectId
|
||||
}
|
||||
|
||||
// Claude 官方账号优先级更新
|
||||
// Claude 官方账号优先级和订阅类型更新
|
||||
if (props.account.platform === 'claude') {
|
||||
data.priority = form.value.priority || 50
|
||||
// 更新订阅类型信息
|
||||
data.subscriptionInfo = {
|
||||
accountType: form.value.subscriptionType || 'claude_max',
|
||||
hasClaudeMax: form.value.subscriptionType === 'claude_max',
|
||||
hasClaudePro: form.value.subscriptionType === 'claude_pro',
|
||||
manuallySet: true // 标记为手动设置
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAI 账号优先级更新
|
||||
@@ -2319,12 +2417,32 @@ watch(
|
||||
groupId = newAccount.groupId || (newAccount.groupInfo && newAccount.groupInfo.id) || ''
|
||||
}
|
||||
|
||||
// 初始化订阅类型(从 subscriptionInfo 中提取,兼容旧数据默认为 claude_max)
|
||||
let subscriptionType = 'claude_max'
|
||||
if (newAccount.subscriptionInfo) {
|
||||
const info =
|
||||
typeof newAccount.subscriptionInfo === 'string'
|
||||
? JSON.parse(newAccount.subscriptionInfo)
|
||||
: newAccount.subscriptionInfo
|
||||
|
||||
if (info.accountType) {
|
||||
subscriptionType = info.accountType
|
||||
} else if (info.hasClaudeMax) {
|
||||
subscriptionType = 'claude_max'
|
||||
} else if (info.hasClaudePro) {
|
||||
subscriptionType = 'claude_pro'
|
||||
} else {
|
||||
subscriptionType = 'claude_free'
|
||||
}
|
||||
}
|
||||
|
||||
form.value = {
|
||||
platform: newAccount.platform,
|
||||
addType: 'oauth',
|
||||
name: newAccount.name,
|
||||
description: newAccount.description || '',
|
||||
accountType: newAccount.accountType || 'shared',
|
||||
subscriptionType: subscriptionType,
|
||||
groupId: groupId,
|
||||
projectId: newAccount.projectId || '',
|
||||
accessToken: '',
|
||||
|
||||
@@ -292,16 +292,25 @@
|
||||
<span class="text-xs font-medium text-gray-950">Oauth</span>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
v-else-if="account.platform === 'claude' || account.platform === 'claude-oauth'"
|
||||
class="flex items-center gap-1.5 rounded-lg border border-indigo-200 bg-gradient-to-r from-indigo-100 to-blue-100 px-2.5 py-1"
|
||||
>
|
||||
<i class="fas fa-brain text-xs text-indigo-700" />
|
||||
<span class="text-xs font-semibold text-indigo-800">Claude</span>
|
||||
<span class="text-xs font-semibold text-indigo-800">{{
|
||||
getClaudeAccountType(account)
|
||||
}}</span>
|
||||
<span class="mx-1 h-4 w-px bg-indigo-300" />
|
||||
<span class="text-xs font-medium text-indigo-700">
|
||||
{{ account.scopes && account.scopes.length > 0 ? 'OAuth' : '传统' }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="flex items-center gap-1.5 rounded-lg border border-gray-200 bg-gradient-to-r from-gray-100 to-gray-200 px-2.5 py-1"
|
||||
>
|
||||
<i class="fas fa-question text-xs text-gray-700" />
|
||||
<span class="text-xs font-semibold text-gray-800">未知</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-3 py-4">
|
||||
@@ -1378,6 +1387,45 @@ const handleEditSuccess = () => {
|
||||
loadAccounts()
|
||||
}
|
||||
|
||||
// 获取 Claude 账号类型显示
|
||||
const getClaudeAccountType = (account) => {
|
||||
// 如果有订阅信息
|
||||
if (account.subscriptionInfo) {
|
||||
try {
|
||||
// 如果 subscriptionInfo 是字符串,尝试解析
|
||||
const info =
|
||||
typeof account.subscriptionInfo === 'string'
|
||||
? JSON.parse(account.subscriptionInfo)
|
||||
: account.subscriptionInfo
|
||||
|
||||
// 添加调试日志
|
||||
console.log('Account subscription info:', {
|
||||
accountName: account.name,
|
||||
subscriptionInfo: info,
|
||||
hasClaudeMax: info.hasClaudeMax,
|
||||
hasClaudePro: info.hasClaudePro
|
||||
})
|
||||
|
||||
// 根据 has_claude_max 和 has_claude_pro 判断
|
||||
if (info.hasClaudeMax === true) {
|
||||
return 'Claude Max'
|
||||
} else if (info.hasClaudePro === true) {
|
||||
return 'Claude Pro'
|
||||
} else {
|
||||
return 'Claude Free'
|
||||
}
|
||||
} catch (e) {
|
||||
// 解析失败,返回默认值
|
||||
console.error('Failed to parse subscription info:', e)
|
||||
return 'Claude'
|
||||
}
|
||||
}
|
||||
|
||||
// 没有订阅信息,保持原有显示
|
||||
console.log('No subscription info for account:', account.name)
|
||||
return 'Claude'
|
||||
}
|
||||
|
||||
// 获取账户状态文本
|
||||
const getAccountStatusText = (account) => {
|
||||
// 检查是否被封锁
|
||||
|
||||
Reference in New Issue
Block a user