mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-03 03:10:50 +08:00
feat: improve iFlow cookie auth UX with duplicate config handling
- Add 409 conflict handling for duplicate iFlow config files - Add key creation hint in cookie login section - Move extra actions button after delete button for consistency - Improve OAuth status badge display logic (hide when idle) - Add config toggle enable/disable i18n translations - Adjust item-actions spacing from sm to md
This commit is contained in:
@@ -447,10 +447,13 @@
|
||||
"iflow_cookie_label": "Cookie Value:",
|
||||
"iflow_cookie_placeholder": "Paste browser cookie, e.g. sessionid=...;",
|
||||
"iflow_cookie_hint": "Submit an existing cookie to finish login without opening the authorization link; the credential file will be saved automatically.",
|
||||
"iflow_cookie_key_hint": "Note: Create a key on the platform first.",
|
||||
"iflow_cookie_button": "Submit Cookie Login",
|
||||
"iflow_cookie_status_success": "Cookie login succeeded and credentials are saved.",
|
||||
"iflow_cookie_status_error": "Cookie login failed:",
|
||||
"iflow_cookie_status_duplicate": "Duplicate config:",
|
||||
"iflow_cookie_start_error": "Failed to submit cookie login:",
|
||||
"iflow_cookie_config_duplicate": "A config file already exists (duplicate). Remove the existing file and try again if you want to re-save it.",
|
||||
"iflow_cookie_required": "Please provide the Cookie value first.",
|
||||
"iflow_cookie_result_title": "Cookie Login Result",
|
||||
"iflow_cookie_result_email": "Account",
|
||||
|
||||
@@ -148,6 +148,8 @@
|
||||
"excluded_models_placeholder": "用逗号或换行分隔,例如: gemini-1.5-pro, gemini-1.5-flash",
|
||||
"excluded_models_hint": "留空表示不过滤;保存时会自动去重并忽略空白。",
|
||||
"excluded_models_count": "排除 {{count}} 个模型",
|
||||
"config_toggle_label": "启用",
|
||||
"config_disabled_badge": "已停用",
|
||||
"codex_title": "Codex API 配置",
|
||||
"codex_add_button": "添加配置",
|
||||
"codex_empty_title": "暂无Codex配置",
|
||||
@@ -445,10 +447,13 @@
|
||||
"iflow_cookie_label": "Cookie 内容:",
|
||||
"iflow_cookie_placeholder": "粘贴浏览器中的 Cookie,例如 sessionid=...;",
|
||||
"iflow_cookie_hint": "直接提交 Cookie 以完成登录(无需打开授权链接),服务端将自动保存凭据。",
|
||||
"iflow_cookie_key_hint": "提示:需在平台上先创建 Key。",
|
||||
"iflow_cookie_button": "提交 Cookie 登录",
|
||||
"iflow_cookie_status_success": "Cookie 登录成功,凭据已保存。",
|
||||
"iflow_cookie_status_error": "Cookie 登录失败:",
|
||||
"iflow_cookie_status_duplicate": "配置文件重复:",
|
||||
"iflow_cookie_start_error": "提交 Cookie 登录失败:",
|
||||
"iflow_cookie_config_duplicate": "检测到配置文件已存在(重复),如需重新保存请先删除原文件后重试。",
|
||||
"iflow_cookie_required": "请先填写 Cookie 内容",
|
||||
"iflow_cookie_result_title": "Cookie 登录结果",
|
||||
"iflow_cookie_result_email": "账号",
|
||||
@@ -636,6 +641,8 @@
|
||||
"claude_config_added": "Claude配置添加成功",
|
||||
"claude_config_updated": "Claude配置更新成功",
|
||||
"claude_config_deleted": "Claude配置删除成功",
|
||||
"config_enabled": "配置已启用",
|
||||
"config_disabled": "配置已停用",
|
||||
"field_required": "必填字段不能为空",
|
||||
"openai_provider_required": "请填写提供商名称和Base URL",
|
||||
"openai_provider_added": "OpenAI提供商添加成功",
|
||||
|
||||
@@ -1046,7 +1046,6 @@ export function AiProvidersPage() {
|
||||
<div key={keyField(item)} className="item-row" style={rowDisabled ? { opacity: 0.6 } : undefined}>
|
||||
<div className="item-meta">{renderContent(item, index)}</div>
|
||||
<div className="item-actions">
|
||||
{options?.renderExtraActions ? options.renderExtraActions(item, index) : null}
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
@@ -1063,6 +1062,7 @@ export function AiProvidersPage() {
|
||||
>
|
||||
{deleteLabel || t('common.delete')}
|
||||
</Button>
|
||||
{options?.renderExtraActions ? options.renderExtraActions(item, index) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -20,6 +20,7 @@ interface IFlowCookieState {
|
||||
loading: boolean;
|
||||
result?: IFlowCookieAuthResponse;
|
||||
error?: string;
|
||||
errorType?: 'error' | 'warning';
|
||||
}
|
||||
|
||||
const PROVIDERS: { id: OAuthProvider; titleKey: string; hintKey: string; urlLabelKey: string }[] = [
|
||||
@@ -122,18 +123,35 @@ export function OAuthPage() {
|
||||
showNotification(t('auth_login.iflow_cookie_required'), 'warning');
|
||||
return;
|
||||
}
|
||||
setIflowCookie((prev) => ({ ...prev, loading: true, error: undefined, result: undefined }));
|
||||
setIflowCookie((prev) => ({
|
||||
...prev,
|
||||
loading: true,
|
||||
error: undefined,
|
||||
errorType: undefined,
|
||||
result: undefined
|
||||
}));
|
||||
try {
|
||||
const res = await oauthApi.iflowCookieAuth(cookie);
|
||||
if (res.status === 'ok') {
|
||||
setIflowCookie((prev) => ({ ...prev, loading: false, result: res }));
|
||||
showNotification(t('auth_login.iflow_cookie_status_success'), 'success');
|
||||
} else {
|
||||
setIflowCookie((prev) => ({ ...prev, loading: false, error: res.error }));
|
||||
setIflowCookie((prev) => ({
|
||||
...prev,
|
||||
loading: false,
|
||||
error: res.error,
|
||||
errorType: 'error'
|
||||
}));
|
||||
showNotification(`${t('auth_login.iflow_cookie_status_error')} ${res.error || ''}`, 'error');
|
||||
}
|
||||
} catch (err: any) {
|
||||
setIflowCookie((prev) => ({ ...prev, loading: false, error: err?.message }));
|
||||
if (err?.status === 409) {
|
||||
const message = t('auth_login.iflow_cookie_config_duplicate');
|
||||
setIflowCookie((prev) => ({ ...prev, loading: false, error: message, errorType: 'warning' }));
|
||||
showNotification(message, 'warning');
|
||||
return;
|
||||
}
|
||||
setIflowCookie((prev) => ({ ...prev, loading: false, error: err?.message, errorType: 'error' }));
|
||||
showNotification(`${t('auth_login.iflow_cookie_start_error')} ${err?.message || ''}`, 'error');
|
||||
}
|
||||
};
|
||||
@@ -185,15 +203,13 @@ export function OAuthPage() {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{!isDisabled && (
|
||||
{!isDisabled && state.status && state.status !== 'idle' && (
|
||||
<div className="status-badge" style={{ marginTop: 8 }}>
|
||||
{state.status === 'success'
|
||||
? t('auth_login.codex_oauth_status_success')
|
||||
: state.status === 'error'
|
||||
? `${t('auth_login.codex_oauth_status_error')} ${state.error || ''}`
|
||||
: state.status === 'waiting'
|
||||
? t('auth_login.codex_oauth_status_waiting')
|
||||
: t('common.info')}
|
||||
: t('auth_login.codex_oauth_status_waiting')}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
@@ -211,6 +227,9 @@ export function OAuthPage() {
|
||||
}
|
||||
>
|
||||
<div className="hint">{t('auth_login.iflow_cookie_hint')}</div>
|
||||
<div className="hint" style={{ marginTop: 4 }}>
|
||||
{t('auth_login.iflow_cookie_key_hint')}
|
||||
</div>
|
||||
<div className="form-item" style={{ marginTop: 12 }}>
|
||||
<label className="label">{t('auth_login.iflow_cookie_label')}</label>
|
||||
<Input
|
||||
@@ -220,8 +239,14 @@ export function OAuthPage() {
|
||||
/>
|
||||
</div>
|
||||
{iflowCookie.error && (
|
||||
<div className="status-badge error" style={{ marginTop: 8 }}>
|
||||
{t('auth_login.iflow_cookie_status_error')} {iflowCookie.error}
|
||||
<div
|
||||
className={`status-badge ${iflowCookie.errorType === 'warning' ? 'warning' : 'error'}`}
|
||||
style={{ marginTop: 8 }}
|
||||
>
|
||||
{iflowCookie.errorType === 'warning'
|
||||
? t('auth_login.iflow_cookie_status_duplicate')
|
||||
: t('auth_login.iflow_cookie_status_error')}{' '}
|
||||
{iflowCookie.error}
|
||||
</div>
|
||||
)}
|
||||
{iflowCookie.result && iflowCookie.result.status === 'ok' && (
|
||||
|
||||
@@ -407,7 +407,7 @@
|
||||
|
||||
.item-actions {
|
||||
display: flex;
|
||||
gap: $spacing-sm;
|
||||
gap: $spacing-md;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user