layout.tsx 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import type { Metadata } from "next";
  2. import { Geist, Geist_Mono } from "next/font/google";
  3. import "./globals.css";
  4. import MatomoTracker from "@/components/MatomoTracker";
  5. import { Toaster } from "@/components/ui/toaster";
  6. const geistSans = Geist({
  7. variable: "--font-geist-sans",
  8. subsets: ["latin"],
  9. });
  10. const geistMono = Geist_Mono({
  11. variable: "--font-geist-mono",
  12. subsets: ["latin"],
  13. });
  14. export const metadata: Metadata = {
  15. title: "AI-CS 智能客服系统",
  16. description: "融合 AI 技术与人工客服,为企业提供高效、智能的客户服务解决方案",
  17. };
  18. // Matomo 容器 URL(格式:container_*.js)
  19. const MATOMO_CONTAINER_URL = process.env.NEXT_PUBLIC_MATOMO_CONTAINER_URL || '';
  20. // 后端端口配置(用于 widget.js)
  21. const BACKEND_PORT = process.env.NEXT_PUBLIC_BACKEND_PORT || '18080';
  22. export default function RootLayout({
  23. children,
  24. }: Readonly<{
  25. children: React.ReactNode;
  26. }>) {
  27. return (
  28. <html lang="en">
  29. <head>
  30. <script
  31. dangerouslySetInnerHTML={{
  32. __html: `window.AICS_BACKEND_PORT = '${BACKEND_PORT}';`,
  33. }}
  34. />
  35. </head>
  36. <body
  37. className={`${geistSans.variable} ${geistMono.variable} antialiased`}
  38. >
  39. {children}
  40. <Toaster />
  41. {MATOMO_CONTAINER_URL && <MatomoTracker containerUrl={MATOMO_CONTAINER_URL} />}
  42. </body>
  43. </html>
  44. );
  45. }