"use client" import { useEffect, useMemo, useState } from "react" import Link from "next/link" import { Mail, MailOpen, Plus, Send, Inbox, Search, Loader2 } from "lucide-react" import { useTranslations } from "next-intl" import { Badge } from "@/shared/components/ui/badge" import { Button } from "@/shared/components/ui/button" import { Card, CardContent, CardHeader } from "@/shared/components/ui/card" import { EmptyState } from "@/shared/components/ui/empty-state" import { Input } from "@/shared/components/ui/input" import { Tabs, TabsList, TabsTrigger } from "@/shared/components/ui/tabs" import { cn, formatDate } from "@/shared/lib/utils" import { usePermission } from "@/shared/hooks/use-permission" import { Permissions } from "@/shared/types/permissions" import { getMessagesAction } from "../actions" import type { Message, MessageType } from "../types" type Tab = "inbox" | "sent" export function MessageList({ messages, currentUserId, initialType = "inbox", }: { messages: Message[] currentUserId: string initialType?: MessageType }) { const t = useTranslations("messages") const [tab, setTab] = useState(initialType === "sent" ? "sent" : "inbox") const [keyword, setKeyword] = useState("") const [searchResults, setSearchResults] = useState<{ kw: string; tab: Tab; items: Message[] } | null>(null) const { hasPermission } = usePermission() const canSend = hasPermission(Permissions.MESSAGE_SEND) // 防抖搜索:keyword 或 tab 变化时调用 getMessagesAction useEffect(() => { const kw = keyword.trim() if (kw.length === 0) { return } let cancelled = false const timer = setTimeout(async () => { if (cancelled) return const res = await getMessagesAction({ type: tab, keyword: kw }) if (cancelled) return if (res.success && res.data) { setSearchResults({ kw, tab, items: res.data.items }) } }, 400) return () => { cancelled = true clearTimeout(timer) } }, [keyword, tab]) // 当前搜索结果是否匹配最新的 keyword 和 tab const currentResults = searchResults && searchResults.kw === keyword.trim() && searchResults.tab === tab ? searchResults.items : null // 搜索中:keyword 非空且尚无匹配结果 const searching = keyword.trim().length > 0 && currentResults === null // 当 keyword 为空时使用 prop messages,否则使用搜索结果 const displayMessages = currentResults ?? messages const filtered = useMemo(() => { if (tab === "inbox") return displayMessages.filter((m) => m.receiverId === currentUserId) return displayMessages.filter((m) => m.senderId === currentUserId) }, [displayMessages, tab, currentUserId]) return (
setTab(v as Tab)}> {t("tabs.inbox")} {t("tabs.sent")} {canSend ? ( ) : null}
{/* 搜索框 */}
{filtered.length === 0 ? ( ) : (
{filtered.map((m) => { const isReceived = m.receiverId === currentUserId const counterpart = isReceived ? m.senderName : m.receiverName const unread = isReceived && !m.isRead return (
{unread ? (

{isReceived ? t("meta.from") : t("meta.to")}: {counterpart ?? t("meta.unknown")}

{formatDate(m.createdAt)}

{m.content}

) })}
)}
) }