import Link from "next/link"; import { Flame, Users, MessageCircle, Heart, UserPlus, Link2, Megaphone, BarChart3, PenLine, Activity, TrendingUp, Info, Pin, ChevronRight, } from "lucide-react"; import type { PostListItem, ActiveUser, OverviewStats, AnnouncementSummary, NewUser, CheckinStatus, SidebarPageItem, } from "@/lib/api"; import Avatar from "@/components/Avatar"; import { PulseCheckin } from "./CheckinCard"; import { FRIEND_LINKS } from "@/lib/friendLinks"; import { formatCompact, formatShortDate } from "@/lib/format"; import { pageGlyph } from "@/lib/pageGlyph"; /* ---------- 站点数据(2×2 bento 统计瓦片) ---------- */ function PulseCard({ stats, checkin, allowComments, }: { stats: OverviewStats; checkin?: CheckinStatus | null; allowComments: boolean; }) { const cells = [ { icon: , label: "注册用户", value: formatCompact(stats.users), foot: `+${formatCompact(stats.today_users)} 今日`, up: true, }, { icon: , label: "话题总数", value: formatCompact(stats.posts), foot: `+${formatCompact(stats.today_posts)} 今日`, up: true, }, ...(allowComments ? [ { icon: , label: "回复总数", value: formatCompact(stats.comments), foot: `+${formatCompact(stats.today_comments)} 今日`, up: true, }, ] : [ { icon: , label: "今日新帖", value: formatCompact(stats.today_posts), foot: "本日新增", up: stats.today_posts > 0, }, ]), { icon: , label: "在线用户", value: formatCompact(stats.online), foot: `峰值 ${formatCompact(stats.peak_online)}`, up: false, }, ]; return (

站点数据

{cells.map((c) => (

{c.label}

{c.value}

{c.up &&

))}
); } /* ---------- 关于本站(侧栏页目录,置于右栏最底) ---------- */ function AboutSite({ pages, siteDescription, }: { pages: SidebarPageItem[]; siteDescription?: string; }) { if (pages.length === 0) return null; const lead = siteDescription?.trim() ?? ""; return (

关于本站

{lead ?

{lead}

: null}
    {pages.map((p) => { const Icon = pageGlyph(p.slug); return (
  • {p.title} {p.excerpt ? {p.excerpt} : null}
  • ); })}
); } /* ---------- 站点公告 ---------- */ function Announcements({ items, canManageAnnouncements, }: { items: AnnouncementSummary[]; canManageAnnouncements?: boolean; }) { return (

站点公告

全部 {canManageAnnouncements ? ( 管理 ) : null}
{items.length === 0 ? (

暂无公告

) : (
    {items.map((a) => (
  • {a.pinned ? ( ) : null} {a.title} {a.tag ? ( {a.tag} ) : null} {formatShortDate(a.created_at)}
  • ))}
)}
); } /* ---------- 热门榜 ---------- */ function HotRanking({ posts, allowComments }: { posts: PostListItem[]; allowComments: boolean }) { return (

热门讨论

{posts.length === 0 ? (

还没有热门讨论

) : (
    {posts.map((p, i) => (
  1. {i + 1} {p.title} {allowComments ? ( {p.comment_count} ) : null} {p.like_count}
  2. ))}
)}
); } /* ---------- 最新注册 ---------- */ function NewUsers({ users }: { users: NewUser[] }) { if (users.length === 0) return null; return (

最新注册

    {users.map((u) => { const name = u.nickname || u.username; return (
  • {name}
  • ); })}
); } /* ---------- 活跃成员(本周发帖 / 回复) ---------- */ function ActiveUsers({ users, allowComments }: { users: ActiveUser[]; allowComments: boolean }) { return (

活跃成员 本周

{users.length === 0 ? (

本周还没有人互动

) : (
    {users.map((u) => { const name = u.nickname || u.username; return (
  • {name} 发帖 {u.post_count} {allowComments ? ( 回复 {u.comment_count} ) : null} {allowComments ? u.post_count + u.comment_count : u.post_count}
  • ); })}
)}
); } /* ---------- 友情链接 ---------- */ function FriendLinks() { return (

友情链接 申请

{FRIEND_LINKS.map((l) => l.href.startsWith("http") ? ( {l.name} ) : ( {l.name} ) )}
); } /* ---------- 桌面 / 移动两种装配 ---------- */ type PanelsProps = { stats: OverviewStats; hot: PostListItem[]; activeUsers: ActiveUser[]; announcements: AnnouncementSummary[]; newUsers: NewUser[]; checkin?: CheckinStatus | null; allowComments: boolean; canManageAnnouncements?: boolean; sidebarPages?: SidebarPageItem[]; siteDescription?: string; }; function CommunityPanelsBody({ stats, hot, activeUsers, announcements, newUsers, checkin, allowComments, canManageAnnouncements, sidebarPages = [], siteDescription, }: PanelsProps) { return ( <> ); } export function CommunityPanels(props: PanelsProps) { return ( ); } export function CommunityPanelsMobile(props: PanelsProps) { return (
); }