From 19b18d091a59442183d6a7fa7d53249372ecbcff Mon Sep 17 00:00:00 2001 From: Julian Freeman Date: Wed, 26 Nov 2025 09:04:52 -0400 Subject: [PATCH] split UI --- src-tauri/Cargo.lock | 348 ++++++++++++++++++- src-tauri/Cargo.toml | 2 + src-tauri/src/main.rs | 234 +++++++++---- src/App.vue | 788 +++++++++++++++++++----------------------- 4 files changed, 886 insertions(+), 486 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f563eb0..d3e1965 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -280,6 +280,24 @@ dependencies = [ "piper", ] +[[package]] +name = "breakpad-symbols" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b002797414ffc34425bdf5b21a9e50d102013292625749eeba0a59923176ab05" +dependencies = [ + "async-trait", + "cachemap2", + "circular", + "debugid", + "futures-util", + "minidump-common", + "nom", + "range-map", + "thiserror 1.0.69", + "tracing", +] + [[package]] name = "brotli" version = "8.0.2" @@ -328,6 +346,12 @@ dependencies = [ "serde", ] +[[package]] +name = "cachemap2" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bba2f68a9fefca870fed897de7c655f9d5c1eaf1cd9517db96c9a3861f648b" + [[package]] name = "cairo-rs" version = "0.18.5" @@ -458,6 +482,12 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "circular" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fc239e0f6cb375d2402d48afb92f76f5404fd1df208a41930ec81eda078bea" + [[package]] name = "combine" version = "4.6.7" @@ -585,6 +615,31 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.10.0", + "crossterm_winapi", + "libc", + "mio 0.8.11", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -667,6 +722,15 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + [[package]] name = "deranged" version = "0.5.5" @@ -833,6 +897,15 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "endi" version = "1.1.0" @@ -1976,6 +2049,15 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "memmap2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.9.1" @@ -1991,6 +2073,82 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minidump" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c671544a05d0e8daa3018c8fb6687c11935c4ae8f122de8f2386c2896b4e9b8" +dependencies = [ + "debugid", + "encoding_rs", + "memmap2", + "minidump-common", + "num-traits", + "range-map", + "scroll", + "thiserror 1.0.69", + "time", + "tracing", + "uuid", +] + +[[package]] +name = "minidump-common" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dbc11dfb55b3b7b5684fb16d98e0fc9d1e93a64d6b00bf383eabfc4541aaac2" +dependencies = [ + "bitflags 2.10.0", + "debugid", + "num-derive", + "num-traits", + "range-map", + "scroll", + "smart-default", +] + +[[package]] +name = "minidump-processor" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b49bde7c0ae9a7142c540c27c7fc29db2288fd9614f11a9ce57badeb74af43" +dependencies = [ + "async-trait", + "breakpad-symbols", + "debugid", + "futures-util", + "memmap2", + "minidump", + "minidump-common", + "minidump-unwind", + "scroll", + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", + "yaxpeax-x86", +] + +[[package]] +name = "minidump-unwind" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63aef4cd2e018881680b152296ae28e674242823faa1767b417b6669a1896cdc" +dependencies = [ + "async-trait", + "breakpad-symbols", + "minidump", + "minidump-common", + "scroll", + "tracing", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -2001,6 +2159,18 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + [[package]] name = "mio" version = "1.1.0" @@ -2088,6 +2258,16 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "ntapi" version = "0.4.1" @@ -2103,6 +2283,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2904,6 +3095,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "range-map" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a5a2d6c7039059af621472a4389be1215a816df61aa4d531cfe85264aee95f" +dependencies = [ + "num-traits", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -3134,6 +3334,26 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "selectors" version = "0.24.0" @@ -3349,6 +3569,27 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" +dependencies = [ + "libc", + "mio 0.8.11", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.7" @@ -3388,6 +3629,17 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "smart-default" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "socket2" version = "0.6.1" @@ -3575,6 +3827,8 @@ name = "system-doctor" version = "0.1.0" dependencies = [ "chrono", + "minidump", + "minidump-processor", "serde", "serde_json", "sysinfo", @@ -4009,7 +4263,7 @@ checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ "bytes", "libc", - "mio", + "mio 1.1.0", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -4189,6 +4443,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4876,6 +5131,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.59.0" @@ -4918,6 +5182,21 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -4975,6 +5254,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -4993,6 +5278,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -5011,6 +5302,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5041,6 +5338,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -5059,6 +5362,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -5077,6 +5386,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -5095,6 +5410,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -5228,6 +5549,31 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "yaxpeax-arch" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f005c964432a1f9ee04598e094a3eb5f7568f6b33e89a2762d7bef6fbe8b255" +dependencies = [ + "crossterm", + "num-traits", + "serde", + "serde_derive", +] + +[[package]] +name = "yaxpeax-x86" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107477944697db42c41326f82d4c65b769b32512cdad1e086f36f0e0f25ff45" +dependencies = [ + "cfg-if", + "num-traits", + "serde", + "serde_derive", + "yaxpeax-arch", +] + [[package]] name = "yoke" version = "0.8.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a58593b..a6ec5f2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -26,6 +26,8 @@ sysinfo = "0.30" wmi = "0.13" chrono = { version = "0.4", features = ["serde"] } tokio = { version = "1", features = ["full"] } +minidump = "0.19" +minidump-processor = "0.19" [features] # this feature is used for production builds or when `devPath` points to the filesystem diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 586b616..263e53e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -8,13 +8,15 @@ use serde::Serialize; use sysinfo::{System, Disks}; use wmi::{COMLibrary, WMIConnection}; use std::fs; -// 引入 tauri::Emitter 用于发送事件 (Tauri v2) +use std::path::Path; use tauri::Emitter; -use chrono::{Duration, FixedOffset, Local, NaiveDate, TimeZone}; +use chrono::{Duration, FixedOffset, Local, NaiveDate, TimeZone, DateTime}; +// [修改] 只引入 minidump 基础库,移除 processor 依赖以避免 API 冲突 +use minidump::{Minidump, MinidumpException, MinidumpSystemInfo}; -// --- 1. 数据结构 (保持不变,用于序列化部分数据) --- +// --- 1. 数据结构 (保持不变) --- -#[derive(Serialize, Clone)] // 增加 Clone trait 方便使用 +#[derive(Serialize, Clone)] struct HardwareSummary { cpu_name: String, sys_vendor: String, @@ -67,51 +69,39 @@ struct BatteryInfo { explanation: String, } +#[derive(Serialize, Clone)] +struct BsodFileItem { + filename: String, + path: String, + size_kb: u64, + created_time: String, +} + +#[derive(Serialize, Clone)] +struct BsodAnalysisReport { + crash_reason: String, + crash_address: String, + bug_check_code: String, + crashing_thread: Option, + human_analysis: String, + recommendation: String, +} + // --- WMI 反序列化结构 --- - #[derive(serde::Deserialize, Debug)] -struct Win32_DiskDrive { - Model: Option, - Status: Option, -} - +struct Win32_DiskDrive { Model: Option, Status: Option } #[derive(serde::Deserialize, Debug)] -struct Win32_NTLogEvent { - TimeGenerated: String, - EventCode: u32, - SourceName: String, - Message: Option, -} - +struct Win32_NTLogEvent { TimeGenerated: String, EventCode: u32, SourceName: String, Message: Option } #[derive(serde::Deserialize, Debug)] -struct Win32_PnPEntity { - Name: Option, - ConfigManagerErrorCode: Option, -} - +struct Win32_PnPEntity { Name: Option, ConfigManagerErrorCode: Option } #[derive(serde::Deserialize, Debug)] -struct Win32_Battery { - DesignCapacity: Option, - FullChargeCapacity: Option, - BatteryStatus: Option, -} - +struct Win32_Battery { DesignCapacity: Option, FullChargeCapacity: Option, BatteryStatus: Option } #[derive(serde::Deserialize, Debug)] -struct Win32_BIOS { - SMBIOSBIOSVersion: Option, -} - +struct Win32_BIOS { SMBIOSBIOSVersion: Option } #[derive(serde::Deserialize, Debug)] -struct Win32_BaseBoard { - Manufacturer: Option, - Product: Option, -} - +struct Win32_BaseBoard { Manufacturer: Option, Product: Option } #[derive(serde::Deserialize, Debug)] -struct Win32_ComputerSystem { - Manufacturer: Option, - Model: Option, -} +struct Win32_ComputerSystem { Manufacturer: Option, Model: Option } // --- 辅助函数 --- fn get_wmi_query_time(days_ago: i64) -> String { @@ -120,9 +110,7 @@ fn get_wmi_query_time(days_ago: i64) -> String { } fn format_wmi_time(wmi_str: &str) -> String { - if wmi_str.len() < 25 { - return wmi_str.to_string(); - } + if wmi_str.len() < 25 { return wmi_str.to_string(); } let year = wmi_str[0..4].parse::().unwrap_or(1970); let month = wmi_str[4..6].parse::().unwrap_or(1); let day = wmi_str[6..8].parse::().unwrap_or(1); @@ -141,14 +129,146 @@ fn format_wmi_time(wmi_str: &str) -> String { } } -// --- 核心逻辑:分步流式传输 --- +// --- 新增功能:翻译蓝屏代码为人话 (手动映射常见代码) --- +fn translate_bugcheck_u32(code: u32) -> (String, String) { + // 这些是 Windows 最常见的 BSOD 代码 + match code { + 0x000000D1 => ( + "DRIVER_IRQL_NOT_LESS_OR_EQUAL (0xD1)".to_string(), + "驱动程序使用了不正确的内存地址。通常是驱动程序冲突或损坏。请检查最近安装的硬件驱动(显卡、网卡等),尝试回滚或更新驱动。" + .to_string(), + ), + 0x0000007E | 0x1000007E => ( + "SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (0x7E)".to_string(), + "系统线程抛出了未捕获的异常。可能是显卡驱动不兼容,或者BIOS设置问题。建议重装显卡驱动,或恢复BIOS默认设置。" + .to_string(), + ), + 0x0000001A => ( + "MEMORY_MANAGEMENT (0x1A)".to_string(), + "严重的内存管理错误。高度怀疑内存条物理故障。建议立即运行 Windows 内存诊断工具,或者尝试拔插内存条。" + .to_string(), + ), + 0x000000EF => ( + "CRITICAL_PROCESS_DIED (0xEF)".to_string(), + "Windows 核心进程意外终止。通常是系统文件损坏或硬盘故障。建议运行 'sfc /scannow' 修复系统,并检查硬盘健康度。" + .to_string(), + ), + 0x00000124 => ( + "WHEA_UNCORRECTABLE_ERROR (0x124)".to_string(), + "硬件发生无法纠正的物理错误。这是纯硬件故障。通常是 CPU 电压不足、超频失败、过热,或者主板/PCIe设备(如 NVMe 硬盘)故障。" + .to_string(), + ), + 0x00000116 => ( + "VIDEO_TDR_FAILURE (0x116)".to_string(), + "显卡响应超时。显卡驱动崩溃或显卡过热。如果你在玩游戏,可能是显卡超频不稳定或散热硅脂干了。" + .to_string(), + ), + 0x00000050 => ( + "PAGE_FAULT_IN_NONPAGED_AREA (0x50)".to_string(), + "试图访问无效的内存地址。可能是内存条故障,或者是防病毒软件/驱动程序冲突。建议检查内存。" + .to_string(), + ), + 0x0000000A => ( + "IRQL_NOT_LESS_OR_EQUAL (0x0A)".to_string(), + "驱动程序使用了不正确的内存地址。通常由有缺陷的驱动程序或硬件兼容性问题引起。" + .to_string(), + ), + 0x0000003B => ( + "SYSTEM_SERVICE_EXCEPTION (0x3B)".to_string(), + "系统服务执行异常。通常与图形驱动程序或过时的系统文件有关。" + .to_string(), + ), + 0x00000133 => ( + "DPC_WATCHDOG_VIOLATION (0x133)".to_string(), + "DPC 看门狗超时。通常是 SSD 固件过旧或无线网卡驱动冲突导致系统卡死时间过长。" + .to_string(), + ), + _ => ( + format!("未知错误代码: 0x{:X}", code), + "请尝试在搜索引擎中搜索此错误代码。通用建议:更新驱动、检查内存、扫描病毒。".to_string(), + ), + } +} +// --- 命令:列出 Minidump 文件 --- +#[tauri::command] +async fn list_minidumps() -> Result, String> { + let path = Path::new("C:\\Windows\\Minidump"); + let mut files = Vec::new(); + + if path.exists() { + if let Ok(entries) = fs::read_dir(path) { + for entry in entries { + if let Ok(entry) = entry { + // [修复] 使用 .as_ref() 防止 metadata 所有权被移动 + let metadata = entry.metadata().ok(); + let created = metadata.as_ref() + .and_then(|m| m.modified().ok()) // 通常用修改时间 + .map(|t| { + let dt: DateTime = t.into(); + dt.format("%Y-%m-%d %H:%M:%S").to_string() + }) + .unwrap_or("Unknown".to_string()); + + // [修复] 使用 .as_ref() 再次访问 metadata + let size = metadata.as_ref().map(|m| m.len() / 1024).unwrap_or(0); + + files.push(BsodFileItem { + filename: entry.file_name().to_string_lossy().to_string(), + path: entry.path().to_string_lossy().to_string(), + size_kb: size, + created_time: created, + }); + } + } + } + } + // 按时间倒序排列 + files.sort_by(|a, b| b.created_time.cmp(&a.created_time)); + Ok(files) +} + +// --- 命令:分析指定的 Minidump 文件 --- +#[tauri::command] +async fn analyze_minidump(filepath: String) -> Result { + let path = Path::new(&filepath); + + // 1. 读取文件 (使用基础 minidump 库) + let dump = Minidump::read_path(path).map_err(|e| format!("无法读取文件: {}", e))?; + + // 2. 直接获取异常流 (Exception Stream) + let exception_stream = dump.get_stream::() + .map_err(|_| "无法找到异常信息流 (No Exception Stream)".to_string())?; + + // [修复] 使用 .raw 访问内部原始结构 + let exception_code = exception_stream.raw.exception_record.exception_code; + let exception_address = exception_stream.raw.exception_record.exception_address; + + // 3. 尝试获取系统信息 (OS Version) + let sys_info_str = match dump.get_stream::() { + // [修复] 使用 .raw 访问 build_number + Ok(info) => format!("Windows Build {}", info.raw.build_number), + Err(_) => "Unknown OS".to_string(), + }; + + // 4. 翻译 + let (reason_str, recommend) = translate_bugcheck_u32(exception_code); + + Ok(BsodAnalysisReport { + crash_reason: reason_str, + crash_address: format!("0x{:X}", exception_address), + bug_check_code: format!("0x{:X} ({})", exception_code, sys_info_str), + crashing_thread: None, // 基础解析不包含线程栈回溯 + human_analysis: "根据错误代码自动匹配的分析结果。".to_string(), + recommendation: recommend, + }) +} + +// --- 现有命令:run_diagnosis (保持不变) --- #[tauri::command] async fn run_diagnosis(window: tauri::Window) -> Result<(), String> { - // 使用 spawn 在后台线程运行,避免阻塞 Tauri 主线程 - // 注意:这里不等待 join,而是让它在后台跑,通过 window.emit 发送进度 std::thread::spawn(move || { - // 1. 硬件概览 (最快) + // 1. 硬件概览 { let mut sys = System::new(); sys.refresh_memory(); @@ -180,7 +300,6 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> { } } - // C盘 let mut c_total = 0u64; let mut c_used = 0u64; let disks = Disks::new_with_refreshed_list(); @@ -209,15 +328,12 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> { c_drive_total_gb: c_total, c_drive_used_gb: c_used, }; - - // 发送硬件事件 let _ = window.emit("report-hardware", hardware); } - // WMI 连接复用 (如果需要) 或者重新建立 let wmi_con = WMIConnection::new(COMLibrary::new().unwrap()).ok(); - // 2. 存储设备 (较快) + // 2. 存储设备 { let mut storage = Vec::new(); if let Some(con) = &wmi_con { @@ -242,7 +358,7 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> { let _ = window.emit("report-storage", storage); } - // 3. 驱动 (快) + // 3. 驱动 { let mut driver_issues = Vec::new(); if let Some(con) = &wmi_con { @@ -267,7 +383,7 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> { let _ = window.emit("report-drivers", driver_issues); } - // 4. Minidump (快) + // 4. Minidump { let mut minidump = MinidumpInfo { found: false, count: 0, explanation: "无蓝屏记录".to_string() }; if let Ok(entries) = fs::read_dir("C:\\Windows\\Minidump") { @@ -283,7 +399,7 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> { let _ = window.emit("report-minidumps", minidump); } - // 5. 电池 (快) + // 5. 电池 { let mut battery_info = None; if let Some(con) = &wmi_con { @@ -309,12 +425,10 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> { } } } - // 即使是 None 也要发,以便前端知道检查完成了 - // 这里为了简化,直接发 Option let _ = window.emit("report-battery", battery_info); } - // 6. 日志 (最慢,放在最后) + // 6. 日志 { let mut events = Vec::new(); if let Some(con) = &wmi_con { @@ -366,7 +480,7 @@ async fn run_diagnosis(window: tauri::Window) -> Result<(), String> { fn main() { tauri::Builder::default() - .invoke_handler(tauri::generate_handler![run_diagnosis]) + .invoke_handler(tauri::generate_handler![run_diagnosis, list_minidumps, analyze_minidump]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 5cf95ba..8251ede 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,235 +1,254 @@ - - \ No newline at end of file