diff --git a/web/admin-spa/src/components/apikeys/BatchEditApiKeyModal.vue b/web/admin-spa/src/components/apikeys/BatchEditApiKeyModal.vue index 853287d6..07e22954 100644 --- a/web/admin-spa/src/components/apikeys/BatchEditApiKeyModal.vue +++ b/web/admin-spa/src/components/apikeys/BatchEditApiKeyModal.vue @@ -346,151 +346,76 @@ - +
- +
- +
- +
- +
@@ -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()) { diff --git a/web/admin-spa/src/components/common/AccountSelector.vue b/web/admin-spa/src/components/common/AccountSelector.vue index 78b458da..191b8d16 100644 --- a/web/admin-spa/src/components/common/AccountSelector.vue +++ b/web/admin-spa/src/components/common/AccountSelector.vue @@ -62,6 +62,28 @@
+ +
+
+ {{ option.label }} + + {{ option.description }} + +
+
+
[] } }) @@ -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