修改提示框样式、完成付费片单、推荐跳转

Change-Id: Ie84c53d4e306435144b1f26ceb39cc182e99d57a
diff --git a/src/pages/SeedList/Recommend/CreatePlaylistModal.jsx b/src/pages/SeedList/Recommend/CreatePlaylistModal.jsx
new file mode 100644
index 0000000..60a5b76
--- /dev/null
+++ b/src/pages/SeedList/Recommend/CreatePlaylistModal.jsx
@@ -0,0 +1,153 @@
+import React, { useState } from 'react';
+import axios from 'axios';
+import toast from 'react-hot-toast';
+import TorrentSelector from './TorrentSelector'; // 引入种子选择组件
+import './CreatePlaylistModal.css';
+import { uploadFile } from '../../../api/file';
+
+const CreatePlaylistModal = ({ onClose, onSuccess }) => {
+  const [newPlaylist, setNewPlaylist] = useState({
+    title: '',
+    price: '',
+    description: '',
+    torrentList: [], // 选中的种子ID数组
+  });
+
+  const [coverFile, setCoverFile] = useState(null); // 新增封面文件状态
+  const [previewUrl, setPreviewUrl] = useState(''); // 封面预览URL
+
+  const handleSelect = (id, checked) => {
+    setNewPlaylist(prev => {
+      let newList = [...prev.torrentList];
+      if (checked) {
+        if (!newList.includes(id)) newList.push(id);
+      } else {
+        newList = newList.filter(i => i !== id);
+      }
+      return { ...prev, torrentList: newList };
+    });
+  };
+
+  const handleCoverChange = (e) => {
+    const file = e.target.files?.[0];
+    if (file) {
+      setCoverFile(file);
+      setPreviewUrl(URL.createObjectURL(file)); // 生成预览图
+    } else {
+      setCoverFile(null);
+      setPreviewUrl('');
+    }
+  };
+
+  const handleCreate = async () => {
+    const { title, price, description, torrentList } = newPlaylist;
+
+    if (!title.trim()) {
+      toast.error('标题不能为空');
+      return;
+    }
+    if (!price || isNaN(Number(price)) || Number(price) < 0) {
+      toast.error('请输入合法的价格');
+      return;
+    }
+    if (torrentList.length === 0) {
+      toast.error('请至少选择一个种子');
+      return;
+    }
+
+    const toastId = toast.loading('正在创建...');
+    const playlistData = { title, price, description, torrentList }; // 构建片单数据
+    
+    try {
+
+      if (coverFile) {
+        const { data } = await uploadFile(coverFile);
+        if (data.code === 0) {
+          playlistData['coverUrl'] = data.data;
+        } else {
+          toast.error('封面上传失败: ' + data.msg, { id: toastId});
+          return;
+        }
+      }
+
+      const res = await axios.post('/playlist', playlistData, {
+      });
+
+      if (res.data.code === 0) {
+        toast.success('片单创建成功', { id: toastId });
+        onSuccess(res.data.data);
+        onClose();
+      } else {
+        toast.error(`创建失败:${res.data.msg}`, { id: toastId });
+      }
+    } catch (err) {
+      console.error('创建片单失败', err);
+      toast.error('创建失败,请稍后重试', { id: toastId });
+    }
+  };
+
+  return (
+    <div className="modal-overlay create-playlist-modal">
+      <div className="modal">
+        <h3>创建新片单</h3>
+
+        <label>
+          标题:
+          <input
+            type="text"
+            value={newPlaylist.title}
+            onChange={(e) => setNewPlaylist({ ...newPlaylist, title: e.target.value })}
+          />
+        </label>
+
+        <label>
+          封面图:
+          <input
+            type="file"
+            accept="image/*"
+            onChange={handleCoverChange}
+          />
+          {previewUrl && (
+            <div style={{ marginTop: '10px' }}>
+              <img src={previewUrl} alt="封面预览" style={{ maxWidth: '100%', maxHeight: '150px' }} />
+            </div>
+          )}
+        </label>
+
+        <label>
+          价格(元):
+          <input
+            type="number"
+            step="0.01"
+            min="0"
+            value={newPlaylist.price}
+            onChange={(e) => setNewPlaylist({ ...newPlaylist, price: e.target.value })}
+          />
+        </label>
+
+        <label>
+          片单描述:
+          <textarea
+            value={newPlaylist.description}
+            onChange={(e) => setNewPlaylist({ ...newPlaylist, description: e.target.value })}
+          />
+        </label>
+
+        <label>
+          关联种子选择:
+          <TorrentSelector
+            selectedIds={newPlaylist.torrentList}
+            onSelect={handleSelect}
+          />
+        </label>
+
+        <div className="modal-actions">
+          <button onClick={handleCreate}>提交</button>
+          <button onClick={onClose}>取消</button>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default CreatePlaylistModal;