"use client"; import { useCallback, useEffect, useState } from "react"; import { FolderOpen, Plus, Pencil, Trash2, Users as UsersIcon, ChevronUp, ChevronDown, EyeOff, Check, } from "lucide-react"; import { apiAdminAddBoardModerator, apiAdminCreateBoard, apiAdminDeleteBoard, apiAdminListBoardModerators, apiAdminListBoards, apiAdminReorderBoards, apiAdminRemoveBoardModerator, apiAdminUpdateBoard, BOARD_POST_POLICY, type AdminBoard, type AdminBoardInput, type AdminBoardModerator, } from "@/lib/api"; import { AdminEmpty, AdminPageHeader, AdminStatusChip, } from "@/components/admin"; import Modal from "@/components/Modal"; import Avatar from "@/components/Avatar"; import BoardIcon, { BOARD_ICONS, BOARD_COLOR_COUNT, boardColor, } from "@/components/BoardIcon"; const POLICY_LABEL: Record = { [BOARD_POST_POLICY.ALL]: "全员可发", [BOARD_POST_POLICY.STAFF]: "仅管理员", }; const POST_POLICY_OPTIONS: { value: string; label: string; desc: string }[] = [ { value: BOARD_POST_POLICY.ALL, label: "全员可发", desc: "所有登录用户均可在此板块发帖", }, { value: BOARD_POST_POLICY.STAFF, label: "仅管理员及以上", desc: "仅版主、超级管理员、站长可发帖", }, ]; function emptyInput(): AdminBoardInput { return { name: "", description: "", icon: "message-circle", color_index: -1, sort_order: 0, post_policy: BOARD_POST_POLICY.ALL, visible: true, }; } function toInput(b: AdminBoard): AdminBoardInput { return { name: b.name, description: b.description, icon: b.icon, color_index: b.color_index, sort_order: b.sort_order, post_policy: b.post_policy, visible: b.visible, }; } function BoardEditModal({ open, initial, title, busy, editTarget, onClose, onSubmit, }: { open: boolean; initial: AdminBoardInput; title: string; busy: boolean; /** 编辑中的板块(新建为 null);自动配色预览按其 ID 轮换 */ editTarget: AdminBoard | null; onClose: () => void; onSubmit: (input: AdminBoardInput) => void; }) { const [form, setForm] = useState(initial); useEffect(() => { if (open) setForm(initial); }, [open, initial]); const update = (patch: Partial) => setForm((f) => ({ ...f, ...patch })); // 预览配色:固定(>0)按存值取模;自动(-1/0)按已有板块 ID 轮换,新板块用 accent 占位 const previewColor = (form.color_index ?? 0) > 0 ? (form.color_index ?? 0) % BOARD_COLOR_COUNT : editTarget ? editTarget.id % BOARD_COLOR_COUNT : -1; return ( } >
{/* 外观:实时预览 + 图标 + 颜色,联动更新 */}
= 0 ? `av-${previewColor}` : "" }`} style={ previewColor < 0 ? { background: "var(--accent-soft)", color: "var(--accent)" } : undefined } aria-hidden >

{form.name.trim() || "板块名称预览"}

{form.description?.trim() || "描述将显示在这里"}

前台预览

图标

{BOARD_ICONS.map((o) => { const active = form.icon === o.value; return ( ); })}

图标颜色

{/* 存值 1..16 → 渲染 av-1..av-15、av-0;0 与 -1 均视为自动 */} {Array.from({ length: BOARD_COLOR_COUNT }, (_, k) => k + 1).map((v) => { const active = (form.color_index ?? 0) === v; return ( ); })}

{(form.color_index ?? 0) <= 0 ? "自动模式:前台按板块编号分配配色,各页面保持一致。" : "指定固定配色,前台所有位置保持一致。"}