优化种子评分、热门资源推荐
Change-Id: I9007f3d1d77df8a1d3eeb33c35897ea04c8e3c16
diff --git a/src/pages/SeedList/Recommend/Recommend.css b/src/pages/SeedList/Recommend/Recommend.css
index 1eb3541..cf46b86 100644
--- a/src/pages/SeedList/Recommend/Recommend.css
+++ b/src/pages/SeedList/Recommend/Recommend.css
@@ -1,4 +1,4 @@
-.recommend-wrapper {
+/* .recommend-wrapper {
padding: 20px;
background-color: #fff;
}
@@ -35,4 +35,56 @@
.paid-title {
font-size: 16px;
padding: 10px;
+} */
+
+
+.recommendation-page {
+ padding: 20px;
+ background-color: #f8f9fa;
+}
+
+.recommendation-page h2 {
+ font-size: 1.5rem;
+ margin-bottom: 10px;
+ color: #333;
+}
+
+.seed-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ margin-bottom: 32px;
+}
+
+.seed-card {
+ width: 160px;
+ background: white;
+ border-radius: 12px;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
+ overflow: hidden;
+ transition: transform 0.2s ease;
+ cursor: pointer;
+}
+
+.seed-card:hover {
+ transform: translateY(-4px);
+}
+
+.seed-card img {
+ width: 100%;
+ height: 220px;
+ object-fit: cover;
+}
+
+.seed-card .title {
+ padding: 8px;
+ font-size: 0.95rem;
+ text-align: center;
+ color: #333;
+}
+
+.login-reminder {
+ font-size: 1rem;
+ color: #888;
+ padding: 10px;
}
diff --git a/src/pages/SeedList/Recommend/Recommend.jsx b/src/pages/SeedList/Recommend/Recommend.jsx
index dd38184..8270145 100644
--- a/src/pages/SeedList/Recommend/Recommend.jsx
+++ b/src/pages/SeedList/Recommend/Recommend.jsx
@@ -1,50 +1,48 @@
-// export default Recommend;
import React, { useEffect, useState } from 'react';
+import axios from 'axios';
import './Recommend.css';
+import { useUser } from '../../../context/UserContext';
const Recommend = () => {
- const [paidLists, setPaidLists] = useState([]);
- const [loading, setLoading] = useState(true);
+ const { user } = useUser();
+ const [popularSeeds, setPopularSeeds] = useState([]);
+ const [recommendedSeeds, setRecommendedSeeds] = useState([]);
useEffect(() => {
- const fetchPaidLists = async () => {
- try {
-
- const response = await fetch(`/echo/recommendations/paid?user_id=1`);
- console.log('请求地址:', `${process.env.REACT_APP_API_BASE}/echo/recommendations/paid?user_id=1`);
-
-
- // const response = await fetch('/echo/recommendations/paid?user_id=1');
- const data = await response.json();
- if (data.status === 'success') {
- setPaidLists(data.paid_recommendations);
- } else {
- console.warn('获取付费片单失败');
- }
- } catch (error) {
- console.error('请求出错:', error);
- } finally {
- setLoading(false);
- }
- };
-
- fetchPaidLists();
+ // 获取热门资源
+ axios
+ .get('/echo/recommendation/popular', { params: { limit: 16 } })
+ .then((res) => setPopularSeeds(res.data))
+ .catch((err) => console.error('获取热门资源失败', err));
}, []);
+ useEffect(() => {
+ // 获取个性化推荐
+ if (user && user.userId) {
+ axios
+ .get(`/echo/recommendation/seeds/${user.userId}`)
+ .then((res) => setRecommendedSeeds(res.data))
+ .catch((err) => console.error('获取个性化推荐失败', err));
+ }
+ }, [user]);
+
+ const renderSeedCard = (seed) => (
+ <div className="seed-card" key={seed.id}>
+ <img src={seed.coverUrl || '/default-cover.jpg'} alt={seed.title} />
+ <div className="title">{seed.title}</div>
+ </div>
+ );
+
return (
- <div className="recommend-wrapper">
- <h2 className="recommend-section-title">付费片单</h2>
- {loading ? (
- <p>加载中...</p>
+ <div className="recommendation-page">
+ <h2>🎬 正在热映</h2>
+ <div className="seed-list">{popularSeeds.map(renderSeedCard)}</div>
+
+ <h2>🎯 个性化推荐</h2>
+ {user ? (
+ <div className="seed-list">{recommendedSeeds.map(renderSeedCard)}</div>
) : (
- <div className="recommend-paid-row">
- {paidLists.map((item) => (
- <div className="paid-card" key={item.group_id}>
- <img src={item.image_url} alt={item.group_name} className="paid-cover" />
- <div className="paid-title">{item.group_name}</div>
- </div>
- ))}
- </div>
+ <div className="login-reminder">请登录以获取个性化推荐</div>
)}
</div>
);
diff --git a/src/pages/SeedList/SeedDetail/SeedDetail.jsx b/src/pages/SeedList/SeedDetail/SeedDetail.jsx
index 0cb738c..4ab9274 100644
--- a/src/pages/SeedList/SeedDetail/SeedDetail.jsx
+++ b/src/pages/SeedList/SeedDetail/SeedDetail.jsx
@@ -4,6 +4,7 @@
import Header from '../../../components/Header';
import './SeedDetail.css';
import { useUser } from '../../../context/UserContext';
+import SeedRating from './SeedRating';
const SeedDetail = () => {
const params = useParams();
@@ -214,6 +215,8 @@
<div className="action-buttons">
<button className="btn" onClick={() => handleDownload(seed.id)}>下载</button>
<button className="btn-outline" onClick={handleCollect}>收藏</button>
+ {/* <button className="btn" onClick={handleCollect}>收藏</button> */}
+ <SeedRating seedId={seed.id} />
</div>
<hr className="divider" />
diff --git a/src/pages/SeedList/SeedDetail/SeedRating.css b/src/pages/SeedList/SeedDetail/SeedRating.css
new file mode 100644
index 0000000..e40c055
--- /dev/null
+++ b/src/pages/SeedList/SeedDetail/SeedRating.css
@@ -0,0 +1,23 @@
+.seed-rating {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 18px;
+}
+
+.star {
+ cursor: pointer;
+ color: #ccc;
+ font-size: 24px;
+ transition: color 0.3s;
+}
+
+.star.active {
+ color: rgba(240, 184, 62, 0.916);
+}
+
+.thank-you {
+ margin-left: 10px;
+ font-size: 14px;
+ color: rgba(222, 91, 111, 0.982);
+}
diff --git a/src/pages/SeedList/SeedDetail/SeedRating.jsx b/src/pages/SeedList/SeedDetail/SeedRating.jsx
new file mode 100644
index 0000000..1841443
--- /dev/null
+++ b/src/pages/SeedList/SeedDetail/SeedRating.jsx
@@ -0,0 +1,125 @@
+// import React, { useState, useEffect } from 'react';
+// import axios from 'axios';
+// import './SeedRating.css';
+// import { useUser } from '../../../context/UserContext';
+
+// const SeedRating = ({ seedId }) => {
+// const { user } = useUser();
+// const [score, setScore] = useState(0);
+// const [submitted, setSubmitted] = useState(false);
+
+// const handleRating = async (newScore) => {
+// if (!user || !user.userId) {
+// alert('请先登录再评分');
+// return;
+// }
+
+// try {
+// const res = await axios.post('/echo/ratings', null, {
+// params: {
+// userId: user.userId,
+// seedId,
+// score: newScore,
+// },
+// });
+
+// if (res.data && res.data.status === 'success') {
+// setScore(newScore);
+// setSubmitted(true);
+// alert('评分成功');
+// } else {
+// alert('评分失败,请稍后再试');
+// }
+// } catch (error) {
+// console.error('评分出错:', error);
+// alert('评分请求失败');
+// }
+// };
+
+
+
+// return (
+// <div className="seed-rating">
+// <span>评分:</span>
+// {[1, 2, 3, 4, 5].map((star) => (
+// <span
+// key={star}
+// className={`star ${star <= score ? 'active' : ''}`}
+// // onClick={() => !submitted && handleRating(star)}
+// onClick={() => handleRating(star)}
+
+// >
+// ★
+// </span>
+// ))}
+// {submitted && <span className="thank-you">感谢您的评分!</span>}
+// </div>
+// );
+// };
+
+// export default SeedRating;
+
+import React, { useState, useEffect } from 'react';
+import axios from 'axios';
+import './SeedRating.css';
+import { useUser } from '../../../context/UserContext';
+
+const SeedRating = ({ seedId }) => {
+ const { user } = useUser();
+ const [score, setScore] = useState(0); // 最终提交的分数
+ const [hoverScore, setHoverScore] = useState(0); // 鼠标悬停显示
+ const [submitted, setSubmitted] = useState(false);
+ const [loading, setLoading] = useState(false); // 防止重复点击
+
+ const handleRating = async (newScore) => {
+ if (!user || !user.userId) {
+ alert('请先登录再评分');
+ return;
+ }
+ if (submitted || loading) return;
+
+ setLoading(true);
+ try {
+ const res = await axios.post('/echo/ratings', null, {
+ params: {
+ userId: user.userId,
+ seedId,
+ score: newScore,
+ },
+ });
+
+ if (res.data?.status === 'success') {
+ setScore(newScore);
+ setSubmitted(true);
+ alert('评分成功');
+ } else {
+ alert('评分失败,请稍后再试');
+ }
+ } catch (error) {
+ console.error('评分出错:', error);
+ alert('评分请求失败');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+ <div className="seed-rating">
+ <span>评分:</span>
+ {[1, 2, 3, 4, 5].map((star) => (
+ <span
+ key={star}
+ className={`star ${star <= (hoverScore || score) ? 'active' : ''}`}
+ onMouseEnter={() => !submitted && setHoverScore(star)}
+ onMouseLeave={() => !submitted && setHoverScore(0)}
+ onClick={() => handleRating(star)}
+ >
+ ★
+ </span>
+ ))}
+ {submitted && <span className="thank-you">感谢您的评分!</span>}
+ </div>
+ );
+};
+
+export default SeedRating;