修复应用多开的情况,增加更新模块的日志

master
cysamurai 2 months ago
parent fb60188b79
commit 9148bdacb5

@ -1,7 +1,7 @@
{
"name": "broadcast-client",
"private": true,
"version": "0.1.0",
"version": "0.1.1",
"type": "module",
"scripts": {
"dev": "vite",

@ -127,6 +127,7 @@ name = "broadcast-client"
version = "0.1.0"
dependencies = [
"chrono",
"fs2",
"serde",
"serde_json",
"tauri",
@ -753,6 +754,16 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "futf"
version = "0.1.5"
@ -1518,6 +1529,8 @@ version = "0.3.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9"
dependencies = [
"cfg-if",
"futures-util",
"once_cell",
"wasm-bindgen",
]
@ -1794,6 +1807,17 @@ dependencies = [
"objc_exception",
]
[[package]]
name = "objc-foundation"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
dependencies = [
"block",
"objc",
"objc_id",
]
[[package]]
name = "objc_exception"
version = "0.1.2"
@ -2328,6 +2352,30 @@ version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "rfd"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea"
dependencies = [
"block",
"dispatch",
"glib-sys",
"gobject-sys",
"gtk-sys",
"js-sys",
"lazy_static",
"log",
"objc",
"objc-foundation",
"objc_id",
"raw-window-handle",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"windows 0.37.0",
]
[[package]]
name = "rustc_version"
version = "0.4.1"
@ -2850,6 +2898,7 @@ dependencies = [
"plist",
"rand 0.8.5",
"raw-window-handle",
"rfd",
"semver",
"serde",
"serde_json",
@ -3406,6 +3455,16 @@ dependencies = [
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.117"
@ -3472,6 +3531,16 @@ dependencies = [
"semver",
]
[[package]]
name = "web-sys"
version = "0.3.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webkit2gtk"
version = "0.18.2"
@ -3588,6 +3657,19 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647"
dependencies = [
"windows_aarch64_msvc 0.37.0",
"windows_i686_gnu 0.37.0",
"windows_i686_msvc 0.37.0",
"windows_x86_64_gnu 0.37.0",
"windows_x86_64_msvc 0.37.0",
]
[[package]]
name = "windows"
version = "0.39.0"
@ -3750,6 +3832,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a"
[[package]]
name = "windows_aarch64_msvc"
version = "0.39.0"
@ -3762,6 +3850,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1"
[[package]]
name = "windows_i686_gnu"
version = "0.39.0"
@ -3774,6 +3868,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c"
[[package]]
name = "windows_i686_msvc"
version = "0.39.0"
@ -3786,6 +3886,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.39.0"
@ -3804,6 +3910,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.39.0"

@ -1,6 +1,6 @@
[package]
name = "broadcast-client"
version = "0.1.0"
version = "0.1.1"
description = "Broadcast Ruler Client"
authors = ["team"]
edition = "2021"
@ -17,7 +17,8 @@ default = ["custom-protocol"]
custom-protocol = ["tauri/custom-protocol"]
[dependencies]
tauri = { version = "1", features = ["window-all"] }
tauri = { version = "1", features = ["window-all", "dialog"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
chrono = { version = "0.4", features = ["clock"] }
fs2 = "0.4"

@ -1,5 +1,6 @@
use std::{
fs::{create_dir_all, read_dir, remove_file, OpenOptions},
fs::{create_dir_all, read_dir, remove_file, File, OpenOptions},
io,
io::Read,
io::Write,
net::TcpListener,
@ -13,6 +14,7 @@ use std::{
};
use chrono::Local;
use fs2::FileExt;
use serde::{Deserialize, Serialize};
use tauri::Manager;
#[cfg(target_os = "linux")]
@ -26,6 +28,30 @@ const LOG_FILE_EXT: &str = ".log";
const LOG_FILE_MAX_BYTES: u64 = 5 * 1024 * 1024;
const LOG_RETENTION_DAYS: u64 = 7;
#[allow(dead_code)]
struct SingleInstanceLock(File);
fn acquire_single_instance_lock(app: &tauri::App) -> Result<SingleInstanceLock, String> {
let base_dir = app.path_resolver().app_data_dir().ok_or("无法获取应用数据目录")?;
create_dir_all(&base_dir).map_err(|err| format!("创建锁目录失败: {err}"))?;
let lock_path = base_dir.join("single-instance.lock");
let lock_file = OpenOptions::new()
.create(true)
.read(true)
.write(true)
.open(lock_path)
.map_err(|err| format!("打开锁文件失败: {err}"))?;
match lock_file.try_lock_exclusive() {
Ok(()) => Ok(SingleInstanceLock(lock_file)),
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
Err("duplicate instance".to_string())
}
Err(err) => Err(format!("加锁失败: {err}")),
}
}
#[derive(Default)]
struct SocketServiceState {
runtime: Mutex<Option<SocketServiceRuntime>>,
@ -98,6 +124,22 @@ struct AptUpdateCheckResult {
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.setup(|app| match acquire_single_instance_lock(app) {
Ok(lock) => {
app.manage(lock);
Ok(())
}
Err(reason) if reason == "duplicate instance" => {
tauri::api::dialog::blocking::message(
None::<&tauri::Window>,
"提示",
"请勿重复打开",
);
app.handle().exit(0);
Ok(())
}
Err(reason) => Err(reason.into()),
})
.manage(SocketServiceState::default())
.invoke_handler(tauri::generate_handler![
start_socket_service,
@ -245,10 +287,31 @@ fn extract_policy_value(output: &str, key: &str) -> String {
}
#[tauri::command]
fn check_apt_update(package_name: String, current_version: String) -> Result<AptUpdateCheckResult, String> {
fn check_apt_update(
app: tauri::AppHandle,
package_name: String,
current_version: String,
) -> Result<AptUpdateCheckResult, String> {
append_socket_log(
&app,
"INFO",
format!(
"检查更新开始 package={} current_version={}",
package_name, current_version
),
);
#[cfg(not(target_os = "linux"))]
{
let _ = (&package_name, &current_version);
append_socket_log(
&app,
"WARN",
format!(
"检查更新失败 package={} reason=当前系统不支持 apt 更新检测,仅支持 Linux",
package_name
),
);
return Err("当前系统不支持 apt 更新检测,仅支持 Linux。".to_string());
}
@ -258,15 +321,29 @@ fn check_apt_update(package_name: String, current_version: String) -> Result<Apt
.arg("policy")
.arg(&package_name)
.output()
.map_err(|error| format!("执行 apt-cache 失败: {error}"))?;
.map_err(|error| {
let message = format!("执行 apt-cache 失败: {error}");
append_socket_log(
&app,
"ERROR",
format!("检查更新失败 package={} {}", package_name, message),
);
message
})?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
return Err(if stderr.is_empty() {
let message = if stderr.is_empty() {
"apt-cache policy 执行失败".to_string()
} else {
format!("apt-cache policy 执行失败: {stderr}")
});
};
append_socket_log(
&app,
"ERROR",
format!("检查更新失败 package={} {}", package_name, message),
);
return Err(message);
}
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
@ -286,7 +363,7 @@ fn check_apt_update(package_name: String, current_version: String) -> Result<Apt
package_name
);
Ok(AptUpdateCheckResult {
let result = AptUpdateCheckResult {
package_name,
current_version,
installed_version,
@ -294,7 +371,22 @@ fn check_apt_update(package_name: String, current_version: String) -> Result<Apt
has_update,
source_available,
update_command,
})
};
append_socket_log(
&app,
"INFO",
format!(
"检查更新完成 package={} installed_version={} candidate_version={} has_update={} source_available={}",
result.package_name,
result.installed_version,
result.candidate_version,
result.has_update,
result.source_available
),
);
Ok(result)
}
}

@ -2,7 +2,7 @@
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
"package": {
"productName": "broadcast-client",
"version": "0.1.0"
"version": "0.1.1"
},
"build": {
"beforeDevCommand": "npm run dev",

@ -561,12 +561,18 @@ async function handleCheckUpdate() {
checkingUpdate.value = true;
try {
console.info("[update] 检查更新开始", {
packageName: "broadcast-client",
currentVersion: appVersion.value,
});
const result = await invoke<AptUpdateCheckResult>("check_apt_update", {
packageName: "broadcast-client",
currentVersion: "0.1.0",
currentVersion: appVersion.value,
});
console.info("[update] 检查更新结果", result);
if (!result.sourceAvailable) {
console.warn("[update] 未检测到可用更新源", { packageName: result.packageName });
ElMessage.warning(
`未检测到可用更新源,请先执行:${APT_SOURCE_SETUP_COMMAND}`,
);
@ -574,14 +580,21 @@ async function handleCheckUpdate() {
}
if (!result.hasUpdate) {
console.info("[update] 当前已是最新版本", { installedVersion: result.installedVersion });
ElMessage.success(`当前已是最新版本(${result.installedVersion}`);
return;
}
console.info("[update] 检测到新版本", {
installedVersion: result.installedVersion,
candidateVersion: result.candidateVersion,
updateCommand: result.updateCommand,
});
ElMessage.warning(
`发现新版本 ${result.candidateVersion},请在终端执行:${result.updateCommand}`,
);
} catch (error) {
console.error("[update] 检查更新失败", error);
ElMessage.error(`检查更新失败:${String(error)}`);
} finally {
checkingUpdate.value = false;

@ -1,7 +1,7 @@
{
"name": "call-client",
"private": true,
"version": "0.1.0",
"version": "0.1.1",
"type": "module",
"scripts": {
"dev": "vite",

@ -394,6 +394,7 @@ dependencies = [
name = "call-client"
version = "0.1.0"
dependencies = [
"fs2",
"serde",
"serde_json",
"tauri",
@ -1075,6 +1076,16 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "futf"
version = "0.1.5"
@ -2670,7 +2681,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
dependencies = [
"libc",
"windows-sys 0.48.0",
"windows-sys 0.61.2",
]
[[package]]

@ -1,6 +1,6 @@
[package]
name = "call-client"
version = "0.1.0"
version = "0.1.1"
description = "A Tauri App"
authors = ["you"]
edition = "2021"
@ -25,4 +25,5 @@ custom-protocol = ["tauri/custom-protocol"]
tauri = { version = "1", features = ["api-all"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
fs2 = "0.4"

@ -1,6 +1,9 @@
use serde::Serialize;
#[cfg(target_os = "linux")]
use std::process::Command;
use tauri::AppHandle;
use super::logger::app_log;
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
@ -24,10 +27,29 @@ fn extract_policy_value(output: &str, key: &str) -> String {
}
#[tauri::command]
pub fn check_apt_update(package_name: String, current_version: String) -> Result<AptUpdateCheckResult, String> {
pub fn check_apt_update(
_app: AppHandle,
package_name: String,
current_version: String,
) -> Result<AptUpdateCheckResult, String> {
let _ = app_log(
"info".to_string(),
format!(
"检查更新开始: package={}, current_version={}",
package_name, current_version
),
);
#[cfg(not(target_os = "linux"))]
{
let _ = (&package_name, &current_version);
let _ = app_log(
"warn".to_string(),
format!(
"检查更新失败: package={}, reason=当前系统不支持 apt 更新检测,仅支持 Linux",
package_name
),
);
return Err("当前系统不支持 apt 更新检测,仅支持 Linux。".to_string());
}
@ -37,15 +59,27 @@ pub fn check_apt_update(package_name: String, current_version: String) -> Result
.arg("policy")
.arg(&package_name)
.output()
.map_err(|error| format!("执行 apt-cache 失败: {error}"))?;
.map_err(|error| {
let message = format!("执行 apt-cache 失败: {error}");
let _ = app_log(
"error".to_string(),
format!("检查更新失败: package={}, {}", package_name, message),
);
message
})?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
return Err(if stderr.is_empty() {
let message = if stderr.is_empty() {
"apt-cache policy 执行失败".to_string()
} else {
format!("apt-cache policy 执行失败: {stderr}")
});
};
let _ = app_log(
"error".to_string(),
format!("检查更新失败: package={}, {}", package_name, message),
);
return Err(message);
}
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
@ -65,7 +99,7 @@ pub fn check_apt_update(package_name: String, current_version: String) -> Result
package_name
);
Ok(AptUpdateCheckResult {
let result = AptUpdateCheckResult {
package_name,
current_version,
installed_version,
@ -73,6 +107,20 @@ pub fn check_apt_update(package_name: String, current_version: String) -> Result
has_update,
source_available,
update_command,
})
};
let _ = app_log(
"info".to_string(),
format!(
"检查更新完成: package={}, installed_version={}, candidate_version={}, has_update={}, source_available={}",
result.package_name,
result.installed_version,
result.candidate_version,
result.has_update,
result.source_available
),
);
Ok(result)
}
}

@ -1,6 +1,11 @@
mod commands;
mod state;
use std::{
fs::{create_dir_all, File, OpenOptions},
io,
};
use commands::{
config::{config_get_all, config_merge},
events::{emit_to_window, list_windows},
@ -12,13 +17,57 @@ use commands::{
open_ticket_window, quit_app,
},
};
use fs2::FileExt;
use state::AppState;
use tauri::Manager;
#[allow(dead_code)]
struct SingleInstanceLock(File);
fn acquire_single_instance_lock(app: &tauri::App) -> Result<SingleInstanceLock, String> {
let base_dir = app.path_resolver().app_data_dir().ok_or("无法获取应用数据目录")?;
create_dir_all(&base_dir).map_err(|err| format!("创建锁目录失败: {err}"))?;
let lock_path = base_dir.join("single-instance.lock");
let lock_file = OpenOptions::new()
.create(true)
.read(true)
.write(true)
.open(lock_path)
.map_err(|err| format!("打开锁文件失败: {err}"))?;
match lock_file.try_lock_exclusive() {
Ok(()) => Ok(SingleInstanceLock(lock_file)),
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
Err("duplicate instance".to_string())
}
Err(err) => Err(format!("加锁失败: {err}")),
}
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.manage(AppState::default())
.setup(|app| {
match acquire_single_instance_lock(app) {
Ok(lock) => {
app.manage(lock);
}
Err(reason) if reason == "duplicate instance" => {
tauri::api::dialog::blocking::message(
None::<&tauri::Window>,
"提示",
"请勿重复打开",
);
app.handle().exit(0);
return Ok(());
}
Err(reason) => {
return Err(reason.into());
}
}
ensure_main_window(app.handle())?;
Ok(())
})

@ -2,7 +2,7 @@
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
"package": {
"productName": "call-client",
"version": "0.1.0"
"version": "0.1.1"
},
"build": {
"beforeDevCommand": "npm run dev",
@ -12,7 +12,12 @@
},
"tauri": {
"allowlist": {
"all": true
"all": true,
"http": {
"all": true,
"request": true,
"scope": ["http://*/*", "https://*/*"]
}
},
"windows": [
{

@ -13,11 +13,11 @@ export async function minimizeWindow(): Promise<void> {
}
/**
*
*
*/
export async function closeWindow(): Promise<void> {
try {
await appWindow.close();
await invoke("quit_app");
} catch (error) {
throw new Error(`关闭窗口失败: ${String(error)}`);
}

@ -1,4 +1,10 @@
import axios, { type AxiosRequestConfig } from "axios";
import axios, {
AxiosError,
type AxiosRequestConfig,
type AxiosResponse,
type InternalAxiosRequestConfig,
} from "axios";
import { Body, fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http";
import { showErrorNative } from "../host/dialog";
import { getSession, setSession } from "../host/session";
import type { SessionState } from "../host/types";
@ -27,6 +33,96 @@ type RetryableAxiosRequestConfig = AxiosRequestConfig & {
let refreshTokenPromise: Promise<string | null> | null = null;
function shouldUseTauriHttpTransport(): boolean {
return !import.meta.env.DEV;
}
function buildRequestUrl(config: AxiosRequestConfig): string {
const rawUrl = config.url ?? "";
const baseURL = config.baseURL ?? "";
const isAbsoluteUrl = /^https?:\/\//i.test(rawUrl);
const finalUrl = isAbsoluteUrl
? rawUrl
: `${baseURL.replace(/\/$/, "")}/${rawUrl.replace(/^\//, "")}`;
if (!config.params) {
return finalUrl;
}
const searchParams = new URLSearchParams();
const params = config.params as Record<string, unknown>;
Object.entries(params).forEach(([key, value]) => {
if (value === undefined || value === null) {
return;
}
if (Array.isArray(value)) {
value.forEach((item) => searchParams.append(key, String(item)));
return;
}
searchParams.append(key, String(value));
});
const query = searchParams.toString();
if (!query) {
return finalUrl;
}
const connector = finalUrl.includes("?") ? "&" : "?";
return `${finalUrl}${connector}${query}`;
}
function buildTauriBody(config: AxiosRequestConfig): Body | undefined {
const method = (config.method ?? "GET").toUpperCase();
if (method === "GET" || method === "HEAD" || config.data === undefined) {
return undefined;
}
if (typeof config.data === "string") {
return Body.text(config.data);
}
return Body.json(config.data);
}
/**
* 使 Tauri HTTP WebView /
*/
async function tauriAxiosAdapter(
config: InternalAxiosRequestConfig,
): Promise<AxiosResponse> {
try {
const url = buildRequestUrl(config);
const method = (config.method ?? "GET").toUpperCase() as
| "GET"
| "POST"
| "PUT"
| "DELETE"
| "PATCH"
| "HEAD";
const headers = (config.headers ?? {}) as Record<string, string>;
const response = await tauriFetch<unknown>(url, {
method,
timeout: config.timeout,
headers,
body: buildTauriBody(config),
responseType: ResponseType.JSON,
});
return {
data: response.data,
status: response.status,
statusText: String(response.status),
headers: response.headers as Record<string, string>,
config,
request: null,
};
} catch (error) {
throw new AxiosError(
error instanceof Error ? error.message : String(error),
"ERR_NETWORK",
config,
);
}
}
/**
* baseURL
*/
@ -57,6 +153,10 @@ const instance = axios.create({
},
});
if (shouldUseTauriHttpTransport()) {
instance.defaults.adapter = tauriAxiosAdapter;
}
function isApiSuccessCode(code: unknown): boolean {
return code === 200 || code === 0;
}

@ -258,12 +258,18 @@ async function handleCheckUpdate(): Promise<void> {
checkingUpdate.value = true;
try {
await log("info", `检查更新开始: package=call-client, currentVersion=${appVersion.value}`);
const result = await invoke<AptUpdateCheckResult>("check_apt_update", {
packageName: "call-client",
currentVersion: appVersion.value,
});
await log(
"info",
`检查更新结果: package=${result.packageName}, installed=${result.installedVersion}, candidate=${result.candidateVersion}, hasUpdate=${result.hasUpdate}, sourceAvailable=${result.sourceAvailable}`,
);
if (!result.sourceAvailable) {
await log("warn", `检查更新提示: 未检测到可用更新源, package=${result.packageName}`);
try {
await ElMessageBox.confirm(
[
@ -291,10 +297,15 @@ async function handleCheckUpdate(): Promise<void> {
}
if (!result.hasUpdate) {
await log("info", `检查更新提示: 当前已是最新版本, version=${result.installedVersion}`);
showMessage("success", `当前已是最新版本(${result.installedVersion}`);
return;
}
await log(
"info",
`检查更新提示: 检测到新版本, installed=${result.installedVersion}, candidate=${result.candidateVersion}`,
);
try {
await ElMessageBox.confirm(
[

Loading…
Cancel
Save