disable all dev logs

This commit is contained in:
2025-11-08 18:21:35 +08:00
parent 6103164e37
commit c50fedd305
4 changed files with 111 additions and 147 deletions

2
next-env.d.ts vendored
View File

@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -1,19 +1,19 @@
use crate::steam;
use crate::tool::*;
use crate::tool::updater::{check_update, download_update, install_update, UpdateInfo};
use crate::tool::*;
use crate::vdf::preset;
use crate::vdf::preset::VideoConfig;
use crate::wrap_err;
use anyhow::Result;
use std::fs::File;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, OnceLock};
use tauri::path::BaseDirectory;
use tauri::Manager;
use serde::{Deserialize, Serialize};
// use tauri_plugin_shell::ShellExt;
@@ -23,7 +23,9 @@ use serde::{Deserialize, Serialize};
static DOWNLOAD_CANCELLED: OnceLock<Arc<AtomicBool>> = OnceLock::new();
fn get_download_cancelled() -> Arc<AtomicBool> {
DOWNLOAD_CANCELLED.get_or_init(|| Arc::new(AtomicBool::new(false))).clone()
DOWNLOAD_CANCELLED
.get_or_init(|| Arc::new(AtomicBool::new(false)))
.clone()
}
#[tauri::command]
@@ -127,7 +129,9 @@ pub fn start_watch_cs2_video(
steam_dir: String,
steam_id32: u32,
) -> Result<(), String> {
wrap_err!(steam::watch::start_watch_cs2_video(app, steam_dir, steam_id32))
wrap_err!(steam::watch::start_watch_cs2_video(
app, steam_dir, steam_id32
))
}
#[tauri::command]
@@ -169,16 +173,16 @@ pub fn check_path(path: &str) -> Result<bool, String> {
#[tauri::command]
pub fn check_steam_dir_valid(steam_dir: &str) -> Result<bool, String> {
use std::path::Path;
let path = Path::new(steam_dir);
if !path.exists() {
return Ok(false);
}
// 检查是否存在 steam.exe 或 config 目录(至少有一个即可)
let steam_exe = path.join("steam.exe");
let config_dir = path.join("config");
Ok(steam_exe.exists() || config_dir.exists())
}
@@ -201,14 +205,14 @@ pub async fn analyze_replay(app: tauri::AppHandle, path: &str) -> Result<String,
fs::create_dir_all(&config_dir).expect("无法创建 metadata 文件夹");
}
// 提取文件名部分
let file_name = std::path::Path::new(path)
.file_name()
.and_then(|name| name.to_str())
.unwrap_or("default_filename");
// 提取文件名部分
let file_name = std::path::Path::new(path)
.file_name()
.and_then(|name| name.to_str())
.unwrap_or("default_filename");
// 拼接输出文件路径
let output_path = config_dir.join(format!("{}.json", file_name));
// 拼接输出文件路径
let output_path = config_dir.join(format!("{}.json", file_name));
// 确保输出文件存在,如果不存在则创建空文件
if !output_path.exists() {
@@ -265,21 +269,21 @@ pub fn get_console_log_path(cs_path: &str) -> Result<String, String> {
#[tauri::command]
pub fn read_vprof_report(console_log_path: &str) -> Result<String, String> {
let path = Path::new(console_log_path);
if !path.exists() {
return Err("console.log 文件不存在".to_string());
}
let file = File::open(path).map_err(|e| format!("无法打开文件: {}", e))?;
let reader = BufReader::new(file);
let mut vprof_lines = Vec::new();
let mut in_vprof_section = false;
let mut empty_line_count = 0;
for line_result in reader.lines() {
let line = line_result.map_err(|e| format!("读取行错误: {}", e))?;
// 检测 [VProf] 标记
if line.contains("[VProf]") {
in_vprof_section = true;
@@ -300,11 +304,11 @@ pub fn read_vprof_report(console_log_path: &str) -> Result<String, String> {
}
}
}
if vprof_lines.is_empty() {
return Err("未找到 [VProf] 报告".to_string());
}
Ok(vprof_lines.join("\n"))
}
@@ -321,34 +325,22 @@ pub async fn check_app_update(
let current_version = app.package_info().version.to_string();
let use_mirror = use_mirror.unwrap_or(false);
let include_prerelease = include_prerelease.unwrap_or(false);
// println!("[检查更新命令] 当前应用版本: {}", current_version);
// println!("[检查更新命令] 使用镜像: {}", use_mirror);
// println!("[检查更新命令] 包含预发布版本: {}", include_prerelease);
// if let Some(ref ep) = endpoint {
// println!("[检查更新命令] 自定义端点: {}", ep);
// }
// 从环境变量获取 GitHub 仓库信息,如果没有则使用默认值
const DEFAULT_GITHUB_REPO: &str = "plsgo/cstb";
let github_repo_str = std::env::var("GITHUB_REPO").ok();
let github_repo = github_repo_str.as_deref().unwrap_or(DEFAULT_GITHUB_REPO);
// println!("[检查更新命令] GitHub 仓库: {}", github_repo);
let result = wrap_err!(check_update(
endpoint.as_deref(),
&current_version,
use_mirror,
Some(github_repo),
include_prerelease
).await)?;
// if result.is_some() {
// println!("[检查更新命令] ✓ 返回更新信息");
// } else {
// println!("[检查更新命令] ✗ 无更新可用");
// }
let result = wrap_err!(
check_update(
endpoint.as_deref(),
&current_version,
use_mirror,
Some(github_repo),
include_prerelease
)
.await
)?;
Ok(result)
}
@@ -361,7 +353,7 @@ pub async fn download_app_update(
// 重置取消标志
let cancelled = get_download_cancelled();
cancelled.store(false, Ordering::Relaxed);
let path = wrap_err!(download_update(&app, &download_url, cancelled).await)?;
Ok(path.to_string_lossy().to_string())
}
@@ -385,7 +377,7 @@ pub fn install_app_update(installer_path: String) -> Result<(), String> {
#[cfg(target_os = "windows")]
pub async fn get_computer_info() -> Result<serde_json::Value, String> {
use tokio::process::Command;
// 异步执行 PowerShell 命令获取计算机信息并转换为 JSON
let output = Command::new("powershell")
.args(&[
@@ -396,24 +388,24 @@ pub async fn get_computer_info() -> Result<serde_json::Value, String> {
.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));
}
// 处理 PowerShell 输出,移除 BOM 和空白字符
let stdout = String::from_utf8_lossy(&output.stdout);
let cleaned = stdout.trim().trim_start_matches('\u{feff}'); // 移除 BOM
// 如果输出为空,返回空对象
if cleaned.is_empty() {
return Ok(serde_json::json!({}));
}
let mut json: serde_json::Value = serde_json::from_str(cleaned)
.map_err(|e| format!("解析 JSON 失败: {},原始输出: {}", e, cleaned))?;
// 对于 Windows 11优先使用 OSDisplayVersion 获取版本代码(如 25H2
// 如果 OSDisplayVersion 存在且包含版本代码,提取它
if let Some(os_display_version) = json.get("OSDisplayVersion").and_then(|v| v.as_str()) {
@@ -428,7 +420,7 @@ pub async fn get_computer_info() -> Result<serde_json::Value, String> {
}
}
}
// 如果没有从 OSDisplayVersion 获取到版本代码,尝试从注册表获取 ReleaseId
if !json.get("ReleaseId").and_then(|v| v.as_str()).is_some() {
let release_id_output = Command::new("powershell")
@@ -439,17 +431,19 @@ pub async fn get_computer_info() -> Result<serde_json::Value, String> {
])
.output()
.await;
if let Ok(release_output) = release_id_output {
if release_output.status.success() {
let release_str = String::from_utf8_lossy(&release_output.stdout).trim().to_string();
let release_str = String::from_utf8_lossy(&release_output.stdout)
.trim()
.to_string();
if !release_str.is_empty() {
json["ReleaseId"] = serde_json::Value::String(release_str);
}
}
}
}
Ok(json)
}
@@ -488,12 +482,12 @@ fn format_bytes(bytes: u64) -> String {
#[tauri::command]
pub fn get_gpu_info() -> Result<Option<GpuInfo>, String> {
use gfxinfo::active_gpu;
match active_gpu() {
Ok(gpu) => {
let info = gpu.info();
let temp = info.temperature() as f64 / 1000.0;
Ok(Some(GpuInfo {
vendor: gpu.vendor().to_string(),
model: gpu.model().to_string(),
@@ -558,7 +552,7 @@ pub struct MotherboardInfo {
#[cfg(target_os = "windows")]
pub async fn get_memory_info() -> Result<Vec<MemoryInfo>, String> {
use tokio::process::Command;
// 执行 PowerShell 命令获取内存信息
let output = Command::new("powershell")
.args(&[
@@ -569,25 +563,25 @@ pub async fn get_memory_info() -> Result<Vec<MemoryInfo>, String> {
.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 {
@@ -597,31 +591,30 @@ pub async fn get_memory_info() -> Result<Vec<MemoryInfo>, String> {
// 如果是单个对象
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")
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")
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);
let default_speed = json.get("Speed").and_then(|v| v.as_u64()).map(|v| v as u32);
MemoryInfo {
capacity,
manufacturer,
@@ -642,7 +635,7 @@ pub async fn get_memory_info() -> Result<Vec<MemoryInfo>, String> {
#[cfg(target_os = "windows")]
pub async fn get_monitor_info() -> Result<Vec<MonitorInfo>, String> {
use tokio::process::Command;
// 执行 PowerShell 命令获取显示器信息
let output = Command::new("powershell")
.args(&[
@@ -653,24 +646,24 @@ pub async fn get_monitor_info() -> Result<Vec<MonitorInfo>, String> {
.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));
@@ -678,7 +671,7 @@ pub async fn get_monitor_info() -> Result<Vec<MonitorInfo>, String> {
} else {
monitor_list.push(parse_monitor_info(&json));
}
// 尝试获取刷新率和分辨率信息
let _display_output = Command::new("powershell")
.args(&[
@@ -688,7 +681,7 @@ pub async fn get_monitor_info() -> Result<Vec<MonitorInfo>, String> {
])
.output()
.await;
// 获取刷新率信息
let _refresh_output = Command::new("powershell")
.args(&[
@@ -698,7 +691,7 @@ pub async fn get_monitor_info() -> Result<Vec<MonitorInfo>, String> {
])
.output()
.await;
// 获取当前显示器的分辨率和刷新率
let current_display_output = Command::new("powershell")
.args(&[
@@ -708,12 +701,15 @@ pub async fn get_monitor_info() -> Result<Vec<MonitorInfo>, String> {
])
.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();
let display_str = display_str
.trim()
.trim_start_matches('\u{feff}')
.to_string();
if let Ok(display_json) = serde_json::from_str::<serde_json::Value>(&display_str) {
if let Some(displays) = display_json.as_array() {
for (i, display) in displays.iter().enumerate() {
@@ -739,22 +735,24 @@ pub async fn get_monitor_info() -> Result<Vec<MonitorInfo>, String> {
}
}
}
Ok(monitor_list)
}
/// 解析显示器信息
fn parse_monitor_info(json: &serde_json::Value) -> MonitorInfo {
let manufacturer = json.get("Manufacturer")
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")
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)),
@@ -762,7 +760,7 @@ fn parse_monitor_info(json: &serde_json::Value) -> MonitorInfo {
(None, Some(model_name)) => Some(model_name.clone()),
(None, None) => None,
};
MonitorInfo {
manufacturer,
model,
@@ -785,7 +783,7 @@ pub async fn get_monitor_info() -> Result<Vec<MonitorInfo>, String> {
#[cfg(target_os = "windows")]
pub async fn get_motherboard_info() -> Result<MotherboardInfo, String> {
use tokio::process::Command;
// 执行 PowerShell 命令获取主板信息
let output = Command::new("powershell")
.args(&[
@@ -796,15 +794,15 @@ pub async fn get_motherboard_info() -> Result<MotherboardInfo, String> {
.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,
@@ -812,25 +810,28 @@ pub async fn get_motherboard_info() -> Result<MotherboardInfo, String> {
version: None,
});
}
let json: serde_json::Value = serde_json::from_str(cleaned)
.map_err(|e| format!("解析 JSON 失败: {},原始输出: {}", e, cleaned))?;
// 分别获取制造商和型号
let manufacturer = json.get("Manufacturer")
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")
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")
version: json
.get("Version")
.and_then(|v| v.as_str())
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty()),
@@ -846,4 +847,4 @@ pub async fn get_motherboard_info() -> Result<MotherboardInfo, String> {
model: None,
version: None,
})
}
}

View File

@@ -61,9 +61,6 @@ pub async fn check_update(
github_repo: Option<&str>,
include_prerelease: bool,
) -> Result<Option<UpdateInfo>> {
println!("[更新检查] 开始检查更新...");
println!("[更新检查] 当前版本: {}", current_version);
println!("[更新检查] 包含预发布版本: {}", include_prerelease);
// 确定使用的 API 端点
let api_url = if let Some(custom_endpoint) = endpoint {
@@ -79,7 +76,6 @@ pub async fn check_update(
}
};
println!("[更新检查] API URL: {}", api_url);
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(10))
@@ -89,7 +85,6 @@ pub async fn check_update(
let response = client.get(&api_url).send().await?;
if !response.status().is_success() {
println!("[更新检查] ✗ API 请求失败HTTP 状态码: {}", response.status());
return Err(anyhow::anyhow!("API 请求失败HTTP 状态码: {}", response.status()));
}
@@ -100,19 +95,13 @@ pub async fn check_update(
// 尝试解析为自定义更新服务器格式
let update_info = if let Ok(custom_resp) = serde_json::from_str::<CustomUpdateApiResponse>(&response_text) {
println!("[更新检查] 检测到自定义更新服务器格式");
// 提取版本号(去掉 'v' 前缀)
let version = custom_resp.version.trim_start_matches('v').to_string();
println!("[更新检查] 远程版本: {}", version);
// 版本比较
let comparison = compare_version(&version, current_version);
println!("[更新检查] 版本比较结果: {} (1=有新版本, 0=相同, -1=当前更新)", comparison);
if comparison > 0 {
println!("[更新检查] ✓ 发现新版本: {}", version);
// 获取下载链接
// 优先使用平台特定的链接
let download_url = if let Some(ref platforms) = custom_resp.platforms {
@@ -139,33 +128,26 @@ pub async fn check_update(
custom_resp.download_url.clone()
};
println!("[更新检查] 下载链接: {}", download_url);
Some(UpdateInfo {
version,
notes: custom_resp.notes,
download_url,
})
} else {
println!("[更新检查] ✗ 已是最新版本");
None
}
} else {
// 尝试解析为 gh-info API 格式
println!("[更新检查] 尝试解析为 gh-info API 格式");
let api_resp: GhInfoApiResponse = serde_json::from_str(&response_text)
.context("解析更新 API 响应失败,既不是自定义格式也不是 gh-info 格式")?;
// 提取版本号(去掉 'v' 前缀)
let version = api_resp.latest_version.trim_start_matches('v').to_string();
println!("[更新检查] 远程版本: {}", version);
// 版本比较
let comparison = compare_version(&version, current_version);
println!("[更新检查] 版本比较结果: {} (1=有新版本, 0=相同, -1=当前更新)", comparison);
if comparison > 0 {
println!("[更新检查] ✓ 发现新版本: {}", version);
// 从 attachments 中获取下载链接
// 支持两种格式:
@@ -174,15 +156,12 @@ pub async fn check_update(
let download_url = extract_download_url(&api_resp.attachments)
.ok_or_else(|| anyhow::anyhow!("未找到可下载的安装包"))?;
println!("[更新检查] 下载链接: {}", download_url);
Some(UpdateInfo {
version,
notes: api_resp.changelog,
download_url,
})
} else {
println!("[更新检查] ✗ 已是最新版本");
None
}
};
@@ -197,7 +176,6 @@ pub async fn check_update(
fn extract_download_url(attachments: &serde_json::Value) -> Option<String> {
// 尝试解析为字符串数组格式: ["URL1", "URL2", ...]
if let Ok(urls) = serde_json::from_value::<Vec<String>>(attachments.clone()) {
println!("[更新检查] 检测到字符串数组格式的 attachments");
// 优先选择 .exe 或 .msi 文件
if let Some(url) = urls.iter().find(|url| {
url.ends_with(".exe") || url.ends_with(".msi")
@@ -210,7 +188,6 @@ fn extract_download_url(attachments: &serde_json::Value) -> Option<String> {
// 尝试解析为嵌套数组格式: [["文件名", "URL"], ...]
if let Ok(nested) = serde_json::from_value::<Vec<Vec<String>>>(attachments.clone()) {
println!("[更新检查] 检测到嵌套数组格式的 attachments");
// 优先选择 .exe 或 .msi 文件
if let Some(url) = nested.iter().find_map(|attachment| {
if attachment.len() >= 2 {
@@ -240,27 +217,22 @@ fn extract_download_url(attachments: &serde_json::Value) -> Option<String> {
/// 改进的版本比较函数支持预发布版本beta.5, beta.6等)
fn compare_version(new: &str, current: &str) -> i32 {
println!("[版本比较] 比较版本: '{}' vs '{}'", new, current);
// 解析版本号:支持格式如 "0.0.6-beta.5", "beta.6", "0.0.6" 等
let (new_base, new_pre) = parse_version(new);
let (current_base, current_pre) = parse_version(current);
println!("[版本比较] 新版本 - 基础部分: {:?}, 预发布部分: {:?}", new_base, new_pre);
println!("[版本比较] 当前版本 - 基础部分: {:?}, 预发布部分: {:?}", current_base, current_pre);
// 先比较基础版本号(数字部分)
let base_comparison = compare_version_parts(&new_base, &current_base);
if base_comparison != 0 {
println!("[版本比较] 基础版本不同,返回: {}", base_comparison);
return base_comparison;
}
// 如果基础版本相同(或都为空),比较预发布标识符
// 如果基础版本都为空,说明是纯预发布版本(如 beta.5 vs beta.6
let pre_comparison = compare_prerelease(&new_pre, &current_pre);
println!("[版本比较] 预发布版本比较结果: {}", pre_comparison);
// 如果基础版本都为空且预发布比较结果为0说明版本完全相同
if new_base.is_empty() && current_base.is_empty() && pre_comparison == 0 {
@@ -371,8 +343,6 @@ pub async fn download_update(
download_url: &str,
cancelled: Arc<AtomicBool>,
) -> Result<PathBuf> {
println!("[下载更新] 开始下载,下载链接: {}", download_url);
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(300))
.build()?;
@@ -405,10 +375,6 @@ pub async fn download_update(
let file_path = cache_dir.join(filename);
println!("[下载更新] 文件名: {}", filename);
println!("[下载更新] 文件大小: {} bytes ({:.2} MB)", total_size, total_size as f64 / 1024.0 / 1024.0);
println!("[下载更新] 保存路径: {}", file_path.display());
// 下载文件
let mut file = fs::File::create(&file_path)?;
let mut stream = response.bytes_stream();
@@ -443,9 +409,6 @@ pub async fn download_update(
// 发送完成事件
let _ = app.emit("update-download-progress", 100u64);
println!("[下载更新] ✓ 下载完成,文件已保存到: {}", file_path.display());
Ok(file_path)
}

View File

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