// 网络管理:智能检测内外网 // 判断是否为内网IP地址 function isInternalIP(hostname: string): boolean { // 如果是localhost if (hostname === 'localhost' || hostname === '127.0.0.1') { return true } // 判断是否为内网IP段 // 10.0.0.0 - 10.255.255.255 // 172.16.0.0 - 172.31.255.255 // 192.168.0.0 - 192.168.255.255 const ipv4Regex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ const match = hostname.match(ipv4Regex) if (match) { const [, a, b] = match.map(Number) // 10.x.x.x if (a === 10) return true // 172.16.x.x - 172.31.x.x if (a === 172 && b >= 16 && b <= 31) return true // 192.168.x.x if (a === 192 && b === 168) return true } return false } function getCurrentHost(): string { if (typeof window === 'undefined') return '' return window.location.host } function getCurrentHostname(): string { if (typeof window === 'undefined') return '' return window.location.hostname } export interface NetworkStatus { isInternal: boolean host: string lastChecked?: number // 上次检测时间戳 } let currentNetwork: NetworkStatus | null = null let networkChangeListeners: ((status: NetworkStatus) => void)[] = [] // 网络状态缓存有效期(1分钟,缩短以便更快响应网络变化) const NETWORK_CACHE_TTL = 60 * 1000 // 初始化网络检测(优先使用后端API获取准确状态) export async function initializeNetwork(forceRefresh: boolean = false): Promise { if (typeof window === 'undefined') { return { isInternal: false, host: '' } } // 如果已经检测过且缓存未过期,直接返回缓存结果 if (!forceRefresh && currentNetwork && currentNetwork.lastChecked) { const cacheAge = Date.now() - currentNetwork.lastChecked if (cacheAge < NETWORK_CACHE_TTL) { return currentNetwork } } const host = getCurrentHost() const hostname = getCurrentHostname() const previousStatus = currentNetwork?.isInternal // 优先调用后端API获取准确的网络状态(后端可以通过请求头获取真实的客户端IP) try { const response = await fetch('/api/network-status', { cache: 'no-store', // 不缓存,确保获取最新状态 }) if (response.ok) { const data = await response.json() if (data.success) { currentNetwork = { isInternal: data.isIntranet, host, lastChecked: Date.now() } // 使用 debug 级别,生产环境默认不显示 console.debug(`[Network] ${data.isIntranet ? '内网' : '公网'}访问`) // 如果网络状态发生变化,通知监听器(保留 warn 级别,重要信息) if (previousStatus !== undefined && previousStatus !== data.isIntranet) { console.warn(`[Network] 网络切换: ${previousStatus ? '内网' : '外网'} → ${data.isIntranet ? '内网' : '外网'}`) notifyNetworkChange(currentNetwork) } return currentNetwork } } } catch (error) { console.warn('后端网络检测失败,使用前端判断:', error) } // 如果后端API调用失败,回退到前端判断(基于hostname) const isInternal = isInternalIP(hostname) currentNetwork = { isInternal, host, lastChecked: Date.now() } // 使用 debug 级别,生产环境默认不显示 console.debug(`[Network] ${isInternal ? '内网' : '公网'}访问 (前端检测)`) // 如果网络状态发生变化,通知监听器(保留 warn 级别,重要信息) if (previousStatus !== undefined && previousStatus !== isInternal) { console.warn(`[Network] 网络切换: ${previousStatus ? '内网' : '外网'} → ${isInternal ? '内网' : '外网'}`) notifyNetworkChange(currentNetwork) } return currentNetwork } // 获取当前网络状态 export function getNetworkStatus(): NetworkStatus { if (!currentNetwork) { const host = getCurrentHost() const hostname = getCurrentHostname() const isInternal = isInternalIP(hostname) return { isInternal, host } } return currentNetwork } // 获取API基础URL export function getApiBaseUrl(): string { if (!currentNetwork) { return '' // 使用相对路径 } return currentNetwork.isInternal ? `http://${currentNetwork.host}` : '' } // 清除缓存(用于刷新网络状态) export function clearNetworkCache() { currentNetwork = null console.debug('[Network] 缓存已清除') } // 手动失效缓存并重新检测(用于用户主动刷新) export async function invalidateAndRefresh(): Promise { console.debug('[Network] 手动刷新') clearNetworkCache() return await initializeNetwork(true) } // 添加网络状态变化监听器 export function addNetworkChangeListener(listener: (status: NetworkStatus) => void) { networkChangeListeners.push(listener) return () => { networkChangeListeners = networkChangeListeners.filter(l => l !== listener) } } // 通知所有监听器网络状态变化 function notifyNetworkChange(status: NetworkStatus) { networkChangeListeners.forEach(listener => { try { listener(status) } catch (error) { console.error('网络状态变化监听器执行失败:', error) } }) } // 设置网络变化监听(监听浏览器online/offline事件) export function setupNetworkChangeDetection() { if (typeof window === 'undefined') return // 监听浏览器网络状态变化 window.addEventListener('online', () => { console.debug('[Network] 网络恢复,重新检测') initializeNetwork(true) }) window.addEventListener('offline', () => { console.warn('[Network] 网络断开') }) // 监听页面可见性变化(用户切换回页面时重新检测) document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible' && currentNetwork) { const cacheAge = Date.now() - (currentNetwork.lastChecked || 0) // 如果缓存超过1分钟,重新检测 if (cacheAge > 60 * 1000) { console.debug('[Network] 页面可见,刷新状态') initializeNetwork(true) } } }) }