修改管理者數據分析數據

This commit is contained in:
2025-09-19 08:57:16 +08:00
parent 753e32ada2
commit 04f685ec0c
3 changed files with 445 additions and 157 deletions

View File

@@ -32,40 +32,51 @@ export function AnalyticsDashboard() {
totalApps: 0,
newThisWeek: 0,
userGrowth: 0,
userGrowthText: "較上月",
dailyUsageData: [],
categoryData: [],
topApps: [],
hourlyData: [],
satisfactionRate: 0,
weeklyFeedback: 0
weeklyFeedback: 0,
userAvgRating: 0,
totalRatings: 0,
systemLoadStatus: "normal",
systemLoadAdvice: "",
maxCpuPeak: 0,
maxDailyUsers: 0,
avgDailyUsers: 0,
totalWeeklySessions: 0,
hourlyAnalysis: "",
hourlyAdvice: ""
})
// 24小時使用數據 - 優化版本
const hourlyData = [
{ hour: "00", users: 39, period: "深夜", intensity: "low", cpuUsage: 25, memoryUsage: 45 },
{ hour: "01", users: 62, period: "深夜", intensity: "normal", cpuUsage: 22, memoryUsage: 43 },
{ hour: "02", users: 24, period: "深夜", intensity: "low", cpuUsage: 20, memoryUsage: 41 },
{ hour: "03", users: 40, period: "深夜", intensity: "low", cpuUsage: 18, memoryUsage: 40 },
{ hour: "04", users: 40, period: "深夜", intensity: "low", cpuUsage: 17, memoryUsage: 39 },
{ hour: "05", users: 55, period: "清晨", intensity: "normal", cpuUsage: 19, memoryUsage: 41 },
{ hour: "06", users: 26, period: "清晨", intensity: "low", cpuUsage: 28, memoryUsage: 48 },
{ hour: "07", users: 67, period: "清晨", intensity: "normal", cpuUsage: 35, memoryUsage: 52 },
{ hour: "08", users: 26, period: "工作時間", intensity: "normal", cpuUsage: 42, memoryUsage: 58 },
{ hour: "09", users: 89, period: "工作時間", intensity: "high", cpuUsage: 58, memoryUsage: 68 },
{ hour: "10", users: 88, period: "工作時間", intensity: "high", cpuUsage: 65, memoryUsage: 72 },
{ hour: "11", users: 129, period: "工作時間", intensity: "peak", cpuUsage: 72, memoryUsage: 76 },
{ hour: "12", users: 106, period: "工作時間", intensity: "peak", cpuUsage: 62, memoryUsage: 70 },
{ hour: "13", users: 105, period: "工作時間", intensity: "peak", cpuUsage: 68, memoryUsage: 74 },
{ hour: "14", users: 81, period: "工作時間", intensity: "high", cpuUsage: 78, memoryUsage: 82 },
{ hour: "15", users: 119, period: "工作時間", intensity: "peak", cpuUsage: 74, memoryUsage: 79 },
{ hour: "16", users: 126, period: "工作時間", intensity: "peak", cpuUsage: 67, memoryUsage: 73 },
{ hour: "17", users: 112, period: "工作時間", intensity: "peak", cpuUsage: 59, memoryUsage: 67 },
{ hour: "18", users: 22, period: "晚間", intensity: "low", cpuUsage: 45, memoryUsage: 58 },
{ hour: "19", users: 60, period: "晚間", intensity: "normal", cpuUsage: 38, memoryUsage: 53 },
{ hour: "20", users: 32, period: "晚間", intensity: "low", cpuUsage: 33, memoryUsage: 50 },
{ hour: "21", users: 22, period: "晚間", intensity: "low", cpuUsage: 29, memoryUsage: 47 },
{ hour: "22", users: 36, period: "晚間", intensity: "low", cpuUsage: 26, memoryUsage: 46 },
{ hour: "23", users: 66, period: "晚間", intensity: "normal", cpuUsage: 24, memoryUsage: 44 },
]
// 載入分析數據
const loadAnalyticsData = async () => {
try {
setIsLoading(true)
const response = await fetch('/api/admin/analytics')
const data = await response.json()
if (data.success) {
setAnalyticsData(data.data)
} else {
console.error('載入分析數據失敗:', data.error)
}
} catch (error) {
console.error('載入分析數據錯誤:', error)
} finally {
setIsLoading(false)
}
}
// 初始載入數據
useEffect(() => {
loadAnalyticsData()
}, [])
// 使用API提供的24小時使用數據
const hourlyData = analyticsData.hourlyData || []
// 獲取顏色基於使用強度
const getBarColor = (intensity: string) => {
@@ -126,38 +137,28 @@ export function AnalyticsDashboard() {
{ name: "文本分析工具", views: 692, rating: 4.4, category: "AI工具" },
]
// 獲取歷史數據
// 獲取歷史數據 - 使用真實數據
const getHistoricalData = (range: string) => {
const baseData = [
{ date: "12/1", users: 180, cpuPeak: 55, fullDate: "2024/12/1" },
{ date: "12/8", users: 210, cpuPeak: 62, fullDate: "2024/12/8" },
{ date: "12/15", users: 245, cpuPeak: 68, fullDate: "2024/12/15" },
{ date: "12/22", users: 280, cpuPeak: 74, fullDate: "2024/12/22" },
{ date: "12/29", users: 320, cpuPeak: 78, fullDate: "2024/12/29" },
{ date: "1/5", users: 298, cpuPeak: 73, fullDate: "2025/1/5" },
{ date: "1/12", users: 334, cpuPeak: 79, fullDate: "2025/1/12" },
{ date: "1/19", users: 356, cpuPeak: 82, fullDate: "2025/1/19" },
]
switch (range) {
case "近7天":
return dailyUsageData
case "近30天":
return baseData.slice(-4)
case "近3個月":
return baseData.slice(-6)
case "近6個月":
return baseData
default:
return dailyUsageData
}
// 所有時間範圍都使用真實的 dailyUsageData
// 因為我們已經在API中獲取了近7天的真實數據
return analyticsData.dailyUsageData || []
}
// 獲取歷史統計數據
// 獲取歷史統計數據 - 使用真實數據
const getHistoricalStats = (range: string) => {
const data = getHistoricalData(range)
const users = data.map((d) => d.users)
const cpus = data.map((d) => d.cpuPeak)
if (!data || data.length === 0) {
return {
avgUsers: 0,
maxUsers: 0,
avgCpu: 0,
maxCpu: 0,
}
}
const users = data.map((d) => d.users || 0)
const cpus = data.map((d) => d.cpuPeak || 0)
return {
avgUsers: Math.round(users.reduce((a, b) => a + b, 0) / users.length),
@@ -171,10 +172,21 @@ export function AnalyticsDashboard() {
<div className="p-6 space-y-6">
<div className="flex items-center justify-between">
<h1 className="text-3xl font-bold"></h1>
<Badge variant="outline" className="text-sm">
<div className="flex items-center gap-2">
<Button
variant="outline"
size="sm"
onClick={loadAnalyticsData}
disabled={isLoading}
>
{isLoading ? (
<Loader2 className="w-4 h-4 mr-1 animate-spin" />
) : (
<Activity className="w-4 h-4 mr-1" />
)}
</Badge>
</Button>
</div>
</div>
{/* 關鍵指標卡片 */}
@@ -185,9 +197,21 @@ export function AnalyticsDashboard() {
<Users className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">2,847</div>
<div className="text-2xl font-bold">
{isLoading ? (
<Loader2 className="w-6 h-6 animate-spin" />
) : (
analyticsData.totalUsers.toLocaleString()
)}
</div>
<p className="text-xs text-muted-foreground">
<span className="text-green-600">+12.5%</span>
{isLoading ? (
"載入中..."
) : (
<>
<span className="text-green-600">+{analyticsData.userGrowth}%</span> {analyticsData.userGrowthText}
</>
)}
</p>
</CardContent>
</Card>
@@ -198,9 +222,21 @@ export function AnalyticsDashboard() {
<Eye className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">356</div>
<div className="text-2xl font-bold">
{isLoading ? (
<Loader2 className="w-6 h-6 animate-spin" />
) : (
analyticsData.todayActiveUsers
)}
</div>
<p className="text-xs text-muted-foreground">
<span className="text-green-600">+8.2%</span>
{isLoading ? (
"載入中..."
) : (
<>
<span className="text-green-600">+{analyticsData.todayActiveGrowth}%</span>
</>
)}
</p>
</CardContent>
</Card>
@@ -211,9 +247,21 @@ export function AnalyticsDashboard() {
<Star className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">4.6</div>
<div className="text-2xl font-bold">
{isLoading ? (
<Loader2 className="w-6 h-6 animate-spin" />
) : (
analyticsData.avgRating
)}
</div>
<p className="text-xs text-muted-foreground">
<span className="text-green-600">+0.3</span>
{isLoading ? (
"載入中..."
) : (
<>
<span className="text-green-600">+{analyticsData.ratingGrowth}</span>
</>
)}
</p>
</CardContent>
</Card>
@@ -224,9 +272,21 @@ export function AnalyticsDashboard() {
<TrendingUp className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">127</div>
<div className="text-2xl font-bold">
{isLoading ? (
<Loader2 className="w-6 h-6 animate-spin" />
) : (
analyticsData.totalApps
)}
</div>
<p className="text-xs text-muted-foreground">
<span className="text-green-600">+5</span>
{isLoading ? (
"載入中..."
) : (
<>
<span className="text-green-600">+{analyticsData.newThisWeek}</span>
</>
)}
</p>
</CardContent>
</Card>
@@ -251,7 +311,7 @@ export function AnalyticsDashboard() {
</CardHeader>
<CardContent>
<ResponsiveContainer width="100%" height={320}>
<ComposedChart data={dailyUsageData}>
<ComposedChart data={analyticsData.dailyUsageData}>
<defs>
<linearGradient id="colorUsers" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#3b82f6" stopOpacity={0.3} />
@@ -319,14 +379,56 @@ export function AnalyticsDashboard() {
</ComposedChart>
</ResponsiveContainer>
{/* 系統建議 */}
<div className="mt-4 p-3 bg-orange-50 rounded-lg border border-orange-200">
{/* 系統建議 - 動態狀態 */}
<div className={`mt-4 p-3 rounded-lg border ${
analyticsData.systemLoadStatus === 'critical'
? 'bg-red-50 border-red-200'
: analyticsData.systemLoadStatus === 'warning'
? 'bg-orange-50 border-orange-200'
: analyticsData.systemLoadStatus === 'monitor'
? 'bg-blue-50 border-blue-200'
: analyticsData.systemLoadStatus === 'low'
? 'bg-yellow-50 border-yellow-200'
: 'bg-gray-50 border-gray-200'
}`}>
<div className="flex items-start gap-2">
{analyticsData.systemLoadStatus === 'critical' ? (
<AlertTriangle className="w-5 h-5 text-red-600 mt-0.5 flex-shrink-0" />
) : analyticsData.systemLoadStatus === 'warning' ? (
<AlertTriangle className="w-5 h-5 text-orange-600 mt-0.5 flex-shrink-0" />
) : analyticsData.systemLoadStatus === 'monitor' ? (
<Activity className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
) : analyticsData.systemLoadStatus === 'low' ? (
<TrendingUp className="w-5 h-5 text-yellow-600 mt-0.5 flex-shrink-0" />
) : (
<AlertTriangle className="w-5 h-5 text-gray-600 mt-0.5 flex-shrink-0" />
)}
<div>
<p className="text-sm font-medium text-orange-800"></p>
<p className="text-sm text-orange-700 mt-1">
7CPU峰值達82%350
<p className={`text-sm font-medium ${
analyticsData.systemLoadStatus === 'critical'
? 'text-red-800'
: analyticsData.systemLoadStatus === 'warning'
? 'text-orange-800'
: analyticsData.systemLoadStatus === 'monitor'
? 'text-blue-800'
: analyticsData.systemLoadStatus === 'low'
? 'text-yellow-800'
: 'text-gray-800'
}`}>
</p>
<p className={`text-sm mt-1 ${
analyticsData.systemLoadStatus === 'critical'
? 'text-red-700'
: analyticsData.systemLoadStatus === 'warning'
? 'text-orange-700'
: analyticsData.systemLoadStatus === 'monitor'
? 'text-blue-700'
: analyticsData.systemLoadStatus === 'low'
? 'text-yellow-700'
: 'text-gray-700'
}`}>
{analyticsData.systemLoadAdvice || '正在分析系統負載狀態...'}
</p>
</div>
</div>
@@ -343,7 +445,7 @@ export function AnalyticsDashboard() {
<ResponsiveContainer width="100%" height={300}>
<PieChart>
<Pie
data={categoryData}
data={analyticsData.categoryData}
cx="50%"
cy="50%"
outerRadius={90}
@@ -353,7 +455,7 @@ export function AnalyticsDashboard() {
label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`}
labelLine={false}
>
{categoryData.map((entry, index) => (
{analyticsData.categoryData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} stroke="#ffffff" strokeWidth={2} />
))}
</Pie>
@@ -380,7 +482,7 @@ export function AnalyticsDashboard() {
{/* 添加圖例說明 */}
<div className="mt-4 grid grid-cols-2 gap-2 text-sm">
{categoryData.map((category, index) => (
{analyticsData.categoryData.map((category, index) => (
<div key={index} className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full" style={{ backgroundColor: category.color }} />
<span className="text-gray-700">{category.name}</span>
@@ -473,7 +575,13 @@ export function AnalyticsDashboard() {
<div className="mt-4 p-3 bg-blue-50 rounded-lg">
<p className="text-sm text-blue-800 flex items-center gap-2">
<TrendingUp className="w-4 h-4" />
<strong></strong> 09:00-17:00 使
<strong></strong>
{analyticsData.hourlyAnalysis || '正在分析24小時使用模式...'}
{analyticsData.hourlyAdvice && (
<span className="block mt-1 ml-6">
{analyticsData.hourlyAdvice}
</span>
)}
</p>
</div>
</CardContent>
@@ -486,7 +594,7 @@ export function AnalyticsDashboard() {
</CardHeader>
<CardContent>
<div className="space-y-4">
{topApps.map((app, index) => (
{analyticsData.topApps.map((app, index) => (
<div key={index} className="flex items-center justify-between p-3 border rounded-lg">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center font-bold text-blue-600">
@@ -521,15 +629,38 @@ export function AnalyticsDashboard() {
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="text-center p-4 border rounded-lg">
<div className="text-2xl font-bold text-green-600">92%</div>
<div className="text-2xl font-bold text-green-600">
{isLoading ? (
<Loader2 className="w-6 h-6 animate-spin mx-auto" />
) : (
`${analyticsData.satisfactionRate}%`
)}
</div>
<p className="text-sm text-muted-foreground">滿</p>
</div>
<div className="text-center p-4 border rounded-lg">
<div className="text-2xl font-bold text-blue-600">4.6</div>
<div className="text-2xl font-bold text-blue-600">
{isLoading ? (
<Loader2 className="w-6 h-6 animate-spin mx-auto" />
) : (
analyticsData.userAvgRating || analyticsData.avgRating
)}
</div>
<p className="text-sm text-muted-foreground"></p>
{analyticsData.totalRatings > 0 && (
<p className="text-xs text-gray-500 mt-1">
{analyticsData.totalRatings}
</p>
)}
</div>
<div className="text-center p-4 border rounded-lg">
<div className="text-2xl font-bold text-purple-600">156</div>
<div className="text-2xl font-bold text-purple-600">
{isLoading ? (
<Loader2 className="w-6 h-6 animate-spin mx-auto" />
) : (
analyticsData.weeklyFeedback
)}
</div>
<p className="text-sm text-muted-foreground"></p>
</div>
</div>