blob: 60a5b76ee5920044d5f68e5e839e786464434b6c [file] [log] [blame]
223010091e2aea72025-06-08 16:35:54 +08001import React, { useState } from 'react';
2import axios from 'axios';
3import toast from 'react-hot-toast';
4import TorrentSelector from './TorrentSelector'; // 引入种子选择组件
5import './CreatePlaylistModal.css';
6import { uploadFile } from '../../../api/file';
7
8const CreatePlaylistModal = ({ onClose, onSuccess }) => {
9 const [newPlaylist, setNewPlaylist] = useState({
10 title: '',
11 price: '',
12 description: '',
13 torrentList: [], // 选中的种子ID数组
14 });
15
16 const [coverFile, setCoverFile] = useState(null); // 新增封面文件状态
17 const [previewUrl, setPreviewUrl] = useState(''); // 封面预览URL
18
19 const handleSelect = (id, checked) => {
20 setNewPlaylist(prev => {
21 let newList = [...prev.torrentList];
22 if (checked) {
23 if (!newList.includes(id)) newList.push(id);
24 } else {
25 newList = newList.filter(i => i !== id);
26 }
27 return { ...prev, torrentList: newList };
28 });
29 };
30
31 const handleCoverChange = (e) => {
32 const file = e.target.files?.[0];
33 if (file) {
34 setCoverFile(file);
35 setPreviewUrl(URL.createObjectURL(file)); // 生成预览图
36 } else {
37 setCoverFile(null);
38 setPreviewUrl('');
39 }
40 };
41
42 const handleCreate = async () => {
43 const { title, price, description, torrentList } = newPlaylist;
44
45 if (!title.trim()) {
46 toast.error('标题不能为空');
47 return;
48 }
49 if (!price || isNaN(Number(price)) || Number(price) < 0) {
50 toast.error('请输入合法的价格');
51 return;
52 }
53 if (torrentList.length === 0) {
54 toast.error('请至少选择一个种子');
55 return;
56 }
57
58 const toastId = toast.loading('正在创建...');
59 const playlistData = { title, price, description, torrentList }; // 构建片单数据
60
61 try {
62
63 if (coverFile) {
64 const { data } = await uploadFile(coverFile);
65 if (data.code === 0) {
66 playlistData['coverUrl'] = data.data;
67 } else {
68 toast.error('封面上传失败: ' + data.msg, { id: toastId});
69 return;
70 }
71 }
72
73 const res = await axios.post('/playlist', playlistData, {
74 });
75
76 if (res.data.code === 0) {
77 toast.success('片单创建成功', { id: toastId });
78 onSuccess(res.data.data);
79 onClose();
80 } else {
81 toast.error(`创建失败:${res.data.msg}`, { id: toastId });
82 }
83 } catch (err) {
84 console.error('创建片单失败', err);
85 toast.error('创建失败,请稍后重试', { id: toastId });
86 }
87 };
88
89 return (
90 <div className="modal-overlay create-playlist-modal">
91 <div className="modal">
92 <h3>创建新片单</h3>
93
94 <label>
95 标题:
96 <input
97 type="text"
98 value={newPlaylist.title}
99 onChange={(e) => setNewPlaylist({ ...newPlaylist, title: e.target.value })}
100 />
101 </label>
102
103 <label>
104 封面图:
105 <input
106 type="file"
107 accept="image/*"
108 onChange={handleCoverChange}
109 />
110 {previewUrl && (
111 <div style={{ marginTop: '10px' }}>
112 <img src={previewUrl} alt="封面预览" style={{ maxWidth: '100%', maxHeight: '150px' }} />
113 </div>
114 )}
115 </label>
116
117 <label>
118 价格(元):
119 <input
120 type="number"
121 step="0.01"
122 min="0"
123 value={newPlaylist.price}
124 onChange={(e) => setNewPlaylist({ ...newPlaylist, price: e.target.value })}
125 />
126 </label>
127
128 <label>
129 片单描述:
130 <textarea
131 value={newPlaylist.description}
132 onChange={(e) => setNewPlaylist({ ...newPlaylist, description: e.target.value })}
133 />
134 </label>
135
136 <label>
137 关联种子选择:
138 <TorrentSelector
139 selectedIds={newPlaylist.torrentList}
140 onSelect={handleSelect}
141 />
142 </label>
143
144 <div className="modal-actions">
145 <button onClick={handleCreate}>提交</button>
146 <button onClick={onClose}>取消</button>
147 </div>
148 </div>
149 </div>
150 );
151};
152
153export default CreatePlaylistModal;