您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

next-header.tsx 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
  2. import { Button } from '@/components/ui/button';
  3. import { Container } from '@/components/ui/container';
  4. import { Segmented, SegmentedValue } from '@/components/ui/segmented';
  5. import { useTranslate } from '@/hooks/common-hooks';
  6. import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
  7. import { useNavigateWithFromState } from '@/hooks/route-hook';
  8. import { cn } from '@/lib/utils';
  9. import { Routes } from '@/routes';
  10. import {
  11. ChevronDown,
  12. Cpu,
  13. File,
  14. Github,
  15. House,
  16. Library,
  17. MessageSquareText,
  18. Search,
  19. Star,
  20. Zap,
  21. } from 'lucide-react';
  22. import { useCallback, useMemo } from 'react';
  23. import { useLocation } from 'umi';
  24. export function Header() {
  25. const { t } = useTranslate('header');
  26. const { pathname } = useLocation();
  27. const navigate = useNavigateWithFromState();
  28. const { navigateToHome, navigateToProfile } = useNavigatePage();
  29. const tagsData = useMemo(
  30. () => [
  31. { path: Routes.Datasets, name: t('knowledgeBase'), icon: Library },
  32. { path: Routes.Chats, name: t('chat'), icon: MessageSquareText },
  33. { path: Routes.Search, name: t('search'), icon: Search },
  34. { path: Routes.Agent, name: t('flow'), icon: Cpu },
  35. { path: Routes.Files, name: t('fileManager'), icon: File },
  36. ],
  37. [t],
  38. );
  39. const options = useMemo(() => {
  40. return tagsData.map((tag) => {
  41. const HeaderIcon = tag.icon;
  42. return {
  43. label: (
  44. <div className="flex items-center gap-1">
  45. <HeaderIcon className="size-5"></HeaderIcon>
  46. <span>{tag.name}</span>
  47. </div>
  48. ),
  49. value: tag.path,
  50. };
  51. });
  52. }, [tagsData]);
  53. const currentPath = useMemo(() => {
  54. return (
  55. tagsData.find((x) => pathname.startsWith(x.path))?.path || Routes.Home
  56. );
  57. }, [pathname, tagsData]);
  58. const isHome = Routes.Home === currentPath;
  59. const handleChange = (path: SegmentedValue) => {
  60. navigate(path as Routes);
  61. };
  62. const handleLogoClick = useCallback(() => {
  63. navigate(Routes.Home);
  64. }, [navigate]);
  65. return (
  66. <section className="py-6 px-10 flex justify-between items-center border-b">
  67. <div className="flex items-center gap-4">
  68. <img
  69. src={'/logo.svg'}
  70. alt="logo"
  71. className="w-[100] h-[100] mr-[12]"
  72. onClick={handleLogoClick}
  73. />
  74. <Button
  75. variant="secondary"
  76. className="bg-colors-background-inverse-standard"
  77. >
  78. <Github />
  79. 21.5k stars
  80. <Star />
  81. </Button>
  82. </div>
  83. <div className="flex gap-2 items-center">
  84. <Button
  85. variant={'icon'}
  86. size={'icon'}
  87. onClick={navigateToHome}
  88. className={cn({
  89. 'bg-colors-background-inverse-strong': isHome,
  90. })}
  91. >
  92. <House
  93. className={cn({
  94. 'text-colors-text-inverse-strong': isHome,
  95. })}
  96. />
  97. </Button>
  98. <div className="h-8 w-[1px] bg-colors-outline-neutral-strong"></div>
  99. <Segmented
  100. options={options}
  101. value={currentPath}
  102. onChange={handleChange}
  103. className="bg-colors-background-inverse-standard text-backgroundInverseStandard-foreground"
  104. ></Segmented>
  105. </div>
  106. <div className="flex items-center gap-4">
  107. <Container className="bg-colors-background-inverse-standard hidden xl:flex">
  108. V 0.13.0
  109. <Button variant="secondary" className="size-8">
  110. <ChevronDown />
  111. </Button>
  112. </Container>
  113. <Container className="px-3 py-2 bg-colors-background-inverse-standard">
  114. <Avatar
  115. className="w-[30px] h-[30px] cursor-pointer"
  116. onClick={navigateToProfile}
  117. >
  118. <AvatarImage src="https://github.com/shadcn.png" />
  119. <AvatarFallback>CN</AvatarFallback>
  120. </Avatar>
  121. <span className="max-w-14 truncate"> yifanwu92@gmail.com</span>
  122. <Button
  123. variant="destructive"
  124. className="py-[2px] px-[8px] h-[23px] rounded-[4px]"
  125. >
  126. <Zap />
  127. Pro
  128. </Button>
  129. </Container>
  130. </div>
  131. </section>
  132. );
  133. }