import { useState, useEffect } from "react"; import Modal from "./Modal"; import { adminFetch } from "./adminApi"; import { useToast } from "./Toast"; import { Field, ErrorRow, FormFooter, HintRow, fieldCls } from "./FormPrimitives"; type Music = { id: string; title: string; subtitle: string | null; audioFile: string; sortOrder: number; enabled: boolean; }; type Props = { open: boolean; id: string | null; onClose: () => void; onSaved: () => void; }; export default function MusicForm({ open, id, onClose, onSaved }: Props) { const toast = useToast(); const [currentId, setCurrentId] = useState(null); const [title, setTitle] = useState(""); const [subtitle, setSubtitle] = useState(""); const [audioFile, setAudioFile] = useState(""); const [sortOrder, setSortOrder] = useState(0); const [enabled, setEnabled] = useState(true); const [uploading, setUploading] = useState(false); const [saving, setSaving] = useState(false); const [error, setError] = useState(""); const isEdit = !!currentId; useEffect(() => { if (!open) return; setCurrentId(id); setError(""); if (!id) { setTitle(""); setSubtitle(""); setAudioFile(""); setSortOrder(0); setEnabled(true); return; } adminFetch("/music").then((list) => { const item = list.find((m) => m.id === id); if (item) { setTitle(item.title); setSubtitle(item.subtitle || ""); setAudioFile(item.audioFile); setSortOrder(item.sortOrder); setEnabled(item.enabled); } }); }, [open, id]); const handleUpload = async (file: File) => { if (!currentId) { setError("请先保存后再上传音频"); return; } setError(""); setUploading(true); try { const formData = new FormData(); formData.append("audio", file); const data = await adminFetch<{ path: string }>(`/music/${currentId}/upload`, { method: "POST", body: formData, }); setAudioFile(data.path); toast.show("音频已上传"); onSaved(); } catch (e) { setError(e instanceof Error ? e.message : "上传失败"); } finally { setUploading(false); } }; const handleSave = async () => { setError(""); if (!title.trim()) return setError("请输入标题"); setSaving(true); try { const payload = { title: title.trim(), subtitle: subtitle.trim() || undefined, sortOrder, enabled, }; if (isEdit) { await adminFetch(`/music/${currentId}`, { method: "PUT", body: JSON.stringify(payload), }); toast.show("已保存"); onSaved(); onClose(); } else { const music = await adminFetch("/music", { method: "POST", body: JSON.stringify(payload), }); setCurrentId(music.id); toast.show("已创建,现在可以上传音频"); onSaved(); } } catch (e) { setError(e instanceof Error ? e.message : "保存失败"); } finally { setSaving(false); } }; return (
setTitle(e.target.value)} placeholder="如:朝天宫之歌" className={fieldCls} /> setSubtitle(e.target.value)} placeholder="选填,如:金陵千年韵" className={fieldCls} />
setSortOrder(Number(e.target.value))} className={fieldCls + " w-28"} />
{isEdit ? (
{audioFile ? (
) : ( )} {error && }
); }