Files
jiang13-bbs/frontend/app/boards/page.tsx
freefire 24c6dea38c feat: 完成头像上传、站点主题配置与UI优化
- 新增附件模型与上传服务,拆分头像上传/管理逻辑
- 重构用户资料接口,移除直接修改头像字段,改用专用上传接口
- 添加站点公开设置API与管理员外观配置页
- 全局替换hover背景为accent-soft,优化交互一致性
- 完善头像组件,支持图片加载失败回退与src更新重置
- 新增用户状态事件总线,解决同页头像更新不及时问题
- 调整依赖包顺序与CI依赖版本
- 重构板块列表接口,新增帖子计数
- 迁移账号设置到用户主页tab,合并重复代码
2026-09-15 01:06:12 +08:00

109 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Link from "next/link";
import type { Metadata } from "next";
import { ChevronRight, MessagesSquare, LayoutGrid } from "lucide-react";
import { fetchBoards } from "@/lib/api";
export const metadata: Metadata = {
title: "板块目录 · 姜十三论坛",
description: "浏览论坛全部板块,找到感兴趣的话题社区",
};
// 板块汇总列表页:首页左栏「板块目录」标题的落地页,
// 展示全部板块(介绍 + 讨论量),点击进入板块独立页
export default async function BoardsPage() {
const { boards } = await fetchBoards();
const totalPosts = boards.reduce((sum, b) => sum + (b.post_count || 0), 0);
return (
<div>
{/* 面包屑 */}
<nav className="meta mb-5 flex items-center gap-1.5 text-[13px]">
<Link href="/" className="hover:text-[var(--accent)] transition-colors">首页</Link>
<ChevronRight size={13} />
<span style={{ color: "var(--accent)" }}>板块目录</span>
</nav>
{/* 页头 */}
<div className="panel p-6 sm:p-7 mb-6 relative overflow-hidden">
<span
aria-hidden
className="absolute -top-16 -right-12 w-48 h-48 rounded-full"
style={{ background: "var(--accent-soft)" }}
/>
<div className="relative flex items-center gap-4">
<span
className="w-14 h-14 sm:w-16 sm:h-16 rounded-2xl flex items-center justify-center shrink-0"
style={{ background: "var(--accent-soft)", color: "var(--accent)" }}
>
<LayoutGrid size={28} />
</span>
<div>
<h1 className="text-2xl sm:text-[28px] font-extrabold tracking-tight" style={{ color: "var(--ink)" }}>
板块目录
</h1>
<p className="meta mt-1.5">
共 {boards.length} 个板块 · {totalPosts} 篇讨论
</p>
</div>
</div>
</div>
{/* 板块卡片网格 */}
{boards.length === 0 ? (
<div className="panel text-center py-20 px-6">
<span
className="inline-flex w-14 h-14 rounded-full items-center justify-center mb-4"
style={{ background: "var(--accent-soft)", color: "var(--accent)" }}
>
<MessagesSquare size={26} />
</span>
<p className="font-bold text-lg" style={{ color: "var(--ink)" }}>还没有任何板块</p>
<p className="meta mt-1.5">板块由管理员创建,敬请期待</p>
</div>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{boards.map((b, i) => (
<Link
key={b.id}
href={`/board/${b.id}`}
className="j13-module group flex items-start gap-3.5 transition-[border-color,background] duration-150 hover:border-[var(--nav-active-line)] hover:bg-[var(--accent-soft)] focus-visible:bg-[var(--accent-soft)]"
aria-label={`${b.name}板块,${b.post_count} 篇讨论`}
>
<span className={`av-${i % 8} j13-bcard-ico !w-11 !h-11 !text-lg`} aria-hidden="true">
{b.name.slice(0, 1)}
</span>
<span className="min-w-0 flex-1">
<span className="flex items-center justify-between gap-2">
<span className="truncate text-[15px] font-extrabold" style={{ color: "var(--ink)" }}>
{b.name}
</span>
<span className="meta shrink-0 text-[11.5px] tabular-nums">{b.post_count} 篇</span>
</span>
{b.description?.trim() && (
<span
className="block mt-1 text-[12.5px] leading-relaxed line-clamp-2"
style={{ color: "var(--ink-3)" }}
>
{b.description.trim()}
</span>
)}
<span
className="mt-2.5 inline-flex items-center gap-0.5 text-[12px] font-bold transition-colors group-hover:text-[var(--accent)]"
style={{ color: "var(--ink-2)" }}
>
进入板块
<ChevronRight
size={12}
className="transition-transform group-hover:translate-x-0.5"
aria-hidden="true"
/>
</span>
</span>
</Link>
))}
</div>
)}
</div>
);
}