import { App, Button, Modal, Spin } from "antd"; import { ArrowDown, ArrowUp, GripVertical, ListOrdered } from "lucide-react"; import { useRef, useState } from "react"; import { AdminEmpty } from "@/pages/admin/components/admin-ui"; import { getChannelOrder, saveChannelOrder, type ChannelOrderItem } from "@/services/api/channel-order"; export function moveOrderItem(items: T[], id: string, target: number): T[] { const from = items.findIndex((item) => item.id === id); if (from < 0 || target < 0 || target >= items.length || from === target) return items; const next = [...items]; const [item] = next.splice(from, 1); next.splice(target, 0, item!); return next; } export function ChannelOrderDialog({ channelId, onSaved }: { channelId?: string; onSaved: () => Promise }) { const { message } = App.useApp(); const [open, setOpen] = useState(false), [loading, setLoading] = useState(false), [saving, setSaving] = useState(false); const [items, setItems] = useState([]), [original, setOriginal] = useState([]); const dragged = useRef(null), pending = useRef(false); const changed = items.some((item, index) => item.id !== original[index]); const start = async () => { setOpen(true); setLoading(true); setItems([]); setOriginal([]); try { const result = await getChannelOrder(channelId); setItems(result.items); setOriginal(result.items.map((item) => item.id)); } catch (error) { message.error(error instanceof Error ? error.message : "读取排序失败"); setOpen(false); } finally { setLoading(false); } }; const save = async () => { if (pending.current || !changed) return; pending.current = true; setSaving(true); try { await saveChannelOrder( channelId, items.map((item) => item.id), original, ); setOpen(false); await onSaved(); message.success("排序已保存,用户端按此顺序展示"); } catch (error) { message.error(error instanceof Error ? error.message : "保存排序失败"); } finally { pending.current = false; setSaving(false); } }; return ( <> setOpen(false)} closable={!saving && !loading} mask={{ closable: !saving && !loading }} keyboard={!saving && !loading} width={600} footer={
} >

拖动条目或点击上下箭头调整顺序,保存后用户端按此顺序展示。这里包含全部条目,不受列表筛选和分页影响。

{!loading && !items.length ? ( ) : ( items.map((item, index) => (
{ event.dataTransfer.setData("text/plain", item.id); dragged.current = item.id; }} onDragEnd={() => { dragged.current = null; }} onDragOver={(event) => { if (!saving) event.preventDefault(); }} onDrop={(event) => { event.preventDefault(); const source = dragged.current; if (!saving && source) setItems((current) => moveOrderItem(current, source, index)); dragged.current = null; }} className="flex items-center gap-3 rounded-lg border border-border bg-background p-3" > {item.name} {!item.enabled && 已停用}
)) )}
); }