feat: 同步上游更新 - 可视化配置编辑器与导航重构
- feat(config): 添加可视化配置编辑器和 YAML 处理 - feat(i18n): 可视化配置编辑器国际化支持 - feat(logs): 优化日志加载,支持自动预加载 - feat(ui): API 使用统计显示成功/失败状态 - feat(ui): Payload 规则编辑器空状态显示 - refactor(nav): Config Panel 导航重构,移除 Settings/API Keys 页面 - fix(ui): Config Panel 操作栏居中,ProviderNav 移至底部 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,12 +19,10 @@ import {
|
||||
IconChartLine,
|
||||
IconFileText,
|
||||
IconInfo,
|
||||
IconKey,
|
||||
IconLayoutDashboard,
|
||||
IconScrollText,
|
||||
IconSettings,
|
||||
IconShield,
|
||||
IconSlidersHorizontal,
|
||||
IconTimer,
|
||||
IconActivity,
|
||||
} from '@/components/ui/icons';
|
||||
@@ -41,8 +39,6 @@ import { triggerHeaderRefresh } from '@/hooks/useHeaderRefresh';
|
||||
|
||||
const sidebarIcons: Record<string, ReactNode> = {
|
||||
dashboard: <IconLayoutDashboard size={18} />,
|
||||
settings: <IconSlidersHorizontal size={18} />,
|
||||
apiKeys: <IconKey size={18} />,
|
||||
aiProviders: <IconBot size={18} />,
|
||||
authFiles: <IconFileText size={18} />,
|
||||
oauth: <IconShield size={18} />,
|
||||
@@ -247,6 +243,37 @@ export function MainLayout() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 将主内容区的中心点写入 CSS 变量,供底部浮层(如配置面板操作栏)对齐到内容区而非整窗
|
||||
useLayoutEffect(() => {
|
||||
const updateContentCenter = () => {
|
||||
const el = contentRef.current;
|
||||
if (!el) return;
|
||||
const rect = el.getBoundingClientRect();
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
document.documentElement.style.setProperty('--content-center-x', `${centerX}px`);
|
||||
};
|
||||
|
||||
updateContentCenter();
|
||||
|
||||
const resizeObserver =
|
||||
typeof ResizeObserver !== 'undefined' && contentRef.current
|
||||
? new ResizeObserver(updateContentCenter)
|
||||
: null;
|
||||
|
||||
if (resizeObserver && contentRef.current) {
|
||||
resizeObserver.observe(contentRef.current);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', updateContentCenter);
|
||||
|
||||
return () => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect();
|
||||
}
|
||||
window.removeEventListener('resize', updateContentCenter);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 5秒后自动收起品牌名称
|
||||
useEffect(() => {
|
||||
brandCollapseTimer.current = setTimeout(() => {
|
||||
@@ -359,14 +386,12 @@ export function MainLayout() {
|
||||
|
||||
const navItems = [
|
||||
{ path: '/', label: t('nav.dashboard'), icon: sidebarIcons.dashboard },
|
||||
{ path: '/settings', label: t('nav.basic_settings'), icon: sidebarIcons.settings },
|
||||
{ path: '/api-keys', label: t('nav.api_keys'), icon: sidebarIcons.apiKeys },
|
||||
{ path: '/config', label: t('nav.config_management'), icon: sidebarIcons.config },
|
||||
{ path: '/ai-providers', label: t('nav.ai_providers'), icon: sidebarIcons.aiProviders },
|
||||
{ path: '/auth-files', label: t('nav.auth_files'), icon: sidebarIcons.authFiles },
|
||||
{ path: '/oauth', label: t('nav.oauth', { defaultValue: 'OAuth' }), icon: sidebarIcons.oauth },
|
||||
{ path: '/quota', label: t('nav.quota_management'), icon: sidebarIcons.quota },
|
||||
{ path: '/usage', label: t('nav.usage_stats'), icon: sidebarIcons.usage },
|
||||
{ path: '/config', label: t('nav.config_management'), icon: sidebarIcons.config },
|
||||
...(config?.loggingToFile
|
||||
? [{ path: '/logs', label: t('nav.logs'), icon: sidebarIcons.logs }]
|
||||
: []),
|
||||
|
||||
Reference in New Issue
Block a user