mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-03 03:10:50 +08:00
feat: enhance excluded models management with UI components, internationalization, and data handling
This commit is contained in:
8
i18n.js
8
i18n.js
@@ -149,6 +149,10 @@ const i18n = {
|
|||||||
'ai_providers.gemini_edit_modal_title': '编辑Gemini API密钥',
|
'ai_providers.gemini_edit_modal_title': '编辑Gemini API密钥',
|
||||||
'ai_providers.gemini_edit_modal_key_label': 'API密钥:',
|
'ai_providers.gemini_edit_modal_key_label': 'API密钥:',
|
||||||
'ai_providers.gemini_delete_confirm': '确定要删除这个Gemini密钥吗?',
|
'ai_providers.gemini_delete_confirm': '确定要删除这个Gemini密钥吗?',
|
||||||
|
'ai_providers.excluded_models_label': '排除的模型 (可选):',
|
||||||
|
'ai_providers.excluded_models_placeholder': '用逗号或换行分隔,例如: gemini-1.5-pro, gemini-1.5-flash',
|
||||||
|
'ai_providers.excluded_models_hint': '留空表示不过滤;保存时会自动去重并忽略空白。',
|
||||||
|
'ai_providers.excluded_models_count': '排除 {count} 个模型',
|
||||||
|
|
||||||
'ai_providers.codex_title': 'Codex API 配置',
|
'ai_providers.codex_title': 'Codex API 配置',
|
||||||
'ai_providers.codex_add_button': '添加配置',
|
'ai_providers.codex_add_button': '添加配置',
|
||||||
@@ -755,6 +759,10 @@ const i18n = {
|
|||||||
'ai_providers.gemini_edit_modal_title': 'Edit Gemini API Key',
|
'ai_providers.gemini_edit_modal_title': 'Edit Gemini API Key',
|
||||||
'ai_providers.gemini_edit_modal_key_label': 'API Key:',
|
'ai_providers.gemini_edit_modal_key_label': 'API Key:',
|
||||||
'ai_providers.gemini_delete_confirm': 'Are you sure you want to delete this Gemini key?',
|
'ai_providers.gemini_delete_confirm': 'Are you sure you want to delete this Gemini key?',
|
||||||
|
'ai_providers.excluded_models_label': 'Excluded models (optional):',
|
||||||
|
'ai_providers.excluded_models_placeholder': 'Comma or newline separated, e.g. gemini-1.5-pro, gemini-1.5-flash',
|
||||||
|
'ai_providers.excluded_models_hint': 'Leave empty to allow all models; values are trimmed and deduplicated automatically.',
|
||||||
|
'ai_providers.excluded_models_count': 'Excluding {count} models',
|
||||||
|
|
||||||
'ai_providers.codex_title': 'Codex API Configuration',
|
'ai_providers.codex_title': 'Codex API Configuration',
|
||||||
'ai_providers.codex_add_button': 'Add Configuration',
|
'ai_providers.codex_add_button': 'Add Configuration',
|
||||||
|
|||||||
@@ -59,6 +59,59 @@ const normalizeModelList = (payload) => {
|
|||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const normalizeExcludedModels = (input) => {
|
||||||
|
const rawList = Array.isArray(input)
|
||||||
|
? input
|
||||||
|
: (typeof input === 'string' ? input.split(/[\n,]/) : []);
|
||||||
|
const seen = new Set();
|
||||||
|
const normalized = [];
|
||||||
|
|
||||||
|
rawList.forEach(item => {
|
||||||
|
if (item === undefined || item === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const trimmed = String(item).trim();
|
||||||
|
if (!trimmed) return;
|
||||||
|
const key = trimmed.toLowerCase();
|
||||||
|
if (seen.has(key)) return;
|
||||||
|
seen.add(key);
|
||||||
|
normalized.push(trimmed);
|
||||||
|
});
|
||||||
|
|
||||||
|
return normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function collectExcludedModels(textareaId) {
|
||||||
|
const textarea = document.getElementById(textareaId);
|
||||||
|
if (!textarea) return [];
|
||||||
|
return normalizeExcludedModels(textarea.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setExcludedModelsValue(textareaId, models = []) {
|
||||||
|
const textarea = document.getElementById(textareaId);
|
||||||
|
if (!textarea) return;
|
||||||
|
textarea.value = normalizeExcludedModels(models).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderExcludedModelBadges(models) {
|
||||||
|
const normalized = normalizeExcludedModels(models);
|
||||||
|
if (!normalized.length) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
const badges = normalized.map(model => `
|
||||||
|
<span class="provider-model-tag excluded-model-tag">
|
||||||
|
<span class="model-name">${this.escapeHtml(model)}</span>
|
||||||
|
</span>
|
||||||
|
`).join('');
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="item-subtitle">${i18n.t('ai_providers.excluded_models_count', { count: normalized.length })}</div>
|
||||||
|
<div class="provider-models excluded-models">
|
||||||
|
${badges}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
export async function loadGeminiKeys() {
|
export async function loadGeminiKeys() {
|
||||||
try {
|
try {
|
||||||
const config = await this.getConfig();
|
const config = await this.getConfig();
|
||||||
@@ -144,6 +197,7 @@ export async function renderGeminiKeys(keys, keyStats = null) {
|
|||||||
const configJson = JSON.stringify(config).replace(/"/g, '"');
|
const configJson = JSON.stringify(config).replace(/"/g, '"');
|
||||||
const apiKeyJson = JSON.stringify(rawKey || '').replace(/"/g, '"');
|
const apiKeyJson = JSON.stringify(rawKey || '').replace(/"/g, '"');
|
||||||
const baseUrl = config['base-url'] || config['base_url'] || '';
|
const baseUrl = config['base-url'] || config['base_url'] || '';
|
||||||
|
const excludedModelsHtml = this.renderExcludedModelBadges(config['excluded-models']);
|
||||||
return `
|
return `
|
||||||
<div class="key-item">
|
<div class="key-item">
|
||||||
<div class="item-content">
|
<div class="item-content">
|
||||||
@@ -151,6 +205,7 @@ export async function renderGeminiKeys(keys, keyStats = null) {
|
|||||||
<div class="item-subtitle">${i18n.t('common.api_key')}: ${maskedDisplay}</div>
|
<div class="item-subtitle">${i18n.t('common.api_key')}: ${maskedDisplay}</div>
|
||||||
${baseUrl ? `<div class="item-subtitle">${i18n.t('common.base_url')}: ${this.escapeHtml(baseUrl)}</div>` : ''}
|
${baseUrl ? `<div class="item-subtitle">${i18n.t('common.base_url')}: ${this.escapeHtml(baseUrl)}</div>` : ''}
|
||||||
${this.renderHeaderBadges(config.headers)}
|
${this.renderHeaderBadges(config.headers)}
|
||||||
|
${excludedModelsHtml}
|
||||||
<div class="item-stats">
|
<div class="item-stats">
|
||||||
<span class="stat-badge stat-success">
|
<span class="stat-badge stat-success">
|
||||||
<i class="fas fa-check-circle"></i> ${i18n.t('stats.success')}: ${usageStats.success}
|
<i class="fas fa-check-circle"></i> ${i18n.t('stats.success')}: ${usageStats.success}
|
||||||
@@ -191,6 +246,11 @@ export function showAddGeminiKeyModal() {
|
|||||||
<div id="new-gemini-headers-wrapper" class="header-input-list"></div>
|
<div id="new-gemini-headers-wrapper" class="header-input-list"></div>
|
||||||
<button type="button" class="btn btn-secondary" onclick="manager.addHeaderField('new-gemini-headers-wrapper')">${i18n.t('common.custom_headers_add')}</button>
|
<button type="button" class="btn btn-secondary" onclick="manager.addHeaderField('new-gemini-headers-wrapper')">${i18n.t('common.custom_headers_add')}</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new-gemini-excluded-models">${i18n.t('ai_providers.excluded_models_label')}</label>
|
||||||
|
<p class="form-hint">${i18n.t('ai_providers.excluded_models_hint')}</p>
|
||||||
|
<textarea id="new-gemini-excluded-models" rows="3" data-i18n-placeholder="ai_providers.excluded_models_placeholder" placeholder="${i18n.t('ai_providers.excluded_models_placeholder')}"></textarea>
|
||||||
|
</div>
|
||||||
<div class="modal-actions">
|
<div class="modal-actions">
|
||||||
<button class="btn btn-secondary" onclick="manager.closeModal()">${i18n.t('common.cancel')}</button>
|
<button class="btn btn-secondary" onclick="manager.closeModal()">${i18n.t('common.cancel')}</button>
|
||||||
<button class="btn btn-primary" onclick="manager.addGeminiKey()">${i18n.t('common.add')}</button>
|
<button class="btn btn-primary" onclick="manager.addGeminiKey()">${i18n.t('common.add')}</button>
|
||||||
@@ -200,11 +260,13 @@ export function showAddGeminiKeyModal() {
|
|||||||
modal.style.display = 'block';
|
modal.style.display = 'block';
|
||||||
this.populateGeminiKeyFields('new-gemini-keys-wrapper');
|
this.populateGeminiKeyFields('new-gemini-keys-wrapper');
|
||||||
this.populateHeaderFields('new-gemini-headers-wrapper');
|
this.populateHeaderFields('new-gemini-headers-wrapper');
|
||||||
|
this.setExcludedModelsValue('new-gemini-excluded-models');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addGeminiKey() {
|
export async function addGeminiKey() {
|
||||||
const entries = this.collectGeminiKeyFieldInputs('new-gemini-keys-wrapper');
|
const entries = this.collectGeminiKeyFieldInputs('new-gemini-keys-wrapper');
|
||||||
const headers = this.collectHeaderInputs('new-gemini-headers-wrapper');
|
const headers = this.collectHeaderInputs('new-gemini-headers-wrapper');
|
||||||
|
const excludedModels = this.collectExcludedModels('new-gemini-excluded-models');
|
||||||
|
|
||||||
if (!entries.length) {
|
if (!entries.length) {
|
||||||
this.showNotification(i18n.t('notification.gemini_multi_input_required'), 'error');
|
this.showNotification(i18n.t('notification.gemini_multi_input_required'), 'error');
|
||||||
@@ -245,6 +307,7 @@ export async function addGeminiKey() {
|
|||||||
} else {
|
} else {
|
||||||
delete newConfig['base-url'];
|
delete newConfig['base-url'];
|
||||||
}
|
}
|
||||||
|
newConfig['excluded-models'] = excludedModels;
|
||||||
this.applyHeadersToConfig(newConfig, headers);
|
this.applyHeadersToConfig(newConfig, headers);
|
||||||
|
|
||||||
const nextKeys = [...currentKeys, newConfig];
|
const nextKeys = [...currentKeys, newConfig];
|
||||||
@@ -371,6 +434,11 @@ export function editGeminiKey(index, config) {
|
|||||||
<div id="edit-gemini-headers-wrapper" class="header-input-list"></div>
|
<div id="edit-gemini-headers-wrapper" class="header-input-list"></div>
|
||||||
<button type="button" class="btn btn-secondary" onclick="manager.addHeaderField('edit-gemini-headers-wrapper')">${i18n.t('common.custom_headers_add')}</button>
|
<button type="button" class="btn btn-secondary" onclick="manager.addHeaderField('edit-gemini-headers-wrapper')">${i18n.t('common.custom_headers_add')}</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="edit-gemini-excluded-models">${i18n.t('ai_providers.excluded_models_label')}</label>
|
||||||
|
<p class="form-hint">${i18n.t('ai_providers.excluded_models_hint')}</p>
|
||||||
|
<textarea id="edit-gemini-excluded-models" rows="3" data-i18n-placeholder="ai_providers.excluded_models_placeholder" placeholder="${i18n.t('ai_providers.excluded_models_placeholder')}"></textarea>
|
||||||
|
</div>
|
||||||
<div class="modal-actions">
|
<div class="modal-actions">
|
||||||
<button class="btn btn-secondary" onclick="manager.closeModal()">${i18n.t('common.cancel')}</button>
|
<button class="btn btn-secondary" onclick="manager.closeModal()">${i18n.t('common.cancel')}</button>
|
||||||
<button class="btn btn-primary" onclick="manager.updateGeminiKey(${index})">${i18n.t('common.update')}</button>
|
<button class="btn btn-primary" onclick="manager.updateGeminiKey(${index})">${i18n.t('common.update')}</button>
|
||||||
@@ -380,6 +448,7 @@ export function editGeminiKey(index, config) {
|
|||||||
modal.style.display = 'block';
|
modal.style.display = 'block';
|
||||||
this.populateGeminiKeyFields('edit-gemini-keys-wrapper', [config], { allowRemoval: false });
|
this.populateGeminiKeyFields('edit-gemini-keys-wrapper', [config], { allowRemoval: false });
|
||||||
this.populateHeaderFields('edit-gemini-headers-wrapper', config.headers || null);
|
this.populateHeaderFields('edit-gemini-headers-wrapper', config.headers || null);
|
||||||
|
this.setExcludedModelsValue('edit-gemini-excluded-models', config['excluded-models'] || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateGeminiKey(index) {
|
export async function updateGeminiKey(index) {
|
||||||
@@ -392,6 +461,7 @@ export async function updateGeminiKey(index) {
|
|||||||
const newKey = entry['api-key'];
|
const newKey = entry['api-key'];
|
||||||
const baseUrl = entry['base-url'] || '';
|
const baseUrl = entry['base-url'] || '';
|
||||||
const headers = this.collectHeaderInputs('edit-gemini-headers-wrapper');
|
const headers = this.collectHeaderInputs('edit-gemini-headers-wrapper');
|
||||||
|
const excludedModels = this.collectExcludedModels('edit-gemini-excluded-models');
|
||||||
|
|
||||||
if (!newKey) {
|
if (!newKey) {
|
||||||
this.showNotification(i18n.t('notification.please_enter') + ' ' + i18n.t('notification.gemini_api_key'), 'error');
|
this.showNotification(i18n.t('notification.please_enter') + ' ' + i18n.t('notification.gemini_api_key'), 'error');
|
||||||
@@ -406,6 +476,7 @@ export async function updateGeminiKey(index) {
|
|||||||
} else {
|
} else {
|
||||||
delete newConfig['base-url'];
|
delete newConfig['base-url'];
|
||||||
}
|
}
|
||||||
|
newConfig['excluded-models'] = excludedModels;
|
||||||
this.applyHeadersToConfig(newConfig, headers);
|
this.applyHeadersToConfig(newConfig, headers);
|
||||||
|
|
||||||
await this.makeRequest('/gemini-api-key', {
|
await this.makeRequest('/gemini-api-key', {
|
||||||
@@ -477,6 +548,7 @@ export async function renderCodexKeys(keys, keyStats = null) {
|
|||||||
const maskedDisplay = this.escapeHtml(masked);
|
const maskedDisplay = this.escapeHtml(masked);
|
||||||
const usageStats = (rawKey && (statsBySource[rawKey] || statsBySource[masked])) || { success: 0, failure: 0 };
|
const usageStats = (rawKey && (statsBySource[rawKey] || statsBySource[masked])) || { success: 0, failure: 0 };
|
||||||
const deleteArg = JSON.stringify(rawKey).replace(/"/g, '"');
|
const deleteArg = JSON.stringify(rawKey).replace(/"/g, '"');
|
||||||
|
const excludedModelsHtml = this.renderExcludedModelBadges(config['excluded-models']);
|
||||||
return `
|
return `
|
||||||
<div class="provider-item">
|
<div class="provider-item">
|
||||||
<div class="item-content">
|
<div class="item-content">
|
||||||
@@ -485,6 +557,7 @@ export async function renderCodexKeys(keys, keyStats = null) {
|
|||||||
${config['base-url'] ? `<div class="item-subtitle">${i18n.t('common.base_url')}: ${this.escapeHtml(config['base-url'])}</div>` : ''}
|
${config['base-url'] ? `<div class="item-subtitle">${i18n.t('common.base_url')}: ${this.escapeHtml(config['base-url'])}</div>` : ''}
|
||||||
${config['proxy-url'] ? `<div class="item-subtitle">${i18n.t('common.proxy_url')}: ${this.escapeHtml(config['proxy-url'])}</div>` : ''}
|
${config['proxy-url'] ? `<div class="item-subtitle">${i18n.t('common.proxy_url')}: ${this.escapeHtml(config['proxy-url'])}</div>` : ''}
|
||||||
${this.renderHeaderBadges(config.headers)}
|
${this.renderHeaderBadges(config.headers)}
|
||||||
|
${excludedModelsHtml}
|
||||||
<div class="item-stats">
|
<div class="item-stats">
|
||||||
<span class="stat-badge stat-success">
|
<span class="stat-badge stat-success">
|
||||||
<i class="fas fa-check-circle"></i> ${i18n.t('stats.success')}: ${usageStats.success}
|
<i class="fas fa-check-circle"></i> ${i18n.t('stats.success')}: ${usageStats.success}
|
||||||
@@ -525,6 +598,11 @@ export function showAddCodexKeyModal() {
|
|||||||
<label for="new-codex-proxy">${i18n.t('ai_providers.codex_add_modal_proxy_label')}</label>
|
<label for="new-codex-proxy">${i18n.t('ai_providers.codex_add_modal_proxy_label')}</label>
|
||||||
<input type="text" id="new-codex-proxy" placeholder="${i18n.t('ai_providers.codex_add_modal_proxy_placeholder')}">
|
<input type="text" id="new-codex-proxy" placeholder="${i18n.t('ai_providers.codex_add_modal_proxy_placeholder')}">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="new-codex-excluded-models">${i18n.t('ai_providers.excluded_models_label')}</label>
|
||||||
|
<p class="form-hint">${i18n.t('ai_providers.excluded_models_hint')}</p>
|
||||||
|
<textarea id="new-codex-excluded-models" rows="3" data-i18n-placeholder="ai_providers.excluded_models_placeholder" placeholder="${i18n.t('ai_providers.excluded_models_placeholder')}"></textarea>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>${i18n.t('common.custom_headers_label')}</label>
|
<label>${i18n.t('common.custom_headers_label')}</label>
|
||||||
<p class="form-hint">${i18n.t('common.custom_headers_hint')}</p>
|
<p class="form-hint">${i18n.t('common.custom_headers_hint')}</p>
|
||||||
@@ -539,6 +617,7 @@ export function showAddCodexKeyModal() {
|
|||||||
|
|
||||||
modal.style.display = 'block';
|
modal.style.display = 'block';
|
||||||
this.populateHeaderFields('new-codex-headers-wrapper');
|
this.populateHeaderFields('new-codex-headers-wrapper');
|
||||||
|
this.setExcludedModelsValue('new-codex-excluded-models');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addCodexKey() {
|
export async function addCodexKey() {
|
||||||
@@ -546,6 +625,7 @@ export async function addCodexKey() {
|
|||||||
const baseUrl = document.getElementById('new-codex-url').value.trim();
|
const baseUrl = document.getElementById('new-codex-url').value.trim();
|
||||||
const proxyUrl = document.getElementById('new-codex-proxy').value.trim();
|
const proxyUrl = document.getElementById('new-codex-proxy').value.trim();
|
||||||
const headers = this.collectHeaderInputs('new-codex-headers-wrapper');
|
const headers = this.collectHeaderInputs('new-codex-headers-wrapper');
|
||||||
|
const excludedModels = this.collectExcludedModels('new-codex-excluded-models');
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
this.showNotification(i18n.t('notification.field_required'), 'error');
|
this.showNotification(i18n.t('notification.field_required'), 'error');
|
||||||
@@ -560,7 +640,7 @@ export async function addCodexKey() {
|
|||||||
const data = await this.makeRequest('/codex-api-key');
|
const data = await this.makeRequest('/codex-api-key');
|
||||||
const currentKeys = this.normalizeArrayResponse(data, 'codex-api-key').map(item => ({ ...item }));
|
const currentKeys = this.normalizeArrayResponse(data, 'codex-api-key').map(item => ({ ...item }));
|
||||||
|
|
||||||
const newConfig = this.buildCodexConfig(apiKey, baseUrl, proxyUrl, {}, headers);
|
const newConfig = this.buildCodexConfig(apiKey, baseUrl, proxyUrl, {}, headers, excludedModels);
|
||||||
|
|
||||||
currentKeys.push(newConfig);
|
currentKeys.push(newConfig);
|
||||||
|
|
||||||
@@ -596,6 +676,11 @@ export function editCodexKey(index, config) {
|
|||||||
<label for="edit-codex-proxy">${i18n.t('ai_providers.codex_edit_modal_proxy_label')}</label>
|
<label for="edit-codex-proxy">${i18n.t('ai_providers.codex_edit_modal_proxy_label')}</label>
|
||||||
<input type="text" id="edit-codex-proxy" value="${config['proxy-url'] || ''}">
|
<input type="text" id="edit-codex-proxy" value="${config['proxy-url'] || ''}">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="edit-codex-excluded-models">${i18n.t('ai_providers.excluded_models_label')}</label>
|
||||||
|
<p class="form-hint">${i18n.t('ai_providers.excluded_models_hint')}</p>
|
||||||
|
<textarea id="edit-codex-excluded-models" rows="3" data-i18n-placeholder="ai_providers.excluded_models_placeholder" placeholder="${i18n.t('ai_providers.excluded_models_placeholder')}"></textarea>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>${i18n.t('common.custom_headers_label')}</label>
|
<label>${i18n.t('common.custom_headers_label')}</label>
|
||||||
<p class="form-hint">${i18n.t('common.custom_headers_hint')}</p>
|
<p class="form-hint">${i18n.t('common.custom_headers_hint')}</p>
|
||||||
@@ -610,6 +695,7 @@ export function editCodexKey(index, config) {
|
|||||||
|
|
||||||
modal.style.display = 'block';
|
modal.style.display = 'block';
|
||||||
this.populateHeaderFields('edit-codex-headers-wrapper', config.headers || null);
|
this.populateHeaderFields('edit-codex-headers-wrapper', config.headers || null);
|
||||||
|
this.setExcludedModelsValue('edit-codex-excluded-models', config['excluded-models'] || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateCodexKey(index) {
|
export async function updateCodexKey(index) {
|
||||||
@@ -617,6 +703,7 @@ export async function updateCodexKey(index) {
|
|||||||
const baseUrl = document.getElementById('edit-codex-url').value.trim();
|
const baseUrl = document.getElementById('edit-codex-url').value.trim();
|
||||||
const proxyUrl = document.getElementById('edit-codex-proxy').value.trim();
|
const proxyUrl = document.getElementById('edit-codex-proxy').value.trim();
|
||||||
const headers = this.collectHeaderInputs('edit-codex-headers-wrapper');
|
const headers = this.collectHeaderInputs('edit-codex-headers-wrapper');
|
||||||
|
const excludedModels = this.collectExcludedModels('edit-codex-excluded-models');
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
this.showNotification(i18n.t('notification.field_required'), 'error');
|
this.showNotification(i18n.t('notification.field_required'), 'error');
|
||||||
@@ -636,7 +723,7 @@ export async function updateCodexKey(index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const original = currentList[index] ? { ...currentList[index] } : {};
|
const original = currentList[index] ? { ...currentList[index] } : {};
|
||||||
const newConfig = this.buildCodexConfig(apiKey, baseUrl, proxyUrl, original, headers);
|
const newConfig = this.buildCodexConfig(apiKey, baseUrl, proxyUrl, original, headers, excludedModels);
|
||||||
|
|
||||||
await this.makeRequest('/codex-api-key', {
|
await this.makeRequest('/codex-api-key', {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
@@ -1607,5 +1694,8 @@ export const aiProvidersModule = {
|
|||||||
populateModelFields,
|
populateModelFields,
|
||||||
collectModelInputs,
|
collectModelInputs,
|
||||||
renderModelBadges,
|
renderModelBadges,
|
||||||
|
renderExcludedModelBadges,
|
||||||
|
collectExcludedModels,
|
||||||
|
setExcludedModelsValue,
|
||||||
validateOpenAIProviderInput
|
validateOpenAIProviderInput
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ export const apiKeysModule = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 构造Codex配置,保持未展示的字段
|
// 构造Codex配置,保持未展示的字段
|
||||||
buildCodexConfig(apiKey, baseUrl, proxyUrl, original = {}, headers = null) {
|
buildCodexConfig(apiKey, baseUrl, proxyUrl, original = {}, headers = null, excludedModels = null) {
|
||||||
const result = {
|
const result = {
|
||||||
...original,
|
...original,
|
||||||
'api-key': apiKey,
|
'api-key': apiKey,
|
||||||
@@ -238,6 +238,9 @@ export const apiKeysModule = {
|
|||||||
'proxy-url': proxyUrl || ''
|
'proxy-url': proxyUrl || ''
|
||||||
};
|
};
|
||||||
this.applyHeadersToConfig(result, headers);
|
this.applyHeadersToConfig(result, headers);
|
||||||
|
if (Array.isArray(excludedModels)) {
|
||||||
|
result['excluded-models'] = excludedModels;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -2221,6 +2221,12 @@ input:checked+.slider:before {
|
|||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.provider-item .excluded-models .provider-model-tag {
|
||||||
|
background: var(--warning-bg);
|
||||||
|
border-color: var(--warning-border);
|
||||||
|
color: var(--warning-text);
|
||||||
|
}
|
||||||
|
|
||||||
.provider-model-tag .model-name {
|
.provider-model-tag .model-name {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user