feat: 完成头像上传、站点主题配置与UI优化

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

View File

@@ -1,50 +1,15 @@
import { redirect } from "next/navigation";
import Link from "next/link";
import { cookies } from "next/headers";
import { ChevronRight } from "lucide-react";
import { redirect } from "next/navigation";
import { authCookieHeader } from "@/lib/cookies";
import { getMeCached } from "@/lib/serverData";
import Avatar from "@/components/Avatar";
import ProfileForm from "./ProfileForm";
import PasswordForm from "./PasswordForm";
// SSR 直出账号信息:未登录直接跳登录页,登录后 F5 不再有"正在加载…"闪动
export default async function SettingsPage() {
// /settings 已融合到用户主页 /u/[id]?tab=settings
// 未登录跳登录页,登录后跳自己的主页 settings tab
export default async function SettingsRedirect() {
const cookie = authCookieHeader(await cookies());
const me = await getMeCached(cookie || undefined);
const user = me.user;
if (!user) {
if (!me.user) {
redirect(`/login?redirect=${encodeURIComponent(`/settings`)}`);
}
return (
<div className="max-w-md mx-auto">
<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="mb-7">
<h1 className="text-[26px] sm:text-[30px] font-extrabold tracking-tight" style={{ color: "var(--ink)" }}>
账号设置
</h1>
</div>
<div className="panel p-5 mb-7 flex items-center gap-4">
<Avatar name={user.nickname || user.username} src={user.avatar || undefined} size={46} />
<div className="min-w-0">
<div className="font-bold truncate" style={{ color: "var(--ink)" }}>
{user.nickname}
</div>
<div className="meta">@{user.username} · {user.role === "admin" ? "管理员" : "普通用户"}</div>
</div>
</div>
<div className="space-y-7">
<ProfileForm user={user} />
<PasswordForm />
</div>
</div>
);
redirect(`/u/${me.user.id}?tab=settings`);
}