mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
feat: droid的apikey模式适配多种更新方式
This commit is contained in:
@@ -932,7 +932,26 @@ class DroidAccountService {
|
|||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
const newApiKeysInput = Array.isArray(updates.apiKeys) ? updates.apiKeys : []
|
const newApiKeysInput = Array.isArray(updates.apiKeys) ? updates.apiKeys : []
|
||||||
|
const removeApiKeysInput = Array.isArray(updates.removeApiKeys) ? updates.removeApiKeys : []
|
||||||
const wantsClearApiKeys = Boolean(updates.clearApiKeys)
|
const wantsClearApiKeys = Boolean(updates.clearApiKeys)
|
||||||
|
const rawApiKeyMode =
|
||||||
|
typeof updates.apiKeyUpdateMode === 'string'
|
||||||
|
? updates.apiKeyUpdateMode.trim().toLowerCase()
|
||||||
|
: ''
|
||||||
|
|
||||||
|
let apiKeyUpdateMode = ['append', 'replace', 'delete'].includes(rawApiKeyMode)
|
||||||
|
? rawApiKeyMode
|
||||||
|
: ''
|
||||||
|
|
||||||
|
if (!apiKeyUpdateMode) {
|
||||||
|
if (wantsClearApiKeys) {
|
||||||
|
apiKeyUpdateMode = 'replace'
|
||||||
|
} else if (removeApiKeysInput.length > 0) {
|
||||||
|
apiKeyUpdateMode = 'delete'
|
||||||
|
} else {
|
||||||
|
apiKeyUpdateMode = 'append'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sanitizedUpdates.apiKeys !== undefined) {
|
if (sanitizedUpdates.apiKeys !== undefined) {
|
||||||
delete sanitizedUpdates.apiKeys
|
delete sanitizedUpdates.apiKeys
|
||||||
@@ -940,33 +959,94 @@ class DroidAccountService {
|
|||||||
if (sanitizedUpdates.clearApiKeys !== undefined) {
|
if (sanitizedUpdates.clearApiKeys !== undefined) {
|
||||||
delete sanitizedUpdates.clearApiKeys
|
delete sanitizedUpdates.clearApiKeys
|
||||||
}
|
}
|
||||||
|
if (sanitizedUpdates.apiKeyUpdateMode !== undefined) {
|
||||||
|
delete sanitizedUpdates.apiKeyUpdateMode
|
||||||
|
}
|
||||||
|
if (sanitizedUpdates.removeApiKeys !== undefined) {
|
||||||
|
delete sanitizedUpdates.removeApiKeys
|
||||||
|
}
|
||||||
|
|
||||||
if (wantsClearApiKeys || newApiKeysInput.length > 0) {
|
let mergedApiKeys = existingApiKeyEntries
|
||||||
const mergedApiKeys = this._buildApiKeyEntries(
|
let apiKeysUpdated = false
|
||||||
|
let addedCount = 0
|
||||||
|
let removedCount = 0
|
||||||
|
|
||||||
|
if (apiKeyUpdateMode === 'delete') {
|
||||||
|
const removalHashes = new Set()
|
||||||
|
|
||||||
|
for (const candidate of removeApiKeysInput) {
|
||||||
|
if (typeof candidate !== 'string') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const trimmed = candidate.trim()
|
||||||
|
if (!trimmed) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const hash = crypto.createHash('sha256').update(trimmed).digest('hex')
|
||||||
|
removalHashes.add(hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removalHashes.size > 0) {
|
||||||
|
mergedApiKeys = existingApiKeyEntries.filter(
|
||||||
|
(entry) => entry && entry.hash && !removalHashes.has(entry.hash)
|
||||||
|
)
|
||||||
|
removedCount = existingApiKeyEntries.length - mergedApiKeys.length
|
||||||
|
apiKeysUpdated = removedCount > 0
|
||||||
|
|
||||||
|
if (!apiKeysUpdated) {
|
||||||
|
logger.warn(
|
||||||
|
`⚠️ 删除模式未匹配任何 Droid API Key: ${accountId} (提供 ${removalHashes.size} 条)`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (removeApiKeysInput.length > 0) {
|
||||||
|
logger.warn(`⚠️ 删除模式未收到有效的 Droid API Key: ${accountId}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const clearExisting = apiKeyUpdateMode === 'replace' || wantsClearApiKeys
|
||||||
|
const baselineCount = clearExisting ? 0 : existingApiKeyEntries.length
|
||||||
|
|
||||||
|
mergedApiKeys = this._buildApiKeyEntries(
|
||||||
newApiKeysInput,
|
newApiKeysInput,
|
||||||
existingApiKeyEntries,
|
existingApiKeyEntries,
|
||||||
wantsClearApiKeys
|
clearExisting
|
||||||
)
|
)
|
||||||
|
|
||||||
const baselineCount = wantsClearApiKeys ? 0 : existingApiKeyEntries.length
|
addedCount = Math.max(mergedApiKeys.length - baselineCount, 0)
|
||||||
const addedCount = Math.max(mergedApiKeys.length - baselineCount, 0)
|
apiKeysUpdated = clearExisting || addedCount > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apiKeysUpdated) {
|
||||||
sanitizedUpdates.apiKeys = mergedApiKeys.length ? JSON.stringify(mergedApiKeys) : ''
|
sanitizedUpdates.apiKeys = mergedApiKeys.length ? JSON.stringify(mergedApiKeys) : ''
|
||||||
sanitizedUpdates.apiKeyCount = String(mergedApiKeys.length)
|
sanitizedUpdates.apiKeyCount = String(mergedApiKeys.length)
|
||||||
|
|
||||||
|
if (apiKeyUpdateMode === 'delete') {
|
||||||
|
logger.info(
|
||||||
|
`🔑 删除模式更新 Droid API keys for ${accountId}: 已移除 ${removedCount} 条,剩余 ${mergedApiKeys.length}`
|
||||||
|
)
|
||||||
|
} else if (apiKeyUpdateMode === 'replace' || wantsClearApiKeys) {
|
||||||
|
logger.info(
|
||||||
|
`🔑 覆盖模式更新 Droid API keys for ${accountId}: 当前总数 ${mergedApiKeys.length},新增 ${addedCount}`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
logger.info(
|
||||||
|
`🔑 追加模式更新 Droid API keys for ${accountId}: 当前总数 ${mergedApiKeys.length},新增 ${addedCount}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (mergedApiKeys.length > 0) {
|
if (mergedApiKeys.length > 0) {
|
||||||
sanitizedUpdates.authenticationMethod = 'api_key'
|
sanitizedUpdates.authenticationMethod = 'api_key'
|
||||||
sanitizedUpdates.status = sanitizedUpdates.status || 'active'
|
sanitizedUpdates.status = sanitizedUpdates.status || 'active'
|
||||||
logger.info(
|
} else if (!sanitizedUpdates.accessToken && !account.accessToken) {
|
||||||
`🔑 Updated Droid API keys for ${accountId}: total ${mergedApiKeys.length} (added ${addedCount})`
|
const shouldPreserveApiKeyMode =
|
||||||
)
|
account.authenticationMethod &&
|
||||||
} else {
|
account.authenticationMethod.toLowerCase().trim() === 'api_key' &&
|
||||||
logger.info(`🔑 Cleared all API keys for Droid account ${accountId}`)
|
(apiKeyUpdateMode === 'replace' || apiKeyUpdateMode === 'delete')
|
||||||
// 如果完全移除 API Key,可根据是否仍有 token 来确定认证方式
|
|
||||||
if (!sanitizedUpdates.accessToken && !account.accessToken) {
|
sanitizedUpdates.authenticationMethod = shouldPreserveApiKeyMode
|
||||||
sanitizedUpdates.authenticationMethod =
|
? 'api_key'
|
||||||
account.authenticationMethod === 'api_key' ? '' : account.authenticationMethod
|
: account.authenticationMethod === 'api_key'
|
||||||
}
|
? ''
|
||||||
|
: account.authenticationMethod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2928,10 +2928,10 @@
|
|||||||
</h5>
|
</h5>
|
||||||
<p class="mb-1 text-sm text-purple-800 dark:text-purple-200">
|
<p class="mb-1 text-sm text-purple-800 dark:text-purple-200">
|
||||||
当前已保存 <strong>{{ existingApiKeyCount }}</strong> 条 API Key。您可以追加新的
|
当前已保存 <strong>{{ existingApiKeyCount }}</strong> 条 API Key。您可以追加新的
|
||||||
Key 或使用下方选项清空后重新填写。
|
Key,或通过下方模式快速覆盖、删除指定 Key。
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs text-purple-700 dark:text-purple-300">
|
<p class="text-xs text-purple-700 dark:text-purple-300">
|
||||||
留空表示保留现有 Key 不变;填写内容后将覆盖或追加(视清空选项而定)。
|
留空表示保留现有 Key 不变;根据所选模式决定是追加、覆盖还是删除输入的 Key。
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2945,7 +2945,7 @@
|
|||||||
v-model="form.apiKeysInput"
|
v-model="form.apiKeysInput"
|
||||||
class="form-input w-full resize-none border-gray-300 font-mono text-xs dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
|
class="form-input w-full resize-none border-gray-300 font-mono text-xs dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
|
||||||
:class="{ 'border-red-500': errors.apiKeys }"
|
:class="{ 'border-red-500': errors.apiKeys }"
|
||||||
placeholder="留空表示不更新;每行一个 API Key"
|
placeholder="根据模式填写;每行一个 API Key"
|
||||||
rows="6"
|
rows="6"
|
||||||
/>
|
/>
|
||||||
<p v-if="errors.apiKeys" class="mt-1 text-xs text-red-500">
|
<p v-if="errors.apiKeys" class="mt-1 text-xs text-red-500">
|
||||||
@@ -2953,16 +2953,41 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label
|
<div class="space-y-2">
|
||||||
class="flex cursor-pointer items-center gap-2 rounded-md border border-purple-200 bg-white/80 px-3 py-2 text-sm text-purple-800 transition-colors hover:border-purple-300 dark:border-purple-700 dark:bg-purple-800/20 dark:text-purple-100"
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="text-sm font-semibold text-purple-800 dark:text-purple-100"
|
||||||
|
>API Key 更新模式</span
|
||||||
>
|
>
|
||||||
<input
|
<span class="text-xs text-purple-600 dark:text-purple-300">
|
||||||
v-model="form.clearExistingApiKeys"
|
{{ currentApiKeyModeLabel }}
|
||||||
class="rounded border-purple-300 text-purple-600 focus:ring-purple-500 dark:border-purple-500 dark:bg-purple-900"
|
</span>
|
||||||
type="checkbox"
|
</div>
|
||||||
|
<div
|
||||||
|
class="relative grid h-11 grid-cols-3 overflow-hidden rounded-2xl border border-purple-200/80 bg-gradient-to-r from-purple-50/80 via-white to-purple-50/80 shadow-inner dark:border-purple-700/70 dark:from-purple-900/40 dark:via-purple-900/20 dark:to-purple-900/40"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="pointer-events-none absolute inset-y-0 rounded-2xl bg-gradient-to-r from-purple-500/90 via-purple-600 to-indigo-500/90 shadow-lg ring-1 ring-purple-100/80 transition-all duration-300 ease-out dark:from-purple-500/70 dark:via-purple-600/70 dark:to-indigo-500/70 dark:ring-purple-400/30"
|
||||||
|
:style="apiKeyModeSliderStyle"
|
||||||
/>
|
/>
|
||||||
<span>清空已有 API Key 后再应用上方的 Key 列表</span>
|
<button
|
||||||
</label>
|
v-for="option in apiKeyModeOptions"
|
||||||
|
:key="option.value"
|
||||||
|
class="relative z-10 flex items-center justify-center rounded-2xl px-2 text-xs font-semibold transition-all duration-200 ease-out focus:outline-none focus-visible:ring-2 focus-visible:ring-purple-500/60 dark:focus-visible:ring-purple-400/60"
|
||||||
|
:class="
|
||||||
|
form.apiKeyUpdateMode === option.value
|
||||||
|
? 'text-white drop-shadow-sm'
|
||||||
|
: 'text-purple-500/80 hover:text-purple-700 dark:text-purple-200/70 dark:hover:text-purple-100'
|
||||||
|
"
|
||||||
|
type="button"
|
||||||
|
@click="form.apiKeyUpdateMode = option.value"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-purple-700 dark:text-purple-300">
|
||||||
|
{{ currentApiKeyModeDescription }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="rounded-lg border border-purple-200 bg-white/70 p-3 text-xs text-purple-800 dark:border-purple-700 dark:bg-purple-800/20 dark:text-purple-100"
|
class="rounded-lg border border-purple-200 bg-white/70 p-3 text-xs text-purple-800 dark:border-purple-700 dark:bg-purple-800/20 dark:text-purple-100"
|
||||||
@@ -2970,7 +2995,9 @@
|
|||||||
<p class="font-medium"><i class="fas fa-lightbulb mr-1" />小提示</p>
|
<p class="font-medium"><i class="fas fa-lightbulb mr-1" />小提示</p>
|
||||||
<ul class="mt-1 list-disc space-y-1 pl-4">
|
<ul class="mt-1 list-disc space-y-1 pl-4">
|
||||||
<li>系统会为新的 Key 自动建立粘性映射,保持同一会话命中同一个 Key。</li>
|
<li>系统会为新的 Key 自动建立粘性映射,保持同一会话命中同一个 Key。</li>
|
||||||
<li>勾选“清空”后保存即彻底移除旧 Key,可用于紧急轮换或封禁处理。</li>
|
<li>追加模式会保留现有 Key 并在末尾追加新的 Key。</li>
|
||||||
|
<li>覆盖模式会先清空旧 Key 再写入上方的新列表。</li>
|
||||||
|
<li>删除模式会根据输入精准移除指定 Key,适合快速处理失效或被封禁的 Key。</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -3283,7 +3310,7 @@ const form = ref({
|
|||||||
accessToken: '',
|
accessToken: '',
|
||||||
refreshToken: '',
|
refreshToken: '',
|
||||||
apiKeysInput: '',
|
apiKeysInput: '',
|
||||||
clearExistingApiKeys: false,
|
apiKeyUpdateMode: 'append',
|
||||||
proxy: initProxyConfig(),
|
proxy: initProxyConfig(),
|
||||||
// Claude Console 特定字段
|
// Claude Console 特定字段
|
||||||
apiUrl: props.account?.apiUrl || '',
|
apiUrl: props.account?.apiUrl || '',
|
||||||
@@ -3397,6 +3424,47 @@ const parseApiKeysInput = (input) => {
|
|||||||
return uniqueKeys
|
return uniqueKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const apiKeyModeOptions = [
|
||||||
|
{
|
||||||
|
value: 'append',
|
||||||
|
label: '追加模式',
|
||||||
|
description: '保留现有 Key,并在末尾追加新 Key 列表。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'replace',
|
||||||
|
label: '覆盖模式',
|
||||||
|
description: '先清空旧 Key,再写入上方的新 Key 列表。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'delete',
|
||||||
|
label: '删除模式',
|
||||||
|
description: '输入要移除的 Key,可精准删除失效或被封禁的 Key。'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const apiKeyModeSliderStyle = computed(() => {
|
||||||
|
const index = Math.max(
|
||||||
|
apiKeyModeOptions.findIndex((option) => option.value === form.value.apiKeyUpdateMode),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
const widthPercent = 100 / apiKeyModeOptions.length
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: `${widthPercent}%`,
|
||||||
|
left: `${index * widthPercent}%`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentApiKeyModeLabel = computed(() => {
|
||||||
|
const option = apiKeyModeOptions.find((item) => item.value === form.value.apiKeyUpdateMode)
|
||||||
|
return option ? option.label : apiKeyModeOptions[0].label
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentApiKeyModeDescription = computed(() => {
|
||||||
|
const option = apiKeyModeOptions.find((item) => item.value === form.value.apiKeyUpdateMode)
|
||||||
|
return option ? option.description : apiKeyModeOptions[0].description
|
||||||
|
})
|
||||||
|
|
||||||
// 表单验证错误
|
// 表单验证错误
|
||||||
const errors = ref({
|
const errors = ref({
|
||||||
name: '',
|
name: '',
|
||||||
@@ -4313,7 +4381,25 @@ const updateAccount = async () => {
|
|||||||
|
|
||||||
if (props.account.platform === 'droid') {
|
if (props.account.platform === 'droid') {
|
||||||
const trimmedApiKeysInput = form.value.apiKeysInput?.trim() || ''
|
const trimmedApiKeysInput = form.value.apiKeysInput?.trim() || ''
|
||||||
|
const apiKeyUpdateMode = form.value.apiKeyUpdateMode || 'append'
|
||||||
|
|
||||||
|
if (apiKeyUpdateMode === 'delete') {
|
||||||
|
if (!trimmedApiKeysInput) {
|
||||||
|
errors.value.apiKeys = '请填写需要删除的 API Key'
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeApiKeys = parseApiKeysInput(trimmedApiKeysInput)
|
||||||
|
if (removeApiKeys.length === 0) {
|
||||||
|
errors.value.apiKeys = '请填写需要删除的 API Key'
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data.removeApiKeys = removeApiKeys
|
||||||
|
data.apiKeyUpdateMode = 'delete'
|
||||||
|
} else {
|
||||||
if (trimmedApiKeysInput) {
|
if (trimmedApiKeysInput) {
|
||||||
const apiKeys = parseApiKeysInput(trimmedApiKeysInput)
|
const apiKeys = parseApiKeysInput(trimmedApiKeysInput)
|
||||||
if (apiKeys.length === 0) {
|
if (apiKeys.length === 0) {
|
||||||
@@ -4322,10 +4408,13 @@ const updateAccount = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
data.apiKeys = apiKeys
|
data.apiKeys = apiKeys
|
||||||
|
} else if (apiKeyUpdateMode === 'replace') {
|
||||||
|
data.apiKeys = []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (form.value.clearExistingApiKeys) {
|
if (apiKeyUpdateMode !== 'append' || trimmedApiKeysInput) {
|
||||||
data.clearApiKeys = true
|
data.apiKeyUpdateMode = apiKeyUpdateMode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEditingDroidApiKey.value) {
|
if (isEditingDroidApiKey.value) {
|
||||||
@@ -4674,10 +4763,11 @@ watch(
|
|||||||
errors.value.accessToken = ''
|
errors.value.accessToken = ''
|
||||||
errors.value.refreshToken = ''
|
errors.value.refreshToken = ''
|
||||||
form.value.authenticationMethod = 'api_key'
|
form.value.authenticationMethod = 'api_key'
|
||||||
|
form.value.apiKeyUpdateMode = 'append'
|
||||||
} else if (oldType === 'apikey') {
|
} else if (oldType === 'apikey') {
|
||||||
// 切换离开 API Key 模式时重置 API Key 输入
|
// 切换离开 API Key 模式时重置 API Key 输入
|
||||||
form.value.apiKeysInput = ''
|
form.value.apiKeysInput = ''
|
||||||
form.value.clearExistingApiKeys = false
|
form.value.apiKeyUpdateMode = 'append'
|
||||||
errors.value.apiKeys = ''
|
errors.value.apiKeys = ''
|
||||||
if (!isEdit.value) {
|
if (!isEdit.value) {
|
||||||
form.value.authenticationMethod = ''
|
form.value.authenticationMethod = ''
|
||||||
@@ -4686,6 +4776,20 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 监听 API Key 更新模式切换,自动清理提示
|
||||||
|
watch(
|
||||||
|
() => form.value.apiKeyUpdateMode,
|
||||||
|
(newMode, oldMode) => {
|
||||||
|
if (newMode === oldMode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.value.apiKeys) {
|
||||||
|
errors.value.apiKeys = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// 监听 API Key 输入,自动清理错误提示
|
// 监听 API Key 输入,自动清理错误提示
|
||||||
watch(
|
watch(
|
||||||
() => form.value.apiKeysInput,
|
() => form.value.apiKeysInput,
|
||||||
@@ -4694,7 +4798,22 @@ watch(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseApiKeysInput(newValue).length > 0) {
|
const parsed = parseApiKeysInput(newValue)
|
||||||
|
const mode = form.value.apiKeyUpdateMode
|
||||||
|
|
||||||
|
if (mode === 'append' && parsed.length > 0) {
|
||||||
|
errors.value.apiKeys = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === 'replace') {
|
||||||
|
if (parsed.length > 0 || !newValue || newValue.trim() === '') {
|
||||||
|
errors.value.apiKeys = ''
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === 'delete' && parsed.length > 0) {
|
||||||
errors.value.apiKeys = ''
|
errors.value.apiKeys = ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4830,6 +4949,16 @@ watch(
|
|||||||
initModelMappings()
|
initModelMappings()
|
||||||
// 重新初始化代理配置
|
// 重新初始化代理配置
|
||||||
const proxyConfig = normalizeProxyFormState(newAccount.proxy)
|
const proxyConfig = normalizeProxyFormState(newAccount.proxy)
|
||||||
|
const normalizedAuthMethod =
|
||||||
|
typeof newAccount.authenticationMethod === 'string'
|
||||||
|
? newAccount.authenticationMethod.trim().toLowerCase()
|
||||||
|
: ''
|
||||||
|
const derivedAddType =
|
||||||
|
normalizedAuthMethod === 'api_key'
|
||||||
|
? 'apikey'
|
||||||
|
: normalizedAuthMethod === 'manual'
|
||||||
|
? 'manual'
|
||||||
|
: 'oauth'
|
||||||
|
|
||||||
// 获取分组ID - 可能来自 groupId 字段或 groupInfo 对象
|
// 获取分组ID - 可能来自 groupId 字段或 groupInfo 对象
|
||||||
let groupId = ''
|
let groupId = ''
|
||||||
@@ -4858,7 +4987,7 @@ watch(
|
|||||||
|
|
||||||
form.value = {
|
form.value = {
|
||||||
platform: newAccount.platform,
|
platform: newAccount.platform,
|
||||||
addType: 'oauth',
|
addType: derivedAddType,
|
||||||
name: newAccount.name,
|
name: newAccount.name,
|
||||||
description: newAccount.description || '',
|
description: newAccount.description || '',
|
||||||
accountType: newAccount.accountType || 'shared',
|
accountType: newAccount.accountType || 'shared',
|
||||||
@@ -4872,6 +5001,9 @@ watch(
|
|||||||
projectId: newAccount.projectId || '',
|
projectId: newAccount.projectId || '',
|
||||||
accessToken: '',
|
accessToken: '',
|
||||||
refreshToken: '',
|
refreshToken: '',
|
||||||
|
authenticationMethod: newAccount.authenticationMethod || '',
|
||||||
|
apiKeysInput: '',
|
||||||
|
apiKeyUpdateMode: 'append',
|
||||||
proxy: proxyConfig,
|
proxy: proxyConfig,
|
||||||
// Claude Console 特定字段
|
// Claude Console 特定字段
|
||||||
apiUrl: newAccount.apiUrl || '',
|
apiUrl: newAccount.apiUrl || '',
|
||||||
|
|||||||
Reference in New Issue
Block a user