refactor: invock mihomo api by use tauri-plugin-mihomo (#4926)

* feat: add tauri-plugin-mihomo

* refactor: invock mihomo api by use tauri-plugin-mihomo

* chore: todo

* chore: update

* chore: update

* chore: update

* chore: update

* fix: incorrect delay status and update pretty config

* chore: update

* chore: remove cache

* chore: update

* chore: update

* fix: app freezed when change group proxy

* chore: update

* chore: update

* chore: add rustfmt.toml to tauri-plugin-mihomo

* chore: happy clippy

* refactor: connect mihomo websocket

* chore: update

* chore: update

* fix: parse bigint to number

* chore: update

* Revert "fix: parse bigint to number"

This reverts commit 74c006522e23aa52cf8979a8fb47d2b1ae0bb043.

* chore: use number instead of bigint

* chore: cleanup

* fix: rule data not refresh when switch profile

* chore: update

* chore: cleanup

* chore: update

* fix: traffic graph data display

* feat: add ipc connection pool

* chore: update

* chore: clippy

* fix: incorrect delay status

* fix: typo

* fix: empty proxies tray menu

* chore: clippy

* chore: import tauri-plugin-mihomo by using git repo

* chore: cleanup

* fix: mihomo api

* fix: incorrect delay status

* chore: update tauri-plugin-mihomo dep

chore: update
This commit is contained in:
oomeow
2025-10-08 12:32:40 +08:00
committed by GitHub
parent 72aa56007c
commit 7fc238c27b
85 changed files with 1780 additions and 3344 deletions

View File

@@ -1,12 +1,11 @@
import { useLockFn } from "ahooks";
import useSWR, { mutate } from "swr";
import { getVersion } from "tauri-plugin-mihomo-api";
import { getVersion } from "@/services/cmds";
import {
getClashInfo,
patchClashConfig,
getRuntimeConfig,
forceRefreshClashConfig,
} from "@/services/cmds";
export const useClash = () => {
@@ -25,11 +24,9 @@ export const useClash = () => {
mutateClash();
});
const version = versionData?.premium
? `${versionData.version} Premium`
: versionData?.meta
? `${versionData.version} Mihomo`
: versionData?.version || "-";
const version = versionData?.meta
? `${versionData.version} Mihomo`
: versionData?.version || "-";
return {
clash,
@@ -123,10 +120,7 @@ export const useClashInfo = () => {
await patchClashConfig(patch);
mutateInfo();
// 配置修改后强制刷新缓存
await forceRefreshClashConfig();
mutate("getClashConfig");
// IPC调用不需要刷新axios实例
};
return {

View File

@@ -0,0 +1,108 @@
import { useLocalStorage } from "foxact/use-local-storage";
import { useEffect, useRef } from "react";
import { mutate } from "swr";
import useSWRSubscription from "swr/subscription";
import { MihomoWebSocket } from "tauri-plugin-mihomo-api";
export const initConnData: IConnections = {
uploadTotal: 0,
downloadTotal: 0,
connections: [],
};
export const useConnectionData = () => {
const [date, setDate] = useLocalStorage("mihomo_connection_date", Date.now());
const subscriptKey = `getClashConnection-${date}`;
const ws = useRef<MihomoWebSocket | null>(null);
const wsFirstConnection = useRef<boolean>(true);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>(null);
const response = useSWRSubscription<IConnections, any, string | null>(
subscriptKey,
(_key, { next }) => {
const reconnect = async () => {
await ws.current?.close();
ws.current = null;
timeoutRef.current = setTimeout(async () => await connect(), 500);
};
const connect = () =>
MihomoWebSocket.connect_connections()
.then((ws_) => {
ws.current = ws_;
if (timeoutRef.current) clearTimeout(timeoutRef.current);
ws_.addListener(async (msg) => {
if (msg.type === "Text") {
if (msg.data.startsWith("Websocket error")) {
next(msg.data);
await reconnect();
} else {
const data = JSON.parse(msg.data) as IConnections;
next(null, (old = initConnData) => {
const oldConn = old.connections;
const maxLen = data.connections?.length;
const connections: IConnectionsItem[] = [];
const rest = (data.connections || []).filter((each) => {
const index = oldConn.findIndex((o) => o.id === each.id);
if (index >= 0 && index < maxLen) {
const old = oldConn[index];
each.curUpload = each.upload - old.upload;
each.curDownload = each.download - old.download;
connections[index] = each;
return false;
}
return true;
});
for (let i = 0; i < maxLen; ++i) {
if (!connections[i] && rest.length > 0) {
connections[i] = rest.shift()!;
connections[i].curUpload = 0;
connections[i].curDownload = 0;
}
}
return { ...data, connections };
});
}
}
});
})
.catch((_) => {
if (!ws.current) {
timeoutRef.current = setTimeout(async () => await connect(), 500);
}
});
if (
wsFirstConnection.current ||
(ws.current && !wsFirstConnection.current)
) {
wsFirstConnection.current = false;
if (ws.current) {
ws.current.close();
ws.current = null;
}
connect();
}
return () => {
ws.current?.close();
};
},
{
fallbackData: initConnData,
keepPreviousData: true,
},
);
useEffect(() => {
mutate(`$sub$${subscriptKey}`);
}, [date, subscriptKey]);
const refreshGetClashConnection = () => {
setDate(Date.now());
};
return { response, refreshGetClashConnection };
};

View File

@@ -0,0 +1,151 @@
import dayjs from "dayjs";
import { useLocalStorage } from "foxact/use-local-storage";
import { useEffect, useRef } from "react";
import { mutate } from "swr";
import useSWRSubscription from "swr/subscription";
import { MihomoWebSocket } from "tauri-plugin-mihomo-api";
import { getClashLogs } from "@/services/cmds";
import { useClashLog } from "@/services/states";
const MAX_LOG_NUM = 1000;
export const useLogData = () => {
const [clashLog] = useClashLog();
const enableLog = clashLog.enable;
const logLevel = clashLog.logLevel;
const [date, setDate] = useLocalStorage("mihomo_logs_date", Date.now());
const subscriptKey = enableLog ? `getClashLog-${date}` : null;
const ws = useRef<MihomoWebSocket | null>(null);
const wsFirstConnection = useRef<boolean>(true);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>(null);
const response = useSWRSubscription<ILogItem[], any, string | null>(
subscriptKey,
(_key, { next }) => {
const reconnect = async () => {
await ws.current?.close();
ws.current = null;
timeoutRef.current = setTimeout(async () => await connect(), 500);
};
const connect = () =>
MihomoWebSocket.connect_logs(logLevel)
.then(async (ws_) => {
ws.current = ws_;
if (timeoutRef.current) clearTimeout(timeoutRef.current);
const logs = await getClashLogs();
let filterLogs: ILogItem[] = [];
switch (logLevel) {
case "debug":
filterLogs = logs.filter((i) =>
["debug", "info", "warning", "error"].includes(i.type),
);
break;
case "info":
filterLogs = logs.filter((i) =>
["info", "warning", "error"].includes(i.type),
);
break;
case "warning":
filterLogs = logs.filter((i) =>
["warning", "error"].includes(i.type),
);
break;
case "error":
filterLogs = logs.filter((i) => i.type === "error");
break;
case "silent":
filterLogs = [];
break;
default:
filterLogs = logs;
break;
}
next(null, filterLogs);
const buffer: ILogItem[] = [];
let flushTimer: ReturnType<typeof setTimeout> | null = null;
const flush = () => {
if (buffer.length > 0) {
next(null, (l) => {
let newList = [...(l ?? []), ...buffer.splice(0)];
if (newList.length > MAX_LOG_NUM) {
newList = newList.slice(
-Math.min(MAX_LOG_NUM, newList.length),
);
}
return newList;
});
}
flushTimer = null;
};
ws_.addListener(async (msg) => {
if (msg.type === "Text") {
if (msg.data.startsWith("Websocket error")) {
next(msg.data);
await reconnect();
} else {
const data = JSON.parse(msg.data) as ILogItem;
data.time = dayjs().format("MM-DD HH:mm:ss");
buffer.push(data);
// flush data
if (!flushTimer) {
flushTimer = setTimeout(flush, 50);
}
}
}
});
})
.catch((_) => {
if (!ws.current) {
timeoutRef.current = setTimeout(async () => await connect(), 500);
}
});
if (
wsFirstConnection.current ||
(ws.current && !wsFirstConnection.current)
) {
wsFirstConnection.current = false;
if (ws.current) {
ws.current.close();
ws.current = null;
}
connect();
}
return () => {
ws.current?.close();
};
},
{
fallbackData: [],
keepPreviousData: true,
},
);
useEffect(() => {
mutate(`$sub$${subscriptKey}`);
}, [date, subscriptKey]);
useEffect(() => {
if (!logLevel) return;
ws.current?.close();
setDate(Date.now());
}, [logLevel]);
const refreshGetClashLog = (clear = false) => {
if (clear) {
mutate(`$sub$${subscriptKey}`, []);
} else {
setDate(Date.now());
}
};
return { response, refreshGetClashLog };
};

View File

@@ -1,11 +1,11 @@
import {
useGlobalLogData,
clearGlobalLogs,
LogLevel,
// LogLevel,
} from "@/services/global-log-service";
// 为了向后兼容,导出相同的类型
export type { LogLevel };
// export type { LogLevel };
export const useLogData = useGlobalLogData;

View File

@@ -0,0 +1,84 @@
import { useLocalStorage } from "foxact/use-local-storage";
import { useEffect, useRef } from "react";
import { mutate } from "swr";
import useSWRSubscription from "swr/subscription";
import { MihomoWebSocket } from "tauri-plugin-mihomo-api";
export interface IMemoryUsageItem {
inuse: number;
oslimit?: number;
}
export const useMemoryData = () => {
const [date, setDate] = useLocalStorage("mihomo_memory_date", Date.now());
const subscriptKey = `getClashMemory-${date}`;
const ws = useRef<MihomoWebSocket | null>(null);
const wsFirstConnection = useRef<boolean>(true);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>(null);
const response = useSWRSubscription<IMemoryUsageItem, any, string | null>(
subscriptKey,
(_key, { next }) => {
const reconnect = async () => {
await ws.current?.close();
ws.current = null;
timeoutRef.current = setTimeout(async () => await connect(), 500);
};
const connect = () =>
MihomoWebSocket.connect_memory()
.then((ws_) => {
ws.current = ws_;
if (timeoutRef.current) clearTimeout(timeoutRef.current);
ws_.addListener(async (msg) => {
if (msg.type === "Text") {
if (msg.data.startsWith("Websocket error")) {
next(msg.data, { inuse: 0 });
await reconnect();
} else {
const data = JSON.parse(msg.data) as IMemoryUsageItem;
next(null, data);
}
}
});
})
.catch((_) => {
if (!ws.current) {
timeoutRef.current = setTimeout(async () => await connect(), 500);
}
});
if (
wsFirstConnection.current ||
(ws.current && !wsFirstConnection.current)
) {
wsFirstConnection.current = false;
if (ws.current) {
ws.current.close();
ws.current = null;
}
connect();
}
return () => {
ws.current?.close();
};
},
{
fallbackData: { inuse: 0 },
keepPreviousData: true,
},
);
useEffect(() => {
mutate(`$sub$${subscriptKey}`);
}, [date, subscriptKey]);
const refreshGetClashMemory = () => {
setDate(Date.now());
};
return { response, refreshGetClashMemory };
};

View File

@@ -1,12 +1,12 @@
import useSWR, { mutate } from "swr";
import { selectNodeForGroup } from "tauri-plugin-mihomo-api";
import {
getProfiles,
patchProfile,
patchProfilesConfig,
forceRefreshProxies,
} from "@/services/cmds";
import { getProxies, updateProxy } from "@/services/cmds";
import { calcuProxies } from "@/services/cmds";
export const useProfiles = () => {
const {
@@ -72,7 +72,7 @@ export const useProfiles = () => {
console.log("[ActivateSelected] 开始处理代理选择");
const [proxiesData, profileData] = await Promise.all([
getProxies(),
calcuProxies(),
getProfiles(),
]);
@@ -124,7 +124,7 @@ export const useProfiles = () => {
`[ActivateSelected] 需要切换代理组 ${name}: ${now} -> ${targetProxy}`,
);
hasChange = true;
updateProxy(name, targetProxy);
selectNodeForGroup(name, targetProxy);
}
newSelected.push({ name, now: targetProxy || now });
@@ -141,11 +141,8 @@ export const useProfiles = () => {
await patchProfile(profileData.current!, { selected: newSelected });
console.log("[ActivateSelected] 代理选择配置保存成功");
// 切换节点后强制刷新后端缓存
await forceRefreshProxies();
setTimeout(() => {
mutate("getProxies", getProxies());
mutate("getProxies", calcuProxies());
}, 100);
} catch (error: any) {
console.error(

View File

@@ -1,24 +1,22 @@
import { useLockFn } from "ahooks";
import { useCallback, useMemo } from "react";
import {
closeConnections,
getConnections,
selectNodeForGroup,
} from "tauri-plugin-mihomo-api";
import { useProfiles } from "@/hooks/use-profiles";
import { useVerge } from "@/hooks/use-verge";
import {
updateProxy,
updateProxyAndSync,
forceRefreshProxies,
syncTrayProxySelection,
getConnections,
deleteConnection,
} from "@/services/cmds";
import { syncTrayProxySelection } from "@/services/cmds";
// 缓存连接清理
const cleanupConnections = async (previousProxy: string) => {
try {
const { connections } = await getConnections();
const cleanupPromises = connections
const cleanupPromises = (connections ?? [])
.filter((conn) => conn.chains.includes(previousProxy))
.map((conn) => deleteConnection(conn.id));
.map((conn) => closeConnections(conn.id));
if (cleanupPromises.length > 0) {
await Promise.allSettled(cleanupPromises);
@@ -77,7 +75,8 @@ export const useProxySelection = (options: ProxySelectionOptions = {}) => {
await patchCurrent({ selected: current.selected });
}
await updateProxyAndSync(groupName, proxyName);
await selectNodeForGroup(groupName, proxyName);
await syncTrayProxySelection();
console.log(
`[ProxySelection] 代理和状态同步完成: ${groupName} -> ${proxyName}`,
);
@@ -98,8 +97,7 @@ export const useProxySelection = (options: ProxySelectionOptions = {}) => {
);
try {
await updateProxy(groupName, proxyName);
await forceRefreshProxies();
await selectNodeForGroup(groupName, proxyName);
await syncTrayProxySelection();
onSuccess?.();
console.log(

View File

@@ -1,8 +1,9 @@
import useSWR, { mutate } from "swr";
import { closeAllConnections } from "tauri-plugin-mihomo-api";
import { useVerge } from "@/hooks/use-verge";
import { useAppData } from "@/providers/app-data-context";
import { closeAllConnections, getAutotemProxy } from "@/services/cmds";
import { getAutotemProxy } from "@/services/cmds";
// 系统代理状态检测统一逻辑
export const useSystemProxyState = () => {

View File

@@ -0,0 +1,84 @@
import { useLocalStorage } from "foxact/use-local-storage";
import { useEffect, useRef } from "react";
import { mutate } from "swr";
import useSWRSubscription from "swr/subscription";
import { MihomoWebSocket } from "tauri-plugin-mihomo-api";
import { TrafficRef } from "@/components/layout/traffic-graph";
export const useTrafficData = () => {
const [date, setDate] = useLocalStorage("mihomo_traffic_date", Date.now());
const subscriptKey = `getClashTraffic-${date}`;
const trafficRef = useRef<TrafficRef>(null);
const ws = useRef<MihomoWebSocket | null>(null);
const wsFirstConnection = useRef<boolean>(true);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>(null);
const response = useSWRSubscription<ITrafficItem, any, string | null>(
subscriptKey,
(_key, { next }) => {
const reconnect = async () => {
await ws.current?.close();
ws.current = null;
timeoutRef.current = setTimeout(async () => await connect(), 500);
};
const connect = async () => {
MihomoWebSocket.connect_traffic()
.then(async (ws_) => {
ws.current = ws_;
if (timeoutRef.current) clearTimeout(timeoutRef.current);
ws_.addListener(async (msg) => {
if (msg.type === "Text") {
if (msg.data.startsWith("Websocket error")) {
next(msg.data, { up: 0, down: 0 });
await reconnect();
} else {
const data = JSON.parse(msg.data) as ITrafficItem;
trafficRef.current?.appendData(data);
next(null, data);
}
}
});
})
.catch((_) => {
if (!ws.current) {
timeoutRef.current = setTimeout(async () => await connect(), 500);
}
});
};
if (
wsFirstConnection.current ||
(ws.current && !wsFirstConnection.current)
) {
wsFirstConnection.current = false;
if (ws.current) {
ws.current.close();
ws.current = null;
}
connect();
}
return () => {
ws.current?.close();
};
},
{
fallbackData: { up: 0, down: 0 },
keepPreviousData: true,
},
);
useEffect(() => {
mutate(`$sub$${subscriptKey}`);
}, [date, subscriptKey]);
const refreshGetClashTraffic = () => {
setDate(Date.now());
};
return { response, refreshGetClashTraffic };
};

View File

@@ -1,9 +1,9 @@
import { useState, useEffect, useRef, useCallback } from "react";
import useSWR from "swr";
import { useClashInfo } from "@/hooks/use-clash";
import { useVisibility } from "@/hooks/use-visibility";
import { getSystemMonitorOverviewSafe } from "@/services/cmds";
// import { useClashInfo } from "@/hooks/use-clash";
// import { useVisibility } from "@/hooks/use-visibility";
import { useTrafficData } from "./use-traffic-data";
// 增强的流量数据点接口
export interface ITrafficDataPoint {
@@ -175,14 +175,17 @@ class TrafficDataSampler {
// 全局单例
const refCounter = new ReferenceCounter();
let globalSampler: TrafficDataSampler | null = null;
let lastValidData: ISystemMonitorOverview | null = null;
// let lastValidData: ISystemMonitorOverview | null = null;
/**
* 增强的流量监控Hook - 支持数据压缩、采样和引用计数
*/
export const useTrafficMonitorEnhanced = () => {
const { clashInfo } = useClashInfo();
const pageVisible = useVisibility();
// const { clashInfo } = useClashInfo();
// const pageVisible = useVisibility();
const {
response: { data: traffic },
} = useTrafficData();
// 初始化采样器
if (!globalSampler) {
@@ -230,69 +233,87 @@ export const useTrafficMonitorEnhanced = () => {
refCounter.onCountChange(handleCountChange);
}, []);
// 只有在有引用时才启用SWR
const shouldFetch = clashInfo && pageVisible && refCounter.getCount() > 0;
// const monitorData = useRef<ISystemMonitorOverview | null>(null);
useEffect(() => {
if (globalSampler) {
// 添加到采样器
const timestamp = Date.now();
const dataPoint: ITrafficDataPoint = {
up: traffic?.up || 0,
down: traffic?.down || 0,
timestamp,
name: new Date(timestamp).toLocaleTimeString("en-US", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}),
};
globalSampler.addDataPoint(dataPoint);
triggerUpdate();
}
}, [traffic, triggerUpdate]);
const { data: monitorData, error } = useSWR<ISystemMonitorOverview>(
shouldFetch ? "getSystemMonitorOverviewSafe" : null,
getSystemMonitorOverviewSafe,
{
refreshInterval: shouldFetch ? 1000 : 0, // 只有在需要时才刷新
keepPreviousData: true,
onSuccess: (data) => {
// console.log("[TrafficMonitorEnhanced] 获取到监控数据:", data);
// const { data: monitorData, error } = useSWR<ISystemMonitorOverview>(
// shouldFetch ? "getSystemMonitorOverviewSafe" : null,
// getSystemMonitorOverviewSafe,
// {
// refreshInterval: shouldFetch ? 1000 : 0, // 只有在需要时才刷新
// keepPreviousData: true,
// onSuccess: (data) => {
// // console.log("[TrafficMonitorEnhanced] 获取到监控数据:", data);
if (data?.traffic?.raw && globalSampler) {
// 保存最后有效数据
lastValidData = data;
// if (data?.traffic?.raw && globalSampler) {
// // 保存最后有效数据
// lastValidData = data;
// 添加到采样器
const timestamp = Date.now();
const dataPoint: ITrafficDataPoint = {
up: data.traffic.raw.up_rate || 0,
down: data.traffic.raw.down_rate || 0,
timestamp,
name: new Date(timestamp).toLocaleTimeString("en-US", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}),
};
// // 添加到采样器
// const timestamp = Date.now();
// const dataPoint: ITrafficDataPoint = {
// up: data.traffic.raw.up_rate || 0,
// down: data.traffic.raw.down_rate || 0,
// timestamp,
// name: new Date(timestamp).toLocaleTimeString("en-US", {
// hour12: false,
// hour: "2-digit",
// minute: "2-digit",
// second: "2-digit",
// }),
// };
globalSampler.addDataPoint(dataPoint);
triggerUpdate();
}
},
onError: (error) => {
console.error(
"[TrafficMonitorEnhanced] 网络错误,使用最后有效数据. 错误详情:",
{
message: error?.message || "未知错误",
stack: error?.stack || "无堆栈信息",
},
);
// 网络错误时不清空数据,继续使用最后有效值
// 但是添加一个错误标记的数据点流量为0
if (globalSampler) {
const timestamp = Date.now();
const errorPoint: ITrafficDataPoint = {
up: 0,
down: 0,
timestamp,
name: new Date(timestamp).toLocaleTimeString("en-US", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}),
};
globalSampler.addDataPoint(errorPoint);
triggerUpdate();
}
},
},
);
// globalSampler.addDataPoint(dataPoint);
// triggerUpdate();
// }
// },
// onError: (error) => {
// console.error(
// "[TrafficMonitorEnhanced] 网络错误,使用最后有效数据. 错误详情:",
// {
// message: error?.message || "未知错误",
// stack: error?.stack || "无堆栈信息",
// },
// );
// // 网络错误时不清空数据,继续使用最后有效值
// // 但是添加一个错误标记的数据点流量为0
// if (globalSampler) {
// const timestamp = Date.now();
// const errorPoint: ITrafficDataPoint = {
// up: 0,
// down: 0,
// timestamp,
// name: new Date(timestamp).toLocaleTimeString("en-US", {
// hour12: false,
// hour: "2-digit",
// minute: "2-digit",
// second: "2-digit",
// }),
// };
// globalSampler.addDataPoint(errorPoint);
// triggerUpdate();
// }
// },
// },
// );
// 获取指定时间范围的数据
const getDataForTimeRange = useCallback(
@@ -324,28 +345,28 @@ export const useTrafficMonitorEnhanced = () => {
}, []);
// 构建返回的监控数据优先使用当前数据fallback到最后有效数据
const currentData = monitorData || lastValidData;
const trafficMonitorData = {
traffic: currentData?.traffic || {
raw: { up: 0, down: 0, up_rate: 0, down_rate: 0 },
formatted: {
up_rate: "0B",
down_rate: "0B",
total_up: "0B",
total_down: "0B",
},
is_fresh: false,
},
memory: currentData?.memory || {
raw: { inuse: 0, oslimit: 0, usage_percent: 0 },
formatted: { inuse: "0B", oslimit: "0B", usage_percent: 0 },
is_fresh: false,
},
};
// const currentData = monitorData.current || lastValidData;
// const trafficMonitorData = {
// traffic: currentData?.traffic || {
// raw: { up: 0, down: 0, up_rate: 0, down_rate: 0 },
// formatted: {
// up_rate: "0B",
// down_rate: "0B",
// total_up: "0B",
// total_down: "0B",
// },
// is_fresh: false,
// },
// memory: currentData?.memory || {
// raw: { inuse: 0, oslimit: 0, usage_percent: 0 },
// formatted: { inuse: "0B", oslimit: "0B", usage_percent: 0 },
// is_fresh: false,
// },
// };
return {
// 监控数据
monitorData: trafficMonitorData,
// monitorData: trafficMonitorData,
// 图表数据管理
graphData: {
@@ -355,10 +376,9 @@ export const useTrafficMonitorEnhanced = () => {
},
// 状态信息
isLoading: !currentData && !error,
error,
isDataFresh: currentData?.traffic?.is_fresh || false,
hasValidData: !!lastValidData,
// isLoading: !currentData,
// isDataFresh: currentData?.traffic?.is_fresh || false,
// hasValidData: !!lastValidData,
// 性能统计
samplerStats: getSamplerStats(),
@@ -369,30 +389,28 @@ export const useTrafficMonitorEnhanced = () => {
/**
* 轻量级流量数据Hook
*/
export const useTrafficDataEnhanced = () => {
const { monitorData, isLoading, error, isDataFresh, hasValidData } =
useTrafficMonitorEnhanced();
// export const useTrafficDataEnhanced = () => {
// const { monitorData, isLoading, isDataFresh, hasValidData } =
// useTrafficMonitorEnhanced();
return {
traffic: monitorData.traffic,
memory: monitorData.memory,
isLoading,
error,
isDataFresh,
hasValidData,
};
};
// return {
// traffic: monitorData.traffic,
// memory: monitorData.memory,
// isLoading,
// isDataFresh,
// hasValidData,
// };
// };
/**
* 图表数据Hook
*/
export const useTrafficGraphDataEnhanced = () => {
const { graphData, isDataFresh, samplerStats, referenceCount } =
const { graphData, samplerStats, referenceCount } =
useTrafficMonitorEnhanced();
return {
...graphData,
isDataFresh,
samplerStats,
referenceCount,
};