fix: 头像上传后前端不显示真头像 (row29 续)

真因:上传成功且 setUser 写入了 avatar_url,但前端任何头像位置都没渲染 avatar_url,
只显示姓氏首字占位 → 看着像「没更新」。根因:User 类型里压根没暴露 avatar_url 字段。

修:User 类型补 avatar_url;侧栏 .user、账户菜单 .shell-account-head、设置页 av-big
三处头像改为「有 avatar_url 显 <img>,空则回退首字」;.av/.av-big 加 overflow:hidden + img 铺满规则。
后端上传 200 + 直链公读已实测正常,此为纯前端显示修复。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-30 11:02:28 +08:00
co-authored by Claude Opus 4.8
parent b4e61ce627
commit 291a8bf394
4 changed files with 9 additions and 3 deletions
+2 -2
View File
@@ -167,7 +167,7 @@ function AccountMenu({ anchorRect, onClose, navigate, logout, user, team, canMan
style={{ left: pos.left, top: pos.top }} style={{ left: pos.left, top: pos.top }}
> >
<div className="shell-account-head"> <div className="shell-account-head">
<span className="av">{avatar}</span> <span className="av">{user.avatar_url ? <img src={user.avatar_url} alt="头像" /> : avatar}</span>
<span> <span>
<span className="nm">{team?.name || user.username}</span> <span className="nm">{team?.name || user.username}</span>
<span className="mail">{user.username}</span> <span className="mail">{user.username}</span>
@@ -374,7 +374,7 @@ export function Sidebar({ page, navigate, user, team, canManageBilling = true, p
onClick={toggleAccountMenu} onClick={toggleAccountMenu}
onKeyDown={(event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); toggleAccountMenu(event as unknown as ReactMouseEvent<HTMLElement>); } }} onKeyDown={(event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); toggleAccountMenu(event as unknown as ReactMouseEvent<HTMLElement>); } }}
> >
<div className="av">{avatar}</div> <div className="av">{user.avatar_url ? <img src={user.avatar_url} alt="头像" /> : avatar}</div>
<div className="em">{team?.name || user.username}</div> <div className="em">{team?.name || user.username}</div>
</div> </div>
</div> </div>
+4
View File
@@ -375,7 +375,9 @@ nav a.disabled:hover { background: transparent; color: var(--black-alpha-32); }
color: var(--accent-white); color: var(--accent-white);
display: flex; align-items: center; justify-content: center; display: flex; align-items: center; justify-content: center;
font-weight: 600; font-size: 12px; font-weight: 600; font-size: 12px;
overflow: hidden;
} }
.user .av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.user .em { font-size: 13px; color: var(--accent-black); } .user .em { font-size: 13px; color: var(--accent-black); }
body.sidebar-collapsed aside.sidebar { padding: 22px 12px; } body.sidebar-collapsed aside.sidebar { padding: 22px 12px; }
@@ -1948,7 +1950,9 @@ table.t tbody tr:hover { background: var(--black-alpha-4); }
color: var(--accent-white); color: var(--accent-white);
font-size: 12px; font-size: 12px;
font-weight: 600; font-weight: 600;
overflow: hidden;
} }
.shell-account-head .av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shell-account-head .nm { .shell-account-head .nm {
display: block; display: block;
font-size: 13px; font-size: 13px;
+1 -1
View File
@@ -434,7 +434,7 @@ export function SettingsPage({
<div className="lbl"></div> <div className="lbl"></div>
<div className="val"> <div className="val">
<div className="avatar-edit"> <div className="avatar-edit">
<div className="av-big">{avatarChar}</div> <div className="av-big">{user.avatar_url ? <img src={user.avatar_url} alt="头像" /> : avatarChar}</div>
<div className="av-actions"> <div className="av-actions">
<button className="btn btn-sm" type="button" onClick={openAvatarModal}></button> <button className="btn btn-sm" type="button" onClick={openAvatarModal}></button>
<button className="btn btn-ghost btn-sm" type="button" onClick={() => onResetAvatar?.()}></button> <button className="btn btn-ghost btn-sm" type="button" onClick={() => onResetAvatar?.()}></button>
+2
View File
@@ -4,6 +4,8 @@ export type User = {
email: string; email: string;
status: string; status: string;
is_platform_admin?: boolean; is_platform_admin?: boolean;
// 头像直链(后端 UserSerializer.avatar_url):空则前端回退姓氏首字占位
avatar_url?: string;
}; };
export type Team = { export type Team = {