diff --git a/web/src/components/Analytics.tsx b/web/src/components/Analytics.tsx index 78ff47e..ad4f749 100644 --- a/web/src/components/Analytics.tsx +++ b/web/src/components/Analytics.tsx @@ -118,6 +118,26 @@ interface KOLOverviewResponse { error?: string; } +// 添加概览卡片API响应接口 +interface DashboardCardsResponse { + success: boolean; + data: { + comments_count: { + current: number; + change_percentage: number; + }; + engagement_rate: { + current: number; + change_percentage: number; + }; + sentiment_score: { + current: number; + change_percentage: number; + }; + }; + error?: string; +} + const Analytics: React.FC = () => { const [timeRange, setTimeRange] = useState('30'); // 修改默认值为'30'与API匹配 const [selectedKOL, setSelectedKOL] = useState('all'); @@ -170,6 +190,19 @@ const Analytics: React.FC = () => { const [trackingSuccess, setTrackingSuccess] = useState(null); const [trackingError, setTrackingError] = useState(null); + // 添加概览卡片数据状态 + const [dashboardCards, setDashboardCards] = useState<{ + commentsCount: { current: number; changePercentage: number }; + engagementRate: { current: number; changePercentage: number }; + sentimentScore: { current: number; changePercentage: number }; + }>({ + commentsCount: { current: 0, changePercentage: 0 }, + engagementRate: { current: 0, changePercentage: 0 }, + sentimentScore: { current: 0, changePercentage: 0 } + }); + const [cardsLoading, setCardsLoading] = useState(true); + const [cardsError, setCardsError] = useState(null); + // 获取KOL概览数据 const fetchKolOverviewData = async () => { setKolLoading(true); @@ -245,6 +278,9 @@ const Analytics: React.FC = () => { // 获取贴文表现数据 fetchPostPerformanceData(); + // 获取概览卡片数据 + fetchDashboardCards(); + const fetchAnalyticsData = async () => { try { setLoading(true); @@ -802,6 +838,98 @@ const Analytics: React.FC = () => { ); + // 获取概览卡片数据 + const fetchDashboardCards = async () => { + try { + setCardsLoading(true); + setCardsError(null); + + // 构建API URL + let url = `http://localhost:4000/api/analytics/dashboard-cards`; + + // 添加时间范围参数 + if (timeRange) { + url += `?timeRange=${timeRange}`; + } + + // 添加项目过滤参数(如果选择了特定项目) + if (selectedProject !== 'all') { + url += `${timeRange ? '&' : '?'}projectId=${selectedProject}`; + } + + // 添加平台过滤参数(如果选择了特定平台) + if (selectedPlatform !== 'all') { + url += `${(timeRange || selectedProject !== 'all') ? '&' : '?'}platform=${selectedPlatform}`; + } + + console.log('请求概览卡片数据URL:', url); + + // 添加认证头 + const authToken = 'eyJhbGciOiJIUzI1NiIsImtpZCI6Inl3blNGYnRBOGtBUnl4UmUiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3h0cWhsdXpvcm5hemxta29udWNyLnN1cGFiYXNlLmNvL2F1dGgvdjEiLCJzdWIiOiI1YjQzMThiZi0yMWE4LTQ3YWMtOGJmYS0yYThmOGVmOWMwZmIiLCJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNzQxNjI3ODkyLCJpYXQiOjE3NDE2MjQyOTIsImVtYWlsIjoidml0YWxpdHltYWlsZ0BnbWFpbC5jb20iLCJwaG9uZSI6IiIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6ImVtYWlsIiwicHJvdmlkZXJzIjpbImVtYWlsIl19LCJ1c2VyX21ldGFkYXRhIjp7ImVtYWlsX3ZlcmlmaWVkIjp0cnVlfSwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJwYXNzd29yZCIsInRpbWVzdGFtcCI6MTc0MTYyNDI5Mn1dLCJzZXNzaW9uX2lkIjoiODlmYjg0YzktZmEzYy00YmVlLTk0MDQtNjI1MjE0OGIyMzVlIiwiaXNfYW5vbnltb3VzIjpmYWxzZX0.VuUX2yhqN-FZseKL8fQG91i1cohfRqW2m1Z8CIWhZuk'; + + const response = await fetch(url, { + headers: { + 'accept': 'application/json', + 'Authorization': `Bearer ${authToken}` + } + }); + + if (response.ok) { + const result = await response.json() as DashboardCardsResponse; + console.log('成功获取概览卡片数据:', result); + + if (result.success) { + // 更新状态 + setDashboardCards({ + commentsCount: { + current: result.data.comments_count.current, + changePercentage: result.data.comments_count.change_percentage + }, + engagementRate: { + current: result.data.engagement_rate.current, + changePercentage: result.data.engagement_rate.change_percentage + }, + sentimentScore: { + current: result.data.sentiment_score.current, + changePercentage: result.data.sentiment_score.change_percentage + } + }); + + // 更新情感分析数据 - 基于情感分数计算正面、中性、负面比例 + const sentimentScore = result.data.sentiment_score.current; + // 假设情感分数范围是0-1,0是负面,0.5是中性,1是正面 + // 根据情感分数生成模拟的正面、中性、负面百分比 + const positive = Math.round(Math.min(1, Math.max(0, sentimentScore)) * 100); + const negative = Math.round(Math.min(1, Math.max(0, 1 - sentimentScore)) * 100); + const neutral = Math.max(0, 100 - positive - negative); + + setSentimentData({ + positive, + neutral, + negative + }); + + // 如果API返回了模拟数据标志 + if ('is_mock_data' in result && result.is_mock_data) { + console.info('注意: 使用的是模拟概览卡片数据'); + } + } else { + setCardsError(result.error || '获取概览卡片数据失败'); + console.error('API调用失败:', result.error || '未知错误'); + } + } else { + const errorText = await response.text(); + setCardsError(`获取失败 (${response.status}): ${errorText}`); + console.error('获取概览卡片数据失败,HTTP状态:', response.status, errorText); + } + } catch (error) { + setCardsError(`获取概览卡片数据时发生错误: ${error instanceof Error ? error.message : String(error)}`); + console.error('获取概览卡片数据时发生错误:', error); + } finally { + setCardsLoading(false); + } + }; + return (
@@ -1250,11 +1378,30 @@ const Analytics: React.FC = () => {

留言总数

-

{platformData.reduce((sum, item) => sum + item.value, 0)}

-
- - ↑ 12% 较上周 -
+ {cardsLoading ? ( +
+
+
+ ) : cardsError ? ( +
{cardsError}
+ ) : ( + <> +

{dashboardCards.commentsCount.current.toLocaleString()}

+
+ {dashboardCards.commentsCount.changePercentage > 0 ? ( + <> + + ↑ {dashboardCards.commentsCount.changePercentage.toFixed(1)}% 较上周 + + ) : ( + <> + + ↓ {Math.abs(dashboardCards.commentsCount.changePercentage).toFixed(1)}% 较上周 + + )} +
+ + )}
@@ -1262,11 +1409,30 @@ const Analytics: React.FC = () => {

平均互动率

-

4.8%

-
- - ↑ 0.5% 较上周 -
+ {cardsLoading ? ( +
+
+
+ ) : cardsError ? ( +
{cardsError}
+ ) : ( + <> +

{(dashboardCards.engagementRate.current / 100).toFixed(1)}%

+
+ {dashboardCards.engagementRate.changePercentage > 0 ? ( + <> + + ↑ {dashboardCards.engagementRate.changePercentage.toFixed(1)}% 较上周 + + ) : ( + <> + + ↓ {Math.abs(dashboardCards.engagementRate.changePercentage).toFixed(1)}% 较上周 + + )} +
+ + )}
@@ -1274,11 +1440,30 @@ const Analytics: React.FC = () => {

情感分析

-

{sentimentData.positive}% 正面

-
- - ↑ 5% 较上周 -
+ {cardsLoading ? ( +
+
+
+ ) : cardsError ? ( +
{cardsError}
+ ) : ( + <> +

{sentimentData.positive}% 正面

+
+ {dashboardCards.sentimentScore.changePercentage > 0 ? ( + <> + + ↑ {dashboardCards.sentimentScore.changePercentage.toFixed(1)}% 较上周 + + ) : ( + <> + + ↓ {Math.abs(dashboardCards.sentimentScore.changePercentage).toFixed(1)}% 较上周 + + )} +
+ + )}