feat(web): 用户工作台 - 产品化壳层、内容库布局与积分入口
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
f52702b70f
commit
969e2831b2
46 files changed
+5355
-944
No files matched your search
@@ -0,0 +1,22 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { CircleUserRound } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { LocalUser } from "@/stores/use-user-store";
|
||||
|
||||
export function UserAvatar({ user, className }: { user: LocalUser; className?: string }) {
|
||||
const [failed, setFailed] = useState(false);
|
||||
const avatarUrl = /^https?:\/\//i.test(user.avatarUrl || "") ? user.avatarUrl : "";
|
||||
|
||||
useEffect(() => setFailed(false), [avatarUrl]);
|
||||
|
||||
// 结构保持 button > span > svg:占位图标自动复用顶栏图标按钮的 18px/1.8 描边与配色合同;默认不套圆角容器,hover 由按钮背景反馈。
|
||||
return (
|
||||
<span className={cn("grid shrink-0 place-items-center overflow-hidden", className)}>
|
||||
{avatarUrl && !failed ? (
|
||||
<img src={avatarUrl} alt="" referrerPolicy="no-referrer" className="size-full object-cover" onError={() => setFailed(true)} />
|
||||
) : (
|
||||
<CircleUserRound className="size-full" aria-hidden />
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user