diff --git a/Readme.md b/Readme.md index e8c1b66..c0c1b51 100644 --- a/Readme.md +++ b/Readme.md @@ -16,6 +16,10 @@ Tauri relies on the VC runtime library and WebView runtime. The latest version o # History +## 0.1.4 + +English Translation. + ## 0.1.3 Add a historical record function for laptop battery usage to track changes in battery health, charge/discharge status, charge/discharge power, and battery wear; while also updating the monitoring page. diff --git a/crates/battery/src/battery_status.rs b/crates/battery/src/battery_status.rs index 632636e..adbb07a 100644 --- a/crates/battery/src/battery_status.rs +++ b/crates/battery/src/battery_status.rs @@ -51,11 +51,11 @@ impl std::fmt::Display for State { } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] struct Identifier { - //供应商 + // vendor pub vendor: Option, - //模式 + // model pub model: Option, - //序列号 + // serial number pub serial_number: Option, } impl Default for Identifier { @@ -69,37 +69,37 @@ impl Default for Identifier { } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Status { - // 基于上次更新,电池信息是否已经更改 + // Whether battery info changed since last update pub state_changed: bool, - //额外的标识信息 + // additional identifier info identifier: Identifier, - //序号 + // index index: u16, - //时间戳 + // timestamp pub timestamp: i64, - //状态 + // state pub state: State, - //温度 + // temperature pub temperature: Option, - //循环次数 + // cycle count pub cycle_count: Option, - //电量百分比 + // percentage pub percentage: f32, - //充放电瓦数 + // energy rate (charge/discharge watts) pub energy_rate: f32, - //电池电压 + // voltage pub voltage: f32, - //电池健康状态 + // state of health pub state_of_health: f32, - //设计容量 + // design capacity pub design_capacity: f32, - //满充容量 + // full charge capacity pub full_capacity: f32, - //当前容量 + // current capacity pub capacity: f32, - //预估放电时长 + // estimated seconds to empty pub time_to_empty_secs: u64, - //预估充满电时长 + // estimated seconds to full pub time_to_full_secs: u64, } impl<'a> Default for Status { diff --git a/crates/persis/.vscode/launch.json b/crates/persis/.vscode/launch.json index 3d5fe8c..e12ed6f 100644 --- a/crates/persis/.vscode/launch.json +++ b/crates/persis/.vscode/launch.json @@ -1,7 +1,7 @@ { - // 使用 IntelliSense 了解相关属性。 - // 悬停以查看现有属性的描述。 - // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + // Use IntelliSense to learn about related properties. + // Hover to view descriptions of existing properties. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { diff --git a/crates/persis/migration/src/m20250311_150000_init.rs b/crates/persis/migration/src/m20250311_150000_init.rs index ff5d39f..ea3d320 100644 --- a/crates/persis/migration/src/m20250311_150000_init.rs +++ b/crates/persis/migration/src/m20250311_150000_init.rs @@ -46,7 +46,7 @@ impl MigrationTrait for Migration { .if_not_exists() .col(big_integer(BatteryStateHistory::Timestamp).primary_key()) .col(string(BatteryStateHistory::State)) - .col(ColumnDef::new(BatteryStateHistory::Prev).string().null())//这么写才能定义null + .col(ColumnDef::new(BatteryStateHistory::Prev).string().null())// Use .null() to define a nullable column .col(ColumnDef::new(BatteryStateHistory::EndAt).big_integer().null()) .col(float(BatteryStateHistory::Capacity)) .col(float(BatteryStateHistory::FullCapacity)) diff --git a/crates/persis/src/down_sample.rs b/crates/persis/src/down_sample.rs index f1cf9df..d32abea 100644 --- a/crates/persis/src/down_sample.rs +++ b/crates/persis/src/down_sample.rs @@ -16,7 +16,7 @@ impl Default for DownSampleParams { fn default() -> Self { let end_time = Utc::now().timestamp(); Self { - time_formater: "%Y-%m-%dT%H:%M:%SZ".to_string(), //ISO 8601格式 + time_formater: "%Y-%m-%dT%H:%M:%SZ".to_string(), // ISO 8601 format table_name: "memory_battery_status".to_string(), time_field: "timestamp".to_string(), order_field: "id".to_string(), @@ -54,7 +54,7 @@ UniqueBatteryStatus AS ( SELECT {time_field}, state, - ROW_NUMBER() OVER (PARTITION BY {time_field} ORDER BY {order_field} DESC) AS rn --排序字段用于在分组内的数据排序 + ROW_NUMBER() OVER (PARTITION BY {time_field} ORDER BY {order_field} DESC) AS rn -- Ordering field used to sort data within groups FROM {table_name} WHERE {time_field}>{start_time} and {time_field}<={end_time} diff --git a/crates/persis/src/lib.rs b/crates/persis/src/lib.rs index 3ee8963..1a1dbfa 100644 --- a/crates/persis/src/lib.rs +++ b/crates/persis/src/lib.rs @@ -57,7 +57,7 @@ mod tests { battery.last(); let system = system::Status::build().unwrap(); let res = store.insert(&battery, &system, |_| async {}).await; - //在系统进入休眠或睡眠瞬间,insert会Err,需要处理 + // During system suspend/sleep, insert may Err; handle this case match res { Ok((_vec,inner)) => { inner.map(|x| { diff --git a/crates/persis/src/store.rs b/crates/persis/src/store.rs index 0ed3fb7..d5c593c 100644 --- a/crates/persis/src/store.rs +++ b/crates/persis/src/store.rs @@ -79,7 +79,7 @@ impl BatteryStore { .to_string() .contains("no such table: memory_battery_status") { - //时间长了会出现这个错误,不理解为什么,故丢弃数据,重置这个数据库连接 + // This error can occur after a long uptime; unclear why. Discard the data and reset the in-memory DB connection self.mem_db = Database::connect(String::from("sqlite::memory:")).await?; Migrator::up(&self.mem_db, None).await?; model = status.insert(&self.mem_db).await; diff --git a/crates/store/src/battery.rs b/crates/store/src/battery.rs index bd810eb..efb3ee8 100644 --- a/crates/store/src/battery.rs +++ b/crates/store/src/battery.rs @@ -52,25 +52,25 @@ impl<'de> Deserialize<'de> for SerializableState { #[derive(Clone, Serialize, Deserialize, Debug)] pub struct BatteryInfo { pub state_changed: bool, - //时间戳 + // timestamp pub timestamp: i64, - //状态 + // state pub state: SerializableState, - //电量百分比 + // percentage pub percentage: f32, - //充放电瓦数 + // energy rate (W) pub energy_rate: f32, - //电池电压 + // voltage pub voltage: f32, - //电池健康状态 + // state of health pub state_of_health: f32, - //设计容量 + // design capacity pub design_capacity: f32, - //满充容量 + // full capacity pub full_capacity: f32, - //当前容量 + // current capacity pub capacity: f32, - //cpu使用率 + // CPU usage pub cpu_load: f32, pub serial_number: String, @@ -182,7 +182,7 @@ impl Battery { .to_string(); let mut record = BatteryInfo::default(); - //查询电池数量 + // query number of batteries let batteries = bms.batteries().unwrap(); for battery in batteries { let battery = battery.unwrap(); diff --git a/crates/store/src/processor.rs b/crates/store/src/processor.rs index 3dd3336..7f1a8ea 100644 --- a/crates/store/src/processor.rs +++ b/crates/store/src/processor.rs @@ -129,11 +129,11 @@ impl DataProcessor { .clone() .lazy() .with_columns(vec![ - // 创建一列标识当前行的状态变化 - col("state").shift(lit(1)).alias("prev_state"), // 获取上一行的状态 - ]) - .filter( - // 在每个时间窗口内,检查状态是否变化 + // Create a column to identify state changes in the current row + col("state").shift(lit(1)).alias("prev_state"), // get the previous row's state + ]), + .filter( + // Within each time window, check if state has changed col("state") .neq(col("prev_state")) .or(col("prev_state").is_null()), diff --git a/crates/system/src/system_status.rs b/crates/system/src/system_status.rs index baedfe8..3b3eae2 100644 --- a/crates/system/src/system_status.rs +++ b/crates/system/src/system_status.rs @@ -23,19 +23,19 @@ impl Default for Identifier { #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Status { - //额外的标识信息 + // additional identifier info identifier: Identifier, - //时间戳 + // timestamp pub timestamp: i64, - //是否支持cpu功耗限制 + // whether CPU power limiting is supported pub support_power_set: bool, - //cpu占用 + // CPU load pub cpuload: f32, - //空闲内存 + // free memory pub memfree: u32, - //屏幕亮度 + // screen brightness //pub screen_brightness: f32, - //屏幕标识 + // screen instance identifier //pub screen_instance: String, } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index c1c15dc..8d089af 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "BatteryMaster" -version = "0.1.3" +version = "0.1.4" dependencies = [ "battery 0.1.0", "chrono", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8759e71..e5e7dc5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "BatteryMaster" -version = "0.1.3" +version = "0.1.4" description = "BatteryMaster" authors = ["topabomb"] edition = "2021" diff --git a/src-tauri/WinRing0x64.dll b/src-tauri/WinRing0x64.dll new file mode 100644 index 0000000..4a48c7a Binary files /dev/null and b/src-tauri/WinRing0x64.dll differ diff --git a/src-tauri/WinRing0x64.sys b/src-tauri/WinRing0x64.sys new file mode 100644 index 0000000..197c255 Binary files /dev/null and b/src-tauri/WinRing0x64.sys differ diff --git a/src-tauri/config.json b/src-tauri/config.json new file mode 100644 index 0000000..b1c0b8f --- /dev/null +++ b/src-tauri/config.json @@ -0,0 +1,7 @@ +{ + "auto_start": false, + "start_minimize": false, + "ui_update": 2, + "service_update": 1, + "record_battery_history": true +} diff --git a/src-tauri/history.db b/src-tauri/history.db new file mode 100644 index 0000000..e69de29 diff --git a/src-tauri/inpoutx64.dll b/src-tauri/inpoutx64.dll new file mode 100644 index 0000000..82c343f Binary files /dev/null and b/src-tauri/inpoutx64.dll differ diff --git a/src-tauri/libryzenadj.dll b/src-tauri/libryzenadj.dll new file mode 100644 index 0000000..8a22ecc Binary files /dev/null and b/src-tauri/libryzenadj.dll differ diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index 2d52a2e..c8786f8 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -16,14 +16,14 @@ fn check_if_dev() -> bool { false } -// 定义配置结构体 +// Define configuration struct #[derive(Serialize, Deserialize, Clone, Copy)] pub struct Config { - pub auto_start: bool, // 系统启动时自动启动 - pub start_minimize: bool, //启动时最小化 - pub ui_update: u8, // UI标更新时间 - pub service_update: u8, // 监控服务更新时间 - pub record_battery_history: bool, // 是否记录电池活动历史 + pub auto_start: bool, // Start with the system + pub start_minimize: bool, // Start minimized + pub ui_update: u8, // UI update interval + pub service_update: u8, // Monitoring service update interval + pub record_battery_history: bool, // Whether to record battery activity history } impl Default for Config { @@ -38,7 +38,7 @@ impl Default for Config { } } -// 获取当前执行目录 +// Get current executable directory pub fn get_exe_directory() -> PathBuf { env::current_exe() .expect("Failed to get current executable path") @@ -47,22 +47,22 @@ pub fn get_exe_directory() -> PathBuf { .to_path_buf() } -// 获取配置文件路径(基于执行文件目录) +// Get config file path (based on executable directory) pub fn get_config_file_path() -> PathBuf { get_exe_directory().join("config.json") } -// 读取配置文件并返回配置 +// Read configuration file and return Config pub fn load_config() -> Result> { let config_path = get_config_file_path(); if Path::new(&config_path).exists() { - // 文件存在,读取并解析配置 + // File exists: read and parse configuration let mut file = File::open(config_path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; - // 解析 JSON 配置 + // Parse JSON configuration let config: Config = serde_json::from_str(&contents)?; Ok(config) } else { @@ -72,18 +72,39 @@ pub fn load_config() -> Result> { } } -// 保存配置到文件 +// Save configuration to file pub fn save_config(config: &Config) -> Result<(), Box> { let config_path = get_config_file_path(); let mut file = File::create(config_path)?; - // 将配置序列化为 JSON + // Serialize configuration to JSON let config_json = serde_json::to_string_pretty(config)?; file.write_all(config_json.as_bytes())?; Ok(()) } +// Ensure runtime files exist: history DB and logs file. +pub fn ensure_runtime_files() -> Result<(), Box> { + let exe_dir = get_exe_directory(); + // Ensure directory exists (should normally exist) + if !exe_dir.exists() { + std::fs::create_dir_all(&exe_dir)?; + } + + let history_path = exe_dir.join("history.db"); + if !history_path.exists() { + let _ = File::create(&history_path)?; + } + + let logs_path = exe_dir.join("logs.log"); + if !logs_path.exists() { + let _ = File::create(&logs_path)?; + } + + Ok(()) +} + pub fn set_autostart(app_handle: &tauri::AppHandle, val: bool) { let autostart_manager = app_handle.autolaunch(); if !check_if_dev() { diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 9fae233..58d72be 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -28,7 +28,7 @@ pub fn run() { } else { "Unknown panic payload" }; - // 提取位置信息 + // extract location information let location = info .location() .map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column())) @@ -39,7 +39,7 @@ pub fn run() { message, location ); - std::process::exit(1); // 可以替换为你希望的退出代码 + std::process::exit(1); // replace with desired exit code })); tauri::Builder::default() .plugin(tauri_plugin_clipboard_manager::init()) @@ -62,8 +62,8 @@ pub fn run() { tokio::spawn({ let state = Arc::clone(&state); async move { - let mut state = state.lock().await; // 异步地获取 Mutex 锁 - state.is_min_tray = false; // 修改状态 + let mut state = state.lock().await; // acquire Mutex lock asynchronously + state.is_min_tray = false; // modify state } }); })) @@ -74,6 +74,8 @@ pub fn run() { .setup(move |app| { log!(Level::Info, "args ={:?}", args); let config = config::load_config().expect("load_config err."); + // Ensure runtime files exist (config.json is created by load_config()) + config::ensure_runtime_files().expect("ensure runtime files err."); let session = session::SessionState::new(config); app.manage(Arc::new(Mutex::new(session))); if is_adminstart { @@ -92,7 +94,7 @@ pub fn run() { let (tx, rx) = oneshot::channel::<()>(); //service update. tokio::spawn(async move { - let mut tx = Some(tx); // 将 tx 包装成 Option,以便在第一次发送后取出 + let mut tx = Some(tx); // wrap tx into Option so it can be taken after first send loop { let mut secs = 1; { @@ -159,7 +161,7 @@ pub fn run() { let res = manager .insert_battery(&battery, &system, |_| async { log!(Level::Warn, "new battery history "); - /*绝对不能在lock中再次lock,会导致死锁 + /* Never lock again inside a lock — this would cause deadlock let state = handler1.state::>>(); let state = state.lock().await; @@ -276,10 +278,10 @@ pub fn run() { let state: tauri::State<'_, Arc>> = handler.state::>>(); tokio::spawn({ - let state = Arc::clone(&state); // 克隆 Arc 以便传递给异步任务 + let state = Arc::clone(&state); // clone Arc to pass to async task async move { - let mut state = state.lock().await; // 异步地获取 Mutex 锁 - state.is_min_tray = true; // 修改状态 + let mut state = state.lock().await; // acquire Mutex lock asynchronously + state.is_min_tray = true; // modify state } }); } diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 622fae2..fa4dffd 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -20,16 +20,16 @@ fn generate_tray_icon( let height = 64; let mut img = ImageBuffer::new(width, height); - // 设置透明背景 + // set transparent background for pixel in img.pixels_mut() { *pixel = Rgba([0, 0, 0, 0]); } - // 加载字体 + // load font let font_data = include_bytes!("../assets/fonts/Roboto-Bold.ttf"); let font = Font::try_from_bytes(font_data as &[u8]).unwrap(); - // 配置字体大小 + // configure font size let scale = if number >= 100 { Scale { x: 38.0, y: 38.0 } } else { @@ -37,7 +37,7 @@ fn generate_tray_icon( }; let text = format!("{}", number); - // 计算文本位置 + // calculate text position let width_in_pixels = font .layout(&text, scale, rusttype::point(0.0, 0.0)) .map(|g| g.pixel_bounding_box().unwrap().width()) @@ -67,7 +67,7 @@ fn generate_tray_icon( } } - // 将图像转换为 PNG 字节流 + // convert image to PNG bytes let mut buffer = Vec::new(); image::codecs::png::PngEncoder::new(&mut buffer).write_image( &img, @@ -148,11 +148,11 @@ pub fn build(app: &App, id: &str) { } "admin" => { let state = app.state::>>(); - // 将 state 转移到异步任务中 + // move state into async task tokio::spawn({ - let state = Arc::clone(&state); // 克隆 Arc 以便传递给异步任务 + let state = Arc::clone(&state); // clone Arc to pass to async task async move { - let state = state.lock().await; // 异步地获取 Mutex 锁 + let state = state.lock().await; // acquire Mutex lock asynchronously if !state.is_admin { windows::elevate_self(); } @@ -173,8 +173,8 @@ pub fn build(app: &App, id: &str) { tokio::spawn({ let state = Arc::clone(&state); async move { - let mut state = state.lock().await; // 异步地获取 Mutex 锁 - state.is_min_tray = false; // 修改状态 + let mut state = state.lock().await; // acquire Mutex lock asynchronously + state.is_min_tray = false; // modify state } }); } diff --git a/src-tauri/src/windows.rs b/src-tauri/src/windows.rs index 94b3e6b..7498359 100644 --- a/src-tauri/src/windows.rs +++ b/src-tauri/src/windows.rs @@ -24,14 +24,14 @@ pub fn is_admin() -> bool { &mut size, ); - CloseHandle(token); // 必须关闭句柄 + CloseHandle(token); // must close handle status != 0 && elevation.TokenIsElevated != 0 } } #[cfg(not(windows))] pub fn is_admin() -> bool { - false // 非Windows系统返回false + false // non-Windows systems return false } #[cfg(windows)] pub fn elevate_self() { @@ -40,7 +40,7 @@ pub fn elevate_self() { use winapi::um::shellapi::ShellExecuteW; use winapi::um::winuser::SW_SHOW; - let exe_path = std::env::current_exe().expect("获取程序路径失败"); + let exe_path = std::env::current_exe().expect("Failed to get executable path"); let os_str = exe_path .as_os_str() .encode_wide() @@ -48,9 +48,9 @@ pub fn elevate_self() { .collect::>(); let verb: Vec = "runas\0".encode_utf16().collect(); - // 获取当前的命令行参数,并将 `--adminstart` 加入其中 - let mut params = std::env::args().skip(1).collect::>(); // 获取原有的命令行参数 - params.push("--adminstart".to_string()); // 添加 `--adminstart` 参数 + // Get current command-line arguments and append `--adminstart` + let mut params = std::env::args().skip(1).collect::>(); // get existing command-line arguments + params.push("--adminstart".to_string()); // add `--adminstart` parameter let params_str = params .join(" ") diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 86a83c8..8694f7a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "BatteryMaster", - "version": "0.1.3", + "version": "0.1.4", "identifier": "net.weero.BatteryMaster.app", "build": { "beforeDevCommand": "npm run dev", @@ -27,7 +27,16 @@ }, "bundle": { "active": true, - "targets": [], + "targets": ["nsis"], + "resources": [ + "history.db", + "logs.log", + "config.json", + "inpoutx64.dll", + "libryzenadj.dll", + "WinRing0x64.dll", + "WinRing0x64.sys" + ], "icon": ["icons/icon.ico"] } } diff --git a/src/App.vue b/src/App.vue index b6fd968..376706e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -13,12 +13,12 @@ indicator-color="transparent" align="left" > - + - + - - + + diff --git a/src/components/LineChart.vue b/src/components/LineChart.vue index 139ec18..01b71f4 100644 --- a/src/components/LineChart.vue +++ b/src/components/LineChart.vue @@ -51,7 +51,7 @@ option = { data: [ [ { - name: "放电", + name: "Discharging", xAxis: "2025-1-3", itemStyle: { color: "rgba(255, 127, 127, 0.2)", @@ -63,7 +63,7 @@ option = { ], [ { - name: "满电", + name: "Full", xAxis: "2025-1-5", itemStyle: { color: "rgba(0, 127, 127, 0.2)", diff --git a/src/main.ts b/src/main.ts index 25cc86d..39b334c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,7 @@ import { createApp } from "vue"; import { Quasar, Notify, Dialog } from "quasar"; -import quasarLang from "quasar/lang/zh-CN"; +import quasarLang from "quasar/lang/en-US"; import router from "./router"; import { createPinia } from "pinia"; @@ -17,9 +17,9 @@ import "quasar/src/css/index.sass"; // and placed in same folder as main.js import App from "./App.vue"; -import { zhCN } from "date-fns/locale"; +import { enUS } from "date-fns/locale"; import { setDefaultOptions } from "date-fns"; -setDefaultOptions({ locale: zhCN }); +setDefaultOptions({ locale: enUS }); const myApp = createApp(App); diff --git a/src/pages/CpuPower.vue b/src/pages/CpuPower.vue index 2cde951..c558864 100644 --- a/src/pages/CpuPower.vue +++ b/src/pages/CpuPower.vue @@ -7,13 +7,13 @@ Warning 您设置的功率限制部分没有生效,可能是因为计算机未支持部分设置,也有可能是我们不支持您的计算机;稍后谨慎进行功率限制,最好不要使用锁定功能;Some of the power limits you set did not take effect. This may be because your machine does not support certain settings, or we do not support your hardware. Apply power limits with caution; avoid using the lock feature if unsure. 下面是设置功率后实际查询到的值Actual queried values after applying the power settings @@ -31,8 +31,8 @@ {{ set_result.fast_limit }}w - - 关闭 + + Close @@ -42,15 +42,14 @@ class="text-white bg-red" v-show="!power_store.isAdmin" > - 需要以管理员模式启动 + Requires administrative privileges @@ -58,8 +57,8 @@ dense class="text-white bg-warning" v-show="sys_store.support_power_set && power_store.isAdmin" - >该功能仅在支持的amd - cpu(zen2+)上可用,也可能破坏您的计算机硬件,请谨慎使用;{{ + >This feature is only supported on AMD CPUs (Zen2+). It may damage hardware; use with caution. + }} @@ -97,10 +96,10 @@ label-always :disable="setting_disabled" />长时功耗(w)Long-term power (W) - 在没有触碰温度墙或其他因素,CPU可以长时间维持的最大功率限制;Maximum sustained power limit without hitting thermal walls or other factors; @@ -137,10 +136,10 @@ label-always :disable="setting_disabled" />短时功耗(w)Short-term power (W) - CPU可以短时间维持的最大功率限制Maximum power the CPU can sustain for a short period @@ -177,10 +176,10 @@ label-always :disable="setting_disabled" />瞬时功耗(w)Instantaneous power (W) - CPU在瞬间能达到的最高功率限制Peak instantaneous power the CPU can reach @@ -197,9 +196,9 @@ - 自动锁定 + Auto Lock 可能有其他进程重新设置功率限制,锁定后将每隔10秒恢复到设置的值。Other processes may reset power limits. When locked, values are restored every 10 seconds. @@ -214,7 +213,7 @@ 即将恢复到如下设置Will be reset to the following settings @@ -262,7 +261,7 @@ - 在设置中打开记录历史功能方可跟踪电池健康度; + Enable record history in Settings to track battery health;