Merge pull request #72 from kevinconan/main

feat: 增加APIKey 客户端限制功能
This commit is contained in:
Wesley Liddick
2025-07-26 11:03:06 +08:00
committed by GitHub
7 changed files with 302 additions and 17 deletions

View File

@@ -129,6 +129,8 @@ const app = createApp({
enableModelRestriction: false,
restrictedModels: [],
modelInput: '',
enableClientRestriction: false,
allowedClients: [],
expireDuration: '', // 过期时长选择
customExpireDate: '', // 自定义过期日期
expiresAt: null // 实际的过期时间戳
@@ -188,9 +190,14 @@ const app = createApp({
permissions: 'all',
enableModelRestriction: false,
restrictedModels: [],
modelInput: ''
modelInput: '',
enableClientRestriction: false,
allowedClients: []
},
// 支持的客户端列表
supportedClients: [],
// 账户
accounts: [],
accountsLoading: false,
@@ -427,10 +434,11 @@ const app = createApp({
// 初始化日期筛选器和图表数据
this.initializeDateFilter();
// 预加载账号列表API Keys以便正确显示绑定关系
// 预加载账号列表API Keys和支持的客户端,以便正确显示绑定关系
Promise.all([
this.loadAccounts(),
this.loadApiKeys()
this.loadApiKeys(),
this.loadSupportedClients()
]).then(() => {
// 根据当前活跃标签页加载数据
this.loadCurrentTabData();
@@ -1883,6 +1891,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);
@@ -2053,6 +2073,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
})
});
@@ -2087,6 +2109,8 @@ const app = createApp({
enableModelRestriction: false,
restrictedModels: [],
modelInput: '',
enableClientRestriction: false,
allowedClients: [],
expireDuration: '',
customExpireDate: '',
expiresAt: null
@@ -2254,7 +2278,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;
},
@@ -2273,7 +2299,9 @@ const app = createApp({
permissions: 'all',
enableModelRestriction: false,
restrictedModels: [],
modelInput: ''
modelInput: '',
enableClientRestriction: false,
allowedClients: []
};
},
@@ -2291,7 +2319,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

@@ -2270,6 +2270,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"
@@ -2527,6 +2564,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"