mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 00:35:38 +08:00
feat: better service status and TUN mode usable checks in Setting Page
This commit is contained in:
@@ -237,8 +237,7 @@ pub async fn get_dns_config_content() -> CmdResult<String> {
|
|||||||
/// 验证DNS配置文件
|
/// 验证DNS配置文件
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn validate_dns_config() -> CmdResult<(bool, String)> {
|
pub async fn validate_dns_config() -> CmdResult<(bool, String)> {
|
||||||
use crate::core::CoreManager;
|
use crate::{core::CoreManager, utils::dirs};
|
||||||
use crate::utils::dirs;
|
|
||||||
|
|
||||||
let app_dir = dirs::app_home_dir().map_err(|e| e.to_string())?;
|
let app_dir = dirs::app_home_dir().map_err(|e| e.to_string())?;
|
||||||
let dns_path = app_dir.join("dns_config.yaml");
|
let dns_path = app_dir.join("dns_config.yaml");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use super::CmdResult;
|
use super::CmdResult;
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{service, CoreManager},
|
core::{service, CoreManager},
|
||||||
|
feat,
|
||||||
utils::i18n::t,
|
utils::i18n::t,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -38,3 +39,11 @@ pub async fn reinstall_service() -> CmdResult {
|
|||||||
pub async fn repair_service() -> CmdResult {
|
pub async fn repair_service() -> CmdResult {
|
||||||
execute_service_operation(service::force_reinstall_service(), "Repair").await
|
execute_service_operation(service::force_reinstall_service(), "Repair").await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn is_service_available() -> CmdResult<bool> {
|
||||||
|
service::is_service_available()
|
||||||
|
.await
|
||||||
|
.map(|_| true)
|
||||||
|
.map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
use crate::utils::network::{NetworkManager, ProxyType};
|
use crate::utils::{
|
||||||
use crate::utils::{dirs, help, tmpl};
|
dirs, help,
|
||||||
|
network::{NetworkManager, ProxyType},
|
||||||
|
tmpl,
|
||||||
|
};
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
use std::fs;
|
use std::{fs, time::Duration};
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use super::Config;
|
use super::Config;
|
||||||
|
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ pub async fn reinstall_service() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 检查服务状态 - 使用IPC通信
|
/// 检查服务状态 - 使用IPC通信
|
||||||
pub async fn check_service() -> Result<JsonResponse> {
|
pub async fn check_ipc_service_status() -> Result<JsonResponse> {
|
||||||
logging!(info, Type::Service, true, "开始检查服务状态 (IPC)");
|
logging!(info, Type::Service, true, "开始检查服务状态 (IPC)");
|
||||||
|
|
||||||
// 使用IPC通信
|
// 使用IPC通信
|
||||||
@@ -876,7 +876,7 @@ pub(super) async fn run_core_by_service(config_file: &PathBuf) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查服务状态
|
// 检查服务状态
|
||||||
match check_service().await {
|
match check_ipc_service_status().await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
log::info!(target: "app", "服务可用但未运行核心,尝试启动");
|
log::info!(target: "app", "服务可用但未运行核心,尝试启动");
|
||||||
if let Ok(()) = start_with_existing_service(config_file).await {
|
if let Ok(()) = start_with_existing_service(config_file).await {
|
||||||
@@ -947,7 +947,7 @@ pub(super) async fn stop_core_by_service() -> Result<()> {
|
|||||||
pub async fn is_service_running() -> Result<bool> {
|
pub async fn is_service_running() -> Result<bool> {
|
||||||
logging!(info, Type::Service, true, "开始检查服务是否正在运行");
|
logging!(info, Type::Service, true, "开始检查服务是否正在运行");
|
||||||
|
|
||||||
match check_service().await {
|
match check_ipc_service_status().await {
|
||||||
Ok(resp) => {
|
Ok(resp) => {
|
||||||
if resp.code == 0 && resp.msg == "ok" && resp.data.is_some() {
|
if resp.code == 0 && resp.msg == "ok" && resp.data.is_some() {
|
||||||
logging!(info, Type::Service, true, "服务正在运行");
|
logging!(info, Type::Service, true, "服务正在运行");
|
||||||
@@ -1010,7 +1010,7 @@ pub async fn is_service_running() -> Result<bool> {
|
|||||||
pub async fn is_service_available() -> Result<()> {
|
pub async fn is_service_available() -> Result<()> {
|
||||||
logging!(info, Type::Service, true, "开始检查服务是否可用");
|
logging!(info, Type::Service, true, "开始检查服务是否可用");
|
||||||
|
|
||||||
match check_service().await {
|
match check_ipc_service_status().await {
|
||||||
Ok(resp) => {
|
Ok(resp) => {
|
||||||
if resp.code == 0 && resp.msg == "ok" && resp.data.is_some() {
|
if resp.code == 0 && resp.msg == "ok" && resp.data.is_some() {
|
||||||
logging!(info, Type::Service, true, "服务可用");
|
logging!(info, Type::Service, true, "服务可用");
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::logging;
|
use crate::{logging, utils::logging::Type};
|
||||||
use crate::utils::logging::Type;
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -117,14 +116,18 @@ pub async fn send_ipc_request(
|
|||||||
command: IpcCommand,
|
command: IpcCommand,
|
||||||
payload: serde_json::Value,
|
payload: serde_json::Value,
|
||||||
) -> Result<IpcResponse> {
|
) -> Result<IpcResponse> {
|
||||||
use std::ffi::CString;
|
use std::{
|
||||||
use std::fs::File;
|
ffi::CString,
|
||||||
use std::io::{Read, Write};
|
fs::File,
|
||||||
use std::os::windows::io::{FromRawHandle, RawHandle};
|
io::{Read, Write},
|
||||||
use std::ptr;
|
os::windows::io::{FromRawHandle, RawHandle},
|
||||||
use winapi::um::fileapi::{CreateFileA, OPEN_EXISTING};
|
ptr,
|
||||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
};
|
||||||
use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
|
use winapi::um::{
|
||||||
|
fileapi::{CreateFileA, OPEN_EXISTING},
|
||||||
|
handleapi::INVALID_HANDLE_VALUE,
|
||||||
|
winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE},
|
||||||
|
};
|
||||||
|
|
||||||
logging!(
|
logging!(
|
||||||
info,
|
info,
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ pub mod speed_rate;
|
|||||||
use crate::{
|
use crate::{
|
||||||
cmd,
|
cmd,
|
||||||
config::Config,
|
config::Config,
|
||||||
feat,
|
feat, logging,
|
||||||
module::{
|
module::{
|
||||||
lightweight::{entry_lightweight_mode, is_in_lightweight_mode},
|
lightweight::{entry_lightweight_mode, is_in_lightweight_mode},
|
||||||
mihomo::Rate,
|
mihomo::Rate,
|
||||||
},
|
},
|
||||||
resolve,
|
resolve,
|
||||||
utils::{dirs::find_target_icons, i18n::t, resolve::VERSION},
|
utils::{dirs::find_target_icons, i18n::t, resolve::VERSION},
|
||||||
|
Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
@@ -828,7 +829,13 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) {
|
|||||||
match event.id.as_ref() {
|
match event.id.as_ref() {
|
||||||
mode @ ("rule_mode" | "global_mode" | "direct_mode") => {
|
mode @ ("rule_mode" | "global_mode" | "direct_mode") => {
|
||||||
let mode = &mode[0..mode.len() - 5];
|
let mode = &mode[0..mode.len() - 5];
|
||||||
println!("change mode to: {}", mode);
|
logging!(
|
||||||
|
info,
|
||||||
|
Type::ProxyMode,
|
||||||
|
true,
|
||||||
|
"Switch Proxy Mode To: {}",
|
||||||
|
mode
|
||||||
|
);
|
||||||
feat::change_clash_mode(mode.into());
|
feat::change_clash_mode(mode.into());
|
||||||
}
|
}
|
||||||
"open_window" => {
|
"open_window" => {
|
||||||
|
|||||||
@@ -240,8 +240,10 @@ pub struct Traffic {
|
|||||||
impl Traffic {
|
impl Traffic {
|
||||||
pub async fn get_traffic_stream() -> Result<impl Stream<Item = Result<Traffic, anyhow::Error>>>
|
pub async fn get_traffic_stream() -> Result<impl Stream<Item = Result<Traffic, anyhow::Error>>>
|
||||||
{
|
{
|
||||||
use futures::future::FutureExt;
|
use futures::{
|
||||||
use futures::stream::{self, StreamExt};
|
future::FutureExt,
|
||||||
|
stream::{self, StreamExt},
|
||||||
|
};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
// 先处理错误和超时情况
|
// 先处理错误和超时情况
|
||||||
|
|||||||
@@ -43,19 +43,6 @@ pub fn toggle_system_proxy() {
|
|||||||
|
|
||||||
/// Toggle TUN mode on/off
|
/// Toggle TUN mode on/off
|
||||||
pub fn toggle_tun_mode(not_save_file: Option<bool>) {
|
pub fn toggle_tun_mode(not_save_file: Option<bool>) {
|
||||||
// AsyncHandler::spawn(async {
|
|
||||||
// logging!(
|
|
||||||
// info,
|
|
||||||
// Type::Service,
|
|
||||||
// true,
|
|
||||||
// "Toggle TUN mode need install service"
|
|
||||||
// );
|
|
||||||
// if is_service_available().await.is_err() {
|
|
||||||
// logging_error!(Type::Service, true, install_service().await);
|
|
||||||
// }
|
|
||||||
// logging_error!(Type::Core, true, CoreManager::global().restart_core().await);
|
|
||||||
// });
|
|
||||||
|
|
||||||
let enable = Config::verge().data().enable_tun_mode;
|
let enable = Config::verge().data().enable_tun_mode;
|
||||||
let enable = enable.unwrap_or(false);
|
let enable = enable.unwrap_or(false);
|
||||||
|
|
||||||
|
|||||||
@@ -235,6 +235,7 @@ pub fn run() {
|
|||||||
cmd::uninstall_service,
|
cmd::uninstall_service,
|
||||||
cmd::reinstall_service,
|
cmd::reinstall_service,
|
||||||
cmd::repair_service,
|
cmd::repair_service,
|
||||||
|
cmd::is_service_available,
|
||||||
// clash
|
// clash
|
||||||
cmd::get_clash_info,
|
cmd::get_clash_info,
|
||||||
cmd::patch_clash_config,
|
cmd::patch_clash_config,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::fmt;
|
use std::fmt::{self, write};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
@@ -16,6 +16,7 @@ pub enum Type {
|
|||||||
Backup,
|
Backup,
|
||||||
Lightweight,
|
Lightweight,
|
||||||
Network,
|
Network,
|
||||||
|
ProxyMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Type {
|
impl fmt::Display for Type {
|
||||||
@@ -35,6 +36,7 @@ impl fmt::Display for Type {
|
|||||||
Type::Backup => write!(f, "[Backup]"),
|
Type::Backup => write!(f, "[Backup]"),
|
||||||
Type::Lightweight => write!(f, "[Lightweight]"),
|
Type::Lightweight => write!(f, "[Lightweight]"),
|
||||||
Type::Network => write!(f, "[Network]"),
|
Type::Network => write!(f, "[Network]"),
|
||||||
|
Type::ProxyMode => write!(f, "[ProxMode]"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use reqwest::{Client, ClientBuilder, Proxy, RequestBuilder, Response};
|
use reqwest::{Client, ClientBuilder, Proxy, RequestBuilder, Response};
|
||||||
use std::sync::{Arc, Mutex, Once};
|
use std::{
|
||||||
use std::time::{Duration, Instant};
|
sync::{Arc, Mutex, Once},
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
use tokio::runtime::{Builder, Runtime};
|
use tokio::runtime::{Builder, Runtime};
|
||||||
|
|
||||||
use crate::{config::Config, logging, utils::logging::Type};
|
use crate::{config::Config, logging, utils::logging::Type};
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
getAutotemProxy,
|
getAutotemProxy,
|
||||||
installService,
|
installService,
|
||||||
getAutoLaunchStatus,
|
getAutoLaunchStatus,
|
||||||
|
restartCore,
|
||||||
} from "@/services/cmds";
|
} from "@/services/cmds";
|
||||||
import { useLockFn } from "ahooks";
|
import { useLockFn } from "ahooks";
|
||||||
import { Button, Tooltip } from "@mui/material";
|
import { Button, Tooltip } from "@mui/material";
|
||||||
@@ -41,25 +42,18 @@ const SettingSystem = ({ onError }: Props) => {
|
|||||||
const { data: autoLaunchEnabled } = useSWR(
|
const { data: autoLaunchEnabled } = useSWR(
|
||||||
"getAutoLaunchStatus",
|
"getAutoLaunchStatus",
|
||||||
getAutoLaunchStatus,
|
getAutoLaunchStatus,
|
||||||
{ revalidateOnFocus: false }
|
{ revalidateOnFocus: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
const { isAdminMode, isSidecarMode, mutateRunningMode } = useSystemState();
|
const { isAdminMode, isSidecarMode, mutateRunningMode, isServiceOk } =
|
||||||
|
useSystemState();
|
||||||
|
|
||||||
|
console.log("Is service running:", isServiceOk);
|
||||||
|
|
||||||
// 判断Tun模式是否可用 - 当处于服务模式或管理员模式时可用
|
// 判断Tun模式是否可用 - 当处于服务模式或管理员模式时可用
|
||||||
const isTunAvailable = !isSidecarMode || isAdminMode;
|
const isTunAvailable = isServiceOk || (isSidecarMode && !isAdminMode);
|
||||||
|
|
||||||
// 当实际自启动状态与配置不同步时更新配置
|
console.log("is tun isTunAvailable:", isTunAvailable);
|
||||||
useEffect(() => {
|
|
||||||
if (
|
|
||||||
autoLaunchEnabled !== undefined &&
|
|
||||||
verge &&
|
|
||||||
verge.enable_auto_launch !== autoLaunchEnabled
|
|
||||||
) {
|
|
||||||
// 静默更新配置,不触发UI刷新
|
|
||||||
mutateVerge({ ...verge, enable_auto_launch: autoLaunchEnabled }, false);
|
|
||||||
}
|
|
||||||
}, [autoLaunchEnabled]);
|
|
||||||
|
|
||||||
const sysproxyRef = useRef<DialogRef>(null);
|
const sysproxyRef = useRef<DialogRef>(null);
|
||||||
const tunRef = useRef<DialogRef>(null);
|
const tunRef = useRef<DialogRef>(null);
|
||||||
@@ -87,13 +81,16 @@ const SettingSystem = ({ onError }: Props) => {
|
|||||||
// 安装系统服务
|
// 安装系统服务
|
||||||
const onInstallService = useLockFn(async () => {
|
const onInstallService = useLockFn(async () => {
|
||||||
try {
|
try {
|
||||||
showNotice('info', t("Installing Service..."), 1000);
|
showNotice("info", t("Installing Service..."), 1000);
|
||||||
await installService();
|
await installService();
|
||||||
showNotice('success', t("Service Installed Successfully"), 2000);
|
showNotice("success", t("Service Installed Successfully"), 2000);
|
||||||
|
await restartCore();
|
||||||
|
showNotice("info", t("Restarting Core"), 1000);
|
||||||
|
console.log("restartCore");
|
||||||
// 重新获取运行模式
|
// 重新获取运行模式
|
||||||
await mutateRunningMode();
|
await mutateRunningMode();
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
showNotice('error', err.message || err.toString(), 3000);
|
showNotice("error", err.message || err.toString(), 3000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -111,12 +108,12 @@ const SettingSystem = ({ onError }: Props) => {
|
|||||||
icon={SettingsRounded}
|
icon={SettingsRounded}
|
||||||
onClick={() => tunRef.current?.open()}
|
onClick={() => tunRef.current?.open()}
|
||||||
/>
|
/>
|
||||||
{isSidecarMode && !isAdminMode && (
|
{!isServiceOk && !isAdminMode && (
|
||||||
<Tooltip title={t("TUN requires Service Mode")}>
|
<Tooltip title={t("TUN requires Service Mode")}>
|
||||||
<WarningRounded sx={{ color: "warning.main", mr: 1 }} />
|
<WarningRounded sx={{ color: "warning.main", mr: 1 }} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{isSidecarMode && !isAdminMode && (
|
{!isServiceOk && !isAdminMode && (
|
||||||
<Tooltip title={t("Install Service")}>
|
<Tooltip title={t("Install Service")}>
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@@ -138,20 +135,20 @@ const SettingSystem = ({ onError }: Props) => {
|
|||||||
onCatch={onError}
|
onCatch={onError}
|
||||||
onFormat={onSwitchFormat}
|
onFormat={onSwitchFormat}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
// 当在sidecar模式下且非管理员模式时禁用切换
|
// 非 Service 状态禁止切换
|
||||||
if (isSidecarMode && !isAdminMode) return;
|
if (!isServiceOk) return;
|
||||||
onChangeData({ enable_tun_mode: e });
|
onChangeData({ enable_tun_mode: e });
|
||||||
}}
|
}}
|
||||||
onGuard={(e) => {
|
onGuard={(e) => {
|
||||||
// 当在sidecar模式下且非管理员模式时禁用切换
|
// 非 Service 状态禁止切换
|
||||||
if (isSidecarMode && !isAdminMode) {
|
if (!isServiceOk) {
|
||||||
showNotice('error', t("TUN requires Service Mode"), 2000);
|
showNotice("error", t("TUN requires Service Mode"), 2000);
|
||||||
return Promise.reject(new Error(t("TUN requires Service Mode")));
|
return Promise.reject(new Error(t("TUN requires Service Mode")));
|
||||||
}
|
}
|
||||||
return patchVerge({ enable_tun_mode: e });
|
return patchVerge({ enable_tun_mode: e });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Switch edge="end" disabled={isSidecarMode && !isAdminMode} />
|
<Switch edge="end" disabled={isServiceOk} />
|
||||||
</GuardState>
|
</GuardState>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
<SettingItem
|
<SettingItem
|
||||||
@@ -195,11 +192,13 @@ const SettingSystem = ({ onError }: Props) => {
|
|||||||
</GuardState>
|
</GuardState>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
|
||||||
<SettingItem
|
<SettingItem
|
||||||
label={t("Auto Launch")}
|
label={t("Auto Launch")}
|
||||||
extra={
|
extra={
|
||||||
isAdminMode && (
|
isAdminMode && (
|
||||||
<Tooltip title={t("Administrator mode may not support auto launch")}>
|
<Tooltip
|
||||||
|
title={t("Administrator mode may not support auto launch")}
|
||||||
|
>
|
||||||
<WarningRounded sx={{ color: "warning.main", mr: 1 }} />
|
<WarningRounded sx={{ color: "warning.main", mr: 1 }} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)
|
)
|
||||||
@@ -216,9 +215,13 @@ const SettingSystem = ({ onError }: Props) => {
|
|||||||
}}
|
}}
|
||||||
onGuard={async (e) => {
|
onGuard={async (e) => {
|
||||||
if (isAdminMode) {
|
if (isAdminMode) {
|
||||||
showNotice('info', t("Administrator mode may not support auto launch"), 2000);
|
showNotice(
|
||||||
|
"info",
|
||||||
|
t("Administrator mode may not support auto launch"),
|
||||||
|
2000,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 在应用更改之前先触发UI更新,让用户立即看到反馈
|
// 在应用更改之前先触发UI更新,让用户立即看到反馈
|
||||||
onChangeData({ enable_auto_launch: e });
|
onChangeData({ enable_auto_launch: e });
|
||||||
|
|||||||
@@ -1,29 +1,42 @@
|
|||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { getRunningMode, isAdmin } from "@/services/cmds";
|
import { getRunningMode, isAdmin, isServiceAvailable } from "@/services/cmds";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义 hook 用于获取系统运行状态
|
* 自定义 hook 用于获取系统运行状态
|
||||||
* 包括运行模式和管理员状态
|
* 包括运行模式、管理员状态、系统服务是否可用
|
||||||
*/
|
*/
|
||||||
export function useSystemState() {
|
export function useSystemState() {
|
||||||
// 获取运行模式
|
// 获取运行模式
|
||||||
const { data: runningMode = "Sidecar", mutate: mutateRunningMode } =
|
const { data: runningMode = "Sidecar", mutate: mutateRunningMode } = useSWR(
|
||||||
useSWR("getRunningMode", getRunningMode, {
|
"getRunningMode",
|
||||||
|
getRunningMode,
|
||||||
|
{
|
||||||
suspense: false,
|
suspense: false,
|
||||||
revalidateOnFocus: false
|
revalidateOnFocus: false,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// 获取管理员状态
|
// 获取管理员状态
|
||||||
const { data: isAdminMode = false } =
|
const { data: isAdminMode = false } = useSWR("isAdmin", isAdmin, {
|
||||||
useSWR("isAdmin", isAdmin, {
|
suspense: false,
|
||||||
|
revalidateOnFocus: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取系统服务状态
|
||||||
|
const { data: isServiceOk = false } = useSWR(
|
||||||
|
"isServiceAvailable",
|
||||||
|
isServiceAvailable,
|
||||||
|
{
|
||||||
suspense: false,
|
suspense: false,
|
||||||
revalidateOnFocus: false
|
revalidateOnFocus: false,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
runningMode,
|
runningMode,
|
||||||
isAdminMode,
|
isAdminMode,
|
||||||
isSidecarMode: runningMode === "Sidecar",
|
isSidecarMode: runningMode === "Sidecar",
|
||||||
mutateRunningMode
|
mutateRunningMode,
|
||||||
|
isServiceOk,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,19 +145,19 @@ export async function getAppDir() {
|
|||||||
|
|
||||||
export async function openAppDir() {
|
export async function openAppDir() {
|
||||||
return invoke<void>("open_app_dir").catch((err) =>
|
return invoke<void>("open_app_dir").catch((err) =>
|
||||||
showNotice('error', err?.message || err.toString()),
|
showNotice("error", err?.message || err.toString()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function openCoreDir() {
|
export async function openCoreDir() {
|
||||||
return invoke<void>("open_core_dir").catch((err) =>
|
return invoke<void>("open_core_dir").catch((err) =>
|
||||||
showNotice('error', err?.message || err.toString()),
|
showNotice("error", err?.message || err.toString()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function openLogsDir() {
|
export async function openLogsDir() {
|
||||||
return invoke<void>("open_logs_dir").catch((err) =>
|
return invoke<void>("open_logs_dir").catch((err) =>
|
||||||
showNotice('error', err?.message || err.toString()),
|
showNotice("error", err?.message || err.toString()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ export const openWebUrl = async (url: string) => {
|
|||||||
try {
|
try {
|
||||||
await invoke("open_web_url", { url });
|
await invoke("open_web_url", { url });
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
showNotice('error', err.toString());
|
showNotice("error", err.toString());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ export async function cmdTestDelay(url: string) {
|
|||||||
|
|
||||||
export async function invoke_uwp_tool() {
|
export async function invoke_uwp_tool() {
|
||||||
return invoke<void>("invoke_uwp_tool").catch((err) =>
|
return invoke<void>("invoke_uwp_tool").catch((err) =>
|
||||||
showNotice('error', err?.message || err.toString(), 1500),
|
showNotice("error", err?.message || err.toString(), 1500),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,6 +347,15 @@ export const repairService = async () => {
|
|||||||
return invoke<void>("repair_service");
|
return invoke<void>("repair_service");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 系统服务是否可用
|
||||||
|
export const isServiceAvailable = async () => {
|
||||||
|
try {
|
||||||
|
return await invoke<boolean>("is_service_available");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Service check failed:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
export const entry_lightweight_mode = async () => {
|
export const entry_lightweight_mode = async () => {
|
||||||
return invoke<void>("entry_lightweight_mode");
|
return invoke<void>("entry_lightweight_mode");
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user