mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-19 11:10:49 +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:
@@ -79,6 +79,13 @@ function normalizeAuthIndexValue(value: unknown): string | null {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isRuntimeOnlyAuthFile(file: AuthFileItem): boolean {
|
||||||
|
const raw = file['runtime_only'] ?? file.runtimeOnly;
|
||||||
|
if (typeof raw === 'boolean') return raw;
|
||||||
|
if (typeof raw === 'string') return raw.trim().toLowerCase() === 'true';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 解析认证文件的统计数据
|
// 解析认证文件的统计数据
|
||||||
function resolveAuthFileStats(
|
function resolveAuthFileStats(
|
||||||
file: AuthFileItem,
|
file: AuthFileItem,
|
||||||
@@ -356,11 +363,11 @@ export function AuthFilesPage() {
|
|||||||
// 删除全部
|
// 删除全部
|
||||||
await authFilesApi.deleteAll();
|
await authFilesApi.deleteAll();
|
||||||
showNotification(t('auth_files.delete_all_success'), 'success');
|
showNotification(t('auth_files.delete_all_success'), 'success');
|
||||||
setFiles([]);
|
setFiles((prev) => prev.filter((file) => isRuntimeOnlyAuthFile(file)));
|
||||||
} else {
|
} else {
|
||||||
// 删除筛选类型的文件
|
// 删除筛选类型的文件
|
||||||
const filesToDelete = files.filter(
|
const filesToDelete = files.filter(
|
||||||
(f) => f.type === filter && !f['runtime_only']
|
(f) => f.type === filter && !isRuntimeOnlyAuthFile(f)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (filesToDelete.length === 0) {
|
if (filesToDelete.length === 0) {
|
||||||
@@ -564,9 +571,8 @@ export function AuthFilesPage() {
|
|||||||
|
|
||||||
// 渲染单个认证文件卡片
|
// 渲染单个认证文件卡片
|
||||||
const renderFileCard = (item: AuthFileItem) => {
|
const renderFileCard = (item: AuthFileItem) => {
|
||||||
const fileStats = resolveAuthFileStats(item, keyStats);
|
const fileStats = resolveAuthFileStats(item, keyStats);
|
||||||
const runtimeOnlyValue = item['runtime_only'];
|
const isRuntimeOnly = isRuntimeOnlyAuthFile(item);
|
||||||
const isRuntimeOnly = runtimeOnlyValue === true || runtimeOnlyValue === 'true';
|
|
||||||
const typeColor = getTypeColor(item.type || 'unknown');
|
const typeColor = getTypeColor(item.type || 'unknown');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -601,19 +607,7 @@ export function AuthFilesPage() {
|
|||||||
|
|
||||||
<div className={styles.cardActions}>
|
<div className={styles.cardActions}>
|
||||||
{isRuntimeOnly ? (
|
{isRuntimeOnly ? (
|
||||||
<>
|
<div className={styles.virtualBadge}>{t('auth_files.type_virtual') || '虚拟认证文件'}</div>
|
||||||
<div className={styles.virtualBadge}>{t('auth_files.type_virtual') || '虚拟认证文件'}</div>
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => showModels(item)}
|
|
||||||
className={styles.iconButton}
|
|
||||||
title={t('auth_files.models_button', { defaultValue: '模型' })}
|
|
||||||
disabled={disableControls}
|
|
||||||
>
|
|
||||||
<IconBot className={styles.actionIcon} size={16} />
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -178,6 +178,10 @@
|
|||||||
gap: $spacing-xs;
|
gap: $spacing-xs;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: $breakpoint-mobile) {
|
@media (max-width: $breakpoint-mobile) {
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user