1125-2142

This commit is contained in:
Julian Freeman
2025-11-25 21:42:11 -04:00
commit 44f86f9185
36 changed files with 8094 additions and 0 deletions

14
src-tauri/src/lib.rs Normal file
View File

@@ -0,0 +1,14 @@
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_opener::init())
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

360
src-tauri/src/main.rs Normal file
View File

@@ -0,0 +1,360 @@
// 全局允许非标准命名风格 (因为 WMI 结构体必须匹配 Windows API 的命名)
#![allow(non_camel_case_types, non_snake_case)]
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use serde::Serialize;
use sysinfo::{System, Disks};
use wmi::{COMLibrary, WMIConnection};
use std::fs;
// 引入 chrono 用于时间格式化
use chrono::{FixedOffset, Local, NaiveDate, TimeZone};
// --- 1. 数据结构 ---
#[derive(Serialize)]
struct SystemHealthReport {
hardware: HardwareSummary,
storage: Vec<StorageDevice>,
events: Vec<SystemEvent>,
minidumps: MinidumpInfo,
drivers: Vec<DriverIssue>,
battery: Option<BatteryInfo>,
}
#[derive(Serialize)]
struct HardwareSummary {
cpu_name: String,
// [新增] 1. 整机信息 (适合品牌机/笔记本)
sys_vendor: String,
sys_product: String,
// [新增] 2. 主板信息 (适合 DIY 组装机)
mobo_vendor: String,
mobo_product: String,
memory_total_gb: u64,
memory_used_gb: u64,
os_version: String,
bios_version: String,
c_drive_total_gb: u64,
c_drive_used_gb: u64,
}
#[derive(Serialize)]
struct StorageDevice {
model: String,
health_status: String,
human_explanation: String,
is_danger: bool,
}
#[derive(Serialize)]
struct SystemEvent {
time_generated: String,
event_id: u32,
source: String,
analysis_hint: String,
}
#[derive(Serialize)]
struct MinidumpInfo {
found: bool,
count: usize,
explanation: String,
}
#[derive(Serialize)]
struct DriverIssue {
device_name: String,
error_code: u32,
description: String,
}
#[derive(Serialize)]
struct BatteryInfo {
health_percentage: u32,
is_ac_connected: bool,
explanation: String,
}
// --- WMI 反序列化结构 ---
#[derive(serde::Deserialize, Debug)]
struct Win32_DiskDrive {
Model: Option<String>,
Status: Option<String>,
}
#[derive(serde::Deserialize, Debug)]
struct Win32_NTLogEvent {
TimeGenerated: String,
EventCode: u32,
SourceName: String,
}
#[derive(serde::Deserialize, Debug)]
struct Win32_PnPEntity {
Name: Option<String>,
ConfigManagerErrorCode: Option<u32>,
}
#[derive(serde::Deserialize, Debug)]
struct Win32_Battery {
DesignCapacity: Option<u32>,
FullChargeCapacity: Option<u32>,
BatteryStatus: Option<u16>,
}
#[derive(serde::Deserialize, Debug)]
struct Win32_BIOS {
SMBIOSBIOSVersion: Option<String>,
}
// 主板 WMI 结构 (DIY看这个)
#[derive(serde::Deserialize, Debug)]
struct Win32_BaseBoard {
Manufacturer: Option<String>,
Product: Option<String>,
}
// [新增] 整机 WMI 结构 (品牌机看这个)
#[derive(serde::Deserialize, Debug)]
struct Win32_ComputerSystem {
Manufacturer: Option<String>,
Model: Option<String>,
}
// --- 辅助函数:格式化 WMI 时间 ---
fn format_wmi_time(wmi_str: &str) -> String {
if wmi_str.len() < 25 {
return wmi_str.to_string();
}
let year = wmi_str[0..4].parse::<i32>().unwrap_or(1970);
let month = wmi_str[4..6].parse::<u32>().unwrap_or(1);
let day = wmi_str[6..8].parse::<u32>().unwrap_or(1);
let hour = wmi_str[8..10].parse::<u32>().unwrap_or(0);
let min = wmi_str[10..12].parse::<u32>().unwrap_or(0);
let sec = wmi_str[12..14].parse::<u32>().unwrap_or(0);
let sign = &wmi_str[21..22];
let offset_val = wmi_str[22..25].parse::<i32>().unwrap_or(0);
let offset_mins = if sign == "-" { -offset_val } else { offset_val };
let offset = FixedOffset::east_opt(offset_mins * 60).unwrap_or(FixedOffset::east_opt(0).unwrap());
let naive_date = NaiveDate::from_ymd_opt(year, month, day).unwrap_or(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
let naive_dt = naive_date.and_hms_opt(hour, min, sec).unwrap_or_default();
match offset.from_local_datetime(&naive_dt).single() {
Some(dt) => {
dt.with_timezone(&Local).format("%Y-%m-%d %H:%M:%S").to_string()
},
None => format!("{}-{:02}-{:02} {:02}:{:02}:{:02}", year, month, day, hour, min, sec)
}
}
// --- 核心逻辑 ---
#[tauri::command]
async fn run_diagnosis() -> Result<SystemHealthReport, String> {
let report = tokio::task::spawn_blocking(|| {
let mut sys = System::new_all();
sys.refresh_all();
let wmi_con = WMIConnection::new(COMLibrary::new().unwrap()).ok();
// 1. 硬件基础信息
let mut bios_ver = "Unknown".to_string();
let mut mobo_vendor = "Unknown".to_string();
let mut mobo_product = "Unknown".to_string();
let mut sys_vendor = "Unknown".to_string();
let mut sys_product = "Unknown".to_string();
if let Some(con) = &wmi_con {
// 获取 BIOS 版本
if let Ok(results) = con.raw_query::<Win32_BIOS>("SELECT SMBIOSBIOSVersion FROM Win32_BIOS") {
if let Some(bios) = results.first() {
bios_ver = bios.SMBIOSBIOSVersion.clone().unwrap_or("Unknown".to_string());
}
}
// 获取主板信息 (BaseBoard)
if let Ok(results) = con.raw_query::<Win32_BaseBoard>("SELECT Manufacturer, Product FROM Win32_BaseBoard") {
if let Some(board) = results.first() {
mobo_vendor = board.Manufacturer.clone().unwrap_or("Unknown".to_string());
mobo_product = board.Product.clone().unwrap_or("Unknown".to_string());
}
}
// [新增] 获取整机信息 (ComputerSystem)
if let Ok(results) = con.raw_query::<Win32_ComputerSystem>("SELECT Manufacturer, Model FROM Win32_ComputerSystem") {
if let Some(cs) = results.first() {
sys_vendor = cs.Manufacturer.clone().unwrap_or("Unknown".to_string());
sys_product = cs.Model.clone().unwrap_or("Unknown".to_string());
}
}
}
// --- C 盘空间检查 ---
let mut c_total = 0u64;
let mut c_used = 0u64;
let disks = Disks::new_with_refreshed_list();
for disk in &disks {
if disk.mount_point().to_string_lossy().starts_with("C:") {
c_total = disk.total_space() / 1024 / 1024 / 1024;
let free = disk.available_space() / 1024 / 1024 / 1024;
c_used = c_total - free;
break;
}
}
let cpu_brand = if let Some(cpu) = sys.cpus().first() {
cpu.brand().trim().to_string()
} else {
"Unknown CPU".to_string()
};
let hardware = HardwareSummary {
cpu_name: cpu_brand,
mobo_vendor,
mobo_product,
// [新增] 填入整机数据
sys_vendor,
sys_product,
memory_total_gb: sys.total_memory() / 1024 / 1024 / 1024,
memory_used_gb: sys.used_memory() / 1024 / 1024 / 1024,
os_version: System::long_os_version().unwrap_or("Unknown".to_string()),
bios_version: bios_ver,
c_drive_total_gb: c_total,
c_drive_used_gb: c_used,
};
// 2. 存储设备健康度
let mut storage = Vec::new();
if let Some(con) = &wmi_con {
let query = "SELECT Model, Status FROM Win32_DiskDrive";
if let Ok(results) = con.raw_query::<Win32_DiskDrive>(query) {
for disk in results {
let status = disk.Status.unwrap_or("Unknown".to_string());
let (explanation, is_danger) = match status.as_str() {
"OK" => ("健康".to_string(), false),
"Pred Fail" => ("预测即将损坏".to_string(), true),
_ => ("状态异常".to_string(), true),
};
storage.push(StorageDevice {
model: disk.Model.unwrap_or("Generic Disk".to_string()),
health_status: status,
human_explanation: explanation,
is_danger,
});
}
}
}
// 3. 关键日志
let mut events = Vec::new();
if let Some(con) = &wmi_con {
let query = "SELECT TimeGenerated, EventCode, SourceName FROM Win32_NTLogEvent WHERE Logfile = 'System' AND (EventCode = 41 OR EventCode = 18 OR EventCode = 19)";
if let Ok(mut results) = con.raw_query::<Win32_NTLogEvent>(query) {
results.truncate(5);
for event in results {
let hint = match event.EventCode {
41 => "系统意外断电 (电源/强关)",
18 | 19 => "WHEA 硬件致命错误 (CPU/超频)",
_ => "系统关键错误",
};
events.push(SystemEvent {
time_generated: format_wmi_time(&event.TimeGenerated),
event_id: event.EventCode,
source: event.SourceName,
analysis_hint: hint.to_string(),
});
}
}
}
// 4. Minidump
let mut minidump = MinidumpInfo { found: false, count: 0, explanation: "无蓝屏记录".to_string() };
if let Ok(entries) = fs::read_dir("C:\\Windows\\Minidump") {
let count = entries.count();
if count > 0 {
minidump = MinidumpInfo {
found: true,
count,
explanation: format!("发现 {} 次蓝屏崩溃", count),
};
}
}
// 5. 驱动设备检查
let mut driver_issues = Vec::new();
if let Some(con) = &wmi_con {
let query = "SELECT Name, ConfigManagerErrorCode FROM Win32_PnPEntity WHERE ConfigManagerErrorCode <> 0";
if let Ok(results) = con.raw_query::<Win32_PnPEntity>(query) {
for dev in results {
let code = dev.ConfigManagerErrorCode.unwrap_or(0);
let desc = match code {
10 => "设备无法启动 (Code 10)。通常是驱动不兼容。",
28 => "驱动程序未安装 (Code 28)。",
43 => "硬件报告问题已被停止 (Code 43)。显卡常见,可能虚焊。",
_ => "设备状态异常。",
};
driver_issues.push(DriverIssue {
device_name: dev.Name.unwrap_or("未知设备".to_string()),
error_code: code,
description: desc.to_string(),
});
}
}
}
// 6. 电池健康度
let mut battery_info = None;
if let Some(con) = &wmi_con {
if let Ok(results) = con.raw_query::<Win32_Battery>("SELECT DesignCapacity, FullChargeCapacity, BatteryStatus FROM Win32_Battery") {
if let Some(bat) = results.first() {
let design = bat.DesignCapacity.unwrap_or(0);
let full = bat.FullChargeCapacity.unwrap_or(0);
let status = bat.BatteryStatus.unwrap_or(0);
if design > 0 {
let health = ((full as f64 / design as f64) * 100.0) as u32;
let ac_plugged = status == 2 || status == 6 || status == 1;
let explain = if health < 60 {
"电池老化严重,建议更换,否则可能导致供电不稳。".to_string()
} else {
"电池状态良好。".to_string()
};
battery_info = Some(BatteryInfo {
health_percentage: health,
is_ac_connected: ac_plugged,
explanation: explain,
});
}
}
}
}
SystemHealthReport {
hardware,
storage,
events,
minidumps: minidump,
drivers: driver_issues,
battery: battery_info
}
})
.await
.map_err(|e| e.to_string())?;
Ok(report)
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![run_diagnosis])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}