button state

Change-Id: Ic152517cd68c4fe7d03e8e150fb7e13acf6842b9
diff --git a/Merge/back_rhj/__pycache__/config.cpython-312.pyc b/Merge/back_rhj/__pycache__/config.cpython-312.pyc
index 52dc95c..b52f5ec 100644
--- a/Merge/back_rhj/__pycache__/config.cpython-312.pyc
+++ b/Merge/back_rhj/__pycache__/config.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/__init__.py b/Merge/back_rhj/app/__init__.py
index 098898c..aa7050e 100644
--- a/Merge/back_rhj/app/__init__.py
+++ b/Merge/back_rhj/app/__init__.py
@@ -20,25 +20,25 @@
     from .blueprints.recommend import recommend_bp
     app.register_blueprint(recommend_bp)
     
-    # Register scheduler blueprint
-    from .blueprints.scheduler import scheduler_bp
-    app.register_blueprint(scheduler_bp)
+    # # Register scheduler blueprint
+    # from .blueprints.scheduler import scheduler_bp
+    # app.register_blueprint(scheduler_bp)
     
-    # 初始化定时任务管理器
-    from .utils.scheduler_manager import SchedulerManager
+    # # 初始化定时任务管理器
+    # from .utils.scheduler_manager import SchedulerManager
     
-    scheduler_manager = SchedulerManager()
-    scheduler_manager.init_scheduler(app)
+    # scheduler_manager = SchedulerManager()
+    # scheduler_manager.init_scheduler(app)
     
-    # 检查是否启用定时任务
-    scheduler_enabled = getattr(app.config, 'SCHEDULER_ENABLED', True)
-    if scheduler_enabled:
-        # 从配置获取重建间隔
-        rebuild_interval = getattr(app.config, 'GRAPH_REBUILD_INTERVAL', 1)
-        scheduler_manager.start_graph_rebuild_task(interval_minutes=rebuild_interval)
+    # # 检查是否启用定时任务
+    # scheduler_enabled = getattr(app.config, 'SCHEDULER_ENABLED', True)
+    # if scheduler_enabled:
+    #     # 从配置获取重建间隔
+    #     rebuild_interval = getattr(app.config, 'GRAPH_REBUILD_INTERVAL', 1)
+    #     scheduler_manager.start_graph_rebuild_task(interval_minutes=rebuild_interval)
     
-    # 注册关闭时的清理函数
-    atexit.register(lambda: scheduler_manager.shutdown())
+    # # 注册关闭时的清理函数
+    # atexit.register(lambda: scheduler_manager.shutdown())
 
     return app
 
diff --git a/Merge/back_rhj/app/__pycache__/__init__.cpython-312.pyc b/Merge/back_rhj/app/__pycache__/__init__.cpython-312.pyc
index 59d6618..6098e13 100644
--- a/Merge/back_rhj/app/__pycache__/__init__.cpython-312.pyc
+++ b/Merge/back_rhj/app/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/__pycache__/routes.cpython-312.pyc b/Merge/back_rhj/app/__pycache__/routes.cpython-312.pyc
index 696eaf4..f1d3c73 100644
--- a/Merge/back_rhj/app/__pycache__/routes.cpython-312.pyc
+++ b/Merge/back_rhj/app/__pycache__/routes.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/blueprints/__pycache__/recommend.cpython-312.pyc b/Merge/back_rhj/app/blueprints/__pycache__/recommend.cpython-312.pyc
index fc734ad..75ccdab 100644
--- a/Merge/back_rhj/app/blueprints/__pycache__/recommend.cpython-312.pyc
+++ b/Merge/back_rhj/app/blueprints/__pycache__/recommend.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/blueprints/__pycache__/scheduler.cpython-312.pyc b/Merge/back_rhj/app/blueprints/__pycache__/scheduler.cpython-312.pyc
index 57040f1..d574676 100644
--- a/Merge/back_rhj/app/blueprints/__pycache__/scheduler.cpython-312.pyc
+++ b/Merge/back_rhj/app/blueprints/__pycache__/scheduler.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/functions/__pycache__/FAuth.cpython-312.pyc b/Merge/back_rhj/app/functions/__pycache__/FAuth.cpython-312.pyc
index a806a51..6c0297b 100644
--- a/Merge/back_rhj/app/functions/__pycache__/FAuth.cpython-312.pyc
+++ b/Merge/back_rhj/app/functions/__pycache__/FAuth.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/__pycache__/__init__.cpython-312.pyc b/Merge/back_rhj/app/models/__pycache__/__init__.cpython-312.pyc
index 13b00b1..8eec580 100644
--- a/Merge/back_rhj/app/models/__pycache__/__init__.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/__pycache__/email_verification.cpython-312.pyc b/Merge/back_rhj/app/models/__pycache__/email_verification.cpython-312.pyc
index 7a02a9f..c9ad75d 100644
--- a/Merge/back_rhj/app/models/__pycache__/email_verification.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/__pycache__/email_verification.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/__pycache__/users.cpython-312.pyc b/Merge/back_rhj/app/models/__pycache__/users.cpython-312.pyc
index 1cd3627..1af05fe 100644
--- a/Merge/back_rhj/app/models/__pycache__/users.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/__pycache__/users.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recall/__pycache__/__init__.cpython-312.pyc b/Merge/back_rhj/app/models/recall/__pycache__/__init__.cpython-312.pyc
index ec1bb4b..88c8123 100644
--- a/Merge/back_rhj/app/models/recall/__pycache__/__init__.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recall/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recall/__pycache__/ad_recall.cpython-312.pyc b/Merge/back_rhj/app/models/recall/__pycache__/ad_recall.cpython-312.pyc
index 372104d..ed8dbc9 100644
--- a/Merge/back_rhj/app/models/recall/__pycache__/ad_recall.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recall/__pycache__/ad_recall.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recall/__pycache__/hot_recall.cpython-312.pyc b/Merge/back_rhj/app/models/recall/__pycache__/hot_recall.cpython-312.pyc
index de7e3f9..3cfdd43 100644
--- a/Merge/back_rhj/app/models/recall/__pycache__/hot_recall.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recall/__pycache__/hot_recall.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recall/__pycache__/multi_recall_manager.cpython-312.pyc b/Merge/back_rhj/app/models/recall/__pycache__/multi_recall_manager.cpython-312.pyc
index 0b05f7e..9e1d7c8 100644
--- a/Merge/back_rhj/app/models/recall/__pycache__/multi_recall_manager.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recall/__pycache__/multi_recall_manager.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recall/__pycache__/swing_recall.cpython-312.pyc b/Merge/back_rhj/app/models/recall/__pycache__/swing_recall.cpython-312.pyc
index 87bc373..91fa864 100644
--- a/Merge/back_rhj/app/models/recall/__pycache__/swing_recall.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recall/__pycache__/swing_recall.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recall/__pycache__/usercf_recall.cpython-312.pyc b/Merge/back_rhj/app/models/recall/__pycache__/usercf_recall.cpython-312.pyc
index e5dc324..e212bf5 100644
--- a/Merge/back_rhj/app/models/recall/__pycache__/usercf_recall.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recall/__pycache__/usercf_recall.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recall/swing_recall.py b/Merge/back_rhj/app/models/recall/swing_recall.py
index bf7fdd6..5bab5b7 100644
--- a/Merge/back_rhj/app/models/recall/swing_recall.py
+++ b/Merge/back_rhj/app/models/recall/swing_recall.py
@@ -36,7 +36,7 @@
                 WHERE type IN ('like', 'favorite', 'comment')
             """)
             interactions = cursor.fetchall()
-            
+            print(f"获取到{len(interactions)}条用户-物品交互数据")
             for user_id, post_id in interactions:
                 self.user_items[user_id].add(post_id)
                 self.item_users[post_id].add(user_id)
diff --git a/Merge/back_rhj/app/models/recommend/__pycache__/LightGCN.cpython-312.pyc b/Merge/back_rhj/app/models/recommend/__pycache__/LightGCN.cpython-312.pyc
index 48bb03f..f7079b8 100644
--- a/Merge/back_rhj/app/models/recommend/__pycache__/LightGCN.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recommend/__pycache__/LightGCN.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recommend/__pycache__/base_model.cpython-312.pyc b/Merge/back_rhj/app/models/recommend/__pycache__/base_model.cpython-312.pyc
index 204d2a7..19bf281 100644
--- a/Merge/back_rhj/app/models/recommend/__pycache__/base_model.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recommend/__pycache__/base_model.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/models/recommend/__pycache__/operators.cpython-312.pyc b/Merge/back_rhj/app/models/recommend/__pycache__/operators.cpython-312.pyc
index 4e24e5b..28de5cd 100644
--- a/Merge/back_rhj/app/models/recommend/__pycache__/operators.cpython-312.pyc
+++ b/Merge/back_rhj/app/models/recommend/__pycache__/operators.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/routes.py b/Merge/back_rhj/app/routes.py
index f123a84..6f159ca 100644
--- a/Merge/back_rhj/app/routes.py
+++ b/Merge/back_rhj/app/routes.py
@@ -1,6 +1,7 @@
 from flask import Blueprint, request, jsonify
 from .functions.FAuth import FAuth
-from .services.recommendation_service import RecommendationService
+from app.services.recommendation_service import RecommendationService
+from app.utils.graph_build import build_user_post_graph
 from sqlalchemy import create_engine
 from sqlalchemy.orm import sessionmaker
 from config import Config
@@ -17,7 +18,10 @@
     @wraps(f)
     def decorated(*args, **kwargs):
         token = request.headers.get('Authorization')
+        print(f"收到的Authorization头: {token}")
+        
         if not token:
+            print("缺少Authorization头")
             return jsonify({'success': False, 'message': '缺少访问令牌'}), 401
         
         session = None
@@ -25,22 +29,35 @@
             # 移除Bearer前缀
             if token.startswith('Bearer '):
                 token = token[7:]
+                print(f"提取的token: {token[:20]}...")
             
             engine = create_engine(Config.SQLURL)
             SessionLocal = sessionmaker(bind=engine)
             session = SessionLocal()
             f_auth = FAuth(session)
             
+            # 验证token
+            token_data = f_auth.verify_token(token)
+            print(f"Token验证结果: {token_data}")
+            
+            if not token_data:
+                print("Token验证失败 - token无效")
+                return jsonify({'success': False, 'message': '无效的访问令牌'}), 401
+            
             user = f_auth.get_user_by_token(token)
             if not user:
+                print("根据token获取用户失败")
                 return jsonify({'success': False, 'message': '无效的访问令牌'}), 401
             
+            print(f"Token验证成功,用户: {user.username}, ID: {user.id}")
+            
             # 将用户信息传递给路由函数
             return f(user, *args, **kwargs)
         except Exception as e:
+            print(f"Token验证异常: {str(e)}")
             if session:
                 session.rollback()
-            return jsonify({'success': False, 'message': '令牌验证失败'}), 401
+            return jsonify({'success': False, 'message': f'令牌验证失败: {str(e)}'}), 401
         finally:
             if session:
                 session.close()
@@ -368,12 +385,12 @@
     try:
         data = request.get_json() or {}
         user_id = data.get('user_id') or current_user.id
-        topk = data.get('topk', 10)  # 默认推荐10个
         
-        print(f"为用户 {user_id} 获取推荐,数量: {topk}")
+        print(f"为用户 {user_id} 获取个性化推荐")
         
         # 调用推荐系统
-        recommendations = recommendation_service.get_recommendations(user_id, topk)
+        user2idx, post2idx = build_user_post_graph(return_mapping=True)
+        recommendations = recommendation_service.get_recommendations(float(user_id), topk=10)
         
         return jsonify({
             'success': True,
diff --git a/Merge/back_rhj/app/services/__pycache__/lightgcn_scorer.cpython-312.pyc b/Merge/back_rhj/app/services/__pycache__/lightgcn_scorer.cpython-312.pyc
index bd899a9..5e2f64b 100644
--- a/Merge/back_rhj/app/services/__pycache__/lightgcn_scorer.cpython-312.pyc
+++ b/Merge/back_rhj/app/services/__pycache__/lightgcn_scorer.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/services/__pycache__/recommendation_service.cpython-312.pyc b/Merge/back_rhj/app/services/__pycache__/recommendation_service.cpython-312.pyc
index 0446ed2..8eac212 100644
--- a/Merge/back_rhj/app/services/__pycache__/recommendation_service.cpython-312.pyc
+++ b/Merge/back_rhj/app/services/__pycache__/recommendation_service.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/services/lightgcn_scorer.py b/Merge/back_rhj/app/services/lightgcn_scorer.py
index f6aeb19..30cddd4 100644
--- a/Merge/back_rhj/app/services/lightgcn_scorer.py
+++ b/Merge/back_rhj/app/services/lightgcn_scorer.py
@@ -121,6 +121,8 @@
             List[float]: 每个候选物品的LightGCN分数
         """
         self._initialize_model()
+        print(self.user2idx, "用户映射")
+        print(self.post2idx, "物品映射")
         
         # 检查用户是否存在
         if user_id not in self.user2idx:
diff --git a/Merge/back_rhj/app/services/recommendation_service.py b/Merge/back_rhj/app/services/recommendation_service.py
index 0547f7b..8982bd3 100644
--- a/Merge/back_rhj/app/services/recommendation_service.py
+++ b/Merge/back_rhj/app/services/recommendation_service.py
@@ -27,7 +27,7 @@
         args.data_path = './app/user_post_graph.txt'  # 修改为帖子图文件
         args.pre_model_path = './app/models/recommend/LightGCN_pretrained.pt'
         
-        self.topk = 2  # 默认推荐数量
+        self.topk = 10  # 默认推荐数量
         
         # 初始化多路召回管理器
         self.multi_recall = None
@@ -82,7 +82,7 @@
         
         return intersection / union if union > 0 else 0.0
     
-    def mmr_rerank_with_ads(self, post_ids, scores, theta=0.5, target_size=None):
+    def mmr_rerank_with_ads(self, post_ids, scores, theta=0.7, target_size=None):
         """
         使用MMR算法重新排序推荐结果,并在过程中加入广告约束
         输入:
diff --git a/Merge/back_rhj/app/user_post_graph.txt b/Merge/back_rhj/app/user_post_graph.txt
index f2f2e58..43edcc7 100644
--- a/Merge/back_rhj/app/user_post_graph.txt
+++ b/Merge/back_rhj/app/user_post_graph.txt
@@ -1,7 +1,13 @@
-0	0 0 1 0 1 0 1	1749827292 1749953091 1749953091 1749953480 1749953480 1749954059 1749954059	1 1 2 1 2 1 2
-1	1 0 3	1749827292 1749955282 1749955282	5 2 5
-2	1 0 0 1 1	1749955282 1750372189 1750372215 1750372231 1750372241	5 3 2 3 2
-3	0	1749954059	2
-4	1	1749954059	5
-5	2	1749955282	2
-6	1 3 0 3 0	1750372862 1750372873 1750373592 1750374867 1750392753	3 3 2 2 3
+0	0 0 1 2 2 1 0 0 1	1749827292 1749953091 1749953091 1749953091 1749953480 1749953480 1749953480 1749954059 1749954059	1 1 2 1 1 2 1 1 2
+1	1 4 0	1749827292 1749955282 1749955282	5 5 2
+2	2 2 1 0 0 1 1	1749953091 1749953480 1749955282 1750372189 1750372215 1750372231 1750372241	5 5 5 3 2 3 2
+3	2 2 0 2	1749953091 1749953480 1749954059 1749955282	5 5 2 1
+4	2 2 1	1749953091 1749953480 1749954059	1 1 5
+5	3	1749955282	2
+6	8 1 6 5 5	1750406052 1750410775 1750410789 1750814082 1750814094	2 2 2 2 3
+7	9	1750751914	2
+8	0	1750459840	2
+9	1 4 0 4 0 5 6 6 7 7	1750372862 1750372873 1750373592 1750374867 1750392753 1750400557 1750401552 1750401563 1750401600 1750401789	3 3 2 2 3 3 3 3 3 3
+10	6 6 8	1750405296 1750405430 1750459720	2 3 2
+11	6	1750406518	3
+12	0 0	1750438409 1750481198	2 5
diff --git a/Merge/back_rhj/app/utils/__pycache__/data_loader.cpython-312.pyc b/Merge/back_rhj/app/utils/__pycache__/data_loader.cpython-312.pyc
index 70405e3..8157bf8 100644
--- a/Merge/back_rhj/app/utils/__pycache__/data_loader.cpython-312.pyc
+++ b/Merge/back_rhj/app/utils/__pycache__/data_loader.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/utils/__pycache__/graph_build.cpython-312.pyc b/Merge/back_rhj/app/utils/__pycache__/graph_build.cpython-312.pyc
index 6fa5bc6..e1676da 100644
--- a/Merge/back_rhj/app/utils/__pycache__/graph_build.cpython-312.pyc
+++ b/Merge/back_rhj/app/utils/__pycache__/graph_build.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/utils/__pycache__/parse_args.cpython-312.pyc b/Merge/back_rhj/app/utils/__pycache__/parse_args.cpython-312.pyc
index 9295682..ba17fcf 100644
--- a/Merge/back_rhj/app/utils/__pycache__/parse_args.cpython-312.pyc
+++ b/Merge/back_rhj/app/utils/__pycache__/parse_args.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/app/utils/__pycache__/scheduler_manager.cpython-312.pyc b/Merge/back_rhj/app/utils/__pycache__/scheduler_manager.cpython-312.pyc
index 89f68ad..0f67d6a 100644
--- a/Merge/back_rhj/app/utils/__pycache__/scheduler_manager.cpython-312.pyc
+++ b/Merge/back_rhj/app/utils/__pycache__/scheduler_manager.cpython-312.pyc
Binary files differ
diff --git a/Merge/back_rhj/test_redbook_recommendation.py b/Merge/back_rhj/test_redbook_recommendation.py
index 325def5..d5dfcd3 100644
--- a/Merge/back_rhj/test_redbook_recommendation.py
+++ b/Merge/back_rhj/test_redbook_recommendation.py
@@ -120,8 +120,11 @@
         result = cursor.fetchone()
         
         if result:
-            user_id = result[0]
+            user_id = 33
+            cursor.execute("select username from users where id = %s", (user_id,))
+            username = cursor.fetchone()[0]
             print(f"测试用户ID: {user_id}")
+            print(f"测试用户名: {username}")
             
             # 查看用户的历史行为
             cursor.execute("""
@@ -250,11 +253,11 @@
     print("=" * 50)
     
     tests = [
-        test_database_connection,
+        # test_database_connection,
         test_graph_building,
-        test_cold_start_recommendation,
+        # test_cold_start_recommendation,
         test_user_recommendation,
-        test_recommendation_performance
+        # test_recommendation_performance
     ]
     
     passed = 0
diff --git a/Merge/front/src/components/PostDetailJWLLL.jsx b/Merge/front/src/components/PostDetailJWLLL.jsx
index 417105a..9304b39 100644
--- a/Merge/front/src/components/PostDetailJWLLL.jsx
+++ b/Merge/front/src/components/PostDetailJWLLL.jsx
@@ -8,7 +8,7 @@
 import MediaPreview from './MediaPreview'
 import '../style/PostDetail.css'
 import dayjs from 'dayjs'
-import { followUser, unfollowUser } from '../api/api_ljc'
+import { followUser, unfollowUser ,getUserFollowing} from '../api/api_ljc'
 
 export default function PostDetail() {
   const { id } = useParams()
@@ -67,24 +67,33 @@
   }, [id])
 
   // 检查当前用户是否已关注发帖人
-  useEffect(() => {
-    if (post && post.user_id) {
-      // 这里假设有API postsAPI.getUserFollowing
-      const checkFollow = async () => {
-        try {
-          const userInfo = getUserInfo()
-          if (!userInfo?.id) return
-          const res = await postsAPI.getUserFollowing(userInfo.id)
-          if (Array.isArray(res)) {
-            setIsFollowing(res.some(u => u.id === post.user_id))
-          } else if (Array.isArray(res.following)) {
-            setIsFollowing(res.following.some(u => u.id === post.user_id))
-          }
-        } catch {}
-      }
-      checkFollow()
-    }
-  }, [post])
+  const checkFollowStatus = useCallback(async (postUserId) => {
+  if (!postUserId) return;
+  
+  const currentUserId = getCurrentUserId();
+  if (!currentUserId) return;
+  
+  try {
+    const response = await getUserFollowing(currentUserId);
+    // 处理不同的响应结构
+    const followingList = Array.isArray(response) ? response : (response.data || []);
+    
+    console.log(response)
+    // 检查目标用户是否在关注列表中
+    setIsFollowing(
+      followingList.some(user => user.id === postUserId)
+    );
+  } catch (error) {
+    console.error('获取关注状态失败:', error);
+  }
+}, []);
+
+// 当帖子数据加载后,检查关注状态
+useEffect(() => {
+  if (post && post.user_id) {
+    checkFollowStatus(post.user_id);
+  }
+}, [post, checkFollowStatus])
 
   // 拉取发帖人信息
   useEffect(() => {
@@ -319,24 +328,24 @@
               </span>
               {/* 关注按钮 */}
               {post.user_id && (
-                <button 
-                  className={`follow-btn ${isFollowing ? 'following' : ''}`}
-                  onClick={handleFollowAction}
-                  disabled={followLoading}
-                  style={{ 
-                    marginLeft: '12px', 
-                    padding: '4px 12px', 
-                    borderRadius: '20px', 
-                    border: '1px solid #ccc', 
-                    background: isFollowing ? '#f0f0f0' : '#007bff', 
-                    color: isFollowing ? '#333' : 'white', 
-                    cursor: 'pointer',
-                    fontSize: '14px'
-                  }}
-                >
-                  {followLoading ? '处理中...' : (isFollowing ? '已关注' : '关注')}
-                </button>
-              )}
+                  <button 
+                    className={`follow-btn ${isFollowing ? 'following' : ''}`}
+                    onClick={handleFollowAction}
+                    disabled={followLoading}
+                    style={{ 
+                      marginLeft: '12px', 
+                      padding: '4px 12px', 
+                      borderRadius: '20px', 
+                      border: '1px solid #ccc', 
+                      background: isFollowing ? '#f0f0f0' : '#007bff', 
+                      color: isFollowing ? '#333' : 'white', 
+                      cursor: 'pointer',
+                      fontSize: '14px'
+                    }}
+                  >
+                    {followLoading ? '处理中...' : (isFollowing ? '已关注' : '关注')}
+                  </button>
+                )}
             </div>
           </div>
           <div className="post-stats">