完成用户等级权限设置、修复下载次数不增加

Change-Id: Ia8ab0e643c86e236a5c25ac77b081cd1f3ba5976
diff --git a/src/pages/Forum/posts-detail/PostDetailPage.jsx b/src/pages/Forum/posts-detail/PostDetailPage.jsx
index 2e4874a..bf0f062 100644
--- a/src/pages/Forum/posts-detail/PostDetailPage.jsx
+++ b/src/pages/Forum/posts-detail/PostDetailPage.jsx
@@ -5,6 +5,7 @@
 import './PostDetailPage.css';
 import { UserContext } from '../../../context/UserContext'; // 用户上下文
 import Header from '../../../components/Header';
+import AuthButton from '../../../components/AuthButton';
 
 const formatImageUrl = (url) => {
   if (!url) return '';
@@ -259,7 +260,10 @@
                       onChange={(e) => setNewComment(e.target.value)}
                     />
                     <div className="comment-options">
-                      <button onClick={handleAddComment}>发布回复</button>
+                      <AuthButton roles={['cookie', 'chocolate', 'ice-cream']} onClick={handleAddComment}>
+                        发布回复
+                      </AuthButton>
+
                       <button
                         onClick={() => {
                           setReplyToCommentId(null);
@@ -284,7 +288,10 @@
                   onChange={(e) => setNewComment(e.target.value)}
                 />
                 <div className="comment-options">
-                  <button onClick={handleAddComment}>发布评论</button>
+                  <AuthButton roles={['cookie', 'chocolate', 'ice-cream']} onClick={handleAddComment}>
+                    发布评论
+                  </AuthButton>
+
                 </div>
               </div>
             )}
diff --git a/src/pages/InterestGroup/GroupItem.jsx b/src/pages/InterestGroup/GroupItem.jsx
index 8e6068b..1718111 100644
--- a/src/pages/InterestGroup/GroupItem.jsx
+++ b/src/pages/InterestGroup/GroupItem.jsx
@@ -3,6 +3,7 @@
 import { useUser } from '../../context/UserContext';
 import { useLocation } from 'wouter';
 import './GroupDetail.css';
+import AuthButton from '../../components/AuthButton';
 
 const GroupItem = ({ group }) => {
   const [, setLocation] = useLocation();
@@ -97,7 +98,8 @@
           <p style={{ color: '#BA929A' }}>{group.memberCount || 0}人加入了小组</p>
 
           {userId && (
-            <button
+            <AuthButton
+              roles={["chocolate", "ice-cream"]}
               style={{ color: '#2167c9', background: 'none', border: 'none', padding: 0, cursor: 'pointer', fontSize: '16px' }}
               onClick={(e) => {
                 e.stopPropagation();
@@ -106,7 +108,7 @@
               disabled={loading}
             >
               {loading ? '处理中...' : isMember ? '退出小组' : '+加入小组'}
-            </button>
+            </AuthButton>
           )}
           {!userId && <button disabled>请登录</button>}
 
diff --git a/src/pages/InterestGroup/GroupPosts.jsx b/src/pages/InterestGroup/GroupPosts.jsx
index 7bd16ba..d7893c7 100644
--- a/src/pages/InterestGroup/GroupPosts.jsx
+++ b/src/pages/InterestGroup/GroupPosts.jsx
@@ -2,6 +2,7 @@
 import CommentForm from './CommentForm';
 import { GoodTwo, Comment } from '@icon-park/react';
 import './GroupDetail.css';
+import AuthButton from '../../components/AuthButton';
 
 const GroupPosts = ({ 
   posts, 
@@ -21,12 +22,13 @@
       
       <div className="post-list-header">
         {userId && isMember && (
-          <button 
+          <AuthButton
+          roles={[ "chocolate", "ice-cream"]}
             className="create-post-btn" 
             onClick={onShowCreatePost}
           >
             + 发布帖子
-          </button>
+          </AuthButton>
         )}
         {(!userId || !isMember) && <p className="login-hint">{loginHint}</p>}
       </div>
diff --git a/src/pages/PublishSeed/PublishSeed.jsx b/src/pages/PublishSeed/PublishSeed.jsx
index 27717ca..6528b0d 100644
--- a/src/pages/PublishSeed/PublishSeed.jsx
+++ b/src/pages/PublishSeed/PublishSeed.jsx
@@ -5,6 +5,7 @@
 import './PublishSeed.css';
 import { useUser } from '../../context/UserContext';
 import { uploadFile } from '../../api/file';
+import AuthButton from '../../components/AuthButton';
 
 const PublishSeed = () => {
   const [title, setTitle] = useState('');
@@ -99,7 +100,7 @@
       });
       console.log('[DEBUG] 请求成功,响应:', response.data);
 
-      if (response.data.status === 'success') {
+      if (response.data.code === 0) {
         setMessage('种子上传成功');
       } else {
         setMessage(response.data.message || '上传失败,请稍后再试');
@@ -238,13 +239,14 @@
           </div>
 
           <div className="ps-upload-button">
-            <button
+            <AuthButton
+              roles={["cookie", "chocolate", "ice-cream"]}
               type="submit"
               disabled={isLoading}
               onClick={() => console.log('[DEBUG] 上传按钮 onClick 触发')}
             >
               {isLoading ? '正在上传...' : '上传种子'}
-            </button>
+            </AuthButton>
           </div>
         </form>
       </div>
diff --git a/src/pages/SeedList/Recommend/Recommend.jsx b/src/pages/SeedList/Recommend/Recommend.jsx
index f58c73d..2229bb1 100644
--- a/src/pages/SeedList/Recommend/Recommend.jsx
+++ b/src/pages/SeedList/Recommend/Recommend.jsx
@@ -7,6 +7,7 @@
 import CreatePlaylistModal from './CreatePlaylistModal';
 import { confirmAlert } from 'react-confirm-alert';
 import 'react-confirm-alert/src/react-confirm-alert.css';
+import AuthButton from '../../../components/AuthButton';
 
 const Recommend = () => {
   const { user } = useUser();
@@ -160,15 +161,18 @@
             />
             <div className="paid-title">{list.title}</div>
 
-            {user && user.role === 'admin' ? (
-              <div className="admin-actions">
-                <button onClick={() => handleDelete(list.id)}>删除</button>
-              </div>
-            ) : list.isPaid ? (
-              <button onClick={() => navigate(`/playlist/${list.id}`)}>详情</button>
-            ) : (
-              <button onClick={() => handlePurchase(list.id)}>购买</button>
-            )}
+          {user && user.role === 'admin' ? (
+            <div className="admin-actions">
+              <button onClick={() => handleDelete(list.id)}>删除</button>
+            </div>
+          ) : list.isPaid ? (
+            <button onClick={() => navigate(`/playlist/${list.id}`)}>详情</button>
+          ) : (
+            <AuthButton roles={['chocolate', 'ice-cream']} onClick={() => handlePurchase(list.id)}>
+              购买
+            </AuthButton>
+          )}
+
           </div>
         ))}
       </div>
diff --git a/src/pages/SeedList/SeedDetail/SeedDetail.jsx b/src/pages/SeedList/SeedDetail/SeedDetail.jsx
index 4ab9274..705368a 100644
--- a/src/pages/SeedList/SeedDetail/SeedDetail.jsx
+++ b/src/pages/SeedList/SeedDetail/SeedDetail.jsx
@@ -5,6 +5,7 @@
 import './SeedDetail.css';
 import { useUser } from '../../../context/UserContext';
 import SeedRating from './SeedRating';
+import AuthButton from '../../../components/AuthButton';
 
 const SeedDetail = () => {
   const params = useParams();
@@ -213,12 +214,16 @@
         </div>
 
         <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> */}
+          <AuthButton roles={["cookie", "chocolate", "ice-cream"]} onClick={() => handleDownload(seed.id)}>
+            下载
+          </AuthButton>
+          <AuthButton roles={["cookie", "chocolate", "ice-cream"]} onClick={handleCollect}>
+            收藏
+          </AuthButton>
           <SeedRating seedId={seed.id} />
         </div>
 
+
         <hr className="divider" />
         <h3>评论区</h3>
         <div className="comments-section">
diff --git a/src/pages/SeedList/SeedDetail/SeedRating.css b/src/pages/SeedList/SeedDetail/SeedRating.css
index e40c055..f62131c 100644
--- a/src/pages/SeedList/SeedDetail/SeedRating.css
+++ b/src/pages/SeedList/SeedDetail/SeedRating.css
@@ -20,4 +20,8 @@
   margin-left: 10px;
   font-size: 14px;
   color: rgba(222, 91, 111, 0.982);
+} 
+.star.hover {
+  color: rgba(240, 184, 62, 0.916); /* 亮黄色 */
 }
+
diff --git a/src/pages/SeedList/SeedDetail/SeedRating.jsx b/src/pages/SeedList/SeedDetail/SeedRating.jsx
index 1841443..8e2d3f0 100644
--- a/src/pages/SeedList/SeedDetail/SeedRating.jsx
+++ b/src/pages/SeedList/SeedDetail/SeedRating.jsx
@@ -63,6 +63,7 @@
 import axios from 'axios';
 import './SeedRating.css';
 import { useUser } from '../../../context/UserContext';
+import AuthButton from '../../../components/AuthButton';
 
 const SeedRating = ({ seedId }) => {
   const { user } = useUser();
@@ -105,17 +106,28 @@
 
   return (
     <div className="seed-rating">
-      <span>评分:</span>
+      <span style={{color: '#333'}}>评分:</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>
+      <AuthButton
+        key={star}
+        roles={["cookie", "chocolate", "ice-cream"]}
+        style={{
+          backgroundColor: 'inherit',
+          margin: 0,
+          // color: '#ccc',
+          padding: 0,
+          outline: 'none',
+          border: 'none',
+          cursor: 'pointer'
+        }}
+        className={`star ${(star <= (hoverScore || score) ? 'active' : '')} ${hoverScore >= star ? 'hover' : ''}`}
+        onMouseEnter={() => !submitted && setHoverScore(star)}
+        onMouseLeave={() => !submitted && setHoverScore(0)}
+        onClick={() => handleRating(star)}
+      >
+        ★
+      </AuthButton>
+
       ))}
       {submitted && <span className="thank-you">感谢您的评分!</span>}
     </div>
diff --git a/src/pages/SeedList/SeedList.jsx b/src/pages/SeedList/SeedList.jsx
index 263038b..45b9f8c 100644
--- a/src/pages/SeedList/SeedList.jsx
+++ b/src/pages/SeedList/SeedList.jsx
@@ -169,8 +169,8 @@
 
             <div className="tag-filters">
                 {TAGS.map(tag => (
-                    <AuthButton
-                        roles={["test"]}
+                     <button
+                        // roles={["test"]}
                         key={tag}
                         className={`tag-button ${activeTab === tag ? 'active-tag' : ''}`}
                         onClick={() => {
@@ -180,7 +180,7 @@
                         }}
                     >
                         {tag}
-                    </AuthButton>
+                    </button>
                 ))}
             </div>
 
@@ -257,9 +257,10 @@
                                             </div>
                                             <div className="seed-item-size">{seed.size || '未知'}</div>
                                             <div className="seed-item-upload-time">{seed.upload_time?.split('T')[0] || '未知'}</div>
-                                            <div className="seed-item-downloads">{seed.downloads ?? 0} 次下载</div>
+                                            <div className="seed-item-downloads">{seed.leechers ?? 0} 次下载</div>
                                             <div className="seed-item-actions" onClick={e => e.stopPropagation()}>
-                                                <button
+                                                <AuthButton
+                                                roles={["cookie", "chocolate", "ice-cream"]}
                                                     className="btn-primary"
                                                     onClick={e => {
                                                         e.preventDefault();
@@ -285,8 +286,9 @@
                                                     }}
                                                 >
                                                     下载
-                                                </button>
-                                                <button
+                                                </AuthButton>
+                                                <AuthButton
+                                                    roles={["cookie", "chocolate", "ice-cream"]}
                                                     className="btn-outline"
                                                     onClick={async (e) => {
                                                         e.preventDefault();
@@ -314,7 +316,7 @@
                                                     }}
                                                 >
                                                     收藏
-                                                </button>
+                                                </AuthButton>
                                             </div>
                                         </div>
                                     </Link>
diff --git a/src/pages/UserCenter/UserProfileBase.jsx b/src/pages/UserCenter/UserProfileBase.jsx
index 791baca..c90cb63 100644
--- a/src/pages/UserCenter/UserProfileBase.jsx
+++ b/src/pages/UserCenter/UserProfileBase.jsx
@@ -9,7 +9,7 @@
 const DEFAULT_AVATAR_URL = `${process.env.PUBLIC_URL}/default-avatar.png`;
 
 const UserProfileBase = ({ onLoadExperienceInfo }) => {
-  const { user, loading, logout } = useUser();
+  const { user, loading, logout ,saveUser} = useUser();
   const [userProfile, setUserProfile] = useState(null);
   const [error, setError] = useState(null);
 
@@ -66,34 +66,44 @@
     fetchUserProfile();
   }, [user, loading, onLoadExperienceInfo]);
 
-  const handleAvatarUpload = async (e) => {
-    const file = e.target.files[0];
-    if (!file) return;
+const handleAvatarUpload = async (e) => {
+  const file = e.target.files[0];
+  if (!file) return;
 
-    const formData = new FormData();
-    formData.append('file', file);
+  const formData = new FormData();
+  formData.append('file', file);
 
-    try {
-      const { data } = await axios.post(
-        `/echo/user/${user.userId}/uploadAvatar`,
-        formData,
-        { headers: { 'Content-Type': 'multipart/form-data' } }
-      );
+  try {
+    const { data } = await axios.post(
+      `/echo/user/${user.userId}/uploadAvatar`,
+      formData,
+      { headers: { 'Content-Type': 'multipart/form-data' } }
+    );
 
-      if (data?.avatarUrl) {
-        setUserProfile((prev) => ({
-          ...prev,
-          avatarUrl: `${process.env.REACT_APP_AVATAR_BASE_URL}${data.avatarUrl}`,
-        }));
-        toast.success('头像上传成功');
-      } else {
-        toast.success('头像上传成功,但未返回新头像地址');
-      }
-    } catch (err) {
-      console.error('上传失败:', err);
-      toast.error('头像上传失败,请重试');
+    if (data?.avatarUrl) {
+      // 加时间戳避免缓存
+      const newAvatarUrl = `${process.env.REACT_APP_AVATAR_BASE_URL}${data.avatarUrl}?t=${Date.now()}`;
+
+      setUserProfile((prev) => ({
+        ...prev,
+        avatarUrl: newAvatarUrl,
+      }));
+
+      saveUser({
+        ...user,
+        avatarUrl: newAvatarUrl,
+      });
+
+      toast.success('头像上传成功');
+    } else {
+      toast.success('头像上传成功,但未返回新头像地址');
     }
-  };
+  } catch (err) {
+    console.error('上传失败:', err);
+    toast.error('头像上传失败,请重试');
+  }
+};
+
 
   const handleLogout = () => {
     logout();