[feat] batch testing and average
This commit is contained in:
@@ -30,6 +30,9 @@ import {
|
|||||||
DropdownTrigger,
|
DropdownTrigger,
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownItem,
|
DropdownItem,
|
||||||
|
Select,
|
||||||
|
SelectItem,
|
||||||
|
CircularProgress,
|
||||||
} from "@heroui/react"
|
} from "@heroui/react"
|
||||||
import { useState, useEffect, useRef, useCallback } from "react"
|
import { useState, useEffect, useRef, useCallback } from "react"
|
||||||
import {
|
import {
|
||||||
@@ -226,6 +229,18 @@ 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 [batchTestCount, setBatchTestCount] = useState<number>(1) // 批量测试次数(1表示单次测试)
|
||||||
|
const [batchTestProgress, setBatchTestProgress] = useState<{
|
||||||
|
current: number
|
||||||
|
total: number
|
||||||
|
} | null>(null) // 批量测试进度
|
||||||
|
const [batchTestResults, setBatchTestResults] = useState<
|
||||||
|
Array<{ avg: number | null; p1: number | null }>
|
||||||
|
>([]) // 批量测试结果
|
||||||
|
const [isBatchTesting, setIsBatchTesting] = useState<boolean>(false) // 批量测试是否正在进行
|
||||||
|
const batchTestAbortRef = useRef<boolean>(false) // 批量测试中止标志
|
||||||
|
const testCompleteRef = useRef<boolean>(false) // 测试完成标志
|
||||||
|
const batchTestResultsRef = useRef<Array<{ avg: number | null; p1: number | null }>>([]) // 批量测试结果ref(用于在循环中收集)
|
||||||
const {
|
const {
|
||||||
isOpen: isNoteModalOpen,
|
isOpen: isNoteModalOpen,
|
||||||
onOpen: onNoteModalOpen,
|
onOpen: onNoteModalOpen,
|
||||||
@@ -286,6 +301,15 @@ export function FpsTest() {
|
|||||||
|
|
||||||
// 停止测试
|
// 停止测试
|
||||||
const stopTest = useCallback(async () => {
|
const stopTest = useCallback(async () => {
|
||||||
|
// 如果是批量测试,设置中止标志
|
||||||
|
if (batchTestProgress) {
|
||||||
|
batchTestAbortRef.current = true
|
||||||
|
setBatchTestProgress(null)
|
||||||
|
setBatchTestResults([])
|
||||||
|
setIsBatchTesting(false) // 重置批量测试状态
|
||||||
|
addToast({ title: "已停止批量测试" })
|
||||||
|
}
|
||||||
|
|
||||||
setIsMonitoring(false)
|
setIsMonitoring(false)
|
||||||
if (monitoringIntervalRef.current) {
|
if (monitoringIntervalRef.current) {
|
||||||
clearInterval(monitoringIntervalRef.current)
|
clearInterval(monitoringIntervalRef.current)
|
||||||
@@ -310,7 +334,7 @@ export function FpsTest() {
|
|||||||
} else {
|
} else {
|
||||||
addToast({ title: "已停止测试" })
|
addToast({ title: "已停止测试" })
|
||||||
}
|
}
|
||||||
}, [tool.state.autoCloseGame])
|
}, [tool.state.autoCloseGame, batchTestProgress])
|
||||||
|
|
||||||
// 读取结果函数
|
// 读取结果函数
|
||||||
const readResult = useCallback(
|
const readResult = useCallback(
|
||||||
@@ -354,6 +378,7 @@ export function FpsTest() {
|
|||||||
|
|
||||||
// 停止监控和超时
|
// 停止监控和超时
|
||||||
setIsMonitoring(false)
|
setIsMonitoring(false)
|
||||||
|
testCompleteRef.current = true // 标记测试完成
|
||||||
if (monitoringIntervalRef.current) {
|
if (monitoringIntervalRef.current) {
|
||||||
clearInterval(monitoringIntervalRef.current)
|
clearInterval(monitoringIntervalRef.current)
|
||||||
monitoringIntervalRef.current = null
|
monitoringIntervalRef.current = null
|
||||||
@@ -375,6 +400,51 @@ export function FpsTest() {
|
|||||||
const currentVideoSetting =
|
const currentVideoSetting =
|
||||||
testStartVideoSettingRef.current || tool.store.state.videoSetting
|
testStartVideoSettingRef.current || tool.store.state.videoSetting
|
||||||
|
|
||||||
|
// 如果是批量测试,保存结果到批量结果数组,否则直接保存
|
||||||
|
const currentBatchProgress = batchTestProgress
|
||||||
|
if (currentBatchProgress) {
|
||||||
|
const result = { avg, p1 }
|
||||||
|
setBatchTestResults((prev) => [...prev, result])
|
||||||
|
batchTestResultsRef.current = [...batchTestResultsRef.current, result]
|
||||||
|
|
||||||
|
// 添加带批量标识的备注
|
||||||
|
const batchNote = testNote
|
||||||
|
? `${testNote} [批量${currentBatchProgress.current}/${currentBatchProgress.total}]`
|
||||||
|
: `[批量${currentBatchProgress.current}/${currentBatchProgress.total}]`
|
||||||
|
|
||||||
|
fpsTest.addResult({
|
||||||
|
id: `${now.getTime()}-${Math.random().toString(36).slice(2, 11)}`,
|
||||||
|
testTime: parsed.timestamp,
|
||||||
|
testDate,
|
||||||
|
mapName: mapConfig?.name || "unknown",
|
||||||
|
mapLabel: mapConfig?.label || "未知地图",
|
||||||
|
avg,
|
||||||
|
p1,
|
||||||
|
rawResult: parsed.data,
|
||||||
|
videoSetting: currentVideoSetting,
|
||||||
|
hardwareInfo: hardwareInfo
|
||||||
|
? {
|
||||||
|
cpu: hardwareInfo.cpus[0]?.brand || null,
|
||||||
|
cpuCount: hardwareInfo.cpu_count || null,
|
||||||
|
os:
|
||||||
|
hardwareInfo.name && hardwareInfo.os_version
|
||||||
|
? `${hardwareInfo.name} ${hardwareInfo.os_version}`
|
||||||
|
: null,
|
||||||
|
memory: hardwareInfo.total_memory
|
||||||
|
? Math.round(hardwareInfo.total_memory / 1024 / 1024 / 1024)
|
||||||
|
: null,
|
||||||
|
gpu: null,
|
||||||
|
monitor: null,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
note: batchNote,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 批量测试中,测试完成后继续下一轮
|
||||||
|
if (currentBatchProgress.current < currentBatchProgress.total) {
|
||||||
|
// 不在这里处理,由startTest的循环处理
|
||||||
|
}
|
||||||
|
} else {
|
||||||
fpsTest.addResult({
|
fpsTest.addResult({
|
||||||
id: `${now.getTime()}-${Math.random().toString(36).slice(2, 11)}`,
|
id: `${now.getTime()}-${Math.random().toString(36).slice(2, 11)}`,
|
||||||
testTime: parsed.timestamp,
|
testTime: parsed.timestamp,
|
||||||
@@ -402,6 +472,7 @@ export function FpsTest() {
|
|||||||
: null,
|
: null,
|
||||||
note: testNote, // 保存备注
|
note: testNote, // 保存备注
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 清除保存的启动时视频设置
|
// 清除保存的启动时视频设置
|
||||||
testStartVideoSettingRef.current = null
|
testStartVideoSettingRef.current = null
|
||||||
@@ -457,6 +528,8 @@ export function FpsTest() {
|
|||||||
tool.store,
|
tool.store,
|
||||||
hardwareInfo,
|
hardwareInfo,
|
||||||
tool.state.autoCloseGame,
|
tool.state.autoCloseGame,
|
||||||
|
batchTestProgress,
|
||||||
|
testNote,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -522,16 +595,19 @@ export function FpsTest() {
|
|||||||
}
|
}
|
||||||
}, [isMonitoring, steam.state.cs2Dir, readResult, tool.state.autoCloseGame])
|
}, [isMonitoring, steam.state.cs2Dir, readResult, tool.state.autoCloseGame])
|
||||||
|
|
||||||
const startTest = async () => {
|
// 执行单次测试
|
||||||
|
const runSingleTest = async (
|
||||||
|
testIndex: number,
|
||||||
|
totalTests: number,
|
||||||
|
isFirstTest: boolean = false
|
||||||
|
): Promise<boolean> => {
|
||||||
if (!steam.state.steamDir || !steam.state.cs2Dir) {
|
if (!steam.state.steamDir || !steam.state.cs2Dir) {
|
||||||
addToast({ title: "请先配置 Steam 和 CS2 路径", variant: "flat", color: "warning" })
|
return false
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapConfig = BENCHMARK_MAPS[selectedMapIndex]
|
const mapConfig = BENCHMARK_MAPS[selectedMapIndex]
|
||||||
if (!mapConfig) {
|
if (!mapConfig) {
|
||||||
addToast({ title: "请选择测试地图", variant: "flat", color: "warning" })
|
return false
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果启用了自动关闭游戏,检测并关闭正在运行的游戏
|
// 如果启用了自动关闭游戏,检测并关闭正在运行的游戏
|
||||||
@@ -540,23 +616,17 @@ export function FpsTest() {
|
|||||||
if (gameRunning) {
|
if (gameRunning) {
|
||||||
try {
|
try {
|
||||||
await invoke("kill_game")
|
await invoke("kill_game")
|
||||||
addToast({ title: "检测到游戏正在运行,已关闭" })
|
|
||||||
// 等待一下确保游戏关闭
|
// 等待一下确保游戏关闭
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2000))
|
await new Promise((resolve) => setTimeout(resolve, 2000))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("关闭游戏失败:", error)
|
console.error("关闭游戏失败:", error)
|
||||||
addToast({
|
return false
|
||||||
title: `关闭游戏失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
||||||
variant: "flat",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTestResult(null)
|
setTestResult(null)
|
||||||
setTestTimestamp(null)
|
setTestTimestamp(null)
|
||||||
// 注意:不清空备注,让用户可以在测试过程中记住备注内容
|
|
||||||
|
|
||||||
// 记录测试开始时间戳(格式:MM/DD HH:mm:ss)
|
// 记录测试开始时间戳(格式:MM/DD HH:mm:ss)
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
@@ -567,8 +637,6 @@ export function FpsTest() {
|
|||||||
const second = String(now.getSeconds()).padStart(2, "0")
|
const second = String(now.getSeconds()).padStart(2, "0")
|
||||||
testStartTimestampRef.current = `${month}/${day} ${hour}:${minute}:${second}`
|
testStartTimestampRef.current = `${month}/${day} ${hour}:${minute}:${second}`
|
||||||
testStartTimeRef.current = now.getTime()
|
testStartTimeRef.current = now.getTime()
|
||||||
// 保存启动时的视频设置
|
|
||||||
testStartVideoSettingRef.current = { ...tool.store.state.videoSetting }
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 构建启动参数:基础参数 + 分辨率和全屏设置 + 自定义启动项(如果有)
|
// 构建启动参数:基础参数 + 分辨率和全屏设置 + 自定义启动项(如果有)
|
||||||
@@ -601,10 +669,57 @@ export function FpsTest() {
|
|||||||
server: "worldwide",
|
server: "worldwide",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 延迟读取视频设置(修复分辨率读取bug)
|
||||||
|
// 等待游戏启动并应用分辨率设置(5秒)
|
||||||
|
// 批量测试的第一次不需要等待,因为游戏还没有启动过
|
||||||
|
if (!isFirstTest) {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 5000))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新读取视频配置
|
||||||
|
if (steam.state.steamDirValid && steam.currentUser()) {
|
||||||
|
await tool.getVideoConfig(steam.state.steamDir, steam.currentUser()?.steam_id32 || 0)
|
||||||
|
// 再等待一下确保配置已更新
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存启动后的视频设置(延迟读取后的)
|
||||||
|
testStartVideoSettingRef.current = { ...tool.store.state.videoSetting }
|
||||||
|
|
||||||
|
if (totalTests > 1) {
|
||||||
|
addToast({
|
||||||
|
title: `批量测试 ${testIndex}/${totalTests}:已启动 ${mapConfig.label} 测试,正在自动监听结果...`,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
addToast({ title: `已启动 ${mapConfig.label} 测试,正在自动监听结果...` })
|
addToast({ title: `已启动 ${mapConfig.label} 测试,正在自动监听结果...` })
|
||||||
|
}
|
||||||
|
|
||||||
// 开始自动监听文件更新
|
// 开始自动监听文件更新
|
||||||
setIsMonitoring(true)
|
setIsMonitoring(true)
|
||||||
|
testCompleteRef.current = false // 重置完成标志
|
||||||
|
|
||||||
|
// 等待测试完成(通过readResult的回调来处理)
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
let resolved = false
|
||||||
|
// 设置一个标志,当readResult成功时调用resolve
|
||||||
|
const checkInterval = setInterval(() => {
|
||||||
|
// 检查是否已经读取到结果(testCompleteRef被设置为true表示测试完成)
|
||||||
|
if (testCompleteRef.current && !resolved) {
|
||||||
|
resolved = true
|
||||||
|
clearInterval(checkInterval)
|
||||||
|
resolve(true)
|
||||||
|
}
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
// 设置超时
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!resolved) {
|
||||||
|
resolved = true
|
||||||
|
clearInterval(checkInterval)
|
||||||
|
resolve(false)
|
||||||
|
}
|
||||||
|
}, TEST_TIMEOUT + 10000)
|
||||||
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("启动测试失败:", error)
|
console.error("启动测试失败:", error)
|
||||||
addToast({
|
addToast({
|
||||||
@@ -612,15 +727,138 @@ export function FpsTest() {
|
|||||||
variant: "flat",
|
variant: "flat",
|
||||||
})
|
})
|
||||||
setIsMonitoring(false)
|
setIsMonitoring(false)
|
||||||
// 启动失败,清除测试开始时间戳和视频设置
|
|
||||||
testStartTimestampRef.current = null
|
testStartTimestampRef.current = null
|
||||||
testStartTimeRef.current = null
|
testStartTimeRef.current = null
|
||||||
testStartVideoSettingRef.current = null
|
testStartVideoSettingRef.current = null
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否可以开始测试
|
const startTest = async () => {
|
||||||
const canStartTest = !tool.state.autoCloseGame ? !isGameRunning : true
|
if (!steam.state.steamDir || !steam.state.cs2Dir) {
|
||||||
|
addToast({ title: "请先配置 Steam 和 CS2 路径", variant: "flat", color: "warning" })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapConfig = BENCHMARK_MAPS[selectedMapIndex]
|
||||||
|
if (!mapConfig) {
|
||||||
|
addToast({ title: "请选择测试地图", variant: "flat", color: "warning" })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalTests = batchTestCount
|
||||||
|
batchTestAbortRef.current = false
|
||||||
|
setBatchTestResults([])
|
||||||
|
batchTestResultsRef.current = []
|
||||||
|
|
||||||
|
if (totalTests > 1) {
|
||||||
|
// 批量测试
|
||||||
|
setIsBatchTesting(true) // 设置批量测试状态
|
||||||
|
setBatchTestProgress({ current: 0, total: totalTests })
|
||||||
|
|
||||||
|
for (let i = 1; i <= totalTests; i++) {
|
||||||
|
if (batchTestAbortRef.current) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
setBatchTestProgress({ current: i, total: totalTests })
|
||||||
|
|
||||||
|
// 执行单次测试,第一次测试跳过5秒等待
|
||||||
|
const success = await runSingleTest(i, totalTests, i === 1)
|
||||||
|
|
||||||
|
if (!success && !batchTestAbortRef.current) {
|
||||||
|
addToast({ title: `批量测试 ${i}/${totalTests} 失败`, variant: "flat", color: "warning" })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果不是最后一次测试,等待5秒再继续
|
||||||
|
if (i < totalTests && !batchTestAbortRef.current) {
|
||||||
|
// 确保游戏已关闭(如果自动关闭已启用,readResult中已经关闭了)
|
||||||
|
if (tool.state.autoCloseGame) {
|
||||||
|
// 等待游戏关闭完成(readResult中延迟2秒关闭)
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 3000))
|
||||||
|
try {
|
||||||
|
await invoke("kill_game").catch(() => {})
|
||||||
|
} catch (error) {
|
||||||
|
console.error("关闭游戏失败:", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 等待5秒
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 5000))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量测试完成,计算平均值
|
||||||
|
// 使用ref中收集的结果(确保获取到所有结果)
|
||||||
|
const finalResults = batchTestResultsRef.current
|
||||||
|
if (!batchTestAbortRef.current && finalResults.length > 0) {
|
||||||
|
const validResults = finalResults.filter((r) => r.avg !== null || r.p1 !== null)
|
||||||
|
if (validResults.length > 0) {
|
||||||
|
const avgAvg =
|
||||||
|
validResults.reduce((sum, r) => sum + (r.avg || 0), 0) / validResults.length
|
||||||
|
const avgP1 = validResults.reduce((sum, r) => sum + (r.p1 || 0), 0) / validResults.length
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
|
const testDate = now.toISOString()
|
||||||
|
const month = String(now.getMonth() + 1).padStart(2, "0")
|
||||||
|
const day = String(now.getDate()).padStart(2, "0")
|
||||||
|
const hour = String(now.getHours()).padStart(2, "0")
|
||||||
|
const minute = String(now.getMinutes()).padStart(2, "0")
|
||||||
|
const second = String(now.getSeconds()).padStart(2, "0")
|
||||||
|
const testTime = `${month}/${day} ${hour}:${minute}:${second}`
|
||||||
|
|
||||||
|
const averageNote = testNote
|
||||||
|
? `${testNote} [批量${totalTests}次平均]`
|
||||||
|
: `[批量${totalTests}次平均]`
|
||||||
|
|
||||||
|
fpsTest.addResult({
|
||||||
|
id: `${now.getTime()}-${Math.random().toString(36).slice(2, 11)}`,
|
||||||
|
testTime,
|
||||||
|
testDate,
|
||||||
|
mapName: mapConfig?.name || "unknown",
|
||||||
|
mapLabel: mapConfig?.label || "未知地图",
|
||||||
|
avg: avgAvg,
|
||||||
|
p1: avgP1,
|
||||||
|
rawResult: `批量测试${totalTests}次平均值\n平均帧: ${avgAvg.toFixed(
|
||||||
|
1
|
||||||
|
)}\nP1低帧: ${avgP1.toFixed(1)}`,
|
||||||
|
videoSetting: tool.store.state.videoSetting,
|
||||||
|
hardwareInfo: hardwareInfo
|
||||||
|
? {
|
||||||
|
cpu: hardwareInfo.cpus[0]?.brand || null,
|
||||||
|
cpuCount: hardwareInfo.cpu_count || null,
|
||||||
|
os:
|
||||||
|
hardwareInfo.name && hardwareInfo.os_version
|
||||||
|
? `${hardwareInfo.name} ${hardwareInfo.os_version}`
|
||||||
|
: null,
|
||||||
|
memory: hardwareInfo.total_memory
|
||||||
|
? Math.round(hardwareInfo.total_memory / 1024 / 1024 / 1024)
|
||||||
|
: null,
|
||||||
|
gpu: null,
|
||||||
|
monitor: null,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
note: averageNote,
|
||||||
|
})
|
||||||
|
|
||||||
|
addToast({
|
||||||
|
title: `批量测试完成!平均值:avg ${avgAvg.toFixed(1)} FPS, p1 ${avgP1.toFixed(1)} FPS`,
|
||||||
|
color: "success",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setBatchTestProgress(null)
|
||||||
|
setBatchTestResults([])
|
||||||
|
setIsBatchTesting(false) // 批量测试结束,重置状态
|
||||||
|
} else {
|
||||||
|
// 单次测试
|
||||||
|
await runSingleTest(1, 1, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否可以开始测试(批量测试进行中时不能开始新测试)
|
||||||
|
const canStartTest = (!tool.state.autoCloseGame ? !isGameRunning : true) && !isBatchTesting
|
||||||
|
|
||||||
// 格式化视频设置摘要
|
// 格式化视频设置摘要
|
||||||
const formatVideoSettingSummary = (
|
const formatVideoSettingSummary = (
|
||||||
@@ -763,6 +1001,25 @@ export function FpsTest() {
|
|||||||
</CardIcon>
|
</CardIcon>
|
||||||
<CardTool className="justify-end">
|
<CardTool className="justify-end">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
{batchTestProgress && (
|
||||||
|
<div className="flex flex-col gap-1.5 items-center justify-center">
|
||||||
|
<div className="relative ">
|
||||||
|
<CircularProgress
|
||||||
|
aria-label="批量测试进度"
|
||||||
|
value={(batchTestProgress.current / batchTestProgress.total) * 100}
|
||||||
|
color="primary"
|
||||||
|
size="sm"
|
||||||
|
showValueLabel={false}
|
||||||
|
classNames={{
|
||||||
|
svg: " ",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center text-xs font-medium">
|
||||||
|
{batchTestProgress.current}/{batchTestProgress.total}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{showResultsTable && (
|
{showResultsTable && (
|
||||||
<Button size="sm" variant="flat" onPress={handleExportCSV} className="font-medium">
|
<Button size="sm" variant="flat" onPress={handleExportCSV} className="font-medium">
|
||||||
<DownloadOne size={14} />
|
<DownloadOne size={14} />
|
||||||
@@ -950,6 +1207,29 @@ export function FpsTest() {
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs text-default-500">批量测试</label>
|
||||||
|
<Select
|
||||||
|
size="md"
|
||||||
|
selectedKeys={[String(batchTestCount)]}
|
||||||
|
onSelectionChange={(keys) => {
|
||||||
|
const value = Array.from(keys)[0]
|
||||||
|
if (value && !isMonitoring) {
|
||||||
|
setBatchTestCount(Number(value))
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
isDisabled={isMonitoring}
|
||||||
|
className="w-24"
|
||||||
|
aria-label="批量测试次数"
|
||||||
|
>
|
||||||
|
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((count) => (
|
||||||
|
<SelectItem
|
||||||
|
key={String(count)}
|
||||||
|
title={count === 1 ? "单次" : `${count}次`}
|
||||||
|
></SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
<div className="flex flex-col gap-1.5 flex-1">
|
<div className="flex flex-col gap-1.5 flex-1">
|
||||||
<label className="text-xs text-default-500">备注</label>
|
<label className="text-xs text-default-500">备注</label>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -1112,12 +1392,6 @@ export function FpsTest() {
|
|||||||
关闭游戏
|
关闭游戏
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{isMonitoring && (
|
|
||||||
<Chip size="sm" color="primary" variant="flat">
|
|
||||||
正在监听中...
|
|
||||||
</Chip>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="flat"
|
variant="flat"
|
||||||
@@ -1130,6 +1404,12 @@ export function FpsTest() {
|
|||||||
手动读取结果
|
手动读取结果
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{isMonitoring && (
|
||||||
|
<Chip size="lg" color="primary" variant="flat" className="text-xs">
|
||||||
|
正在监听中...
|
||||||
|
</Chip>
|
||||||
|
)}
|
||||||
|
|
||||||
{testResult &&
|
{testResult &&
|
||||||
testTimestamp &&
|
testTimestamp &&
|
||||||
(() => {
|
(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user