From f2b7cff70cdd1c66dc95c77dc37e4f4a525ac765 Mon Sep 17 00:00:00 2001 From: "Km.Van" Date: Thu, 9 Jul 2026 22:45:05 +0800 Subject: [PATCH] adjust types adjust xconfig.toml --- pnpm-workspace.yaml | 6 + src/Components/Bootstrap/components/types.ts | 11 ++ .../BrowserBenchmark/components/types.ts | 14 +++ src/Components/Button/components/types.ts | 9 ++ src/Components/Config/types.ts | 13 ++ src/Components/Database/components/types.ts | 1 + src/Components/DiskUsage/components/types.ts | 8 ++ src/Components/Location/components/types.ts | 5 + src/Components/Module/components/types.ts | 11 ++ .../components/use-available-modules.ts | 30 +++++ src/Components/MyInfo/components/types.ts | 5 + .../NetworkStats/components/types.ts | 9 ++ src/Components/Nodes/components/types.ts | 11 ++ .../PhpExtensions/components/types.ts | 27 +++++ src/Components/PhpInfo/components/types.ts | 16 +++ src/Components/Ping/components/types.ts | 8 ++ src/Components/Poll/components/types.ts | 27 +++++ .../ServerBenchmark/components/types.ts | 15 +++ src/Components/ServerInfo/components/types.ts | 20 ++++ .../ServerStatus/components/types.ts | 19 +++ .../TemperatureSensor/components/types.ts | 8 ++ .../components/use-update-noti-text.ts | 32 +++++ src/Components/UserConfig/types.ts | 26 ++++ src/Components/Utils/UtilsTomlParser.php | 113 ++++++++++++++++++ .../Utils/components/fetch-status.ts | 1 + .../WindowConfig/components/types.ts | 7 ++ src/Components/ui/pie-chart/types.ts | 8 ++ xconfig.toml | 50 ++++++++ 28 files changed, 510 insertions(+) create mode 100644 pnpm-workspace.yaml create mode 100644 src/Components/Bootstrap/components/types.ts create mode 100644 src/Components/BrowserBenchmark/components/types.ts create mode 100644 src/Components/Button/components/types.ts create mode 100644 src/Components/Config/types.ts create mode 100644 src/Components/Database/components/types.ts create mode 100644 src/Components/DiskUsage/components/types.ts create mode 100644 src/Components/Location/components/types.ts create mode 100644 src/Components/Module/components/types.ts create mode 100644 src/Components/Module/components/use-available-modules.ts create mode 100644 src/Components/MyInfo/components/types.ts create mode 100644 src/Components/NetworkStats/components/types.ts create mode 100644 src/Components/Nodes/components/types.ts create mode 100644 src/Components/PhpExtensions/components/types.ts create mode 100644 src/Components/PhpInfo/components/types.ts create mode 100644 src/Components/Ping/components/types.ts create mode 100644 src/Components/Poll/components/types.ts create mode 100644 src/Components/ServerBenchmark/components/types.ts create mode 100644 src/Components/ServerInfo/components/types.ts create mode 100644 src/Components/ServerStatus/components/types.ts create mode 100644 src/Components/TemperatureSensor/components/types.ts create mode 100644 src/Components/Updater/components/use-update-noti-text.ts create mode 100644 src/Components/UserConfig/types.ts create mode 100644 src/Components/Utils/UtilsTomlParser.php create mode 100644 src/Components/Utils/components/fetch-status.ts create mode 100644 src/Components/WindowConfig/components/types.ts create mode 100644 src/Components/ui/pie-chart/types.ts create mode 100644 xconfig.toml diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..3fbfb93 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,6 @@ +allowBuilds: + '@parcel/watcher': true + core-js: true + esbuild: true +minimumReleaseAgeExclude: + - ultracite@7.9.2 diff --git a/src/Components/Bootstrap/components/types.ts b/src/Components/Bootstrap/components/types.ts new file mode 100644 index 0000000..978348f --- /dev/null +++ b/src/Components/Bootstrap/components/types.ts @@ -0,0 +1,11 @@ +export type BootstrapPollDataModel = { + isDev: boolean; + version: string; + appName: string; + appUrl: string; + appConfigUrls: string[]; + appConfigUrlDev: string; + authorUrl: string; + authorName: string; + authorization: string; +}; diff --git a/src/Components/BrowserBenchmark/components/types.ts b/src/Components/BrowserBenchmark/components/types.ts new file mode 100644 index 0000000..fd01f3a --- /dev/null +++ b/src/Components/BrowserBenchmark/components/types.ts @@ -0,0 +1,14 @@ +export type BrowserBenchmarkMarksProps = { + js: number; + dom: number; + canvas: number; +}; +export type BrowserBenchmarkProps = { + id: string; + name: string; + version: string; + ua: string; + date: string; + total: number; + detail: BrowserBenchmarkMarksProps; +}; diff --git a/src/Components/Button/components/types.ts b/src/Components/Button/components/types.ts new file mode 100644 index 0000000..72a285b --- /dev/null +++ b/src/Components/Button/components/types.ts @@ -0,0 +1,9 @@ +export const ButtonStatus = { + Error: "error", + Loading: "loading", + Pointer: "pointer", + Warning: "warning", +} as const; +export type ButtonStatusKey = keyof typeof ButtonStatus; +export type ButtonStatusValue = + (typeof ButtonStatus)[keyof typeof ButtonStatus]; diff --git a/src/Components/Config/types.ts b/src/Components/Config/types.ts new file mode 100644 index 0000000..84b0347 --- /dev/null +++ b/src/Components/Config/types.ts @@ -0,0 +1,13 @@ +export type ConfigProps = { + APP_VERSION: string; + APP_NAME: string; + APP_URL: string; + AUTHOR_URL: string; + UPDATE_PHP_URLS: string[]; + APP_CONFIG_URLS: string[]; + BENCHMARKS_URLS: string[]; + APP_CONFIG_URL_DEV: string; + AUTHOR_NAME: string; + LATEST_PHP_STABLE_VERSION: string; + LATEST_NGINX_STABLE_VERSION: string; +}; diff --git a/src/Components/Database/components/types.ts b/src/Components/Database/components/types.ts new file mode 100644 index 0000000..f57f905 --- /dev/null +++ b/src/Components/Database/components/types.ts @@ -0,0 +1 @@ +export type DatabasePollDataProps = Record; diff --git a/src/Components/DiskUsage/components/types.ts b/src/Components/DiskUsage/components/types.ts new file mode 100644 index 0000000..03d0ff3 --- /dev/null +++ b/src/Components/DiskUsage/components/types.ts @@ -0,0 +1,8 @@ +export type DiskUsageItemProps = { + id: string; + total: number; + free: number; +}; +export type DiskUsagePollDataProps = { + items: DiskUsageItemProps[]; +}; diff --git a/src/Components/Location/components/types.ts b/src/Components/Location/components/types.ts new file mode 100644 index 0000000..ef20cb2 --- /dev/null +++ b/src/Components/Location/components/types.ts @@ -0,0 +1,5 @@ +export type LocationProps = { + continent: string; + country: string; + city: string; +}; diff --git a/src/Components/Module/components/types.ts b/src/Components/Module/components/types.ts new file mode 100644 index 0000000..2764b90 --- /dev/null +++ b/src/Components/Module/components/types.ts @@ -0,0 +1,11 @@ +import type { FC } from "react"; + +export type ModuleProps = { + id: string; + content: FC; + nav: FC; +}; +export type SortedModuleProps = { + id: string; + priority: number; +}; diff --git a/src/Components/Module/components/use-available-modules.ts b/src/Components/Module/components/use-available-modules.ts new file mode 100644 index 0000000..9a6f1dc --- /dev/null +++ b/src/Components/Module/components/use-available-modules.ts @@ -0,0 +1,30 @@ +import { useMemo } from "react"; +import { useShallow } from "zustand/react/shallow"; +import { usePollStore } from "@/Components/Poll/components/store.ts"; +import type { PollData } from "@/Components/Poll/components/types.ts"; +import { presetModules } from "./preset.ts"; +import { useModuleStore } from "./store.ts"; +import type { ModuleProps } from "./types.ts"; + +export const useAvailableModules = (): ModuleProps[] => { + // 1. 获取完整的优先级顺序 + const priorities = useModuleStore((s) => s.priorities); + // 2. 获取服务端的有效性凭证 + const pollData = usePollStore(useShallow((s) => s.pollData)); + + // 3. 使用 useMemo 缓存计算结果,只有当底层数据改变时才重新计算 + const available = useMemo(() => { + if (!pollData) { + return []; + } + const maps = new Map(presetModules.map((item) => [item.id, item])); + return priorities + .map((id) => maps.get(id)) + .filter( + (n): n is ModuleProps => + !!n && Object.hasOwn(pollData as PollData, n.id) + ); + }, [priorities, pollData]); + + return available; +}; diff --git a/src/Components/MyInfo/components/types.ts b/src/Components/MyInfo/components/types.ts new file mode 100644 index 0000000..e324f62 --- /dev/null +++ b/src/Components/MyInfo/components/types.ts @@ -0,0 +1,5 @@ +export type MyInfoPollDataProps = { + ipv4: string; + ipv6: string; + phpLanguage: string; +}; diff --git a/src/Components/NetworkStats/components/types.ts b/src/Components/NetworkStats/components/types.ts new file mode 100644 index 0000000..910e002 --- /dev/null +++ b/src/Components/NetworkStats/components/types.ts @@ -0,0 +1,9 @@ +export type NetworkStatsItemProps = { + id: string; + rx: number; + tx: number; +}; +export type NetworkStatsPollDataProps = { + networks: NetworkStatsItemProps[]; + timestamp: number; +}; diff --git a/src/Components/Nodes/components/types.ts b/src/Components/Nodes/components/types.ts new file mode 100644 index 0000000..713486f --- /dev/null +++ b/src/Components/Nodes/components/types.ts @@ -0,0 +1,11 @@ +import type { PollData } from "@/Components/Poll/components/types"; + +export type NodesItemProps = { + id: string; + loading: boolean; + status: number; + data: PollData | null; +}; +export type NodesPollDataProps = { + nodesIds: string[]; +}; diff --git a/src/Components/PhpExtensions/components/types.ts b/src/Components/PhpExtensions/components/types.ts new file mode 100644 index 0000000..12e3911 --- /dev/null +++ b/src/Components/PhpExtensions/components/types.ts @@ -0,0 +1,27 @@ +export type PhpExtensionsPollDataProps = { + redis: boolean; + sqlite3: boolean; + memcache: boolean; + memcached: boolean; + opcache: boolean; + opcacheEnabled: boolean; + opcacheJitEnabled: boolean; + swoole: boolean; + imagick: boolean; + gmagick: boolean; + exif: boolean; + fileinfo: boolean; + simplexml: boolean; + sockets: boolean; + mysqli: boolean; + zip: boolean; + mbstring: boolean; + phalcon: boolean; + xdebug: boolean; + zendOptimizer: boolean; + ionCube: boolean; + sourceGuardian: boolean; + ldap: boolean; + curl: boolean; + loadedExtensions: string[]; +}; diff --git a/src/Components/PhpInfo/components/types.ts b/src/Components/PhpInfo/components/types.ts new file mode 100644 index 0000000..0f8d36c --- /dev/null +++ b/src/Components/PhpInfo/components/types.ts @@ -0,0 +1,16 @@ +export type PhpInfoPollDataProps = { + phpVersion: string; + sapi: string; + displayErrors: boolean; + errorReporting: number; + memoryLimit: string; + postMaxSize: string; + uploadMaxFilesize: string; + maxInputVars: number; + maxExecutionTime: number; + defaultSocketTimeout: number; + allowUrlFopen: boolean; + smtp: boolean; + disableFunctions: string[]; + disableClasses: string[]; +}; diff --git a/src/Components/Ping/components/types.ts b/src/Components/Ping/components/types.ts new file mode 100644 index 0000000..2909f13 --- /dev/null +++ b/src/Components/Ping/components/types.ts @@ -0,0 +1,8 @@ +export type ServerToBrowserPingItemProps = { + id: string; + time: number; +}; +export type ServerToBrowserPingProps = { + location: string; + items: ServerToBrowserPingItemProps[]; +}; diff --git a/src/Components/Poll/components/types.ts b/src/Components/Poll/components/types.ts new file mode 100644 index 0000000..089ab7a --- /dev/null +++ b/src/Components/Poll/components/types.ts @@ -0,0 +1,27 @@ +import type { ConfigProps } from "@/Components/Config/types"; +import type { DatabasePollDataProps } from "@/Components/Database/components/types"; +import type { DiskUsagePollDataProps } from "@/Components/DiskUsage/components/types"; +import type { MyInfoPollDataProps } from "@/Components/MyInfo/components/types"; +import type { NetworkStatsPollDataProps } from "@/Components/NetworkStats/components/types"; +import type { NodesPollDataProps } from "@/Components/Nodes/components/types"; +import type { PhpExtensionsPollDataProps } from "@/Components/PhpExtensions/components/types"; +import type { PhpInfoPollDataProps } from "@/Components/PhpInfo/components/types"; +import type { ServerInfoPollDataProps } from "@/Components/ServerInfo/components/types"; +import type { ServerStatusPollDataProps } from "@/Components/ServerStatus/components/types"; +import type { TemperatureSensorPollDataProps } from "@/Components/TemperatureSensor/components/types"; +import type { UserConfigProps } from "@/Components/UserConfig/types"; + +export type PollData = { + config: ConfigProps | null; + userConfig: UserConfigProps | null; + database: DatabasePollDataProps | null; + myInfo: MyInfoPollDataProps | null; + phpInfo: PhpInfoPollDataProps | null; + diskUsage: DiskUsagePollDataProps | null; + networkStats: NetworkStatsPollDataProps | null; + phpExtensions: PhpExtensionsPollDataProps | null; + serverStatus: ServerStatusPollDataProps | null; + serverInfo: ServerInfoPollDataProps | null; + nodes: NodesPollDataProps | null; + temperatureSensor: TemperatureSensorPollDataProps | null; +}; diff --git a/src/Components/ServerBenchmark/components/types.ts b/src/Components/ServerBenchmark/components/types.ts new file mode 100644 index 0000000..9dd6879 --- /dev/null +++ b/src/Components/ServerBenchmark/components/types.ts @@ -0,0 +1,15 @@ +export type ServerBenchmarkMarksProps = { + cpu: number; + read: number; + write: number; +}; +export type ServerBenchmarkProps = { + id: string; + name: string; + url: string; + date: string; + probeUrl: string; + binUrl: string; + total: number; + detail: ServerBenchmarkMarksProps; +}; diff --git a/src/Components/ServerInfo/components/types.ts b/src/Components/ServerInfo/components/types.ts new file mode 100644 index 0000000..75f1f65 --- /dev/null +++ b/src/Components/ServerInfo/components/types.ts @@ -0,0 +1,20 @@ +export type ServerInfoUptimeProps = { + days: number; + hours: number; + mins: number; + secs: number; +}; +export type ServerInfoPollDataProps = { + serverName: string; + serverUtcTime: string; + serverTime: string; + localIpv4: string; + localIpv6: string; + serverUptime: ServerInfoUptimeProps; + serverIp: string; + serverSoftware: string; + phpVersion: string; + cpuModel: string; + serverOs: string; + scriptPath: string; +}; diff --git a/src/Components/ServerStatus/components/types.ts b/src/Components/ServerStatus/components/types.ts new file mode 100644 index 0000000..a687d61 --- /dev/null +++ b/src/Components/ServerStatus/components/types.ts @@ -0,0 +1,19 @@ +export type ServerStatusUsageProps = { + max: number; + value: number; +}; +export type ServerStatusCpuUsageProps = { + usage: number; + idle: number; + sys: number; + user: number; +}; +export type ServerStatusPollDataProps = { + sysLoad: number[]; + cpuUsage: ServerStatusCpuUsageProps; + memRealUsage: ServerStatusUsageProps; + memBuffers: ServerStatusUsageProps; + memCached: ServerStatusUsageProps; + swapUsage: ServerStatusUsageProps; + swapCached: ServerStatusUsageProps; +}; diff --git a/src/Components/TemperatureSensor/components/types.ts b/src/Components/TemperatureSensor/components/types.ts new file mode 100644 index 0000000..c2b0fb1 --- /dev/null +++ b/src/Components/TemperatureSensor/components/types.ts @@ -0,0 +1,8 @@ +export type TemperatureSensorItemProps = { + id: string; + name: string; + celsius: number; +}; +export type TemperatureSensorPollDataProps = { + items: TemperatureSensorItemProps[]; +}; diff --git a/src/Components/Updater/components/use-update-noti-text.ts b/src/Components/Updater/components/use-update-noti-text.ts new file mode 100644 index 0000000..f79119d --- /dev/null +++ b/src/Components/Updater/components/use-update-noti-text.ts @@ -0,0 +1,32 @@ +import { useShallow } from "zustand/react/shallow"; +import { useConfigStore } from "@/Components/Config/store"; +import { gettext } from "@/Components/Language"; +import { template } from "@/Components/Utils/components/template"; +import { useUpdaterStore } from "./store"; + +export const useUpdateNotiText = (): string => { + const { isUpdating, hasUpdateError, targetVersion } = useUpdaterStore( + useShallow((s) => ({ + isUpdating: s.isUpdating, + hasUpdateError: s.hasUpdateError, + targetVersion: s.targetVersion, + })) + ); + const AppVersion = useConfigStore((s) => s?.pollData?.APP_VERSION ?? "-"); + if (isUpdating) { + return gettext("⏳ Updating, please wait a second..."); + } + if (hasUpdateError) { + return gettext("❌ Update error, click here to try again?"); + } + if (targetVersion) { + return template( + gettext("✨ Found new version: {{oldVersion}} ⇢ {{newVersion}}"), + { + oldVersion: AppVersion, + newVersion: targetVersion, + } + ); + } + return ""; +}; diff --git a/src/Components/UserConfig/types.ts b/src/Components/UserConfig/types.ts new file mode 100644 index 0000000..8a3b452 --- /dev/null +++ b/src/Components/UserConfig/types.ts @@ -0,0 +1,26 @@ +export const UserConfigDisableFeature = { + Database: "database", + DiskUsage: "diskUsage", + MyInfo: "myInfo", + MyServerBenchmark: "myServerBenchmark", + NetworkStats: "networkStats", + PhpDisabledClasses: "phpDisabledClasses", + PhpDisabledFunctions: "phpDisabledFunctions", + PhpExtensions: "phpExtensions", + PhpExtensionsLoaded: "phpExtensionsLoaded", + PhpInfo: "phpInfo", + PhpInfoDetail: "phpInfoDetail", + Ping: "ping", + ServerInfo: "serverInfo", + ServerIp: "serverIp", + ServerStatus: "serverStatus", +} as const; +export type UserConfigDisableFeatureKey = keyof typeof UserConfigDisableFeature; +export type UserConfigDisableFeatureValue = + (typeof UserConfigDisableFeature)[keyof typeof UserConfigDisableFeature]; +export type UserConfigNodeProps = [nodeName: string, url: string]; +export type UserConfigProps = { + serverBenchmarkCd?: number; + nodes?: UserConfigNodeProps[]; + disabled?: UserConfigDisableFeatureKey; +}; diff --git a/src/Components/Utils/UtilsTomlParser.php b/src/Components/Utils/UtilsTomlParser.php new file mode 100644 index 0000000..f9eccc3 --- /dev/null +++ b/src/Components/Utils/UtilsTomlParser.php @@ -0,0 +1,113 @@ + $line) { + $line = trim($line); + + if ('' === $line || '#' === $line[0]) { + continue; + } + + if ('[' === $line[0] && ']' === substr($line, -1)) { + $group_name = substr($line, 1, -1); + $groups = explode('.', $group_name); + + $current_group = &$result; + foreach ($groups as $g) { + if ( ! isset($current_group[$g])) { + $current_group[$g] = []; + } + $current_group = &$current_group[$g]; + } + continue; + } + + if (false !== strpos($line, '=')) { + [$key, $value] = explode('=', $line, 2); + $key = trim($key); + $value = trim($value); + + $parsed_value = self::parse_value($value); + $current_group[$key] = $parsed_value; + } + } + + return $result; + } + + public static function parse_value($value) + { + if (preg_match('/^"(.*)"$/', $value, $matches)) { + return str_replace('\\"', '"', $matches[1]); + } + + if (preg_match("/^'(.*)'$/", $value, $matches)) { + return $matches[1]; + } + + if ('true' === $value) { + return true; + } + if ('false' === $value) { + return false; + } + + if (preg_match('/^-?\\d+$/', $value)) { + return (int) $value; + } + + if (preg_match('/^-?\\d+\\.\\d+$/', $value)) { + return (float) $value; + } + + if ('[' === $value[0] && ']' === substr($value, -1)) { + $inner = trim(substr($value, 1, -1)); + if ('' === $inner) { + return []; + } + + $items = []; + $current = ''; + $in_string = false; + $string_char = ''; + $i = 0; + $len = \strlen($inner); + + while ($i < $len) { + $char = $inner[$i]; + + if ( ! $in_string && ('"' === $char || "'" === $char)) { + $in_string = true; + $string_char = $char; + $current .= $char; + } elseif ($in_string && $char === $string_char && '\\' !== $inner[$i - 1]) { + $in_string = false; + $current .= $char; + } elseif ( ! $in_string && ',' === $char) { + $items[] = self::parse_value(trim($current)); + $current = ''; + } else { + $current .= $char; + } + ++$i; + } + + if ('' !== trim($current)) { + $items[] = self::parse_value(trim($current)); + } + + return $items; + } + + return trim($value, '"\''); + } +} diff --git a/src/Components/Utils/components/fetch-status.ts b/src/Components/Utils/components/fetch-status.ts new file mode 100644 index 0000000..ada2d63 --- /dev/null +++ b/src/Components/Utils/components/fetch-status.ts @@ -0,0 +1 @@ +export type FetchStatus = "loading" | "idel" | "error"; diff --git a/src/Components/WindowConfig/components/types.ts b/src/Components/WindowConfig/components/types.ts new file mode 100644 index 0000000..70acf13 --- /dev/null +++ b/src/Components/WindowConfig/components/types.ts @@ -0,0 +1,7 @@ +export type WindowConfigProps = { + IS_DEV: boolean; + AUTHORIZATION: string; +}; +export type WindowProps = { + GLOBAL_CONFIG: WindowConfigProps; +}; diff --git a/src/Components/ui/pie-chart/types.ts b/src/Components/ui/pie-chart/types.ts new file mode 100644 index 0000000..2aa96bc --- /dev/null +++ b/src/Components/ui/pie-chart/types.ts @@ -0,0 +1,8 @@ +export const PieChartStatus = { + High: "high", + Low: "low", + Medium: "medium", +} as const; +export type PieChartStatusKey = keyof typeof PieChartStatus; +export type PieChartStatusValue = + (typeof PieChartStatus)[keyof typeof PieChartStatus]; diff --git a/xconfig.toml b/xconfig.toml new file mode 100644 index 0000000..d717307 --- /dev/null +++ b/xconfig.toml @@ -0,0 +1,50 @@ +# ============================================================================= +# X-Prober 配置文件 | X-Prober Configuration +# ============================================================================= + +# ----------------------------------------------------------------------------- +# 功能开关 | Feature Toggles +# ----------------------------------------------------------------------------- +# 禁用特定功能以增强安全性或减少系统开销。 +# Disable specific features to improve security or reduce overhead. +# +# 可用选项 | Available options: serverStatus, diskUsage, networkStats, ping, +# serverInfo, phpInfo, phpInfoDetail, phpDisabledFunctions, +# phpDisabledClasses, phpExtensions, phpExtensionsLoaded, database, +# myServerBenchmark, myInfo, serverIp +# +# disabled = ["serverIp", "phpInfoDetail"] + +# ----------------------------------------------------------------------------- +# 硬件监控 | Hardware Monitoring +# ----------------------------------------------------------------------------- +# 温度传感器接口地址(例如:树莓派传感器)。 +# Temperature sensor endpoints (e.g., Raspberry Pi sensors). +# +# 参考文档 | Reference: /extensions/temperature-sensors/raspberrypi.js +# +# temperatureSensors = [ +# "http://localhost:4096" +# ] + +# ----------------------------------------------------------------------------- +# 性能测试 | Performance Testing +# ----------------------------------------------------------------------------- +# 服务器基准测试冷却时间(秒),防止频繁测试导致服务器过载。 +# Cooldown period between server benchmark runs (in seconds). +# Prevents excessive load from frequent testing. +# +# serverBenchmarkCd = 30 + +# ----------------------------------------------------------------------------- +# 多节点聚合 | Multi-Node Aggregation +# ----------------------------------------------------------------------------- +# 定义其他 X-Prober 节点,用于聚合仪表盘展示。 +# Define additional X-Prober nodes for aggregated dashboard view. +# +# 格式 | Format: ["显示名称", "节点地址"] | ["display-name", "node-url"] +# +# nodes = [ +# ["node-1", "http://localhost:5173"], +# ["node-3", "http://localhost:5173"] +# ]