diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs index eef5e95..2c472b5 100644 --- a/src-tauri/src/cmds.rs +++ b/src-tauri/src/cmds.rs @@ -470,9 +470,338 @@ pub fn get_gpu_info() -> Result, String> { } } +/// 内存信息结构体 +#[derive(Debug, Serialize, Deserialize)] +pub struct MemoryInfo { + #[serde(skip_serializing_if = "Option::is_none")] + capacity: Option, // 容量(字节) + #[serde(skip_serializing_if = "Option::is_none")] + manufacturer: Option, + #[serde(skip_serializing_if = "Option::is_none")] + speed: Option, // MHz,实际频率 ConfiguredClockSpeed + #[serde(skip_serializing_if = "Option::is_none")] + default_speed: Option, // MHz,默认频率 Speed(如果存在) +} + +/// 显示器信息结构体 +#[derive(Debug, Serialize, Deserialize)] +pub struct MonitorInfo { + #[serde(skip_serializing_if = "Option::is_none")] + manufacturer: Option, + #[serde(skip_serializing_if = "Option::is_none")] + model: Option, + #[serde(skip_serializing_if = "Option::is_none")] + name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + refresh_rate: Option, // Hz + #[serde(skip_serializing_if = "Option::is_none")] + resolution_width: Option, + #[serde(skip_serializing_if = "Option::is_none")] + resolution_height: Option, +} + +/// 主板信息结构体 +#[derive(Debug, Serialize, Deserialize)] +pub struct MotherboardInfo { + #[serde(skip_serializing_if = "Option::is_none")] + manufacturer: Option, // 制造商 + #[serde(skip_serializing_if = "Option::is_none")] + model: Option, // 型号 + #[serde(skip_serializing_if = "Option::is_none")] + version: Option, +} + +/// 获取内存信息(Windows) +#[tauri::command] +#[cfg(target_os = "windows")] +pub async fn get_memory_info() -> Result, String> { + use tokio::process::Command; + + // 执行 PowerShell 命令获取内存信息 + let output = Command::new("powershell") + .args(&[ + "-NoProfile", + "-Command", + "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-WmiObject Win32_PhysicalMemory | Select-Object Capacity, Manufacturer, ConfiguredClockSpeed, Speed | ConvertTo-Json -Compress" + ]) + .output() + .await + .map_err(|e| format!("执行 PowerShell 命令失败: {}", e))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("PowerShell 命令执行失败: {}", stderr)); + } + + let stdout = String::from_utf8_lossy(&output.stdout); + let cleaned = stdout.trim().trim_start_matches('\u{feff}'); + + if cleaned.is_empty() { + return Ok(vec![]); + } + + // PowerShell 可能返回数组或单个对象 + let json: serde_json::Value = serde_json::from_str(cleaned) + .map_err(|e| format!("解析 JSON 失败: {},原始输出: {}", e, cleaned))?; + + let mut memory_list = Vec::new(); + + if let Some(array) = json.as_array() { + // 如果是数组 + for item in array { + memory_list.push(parse_memory_info(item)); + } + } else { + // 如果是单个对象 + memory_list.push(parse_memory_info(&json)); + } + + Ok(memory_list) +} + +/// 解析内存信息 +fn parse_memory_info(json: &serde_json::Value) -> MemoryInfo { + // 容量(字节) + let capacity = json.get("Capacity") + .and_then(|v| v.as_u64()); + + let manufacturer = json.get("Manufacturer") + .and_then(|v| v.as_str()) + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()); + + // 实际频率:优先使用 ConfiguredClockSpeed + let speed = json.get("ConfiguredClockSpeed") + .and_then(|v| v.as_u64()) + .map(|v| v as u32); + + // 默认频率:Speed(如果存在) + let default_speed = json.get("Speed") + .and_then(|v| v.as_u64()) + .map(|v| v as u32); + + MemoryInfo { + capacity, + manufacturer, + speed, + default_speed, + } +} + +/// 获取内存信息(非 Windows 平台返回空) +#[tauri::command] +#[cfg(not(target_os = "windows"))] +pub async fn get_memory_info() -> Result, String> { + Ok(vec![]) +} + +/// 获取显示器信息(Windows) +#[tauri::command] +#[cfg(target_os = "windows")] +pub async fn get_monitor_info() -> Result, String> { + use tokio::process::Command; + + // 执行 PowerShell 命令获取显示器信息 + let output = Command::new("powershell") + .args(&[ + "-NoProfile", + "-Command", + "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-CimInstance -Namespace root/wmi -ClassName WmiMonitorID | ForEach-Object { [PSCustomObject]@{ Manufacturer = [System.Text.Encoding]::ASCII.GetString($_.ManufacturerName) -replace \"`0\"; Model = [System.Text.Encoding]::ASCII.GetString($_.UserFriendlyName) -replace \"`0\" } } | ConvertTo-Json -Compress" + ]) + .output() + .await + .map_err(|e| format!("执行 PowerShell 命令失败: {}", e))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("PowerShell 命令执行失败: {}", stderr)); + } + + let stdout = String::from_utf8_lossy(&output.stdout); + let cleaned = stdout.trim().trim_start_matches('\u{feff}'); + + if cleaned.is_empty() { + return Ok(vec![]); + } + + let json: serde_json::Value = serde_json::from_str(cleaned) + .map_err(|e| format!("解析 JSON 失败: {},原始输出: {}", e, cleaned))?; + + let mut monitor_list = Vec::new(); + + if let Some(array) = json.as_array() { + for item in array { + monitor_list.push(parse_monitor_info(item)); + } + } else { + monitor_list.push(parse_monitor_info(&json)); + } + + // 尝试获取刷新率和分辨率信息 + let display_output = Command::new("powershell") + .args(&[ + "-NoProfile", + "-Command", + "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-CimInstance -Namespace root/wmi -ClassName WmiMonitorBasicDisplayParams | Select-Object MaxHorizontalImageSize, MaxVerticalImageSize | ConvertTo-Json -Compress" + ]) + .output() + .await; + + // 获取刷新率信息 + let refresh_output = Command::new("powershell") + .args(&[ + "-NoProfile", + "-Command", + "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-CimInstance -Namespace root/wmi -ClassName WmiMonitorListedSupportedSourceModes | Select-Object -First 1 -ExpandProperty ModeTimings | Select-Object -First 1 -ExpandProperty RefreshRate | ConvertTo-Json -Compress" + ]) + .output() + .await; + + // 获取当前显示器的分辨率和刷新率 + let current_display_output = Command::new("powershell") + .args(&[ + "-NoProfile", + "-Command", + "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Add-Type -AssemblyName System.Windows.Forms; $screens = [System.Windows.Forms.Screen]::AllScreens; $screens | ForEach-Object { [PSCustomObject]@{ Width = $_.Bounds.Width; Height = $_.Bounds.Height; Primary = $_.Primary } } | ConvertTo-Json -Compress" + ]) + .output() + .await; + + // 合并显示器信息 + if let Ok(display_result) = current_display_output { + if display_result.status.success() { + let display_str = String::from_utf8_lossy(&display_result.stdout).to_string(); + let display_str = display_str.trim().trim_start_matches('\u{feff}').to_string(); + if let Ok(display_json) = serde_json::from_str::(&display_str) { + if let Some(displays) = display_json.as_array() { + for (i, display) in displays.iter().enumerate() { + if i < monitor_list.len() { + if let Some(width) = display.get("Width").and_then(|v| v.as_u64()) { + monitor_list[i].resolution_width = Some(width as u32); + } + if let Some(height) = display.get("Height").and_then(|v| v.as_u64()) { + monitor_list[i].resolution_height = Some(height as u32); + } + } + } + } else if let Some(display) = display_json.as_object() { + if monitor_list.len() > 0 { + if let Some(width) = display.get("Width").and_then(|v| v.as_u64()) { + monitor_list[0].resolution_width = Some(width as u32); + } + if let Some(height) = display.get("Height").and_then(|v| v.as_u64()) { + monitor_list[0].resolution_height = Some(height as u32); + } + } + } + } + } + } + + Ok(monitor_list) +} + +/// 解析显示器信息 +fn parse_monitor_info(json: &serde_json::Value) -> MonitorInfo { + let manufacturer = json.get("Manufacturer") + .and_then(|v| v.as_str()) + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()); + + let model = json.get("Model") + .and_then(|v| v.as_str()) + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()); + + // 组合制造商和型号作为名称 + let name = match (&manufacturer, &model) { + (Some(mfg), Some(model_name)) => Some(format!("{} {}", mfg, model_name)), + (Some(mfg), None) => Some(mfg.clone()), + (None, Some(model_name)) => Some(model_name.clone()), + (None, None) => None, + }; + + MonitorInfo { + manufacturer, + model, + name, + refresh_rate: None, // 需要从其他来源获取 + resolution_width: None, + resolution_height: None, + } +} + /// 获取显示器信息(非 Windows 平台返回空) #[tauri::command] #[cfg(not(target_os = "windows"))] pub async fn get_monitor_info() -> Result, String> { Ok(vec![]) +} + +/// 获取主板信息(Windows) +#[tauri::command] +#[cfg(target_os = "windows")] +pub async fn get_motherboard_info() -> Result { + use tokio::process::Command; + + // 执行 PowerShell 命令获取主板信息 + let output = Command::new("powershell") + .args(&[ + "-NoProfile", + "-Command", + "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-CimInstance -ClassName Win32_BaseBoard | Select-Object Manufacturer, Product, Version | ConvertTo-Json -Compress" + ]) + .output() + .await + .map_err(|e| format!("执行 PowerShell 命令失败: {}", e))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("PowerShell 命令执行失败: {}", stderr)); + } + + let stdout = String::from_utf8_lossy(&output.stdout); + let cleaned = stdout.trim().trim_start_matches('\u{feff}'); + + if cleaned.is_empty() { + return Ok(MotherboardInfo { + manufacturer: None, + model: None, + version: None, + }); + } + + let json: serde_json::Value = serde_json::from_str(cleaned) + .map_err(|e| format!("解析 JSON 失败: {},原始输出: {}", e, cleaned))?; + + // 分别获取制造商和型号 + let manufacturer = json.get("Manufacturer") + .and_then(|v| v.as_str()) + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()); + + let model = json.get("Product") + .and_then(|v| v.as_str()) + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()); + + Ok(MotherboardInfo { + manufacturer, + model, + version: json.get("Version") + .and_then(|v| v.as_str()) + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()), + }) +} + +/// 获取主板信息(非 Windows 平台返回空) +#[tauri::command] +#[cfg(not(target_os = "windows"))] +pub async fn get_motherboard_info() -> Result { + Ok(MotherboardInfo { + manufacturer: None, + model: None, + version: None, + }) } \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index d78508a..2e91bcc 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -171,7 +171,9 @@ fn main() { cmds::install_app_update, cmds::get_computer_info, cmds::get_gpu_info, + cmds::get_memory_info, cmds::get_monitor_info, + cmds::get_motherboard_info, on_button_clicked ]) .run(ctx) diff --git a/src/app/(main)/gear/page.tsx b/src/app/(main)/gear/page.tsx index 06371f6..45b3c3e 100644 --- a/src/app/(main)/gear/page.tsx +++ b/src/app/(main)/gear/page.tsx @@ -71,9 +71,10 @@ interface GpuInfo { } interface MemoryInfo { + capacity?: number // 容量(字节) manufacturer?: string - part_number?: string - speed?: number // MHz + speed?: number // MHz,实际频率 ConfiguredClockSpeed + default_speed?: number // MHz,默认频率 Speed(如果存在) } interface MonitorInfo { @@ -83,42 +84,55 @@ interface MonitorInfo { resolution_height?: number } +interface MotherboardInfo { + manufacturer?: string // 制造商 + model?: string // 型号 + version?: string +} + interface HardwareData { allSysData: AllSystemInfo computerInfo: ComputerInfo gpuInfo: GpuInfo | null memoryInfo: MemoryInfo[] monitorInfo: MonitorInfo[] + motherboardInfo: MotherboardInfo | null } // 硬件信息 fetcher const hardwareInfoFetcher = async (): Promise => { - // 并行获取系统信息、PowerShell 信息、GPU 信息、内存信息和显示器信息 - const [sys, computerInfoData, gpuInfoData, memoryInfoData, monitorInfoData] = await Promise.all([ - allSysInfo(), - invoke("get_computer_info").catch((error) => { - console.error("获取 PowerShell 信息失败:", error) - return {} as ComputerInfo - }), - invoke("get_gpu_info").catch((error) => { - console.error("获取 GPU 信息失败:", error) - return null - }), - invoke("get_memory_info").catch((error) => { - console.error("获取内存信息失败:", error) - return [] as MemoryInfo[] - }), - invoke("get_monitor_info").catch((error) => { - console.error("获取显示器信息失败:", error) - return [] as MonitorInfo[] - }), - ]) + // 并行获取系统信息、PowerShell 信息、GPU 信息、内存信息、显示器信息和主板信息 + const [sys, computerInfoData, gpuInfoData, memoryInfoData, monitorInfoData, motherboardInfoData] = + await Promise.all([ + allSysInfo(), + invoke("get_computer_info").catch((error) => { + console.error("获取 PowerShell 信息失败:", error) + return {} as ComputerInfo + }), + invoke("get_gpu_info").catch((error) => { + console.error("获取 GPU 信息失败:", error) + return null + }), + invoke("get_memory_info").catch((error) => { + console.error("获取内存信息失败:", error) + return [] as MemoryInfo[] + }), + invoke("get_monitor_info").catch((error) => { + console.error("获取显示器信息失败:", error) + return [] as MonitorInfo[] + }), + invoke("get_motherboard_info").catch((error) => { + console.error("获取主板信息失败:", error) + return { manufacturer: undefined, model: undefined, version: undefined } as MotherboardInfo + }), + ]) console.log("系统信息:", sys) console.log("PowerShell 信息:", computerInfoData) console.log("GPU 信息:", gpuInfoData) console.log("内存信息:", memoryInfoData) console.log("显示器信息:", monitorInfoData) + console.log("主板信息:", motherboardInfoData) if (sys?.cpus) { console.log("CPU数据:", sys.cpus) @@ -134,11 +148,12 @@ const hardwareInfoFetcher = async (): Promise => { gpuInfo: gpuInfoData, memoryInfo: memoryInfoData, monitorInfo: monitorInfoData, + motherboardInfo: motherboardInfoData, } } function HardwareInfoContent() { - const { data, isLoading } = useSWR("/api/hardware-info", hardwareInfoFetcher, { + const { data, isLoading, isValidating } = useSWR("/api/hardware-info", hardwareInfoFetcher, { revalidateOnFocus: false, revalidateOnReconnect: false, dedupingInterval: 5 * 60 * 1000, // 5分钟内相同请求去重 @@ -149,6 +164,7 @@ function HardwareInfoContent() { const gpuInfo = data?.gpuInfo const memoryInfo = data?.memoryInfo || [] const monitorInfo = data?.monitorInfo || [] + const motherboardInfo = data?.motherboardInfo const formatBytes = (bytes?: number) => { if (!bytes) return "未知" @@ -227,8 +243,8 @@ function HardwareInfoContent() { })() : null - // 如果正在加载,显示 Skeleton 骨架屏 - if (isLoading) { + // 如果正在加载或正在验证(包括刷新),显示 Skeleton 骨架屏 + if (isLoading || isValidating) { return (
{/* 系统信息 Skeleton */} @@ -324,6 +340,7 @@ function HardwareInfoContent() { {allSysData?.total_memory && (
内存
+ {/* 第一行:总容量和已用内存 */}
总容量: {formatBytes(allSysData.total_memory)} @@ -336,23 +353,34 @@ function HardwareInfoContent() { )} )} - {allSysData.total_memory !== undefined && allSysData.used_memory !== undefined && ( - - 可用:{" "} - {formatBytes(allSysData.total_memory - allSysData.used_memory)} - - )} - {memoryInfo.length > 0 && memoryInfo[0].part_number && ( - - 型号: {memoryInfo[0].part_number} - - )} - {memoryInfo.length > 0 && memoryInfo[0].speed && ( - - 频率: {memoryInfo[0].speed} MHz - - )}
+ {/* 每个内存条的详细信息 */} + {memoryInfo.length > 0 && ( +
+ {memoryInfo.map((mem, index) => ( +
+ {mem.capacity && ( + + 容量: {formatBytes(mem.capacity)} + + )} + {mem.manufacturer && ( + + 制造商: {mem.manufacturer} + + )} + {mem.speed && ( + + 频率: {mem.speed} MHz + {mem.default_speed && ( + ({mem.default_speed} MHz) + )} + + )} +
+ ))} +
+ )}
)} @@ -410,13 +438,28 @@ function HardwareInfoContent() { )} {/* 主板信息 */} - {(computerInfo.CsManufacturer || computerInfo.BiosSMBIOSBIOSVersion) && ( + {(motherboardInfo?.model || + motherboardInfo?.manufacturer || + motherboardInfo?.version || + computerInfo.BiosSMBIOSBIOSVersion) && (
主板
- {computerInfo.CsManufacturer && ( + {motherboardInfo?.model && ( - 制造商: {computerInfo.CsManufacturer} + 型号: {motherboardInfo.model} + + )} + {motherboardInfo?.manufacturer && ( + + 品牌: {motherboardInfo.manufacturer} + + )} +
+
+ {motherboardInfo?.version && ( + + 版本: {motherboardInfo.version} )} {computerInfo.BiosSMBIOSBIOSVersion && ( diff --git a/src/components/cstb/FpsTest.tsx b/src/components/cstb/FpsTest.tsx index d85807e..09c377a 100644 --- a/src/components/cstb/FpsTest.tsx +++ b/src/components/cstb/FpsTest.tsx @@ -151,6 +151,58 @@ export function FpsTest() { } }, [tool.state.autoCloseGame, batchTestProgress]) + // 生成硬件信息对象的辅助函数 + const getHardwareInfoObject = useCallback(() => { + if (!hardwareInfo?.systemInfo) { + return null + } + + const osVersion = hardwareInfo.systemInfo.os_version || null + const osDisplayVersion = hardwareInfo.computerInfo?.OSDisplayVersion || null + let osStr = hardwareInfo.systemInfo.name || null + if (osStr) { + if (osVersion) { + osStr += ` ${osVersion}` + } + if (osDisplayVersion) { + osStr += ` ${osDisplayVersion}` + } + } + + return { + cpu: hardwareInfo.systemInfo.cpus[0]?.brand || null, + cpuCount: hardwareInfo.systemInfo.cpu_count || null, + os: osStr, + memory: hardwareInfo.systemInfo.total_memory + ? Math.round(hardwareInfo.systemInfo.total_memory / 1024 / 1024 / 1024) + : null, + memoryManufacturer: hardwareInfo.memoryInfo && hardwareInfo.memoryInfo.length > 0 + ? hardwareInfo.memoryInfo[0].manufacturer || null + : null, + memorySpeed: hardwareInfo.memoryInfo && hardwareInfo.memoryInfo.length > 0 + ? hardwareInfo.memoryInfo[0].speed || null + : null, + memoryDefaultSpeed: hardwareInfo.memoryInfo && hardwareInfo.memoryInfo.length > 0 + ? hardwareInfo.memoryInfo[0].default_speed || null + : null, + gpu: hardwareInfo.gpuInfo + ? hardwareInfo.gpuInfo.model + : null, + monitor: hardwareInfo.monitorInfo && hardwareInfo.monitorInfo.length > 0 + ? hardwareInfo.monitorInfo[0].name || null + : null, + monitorManufacturer: hardwareInfo.monitorInfo && hardwareInfo.monitorInfo.length > 0 + ? hardwareInfo.monitorInfo[0].manufacturer || null + : null, + monitorModel: hardwareInfo.monitorInfo && hardwareInfo.monitorInfo.length > 0 + ? hardwareInfo.monitorInfo[0].model || null + : null, + motherboardModel: hardwareInfo.motherboardInfo?.model || null, + motherboardVersion: hardwareInfo.motherboardInfo?.version || null, + biosVersion: hardwareInfo.computerInfo?.BiosSMBIOSBIOSVersion || null, + } + }, [hardwareInfo]) + // 读取结果函数 const readResult = useCallback( async (silent = false): Promise => { @@ -285,35 +337,7 @@ export function FpsTest() { p1, rawResult: parsed.data, videoSetting: currentVideoSetting, - hardwareInfo: hardwareInfo?.systemInfo - ? { - cpu: hardwareInfo.systemInfo.cpus[0]?.brand || null, - cpuCount: hardwareInfo.systemInfo.cpu_count || null, - os: (() => { - const osVersion = hardwareInfo.systemInfo.os_version || null - // 使用 OSDisplayVersion 作为版本代码(如 "25H2") - const osDisplayVersion = hardwareInfo.computerInfo?.OSDisplayVersion || null - - let osStr = hardwareInfo.systemInfo.name || null - if (!osStr) return null - - if (osVersion) { - osStr += ` ${osVersion}` - } - if (osDisplayVersion) { - osStr += ` ${osDisplayVersion}` - } - return osStr - })(), - memory: hardwareInfo.systemInfo.total_memory - ? Math.round(hardwareInfo.systemInfo.total_memory / 1024 / 1024 / 1024) - : null, - gpu: hardwareInfo.gpuInfo - ? hardwareInfo.gpuInfo.model - : null, - monitor: null, - } - : null, + hardwareInfo: getHardwareInfoObject(), note: batchNote, }) @@ -339,35 +363,7 @@ export function FpsTest() { p1, rawResult: parsed.data, videoSetting: currentVideoSetting, - hardwareInfo: hardwareInfo?.systemInfo - ? { - cpu: hardwareInfo.systemInfo.cpus[0]?.brand || null, - cpuCount: hardwareInfo.systemInfo.cpu_count || null, - os: (() => { - const osVersion = hardwareInfo.systemInfo.os_version || null - // 使用 OSDisplayVersion 作为版本代码(如 "25H2") - const osDisplayVersion = hardwareInfo.computerInfo?.OSDisplayVersion || null - - let osStr = hardwareInfo.systemInfo.name || null - if (!osStr) return null - - if (osVersion) { - osStr += ` ${osVersion}` - } - if (osDisplayVersion) { - osStr += ` ${osDisplayVersion}` - } - return osStr - })(), - memory: hardwareInfo.systemInfo.total_memory - ? Math.round(hardwareInfo.systemInfo.total_memory / 1024 / 1024 / 1024) - : null, - gpu: hardwareInfo.gpuInfo - ? hardwareInfo.gpuInfo.model - : null, - monitor: null, - } - : null, + hardwareInfo: getHardwareInfoObject(), note: singleNote, // 保存备注(包含分辨率信息) }) } @@ -818,23 +814,7 @@ export function FpsTest() { 1 )}\nP1低帧: ${avgP1.toFixed(1)}`, videoSetting: tool.store.state.videoSetting, - hardwareInfo: hardwareInfo?.systemInfo - ? { - cpu: hardwareInfo.systemInfo.cpus[0]?.brand || null, - cpuCount: hardwareInfo.systemInfo.cpu_count || null, - os: - hardwareInfo.systemInfo.name && hardwareInfo.systemInfo.os_version - ? `${hardwareInfo.systemInfo.name} ${hardwareInfo.systemInfo.os_version}` - : null, - memory: hardwareInfo.systemInfo.total_memory - ? Math.round(hardwareInfo.systemInfo.total_memory / 1024 / 1024 / 1024) - : null, - gpu: hardwareInfo.gpuInfo - ? `${hardwareInfo.gpuInfo.vendor} ${hardwareInfo.gpuInfo.model}` - : null, - monitor: null, - } - : null, + hardwareInfo: getHardwareInfoObject(), note: averageNote, }) @@ -944,23 +924,7 @@ export function FpsTest() { 1 )}\nP1低帧: ${avgP1.toFixed(1)}`, videoSetting: tool.store.state.videoSetting, - hardwareInfo: hardwareInfo?.systemInfo - ? { - cpu: hardwareInfo.systemInfo.cpus[0]?.brand || null, - cpuCount: hardwareInfo.systemInfo.cpu_count || null, - os: - hardwareInfo.systemInfo.name && hardwareInfo.systemInfo.os_version - ? `${hardwareInfo.systemInfo.name} ${hardwareInfo.systemInfo.os_version}` - : null, - memory: hardwareInfo.systemInfo.total_memory - ? Math.round(hardwareInfo.systemInfo.total_memory / 1024 / 1024 / 1024) - : null, - gpu: hardwareInfo.gpuInfo - ? `${hardwareInfo.gpuInfo.vendor} ${hardwareInfo.gpuInfo.model}` - : null, - monitor: null, - } - : null, + hardwareInfo: getHardwareInfoObject(), note: averageNote, }) diff --git a/src/components/cstb/FpsTest/components/TestResultsTable.tsx b/src/components/cstb/FpsTest/components/TestResultsTable.tsx index 0739ef8..d568594 100644 --- a/src/components/cstb/FpsTest/components/TestResultsTable.tsx +++ b/src/components/cstb/FpsTest/components/TestResultsTable.tsx @@ -41,16 +41,20 @@ export function TestResultsTable({ > 测试时间 - 测试地图 - 平均帧 - P1低帧 + 地图 + 平均帧 + P1低帧 CPU 系统版本 GPU 内存 + 内存频率 + 主板型号 + 主板版本 + BIOS版本 视频设置 - 备注 - + 备注 + 操作 @@ -69,10 +73,10 @@ export function TestResultsTable({ {result.p1 !== null ? `${result.p1.toFixed(1)}` : "N/A"} - +
@@ -91,6 +95,28 @@ export function TestResultsTable({ ? `${result.hardwareInfo.memory}GB` : "N/A"} + + {result.hardwareInfo?.memorySpeed + ? `${result.hardwareInfo.memorySpeed}MHz` + : "N/A"} + + + +
+ {result.hardwareInfo?.motherboardModel || "N/A"} +
+
+
+ +
{result.hardwareInfo?.motherboardVersion || "N/A"}
+
+ +
{result.hardwareInfo?.biosVersion || "N/A"}
+
@@ -100,7 +126,7 @@ export function TestResultsTable({ - + onEditNote(result.id, result.note || "")} diff --git a/src/components/cstb/FpsTest/hooks/useHardwareInfo.ts b/src/components/cstb/FpsTest/hooks/useHardwareInfo.ts index 666692e..5f91306 100644 --- a/src/components/cstb/FpsTest/hooks/useHardwareInfo.ts +++ b/src/components/cstb/FpsTest/hooks/useHardwareInfo.ts @@ -22,10 +22,35 @@ interface ComputerInfo { ReleaseId?: string } +interface MemoryInfo { + capacity?: number // 容量(字节) + manufacturer?: string + speed?: number // MHz,实际频率 ConfiguredClockSpeed + default_speed?: number // MHz,默认频率 Speed(如果存在) +} + +interface MonitorInfo { + manufacturer?: string + model?: string + name?: string + refresh_rate?: number // Hz + resolution_width?: number + resolution_height?: number +} + +interface MotherboardInfo { + manufacturer?: string // 制造商 + model?: string // 型号 + version?: string +} + export interface HardwareInfoWithGpu { systemInfo: AllSystemInfo | null gpuInfo: GpuInfo | null computerInfo: ComputerInfo | null + memoryInfo: MemoryInfo[] + monitorInfo: MonitorInfo[] + motherboardInfo: MotherboardInfo | null } export function useHardwareInfo() { @@ -34,7 +59,7 @@ export function useHardwareInfo() { useEffect(() => { const fetchHardwareInfo = async () => { try { - const [sys, gpuInfo, computerInfo] = await Promise.all([ + const [sys, gpuInfo, computerInfo, memoryInfo, monitorInfo, motherboardInfo] = await Promise.all([ allSysInfo(), invoke("get_gpu_info").catch((error) => { console.error("获取 GPU 信息失败:", error) @@ -43,12 +68,27 @@ export function useHardwareInfo() { invoke("get_computer_info").catch((error) => { console.error("获取 PowerShell 信息失败:", error) return {} as ComputerInfo + }), + invoke("get_memory_info").catch((error) => { + console.error("获取内存信息失败:", error) + return [] as MemoryInfo[] + }), + invoke("get_monitor_info").catch((error) => { + console.error("获取显示器信息失败:", error) + return [] as MonitorInfo[] + }), + invoke("get_motherboard_info").catch((error) => { + console.error("获取主板信息失败:", error) + return { manufacturer: undefined, model: undefined, version: undefined } as MotherboardInfo }) ]) setHardwareInfo({ systemInfo: sys, gpuInfo, - computerInfo + computerInfo, + memoryInfo, + monitorInfo, + motherboardInfo }) } catch (error) { console.error("获取硬件信息失败:", error) diff --git a/src/components/cstb/FpsTest/utils/csv-export.ts b/src/components/cstb/FpsTest/utils/csv-export.ts index 5421b33..c37e422 100644 --- a/src/components/cstb/FpsTest/utils/csv-export.ts +++ b/src/components/cstb/FpsTest/utils/csv-export.ts @@ -38,6 +38,10 @@ export async function handleExportCSV( "系统版本", "GPU", "内存(GB)", + "内存频率(MHz)", + "主板型号", + "主板版本", + "BIOS版本", "分辨率", "视频设置", "备注", @@ -55,6 +59,10 @@ export async function handleExportCSV( `"${result.hardwareInfo?.os || "N/A"}"`, `"${result.hardwareInfo?.gpu || "N/A"}"`, result.hardwareInfo?.memory ? result.hardwareInfo.memory.toString() : "N/A", + result.hardwareInfo?.memorySpeed ? result.hardwareInfo.memorySpeed.toString() : "N/A", + `"${result.hardwareInfo?.motherboardModel || "N/A"}"`, + `"${result.hardwareInfo?.motherboardVersion || "N/A"}"`, + `"${result.hardwareInfo?.biosVersion || "N/A"}"`, result.videoSetting ? `${result.videoSetting.defaultres}x${result.videoSetting.defaultresheight}` : "N/A", @@ -118,6 +126,10 @@ export async function handleExportAverageCSV( "系统版本", "GPU", "内存(GB)", + "内存频率(MHz)", + "主板型号", + "主板版本", + "BIOS版本", "分辨率", "视频设置", "备注", @@ -135,6 +147,10 @@ export async function handleExportAverageCSV( `"${result.hardwareInfo?.os || "N/A"}"`, `"${result.hardwareInfo?.gpu || "N/A"}"`, result.hardwareInfo?.memory ? result.hardwareInfo.memory.toString() : "N/A", + result.hardwareInfo?.memorySpeed ? result.hardwareInfo.memorySpeed.toString() : "N/A", + `"${result.hardwareInfo?.motherboardModel || "N/A"}"`, + `"${result.hardwareInfo?.motherboardVersion || "N/A"}"`, + `"${result.hardwareInfo?.biosVersion || "N/A"}"`, result.videoSetting ? `${result.videoSetting.defaultres}x${result.videoSetting.defaultresheight}` : "N/A", diff --git a/src/store/fps_test.ts b/src/store/fps_test.ts index 7de2959..79ebba1 100644 --- a/src/store/fps_test.ts +++ b/src/store/fps_test.ts @@ -19,8 +19,16 @@ export interface FpsTestResult { cpuCount: number | null os: string | null memory: number | null // GB + memoryManufacturer: string | null + memorySpeed: number | null // MHz,实际频率 ConfiguredClockSpeed + memoryDefaultSpeed: number | null // MHz,默认频率 Speed(如果存在) gpu: string | null monitor: string | null + monitorManufacturer: string | null + monitorModel: string | null + motherboardModel: string | null // 合并后的制造商和型号 + motherboardVersion: string | null + biosVersion: string | null } | null // 硬件信息 note?: string // 备注(可选,用于向后兼容) }