"use client"; import Link from "next/link"; import { useCallback, useEffect, useState } from "react"; import { CommunityPageHero } from "../components/CommunityPageHero"; import { COMMUNITY_CHANGED_EVENT } from "../components/communityEvents"; import styles from "../components/memos.module.css"; type AttachmentItem = { id: string; url: string; original_name: string; created: string; size: number; }; function getStorage(key: string): string | null { if (typeof window === "undefined") { return null; } return localStorage.getItem(key); } function formatFileSize(size: number) { if (size < 1024) { return `${size} B`; } if (size < 1024 * 1024) { return `${(size / 1024).toFixed(1)} KB`; } return `${(size / 1024 / 1024).toFixed(1)} MB`; } export default function AttachmentsPage() { const [userId, setUserId] = useState(null); const [isVip, setIsVip] = useState(false); const [showLoginPrompt, setShowLoginPrompt] = useState(false); const [items, setItems] = useState([]); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const [loading, setLoading] = useState(false); useEffect(() => { const uid = getStorage("userId") || getStorage("memosAccount"); const type = getStorage("paidType"); setUserId(uid || null); setIsVip(type === "vip"); }, []); const fetchAttachments = useCallback( async (pageNum: number, append: boolean) => { if (!userId || !isVip) { return; } setLoading(true); try { const response = await fetch( `/api/community/attachments?user_id=${encodeURIComponent(userId)}&page=${pageNum}&per_page=24`, { cache: "no-store" } ); const data = await response.json().catch(() => null); if (response.status === 403) { setShowLoginPrompt(true); return; } if (!response.ok) { return; } const nextItems = Array.isArray(data?.items) ? (data.items as AttachmentItem[]) : []; setItems((current) => (append ? [...current, ...nextItems] : nextItems)); setHasMore(Boolean(data?.next_page_token)); setPage(pageNum); } finally { setLoading(false); } }, [isVip, userId] ); useEffect(() => { void fetchAttachments(1, false); }, [fetchAttachments]); useEffect(() => { const handler = () => { void fetchAttachments(1, false); }; window.addEventListener(COMMUNITY_CHANGED_EVENT, handler); return () => window.removeEventListener(COMMUNITY_CHANGED_EVENT, handler); }, [fetchAttachments]); return (
{showLoginPrompt ? (

附件资料库仅对会员开放。

立即加入会员
) : null} {isVip && userId ? ( items.length ? ( <>
{items.map((item) => ( {item.original_name}
{item.original_name} {formatFileSize(item.size)} · {new Date(item.created).toLocaleDateString("zh-CN")}
))}
{hasMore ? ( ) : null} ) : (
Attachment Library

还没有附件

在首页动态中上传图片后,这里会自动生成资料缩略图墙。

) ) : (
Members Only

附件资料库需要会员权限

加入后即可查看所有上传图片与资料沉淀。

去开通会员
)}
); }