Files
ai-showcase-platform/app/test-ip-cleanup/page.tsx

227 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import React, { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Loader2, Database, Trash2, Eye, Zap } from 'lucide-react';
import { clientCleanup } from '@/lib/client-connection-cleanup';
export default function TestIPCleanupPage() {
const [status, setStatus] = useState<any>(null);
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState<string>('');
const [error, setError] = useState<string>('');
// 獲取連線狀態
const fetchStatus = async () => {
try {
setLoading(true);
const status = await clientCleanup.getConnectionStatus();
setStatus(status);
setMessage('連線狀態更新成功');
setError('');
} catch (err) {
setError('獲取狀態失敗: ' + (err instanceof Error ? err.message : '未知錯誤'));
} finally {
setLoading(false);
}
};
// 手動清理
const manualCleanup = async () => {
try {
setLoading(true);
const success = await clientCleanup.manualCleanup();
if (success) {
setMessage('手動清理完成');
setError('');
await fetchStatus(); // 重新獲取狀態
} else {
setError('手動清理失敗');
}
} catch (err) {
setError('手動清理錯誤: ' + (err instanceof Error ? err.message : '未知錯誤'));
} finally {
setLoading(false);
}
};
// 模擬關閉頁面
const simulatePageClose = () => {
if (confirm('確定要模擬關閉頁面嗎?這會觸發自動清理機制。')) {
// 觸發 beforeunload 事件
window.dispatchEvent(new Event('beforeunload'));
// 等待一下再觸發 unload 事件
setTimeout(() => {
window.dispatchEvent(new Event('unload'));
}, 100);
}
};
// 組件載入時獲取狀態
useEffect(() => {
fetchStatus();
}, []);
return (
<div className="container mx-auto p-6 space-y-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold">IP </h1>
<p className="text-muted-foreground">
IP
</p>
</div>
<Button
onClick={fetchStatus}
disabled={loading}
variant="outline"
>
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Eye className="h-4 w-4" />}
</Button>
</div>
{/* 客戶端信息 */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Database className="h-5 w-5" />
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2">
<p><strong> ID:</strong> {clientCleanup.getClientId()}</p>
<p><strong>:</strong> {navigator.userAgent}</p>
<p><strong>:</strong> {new Date().toLocaleString()}</p>
</div>
</CardContent>
</Card>
{/* 連線狀態 */}
{status && (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Eye className="h-5 w-5" />
</CardTitle>
<CardDescription>
IP: {status.ip} | : {status.connectionCount}
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center gap-4">
<Badge variant="outline" className="text-lg px-3 py-1">
: {status.connectionCount}
</Badge>
<Badge
variant={status.connectionCount > 5 ? "destructive" : "default"}
className="text-lg px-3 py-1"
>
: {status.connectionCount > 5 ? "異常" : "正常"}
</Badge>
</div>
{status.connections && status.connections.length > 0 && (
<div className="space-y-2">
<h4 className="font-medium">:</h4>
{status.connections.slice(0, 5).map((conn: any, index: number) => (
<div key={index} className="p-2 border rounded text-sm">
<p>ID: {conn.ID} | HOST: {conn.HOST} | : {conn.TIME}s</p>
</div>
))}
{status.connections.length > 5 && (
<p className="text-sm text-muted-foreground">
... {status.connections.length - 5}
</p>
)}
</div>
)}
</CardContent>
</Card>
)}
{/* 測試操作 */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Zap className="h-5 w-5" />
</CardTitle>
<CardDescription>
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Button
onClick={manualCleanup}
disabled={loading}
variant="outline"
className="w-full"
>
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Trash2 className="h-4 w-4" />}
</Button>
<Button
onClick={simulatePageClose}
disabled={loading}
variant="destructive"
className="w-full"
>
<Zap className="h-4 w-4" />
</Button>
<Button
onClick={() => window.location.reload()}
disabled={loading}
variant="secondary"
className="w-full"
>
<Database className="h-4 w-4" />
</Button>
</div>
</CardContent>
</Card>
{/* 自動清理說明 */}
<Card>
<CardHeader>
<CardTitle></CardTitle>
</CardHeader>
<CardContent className="space-y-2 text-sm text-muted-foreground">
<p> <strong>:</strong> IP </p>
<p> <strong>:</strong> </p>
<p> <strong>:</strong> 5</p>
<p> <strong>:</strong> </p>
<p> <strong>:</strong> IP </p>
</CardContent>
</Card>
{/* 訊息顯示 */}
{message && (
<Alert>
<Database className="h-4 w-4" />
<AlertDescription>{message}</AlertDescription>
</Alert>
)}
{error && (
<Alert variant="destructive">
<Trash2 className="h-4 w-4" />
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
</div>
);
}