diff --git a/go.mod b/go.mod index f2f3017c..b320be28 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/oneclickvirt/ecs go 1.25.4 require ( + github.com/charmbracelet/bubbles v1.0.0 github.com/charmbracelet/bubbletea v1.3.10 github.com/charmbracelet/lipgloss v1.1.0 github.com/imroc/req/v3 v3.54.0 @@ -27,11 +28,15 @@ require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/andybalholm/cascadia v1.3.2 // indirect + github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect - github.com/charmbracelet/x/ansi v0.10.1 // indirect - github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect - github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/charmbracelet/colorprofile v0.4.1 // indirect + github.com/charmbracelet/x/ansi v0.11.6 // indirect + github.com/charmbracelet/x/cellbuf v0.0.15 // indirect + github.com/charmbracelet/x/term v0.2.2 // indirect + github.com/clipperhouse/displaywidth v0.9.0 // indirect + github.com/clipperhouse/stringish v0.1.1 // indirect + github.com/clipperhouse/uax29/v2 v2.5.0 // indirect github.com/cloudflare/circl v1.6.1 // indirect github.com/ebitengine/purego v0.8.4 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect @@ -56,12 +61,12 @@ require ( github.com/koron/go-ssdp v0.0.4 // indirect github.com/libp2p/go-nat v0.2.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/lucasb-eyer/go-colorful v1.3.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.19 // indirect github.com/miekg/dns v1.1.61 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect diff --git a/go.sum b/go.sum index 01217377..ccdc767a 100644 --- a/go.sum +++ b/go.sum @@ -6,22 +6,40 @@ github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwTo github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= +github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= +github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ= github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= +github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= +github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= +github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= +github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= +github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA= +github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA= +github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= +github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= +github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U= +github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -93,6 +111,8 @@ github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9t github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= +github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= @@ -103,6 +123,8 @@ github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2J github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= +github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= diff --git a/internal/menu/tui.go b/internal/menu/tui.go index a53f80c3..faee9de3 100644 --- a/internal/menu/tui.go +++ b/internal/menu/tui.go @@ -120,14 +120,14 @@ type tuiModel struct { func defaultMainItems() []mainMenuItem { return []mainMenuItem{ {id: "1", zh: "融合怪完全体(能测全测)", en: "Full Test (All Available Tests)", descZh: "系统信息、CPU、内存、磁盘、解锁、IP质量、邮件端口、回程、NT3、测速、TGDC、网站延迟。", descEn: "Runs all available modules: system, compute, memory, disk, unlock, security, routing and speed.", needNet: false}, - {id: "2", zh: "极简版", en: "Minimal Suite", descZh: "基础系统+CPU+内存+磁盘+5个测速节点,适合快速健康检查。", descEn: "Basic system + CPU + memory + disk + 5 speed nodes for quick health checks.", needNet: false}, - {id: "3", zh: "精简版", en: "Standard Suite", descZh: "在极简版基础上增加平台解锁与路由能力评估。", descEn: "Minimal suite plus unlock and routing capability checks.", needNet: false}, - {id: "4", zh: "精简网络版", en: "Network Suite", descZh: "强调网络回程与路由质量,辅以基础硬件测试。", descEn: "Network-focused profile with backtrace/routing plus basic hardware checks.", needNet: false}, - {id: "5", zh: "精简解锁版", en: "Unlock Suite", descZh: "以流媒体和平台解锁能力为主,附基础性能测试。", descEn: "Unlock-focused profile with essential compute/storage checks.", needNet: false}, + {id: "2", zh: "极简版", en: "Minimal Suite", descZh: "系统信息+CPU+内存+磁盘+测速节点×5,不含解锁/网络/路由测试。", descEn: "System info + CPU + memory + disk + 5 speed nodes. No unlock/network/routing tests.", needNet: false}, + {id: "3", zh: "精简版", en: "Standard Suite", descZh: "系统信息+CPU+内存+磁盘+跨国平台解锁+三网回程路由+测速节点×5。", descEn: "System info + CPU + memory + disk + streaming unlock + 3-network routing + 5 speed nodes.", needNet: false}, + {id: "4", zh: "精简网络版", en: "Network Suite", descZh: "系统信息+CPU+内存+磁盘+上游及三网回程路由+测速节点×5。", descEn: "System info + CPU + memory + disk + upstream/3-network backtrace routing + 5 speed nodes.", needNet: false}, + {id: "5", zh: "精简解锁版", en: "Unlock Suite", descZh: "系统信息+CPU+内存+磁盘IO+跨国平台解锁+测速节点×5。", descEn: "System info + CPU + memory + disk IO + streaming unlock + 5 speed nodes.", needNet: false}, {id: "6", zh: "网络单项", en: "Network Only", descZh: "仅网络维度:IP质量、回程、NT3、延迟、TGDC、网站和测速。", descEn: "Network-only profile: IP quality, route, latency, TGDC, websites, speed.", needNet: true}, {id: "7", zh: "解锁单项", en: "Unlock Only", descZh: "仅进行跨国平台解锁与流媒体可用性检测。", descEn: "Unlock-only profile for cross-border media/service availability.", needNet: true}, {id: "8", zh: "硬件单项", en: "Hardware Only", descZh: "系统信息、CPU、内存、dd/fio 磁盘测试。", descEn: "Hardware-only profile with system, CPU, memory and disk tests.", needNet: false}, - {id: "9", zh: "IP质量检测", en: "IP Quality", descZh: "15库 IP质量 + 邮件端口,适合网络身份风险评估。", descEn: "IP quality across multiple datasets plus email port checks.", needNet: true}, + {id: "9", zh: "IP质量检测", en: "IP Quality", descZh: "15个数据库IP质量检测+邮件端口连通性检测。", descEn: "IP quality check across 15 databases + email port connectivity test.", needNet: true}, {id: "10", zh: "三网回程线路", en: "3-Network Route", descZh: "三网回程、NT3路由、延迟、TGDC、网站延迟专项。", descEn: "3-network backtrace + NT3 route + latency/TGDC/website checks.", needNet: true}, {id: "custom", zh: ">>> 高级自定义(全参数模式)", en: ">>> Advanced Custom (Full Parameters)", descZh: "按参数逐项配置,支持测试项、方法、路径、上传和结果分析。", descEn: "Configure per-parameter with test toggles, methods, paths, upload and analysis.", needNet: false}, {id: "0", zh: "退出程序", en: "Exit Program", descZh: "退出当前程序。", descEn: "Exit program.", needNet: false}, @@ -147,7 +147,7 @@ func defaultTestToggles() []testToggle { {key: "nt3", nameZh: "NT3路由", nameEn: "NT3 Route", descZh: "按指定地区与协议执行详细路由追踪。", descEn: "Run detailed route trace by selected location/protocol.", enabled: false, needNet: true}, {key: "speed", nameZh: "测速", nameEn: "Speed Test", descZh: "测试下载/上传带宽与延迟。", descEn: "Measure download/upload bandwidth and latency.", enabled: false, needNet: true}, {key: "ping", nameZh: "Ping测试", nameEn: "Ping Test", descZh: "全国/多地区延迟质量测试。", descEn: "Latency quality checks across multiple regions.", enabled: false, needNet: true}, - {key: "tgdc", nameZh: "Telegram DC测试", nameEn: "Telegram DC Test", descZh: "检测 Telegram 数据中心延迟表现。", descEn: "Measure latency to Telegram data centers.", enabled: false, needNet: true}, + {key: "tgdc", nameZh: "Telegram DC测试", nameEn: "Telegram DC Test", descZh: "检测各 Telegram 数据中心节点延迟。", descEn: "Measure latency to each Telegram data center node.", enabled: false, needNet: true}, {key: "web", nameZh: "网站延迟", nameEn: "Website Latency", descZh: "检测常见网站访问延迟。", descEn: "Check latency to commonly used websites.", enabled: false, needNet: true}, } } @@ -160,43 +160,43 @@ func defaultAdvSettings(config *params.Config) []advSetting { adv := []advSetting{ { key: "cpum", nameZh: "CPU测试方法", nameEn: "CPU Method", kind: "option", - descZh: "选择 CPU 压测方法,不同方法偏向不同负载模型。", - descEn: "Choose CPU benchmark method. Different methods model different workloads.", + descZh: "选择 CPU 基准测试工具(sysbench/geekbench/winsat)。", + descEn: "Choose CPU benchmark tool (sysbench/geekbench/winsat).", options: []advOption{ - option("sysbench", "Sysbench", "Sysbench", "通用基准,稳定易比较。", "General-purpose benchmark with stable comparability."), - option("geekbench", "Geekbench", "Geekbench", "偏综合应用模型,便于横向对比。", "Application-like synthetic benchmark for broad comparison."), - option("winsat", "WinSAT", "WinSAT", "Windows 场景下常用基准。", "Common benchmark in Windows environments."), + option("sysbench", "Sysbench", "Sysbench", "通用 CPU 基准测试工具。", "General-purpose CPU benchmark tool."), + option("geekbench", "Geekbench", "Geekbench", "综合场景 CPU 基准测试工具。", "Synthetic benchmark simulating real-world application workloads."), + option("winsat", "WinSAT", "WinSAT", "Windows 环境下的 CPU 基准测试工具。", "CPU benchmark tool for Windows environments."), }, }, { key: "cput", nameZh: "CPU线程模式", nameEn: "CPU Thread Mode", kind: "option", - descZh: "单线程看核心峰值,多线程看整机并发能力。", - descEn: "Single-core shows peak core power; multi-core shows parallel throughput.", + descZh: "单线程: 测试单核最高运算速度; 多线程: 测试全核并发吞吐。", + descEn: "Single-thread: peak single-core speed; Multi-thread: full-core parallel throughput.", options: []advOption{ - option("multi", "多线程", "Multi-thread", "评估整机并发算力。", "Evaluate full-machine parallel compute capability."), - option("single", "单线程", "Single-thread", "评估单核心峰值性能。", "Evaluate peak single-core performance."), + option("multi", "多线程", "Multi-thread", "测试所有核心并发运算吞吐。", "Measure parallel compute throughput across all cores."), + option("single", "单线程", "Single-thread", "测试单核最高运算速度。", "Measure peak single-core compute speed."), }, }, { key: "memorym", nameZh: "内存测试方法", nameEn: "Memory Method", kind: "option", - descZh: "选择内存测试方法,结果关注带宽与访问效率。", - descEn: "Choose memory benchmark method to evaluate bandwidth/access efficiency.", + descZh: "选择内存基准测试工具。", + descEn: "Choose memory benchmark tool.", options: []advOption{ - option("stream", "STREAM", "STREAM", "侧重带宽测试。", "Focused on memory bandwidth."), - option("sysbench", "Sysbench", "Sysbench", "通用内存压测。", "General-purpose memory stress benchmark."), - option("dd", "dd", "dd", "基于系统工具的简化测试。", "Simple system-tool-based measurement."), - option("winsat", "WinSAT", "WinSAT", "Windows 环境内存基准。", "Windows-oriented memory benchmark."), - option("auto", "自动", "Auto", "自动选择可用且优先方法。", "Automatically select the preferred available method."), + option("stream", "STREAM", "STREAM", "专项内存带宽基准测试工具(STREAM)。", "Memory bandwidth benchmark tool (STREAM)."), + option("sysbench", "Sysbench", "Sysbench", "通用内存基准测试工具。", "General-purpose memory benchmark tool."), + option("dd", "dd", "dd", "使用 dd 命令测量内存顺序读写。", "Measure memory sequential R/W using dd command."), + option("winsat", "WinSAT", "WinSAT", "Windows 环境内存基准测试工具。", "Memory benchmark tool for Windows environments."), + option("auto", "自动", "Auto", "按优先级自动选择可用测试工具。", "Automatically select the preferred available tool."), }, }, { key: "diskm", nameZh: "磁盘测试方法", nameEn: "Disk Method", kind: "option", - descZh: "选择磁盘测试方法,评估顺序/随机读写能力。", - descEn: "Choose disk method to evaluate sequential/random I/O performance.", + descZh: "选择磁盘基准测试工具。", + descEn: "Choose disk benchmark tool.", options: []advOption{ - option("fio", "FIO", "FIO", "更全面的磁盘 I/O 基准。", "Comprehensive disk I/O benchmark."), - option("dd", "dd", "dd", "快速顺序写读基准。", "Quick sequential write/read benchmark."), - option("winsat", "WinSAT", "WinSAT", "Windows 磁盘基准。", "Disk benchmark for Windows environments."), + option("fio", "FIO", "FIO", "多队列深度顺序/随机 I/O 全面基准测试。", "Comprehensive sequential/random I/O benchmark with multiple queue depths."), + option("dd", "dd", "dd", "使用 dd 命令进行顺序读写基准测试。", "Sequential read/write benchmark using dd command."), + option("winsat", "WinSAT", "WinSAT", "Windows 环境磁盘基准测试工具。", "Disk benchmark tool for Windows environments."), }, }, { @@ -207,10 +207,16 @@ func defaultAdvSettings(config *params.Config) []advSetting { }, { key: "diskmc", nameZh: "多磁盘检测", nameEn: "Multi-Disk Check", kind: "bool", - descZh: "启用后尝试检测并测试多磁盘路径。", - descEn: "When enabled, detect and benchmark multiple disk paths.", + descZh: "启用后检测并测试所有已挂载磁盘路径。", + descEn: "When enabled, detect and benchmark all mounted disk paths.", boolVal: config.DiskMultiCheck, }, + { + key: "autodiskm", nameZh: "磁盘方法失败自动切换", nameEn: "Auto Switch Disk Method", kind: "bool", + descZh: "所选磁盘测试方法失败时自动切换为其他可用方法。", + descEn: "Automatically try another available disk method if the selected method fails.", + boolVal: config.AutoChangeDiskMethod, + }, { key: "nt3loc", nameZh: "NT3测试地区", nameEn: "NT3 Location", kind: "option", descZh: "选择路由追踪地区。显示中文全称,内部仍使用标准参数值。", @@ -235,19 +241,19 @@ func defaultAdvSettings(config *params.Config) []advSetting { }, { key: "spnum", nameZh: "测速节点数/运营商", nameEn: "Speed Nodes per ISP", kind: "option", - descZh: "每个运营商选择的测速节点数量。", - descEn: "Number of speed test nodes selected per ISP.", + descZh: "每个运营商参与测速的节点数量。", + descEn: "Number of speed test nodes per ISP.", options: []advOption{ - option("1", "1 个", "1 node", "最快速,覆盖最少。", "Fastest run with least coverage."), - option("2", "2 个", "2 nodes", "默认平衡。", "Default balanced option."), - option("3", "3 个", "3 nodes", "覆盖更广,耗时增加。", "Broader coverage with more runtime."), - option("4", "4 个", "4 nodes", "更完整网络采样。", "More complete network sampling."), - option("5", "5 个", "5 nodes", "高覆盖,耗时较高。", "High coverage with longer runtime."), - option("6", "6 个", "6 nodes", "深度采样。", "Deep sampling."), - option("7", "7 个", "7 nodes", "深度采样。", "Deep sampling."), - option("8", "8 个", "8 nodes", "深度采样。", "Deep sampling."), - option("9", "9 个", "9 nodes", "深度采样。", "Deep sampling."), - option("10", "10 个", "10 nodes", "最全面,耗时最高。", "Most comprehensive, longest runtime."), + option("1", "1 个", "1 node", "每运营商1节点,耗时最短,覆盖面最小。", "1 node per ISP, shortest runtime, least coverage."), + option("2", "2 个", "2 nodes", "每运营商2节点(默认值)。", "2 nodes per ISP (default)."), + option("3", "3 个", "3 nodes", "每运营商3节点,覆盖面扩大,耗时增加。", "3 nodes per ISP, wider coverage, longer runtime."), + option("4", "4 个", "4 nodes", "每运营商4节点。", "4 nodes per ISP."), + option("5", "5 个", "5 nodes", "每运营商5节点,覆盖面宽,耗时较高。", "5 nodes per ISP, wide coverage, higher runtime."), + option("6", "6 个", "6 nodes", "每运营商6节点。", "6 nodes per ISP."), + option("7", "7 个", "7 nodes", "每运营商7节点。", "7 nodes per ISP."), + option("8", "8 个", "8 nodes", "每运营商8节点。", "8 nodes per ISP."), + option("9", "9 个", "9 nodes", "每运营商9节点。", "9 nodes per ISP."), + option("10", "10 个", "10 nodes", "每运营商10节点,覆盖面最宽,耗时最高。", "10 nodes per ISP, widest coverage, longest runtime."), }, }, { @@ -264,8 +270,8 @@ func defaultAdvSettings(config *params.Config) []advSetting { }, { key: "analysis", nameZh: "测试后结果总结分析", nameEn: "Post-Test Summary Analysis", kind: "bool", - descZh: "测试结束后生成简明总结,提炼优势、短板和用途建议。", - descEn: "Generate concise final summary with strengths, limits and usage hints.", + descZh: "测试结束后输出简明总结(含CPU排名、带宽和延迟数据)。", + descEn: "Output a concise summary after tests (CPU rank, bandwidth, latency scores).", boolVal: config.AnalyzeResult, }, { @@ -766,11 +772,28 @@ func (m tuiModel) viewCustom() string { var s strings.Builder s.WriteString("\n") if lang == "zh" { - s.WriteString(tTitleStyle.Render(" 高级自定义参数模式")) + s.WriteString(tTitleStyle.Render(fmt.Sprintf(" VPS融合怪 %s — 高级自定义", m.config.EcsVersion))) } else { - s.WriteString(tTitleStyle.Render(" Advanced Custom Parameter Mode")) + s.WriteString(tTitleStyle.Render(fmt.Sprintf(" VPS Fusion Monster %s — Advanced Custom", m.config.EcsVersion))) } - s.WriteString("\n\n") + s.WriteString("\n") + if m.preCheck.Connected && m.cmpVersion == -1 { + if lang == "zh" { + s.WriteString(tWarnStyle.Render(fmt.Sprintf(" ! 检测到新版本 %s 如有必要请更新", m.newVersion))) + } else { + s.WriteString(tWarnStyle.Render(fmt.Sprintf(" ! New version %s detected", m.newVersion))) + } + s.WriteString("\n") + } + if m.preCheck.Connected && m.hasStats { + if lang == "zh" { + s.WriteString(tInfoStyle.Render(fmt.Sprintf(" 总使用量: %s | 今日使用: %s", utils.FormatGoecsNumber(m.statsTotal), utils.FormatGoecsNumber(m.statsDaily)))) + } else { + s.WriteString(tInfoStyle.Render(fmt.Sprintf(" Total Usage: %s | Daily Usage: %s", utils.FormatGoecsNumber(m.statsTotal), utils.FormatGoecsNumber(m.statsDaily)))) + } + s.WriteString("\n") + } + s.WriteString("\n") if lang == "zh" { s.WriteString(tSectStyle.Render(" 测试开关 (空格切换, a 全选/全不选):")) } else { @@ -967,6 +990,8 @@ func applyCustomResult(result tuiResult, preCheck utils.NetCheckResult, config * config.DiskTestPath = strings.TrimSpace(a.textVal) case "diskmc": config.DiskMultiCheck = a.boolVal + case "autodiskm": + config.AutoChangeDiskMethod = a.boolVal case "nt3loc": config.Nt3Location = a.options[a.current].value case "nt3t": @@ -995,5 +1020,4 @@ func applyCustomResult(result tuiResult, preCheck utils.NetCheckResult, config * if !config.BasicStatus && !config.CpuTestStatus && !config.MemoryTestStatus && !config.DiskTestStatus { config.OnlyIpInfoCheck = true } - config.AutoChangeDiskMethod = true }