("/api/hardware-info", hardwareInfoFetcher, {
- revalidateOnFocus: false,
- revalidateOnReconnect: false,
- dedupingInterval: 5 * 60 * 1000, // 5分钟内相同请求去重
- })
+ const { state, fetchHardwareInfo } = useHardwareStore()
+ const [isLoading, setIsLoading] = useState(!state.allSysData)
- const allSysData = data?.allSysData
- const computerInfo = data?.computerInfo || {}
- const gpuInfo = data?.gpuInfo
- const memoryInfo = data?.memoryInfo || []
- const monitorInfo = data?.monitorInfo || []
- const motherboardInfo = data?.motherboardInfo
+ useEffect(() => {
+ // 如果数据不存在,则加载数据
+ if (!state.allSysData) {
+ setIsLoading(true)
+ void fetchHardwareInfo().finally(() => {
+ setIsLoading(false)
+ })
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []) // 只在组件挂载时执行一次,state 是响应式的,不需要作为依赖
+
+ const allSysData = state.allSysData
+ const computerInfo = state.computerInfo || {}
+ const gpuInfo = state.gpuInfo
+ const memoryInfo = state.memoryInfo || []
+ const monitorInfo = state.monitorInfo || []
+ const motherboardInfo = state.motherboardInfo
const formatBytes = (bytes?: number) => {
if (!bytes) return "未知"
@@ -243,8 +153,8 @@ function HardwareInfoContent() {
})()
: null
- // 如果正在加载或正在验证(包括刷新),显示 Skeleton 骨架屏
- if (isLoading || isValidating) {
+ // 如果正在加载,显示 Skeleton 骨架屏
+ if (isLoading || !allSysData) {
return (
{/* 系统信息 Skeleton */}
diff --git a/src/components/cstb/FpsTest/hooks/useHardwareInfo.ts b/src/components/cstb/FpsTest/hooks/useHardwareInfo.ts
index 5f91306..605c09b 100644
--- a/src/components/cstb/FpsTest/hooks/useHardwareInfo.ts
+++ b/src/components/cstb/FpsTest/hooks/useHardwareInfo.ts
@@ -1,48 +1,13 @@
-import { useState, useEffect } from "react"
-import { allSysInfo, type AllSystemInfo } from "tauri-plugin-system-info-api"
-import { invoke } from "@tauri-apps/api/core"
-
-interface GpuInfo {
- vendor: string
- model: string
- family: string
- device_id: string
- total_vram: number
- used_vram: number
- load_pct: number
- temperature: number
-}
-
-interface ComputerInfo {
- OsName?: string
- OSDisplayVersion?: string
- BiosSMBIOSBIOSVersion?: string
- CsManufacturer?: string
- CsName?: string
- 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
-}
+import { useEffect } from "react"
+import { useHardwareStore } from "@/store/hardware"
+import type { AllSystemInfo } from "tauri-plugin-system-info-api"
+import type {
+ GpuInfo,
+ ComputerInfo,
+ MemoryInfo,
+ MonitorInfo,
+ MotherboardInfo,
+} from "@/store/hardware"
export interface HardwareInfoWithGpu {
systemInfo: AllSystemInfo | null
@@ -54,49 +19,23 @@ export interface HardwareInfoWithGpu {
}
export function useHardwareInfo() {
- const [hardwareInfo, setHardwareInfo] = useState(null)
+ const { state, fetchHardwareInfo } = useHardwareStore()
useEffect(() => {
- const fetchHardwareInfo = async () => {
- try {
- const [sys, gpuInfo, computerInfo, memoryInfo, monitorInfo, motherboardInfo] = await Promise.all([
- allSysInfo(),
- invoke("get_gpu_info").catch((error) => {
- console.error("获取 GPU 信息失败:", error)
- return null
- }),
- 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,
- memoryInfo,
- monitorInfo,
- motherboardInfo
- })
- } catch (error) {
- console.error("获取硬件信息失败:", error)
- }
+ // 如果数据不存在,则加载数据(store 初始化时已经加载,这里只是确保)
+ if (!state.allSysData) {
+ void fetchHardwareInfo()
}
- void fetchHardwareInfo()
- }, [])
+ }, []) // 只在组件挂载时执行一次
- return hardwareInfo
+ // 将 store 中的数据转换为兼容的格式
+ return {
+ systemInfo: state.allSysData,
+ gpuInfo: state.gpuInfo,
+ computerInfo: state.computerInfo,
+ memoryInfo: state.memoryInfo,
+ monitorInfo: state.monitorInfo,
+ motherboardInfo: state.motherboardInfo,
+ } as HardwareInfoWithGpu
}
diff --git a/src/components/cstb/UpdateChecker.tsx b/src/components/cstb/UpdateChecker.tsx
index f453d40..9ea3309 100644
--- a/src/components/cstb/UpdateChecker.tsx
+++ b/src/components/cstb/UpdateChecker.tsx
@@ -170,19 +170,22 @@ export function UpdateChecker({ useMirror = true, customEndpoint, includePrerele
if (!installerPath) return
try {
+ addToast({
+ title: "安装已启动",
+ description: "应用将在安装完成后自动重启",
+ color: "success",
+ })
+
+ // 调用安装命令(这会阻塞直到安装完成)
await invoke("install_app_update", {
installerPath: installerPath,
})
- addToast({
- title: "安装已启动",
- description: "应用将在安装完成后重启",
- color: "success",
- })
-
- setTimeout(async () => {
- await relaunch()
- }, 1000)
+ // 安装完成后,等待一小段时间确保安装程序完全退出
+ await new Promise(resolve => setTimeout(resolve, 500))
+
+ // 启动新版本
+ await relaunch()
} catch (error) {
console.error("安装更新失败:", error)
addToast({
diff --git a/src/store/hardware.ts b/src/store/hardware.ts
new file mode 100644
index 0000000..dc8baa0
--- /dev/null
+++ b/src/store/hardware.ts
@@ -0,0 +1,151 @@
+import { store } from "@tauri-store/valtio"
+import { useSnapshot } from "valtio"
+import { DEFAULT_STORE_CONFIG } from "./config"
+import { allSysInfo, type AllSystemInfo } from "tauri-plugin-system-info-api"
+import { invoke } from "@tauri-apps/api/core"
+
+export interface ComputerInfo {
+ OsName?: string
+ OSDisplayVersion?: string
+ BiosSMBIOSBIOSVersion?: string
+ CsManufacturer?: string
+ CsName?: string
+ ReleaseId?: string
+}
+
+export interface GpuInfo {
+ vendor: string
+ model: string
+ family: string
+ device_id: string
+ total_vram: number
+ used_vram: number
+ load_pct: number
+ temperature: number
+}
+
+export interface MemoryInfo {
+ capacity?: number // 容量(字节)
+ manufacturer?: string
+ speed?: number // MHz,实际频率 ConfiguredClockSpeed
+ default_speed?: number // MHz,默认频率 Speed(如果存在)
+}
+
+export interface MonitorInfo {
+ name?: string
+ refresh_rate?: number // Hz
+ resolution_width?: number
+ resolution_height?: number
+}
+
+export interface MotherboardInfo {
+ manufacturer?: string // 制造商
+ model?: string // 型号
+ version?: string
+}
+
+export interface HardwareData {
+ allSysData: AllSystemInfo | null
+ computerInfo: ComputerInfo
+ gpuInfo: GpuInfo | null
+ memoryInfo: MemoryInfo[]
+ monitorInfo: MonitorInfo[]
+ motherboardInfo: MotherboardInfo | null
+ lastUpdated: number // 最后更新时间戳
+}
+
+const defaultValue: HardwareData = {
+ allSysData: null,
+ computerInfo: {},
+ gpuInfo: null,
+ memoryInfo: [],
+ monitorInfo: [],
+ motherboardInfo: null,
+ lastUpdated: 0,
+}
+
+// 硬件信息 fetcher
+const hardwareInfoFetcher = async (): Promise => {
+ // 并行获取系统信息、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
+ }),
+ ])
+
+ return {
+ allSysData: sys,
+ computerInfo: computerInfoData,
+ gpuInfo: gpuInfoData,
+ memoryInfo: memoryInfoData,
+ monitorInfo: monitorInfoData,
+ motherboardInfo: motherboardInfoData,
+ lastUpdated: Date.now(),
+ }
+}
+
+export const hardwareStore = store("hardware", { ...defaultValue }, DEFAULT_STORE_CONFIG)
+
+// 检查数据是否过期(30分钟)
+const isDataStale = (lastUpdated: number): boolean => {
+ const thirtyMinutes = 30 * 60 * 1000
+ return Date.now() - lastUpdated > thirtyMinutes
+}
+
+// 获取硬件信息(如果数据过期或不存在则重新获取)
+export const fetchHardwareInfo = async (force = false): Promise => {
+ // 如果数据存在且未过期,且不是强制刷新,则直接返回
+ if (!force && hardwareStore.state.allSysData && !isDataStale(hardwareStore.state.lastUpdated)) {
+ return
+ }
+
+ try {
+ const data = await hardwareInfoFetcher()
+ hardwareStore.state.allSysData = data.allSysData
+ hardwareStore.state.computerInfo = data.computerInfo
+ hardwareStore.state.gpuInfo = data.gpuInfo
+ hardwareStore.state.memoryInfo = data.memoryInfo
+ hardwareStore.state.monitorInfo = data.monitorInfo
+ hardwareStore.state.motherboardInfo = data.motherboardInfo
+ hardwareStore.state.lastUpdated = data.lastUpdated
+ } catch (error) {
+ console.error("获取硬件信息失败:", error)
+ }
+}
+
+// 强制刷新硬件信息
+export const refreshHardwareInfo = async (): Promise => {
+ await fetchHardwareInfo(true)
+}
+
+export const useHardwareStore = () => {
+ void hardwareStore.start
+ const state = useSnapshot(hardwareStore.state)
+
+ return {
+ state,
+ store: hardwareStore,
+ fetchHardwareInfo,
+ refreshHardwareInfo,
+ }
+}
+
diff --git a/src/store/index.ts b/src/store/index.ts
index 801e0a1..b3e5bb6 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -3,6 +3,7 @@ import { authStore } from "./auth"
import { steamStore } from "./steam"
import { toolStore } from "./tool"
import { fpsTestStore } from "./fps_test"
+import { hardwareStore, fetchHardwareInfo } from "./hardware"
export async function init() {
await appStore.start()
@@ -10,4 +11,7 @@ export async function init() {
await toolStore.start()
await steamStore.start()
await fpsTestStore.start()
+ await hardwareStore.start()
+ // 初始化时自动加载硬件信息(如果数据过期或不存在)
+ await fetchHardwareInfo()
}