"use client" import { useEffect, useState } from "react" import { Globe, Shield, ShieldAlert, Info } from "lucide-react" interface IpDisplayProps { mobileSimplified?: boolean } interface IpInfo { ip: string isAllowed: boolean enableIpWhitelist: boolean allowedIps: string[] timestamp: string ipv6Info?: { isIPv6Mapped: boolean originalFormat: string ipv6Format: string hasIPv6Support: boolean } debug?: { originalDetectedIp?: string finalDetectedIp?: string rawDetectedIp?: string allFoundIps?: string[] ipDetectionMethod?: string } } // 清理IP地址,確保顯示IPv4格式 function cleanIpForDisplay(ip: string): string { if (!ip) return '127.0.0.1'; // 移除空白字符 ip = ip.trim(); // 處理IPv6格式的IPv4地址 (例如: ::ffff:192.168.1.1) if (ip.startsWith('::ffff:')) { return ip.substring(7); } // 處理純IPv6本地回環地址 if (ip === '::1') { return '127.0.0.1'; } // 驗證是否為有效的IPv4地址 const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; if (ipv4Regex.test(ip)) { return ip; } // 如果不是有效的IPv4,返回默認值 return '127.0.0.1'; } // 檢查是否為IPv6格式的IPv4地址 function isIPv6MappedIPv4(ip: string): boolean { return ip.startsWith('::ffff:'); } // 獲取IPv6格式的IPv4地址 function getIPv6MappedFormat(ipv4: string): string { return `::ffff:${ipv4}`; } export default function IpDisplay({ mobileSimplified = false }: IpDisplayProps) { const [ipInfo, setIpInfo] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [showIPv6Format, setShowIPv6Format] = useState(false) useEffect(() => { const fetchIpInfo = async () => { try { const response = await fetch('/api/ip') if (!response.ok) { throw new Error('無法獲取IP信息') } const data = await response.json() setIpInfo(data) } catch (error) { console.error("無法獲取IP信息:", error) setError("無法獲取IP信息") } finally { setLoading(false) } } fetchIpInfo() }, []) if (loading) { return (
載入中...
) } if (error || !ipInfo) { return (
錯誤
) } // 清理IP地址確保顯示IPv4格式 const displayIp = cleanIpForDisplay(ipInfo.ip); // 使用API返回的IPv6信息,如果沒有則回退到本地檢測 const isIPv6Mapped = ipInfo.ipv6Info?.isIPv6Mapped || isIPv6MappedIPv4(ipInfo.debug?.originalDetectedIp || ipInfo.ip); const ipv6Format = ipInfo.ipv6Info?.ipv6Format || getIPv6MappedFormat(displayIp); const originalFormat = ipInfo.ipv6Info?.originalFormat || ipInfo.debug?.originalDetectedIp || ipInfo.ip; // 手機版簡化顯示 if (mobileSimplified) { return (
{ipInfo.enableIpWhitelist && !ipInfo.isAllowed ? ( ) : ( )} {isIPv6Mapped ? 'IPv6' : 'IPv4'}: {displayIp.split('.').slice(0, 2).join('.')}...
) } return (
{ipInfo.enableIpWhitelist && !ipInfo.isAllowed ? ( ) : ( )}
{isIPv6Mapped ? 'IPv6' : 'IPv4'}: {displayIp} {isIPv6Mapped && ( {ipv6Format} )}
{ipInfo.enableIpWhitelist && ( {ipInfo.isAllowed ? '允許' : '拒絕'} )} {/* IPv6格式切換按鈕 */}
{/* 詳細信息彈出框 */} {showIPv6Format && (
IPv4格式: {displayIp}
IPv6格式: {ipv6Format}
{originalFormat && originalFormat !== displayIp && (
原始格式: {originalFormat}
)} {ipInfo.debug?.ipDetectionMethod && (
檢測方法: {ipInfo.debug.ipDetectionMethod}
)} {ipInfo.debug?.allFoundIps && ipInfo.debug.allFoundIps.length > 0 && (
所有檢測到的IP:
{ipInfo.debug.allFoundIps.map((ip, index) => (
{ip}
))}
)} {ipInfo.ipv6Info?.hasIPv6Support && (
✓ IPv6支援已啟用
)}
)}
) }