Files
jiang13-bbs/frontend/components/BoardIcon.tsx
freefire 3e55b5d230 feat: 管理端板块管理与旧版数据导入,补充部署运营文档
- 新增管理端板块管理页面与后端接口(admin_board)
- 新增旧版数据导入:legacyimport 服务、导入面板、importusers 命令行工具
- 聊天用户卡片、板块图标等 UI 组件与界面优化
- 补充 about/公告/1Panel 部署等文档
- gitignore 排除 dist/ 构建产物与 .agents/ 本地工具目录
2026-09-24 03:37:44 +08:00

120 lines
3.1 KiB
TypeScript
Raw Permalink 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.
import {
Bookmark,
Book,
Briefcase,
Bell,
Camera,
Code,
Coffee,
Cpu,
Film,
Flame,
FlaskConical,
Gamepad2,
Globe,
Hash,
Heart,
HelpCircle,
Megaphone,
MessageCircle,
Music,
Newspaper,
Palette,
Pencil,
Rocket,
Sparkles,
Star,
type LucideIcon,
} from "lucide-react";
/** 板块图标库:icon 字段值 → lucide 图标;与后端种子数据保持一致 */
const BOARD_ICON_MAP: Record<string, LucideIcon> = {
"message-circle": MessageCircle,
code: Code,
"help-circle": HelpCircle,
coffee: Coffee,
sparkles: Sparkles,
star: Star,
heart: Heart,
bookmark: Bookmark,
hash: Hash,
flame: Flame,
bell: Bell,
megaphone: Megaphone,
newspaper: Newspaper,
book: Book,
briefcase: Briefcase,
camera: Camera,
music: Music,
film: Film,
"gamepad-2": Gamepad2,
rocket: Rocket,
globe: Globe,
pencil: Pencil,
palette: Palette,
cpu: Cpu,
"flask-conical": FlaskConical,
};
/** 管理端图标选项:value 即 icon 字段值,label 为中文描述 */
export const BOARD_ICONS: { value: string; label: string }[] = [
{ value: "message-circle", label: "综合" },
{ value: "hash", label: "话题" },
{ value: "code", label: "代码" },
{ value: "help-circle", label: "求助" },
{ value: "coffee", label: "闲聊" },
{ value: "sparkles", label: "闪光" },
{ value: "star", label: "星标" },
{ value: "heart", label: "心形" },
{ value: "bookmark", label: "书签" },
{ value: "flame", label: "热门" },
{ value: "bell", label: "通知" },
{ value: "megaphone", label: "公告" },
{ value: "newspaper", label: "资讯" },
{ value: "book", label: "学习" },
{ value: "briefcase", label: "职场" },
{ value: "camera", label: "摄影" },
{ value: "music", label: "音乐" },
{ value: "film", label: "影视" },
{ value: "gamepad-2", label: "游戏" },
{ value: "rocket", label: "创业" },
{ value: "globe", label: "国际" },
{ value: "pencil", label: "写作" },
{ value: "palette", label: "设计" },
{ value: "cpu", label: "硬件" },
{ value: "flask-conical", label: "科学" },
];
/** 配色总数:av-0 ~ av-(N-1),与 globals.css 保持一致 */
export const BOARD_COLOR_COUNT = 16;
/**
* 解析板块配色下标(全站统一规则):
* - color_index > 0:固定配色,按 N 取模(存 1..16 渲染 av-0..av-15)
* - 其余(0 = 旧数据未设置 / -1 = 自动):按板块 ID 轮换,任何页面位置都一致
*/
export function boardColor(b: { id: number; color_index?: number | null }): number {
const ci = b.color_index ?? 0;
if (ci > 0) return ci % BOARD_COLOR_COUNT;
return b.id % BOARD_COLOR_COUNT;
}
/** 板块图标:icon 匹配 lucide 图标名;未知/缺失时回退为板块名首字 */
export default function BoardIcon({
icon,
name,
size = 15,
}: {
icon?: string | null;
name: string;
size?: number;
}) {
const I = icon ? BOARD_ICON_MAP[icon] : undefined;
if (I) return <I size={size} aria-hidden="true" />;
return (
<span aria-hidden="true" style={{ fontSize: Math.max(10, size * 0.78), lineHeight: 1 }}>
{name.slice(0, 1)}
</span>
);
}