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

@@ -147,7 +147,7 @@ function AuthorRailCard({ profile }: { profile: UserProfile }) {
</p>
<div className="flex items-center gap-3">
<Link href={`/u/${u.id}`} className="shrink-0" aria-label={u.nickname}>
<Avatar name={u.nickname || u.username} size={48} />
<Avatar name={u.nickname || u.username} src={u.avatar || undefined} size={48} />
</Link>
<div className="min-w-0">
<Link
@@ -198,7 +198,7 @@ function AuthorPosts({ posts }: { posts: PostListItem[] }) {
<Link
href={`/post/${p.id}`}
title={p.title}
className="block rounded-[10px] px-2 py-2 transition-colors hover:bg-[var(--panel-2)]"
className="block rounded-[10px] px-2 py-2 transition-colors hover:bg-[var(--accent-soft)] focus-visible:bg-[var(--accent-soft)]"
>
<span
className="block text-[13px] font-semibold leading-snug line-clamp-2"
@@ -284,7 +284,7 @@ function AuthorCardStacked({ profile }: { profile: UserProfile }) {
</p>
<div className="flex items-center gap-4 flex-wrap">
<Link href={`/u/${profile.user.id}`} className="shrink-0" aria-label={profile.user.nickname}>
<Avatar name={profile.user.nickname || profile.user.username} size={52} />
<Avatar name={profile.user.nickname || profile.user.username} src={profile.user.avatar || undefined} size={52} />
</Link>
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2 flex-wrap">
@@ -424,7 +424,7 @@ export default async function PostDetailPage({ params, searchParams }: PageProps
>
<div className="flex items-center gap-3 min-w-0">
<Link href={`/u/${post.user.id}`} className="shrink-0" aria-label={post.user.nickname}>
<Avatar name={post.user.nickname || post.user.username} size={40} />
<Avatar name={post.user.nickname || post.user.username} src={post.user.avatar || undefined} size={40} />
</Link>
<Link
href={`/u/${post.user.id}`}