Compare commits

...

4 Commits

5 changed files with 60 additions and 13 deletions

35
app.js
View File

@@ -235,7 +235,7 @@ class CLIProxyManager {
const isLocalhost = hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1';
if (!isLocalhost) {
// 隐藏所有 OAuth 登录卡片
// 隐藏所有 OAuth 登录卡片(除了iFlow,因为它有Cookie登录功能可远程使用)
OAUTH_CARD_IDS.forEach(cardId => {
const card = document.getElementById(cardId);
if (card) {
@@ -243,21 +243,39 @@ class CLIProxyManager {
}
});
// 对于 iFlow card,只隐藏 OAuth 部分,保留 Cookie 登录部分
const iflowCard = document.getElementById('iflow-oauth-card');
if (iflowCard) {
// 隐藏 OAuth 部分
const oauthContent = document.getElementById('iflow-oauth-content');
const oauthButton = iflowCard.querySelector('button[onclick*="startIflowOAuth"]');
const oauthStatus = document.getElementById('iflow-oauth-status');
const oauthUrlGroup = iflowCard.querySelector('.form-group:has(#iflow-oauth-url)');
if (oauthContent) oauthContent.style.display = 'none';
if (oauthButton) oauthButton.style.display = 'none';
if (oauthStatus) oauthStatus.style.display = 'none';
if (oauthUrlGroup) oauthUrlGroup.style.display = 'none';
// 保持整个card可见,因为Cookie登录部分仍然可用
iflowCard.style.display = 'block';
}
// 如果找不到具体的卡片 ID尝试通过类名查找
const oauthCardElements = document.querySelectorAll('.card');
oauthCardElements.forEach(card => {
const cardText = card.textContent || '';
// 不再隐藏包含 'iFlow' 的卡片
if (cardText.includes('Codex OAuth') ||
cardText.includes('Anthropic OAuth') ||
cardText.includes('Antigravity OAuth') ||
cardText.includes('Gemini CLI OAuth') ||
cardText.includes('Qwen OAuth') ||
cardText.includes('iFlow OAuth')) {
cardText.includes('Qwen OAuth')) {
card.style.display = 'none';
}
});
console.log(`当前主机名: ${hostname},已隐藏 OAuth 登录框`);
console.log(`当前主机名: ${hostname},已隐藏 OAuth 登录框(保留 iFlow Cookie 登录)`);
}
}
@@ -1011,7 +1029,8 @@ function exposeManagerInstance(instance) {
function setupSiteLogo() {
const img = document.getElementById('site-logo');
const loginImg = document.getElementById('login-logo');
if (!img && !loginImg) return;
const favicon = document.getElementById('favicon-link');
if (!img && !loginImg && !favicon) return;
const inlineLogo = typeof window !== 'undefined' ? window.__INLINE_LOGO__ : null;
if (inlineLogo) {
@@ -1023,6 +1042,9 @@ function setupSiteLogo() {
loginImg.src = inlineLogo;
loginImg.style.display = 'inline-block';
}
if (favicon) {
favicon.href = inlineLogo;
}
return;
}
@@ -1044,6 +1066,9 @@ function setupSiteLogo() {
loginImg.src = test.src;
loginImg.style.display = 'inline-block';
}
if (favicon) {
favicon.href = test.src;
}
};
test.onerror = () => {
idx++;

View File

@@ -5,6 +5,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title data-i18n="title.login">CLI Proxy API Management Center</title>
<link rel="icon" type="image/x-icon" id="favicon-link">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css">

View File

@@ -1275,9 +1275,25 @@ export async function refreshOpenAIModelDiscovery() {
}
try {
const response = await fetch(context.endpoint, {
let response;
let usedSimpleRequest = false;
try {
// 首先尝试正常的带自定义headers的请求
response = await fetch(context.endpoint, {
headers: context.headers || {}
});
} catch (error) {
// 如果fetch失败(通常是CORS预检失败),尝试简单GET请求
console.warn('Normal fetch failed, trying simple GET request:', error);
usedSimpleRequest = true;
response = await fetch(context.endpoint, {
method: 'GET',
mode: 'cors',
credentials: 'omit'
// 不发送自定义headers,避免触发OPTIONS预检
});
}
if (!response.ok) {
throw new Error(`${response.status} ${response.statusText}`);
@@ -1298,6 +1314,10 @@ export async function refreshOpenAIModelDiscovery() {
if (!models.length) {
this.setOpenAIModelDiscoveryStatus(i18n.t('ai_providers.openai_models_fetch_empty'), 'warning');
} else {
if (usedSimpleRequest) {
// 如果使用了简单请求,提示用户
console.info('Models fetched using simple request (without custom headers)');
}
this.setOpenAIModelDiscoveryStatus('', 'info');
}
} catch (error) {

View File

@@ -111,14 +111,14 @@ export const REQUEST_TIMEOUT_MS = 30 * 1000;
/**
* OAuth 卡片元素 ID 列表
* 用于根据主机环境隐藏/显示不同的 OAuth 选项
* 注意: iflow-oauth-card 不在此列表中,因为它包含Cookie登录功能,该功能可在远程使用
*/
export const OAUTH_CARD_IDS = [
'codex-oauth-card',
'anthropic-oauth-card',
'antigravity-oauth-card',
'gemini-cli-oauth-card',
'qwen-oauth-card',
'iflow-oauth-card'
'qwen-oauth-card'
];
/**

View File

@@ -3057,8 +3057,9 @@ input:checked+.slider:before {
.sidebar {
position: fixed;
left: 0;
top: var(--navbar-height, 69px);
height: calc(100vh - var(--navbar-height, 69px));
top: 0;
height: 100vh;
padding-top: calc(var(--navbar-height, 69px) + 20px);
transform: translateX(-100%);
z-index: 150;
box-shadow: var(--shadow-sm);
@@ -3110,7 +3111,7 @@ input:checked+.slider:before {
align-items: stretch;
gap: 8px;
height: auto;
min-height: var(--navbar-height, 69px);
min-height: 60px;
}
.top-navbar-title {