From 5491dcaa5bb29e45de4edef5aed2191aefe3822c Mon Sep 17 00:00:00 2001 From: 537yaha <2930134478@qq.com> Date: Thu, 21 May 2026 16:37:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/chat/page.tsx | 18 ++++++------- frontend/components/layout/Footer.tsx | 25 +++++++++++++++---- .../components/marketing/HomePageClient.tsx | 22 ++++++++++------ frontend/lib/visitor-id.ts | 16 ++++++++++++ 4 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 frontend/lib/visitor-id.ts diff --git a/frontend/app/chat/page.tsx b/frontend/app/chat/page.tsx index 8ec74c9..fb25834 100644 --- a/frontend/app/chat/page.tsx +++ b/frontend/app/chat/page.tsx @@ -4,10 +4,11 @@ import { useEffect, useState, useSyncExternalStore } from "react"; import { ChatWidget } from "@/components/visitor/ChatWidget"; import { FloatingButton } from "@/components/visitor/FloatingButton"; import { isChatEmbedMode } from "@/lib/chat-embed"; +import { getOrCreateVisitorId } from "@/lib/visitor-id"; /** * 访客聊天页面 - * - 独立打开:右下角浮动按钮 + 聊天小窗 + * - 独立打开:默认展开聊天小窗(仍保留右下角浮动按钮) * - iframe / ?embed=1:直接铺满,供宿主站点一次点击打开 iframe 即可使用 */ export default function ChatPage() { @@ -19,17 +20,16 @@ export default function ChatPage() { () => false ); - // 初始化访客 ID(使用 localStorage 保持连续性) useEffect(() => { - let stored = window.localStorage.getItem("visitor_id"); - if (!stored) { - stored = `${Date.now()}${Math.floor(Math.random() * 100000)}`; - window.localStorage.setItem("visitor_id", stored); - } - const parsed = Number.parseInt(stored, 10); - setVisitorId(Number.isNaN(parsed) ? null : parsed); + setVisitorId(getOrCreateVisitorId()); }, []); + useEffect(() => { + if (!embedded && visitorId !== null) { + setIsOpen(true); + } + }, [embedded, visitorId]); + const handleToggle = () => { setIsOpen((prev) => !prev); }; diff --git a/frontend/components/layout/Footer.tsx b/frontend/components/layout/Footer.tsx index 8845ae0..248eb6a 100644 --- a/frontend/components/layout/Footer.tsx +++ b/frontend/components/layout/Footer.tsx @@ -5,10 +5,15 @@ import { Github, Mail, MessageSquare, Users } from "lucide-react"; import { websiteConfig } from "@/lib/website-config"; import { useI18n } from "@/lib/i18n/provider"; +interface FooterProps { + /** 首页打开右下角客服小窗;不传则回退为链到首页并带 openChat 参数 */ + onOpenChat?: () => void; +} + /** * 官网底部页脚 */ -export function Footer() { +export function Footer({ onOpenChat }: FooterProps) { const { t } = useI18n(); return ( @@ -145,10 +150,20 @@ export function Footer() {
  • - - - {t("footer.onlineChat")} - + + {onOpenChat ? ( + + ) : ( + + {t("footer.onlineChat")} + + )}
  • diff --git a/frontend/components/marketing/HomePageClient.tsx b/frontend/components/marketing/HomePageClient.tsx index a870fa7..99e7f7a 100644 --- a/frontend/components/marketing/HomePageClient.tsx +++ b/frontend/components/marketing/HomePageClient.tsx @@ -28,6 +28,7 @@ import { Header } from "@/components/layout/Header"; import { Footer } from "@/components/layout/Footer"; import { FadeIn, FadeInStagger, FadeInItem } from "@/components/ui/fade-in"; import { websiteConfig } from "@/lib/website-config"; +import { getOrCreateVisitorId } from "@/lib/visitor-id"; import { stats } from "@/lib/stats-config"; import type { I18nKey } from "@/lib/i18n/dict"; import { useI18n } from "@/lib/i18n/provider"; @@ -149,15 +150,20 @@ export function HomePageClient() { const [activeScreenshot, setActiveScreenshot] = useState(0); useEffect(() => { - let stored = window.localStorage.getItem("visitor_id"); - if (!stored) { - stored = `${Date.now()}${Math.floor(Math.random() * 100000)}`; - window.localStorage.setItem("visitor_id", stored); - } - const parsed = Number.parseInt(stored, 10); - setVisitorId(Number.isNaN(parsed) ? null : parsed); + setVisitorId(getOrCreateVisitorId()); }, []); + useEffect(() => { + const params = new URLSearchParams(window.location.search); + if (params.get("openChat") === "1") { + handleOpenChat(); + params.delete("openChat"); + const next = `${window.location.pathname}${params.toString() ? `?${params}` : ""}`; + window.history.replaceState(null, "", next); + } + // eslint-disable-next-line react-hooks/exhaustive-deps -- 仅响应 URL 参数 + }, [visitorId]); + const handleToggleChat = () => setIsChatOpen((prev) => !prev); const handleOpenChat = () => { @@ -469,7 +475,7 @@ export function HomePageClient() { -