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

Change-Id: Ie84c53d4e306435144b1f26ceb39cc182e99d57a
diff --git a/src/pages/SeedList/Recommend/PlaylistDetailPage.jsx b/src/pages/SeedList/Recommend/PlaylistDetailPage.jsx
new file mode 100644
index 0000000..07558d6
--- /dev/null
+++ b/src/pages/SeedList/Recommend/PlaylistDetailPage.jsx
@@ -0,0 +1,92 @@
+import React, { useEffect, useState } from 'react';
+import { useRoute } from 'wouter'; // ✅ 修改这里
+import axios from 'axios';
+import Header from '../../../components/Header';
+import './PlaylistDetailPage.css';
+import { useUser } from '../../../context/UserContext';
+import toast from 'react-hot-toast';
+import { confirmAlert } from 'react-confirm-alert';
+import 'react-confirm-alert/src/react-confirm-alert.css';
+
+const PlaylistDetailPage = () => {
+  const [match, params] = useRoute('/playlist/:id'); // ✅ 使用 useRoute
+  const id = params?.id;
+  const { user } = useUser();
+  const userId = user?.userId;
+
+  const [detail, setDetail] = useState(null);
+  const [loading, setLoading] = useState(true);
+  const [error, setError] = useState('');
+
+  const fetchDetail = async () => {
+    if (!id) {
+      setError('无效的片单ID');
+      setLoading(false);
+      return;
+    }
+    if (!userId) {
+      setError('请先登录');
+      setLoading(false);
+      return;
+    }
+
+    try {
+      setLoading(true);
+      setError('');
+      const res = await axios.get(`/playlist/${id}`, {
+        params: { userId }
+      });
+      if (res.data.code === 0) {
+        setDetail(res.data.data);
+      } else {
+        setError(res.data.msg || '加载失败');
+      }
+    } catch (err) {
+      console.error(err);
+      setError('请求失败,请检查网络');
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  useEffect(() => {
+    if (id && userId) fetchDetail(); // ✅ 防止空 ID 反复触发
+  }, [id, userId]);
+
+  if (loading) return <div>加载中...</div>;
+
+  if (error) {
+    return (
+      <div className="error">
+        {error}
+        <button onClick={fetchDetail} className="retry-button">重试</button>
+      </div>
+    );
+  }
+
+return (
+  <div className="playlist-detail">
+    <Header />
+    <h1>{detail.title}</h1>
+    <img
+      src={detail.coverUrl || '/default-cover.jpg'}
+      alt={detail.title}
+      onError={e => { e.target.src = '/default-cover.jpg'; }}
+      className="cover-image"
+    />
+    <p>{detail.description}</p>
+
+    <h3>包含的种子:</h3>
+    {detail.torrentList && detail.torrentList.length > 0 ? (
+      <ul>
+        {detail.torrentList.map(seed => (
+          <li key={seed.id}>{seed.title}</li>
+        ))}
+      </ul>
+    ) : (
+      <p>暂无种子数据</p>
+    )}
+  </div>
+);
+};
+export default PlaylistDetailPage;