diff --git a/web/src/components/Analytics.tsx b/web/src/components/Analytics.tsx index 915d9b7..b158c11 100644 --- a/web/src/components/Analytics.tsx +++ b/web/src/components/Analytics.tsx @@ -51,6 +51,10 @@ interface Article { views: number; engagement: number; platform: string; + influencer?: string; + date?: string; + engagementRate?: number; + isHighEngagement?: boolean; } interface EngagementData { @@ -189,6 +193,26 @@ interface CommentTrendResponse { error?: string; } +// 添加热门文章API响应接口 +interface PopularPostsResponse { + success: boolean; + data: { + title: string; + platform: string; + influencer_name: string; + publish_date: string; + engagement_count: number; + views_count: number; + engagement_rate: number; + is_high_engagement: boolean; + }[]; + metadata: { + total: number; + high_engagement_count: number; + }; + error?: string; +} + const Analytics: React.FC = () => { const [timeRange, setTimeRange] = useState('30'); // 修改默认值为'30'与API匹配 const [selectedKOL, setSelectedKOL] = useState('all'); @@ -263,6 +287,9 @@ const Analytics: React.FC = () => { const [sentimentError, setSentimentError] = useState(null); const [sentimentScore, setSentimentScore] = useState(0); + const [postsLoading, setPostsLoading] = useState(true); + const [postsError, setPostsError] = useState(null); + // 获取KOL概览数据 const fetchKolOverviewData = async () => { setKolLoading(true); @@ -350,12 +377,17 @@ const Analytics: React.FC = () => { // 获取情感分析数据 fetchSentimentAnalysis(); + // 获取热门文章数据 + fetchPopularPosts(); + const fetchAnalyticsData = async () => { try { setLoading(true); // 删除平台分布的硬编码数据,使用API数据替代 + // 删除情感分析的硬编码数据,使用API数据替代 + // Set mock status data setStatusData([ { name: 'approved', value: 45, color: '#10B981' }, @@ -363,14 +395,14 @@ const Analytics: React.FC = () => { { name: 'rejected', value: 25, color: '#EF4444' } ]); - // Set mock popular articles - setPopularArticles([ - { id: '1', title: 'How to Increase Engagement', views: 1200, engagement: 85, platform: 'Facebook' }, - { id: '2', title: 'Top 10 Marketing Strategies', views: 980, engagement: 72, platform: 'LinkedIn' }, - { id: '3', title: 'Social Media in 2023', views: 850, engagement: 68, platform: 'Twitter' }, - { id: '4', title: 'Building Your Brand Online', views: 750, engagement: 63, platform: 'Instagram' }, - { id: '5', title: 'Content Creation Tips', views: 620, engagement: 57, platform: 'YouTube' } - ]); + // 删除热门文章的硬编码数据,使用API数据替代 + // setPopularArticles([ + // { id: '1', title: 'How to Increase Engagement', views: 1200, engagement: 85, platform: 'Facebook' }, + // { id: '2', title: 'Top 10 Marketing Strategies', views: 980, engagement: 72, platform: 'LinkedIn' }, + // { id: '3', title: 'Social Media in 2023', views: 850, engagement: 68, platform: 'Twitter' }, + // { id: '4', title: 'Building Your Brand Online', views: 750, engagement: 63, platform: 'Instagram' }, + // { id: '5', title: 'Content Creation Tips', views: 620, engagement: 57, platform: 'YouTube' } + // ]); // 从API获取漏斗数据 try { @@ -1212,6 +1244,79 @@ const Analytics: React.FC = () => { } }; + // 获取热门文章数据 + const fetchPopularPosts = async () => { + try { + setPostsLoading(true); + setPostsError(null); + + // 构建热门文章API URL + const url = `http://localhost:4000/api/analytics/popular-posts?timeRange=${timeRange}`; + + // 添加项目过滤参数(如果选择了特定项目) + const urlWithFilters = selectedProject !== 'all' + ? `${url}&projectId=${selectedProject}` + : url; + + // 添加平台过滤参数(如果选择了特定平台) + const finalUrl = selectedPlatform !== 'all' + ? `${urlWithFilters}&platform=${selectedPlatform}` + : urlWithFilters; + + console.log('请求热门文章数据URL:', finalUrl); + + // 添加认证头 + const authToken = 'eyJhbGciOiJIUzI1NiIsImtpZCI6Inl3blNGYnRBOGtBUnl4UmUiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3h0cWhsdXpvcm5hemxta29udWNyLnN1cGFiYXNlLmNvL2F1dGgvdjEiLCJzdWIiOiI1YjQzMThiZi0yMWE4LTQ3YWMtOGJmYS0yYThmOGVmOWMwZmIiLCJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNzQxNjI3ODkyLCJpYXQiOjE3NDE2MjQyOTIsImVtYWlsIjoidml0YWxpdHltYWlsZ0BnbWFpbC5jb20iLCJwaG9uZSI6IiIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6ImVtYWlsIiwicHJvdmlkZXJzIjpbImVtYWlsIl19LCJ1c2VyX21ldGFkYXRhIjp7ImVtYWlsX3ZlcmlmaWVkIjp0cnVlfSwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJwYXNzd29yZCIsInRpbWVzdGFtcCI6MTc0MTYyNDI5Mn1dLCJzZXNzaW9uX2lkIjoiODlmYjg0YzktZmEzYy00YmVlLTk0MDQtNjI1MjE0OGIyMzVlIiwiaXNfYW5vbnltb3VzIjpmYWxzZX0.VuUX2yhqN-FZseKL8fQG91i1cohfRqW2m1Z8CIWhZuk'; + + const response = await fetch(finalUrl, { + headers: { + 'accept': 'application/json', + 'Authorization': `Bearer ${authToken}` + } + }); + + if (response.ok) { + const result = await response.json() as PopularPostsResponse; + console.log('成功获取热门文章数据:', result); + + if (result.success) { + // 将API返回的数据映射到Article结构 + const mappedData = result.data.map((post, index) => ({ + id: `post-${index}`, + title: post.title, + views: post.views_count, + engagement: post.engagement_count, + platform: post.platform, + influencer: post.influencer_name, + date: new Date(post.publish_date).toLocaleDateString('zh-CN'), + engagementRate: post.engagement_rate, + isHighEngagement: post.is_high_engagement + })); + + // 更新状态 + setPopularArticles(mappedData); + + // 如果API返回了模拟数据标志 + if ('is_mock_data' in result && result.is_mock_data) { + console.info('注意: 使用的是模拟热门文章数据'); + } + } else { + setPostsError(result.error || '获取热门文章数据失败'); + console.error('API调用失败:', result.error || '未知错误'); + } + } else { + const errorText = await response.text(); + setPostsError(`获取失败 (${response.status}): ${errorText}`); + console.error('获取热门文章数据失败,HTTP状态:', response.status, errorText); + } + } catch (error) { + setPostsError(`获取热门文章数据时发生错误: ${error instanceof Error ? error.message : String(error)}`); + console.error('获取热门文章数据时发生错误:', error); + } finally { + setPostsLoading(false); + } + }; + return (
@@ -1931,22 +2036,55 @@ const Analytics: React.FC = () => {
{/* 热门文章 */} -
+

热门文章

-
- {popularArticles.map((article: any, index: number) => ( -
-

{article.title}

-
- {article.count} 则留言 -
-
- 高互动 + {postsLoading ? ( +
+
+

加载热门文章数据中...

+
+ ) : postsError ? ( +
+ +

{postsError}

+
+ ) : popularArticles.length === 0 ? ( +
+ +

没有找到热门文章数据

+
+ ) : ( +
+ {popularArticles.map((article, index) => ( +
+

{article.title}

+
+
+ + {article.influencer || '匿名创作者'} | {article.platform || '未知平台'} | {article.date || '未知日期'} + +
+
+
+ + {article.views.toLocaleString()} 浏览 +
+
+ + {article.engagement.toLocaleString()} 互动 +
+ {article.isHighEngagement && ( +
+
+ 高互动 +
+ )} +
-
- ))} -
+ ))} +
+ )}
)}