From caca8b2bc492fa4371df1b6f8597e478a52fa7e2 Mon Sep 17 00:00:00 2001 From: Sline Date: Tue, 25 Nov 2025 10:01:04 +0800 Subject: [PATCH] refactor: debugLog for frontend (#5587) --- .../common/traffic-error-boundary.tsx | 3 +- src/components/home/current-proxy-card.tsx | 15 +++-- .../home/enhanced-canvas-traffic-graph.tsx | 3 +- src/components/profile/profile-item.tsx | 13 ++-- src/components/proxy/proxy-chain.tsx | 9 +-- src/components/proxy/proxy-groups.tsx | 17 ++--- src/components/proxy/proxy-head.tsx | 5 +- src/components/proxy/use-render-list.ts | 5 +- src/components/setting/mods/dns-viewer.tsx | 3 +- .../setting/mods/sysproxy-viewer.tsx | 11 ++-- src/components/setting/mods/update-viewer.tsx | 3 +- src/components/test/test-item.tsx | 3 +- src/hooks/use-profiles.ts | 21 +++--- src/hooks/use-proxy-selection.ts | 9 +-- src/hooks/use-traffic-monitor.ts | 18 +++--- src/pages/profiles.tsx | 28 ++++---- src/pages/proxies.tsx | 5 +- src/services/api.ts | 6 +- src/services/cmds.ts | 5 +- src/services/delay.ts | 22 +++---- src/utils/data-validator.ts | 4 +- src/utils/debug.ts | 64 +++++++++++++++++++ src/utils/helper.ts | 4 +- src/utils/parse-hotkey.ts | 4 +- 24 files changed, 181 insertions(+), 99 deletions(-) create mode 100644 src/utils/debug.ts diff --git a/src/components/common/traffic-error-boundary.tsx b/src/components/common/traffic-error-boundary.tsx index 763dcbbea..c43d3d579 100644 --- a/src/components/common/traffic-error-boundary.tsx +++ b/src/components/common/traffic-error-boundary.tsx @@ -71,8 +71,7 @@ export class TrafficErrorBoundary extends Component { url: window.location.href, }; - console.log("[TrafficErrorBoundary] 错误报告:", errorReport); - + console.error("[TrafficErrorBoundary] 错误报告:", errorReport); // TODO: 发送到错误监控服务 // sendErrorReport(errorReport); }; diff --git a/src/components/home/current-proxy-card.tsx b/src/components/home/current-proxy-card.tsx index 94acc2a46..2aabba29b 100644 --- a/src/components/home/current-proxy-card.tsx +++ b/src/components/home/current-proxy-card.tsx @@ -39,6 +39,7 @@ import { useProfiles } from "@/hooks/use-profiles"; import { useProxySelection } from "@/hooks/use-proxy-selection"; import { useVerge } from "@/hooks/use-verge"; import delayManager from "@/services/delay"; +import { debugLog } from "@/utils/debug"; // 本地存储的键名 const STORAGE_KEY_GROUP = "clash-verge-selected-proxy-group"; @@ -539,7 +540,7 @@ export const CurrentProxyCard = () => { const proxyRecord = latestProxyRecordRef.current; if (!proxyRecord) { - console.log( + debugLog( `[CurrentProxyCard] 自动延迟检测跳过,组: ${groupName}, 节点: ${proxyName} 未找到`, ); return; @@ -550,7 +551,7 @@ export const CurrentProxyCard = () => { const timeout = latestTimeoutRef.current || 10000; try { - console.log( + debugLog( `[CurrentProxyCard] 自动检测当前节点延迟,组: ${groupName}, 节点: ${proxyName}`, ); if (proxyRecord.provider) { @@ -647,7 +648,7 @@ export const CurrentProxyCard = () => { const groupName = state.selection.group; if (!groupName || isDirectMode) return; - console.log(`[CurrentProxyCard] 开始测试所有延迟,组: ${groupName}`); + debugLog(`[CurrentProxyCard] 开始测试所有延迟,组: ${groupName}`); const timeout = verge?.default_latency_timeout || 10000; @@ -687,13 +688,13 @@ export const CurrentProxyCard = () => { } } - console.log( + debugLog( `[CurrentProxyCard] 找到代理数量: ${proxyNames.length}, 提供者数量: ${providers.size}`, ); // 测试提供者的节点 if (providers.size > 0) { - console.log(`[CurrentProxyCard] 开始测试提供者节点`); + debugLog(`[CurrentProxyCard] 开始测试提供者节点`); await Promise.allSettled( [...providers].map((p) => healthcheckProxyProvider(p)), ); @@ -702,14 +703,14 @@ export const CurrentProxyCard = () => { // 测试非提供者的节点 if (proxyNames.length > 0) { const url = delayManager.getUrl(groupName); - console.log(`[CurrentProxyCard] 测试URL: ${url}, 超时: ${timeout}ms`); + debugLog(`[CurrentProxyCard] 测试URL: ${url}, 超时: ${timeout}ms`); try { await Promise.race([ delayManager.checkListDelay(proxyNames, groupName, timeout), delayGroup(groupName, url, timeout), ]); - console.log(`[CurrentProxyCard] 延迟测试完成,组: ${groupName}`); + debugLog(`[CurrentProxyCard] 延迟测试完成,组: ${groupName}`); } catch (error) { console.error( `[CurrentProxyCard] 延迟测试出错,组: ${groupName}`, diff --git a/src/components/home/enhanced-canvas-traffic-graph.tsx b/src/components/home/enhanced-canvas-traffic-graph.tsx index e56f169b2..3562d3726 100644 --- a/src/components/home/enhanced-canvas-traffic-graph.tsx +++ b/src/components/home/enhanced-canvas-traffic-graph.tsx @@ -16,6 +16,7 @@ import { useTrafficGraphDataEnhanced, type ITrafficDataPoint, } from "@/hooks/use-traffic-monitor"; +import { debugLog } from "@/utils/debug"; import parseTraffic from "@/utils/parse-traffic"; // 流量数据项接口 @@ -1044,7 +1045,7 @@ export const EnhancedCanvasTrafficGraph = memo( // 兼容性方法 const appendData = useCallback((data: ITrafficItem) => { - console.log( + debugLog( "[EnhancedCanvasTrafficGraphV2] appendData called (using global data):", data, ); diff --git a/src/components/profile/profile-item.tsx b/src/components/profile/profile-item.tsx index eb5c68388..7393ea50e 100644 --- a/src/components/profile/profile-item.tsx +++ b/src/components/profile/profile-item.tsx @@ -37,6 +37,7 @@ import { import { showNotice } from "@/services/noticeService"; import { useLoadingCache, useSetLoadingCache } from "@/services/states"; import type { TranslationKey } from "@/types/generated/i18n-keys"; +import { debugLog } from "@/utils/debug"; import parseTraffic from "@/utils/parse-traffic"; import { ProfileBox } from "./profile-box"; @@ -104,16 +105,16 @@ export const ProfileItem = (props: Props) => { itemData.option.update_interval > 0 ) { try { - console.log(`尝试获取配置 ${itemData.uid} 的下次更新时间`); + debugLog(`尝试获取配置 ${itemData.uid} 的下次更新时间`); // 如果需要强制刷新,先触发Timer.refresh() if (forceRefresh) { // 这里可以通过一个新的API来触发刷新,但目前我们依赖patch_profile中的刷新 - console.log(`强制刷新定时器任务`); + debugLog(`强制刷新定时器任务`); } const nextUpdate = await getNextUpdateTime(itemData.uid); - console.log(`获取到下次更新时间结果:`, nextUpdate); + debugLog(`获取到下次更新时间结果:`, nextUpdate); if (nextUpdate) { const nextUpdateDate = dayjs(nextUpdate * 1000); @@ -147,7 +148,7 @@ export const ProfileItem = (props: Props) => { } } } else { - console.log(`返回的下次更新时间为空`); + debugLog(`返回的下次更新时间为空`); setNextUpdateTime( t("profiles.components.profileItem.status.noSchedule"), ); @@ -157,7 +158,7 @@ export const ProfileItem = (props: Props) => { setNextUpdateTime(t("profiles.components.profileItem.status.unknown")); } } else { - console.log(`该配置未设置更新间隔或间隔为0`); + debugLog(`该配置未设置更新间隔或间隔为0`); setNextUpdateTime( t("profiles.components.profileItem.status.autoUpdateDisabled"), ); @@ -197,7 +198,7 @@ export const ProfileItem = (props: Props) => { // 只有当更新的是当前配置时才刷新显示 if (updatedUid === itemData.uid && showNextUpdate) { - console.log(`收到定时器更新事件: uid=${updatedUid}`); + debugLog(`收到定时器更新事件: uid=${updatedUid}`); if (refreshTimeout !== undefined) { clearTimeout(refreshTimeout); } diff --git a/src/components/proxy/proxy-chain.tsx b/src/components/proxy/proxy-chain.tsx index b07757d2d..b10676ce1 100644 --- a/src/components/proxy/proxy-chain.tsx +++ b/src/components/proxy/proxy-chain.tsx @@ -41,6 +41,7 @@ import { import { useProxiesData } from "@/hooks/app-data"; import { calcuProxies, updateProxyChainConfigInRuntime } from "@/services/cmds"; +import { debugLog } from "@/utils/debug"; interface ProxyChainItem { id: string; @@ -319,13 +320,13 @@ export const ProxyChain = ({ try { // 第一步:保存链式代理配置 const chainProxies = proxyChain.map((node) => node.name); - console.log("Saving chain config:", chainProxies); + debugLog("Saving chain config:", chainProxies); await updateProxyChainConfigInRuntime(chainProxies); - console.log("Chain configuration saved successfully"); + debugLog("Chain configuration saved successfully"); // 第二步:连接到代理链的最后一个节点 const lastNode = proxyChain[proxyChain.length - 1]; - console.log(`Connecting to proxy chain, last node: ${lastNode.name}`); + debugLog(`Connecting to proxy chain, last node: ${lastNode.name}`); // 根据模式确定使用的代理组名称 if (mode !== "global" && !selectedGroup) { @@ -340,7 +341,7 @@ export const ProxyChain = ({ // 刷新代理信息以更新连接状态 mutateProxies(); - console.log("Successfully connected to proxy chain"); + debugLog("Successfully connected to proxy chain"); } catch (error) { console.error("Failed to connect to proxy chain:", error); alert(t("proxies.page.chain.connectFailed") || "连接链式代理失败"); diff --git a/src/components/proxy/proxy-groups.tsx b/src/components/proxy/proxy-groups.tsx index d85ba397c..ab4814262 100644 --- a/src/components/proxy/proxy-groups.tsx +++ b/src/components/proxy/proxy-groups.tsx @@ -20,6 +20,7 @@ import { useProxySelection } from "@/hooks/use-proxy-selection"; import { useVerge } from "@/hooks/use-verge"; import { updateProxyChainConfigInRuntime } from "@/services/cmds"; import delayManager from "@/services/delay"; +import { debugLog } from "@/utils/debug"; import { BaseEmpty } from "../base"; import { ScrollTopButton } from "../layout/scroll-top-button"; @@ -274,7 +275,7 @@ export const ProxyGroups = (props: Props) => { // 测全部延迟 const handleCheckAll = useLockFn(async (groupName: string) => { - console.log(`[ProxyGroups] 开始测试所有延迟,组: ${groupName}`); + debugLog(`[ProxyGroups] 开始测试所有延迟,组: ${groupName}`); const proxies = renderList .filter( @@ -283,37 +284,37 @@ export const ProxyGroups = (props: Props) => { .flatMap((e) => e.proxyCol || e.proxy!) .filter(Boolean); - console.log(`[ProxyGroups] 找到代理数量: ${proxies.length}`); + debugLog(`[ProxyGroups] 找到代理数量: ${proxies.length}`); const providers = new Set(proxies.map((p) => p!.provider!).filter(Boolean)); if (providers.size) { - console.log(`[ProxyGroups] 发现提供者,数量: ${providers.size}`); + debugLog(`[ProxyGroups] 发现提供者,数量: ${providers.size}`); Promise.allSettled( [...providers].map((p) => healthcheckProxyProvider(p)), ).then(() => { - console.log(`[ProxyGroups] 提供者健康检查完成`); + debugLog(`[ProxyGroups] 提供者健康检查完成`); onProxies(); }); } const names = proxies.filter((p) => !p!.provider).map((p) => p!.name); - console.log(`[ProxyGroups] 过滤后需要测试的代理数量: ${names.length}`); + debugLog(`[ProxyGroups] 过滤后需要测试的代理数量: ${names.length}`); const url = delayManager.getUrl(groupName); - console.log(`[ProxyGroups] 测试URL: ${url}, 超时: ${timeout}ms`); + debugLog(`[ProxyGroups] 测试URL: ${url}, 超时: ${timeout}ms`); try { await Promise.race([ delayManager.checkListDelay(names, groupName, timeout), delayGroup(groupName, url, timeout).then((result) => { - console.log( + debugLog( `[ProxyGroups] getGroupProxyDelays返回结果数量:`, Object.keys(result || {}).length, ); }), // 查询group delays 将清除fixed(不关注调用结果) ]); - console.log(`[ProxyGroups] 延迟测试完成,组: ${groupName}`); + debugLog(`[ProxyGroups] 延迟测试完成,组: ${groupName}`); } catch (error) { console.error(`[ProxyGroups] 延迟测试出错,组: ${groupName}`, error); } finally { diff --git a/src/components/proxy/proxy-head.tsx b/src/components/proxy/proxy-head.tsx index 56a034bd0..6dea0d7a0 100644 --- a/src/components/proxy/proxy-head.tsx +++ b/src/components/proxy/proxy-head.tsx @@ -17,6 +17,7 @@ import { useTranslation } from "react-i18next"; import { useVerge } from "@/hooks/use-verge"; import delayManager from "@/services/delay"; +import { debugLog } from "@/utils/debug"; import type { ProxySortType } from "./use-filter-sort"; import type { HeadState } from "./use-head-state"; @@ -78,10 +79,10 @@ export const ProxyHead = ({ color="inherit" title={t("proxies.page.tooltips.delayCheck")} onClick={() => { - console.log(`[ProxyHead] 点击延迟测试按钮,组: ${groupName}`); + debugLog(`[ProxyHead] 点击延迟测试按钮,组: ${groupName}`); // Remind the user that it is custom test url if (testUrl?.trim() && textState !== "filter") { - console.log(`[ProxyHead] 使用自定义测试URL: ${testUrl}`); + debugLog(`[ProxyHead] 使用自定义测试URL: ${testUrl}`); onHeadState({ textState: "url" }); } onCheckDelay(); diff --git a/src/components/proxy/use-render-list.ts b/src/components/proxy/use-render-list.ts index 2ebe89ada..9e25c58ec 100644 --- a/src/components/proxy/use-render-list.ts +++ b/src/components/proxy/use-render-list.ts @@ -5,6 +5,7 @@ import { useProxiesData } from "@/hooks/app-data"; import { useVerge } from "@/hooks/use-verge"; import { getRuntimeConfig } from "@/services/cmds"; import delayManager from "@/services/delay"; +import { debugLog } from "@/utils/debug"; import { filterSort } from "./use-filter-sort"; import { @@ -130,7 +131,7 @@ export const useRenderList = ( // 设置组监听器,当有延迟更新时自动刷新 const groupListener = () => { - console.log("[ChainMode] 延迟更新,刷新UI"); + debugLog("[ChainMode] 延迟更新,刷新UI"); refreshProxy(); }; @@ -141,7 +142,7 @@ export const useRenderList = ( const timeout = verge?.default_latency_timeout || 10000; const proxyNames = allProxies.map((proxy) => proxy.name); - console.log(`[ChainMode] 开始计算 ${proxyNames.length} 个节点的延迟`); + debugLog(`[ChainMode] 开始计算 ${proxyNames.length} 个节点的延迟`); // 使用 delayManager 计算延迟,每个节点计算完成后会自动触发监听器刷新界面 delayManager.checkListDelay(proxyNames, "chain-mode", timeout); diff --git a/src/components/setting/mods/dns-viewer.tsx b/src/components/setting/mods/dns-viewer.tsx index 0b0f520d2..b1271226b 100644 --- a/src/components/setting/mods/dns-viewer.tsx +++ b/src/components/setting/mods/dns-viewer.tsx @@ -31,6 +31,7 @@ import { BaseDialog, DialogRef, Switch } from "@/components/base"; import { useClash } from "@/hooks/use-clash"; import { showNotice } from "@/services/noticeService"; import { useThemeMode } from "@/services/states"; +import { debugLog } from "@/utils/debug"; import getSystem from "@/utils/get-system"; const Item = styled(ListItem)(() => ({ @@ -580,7 +581,7 @@ export function DnsViewer({ ref }: { ref?: Ref }) { }, 300); } } catch (err) { - console.log("YAML解析错误,忽略自动更新", err); + debugLog("YAML解析错误,忽略自动更新", err); } }; diff --git a/src/components/setting/mods/sysproxy-viewer.tsx b/src/components/setting/mods/sysproxy-viewer.tsx index 078261564..4b7a4bd02 100644 --- a/src/components/setting/mods/sysproxy-viewer.tsx +++ b/src/components/setting/mods/sysproxy-viewer.tsx @@ -40,6 +40,7 @@ import { patchVergeConfig, } from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; +import { debugLog } from "@/utils/debug"; import getSystem from "@/utils/get-system"; const sleep = (ms: number) => @@ -238,7 +239,7 @@ export const SysproxyViewer = forwardRef((props, ref) => { let hostname = ""; try { hostname = await getSystemHostname(); - console.log("获取到主机名:", hostname); + debugLog("获取到主机名:", hostname); } catch (err) { console.error("获取主机名失败:", err); } @@ -252,12 +253,12 @@ export const SysproxyViewer = forwardRef((props, ref) => { if (hostname !== "localhost" && hostname !== "127.0.0.1") { hostname = hostname + ".local"; options.push(hostname); - console.log("主机名已添加到选项中:", hostname); + debugLog("主机名已添加到选项中:", hostname); } else { - console.log("主机名与已有选项重复:", hostname); + debugLog("主机名与已有选项重复:", hostname); } } else { - console.log("主机名为空"); + debugLog("主机名为空"); } // 添加IP地址 @@ -265,7 +266,7 @@ export const SysproxyViewer = forwardRef((props, ref) => { // 去重 const uniqueOptions = Array.from(new Set(options)); - console.log("最终选项列表:", uniqueOptions); + debugLog("最终选项列表:", uniqueOptions); setHostOptions(uniqueOptions); } catch (error) { console.error("获取网络接口失败:", error); diff --git a/src/components/setting/mods/update-viewer.tsx b/src/components/setting/mods/update-viewer.tsx index 6cc723b25..c46028a41 100644 --- a/src/components/setting/mods/update-viewer.tsx +++ b/src/components/setting/mods/update-viewer.tsx @@ -15,6 +15,7 @@ import { portableFlag } from "@/pages/_layout"; import { showNotice } from "@/services/noticeService"; import { useSetUpdateState, useUpdateState } from "@/services/states"; import { checkUpdateSafe as checkUpdate } from "@/services/update"; +import { debugLog } from "@/utils/debug"; export function UpdateViewer({ ref }: { ref?: Ref }) { const { t } = useTranslation(); @@ -102,7 +103,7 @@ export function UpdateViewer({ ref }: { ref?: Ref }) { useEffect(() => { return () => { if (currentProgressListener) { - console.log("UpdateViewer unmounting, cleaning up progress listener."); + debugLog("UpdateViewer unmounting, cleaning up progress listener."); currentProgressListener(); } }; diff --git a/src/components/test/test-item.tsx b/src/components/test/test-item.tsx index 738c41c02..63c181ced 100644 --- a/src/components/test/test-item.tsx +++ b/src/components/test/test-item.tsx @@ -13,6 +13,7 @@ import { useListen } from "@/hooks/use-listen"; import { cmdTestDelay, downloadIconCache } from "@/services/cmds"; import delayManager from "@/services/delay"; import { showNotice } from "@/services/noticeService"; +import { debugLog } from "@/utils/debug"; import { TestBox } from "./test-box"; @@ -107,7 +108,7 @@ export const TestItem = ({ return () => { if (unlistenFn) { - console.log( + debugLog( `TestItem for ${id} unmounting or url changed, cleaning up test-all listener.`, ); unlistenFn(); diff --git a/src/hooks/use-profiles.ts b/src/hooks/use-profiles.ts index c517c8352..76db32faa 100644 --- a/src/hooks/use-profiles.ts +++ b/src/hooks/use-profiles.ts @@ -7,6 +7,7 @@ import { patchProfilesConfig, } from "@/services/cmds"; import { calcuProxies } from "@/services/cmds"; +import { debugLog } from "@/utils/debug"; export const useProfiles = () => { const { @@ -25,7 +26,7 @@ export const useProfiles = () => { console.error("[useProfiles] SWR错误:", error); }, onSuccess: (data) => { - console.log( + debugLog( "[useProfiles] 配置数据更新成功,配置数量:", data?.items?.length || 0, ); @@ -71,7 +72,7 @@ export const useProfiles = () => { // 根据selected的节点选择 const activateSelected = async () => { try { - console.log("[ActivateSelected] 开始处理代理选择"); + debugLog("[ActivateSelected] 开始处理代理选择"); const [proxiesData, profileData] = await Promise.all([ calcuProxies(), @@ -79,7 +80,7 @@ export const useProfiles = () => { ]); if (!profileData || !proxiesData) { - console.log("[ActivateSelected] 代理或配置数据不可用,跳过处理"); + debugLog("[ActivateSelected] 代理或配置数据不可用,跳过处理"); return; } @@ -88,18 +89,18 @@ export const useProfiles = () => { ); if (!current) { - console.log("[ActivateSelected] 未找到当前profile配置"); + debugLog("[ActivateSelected] 未找到当前profile配置"); return; } // 检查是否有saved的代理选择 const { selected = [] } = current; if (selected.length === 0) { - console.log("[ActivateSelected] 当前profile无保存的代理选择,跳过"); + debugLog("[ActivateSelected] 当前profile无保存的代理选择,跳过"); return; } - console.log( + debugLog( `[ActivateSelected] 当前profile有 ${selected.length} 个代理选择配置`, ); @@ -160,7 +161,7 @@ export const useProfiles = () => { } if (savedProxy !== now) { - console.log( + debugLog( `[ActivateSelected] 需要切换代理组 ${name}: ${now} -> ${savedProxy}`, ); hasChange = true; @@ -171,15 +172,15 @@ export const useProfiles = () => { }); if (!hasChange) { - console.log("[ActivateSelected] 所有代理选择已经是目标状态,无需更新"); + debugLog("[ActivateSelected] 所有代理选择已经是目标状态,无需更新"); return; } - console.log(`[ActivateSelected] 完成代理切换,保存新的选择配置`); + debugLog(`[ActivateSelected] 完成代理切换,保存新的选择配置`); try { await patchProfile(profileData.current!, { selected: newSelected }); - console.log("[ActivateSelected] 代理选择配置保存成功"); + debugLog("[ActivateSelected] 代理选择配置保存成功"); setTimeout(() => { mutate("getProxies", calcuProxies()); diff --git a/src/hooks/use-proxy-selection.ts b/src/hooks/use-proxy-selection.ts index 8d2a2df42..4cfb6a960 100644 --- a/src/hooks/use-proxy-selection.ts +++ b/src/hooks/use-proxy-selection.ts @@ -9,6 +9,7 @@ import { import { useProfiles } from "@/hooks/use-profiles"; import { useVerge } from "@/hooks/use-verge"; import { syncTrayProxySelection } from "@/services/cmds"; +import { debugLog } from "@/utils/debug"; // 缓存连接清理 const cleanupConnections = async (previousProxy: string) => { @@ -20,7 +21,7 @@ const cleanupConnections = async (previousProxy: string) => { if (cleanupPromises.length > 0) { await Promise.allSettled(cleanupPromises); - console.log(`[ProxySelection] 清理了 ${cleanupPromises.length} 个连接`); + debugLog(`[ProxySelection] 清理了 ${cleanupPromises.length} 个连接`); } } catch (error) { console.warn("[ProxySelection] 连接清理失败:", error); @@ -57,7 +58,7 @@ export const useProxySelection = (options: ProxySelectionOptions = {}) => { previousProxy?: string, skipConfigSave: boolean = false, ) => { - console.log(`[ProxySelection] 代理切换: ${groupName} -> ${proxyName}`); + debugLog(`[ProxySelection] 代理切换: ${groupName} -> ${proxyName}`); try { if (current && !skipConfigSave) { @@ -77,7 +78,7 @@ export const useProxySelection = (options: ProxySelectionOptions = {}) => { await selectNodeForGroup(groupName, proxyName); await syncTrayProxySelection(); - console.log( + debugLog( `[ProxySelection] 代理和状态同步完成: ${groupName} -> ${proxyName}`, ); @@ -100,7 +101,7 @@ export const useProxySelection = (options: ProxySelectionOptions = {}) => { await selectNodeForGroup(groupName, proxyName); await syncTrayProxySelection(); onSuccess?.(); - console.log( + debugLog( `[ProxySelection] 代理切换回退成功: ${groupName} -> ${proxyName}`, ); } catch (fallbackError) { diff --git a/src/hooks/use-traffic-monitor.ts b/src/hooks/use-traffic-monitor.ts index de9ae52a2..a92f3d409 100644 --- a/src/hooks/use-traffic-monitor.ts +++ b/src/hooks/use-traffic-monitor.ts @@ -1,6 +1,8 @@ import { useEffect, useRef, useCallback, useReducer } from "react"; import { Traffic } from "tauri-plugin-mihomo-api"; +import { debugLog } from "@/utils/debug"; + // 增强的流量数据点接口 export interface ITrafficDataPoint { up: number; @@ -34,7 +36,7 @@ class ReferenceCounter { increment(): () => void { this.count++; - console.log(`[ReferenceCounter] 引用计数增加: ${this.count}`); + debugLog(`[ReferenceCounter] 引用计数增加: ${this.count}`); if (this.count === 1) { // 从0到1,开始数据收集 @@ -43,7 +45,7 @@ class ReferenceCounter { return () => { this.count--; - console.log(`[ReferenceCounter] 引用计数减少: ${this.count}`); + debugLog(`[ReferenceCounter] 引用计数减少: ${this.count}`); if (this.count === 0) { // 从1到0,停止数据收集 @@ -116,7 +118,7 @@ class TrafficDataSampler { this.compressedBuffer.push(compressedPoint); this.compressionQueue = []; - console.log(`[DataSampler] 压缩了 ${compressedPoint.samples} 个数据点`); + debugLog(`[DataSampler] 压缩了 ${compressedPoint.samples} 个数据点`); } getDataForTimeRange(minutes: number): ITrafficDataPoint[] { @@ -194,12 +196,12 @@ export const useTrafficMonitorEnhanced = () => { // 注册引用计数 useEffect(() => { - console.log("[TrafficMonitorEnhanced] 组件挂载,注册引用计数"); + debugLog("[TrafficMonitorEnhanced] 组件挂载,注册引用计数"); const cleanup = refCounter.increment(); cleanupRef.current = cleanup; return () => { - console.log("[TrafficMonitorEnhanced] 组件卸载,清理引用计数"); + debugLog("[TrafficMonitorEnhanced] 组件卸载,清理引用计数"); cleanup(); cleanupRef.current = null; }; @@ -208,13 +210,13 @@ export const useTrafficMonitorEnhanced = () => { // 设置引用计数变化回调 useEffect(() => { const handleCountChange = () => { - console.log( + debugLog( `[TrafficMonitorEnhanced] 引用计数变化: ${refCounter.getCount()}`, ); if (refCounter.getCount() === 0) { - console.log("[TrafficMonitorEnhanced] 所有组件已卸载,暂停数据收集"); + debugLog("[TrafficMonitorEnhanced] 所有组件已卸载,暂停数据收集"); } else { - console.log("[TrafficMonitorEnhanced] 开始数据收集"); + debugLog("[TrafficMonitorEnhanced] 开始数据收集"); } }; diff --git a/src/pages/profiles.tsx b/src/pages/profiles.tsx index 1beb190f4..15109e49c 100644 --- a/src/pages/profiles.tsx +++ b/src/pages/profiles.tsx @@ -60,14 +60,12 @@ import { } from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; import { useSetLoadingCache, useThemeMode } from "@/services/states"; +import { debugLog } from "@/utils/debug"; // 记录profile切换状态 const debugProfileSwitch = (action: string, profile: string, extra?: any) => { const timestamp = new Date().toISOString().substring(11, 23); - console.log( - `[Profile-Debug][${timestamp}] ${action}: ${profile}`, - extra || "", - ); + debugLog(`[Profile-Debug][${timestamp}] ${action}: ${profile}`, extra || ""); }; // 检查请求是否已过期 @@ -223,7 +221,7 @@ const ProfilePage = () => { // 添加紧急恢复功能 const onEmergencyRefresh = useLockFn(async () => { - console.log("[紧急刷新] 开始强制刷新所有数据"); + debugLog("[紧急刷新] 开始强制刷新所有数据"); try { // 清除所有SWR缓存 @@ -327,7 +325,7 @@ const ProfilePage = () => { while (retryCount < maxRetries) { try { - console.log(`[导入刷新] 第${retryCount + 1}次尝试刷新配置数据`); + debugLog(`[导入刷新] 第${retryCount + 1}次尝试刷新配置数据`); // 强制刷新,绕过所有缓存 await mutateProfiles(undefined, { @@ -393,7 +391,7 @@ const ProfilePage = () => { !abortController.signal.aborted ) { await activateSelected(); - console.log(`[Profile] 后台处理完成,序列号: ${sequence}`); + debugLog(`[Profile] 后台处理完成,序列号: ${sequence}`); } else { debugProfileSwitch( "BACKGROUND_TASK_SKIPPED", @@ -411,9 +409,7 @@ const ProfilePage = () => { const activateProfile = useCallback( async (profile: string, notifySuccess: boolean) => { if (profiles.current === profile && !notifySuccess) { - console.log( - `[Profile] 目标profile ${profile} 已经是当前配置,跳过切换`, - ); + debugLog(`[Profile] 目标profile ${profile} 已经是当前配置,跳过切换`); return; } @@ -445,7 +441,7 @@ const ProfilePage = () => { }); try { - console.log( + debugLog( `[Profile] 开始切换到: ${profile},序列号: ${currentSequence}`, ); @@ -489,7 +485,7 @@ const ProfilePage = () => { ); } - console.log( + debugLog( `[Profile] 切换到 ${profile} 完成,序列号: ${currentSequence},开始后台处理`, ); @@ -569,7 +565,7 @@ const ProfilePage = () => { const onEnhance = useLockFn(async (notifySuccess: boolean) => { if (switchingProfileRef.current) { - console.log( + debugLog( `[Profile] 有profile正在切换中(${switchingProfileRef.current}),跳过enhance操作`, ); return; @@ -752,20 +748,20 @@ const ProfilePage = () => { const newProfileId = event.payload; const now = Date.now(); - console.log(`[Profile] 收到配置变更事件: ${newProfileId}`); + debugLog(`[Profile] 收到配置变更事件: ${newProfileId}`); if ( lastProfileId === newProfileId && now - lastUpdateTime < debounceDelay ) { - console.log(`[Profile] 重复事件被防抖,跳过`); + debugLog(`[Profile] 重复事件被防抖,跳过`); return; } lastProfileId = newProfileId; lastUpdateTime = now; - console.log(`[Profile] 执行配置数据刷新`); + debugLog(`[Profile] 执行配置数据刷新`); if (refreshTimer !== null) { window.clearTimeout(refreshTimer); diff --git a/src/pages/proxies.tsx b/src/pages/proxies.tsx index 31c0bed55..4005c44a3 100644 --- a/src/pages/proxies.tsx +++ b/src/pages/proxies.tsx @@ -15,6 +15,7 @@ import { patchClashMode, updateProxyChainConfigInRuntime, } from "@/services/cmds"; +import { debugLog } from "@/utils/debug"; const MODES = ["rule", "global", "direct"] as const; type Mode = (typeof MODES)[number]; @@ -81,9 +82,9 @@ const ProxyPage = () => { if (!newChainMode) { // 退出链式代理模式时,清除链式代理配置 try { - console.log("Exiting chain mode, clearing chain configuration"); + debugLog("Exiting chain mode, clearing chain configuration"); await updateProxyChainConfigInRuntime(null); - console.log("Chain configuration cleared successfully"); + debugLog("Chain configuration cleared successfully"); } catch (error) { console.error("Failed to clear chain configuration:", error); } diff --git a/src/services/api.ts b/src/services/api.ts index 2ad41c272..4c82e3d77 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -1,5 +1,7 @@ import { fetch } from "@tauri-apps/plugin-http"; +import { debugLog } from "@/utils/debug"; + // Get current IP and geolocation information (refactored IP detection with service-specific mappings) interface IpInfo { ip: string; @@ -163,7 +165,7 @@ export const getIpInfo = async (): Promise => { let lastError: Error | null = null; for (const service of shuffledServices) { - console.log(`尝试IP检测服务: ${service.url}`); + debugLog(`尝试IP检测服务: ${service.url}`); for (let attempt = 0; attempt < maxRetries; attempt++) { let timeoutId: ReturnType | null = null; @@ -186,7 +188,7 @@ export const getIpInfo = async (): Promise => { if (timeoutId) clearTimeout(timeoutId); if (data && data.ip) { - console.log(`IP检测成功,使用服务: ${service.url}`); + debugLog(`IP检测成功,使用服务: ${service.url}`); return service.mapping(data); } else { throw new Error(`无效的响应格式 from ${service.url}`); diff --git a/src/services/cmds.ts b/src/services/cmds.ts index 738b16a8e..860209f61 100644 --- a/src/services/cmds.ts +++ b/src/services/cmds.ts @@ -3,6 +3,7 @@ import dayjs from "dayjs"; import { getProxies, getProxyProviders } from "tauri-plugin-mihomo-api"; import { showNotice } from "@/services/noticeService"; +import { debugLog } from "@/utils/debug"; export async function copyClashEnv() { return invoke("copy_clash_env"); @@ -264,12 +265,12 @@ export async function getSystemProxy() { export async function getAutotemProxy() { try { - console.log("[API] 开始调用 get_auto_proxy"); + debugLog("[API] 开始调用 get_auto_proxy"); const result = await invoke<{ enable: boolean; url: string; }>("get_auto_proxy"); - console.log("[API] get_auto_proxy 调用成功:", result); + debugLog("[API] get_auto_proxy 调用成功:", result); return result; } catch (error) { console.error("[API] get_auto_proxy 调用失败:", error); diff --git a/src/services/delay.ts b/src/services/delay.ts index 214745454..75399ba0b 100644 --- a/src/services/delay.ts +++ b/src/services/delay.ts @@ -1,5 +1,7 @@ import { delayProxyByName, ProxyDelay } from "tauri-plugin-mihomo-api"; +import { debugLog } from "@/utils/debug"; + const hashKey = (name: string, group: string) => `${group ?? ""}::${name}`; export interface DelayUpdate { @@ -108,13 +110,13 @@ class DelayManager { } setUrl(group: string, url: string) { - console.log(`[DelayManager] 设置测试URL,组: ${group}, URL: ${url}`); + debugLog(`[DelayManager] 设置测试URL,组: ${group}, URL: ${url}`); this.urlMap.set(group, url); } getUrl(group: string) { const url = this.urlMap.get(group); - console.log( + debugLog( `[DelayManager] 获取测试URL,组: ${group}, URL: ${url || "未设置"}`, ); // 如果未设置URL,返回默认URL @@ -150,7 +152,7 @@ class DelayManager { meta?: { elapsed?: number }, ): DelayUpdate { const key = hashKey(name, group); - console.log( + debugLog( `[DelayManager] 设置延迟,代理: ${name}, 组: ${group}, 延迟: ${delay}`, ); const update: DelayUpdate = { @@ -212,7 +214,7 @@ class DelayManager { group: string, timeout: number, ): Promise { - console.log( + debugLog( `[DelayManager] 开始测试延迟,代理: ${name}, 组: ${group}, 超时: ${timeout}ms`, ); @@ -226,7 +228,7 @@ class DelayManager { try { const url = this.getUrl(group); - console.log(`[DelayManager] 调用API测试延迟,代理: ${name}, URL: ${url}`); + debugLog(`[DelayManager] 调用API测试延迟,代理: ${name}, URL: ${url}`); // 设置超时处理, delay = 0 为超时 const timeoutPromise = new Promise((resolve) => { @@ -247,9 +249,7 @@ class DelayManager { delay = result.delay; elapsed = elapsedTime; - console.log( - `[DelayManager] 延迟测试完成,代理: ${name}, 结果: ${delay}ms`, - ); + debugLog(`[DelayManager] 延迟测试完成,代理: ${name}, 结果: ${delay}ms`); } catch (error) { // 确保至少显示500ms的加载动画 await new Promise((resolve) => setTimeout(resolve, 500)); @@ -267,7 +267,7 @@ class DelayManager { timeout: number, concurrency = 36, ) { - console.log( + debugLog( `[DelayManager] 批量测试延迟开始,组: ${group}, 数量: ${nameList.length}, 并发数: ${concurrency}`, ); const names = nameList.filter(Boolean); @@ -312,7 +312,7 @@ class DelayManager { // 限制并发数,避免发送太多请求 const actualConcurrency = Math.min(concurrency, names.length, 10); - console.log(`[DelayManager] 实际并发数: ${actualConcurrency}`); + debugLog(`[DelayManager] 实际并发数: ${actualConcurrency}`); const promiseList: Promise[] = []; for (let i = 0; i < actualConcurrency; i++) { @@ -321,7 +321,7 @@ class DelayManager { await Promise.all(promiseList); const totalTime = Date.now() - startTime; - console.log( + debugLog( `[DelayManager] 批量测试延迟完成,组: ${group}, 总耗时: ${totalTime}ms`, ); } diff --git a/src/utils/data-validator.ts b/src/utils/data-validator.ts index 4bdbd12be..e936413f6 100644 --- a/src/utils/data-validator.ts +++ b/src/utils/data-validator.ts @@ -59,7 +59,7 @@ export class SystemMonitorValidator implements ISystemMonitorOverviewValidator { * 清理和修复数据,确保返回有效的ISystemMonitorOverview */ sanitize(data: any): ISystemMonitorOverview { - // console.log("[DataValidator] 开始数据清理:", data); + // debugLog("[DataValidator] 开始数据清理:", data); const sanitized: ISystemMonitorOverview = { traffic: this.sanitizeTrafficData(data?.traffic), @@ -67,7 +67,7 @@ export class SystemMonitorValidator implements ISystemMonitorOverviewValidator { overall_status: this.sanitizeOverallStatus(data?.overall_status), }; - // console.log("[DataValidator] 数据清理完成:", sanitized); + // debugLog("[DataValidator] 数据清理完成:", sanitized); return sanitized; } diff --git a/src/utils/debug.ts b/src/utils/debug.ts new file mode 100644 index 000000000..e57131239 --- /dev/null +++ b/src/utils/debug.ts @@ -0,0 +1,64 @@ +const envVarValue = (import.meta.env.VITE_ENABLE_DEBUG_LOGS ?? "").toString(); + +let runtimeOverride: boolean | null = null; + +const parseStringFlag = (value: string) => { + if (!value) return false; + const normalized = value.trim().toLowerCase(); + return normalized === "1" || normalized === "true" || normalized === "yes"; +}; + +let cachedDebugEnabled: boolean | null = null; + +const computeDebugEnabled = () => { + if (import.meta.env.DEV) { + return true; + } + + if (parseStringFlag(envVarValue)) { + return true; + } + + if (typeof window !== "undefined") { + const globalFlag = (window as any).__VERGE_ENABLE_DEBUG_LOGS__; + if (typeof globalFlag === "boolean") { + return globalFlag; + } + + try { + const stored = window.localStorage?.getItem("VERGE_DEBUG_LOGS"); + if (stored) { + return parseStringFlag(stored); + } + } catch { + // ignore storage access errors + } + } + + return false; +}; + +const isEnvDebugEnabled = () => { + if (runtimeOverride !== null) { + return runtimeOverride; + } + + if (cachedDebugEnabled !== null) { + return cachedDebugEnabled; + } + + cachedDebugEnabled = computeDebugEnabled(); + return cachedDebugEnabled; +}; + +export const setDebugLoggingEnabled = (enabled: boolean) => { + runtimeOverride = enabled; + cachedDebugEnabled = enabled; +}; + +export const isDebugLoggingEnabled = () => isEnvDebugEnabled(); + +export const debugLog = (...args: any[]) => { + if (!isEnvDebugEnabled()) return; + console.log(...args); +}; diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 1a7d10466..aa37526bb 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -1,9 +1,11 @@ +import { debugLog } from "@/utils/debug"; + export const isValidUrl = (url: string) => { try { new URL(url); return true; } catch (e) { - console.log(e); + debugLog(e); return false; } }; diff --git a/src/utils/parse-hotkey.ts b/src/utils/parse-hotkey.ts index f4a37e446..4335a9724 100644 --- a/src/utils/parse-hotkey.ts +++ b/src/utils/parse-hotkey.ts @@ -1,5 +1,7 @@ import { KeyboardEvent } from "react"; +import { debugLog } from "@/utils/debug"; + const KEY_MAP: Record = { // Option + 特殊字符映射 "–": "Minus", // Option + - @@ -62,7 +64,7 @@ export const parseHotkey = (keyEvent: KeyboardEvent) => { } else if (temp.endsWith("RIGHT")) { temp = temp.slice(0, -5); } - console.log(temp, mapKeyCombination(temp)); + debugLog(temp, mapKeyCombination(temp)); switch (temp) { case "CONTROL":