"use client"; import { useEffect, useState, useCallback } from "react"; import { useAuth, type AuthUser } from "@/lib/auth-context"; const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"; interface MemoryItem { id: string; memory: string; created_at?: string; updated_at?: string; } interface GroupedMemories { label: string; items: MemoryItem[]; } function groupByTime(memories: MemoryItem[]): GroupedMemories[] { const now = new Date(); const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const weekAgo = new Date(todayStart.getTime() - 7 * 24 * 60 * 60 * 1000); const today: MemoryItem[] = []; const week: MemoryItem[] = []; const older: MemoryItem[] = []; for (const m of memories) { const d = m.created_at ? new Date(m.created_at) : null; if (!d || isNaN(d.getTime())) { older.push(m); } else if (d >= todayStart) { today.push(m); } else if (d >= weekAgo) { week.push(m); } else { older.push(m); } } const groups: GroupedMemories[] = []; if (today.length > 0) groups.push({ label: "今天", items: today }); if (week.length > 0) groups.push({ label: "最近 7 天", items: week }); if (older.length > 0) groups.push({ label: "更早", items: older }); return groups; } function formatDate(dateStr?: string): string { if (!dateStr) return ""; const d = new Date(dateStr); if (isNaN(d.getTime())) return ""; const now = new Date(); const isThisYear = d.getFullYear() === now.getFullYear(); const month = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); const hour = String(d.getHours()).padStart(2, "0"); const min = String(d.getMinutes()).padStart(2, "0"); if (isThisYear) return `${month}-${day} ${hour}:${min}`; return `${d.getFullYear()}-${month}-${day} ${hour}:${min}`; } export function ProfileModal({ onClose }: { onClose: () => void }) { const { user, token } = useAuth(); const [memories, setMemories] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchMemories = useCallback(async () => { if (!token) return; setLoading(true); setError(null); try { const resp = await fetch(`${API_URL}/api/memory/list`, { headers: { Authorization: `Bearer ${token}` }, }); if (!resp.ok) throw new Error(`HTTP ${resp.status}`); const data = await resp.json(); setMemories(data.memories || []); if (data.error) setError(data.error); } catch (e) { setError(e instanceof Error ? e.message : "加载记忆失败"); } finally { setLoading(false); } }, [token]); useEffect(() => { fetchMemories(); }, [fetchMemories]); useEffect(() => { function handleKey(e: KeyboardEvent) { if (e.key === "Escape") onClose(); } document.addEventListener("keydown", handleKey); return () => document.removeEventListener("keydown", handleKey); }, [onClose]); if (!user) return null; const groups = groupByTime(memories); return (
{/* 遮罩层 */}
{/* 弹窗主体 */}
e.stopPropagation()} > {/* 关闭按钮 */} {/* 用户信息区 */}
{(user.display_name || user.username).charAt(0).toUpperCase()}

{user.display_name || user.username}

@{user.username} {user.is_admin && ( 管理员 )}
{/* 分割线 */}
{/* 记忆区标题 */}
记忆系统 {!loading && ( {memories.length} 条记录 )}
{/* 记忆列表 */}
{loading && (
加载中...
)} {!loading && error && memories.length === 0 && (

{error}

)} {!loading && !error && memories.length === 0 && (

暂无记忆记录

与助手对话时,系统会自动记录关键信息

)} {!loading && groups.map((group) => (
{group.label}
{group.items.map((item) => (

{item.memory}

{item.created_at && (

{formatDate(item.created_at)}

)}
))}
))}
); }