Files
jiang13-bbs/frontend/components/Avatar.tsx
freefire 7b327bc8cc feat: 站点访问统计与可配置侧边栏组件
- 新增访问统计:visitstats 服务与查询、visit_capture 中间件、爬虫/来源识别、管理端 analytics 页面
- 新增侧边栏:sidebar 服务与 handler、管理端 sidebar 配置页、前端侧边栏组件
- 新增 widget 嵌入代码生成(widgetCode)与 widgetApi
- 遥测逻辑迁移至 handler 层,删除 service/telemetry
- env 示例补充 Docker 部署可信代理 IP 说明
2026-09-24 18:53:45 +08:00

56 lines
1.6 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.
"use client";
import { useEffect, useState } from "react";
// 柔和多色头像:按用户名确定性取色,圆形软底,浅/暗主题在 globals.css 各自配色
function hash(s: string) {
let h = 0;
for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0;
return h;
}
export default function Avatar({
name,
size = 36,
src,
className = "",
square = false,
}: {
name: string;
size?: number;
src?: string | null;
className?: string;
/** 方形(带小圆角)轮廓,用于帖子列表行;默认圆形 */
square?: boolean;
}) {
const idx = hash(name || "?") % 8;
const initial = (name || "?").trim().charAt(0).toUpperCase();
// 图片 404(如附件已被彻底删除)时回退到字母头像,不显示裂图
const [imgFailed, setImgFailed] = useState(false);
// 切换到新的图片地址时重置失败状态
useEffect(() => setImgFailed(false), [src]);
const showImg = !!src && !imgFailed;
return (
<span
className={`inline-flex items-center justify-center shrink-0 select-none font-bold overflow-hidden av-${idx} ${
square ? "rounded-[9px]" : "rounded-full"
} ${className}`}
style={{ width: size, height: size, fontSize: size * 0.42 }}
aria-hidden="true"
>
{showImg ? (
// eslint-disable-next-line @next/next/no-img-element
<img
src={src}
alt={name.trim() || "用户头像"}
className="w-full h-full object-cover"
onError={() => setImgFailed(true)}
/>
) : (
initial
)}
</span>
);
}