-
+
+
+
+ {EMOJI_LIST.map(emoji => (
+
+ ))}
+
+
+
+
+
setFormData({ ...formData, name: e.target.value })}
- className="h-16 rounded-[1.5rem] border-none bg-white shadow-sm font-bold text-[#4A3A2C] focus:ring-4 ring-[#D28F4F]/10 transition-all pl-8 text-lg"
+ className="h-14 md:h-16 rounded-2xl md:rounded-3xl border-none bg-white shadow-sm font-bold text-[#4A3A2C] focus:ring-4 ring-[#D28F4F]/10 transition-all pl-6 md:pl-8 text-lg"
/>
-
-
+
+
+
+
+
+ {/* Form Right Side */}
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setFormData({ ...formData, coverId: id })}
- />
-
-
+
+ {/* Action Buttons */}
+
diff --git a/src/pages/Radio/Program/index.tsx b/src/pages/Radio/Program/index.tsx
index 1040527..a48a778 100644
--- a/src/pages/Radio/Program/index.tsx
+++ b/src/pages/Radio/Program/index.tsx
@@ -4,7 +4,7 @@ import {
saveProgramApi,
updateProgramApi,
deleteProgramApi,
- getCategoryTreeApi
+ getChannelListApi
} from '../../../api/radio';
import { FileUploader } from '../../../components/FileUploader';
import { DeleteConfirm } from '../../../components/DeleteConfirm';
@@ -18,20 +18,29 @@ import {
Plus,
Edit,
Trash2,
- ChevronDown,
- ChevronRight,
+ Search,
Play,
Pause,
- Headphones,
- ListMusic,
+ Music,
+ Clock,
+ Tag,
Disc3,
- ThumbsUp,
- Search,
- Clock
+ ArrowRight,
+ Headphones,
+ FileAudio,
+ Smile
} from 'lucide-react';
import { toast } from 'sonner';
import { motion, AnimatePresence } from 'framer-motion';
+const EMOJI_LIST = [
+ '🎵', '🎶', '📻', '🎙️', '🎧', '🌙', '☀️', '🌊', '🌲', '🌌',
+ '🍵', '🏮', '🎐', '🌸', '🎋', '🧘', '💆', '🕯️', '🕊️', '☁️',
+ '🍃', '🐚', '🏔️', '🦊', '🦉', '🦋', '🎈', '🎨', '📚', '⌛',
+ '🌈', '✨', '💎', '🦄', '🍀', '🍎', '🍓', '🍰', '🧁', '🍦',
+ '🧸', '🎮', '🛸', '🚀', '🔭', '🌍', '🏠', '⛺', '🚂', '🚲'
+];
+
export default function Program() {
const [data, setData] = useState
([]);
const [total, setTotal] = useState(0);
@@ -47,65 +56,41 @@ export default function Program() {
const [open, setOpen] = useState(false);
const [isEdit, setIsEdit] = useState(false);
const [formData, setFormData] = useState({
- id: '',
+ id: undefined,
channelId: '',
title: '',
description: '',
content: '',
- duration: 0,
audioId: '',
- audioUrl: '',
+ duration: 0,
+ cover: '🎵',
tags: '',
status: 1
});
- const [treeData, setTreeData] = useState([]);
- const [expandedCategories, setExpandedCategories] = useState([]);
- const [playingId, setPlayingId] = useState(null);
+ const [deleteOpen, setDeleteOpen] = useState(false);
+ const [deleteIds, setDeleteIds] = useState([]);
+
+ const [playingId, setPlayingId] = useState(null);
const audioRef = useRef(null);
- const [deleteOpen, setDeleteOpen] = useState(false);
- const [deleteId, setDeleteId] = useState(null);
-
- const fetchTreeData = async () => {
+ const fetchChannels = async () => {
try {
- const res: any = await getCategoryTreeApi();
- const list = res.list || res || [];
- setTreeData(list);
-
- const allChannels: any = [];
- list.forEach((cat: any) => {
- const channelList = cat.channels || cat.channelList || [];
- allChannels.push(...channelList);
- });
- setChannels(allChannels);
-
- if (list.length > 0) {
- const firstCatId = String(list[0].ID || list[0].id || "");
- setExpandedCategories(prev => prev.length === 0 ? [firstCatId] : prev);
-
- if (selectedChannelId === "") {
- const firstCatChannels = list[0].channels || list[0].channelList || [];
- if (firstCatChannels.length > 0) {
- const firstChanId = String(firstCatChannels[0].ID || firstCatChannels[0].id || "");
- setSelectedChannelId(firstChanId);
- }
- }
- }
+ const res: any = await getChannelListApi({ pageSize: 100 });
+ setChannels(res.list || res || []);
} catch (e) {
console.error(e);
}
}
const fetchData = async () => {
- if (!selectedChannelId) return;
setLoading(true);
try {
const res: any = await getProgramListApi({
current: page,
pageSize: pageSize,
- title: debouncedSearch || "",
- channelId: selectedChannelId || ""
+ title: debouncedSearch,
+ channelId: selectedChannelId || undefined
});
setData(res.list || res || []);
setTotal(res.total || 0);
@@ -117,18 +102,11 @@ export default function Program() {
};
useEffect(() => {
- fetchTreeData();
- audioRef.current = new Audio();
- return () => {
- if (audioRef.current) {
- audioRef.current.pause();
- audioRef.current.src = "";
- }
- };
+ fetchChannels();
}, []);
useEffect(() => {
- if (selectedChannelId) fetchData();
+ fetchData();
}, [page, pageSize, selectedChannelId, debouncedSearch]);
useEffect(() => {
@@ -139,43 +117,17 @@ export default function Program() {
return () => clearTimeout(timer);
}, [searchTitle]);
- const togglePlay = (record: any) => {
- const id = String(record.ID || record.id || "");
- const url = record.audio?.url || record.audioUrl;
-
- if (!url || !audioRef.current) {
- toast.error("无可播放音频");
- return;
- }
-
- if (playingId === id) {
- audioRef.current.pause();
- setPlayingId(null);
- } else {
- audioRef.current.src = url;
- audioRef.current.play().catch(e => {
- toast.error("播放失败: " + e.message);
- setPlayingId(null);
- });
- setPlayingId(id);
- }
- };
-
- if (audioRef.current) {
- audioRef.current.onended = () => setPlayingId(null);
- }
-
const handleOpenAdd = () => {
setIsEdit(false);
setFormData({
- id: '',
- channelId: selectedChannelId,
+ id: undefined,
+ channelId: selectedChannelId || '',
title: '',
description: '',
content: '',
- duration: 0,
audioId: '',
- audioUrl: '',
+ duration: 0,
+ cover: '🎵',
tags: '',
status: 1
});
@@ -190,48 +142,44 @@ export default function Program() {
title: record.title,
description: record.description,
content: record.content,
+ audioId: record.audioId || "",
duration: record.duration,
- audioId: record.audioId,
- audioUrl: record.audio?.url || record.audioUrl || "",
- tags: record.tags,
+ cover: record.cover || '🎵',
+ tags: record.tags || "",
status: record.status
});
setOpen(true);
};
const handleDeleteClick = (id: any) => {
- setDeleteId(id);
+ setDeleteIds([String(id)]);
setDeleteOpen(true);
};
const confirmDelete = async () => {
- if (!deleteId) return;
+ if (deleteIds.length === 0) return;
try {
- await deleteProgramApi({ ids: [String(deleteId)] });
+ await deleteProgramApi({ ids: deleteIds });
toast.success('删除成功');
fetchData();
} catch (e) {
console.error(e);
} finally {
setDeleteOpen(false);
- setDeleteId(null);
+ setDeleteIds([]);
}
};
const handleSubmit = async () => {
- if (!formData.title) return toast.error('请填写标题');
-
- const submitData = { ...formData };
- if (submitData.duration === "" || submitData.duration === undefined || submitData.duration === null) {
- submitData.duration = 0;
- }
+ if (!formData.title) return toast.error('请填写节目标题');
+ if (!formData.channelId) return toast.error('请选择所属频道');
try {
if (isEdit) {
- await updateProgramApi(submitData);
+ await updateProgramApi(formData);
toast.success('更新成功');
} else {
- await saveProgramApi(submitData);
+ await saveProgramApi(formData);
toast.success('创建成功');
}
setOpen(false);
@@ -241,373 +189,386 @@ export default function Program() {
}
};
- const toggleCategory = (catId: string) => {
- setExpandedCategories(prev =>
- prev.includes(catId) ? prev.filter(id => id !== catId) : [...prev, catId]
- );
+ const togglePlay = (record: any) => {
+ const audioUrl = record.audio?.url || record.audioId;
+ if (!audioUrl) return toast.error('无可用音频文件');
+
+ if (playingId === (record.ID || record.id)) {
+ audioRef.current?.pause();
+ setPlayingId(null);
+ } else {
+ if (audioRef.current) {
+ audioRef.current.src = audioUrl;
+ audioRef.current.play();
+ setPlayingId(record.ID || record.id);
+ }
+ }
+ };
+
+ const formatDuration = (seconds: number) => {
+ const m = Math.floor(seconds / 60);
+ const s = Math.floor(seconds % 60);
+ return `${m}:${s < 10 ? '0' : ''}${s}`;
};
return (
-
+