93 lines
4.2 KiB
TypeScript
93 lines
4.2 KiB
TypeScript
import * as React from 'react'
|
|
import { ChevronDown, ChevronRight, LogOut, UserRound } from 'lucide-react'
|
|
|
|
import { AppThemeToggle } from '@/components/app/AppThemeToggle'
|
|
import { Button } from '@/components/ui/button'
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuGroup,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger
|
|
} from '@/components/ui/dropdown-menu'
|
|
import { Separator } from '@/components/ui/separator'
|
|
import { SidebarTrigger } from '@/components/ui/sidebar'
|
|
import { useAuth } from '@/features/auth/AuthProvider'
|
|
|
|
const routeTitles: Array<{ pattern: RegExp; title: string }> = [
|
|
{ pattern: /^\/$/, title: '工作台' },
|
|
{ pattern: /^\/tickets$/, title: '工单中心' },
|
|
{ pattern: /^\/tickets\/new$/, title: '创建工单' },
|
|
{ pattern: /^\/tickets\/\d+$/, title: '工单详情' },
|
|
{ pattern: /^\/solutions$/, title: '解决方案库' },
|
|
{ pattern: /^\/solutions\/new/, title: '新建解决方案' },
|
|
{ pattern: /^\/knowledge$/, title: '知识库' },
|
|
{ pattern: /^\/knowledge\/search$/, title: '知识检索' },
|
|
{ pattern: /^\/knowledge\/items\/new$/, title: '新建知识条目' },
|
|
{ pattern: /^\/system\/users$/, title: '用户管理' },
|
|
{ pattern: /^\/system\/user-groups$/, title: '用户组管理' },
|
|
{ pattern: /^\/system\/roles$/, title: '角色管理' },
|
|
{ pattern: /^\/system\/menus$/, title: '菜单权限' },
|
|
{ pattern: /^\/audit$/, title: '审计日志' },
|
|
{ pattern: /^\/design-system$/, title: '设计系统' }
|
|
]
|
|
|
|
export function getCurrentPageTitle(hash: string) {
|
|
const route = hash.replace(/^#/, '') || '/'
|
|
return routeTitles.find((item) => item.pattern.test(route))?.title ?? '当前工作区'
|
|
}
|
|
|
|
export function AppTopbar() {
|
|
const { logout, user } = useAuth()
|
|
const [pageTitle, setPageTitle] = React.useState(() => getCurrentPageTitle(window.location.hash))
|
|
|
|
React.useEffect(() => {
|
|
const handleHashChange = () => setPageTitle(getCurrentPageTitle(window.location.hash))
|
|
window.addEventListener('hashchange', handleHashChange)
|
|
return () => window.removeEventListener('hashchange', handleHashChange)
|
|
}, [])
|
|
|
|
return (
|
|
<header data-slot="app-topbar" className="sticky top-0 z-20 flex h-14 items-center justify-between border-b border-border/80 bg-background/95 px-4 backdrop-blur sm:px-6 lg:px-8">
|
|
<div className="flex min-w-0 items-center gap-2 text-sm">
|
|
<SidebarTrigger className="-ml-1" aria-label="切换侧边栏" />
|
|
<Separator orientation="vertical" className="mx-1 h-4" />
|
|
<span className="hidden font-medium text-foreground sm:inline">企业服务治理中台</span>
|
|
<ChevronRight className="hidden size-4 text-muted-foreground sm:block" />
|
|
<span className="truncate text-muted-foreground">{pageTitle}</span>
|
|
</div>
|
|
<div className="flex items-center gap-1">
|
|
<AppThemeToggle />
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" className="gap-2 px-2 sm:px-3">
|
|
<span className="flex size-7 items-center justify-center rounded-md bg-muted text-foreground">
|
|
<UserRound />
|
|
</span>
|
|
<span className="hidden max-w-32 truncate sm:inline">{user?.display_name || user?.username || '当前用户'}</span>
|
|
<ChevronDown data-icon="inline-end" className="hidden text-muted-foreground sm:block" />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-56">
|
|
<DropdownMenuLabel>
|
|
<span className="grid gap-0.5">
|
|
<span className="truncate text-sm text-foreground">{user?.display_name || user?.username || '当前用户'}</span>
|
|
<span className="truncate text-xs font-normal text-muted-foreground">{user?.username || '未设置账号'}</span>
|
|
</span>
|
|
</DropdownMenuLabel>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuGroup>
|
|
<DropdownMenuItem variant="destructive" onSelect={() => void logout()}>
|
|
<LogOut data-icon="inline-start" />
|
|
退出登录
|
|
</DropdownMenuItem>
|
|
</DropdownMenuGroup>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</div>
|
|
</header>
|
|
)
|
|
}
|