'use client'; import { useState, useEffect, useCallback } from 'react'; import { List, ChevronUp, X } from 'lucide-react'; import { cn } from '@/lib/utils'; interface MessageAnchor { id: string; index: number; preview: string; } interface ShareNavigatorProps { messages: Array<{ id: string; role: string; content: string; }>; } export function ShareNavigator({ messages }: ShareNavigatorProps) { const [isOpen, setIsOpen] = useState(false); const [showBackTop, setShowBackTop] = useState(false); const [activeIndex, setActiveIndex] = useState(null); // 提取用户消息作为目录项 const userMessages: MessageAnchor[] = messages .filter((msg) => msg.role === 'user') .map((msg, idx) => ({ id: msg.id, index: idx + 1, preview: msg.content.slice(0, 30) + (msg.content.length > 30 ? '...' : ''), })); // 监听滚动,显示/隐藏回到顶部按钮 useEffect(() => { const handleScroll = () => { setShowBackTop(window.scrollY > 500); // 更新当前可视消息 const messageElements = document.querySelectorAll('[data-msg-index]'); let currentIndex: number | null = null; messageElements.forEach((el) => { const rect = el.getBoundingClientRect(); if (rect.top <= 200 && rect.bottom > 0) { currentIndex = parseInt(el.getAttribute('data-msg-index') || '0'); } }); setActiveIndex(currentIndex); }; window.addEventListener('scroll', handleScroll); handleScroll(); // 初始化 return () => window.removeEventListener('scroll', handleScroll); }, []); // 跳转到指定消息 const scrollToMessage = useCallback((id: string, index: number) => { const element = document.getElementById(`msg-${id}`); if (element) { element.scrollIntoView({ behavior: 'smooth', block: 'start' }); // 更新 URL hash window.history.replaceState(null, '', `#msg-${index}`); } setIsOpen(false); }, []); // 回到顶部 const scrollToTop = useCallback(() => { window.scrollTo({ top: 0, behavior: 'smooth' }); window.history.replaceState(null, '', window.location.pathname); }, []); // 如果用户消息少于 2 条,不显示导航 if (userMessages.length < 2) { return null; } return ( <> {/* 浮动导航按钮组 */}
{/* 回到顶部按钮 */} {showBackTop && ( )} {/* 目录按钮 */}
{/* 目录面板 */} {isOpen && ( <> {/* 背景遮罩 */}
setIsOpen(false)} /> {/* 目录内容 */}
{/* 头部 */}
消息目录 {userMessages.length} 条问题
{/* 目录列表 */}
{userMessages.map((msg) => ( ))}
)} ); }