AppShell.tsx 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import Link from "next/link";
  2. import { ArrowLeft, RefreshCw } from "lucide-react";
  3. export function AppShell({
  4. children,
  5. onRefresh,
  6. showBack,
  7. onBack,
  8. backLabel = "返回",
  9. toolbarLeading,
  10. centerNav
  11. }: {
  12. children: React.ReactNode;
  13. onRefresh?: () => void;
  14. showBack?: boolean;
  15. // 提供 onBack 时,返回按钮走该回调(如浏览器历史回退),回到来时的页面;否则默认 Link 到 /runs。
  16. onBack?: () => void;
  17. backLabel?: string;
  18. toolbarLeading?: React.ReactNode;
  19. centerNav?: React.ReactNode;
  20. }) {
  21. return (
  22. <main className="app-shell">
  23. <div className="workspace">
  24. <header className="topbar">
  25. <div className="topbar-left">
  26. {onBack ? (
  27. <button className="back-link" type="button" onClick={onBack}>
  28. <ArrowLeft size={15} />
  29. {backLabel}
  30. </button>
  31. ) : showBack ? (
  32. <Link className="back-link" href="/runs">
  33. <ArrowLeft size={15} />
  34. {backLabel}
  35. </Link>
  36. ) : null}
  37. <Link className="brand" href="/runs">
  38. <strong>ContentFindAgent</strong>
  39. </Link>
  40. </div>
  41. {centerNav ? <div className="topbar-center">{centerNav}</div> : null}
  42. <div className="toolbar">
  43. {toolbarLeading}
  44. <Link className="back-link" href="/config">
  45. 配置
  46. </Link>
  47. {onRefresh ? (
  48. <button className="icon-button" onClick={onRefresh} type="button" title="刷新">
  49. <RefreshCw size={16} />
  50. </button>
  51. ) : null}
  52. </div>
  53. </header>
  54. {children}
  55. </div>
  56. </main>
  57. );
  58. }