diff --git a/frontend/src/app/App.tsx b/frontend/src/app/App.tsx index 0aa4c3a..4d15e6f 100644 --- a/frontend/src/app/App.tsx +++ b/frontend/src/app/App.tsx @@ -1,7 +1,37 @@ import { AppShell } from './layout/AppShell' import { Router } from './router' +import { AuthProvider, useAuth } from '@/features/auth/AuthProvider' +import { LoginPage } from '@/features/auth/LoginPage' +import { Skeleton } from '@/components/ui/skeleton' export function App() { + return ( + + + + ) +} + +function AppContent() { + const { authenticated, loading } = useAuth() + + if (loading) { + return ( +
+
+ + + + +
+
+ ) + } + + if (!authenticated) { + return + } + return ( diff --git a/frontend/src/components/app/AppSidebar.tsx b/frontend/src/components/app/AppSidebar.tsx index 81940c8..3304a94 100644 --- a/frontend/src/components/app/AppSidebar.tsx +++ b/frontend/src/components/app/AppSidebar.tsx @@ -1,32 +1,66 @@ -import { Bot, BriefcaseBusiness, Database, Home, Library, Settings, ShieldCheck, Ticket } from 'lucide-react' +import * as React from 'react' +import { + Bot, + BriefcaseBusiness, + ClipboardList, + Database, + Home, + Library, + Menu, + ScrollText, + Settings, + ShieldCheck, + Ticket, + UserCog, + Users, + UsersRound +} from 'lucide-react' +import { useAuth } from '@/features/auth/AuthProvider' +import type { AuthMenu } from '@/features/auth/types' import { cn } from '@/lib/utils' -const navGroups = [ - { - label: '工作台', - items: [{ href: '#/', label: '运营总览', icon: Home }] - }, - { - label: '业务处理', - items: [ - { href: '#/tickets', label: '工单中心', icon: Ticket }, - { href: '#/tickets/new', label: '创建工单', icon: BriefcaseBusiness }, - { href: '#/solutions', label: '解决方案库', icon: Library } - ] - }, - { - label: '平台能力', - items: [ - { href: '#/knowledge', label: '知识库', icon: Database }, - { href: '#/agents', label: 'Agent 配置', icon: Bot }, - { href: '#/system', label: '系统治理', icon: ShieldCheck }, - { href: '#/design-system', label: '设计系统', icon: Settings } - ] - } -] +const iconMap = { + audit: ScrollText, + bot: Bot, + briefcase: BriefcaseBusiness, + database: Database, + home: Home, + library: Library, + menu: Menu, + roles: UserCog, + settings: Settings, + shield: ShieldCheck, + ticket: Ticket, + user_groups: UsersRound, + users: Users +} + +function getIcon(icon: string) { + return iconMap[icon as keyof typeof iconMap] ?? ClipboardList +} + +function useCurrentHash() { + const [hash, setHash] = React.useState(() => window.location.hash || '#/') + + React.useEffect(() => { + const handleHashChange = () => setHash(window.location.hash || '#/') + window.addEventListener('hashchange', handleHashChange) + return () => window.removeEventListener('hashchange', handleHashChange) + }, []) + + return hash +} + +function visibleChildren(menu: AuthMenu) { + return menu.children.filter((item) => item.is_visible && item.is_enabled) +} export function AppSidebar() { + const { user } = useAuth() + const currentHash = useCurrentHash() + const groups = (user?.menus ?? []).filter((menu) => menu.is_visible && menu.is_enabled) + return (