[fix] csv export codec

This commit is contained in:
2025-11-06 16:21:24 +08:00
parent ae567eece7
commit b7f0d0b0cc
2 changed files with 61 additions and 23 deletions

View File

@@ -51,7 +51,7 @@
}, },
"productName": "CS工具箱", "productName": "CS工具箱",
"mainBinaryName": "cstb", "mainBinaryName": "cstb",
"version": "0.0.6-beta.4", "version": "0.0.6-beta.5",
"identifier": "upup.cool", "identifier": "upup.cool",
"plugins": { "plugins": {
"deep-link": { "deep-link": {

View File

@@ -32,7 +32,18 @@ import {
DropdownItem, DropdownItem,
} from "@heroui/react" } from "@heroui/react"
import { useState, useEffect, useRef, useCallback } from "react" import { useState, useEffect, useRef, useCallback } from "react"
import { TestTube, Power, List, Delete, Play, Edit, Check, Close, Square, DownloadOne } from "@icon-park/react" import {
TestTube,
Power,
List,
Delete,
Play,
Edit,
Check,
Close,
Square,
DownloadOne,
} from "@icon-park/react"
import { allSysInfo, type AllSystemInfo } from "tauri-plugin-system-info-api" import { allSysInfo, type AllSystemInfo } from "tauri-plugin-system-info-api"
import { ToolButton } from "../window/ToolButton" import { ToolButton } from "../window/ToolButton"
import { save } from "@tauri-apps/plugin-dialog" import { save } from "@tauri-apps/plugin-dialog"
@@ -215,7 +226,11 @@ export function FpsTest() {
const [resolutionWidth, setResolutionWidth] = useState<string>("") // 分辨率宽度 const [resolutionWidth, setResolutionWidth] = useState<string>("") // 分辨率宽度
const [resolutionHeight, setResolutionHeight] = useState<string>("") // 分辨率高度 const [resolutionHeight, setResolutionHeight] = useState<string>("") // 分辨率高度
const [isFullscreen, setIsFullscreen] = useState<boolean>(true) // 全屏模式(默认全屏) const [isFullscreen, setIsFullscreen] = useState<boolean>(true) // 全屏模式(默认全屏)
const { isOpen: isNoteModalOpen, onOpen: onNoteModalOpen, onClose: onNoteModalClose } = useDisclosure() const {
isOpen: isNoteModalOpen,
onOpen: onNoteModalOpen,
onClose: onNoteModalClose,
} = useDisclosure()
const monitoringIntervalRef = useRef<NodeJS.Timeout | null>(null) const monitoringIntervalRef = useRef<NodeJS.Timeout | null>(null)
const timeoutRef = useRef<NodeJS.Timeout | null>(null) const timeoutRef = useRef<NodeJS.Timeout | null>(null)
// 记录测试开始的时间戳(用于过滤旧数据) // 记录测试开始的时间戳(用于过滤旧数据)
@@ -357,7 +372,8 @@ export function FpsTest() {
const mapConfig = BENCHMARK_MAPS[selectedMapIndex] const mapConfig = BENCHMARK_MAPS[selectedMapIndex]
// 使用测试开始时的视频设置(如果有的话),否则使用当前的 // 使用测试开始时的视频设置(如果有的话),否则使用当前的
const currentVideoSetting = testStartVideoSettingRef.current || tool.store.state.videoSetting const currentVideoSetting =
testStartVideoSettingRef.current || tool.store.state.videoSetting
fpsTest.addResult({ fpsTest.addResult({
id: `${now.getTime()}-${Math.random().toString(36).slice(2, 11)}`, id: `${now.getTime()}-${Math.random().toString(36).slice(2, 11)}`,
@@ -434,7 +450,14 @@ export function FpsTest() {
return false return false
} }
}, },
[steam.state.cs2Dir, selectedMapIndex, fpsTest, tool.store, hardwareInfo, tool.state.autoCloseGame] [
steam.state.cs2Dir,
selectedMapIndex,
fpsTest,
tool.store,
hardwareInfo,
tool.state.autoCloseGame,
]
) )
// 开始监控文件更新 // 开始监控文件更新
@@ -550,14 +573,14 @@ export function FpsTest() {
try { try {
// 构建启动参数:基础参数 + 分辨率和全屏设置 + 自定义启动项(如果有) // 构建启动参数:基础参数 + 分辨率和全屏设置 + 自定义启动项(如果有)
let baseLaunchOption = `-allow_third_party_software -condebug -conclearlog +map_workshop ${mapConfig.workshopId} ${mapConfig.map}` let baseLaunchOption = `-allow_third_party_software -condebug -conclearlog +map_workshop ${mapConfig.workshopId} ${mapConfig.map}`
// 只有在启用分辨率和全屏设置时才添加相关参数 // 只有在启用分辨率和全屏设置时才添加相关参数
if (isResolutionEnabled) { if (isResolutionEnabled) {
// 添加分辨率设置(如果有设置) // 添加分辨率设置(如果有设置)
if (resolutionWidth && resolutionHeight) { if (resolutionWidth && resolutionHeight) {
baseLaunchOption += ` -w ${resolutionWidth} -h ${resolutionHeight}` baseLaunchOption += ` -w ${resolutionWidth} -h ${resolutionHeight}`
} }
// 添加全屏/窗口化设置 // 添加全屏/窗口化设置
if (isFullscreen) { if (isFullscreen) {
baseLaunchOption += ` -fullscreen` baseLaunchOption += ` -fullscreen`
@@ -565,7 +588,7 @@ export function FpsTest() {
baseLaunchOption += ` -sw` baseLaunchOption += ` -sw`
} }
} }
// 添加自定义启动项(如果有,开头加空格避免粘连) // 添加自定义启动项(如果有,开头加空格避免粘连)
const launchOption = customLaunchOption.trim() const launchOption = customLaunchOption.trim()
? `${baseLaunchOption} ${customLaunchOption.trim()}` ? `${baseLaunchOption} ${customLaunchOption.trim()}`
@@ -600,12 +623,15 @@ export function FpsTest() {
const canStartTest = !tool.state.autoCloseGame ? !isGameRunning : true const canStartTest = !tool.state.autoCloseGame ? !isGameRunning : true
// 格式化视频设置摘要 // 格式化视频设置摘要
const formatVideoSettingSummary = (videoSetting: typeof tool.state.videoSetting | null): string => { const formatVideoSettingSummary = (
videoSetting: typeof tool.state.videoSetting | null
): string => {
if (!videoSetting) return "N/A" if (!videoSetting) return "N/A"
const resolution = `${videoSetting.defaultres}x${videoSetting.defaultresheight}` const resolution = `${videoSetting.defaultres}x${videoSetting.defaultresheight}`
const refreshRate = videoSetting.refreshrate_denominator === "1" const refreshRate =
? videoSetting.refreshrate_numerator videoSetting.refreshrate_denominator === "1"
: `${videoSetting.refreshrate_numerator}/${videoSetting.refreshrate_denominator}` ? videoSetting.refreshrate_numerator
: `${videoSetting.refreshrate_numerator}/${videoSetting.refreshrate_denominator}`
const msaa = videoSetting.msaa_samples === "0" ? "无" : `${videoSetting.msaa_samples}x` const msaa = videoSetting.msaa_samples === "0" ? "无" : `${videoSetting.msaa_samples}x`
return `${resolution}@${refreshRate}Hz, MSAA:${msaa}` return `${resolution}@${refreshRate}Hz, MSAA:${msaa}`
} }
@@ -640,7 +666,7 @@ export function FpsTest() {
const headers = [ const headers = [
"测试时间", "测试时间",
"测试地图", "测试地图",
"AVG平均帧", "平均帧",
"P1低帧", "P1低帧",
"CPU", "CPU",
"系统版本", "系统版本",
@@ -650,9 +676,9 @@ export function FpsTest() {
"视频设置", "视频设置",
"备注", "备注",
] ]
const csvRows = [headers.join(",")] const csvRows = [headers.join(",")]
for (const result of fpsTest.state.results) { for (const result of fpsTest.state.results) {
const row = [ const row = [
`"${result.testTime}"`, `"${result.testTime}"`,
@@ -671,9 +697,12 @@ export function FpsTest() {
] ]
csvRows.push(row.join(",")) csvRows.push(row.join(","))
} }
const csvContent = csvRows.join("\n") const csvContent = csvRows.join("\n")
// 添加UTF-8 BOM以确保Excel等软件正确识别编码
const csvContentWithBOM = "\uFEFF" + csvContent
// 使用文件保存对话框 // 使用文件保存对话框
const filePath = await save({ const filePath = await save({
filters: [ filters: [
@@ -684,9 +713,9 @@ export function FpsTest() {
], ],
defaultPath: `fps_test_results_${new Date().toISOString().split("T")[0]}.csv`, defaultPath: `fps_test_results_${new Date().toISOString().split("T")[0]}.csv`,
}) })
if (filePath) { if (filePath) {
await writeTextFile(filePath, csvContent) await writeTextFile(filePath, csvContentWithBOM)
addToast({ title: "导出成功", color: "success" }) addToast({ title: "导出成功", color: "success" })
} }
} catch (error) { } catch (error) {
@@ -796,7 +825,7 @@ export function FpsTest() {
<TableHeader> <TableHeader>
<TableColumn></TableColumn> <TableColumn></TableColumn>
<TableColumn></TableColumn> <TableColumn></TableColumn>
<TableColumn>AVG平均</TableColumn> <TableColumn></TableColumn>
<TableColumn>P1低帧</TableColumn> <TableColumn>P1低帧</TableColumn>
<TableColumn>CPU</TableColumn> <TableColumn>CPU</TableColumn>
<TableColumn></TableColumn> <TableColumn></TableColumn>
@@ -817,17 +846,26 @@ export function FpsTest() {
<TableCell className="text-xs"> <TableCell className="text-xs">
{result.p1 !== null ? `${result.p1.toFixed(1)}` : "N/A"} {result.p1 !== null ? `${result.p1.toFixed(1)}` : "N/A"}
</TableCell> </TableCell>
<TableCell className="text-xs max-w-[200px]" title={result.hardwareInfo?.cpu || undefined}> <TableCell
className="text-xs max-w-[160px]"
title={result.hardwareInfo?.cpu || undefined}
>
<div className="truncate whitespace-nowrap"> <div className="truncate whitespace-nowrap">
{result.hardwareInfo?.cpu || "N/A"} {result.hardwareInfo?.cpu || "N/A"}
</div> </div>
</TableCell> </TableCell>
<TableCell className="text-xs max-w-[180px]" title={result.hardwareInfo?.os || undefined}> <TableCell
className="text-xs max-w-[160px]"
title={result.hardwareInfo?.os || undefined}
>
<div className="truncate whitespace-nowrap"> <div className="truncate whitespace-nowrap">
{result.hardwareInfo?.os || "N/A"} {result.hardwareInfo?.os || "N/A"}
</div> </div>
</TableCell> </TableCell>
<TableCell className="text-xs max-w-[180px]" title={result.hardwareInfo?.gpu || undefined}> <TableCell
className="text-xs max-w-[180px]"
title={result.hardwareInfo?.gpu || undefined}
>
<div className="truncate whitespace-nowrap"> <div className="truncate whitespace-nowrap">
{result.hardwareInfo?.gpu || "N/A"} {result.hardwareInfo?.gpu || "N/A"}
</div> </div>