feat: 增加APIKey 客户端限制功能

This commit is contained in:
KevinLiao
2025-07-25 23:36:48 +08:00
parent 6f2fe2f643
commit b8c7c3e9f5
7 changed files with 302 additions and 17 deletions

View File

@@ -127,6 +127,8 @@ const app = createApp({
enableModelRestriction: false,
restrictedModels: [],
modelInput: '',
enableClientRestriction: false,
allowedClients: [],
expireDuration: '', // 过期时长选择
customExpireDate: '', // 自定义过期日期
expiresAt: null // 实际的过期时间戳
@@ -186,9 +188,14 @@ const app = createApp({
permissions: 'all',
enableModelRestriction: false,
restrictedModels: [],
modelInput: ''
modelInput: '',
enableClientRestriction: false,
allowedClients: []
},
// 支持的客户端列表
supportedClients: [],
// 账户
accounts: [],
accountsLoading: false,
@@ -346,10 +353,11 @@ const app = createApp({
// 初始化日期筛选器和图表数据
this.initializeDateFilter();
// 预加载账号列表API Keys以便正确显示绑定关系
// 预加载账号列表API Keys和支持的客户端,以便正确显示绑定关系
Promise.all([
this.loadAccounts(),
this.loadApiKeys()
this.loadApiKeys(),
this.loadSupportedClients()
]).then(() => {
// 根据当前活跃标签页加载数据
this.loadCurrentTabData();
@@ -1778,6 +1786,18 @@ const app = createApp({
}
},
async loadSupportedClients() {
try {
const data = await this.apiRequest('/admin/supported-clients');
if (data && data.success) {
this.supportedClients = data.data || [];
console.log('Loaded supported clients:', this.supportedClients);
}
} catch (error) {
console.error('Failed to load supported clients:', error);
}
},
async loadApiKeys() {
this.apiKeysLoading = true;
console.log('Loading API Keys with time range:', this.apiKeyStatsTimeRange);
@@ -1916,6 +1936,8 @@ const app = createApp({
permissions: this.apiKeyForm.permissions || 'all',
enableModelRestriction: this.apiKeyForm.enableModelRestriction,
restrictedModels: this.apiKeyForm.restrictedModels,
enableClientRestriction: this.apiKeyForm.enableClientRestriction,
allowedClients: this.apiKeyForm.allowedClients,
expiresAt: this.apiKeyForm.expiresAt
})
});
@@ -1950,6 +1972,8 @@ const app = createApp({
enableModelRestriction: false,
restrictedModels: [],
modelInput: '',
enableClientRestriction: false,
allowedClients: [],
expireDuration: '',
customExpireDate: '',
expiresAt: null
@@ -2117,7 +2141,9 @@ const app = createApp({
permissions: key.permissions || 'all',
enableModelRestriction: key.enableModelRestriction || false,
restrictedModels: key.restrictedModels ? [...key.restrictedModels] : [],
modelInput: ''
modelInput: '',
enableClientRestriction: key.enableClientRestriction || false,
allowedClients: key.allowedClients ? [...key.allowedClients] : []
};
this.showEditApiKeyModal = true;
},
@@ -2136,7 +2162,9 @@ const app = createApp({
permissions: 'all',
enableModelRestriction: false,
restrictedModels: [],
modelInput: ''
modelInput: '',
enableClientRestriction: false,
allowedClients: []
};
},
@@ -2154,7 +2182,9 @@ const app = createApp({
geminiAccountId: this.editApiKeyForm.geminiAccountId || null,
permissions: this.editApiKeyForm.permissions || 'all',
enableModelRestriction: this.editApiKeyForm.enableModelRestriction,
restrictedModels: this.editApiKeyForm.restrictedModels
restrictedModels: this.editApiKeyForm.restrictedModels,
enableClientRestriction: this.editApiKeyForm.enableClientRestriction,
allowedClients: this.editApiKeyForm.allowedClients
})
});

View File

@@ -2205,6 +2205,43 @@
</div>
</div>
<!-- 客户端限制 -->
<div>
<div class="flex items-center mb-3">
<input
type="checkbox"
v-model="apiKeyForm.enableClientRestriction"
id="enableClientRestriction"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"
>
<label for="enableClientRestriction" class="ml-2 text-sm font-semibold text-gray-700 cursor-pointer">
启用客户端限制
</label>
</div>
<div v-if="apiKeyForm.enableClientRestriction" class="space-y-3">
<div>
<label class="block text-sm font-medium text-gray-600 mb-2">允许的客户端</label>
<p class="text-xs text-gray-500 mb-3">勾选允许使用此API Key的客户端</p>
<div class="space-y-2">
<div v-for="client in supportedClients" :key="client.id" class="flex items-start">
<input
type="checkbox"
:id="`client_${client.id}`"
:value="client.id"
v-model="apiKeyForm.allowedClients"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"
>
<label :for="`client_${client.id}`" class="ml-2 flex-1 cursor-pointer">
<span class="text-sm font-medium text-gray-700">{{ client.name }}</span>
<span class="text-xs text-gray-500 block">{{ client.description }}</span>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="flex gap-3 pt-4">
<button
type="button"
@@ -2462,6 +2499,43 @@
</div>
</div>
<!-- 客户端限制 -->
<div>
<div class="flex items-center mb-3">
<input
type="checkbox"
v-model="editApiKeyForm.enableClientRestriction"
id="editEnableClientRestriction"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"
>
<label for="editEnableClientRestriction" class="ml-2 text-sm font-semibold text-gray-700 cursor-pointer">
启用客户端限制
</label>
</div>
<div v-if="editApiKeyForm.enableClientRestriction" class="space-y-3">
<div>
<label class="block text-sm font-medium text-gray-600 mb-2">允许的客户端</label>
<p class="text-xs text-gray-500 mb-3">勾选允许使用此API Key的客户端</p>
<div class="space-y-2">
<div v-for="client in supportedClients" :key="client.id" class="flex items-start">
<input
type="checkbox"
:id="`edit_client_${client.id}`"
:value="client.id"
v-model="editApiKeyForm.allowedClients"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"
>
<label :for="`edit_client_${client.id}`" class="ml-2 flex-1 cursor-pointer">
<span class="text-sm font-medium text-gray-700">{{ client.name }}</span>
<span class="text-xs text-gray-500 block">{{ client.description }}</span>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="flex gap-3 pt-4">
<button
type="button"