"use client"; import { Images, Loader2 } from "lucide-react"; import { useEffect, useState } from "react"; import Modal from "@/components/Modal"; import { apiAdminMediaLibrary, apiMyMedia } from "@/lib/api"; import { normalizeBrandURL, type BrandSlot } from "@/lib/brand"; import { isOwnImage, variantURL, widthSrcSet } from "@/lib/responsiveImage"; const SLOT_LABEL: Record = { logo_light: "浅色 Logo", logo_dark: "暗色 Logo", favicon: "Favicon", }; /** 选图条目:本人附件带 attachmentId;品牌目录历史图仅 URL(已在品牌目录,无需复制) */ export type BrandPickItem = { key: string; url: string; attachmentId: number | null; }; export default function BrandMediaPicker({ open, slot, onClose, onPick, }: { open: boolean; slot: BrandSlot; onClose: () => void; onPick: (item: BrandPickItem) => void; }) { const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); useEffect(() => { if (!open) return; let cancelled = false; setLoading(true); setError(""); // 本人附件 + 媒体库盘点里的品牌目录历史图(品牌图不落附件,需合并展示) Promise.all([apiMyMedia(), apiAdminMediaLibrary().catch(() => null)]) .then(([mediaRes, libRes]) => { if (cancelled) return; if (mediaRes.error) { setError(mediaRes.error); setItems([]); return; } const out: BrandPickItem[] = (mediaRes.attachments || []).map((a) => ({ key: `att-${a.id}`, url: a.url, attachmentId: a.id, })); const seen = new Set(out.map((i) => i.url)); for (const it of libRes?.items || []) { if (it.category !== "brand") continue; if (!normalizeBrandURL(slot, it.url)) continue; if (seen.has(it.url)) continue; seen.add(it.url); out.unshift({ key: `brand-${it.url}`, url: it.url, attachmentId: null }); } setItems(out); }) .catch(() => { if (!cancelled) setError("加载媒体库失败"); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [open, slot]); return ( {loading ? (

加载中

) : error ? (

{error}

) : items.length === 0 ? (

媒体库还没有图片,先上传一张吧。

) : (
{items.map((item) => ( ))}
)}
); }