mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
fix: 修复批量编辑模式下专属账号修改的问题
This commit is contained in:
@@ -346,151 +346,76 @@
|
||||
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
|
||||
>Claude 专属账号</label
|
||||
>
|
||||
<select
|
||||
v-model="form.claudeAccountId"
|
||||
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200"
|
||||
:disabled="form.permissions && !['all', 'claude'].includes(form.permissions)"
|
||||
>
|
||||
<option value="">不修改</option>
|
||||
<option value="SHARED_POOL">使用共享账号池</option>
|
||||
<optgroup v-if="localAccounts.claudeGroups.length > 0" label="账号分组">
|
||||
<option
|
||||
v-for="group in localAccounts.claudeGroups"
|
||||
:key="group.id"
|
||||
:value="`group:${group.id}`"
|
||||
>
|
||||
分组 - {{ group.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
<optgroup v-if="localAccounts.claude.length > 0" label="专属账号">
|
||||
<option
|
||||
v-for="account in localAccounts.claude"
|
||||
:key="account.id"
|
||||
:value="
|
||||
account.platform === 'claude-console' ? `console:${account.id}` : account.id
|
||||
"
|
||||
>
|
||||
{{ account.name }} ({{
|
||||
account.platform === 'claude-console' ? 'Console' : 'OAuth'
|
||||
}})
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<AccountSelector
|
||||
v-model="claudeAccountSelectorValue"
|
||||
:accounts="localAccounts.claude"
|
||||
default-option-text="请选择Claude账号"
|
||||
:disabled="!isServiceSelectable('claude')"
|
||||
:groups="localAccounts.claudeGroups"
|
||||
placeholder="请选择Claude账号"
|
||||
platform="claude"
|
||||
:special-options="accountSpecialOptions"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
|
||||
>Gemini 专属账号</label
|
||||
>
|
||||
<select
|
||||
v-model="form.geminiAccountId"
|
||||
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200"
|
||||
:disabled="form.permissions && !['all', 'gemini'].includes(form.permissions)"
|
||||
>
|
||||
<option value="">不修改</option>
|
||||
<option value="SHARED_POOL">使用共享账号池</option>
|
||||
<optgroup v-if="localAccounts.geminiGroups.length > 0" label="账号分组">
|
||||
<option
|
||||
v-for="group in localAccounts.geminiGroups"
|
||||
:key="group.id"
|
||||
:value="`group:${group.id}`"
|
||||
>
|
||||
分组 - {{ group.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
<optgroup v-if="localAccounts.gemini.length > 0" label="专属账号">
|
||||
<option
|
||||
v-for="account in localAccounts.gemini"
|
||||
:key="account.id"
|
||||
:value="account.id"
|
||||
>
|
||||
{{ account.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<AccountSelector
|
||||
v-model="geminiAccountSelectorValue"
|
||||
:accounts="localAccounts.gemini"
|
||||
default-option-text="请选择Gemini账号"
|
||||
:disabled="!isServiceSelectable('gemini')"
|
||||
:groups="localAccounts.geminiGroups"
|
||||
placeholder="请选择Gemini账号"
|
||||
platform="gemini"
|
||||
:special-options="accountSpecialOptions"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
|
||||
>OpenAI 专属账号</label
|
||||
>
|
||||
<select
|
||||
v-model="form.openaiAccountId"
|
||||
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200"
|
||||
:disabled="form.permissions && !['all', 'openai'].includes(form.permissions)"
|
||||
>
|
||||
<option value="">不修改</option>
|
||||
<option value="SHARED_POOL">使用共享账号池</option>
|
||||
<optgroup v-if="localAccounts.openaiGroups.length > 0" label="账号分组">
|
||||
<option
|
||||
v-for="group in localAccounts.openaiGroups"
|
||||
:key="group.id"
|
||||
:value="`group:${group.id}`"
|
||||
>
|
||||
分组 - {{ group.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
<optgroup v-if="localAccounts.openai.length > 0" label="专属账号">
|
||||
<option
|
||||
v-for="account in localAccounts.openai"
|
||||
:key="account.id"
|
||||
:value="account.id"
|
||||
>
|
||||
{{ account.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<AccountSelector
|
||||
v-model="openaiAccountSelectorValue"
|
||||
:accounts="localAccounts.openai"
|
||||
default-option-text="请选择OpenAI账号"
|
||||
:disabled="!isServiceSelectable('openai')"
|
||||
:groups="localAccounts.openaiGroups"
|
||||
placeholder="请选择OpenAI账号"
|
||||
platform="openai"
|
||||
:special-options="accountSpecialOptions"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
|
||||
>Bedrock 专属账号</label
|
||||
>
|
||||
<select
|
||||
v-model="form.bedrockAccountId"
|
||||
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200"
|
||||
:disabled="form.permissions && !['all', 'openai'].includes(form.permissions)"
|
||||
>
|
||||
<option value="">不修改</option>
|
||||
<option value="SHARED_POOL">使用共享账号池</option>
|
||||
<optgroup v-if="localAccounts.bedrock.length > 0" label="专属账号">
|
||||
<option
|
||||
v-for="account in localAccounts.bedrock"
|
||||
:key="account.id"
|
||||
:value="account.id"
|
||||
>
|
||||
{{ account.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<AccountSelector
|
||||
v-model="bedrockAccountSelectorValue"
|
||||
:accounts="localAccounts.bedrock"
|
||||
default-option-text="请选择Bedrock账号"
|
||||
:disabled="!isServiceSelectable('openai')"
|
||||
:groups="[]"
|
||||
placeholder="请选择Bedrock账号"
|
||||
platform="bedrock"
|
||||
:special-options="accountSpecialOptions"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
|
||||
>Droid 专属账号</label
|
||||
>
|
||||
<select
|
||||
v-model="form.droidAccountId"
|
||||
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200"
|
||||
:disabled="form.permissions && !['all', 'droid'].includes(form.permissions)"
|
||||
>
|
||||
<option value="">不修改</option>
|
||||
<option value="SHARED_POOL">使用共享账号池</option>
|
||||
<optgroup v-if="localAccounts.droidGroups.length > 0" label="账号分组">
|
||||
<option
|
||||
v-for="group in localAccounts.droidGroups"
|
||||
:key="group.id"
|
||||
:value="`group:${group.id}`"
|
||||
>
|
||||
分组 - {{ group.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
<optgroup v-if="localAccounts.droid.length > 0" label="专属账号">
|
||||
<option
|
||||
v-for="account in localAccounts.droid"
|
||||
:key="account.id"
|
||||
:value="account.id"
|
||||
>
|
||||
{{ account.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<AccountSelector
|
||||
v-model="droidAccountSelectorValue"
|
||||
:accounts="localAccounts.droid"
|
||||
default-option-text="请选择Droid账号"
|
||||
:disabled="!isServiceSelectable('droid')"
|
||||
:groups="localAccounts.droidGroups"
|
||||
placeholder="请选择Droid账号"
|
||||
platform="droid"
|
||||
:special-options="accountSpecialOptions"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -524,6 +449,7 @@ import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { showToast } from '@/utils/toast'
|
||||
import { useApiKeysStore } from '@/stores/apiKeys'
|
||||
import { apiClient } from '@/config/api'
|
||||
import AccountSelector from '@/components/common/AccountSelector.vue'
|
||||
|
||||
const props = defineProps({
|
||||
selectedKeys: {
|
||||
@@ -594,6 +520,37 @@ const form = reactive({
|
||||
isActive: null // null表示不修改
|
||||
})
|
||||
|
||||
const UNCHANGED_OPTION_VALUE = '__KEEP_ORIGINAL__'
|
||||
|
||||
const accountSpecialOptions = [
|
||||
{ value: UNCHANGED_OPTION_VALUE, label: '不修改' },
|
||||
{ value: 'SHARED_POOL', label: '使用共享账号池' }
|
||||
]
|
||||
|
||||
const createAccountSelectorModel = (field) =>
|
||||
computed({
|
||||
get: () => (form[field] === '' ? UNCHANGED_OPTION_VALUE : form[field]),
|
||||
set: (value) => {
|
||||
if (!value || value === UNCHANGED_OPTION_VALUE) {
|
||||
form[field] = ''
|
||||
} else {
|
||||
form[field] = value
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const claudeAccountSelectorValue = createAccountSelectorModel('claudeAccountId')
|
||||
const geminiAccountSelectorValue = createAccountSelectorModel('geminiAccountId')
|
||||
const openaiAccountSelectorValue = createAccountSelectorModel('openaiAccountId')
|
||||
const bedrockAccountSelectorValue = createAccountSelectorModel('bedrockAccountId')
|
||||
const droidAccountSelectorValue = createAccountSelectorModel('droidAccountId')
|
||||
|
||||
const isServiceSelectable = (service) => {
|
||||
if (!form.permissions) return true
|
||||
if (form.permissions === 'all') return true
|
||||
return form.permissions === service
|
||||
}
|
||||
|
||||
// 标签管理方法
|
||||
const addTag = () => {
|
||||
if (newTag.value && newTag.value.trim()) {
|
||||
|
||||
@@ -62,6 +62,28 @@
|
||||
|
||||
<!-- 选项列表 -->
|
||||
<div class="custom-scrollbar flex-1 overflow-y-auto">
|
||||
<!-- 特殊选项 -->
|
||||
<div
|
||||
v-if="specialOptionsList.length > 0"
|
||||
class="border-b border-gray-200 dark:border-gray-600"
|
||||
>
|
||||
<div
|
||||
v-for="option in specialOptionsList"
|
||||
:key="`special-${option.value}`"
|
||||
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
:class="{ 'bg-blue-50 dark:bg-blue-900/20': modelValue === option.value }"
|
||||
@click="selectAccount(option.value)"
|
||||
>
|
||||
<span class="text-gray-700 dark:text-gray-300">{{ option.label }}</span>
|
||||
<span
|
||||
v-if="option.description"
|
||||
class="ml-2 text-xs text-gray-400 dark:text-gray-500"
|
||||
>
|
||||
{{ option.description }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 默认选项 -->
|
||||
<div
|
||||
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
@@ -264,6 +286,10 @@ const props = defineProps({
|
||||
defaultOptionText: {
|
||||
type: String,
|
||||
default: '使用共享账号池'
|
||||
},
|
||||
specialOptions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
@@ -276,9 +302,17 @@ const dropdownRef = ref(null)
|
||||
const dropdownStyle = ref({})
|
||||
const triggerRef = ref(null)
|
||||
const lastDirection = ref('') // 记住上次的显示方向
|
||||
const specialOptionsList = computed(() => props.specialOptions || [])
|
||||
|
||||
// 获取选中的标签
|
||||
const selectedLabel = computed(() => {
|
||||
const matchedSpecial = specialOptionsList.value.find(
|
||||
(option) => option.value === props.modelValue
|
||||
)
|
||||
if (matchedSpecial) {
|
||||
return matchedSpecial.label
|
||||
}
|
||||
|
||||
// 如果没有选中值,显示默认选项文本
|
||||
if (!props.modelValue) return props.defaultOptionText
|
||||
|
||||
|
||||
Reference in New Issue
Block a user