mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 08:45:41 +08:00
115 lines
3.8 KiB
TypeScript
115 lines
3.8 KiB
TypeScript
import { useTranslation } from "react-i18next";
|
||
import { Typography, Stack, Divider } from "@mui/material";
|
||
import { DeveloperBoardOutlined } from "@mui/icons-material";
|
||
import { useClashInfo } from "@/hooks/use-clash";
|
||
import { useClash } from "@/hooks/use-clash";
|
||
import { EnhancedCard } from "./enhanced-card";
|
||
import useSWR from "swr";
|
||
import { getRules } from "@/services/api";
|
||
import { getAppUptime, getSystemProxy } from "@/services/cmds";
|
||
import { useMemo, useState, useEffect } from "react";
|
||
|
||
// 将毫秒转换为时:分:秒格式的函数
|
||
const formatUptime = (uptimeMs: number) => {
|
||
const hours = Math.floor(uptimeMs / 3600000);
|
||
const minutes = Math.floor((uptimeMs % 3600000) / 60000);
|
||
const seconds = Math.floor((uptimeMs % 60000) / 1000);
|
||
return `${hours}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
||
};
|
||
|
||
export const ClashInfoCard = () => {
|
||
const { t } = useTranslation();
|
||
const { clashInfo } = useClashInfo();
|
||
const { version: clashVersion } = useClash();
|
||
const [sysproxy, setSysproxy] = useState<{ server: string; enable: boolean; bypass: string } | null>(null);
|
||
const [rules, setRules] = useState<any[]>([]);
|
||
|
||
// 使用SWR获取应用运行时间,降低更新频率
|
||
const { data: uptimeMs = 0 } = useSWR(
|
||
"appUptime",
|
||
getAppUptime,
|
||
{
|
||
refreshInterval: 1000,
|
||
revalidateOnFocus: false,
|
||
dedupingInterval: 1000,
|
||
},
|
||
);
|
||
|
||
// 在组件加载时获取系统代理信息和规则数据
|
||
useEffect(() => {
|
||
// 获取系统代理信息
|
||
getSystemProxy().then(setSysproxy);
|
||
|
||
// 获取规则数据
|
||
getRules().then(setRules).catch(() => setRules([]));
|
||
}, []);
|
||
|
||
// 使用useMemo缓存格式化后的uptime,避免频繁计算
|
||
const uptime = useMemo(() => formatUptime(uptimeMs), [uptimeMs]);
|
||
|
||
// 使用备忘录组件内容,减少重新渲染
|
||
const cardContent = useMemo(() => {
|
||
if (!clashInfo) return null;
|
||
|
||
return (
|
||
<Stack spacing={1.5}>
|
||
<Stack direction="row" justifyContent="space-between">
|
||
<Typography variant="body2" color="text.secondary">
|
||
{t("Core Version")}
|
||
</Typography>
|
||
<Typography variant="body2" fontWeight="medium">
|
||
{clashVersion || "-"}
|
||
</Typography>
|
||
</Stack>
|
||
<Divider />
|
||
<Stack direction="row" justifyContent="space-between">
|
||
<Typography variant="body2" color="text.secondary">
|
||
{t("System Proxy Address")}
|
||
</Typography>
|
||
<Typography variant="body2" fontWeight="medium">
|
||
{sysproxy?.server || "-"}
|
||
</Typography>
|
||
</Stack>
|
||
<Divider />
|
||
<Stack direction="row" justifyContent="space-between">
|
||
<Typography variant="body2" color="text.secondary">
|
||
{t("Mixed Port")}
|
||
</Typography>
|
||
<Typography variant="body2" fontWeight="medium">
|
||
{clashInfo.mixed_port || "-"}
|
||
</Typography>
|
||
</Stack>
|
||
<Divider />
|
||
<Stack direction="row" justifyContent="space-between">
|
||
<Typography variant="body2" color="text.secondary">
|
||
{t("Uptime")}
|
||
</Typography>
|
||
<Typography variant="body2" fontWeight="medium">
|
||
{uptime}
|
||
</Typography>
|
||
</Stack>
|
||
<Divider />
|
||
<Stack direction="row" justifyContent="space-between">
|
||
<Typography variant="body2" color="text.secondary">
|
||
{t("Rules Count")}
|
||
</Typography>
|
||
<Typography variant="body2" fontWeight="medium">
|
||
{rules.length}
|
||
</Typography>
|
||
</Stack>
|
||
</Stack>
|
||
);
|
||
}, [clashInfo, clashVersion, t, uptime, rules.length, sysproxy]);
|
||
|
||
return (
|
||
<EnhancedCard
|
||
title={t("Clash Info")}
|
||
icon={<DeveloperBoardOutlined />}
|
||
iconColor="warning"
|
||
action={null}
|
||
>
|
||
{cardContent}
|
||
</EnhancedCard>
|
||
);
|
||
};
|