2
0

Header.tsx 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /**
  2. * 页面头部组件
  3. *
  4. * 核心概念:
  5. * - Web UI 是 MCP 测试工具,不需要全局登录
  6. * - 显示已连接的 MCP 服务器数量
  7. */
  8. 'use client';
  9. import { useState, useEffect } from 'react';
  10. import Link from 'next/link';
  11. import { mcpTokenManager } from '@/lib/mcp-token-manager';
  12. export default function Header() {
  13. const [loggedInCount, setLoggedInCount] = useState(0);
  14. const [enabledCount, setEnabledCount] = useState(0);
  15. const [total, setTotal] = useState(0);
  16. useEffect(() => {
  17. // 更新 MCP 登录状态
  18. const updateStatus = () => {
  19. const servers = Object.keys(mcpTokenManager as any).filter(k => k.startsWith('novel-'));
  20. setLoggedInCount(mcpTokenManager.getLoggedInMcpList().length);
  21. setEnabledCount(mcpTokenManager.getEnabledMcpList().length);
  22. setTotal(servers.length || 3);
  23. };
  24. updateStatus();
  25. // 监听 storage 变化
  26. const handleStorageChange = () => updateStatus();
  27. window.addEventListener('storage', handleStorageChange);
  28. return () => window.removeEventListener('storage', handleStorageChange);
  29. }, []);
  30. return (
  31. <header className="bg-white dark:bg-gray-800 border-b dark:border-gray-700 px-6 py-4">
  32. <div className="flex items-center justify-between">
  33. <div className="flex items-center space-x-4">
  34. <h1 className="text-xl font-bold text-gray-800 dark:text-white">
  35. AI MCP Web UI
  36. </h1>
  37. <nav className="flex space-x-4">
  38. <Link href="/" className="text-gray-600 dark:text-gray-300 hover:text-blue-500">
  39. 聊天
  40. </Link>
  41. <Link href="/mcp" className="text-gray-600 dark:text-gray-300 hover:text-blue-500">
  42. MCP 管理
  43. </Link>
  44. </nav>
  45. </div>
  46. <div className="flex items-center space-x-4">
  47. {/* MCP 连接状态 */}
  48. <div className="flex items-center space-x-2 text-sm">
  49. <span className="text-gray-600 dark:text-gray-400">MCP:</span>
  50. <span className={`px-2 py-1 rounded ${
  51. enabledCount > 0
  52. ? 'bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200'
  53. : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400'
  54. }`}>
  55. 已启用 {enabledCount}/{total}
  56. </span>
  57. {loggedInCount > 0 && (
  58. <span className={`px-2 py-1 rounded ${
  59. loggedInCount > 0
  60. ? 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200'
  61. : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400'
  62. }`}>
  63. 已登录 {loggedInCount}/{total}
  64. </span>
  65. )}
  66. </div>
  67. {loggedInCount > 0 ? (
  68. <Link
  69. href="/mcp"
  70. className="text-sm text-blue-500 hover:text-blue-600"
  71. >
  72. 管理连接
  73. </Link>
  74. ) : (
  75. <Link
  76. href="/mcp"
  77. className="px-4 py-2 text-sm bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
  78. >
  79. 连接 MCP
  80. </Link>
  81. )}
  82. </div>
  83. </div>
  84. </header>
  85. );
  86. }