import Link from "next/link";
import {
Flame,
Users,
MessageCircle,
Heart,
UserPlus,
Link2,
Megaphone,
BarChart3,
PenLine,
Activity,
TrendingUp,
Pin,
ChevronRight,
CircleDollarSign,
Handshake,
} from "lucide-react";
import type {
PostListItem,
ActiveUser,
OverviewStats,
AnnouncementSummary,
NewUser,
CheckinStatus,
SidebarPageItem,
PublicAdItem,
PublicSponsorItem,
} from "@/lib/api";
import Avatar from "@/components/Avatar";
import { AdText } from "@/components/AdText";
import { PulseCheckin } from "./CheckinCard";
import { FRIEND_LINKS } from "@/lib/friendLinks";
import { formatCompact, formatShortDate } from "@/lib/format";
import { pageGlyph } from "@/lib/pageGlyph";
import { AboutSiteHeader } from "@/components/site-doc";
import { AD_IMAGE_HEIGHT, AD_IMAGE_SIZE_LABEL, AD_IMAGE_WIDTH } from "@/lib/ads";
/* ---------- 站点数据(2×2 bento 统计瓦片) ---------- */
export 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.icon}
{c.label}
{c.value}
{c.up && }
{c.foot}
))}
);
}
/* ---------- 关于本站(侧栏页目录,置于右栏最底) ---------- */
export function AboutSite({
pages,
siteDescription,
canManagePages,
}: {
pages: SidebarPageItem[];
siteDescription?: string;
canManagePages?: boolean;
}) {
if (pages.length === 0 && !canManagePages) return null;
const lead = siteDescription?.trim() ?? "";
return (
{lead ? {lead}
: null}
{pages.length === 0 ? (
暂无介绍
) : (
{pages.map((p) => {
const Icon = pageGlyph(p.slug);
return (
-
{p.title}
{p.excerpt ? {p.excerpt} : null}
);
})}
)}
);
}
/* ---------- 站点公告 ---------- */
export 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)}
))}
)}
);
}
/* ---------- 热门榜 ---------- */
export function HotRanking({ posts, allowComments }: { posts: PostListItem[]; allowComments: boolean }) {
return (
热门讨论
{posts.length === 0 ? (
还没有热门讨论
) : (
{posts.map((p, i) => (
-
{i + 1}
{p.title}
{allowComments ? (
{p.comment_count}
) : null}
{p.like_count}
))}
)}
);
}
/* ---------- 最新注册 ---------- */
export function NewUsers({ users }: { users: NewUser[] }) {
if (users.length === 0) return null;
return (
最新注册
{users.map((u) => {
const name = u.nickname || u.username;
return (
-
{name}
);
})}
);
}
/* ---------- 活跃成员(本周发帖 / 回复) ---------- */
export 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}
);
})}
)}
);
}
/* ---------- 友情链接 ---------- */
export function FriendLinks() {
if (FRIEND_LINKS.length === 0) return null;
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;
canManagePages?: boolean;
sidebarPages?: SidebarPageItem[];
siteDescription?: string;
ads?: PublicAdItem[];
adsPanelTitle?: string;
adsEnabled?: boolean;
sponsors?: PublicSponsorItem[];
sponsorsPanelTitle?: string;
sponsorsEnabled?: boolean;
};
export function AdsPanel({
items,
title,
enabled,
}: {
items: PublicAdItem[];
title: string;
enabled: boolean;
}) {
if (!enabled) return null;
const IMAGE_SLOTS = 5;
const TEXT_SLOTS = 6;
const images = items.filter((a) => a.kind === "image").slice(0, IMAGE_SLOTS);
const texts = items.filter((a) => a.kind === "text").slice(0, TEXT_SLOTS);
const imageSlots = Array.from({ length: IMAGE_SLOTS }, (_, i) => images[i] ?? null);
const textSlots = Array.from({ length: TEXT_SLOTS }, (_, i) => texts[i] ?? null);
return (
{title || "自助推广"}
购买广告位
{textSlots.map((ad, i) =>
ad ? (
-
) : (
-
文字广告位
)
)}
);
}
export function SponsorsPanel({
items,
title,
enabled,
}: {
items: PublicSponsorItem[];
title: string;
enabled: boolean;
}) {
if (!enabled || items.length === 0) return null;
return (
{title || "赞助商"}
{items.map((sp) => {
const tip = (sp.hover_text || sp.name || "").trim();
const href = sp.link_url?.trim() || undefined;
const inner = (
// eslint-disable-next-line @next/next/no-img-element
);
return (
-
{href ? (
{inner}
) : (
{inner}
)}
);
})}
);
}
function CommunityPanelsBody({
stats,
hot,
activeUsers,
announcements,
newUsers,
checkin,
allowComments,
canManageAnnouncements,
canManagePages,
sidebarPages = [],
siteDescription,
ads = [],
adsPanelTitle = "自助推广",
adsEnabled = true,
sponsors = [],
sponsorsPanelTitle = "赞助商",
sponsorsEnabled = true,
}: PanelsProps) {
return (
<>
>
);
}
export function CommunityPanels(props: PanelsProps) {
return (
);
}
export function CommunityPanelsMobile(props: PanelsProps) {
return (
);
}