补充

Change-Id: I058b37511bf75593587009fabaebaa7b11ad7aed
diff --git a/Merge/front/src/api/recommend_rhj.js b/Merge/front/src/api/recommend_rhj.js
new file mode 100644
index 0000000..34d9164
--- /dev/null
+++ b/Merge/front/src/api/recommend_rhj.js
@@ -0,0 +1,20 @@
+// RHJ 深度推荐接口
+import { getAuthToken } from '../utils/auth'
+const RHJ_BASE_URL = 'http://10.126.59.25:8082' // 端口已修正
+
+export async function deepRecommend(userId, topk = 10) {
+  const token = getAuthToken()
+  const headers = {
+    'Content-Type': 'application/json',
+    ...(token ? { 'Authorization': `Bearer ${token}` } : {})
+  }
+  const res = await fetch(`${RHJ_BASE_URL}/recommend`, {
+    method: 'POST',
+    headers,
+    body: JSON.stringify({ user_id: userId, topk })
+  })
+  if (!res.ok) throw new Error('深度推荐接口调用失败')
+  const data = await res.json()
+  // 兼容接口返回格式
+  return data.data?.recommendations || []
+}
diff --git a/Merge/front/src/components/HomeFeed.jsx b/Merge/front/src/components/HomeFeed.jsx
index cc37642..1fb12a5 100644
--- a/Merge/front/src/components/HomeFeed.jsx
+++ b/Merge/front/src/components/HomeFeed.jsx
@@ -6,6 +6,7 @@
 import { fetchPosts, fetchPost } from '../api/posts_wzy'
 import { searchAPI } from '../api/search_jwlll'
 import { getUserInfo } from '../utils/auth'
+import { deepRecommend } from '../api/recommend_rhj'
 import '../style/HomeFeed.css'
 
 const categories = [
@@ -15,7 +16,8 @@
 
 const recommendModes = [
   { label: '标签推荐', value: 'tag' },
-  { label: '协同过滤推荐', value: 'cf' }
+  { label: '协同过滤推荐', value: 'cf' },
+  { label: '深度推荐', value: 'deep' } // 新增
 ]
 
 const DEFAULT_USER_ID = '3' // 确保数据库有此用户(作为回退值)
@@ -69,16 +71,35 @@
     try {
       const currentUserId = getCurrentUserId()
       const data = await searchAPI.recommendByTags(currentUserId, tags)
-      const formattedItems = (data.recommendations || []).map(item => ({
-        id: item.id,
-        title: item.title,
-        author: item.author || '佚名',
-        avatar: `https://i.pravatar.cc/40?img=${item.id}`,
-        img: item.img || '', 
-        likes: item.heat || 0,
-        content: item.content
-      }))
-      setItems(formattedItems)
+      // 新增:拉取详情,保证和原始数据一致
+      const detailed = await Promise.all(
+        (data.recommendations || []).map(async item => {
+          try {
+            const d = await fetchPost(item.id)
+            return {
+              id:     d.id,
+              title:  d.title,
+              author: `作者 ${d.user_id}`,
+              avatar: `https://i.pravatar.cc/40?img=${d.user_id}`,
+              img:    d.media_urls?.[0] || '',
+              likes:  d.heat,
+              content: d.content || ''
+            }
+          } catch {
+            // 拉详情失败时兜底
+            return {
+              id: item.id,
+              title: item.title,
+              author: item.author || '佚名',
+              avatar: `https://i.pravatar.cc/40?img=${item.id}`,
+              img: item.img || '',
+              likes: item.heat || 0,
+              content: item.content || ''
+            }
+          }
+        })
+      )
+      setItems(detailed)
     } catch (e) {
       console.error('标签推荐失败:', e)
       setError('标签推荐失败')
@@ -93,16 +114,35 @@
     try {
       const currentUserId = getCurrentUserId()
       const data = await searchAPI.userBasedRecommend(currentUserId, topN)
-      const formattedItems = (data.recommendations || []).map(item => ({
-        id: item.id,
-        title: item.title,
-        author: item.author || '佚名',
-        avatar: `https://i.pravatar.cc/40?img=${item.id}`,
-        img: item.img || '', 
-        likes: item.heat || 0,
-        content: item.content
-      }))
-      setItems(formattedItems)
+      // 新增:拉取详情,保证和原始数据一致
+      const detailed = await Promise.all(
+        (data.recommendations || []).map(async item => {
+          try {
+            const d = await fetchPost(item.id)
+            return {
+              id:     d.id,
+              title:  d.title,
+              author: `作者 ${d.user_id}`,
+              avatar: `https://i.pravatar.cc/40?img=${d.user_id}`,
+              img:    d.media_urls?.[0] || '',
+              likes:  d.heat,
+              content: d.content || ''
+            }
+          } catch {
+            // 拉详情失败时兜底
+            return {
+              id: item.id,
+              title: item.title,
+              author: item.author || '佚名',
+              avatar: `https://i.pravatar.cc/40?img=${item.id}`,
+              img: item.img || '',
+              likes: item.heat || 0,
+              content: item.content || ''
+            }
+          }
+        })
+      )
+      setItems(detailed)
     } catch (e) {
       console.error('协同过滤推荐失败:', e)
       setError('协同过滤推荐失败')
@@ -110,6 +150,47 @@
     }
     setLoading(false)
   }, [recCFNum])
+  // 深度推荐
+  const fetchDeepRecommend = useCallback(async (topN = 20) => {
+    setLoading(true)
+    setError(null)
+    try {
+      const currentUserId = getCurrentUserId()
+      const recs = await deepRecommend(currentUserId, topN)
+      // 拉取详情,保证和原始数据一致
+      const detailed = await Promise.all(
+        (recs || []).map(async item => {
+          try {
+            const d = await fetchPost(item.id)
+            return {
+              id:     d.id,
+              title:  d.title,
+              author: `作者 ${d.user_id}`,
+              avatar: `https://i.pravatar.cc/40?img=${d.user_id}`,
+              img:    d.media_urls?.[0] || '',
+              likes:  d.heat,
+              content: d.content || ''
+            }
+          } catch {
+            return {
+              id: item.id,
+              title: item.title,
+              author: item.author || '佚名',
+              avatar: `https://i.pravatar.cc/40?img=${item.id}`,
+              img: item.img || '',
+              likes: item.heat || 0,
+              content: item.content || ''
+            }
+          }
+        })
+      )
+      setItems(detailed)
+    } catch (e) {
+      setError('深度推荐失败')
+      setItems([])
+    }
+    setLoading(false)
+  }, [])
   // 获取用户兴趣标签后再推荐
   const fetchUserTagsAndRecommend = useCallback(async () => {
     setLoading(true)
@@ -124,11 +205,13 @@
     }
     if (recMode === 'tag') {
       await fetchTagRecommend(tags)
-    } else {
+    } else if (recMode === 'cf') {
       await fetchCFRecommend()
+    } else if (recMode === 'deep') {
+      await fetchDeepRecommend()
     }
     setLoading(false)
-  }, [recMode, fetchTagRecommend, fetchCFRecommend])
+  }, [recMode, fetchTagRecommend, fetchCFRecommend, fetchDeepRecommend])
 
   useEffect(() => {
     // 原始数据加载函数
diff --git a/Merge/front/src/components/Sidebar.jsx b/Merge/front/src/components/Sidebar.jsx
index e35db63..b0453e4 100644
--- a/Merge/front/src/components/Sidebar.jsx
+++ b/Merge/front/src/components/Sidebar.jsx
@@ -1,32 +1,15 @@
-import React, { useState, useEffect } from 'react'
+import React, { useState } from 'react'
 import { NavLink, useLocation, useNavigate } from 'react-router-dom'
 import {
   Home,
   BookOpen,
-  BarChart3,
-  Activity,
-  Users,
   ChevronDown,
-  Search,
-  Upload,
 } from 'lucide-react'
 import '../App.css'
 
 const menuItems = [
   { id: 'home',      label: '首页',       icon: Home,      path: '/home' },
   { id: 'notebooks', label: '笔记管理',   icon: BookOpen,  path: '/notebooks' },
-  {
-    id: 'dashboard',
-    label: '数据看板',
-    icon: BarChart3,
-    path: '/dashboard',
-    submenu: [
-      { id: 'overview', label: '账号概况', path: '/dashboard/overview' },
-      { id: 'content',  label: '内容分析', path: '/dashboard/content'  },
-      { id: 'fans',     label: '粉丝数据', path: '/dashboard/fans'     },
-    ]
-  },
-  { id: 'upload-jwlll', label: '智能发布', icon: Upload, path: '/upload-jwlll' },
   // { id: 'activity', label: '活动中心', icon: Activity, path: '/activity' },
   // { id: 'notes',    label: '笔记灵感', icon: BookOpen, path: '/notes'    },
   // { id: 'creator',  label: '创作学院', icon: Users,    path: '/creator'  },
@@ -38,13 +21,6 @@
   const location = useLocation()
   const navigate = useNavigate()
 
-  // 打开 dashboard 下拉时保持展开
-  useEffect(() => {
-    if (location.pathname.startsWith('/dashboard')) {
-      setExpandedMenu('dashboard')
-    }
-  }, [location.pathname])
-
   const toggleMenu = item => {
     if (item.submenu) {
       setExpandedMenu(expandedMenu === item.id ? null : item.id)