fix: 修复批量编辑模式下专属账号修改的问题

This commit is contained in:
shaw
2025-10-13 09:16:13 +08:00
parent 508d9aad1b
commit cea6f976b9
2 changed files with 116 additions and 125 deletions

View File

@@ -346,151 +346,76 @@
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400" <label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
>Claude 专属账号</label >Claude 专属账号</label
> >
<select <AccountSelector
v-model="form.claudeAccountId" v-model="claudeAccountSelectorValue"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200" :accounts="localAccounts.claude"
:disabled="form.permissions && !['all', 'claude'].includes(form.permissions)" default-option-text="请选择Claude账号"
> :disabled="!isServiceSelectable('claude')"
<option value="">不修改</option> :groups="localAccounts.claudeGroups"
<option value="SHARED_POOL">使用共享账号池</option> placeholder="请选择Claude账号"
<optgroup v-if="localAccounts.claudeGroups.length > 0" label="账号分组"> platform="claude"
<option :special-options="accountSpecialOptions"
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>
</div> </div>
<div> <div>
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400" <label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
>Gemini 专属账号</label >Gemini 专属账号</label
> >
<select <AccountSelector
v-model="form.geminiAccountId" v-model="geminiAccountSelectorValue"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200" :accounts="localAccounts.gemini"
:disabled="form.permissions && !['all', 'gemini'].includes(form.permissions)" default-option-text="请选择Gemini账号"
> :disabled="!isServiceSelectable('gemini')"
<option value="">不修改</option> :groups="localAccounts.geminiGroups"
<option value="SHARED_POOL">使用共享账号池</option> placeholder="请选择Gemini账号"
<optgroup v-if="localAccounts.geminiGroups.length > 0" label="账号分组"> platform="gemini"
<option :special-options="accountSpecialOptions"
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>
</div> </div>
<div> <div>
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400" <label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
>OpenAI 专属账号</label >OpenAI 专属账号</label
> >
<select <AccountSelector
v-model="form.openaiAccountId" v-model="openaiAccountSelectorValue"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200" :accounts="localAccounts.openai"
:disabled="form.permissions && !['all', 'openai'].includes(form.permissions)" default-option-text="请选择OpenAI账号"
> :disabled="!isServiceSelectable('openai')"
<option value="">不修改</option> :groups="localAccounts.openaiGroups"
<option value="SHARED_POOL">使用共享账号池</option> placeholder="请选择OpenAI账号"
<optgroup v-if="localAccounts.openaiGroups.length > 0" label="账号分组"> platform="openai"
<option :special-options="accountSpecialOptions"
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>
</div> </div>
<div> <div>
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400" <label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
>Bedrock 专属账号</label >Bedrock 专属账号</label
> >
<select <AccountSelector
v-model="form.bedrockAccountId" v-model="bedrockAccountSelectorValue"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200" :accounts="localAccounts.bedrock"
:disabled="form.permissions && !['all', 'openai'].includes(form.permissions)" default-option-text="请选择Bedrock账号"
> :disabled="!isServiceSelectable('openai')"
<option value="">不修改</option> :groups="[]"
<option value="SHARED_POOL">使用共享账号池</option> placeholder="请选择Bedrock账号"
<optgroup v-if="localAccounts.bedrock.length > 0" label="专属账号"> platform="bedrock"
<option :special-options="accountSpecialOptions"
v-for="account in localAccounts.bedrock" />
:key="account.id"
:value="account.id"
>
{{ account.name }}
</option>
</optgroup>
</select>
</div> </div>
<div> <div>
<label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400" <label class="mb-1 block text-sm font-medium text-gray-600 dark:text-gray-400"
>Droid 专属账号</label >Droid 专属账号</label
> >
<select <AccountSelector
v-model="form.droidAccountId" v-model="droidAccountSelectorValue"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200" :accounts="localAccounts.droid"
:disabled="form.permissions && !['all', 'droid'].includes(form.permissions)" default-option-text="请选择Droid账号"
> :disabled="!isServiceSelectable('droid')"
<option value="">不修改</option> :groups="localAccounts.droidGroups"
<option value="SHARED_POOL">使用共享账号池</option> placeholder="请选择Droid账号"
<optgroup v-if="localAccounts.droidGroups.length > 0" label="账号分组"> platform="droid"
<option :special-options="accountSpecialOptions"
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>
</div> </div>
</div> </div>
</div> </div>
@@ -524,6 +449,7 @@ import { ref, reactive, computed, onMounted } from 'vue'
import { showToast } from '@/utils/toast' import { showToast } from '@/utils/toast'
import { useApiKeysStore } from '@/stores/apiKeys' import { useApiKeysStore } from '@/stores/apiKeys'
import { apiClient } from '@/config/api' import { apiClient } from '@/config/api'
import AccountSelector from '@/components/common/AccountSelector.vue'
const props = defineProps({ const props = defineProps({
selectedKeys: { selectedKeys: {
@@ -594,6 +520,37 @@ const form = reactive({
isActive: null // null表示不修改 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 = () => { const addTag = () => {
if (newTag.value && newTag.value.trim()) { if (newTag.value && newTag.value.trim()) {

View File

@@ -62,6 +62,28 @@
<!-- 选项列表 --> <!-- 选项列表 -->
<div class="custom-scrollbar flex-1 overflow-y-auto"> <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 <div
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700" 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: { defaultOptionText: {
type: String, type: String,
default: '使用共享账号池' default: '使用共享账号池'
},
specialOptions: {
type: Array,
default: () => []
} }
}) })
@@ -276,9 +302,17 @@ const dropdownRef = ref(null)
const dropdownStyle = ref({}) const dropdownStyle = ref({})
const triggerRef = ref(null) const triggerRef = ref(null)
const lastDirection = ref('') // 记住上次的显示方向 const lastDirection = ref('') // 记住上次的显示方向
const specialOptionsList = computed(() => props.specialOptions || [])
// 获取选中的标签 // 获取选中的标签
const selectedLabel = computed(() => { const selectedLabel = computed(() => {
const matchedSpecial = specialOptionsList.value.find(
(option) => option.value === props.modelValue
)
if (matchedSpecial) {
return matchedSpecial.label
}
// 如果没有选中值,显示默认选项文本 // 如果没有选中值,显示默认选项文本
if (!props.modelValue) return props.defaultOptionText if (!props.modelValue) return props.defaultOptionText