feat: add service uninstall functionality and improve service operation flow

This commit is contained in:
Tunglies
2025-05-13 01:56:19 +08:00
parent 6578cd8c51
commit 1ddbe7c2cc
6 changed files with 100 additions and 19 deletions

View File

@@ -39,6 +39,8 @@
- 更新依赖,替换弃用元素 - 更新依赖,替换弃用元素
- 首页当前节点增加排序功能 - 首页当前节点增加排序功能
- DNS 覆写下增加 Hosts 设置功能 - DNS 覆写下增加 Hosts 设置功能
- 修复服务模式安装后无法立即开启 TUN 模式的问题
- 支持手动卸载服务模式,回退到 Sidecar 模式
#### 优化了: #### 优化了:
- 系统代理 Bypass 设置 - 系统代理 Bypass 设置
@@ -54,6 +56,7 @@
- 重构通知系统 - 重构通知系统
- 使用异步方法重构 UI 启动逻辑,解决启动软件过程中的各种卡死问题 - 使用异步方法重构 UI 启动逻辑,解决启动软件过程中的各种卡死问题
- MacOS 下默认关闭托盘速率显示 - MacOS 下默认关闭托盘速率显示
- 优化服务操作流程,提升系统服务相关操作的稳定性和用户体验
## v2.2.3 ## v2.2.3

View File

@@ -65,6 +65,19 @@ pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<String>>
} }
} }
/// 启动核心
#[tauri::command]
pub async fn start_core() -> CmdResult {
wrap_err!(CoreManager::global().start_core().await)
}
/// 关闭核心
#[tauri::command]
pub async fn stop_core() -> CmdResult {
wrap_err!(CoreManager::global().stop_core().await)
}
/// 重启核心 /// 重启核心
#[tauri::command] #[tauri::command]
pub async fn restart_core() -> CmdResult { pub async fn restart_core() -> CmdResult {

View File

@@ -1,7 +1,6 @@
use super::CmdResult; use super::CmdResult;
use crate::{ use crate::{
core::{service, CoreManager}, core::{service, CoreManager},
feat,
utils::i18n::t, utils::i18n::t,
}; };

View File

@@ -217,8 +217,11 @@ pub fn run() {
cmd::get_portable_flag, cmd::get_portable_flag,
cmd::get_network_interfaces, cmd::get_network_interfaces,
cmd::get_system_hostname, cmd::get_system_hostname,
cmd::restart_core,
cmd::restart_app, cmd::restart_app,
// 内核管理
cmd::start_core,
cmd::stop_core,
cmd::restart_core,
// 启动命令 // 启动命令
cmd::notify_ui_ready, cmd::notify_ui_ready,
cmd::update_ui_stage, cmd::update_ui_stage,

View File

@@ -7,6 +7,7 @@ import {
PauseRounded, PauseRounded,
WarningRounded, WarningRounded,
BuildRounded, BuildRounded,
DeleteForeverRounded,
} from "@mui/icons-material"; } from "@mui/icons-material";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { DialogRef, Switch } from "@/components/base"; import { DialogRef, Switch } from "@/components/base";
@@ -19,8 +20,10 @@ import {
getSystemProxy, getSystemProxy,
getAutotemProxy, getAutotemProxy,
installService, installService,
getAutoLaunchStatus, uninstallService,
restartCore, restartCore,
startCore,
stopCore,
} 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";
@@ -43,8 +46,6 @@ const SettingSystem = ({ onError }: Props) => {
const { isAdminMode, isSidecarMode, mutateRunningMode, isServiceOk } = const { isAdminMode, isSidecarMode, mutateRunningMode, isServiceOk } =
useSystemState(); useSystemState();
console.log("Is service running:", isServiceOk);
// 判断Tun模式是否可用 - 当处于服务模式或管理员模式时可用 // 判断Tun模式是否可用 - 当处于服务模式或管理员模式时可用
const isTunAvailable = isServiceOk || (isSidecarMode && !isAdminMode); const isTunAvailable = isServiceOk || (isSidecarMode && !isAdminMode);
@@ -73,20 +74,59 @@ const SettingSystem = ({ onError }: Props) => {
await mutate("getAutotemProxy"); await mutate("getAutotemProxy");
}; };
// 安装系统服务 // 抽象服务操作逻辑
const onInstallService = useLockFn(async () => { const handleServiceOperation = useLockFn(
async (
{
beforeMsg,
action,
actionMsg,
successMsg,
}: {
beforeMsg: string;
action: () => Promise<void>;
actionMsg: string;
successMsg: string;
}
) => {
try { try {
showNotice("info", t("Installing Service..."), 1000); showNotice("info", t(beforeMsg), 1000);
await installService(); await stopCore();
showNotice("success", t("Service Installed Successfully"), 2000); showNotice("info", t(actionMsg), 1000);
await restartCore(); await action();
showNotice("info", t("Restarting Core"), 1000); showNotice("success", t(successMsg), 2000);
console.log("restartCore"); showNotice("info", t("Starting Core..."), 1000);
// 重新获取运行模式 await startCore();
await mutateRunningMode(); await mutateRunningMode();
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString(), 3000); showNotice("error", err.message || err.toString(), 3000);
try {
showNotice("info", t("Try running core as Sidecar..."), 1000);
await startCore();
await mutateRunningMode();
} catch (e: any) {
showNotice("error", e?.message || e?.toString(), 3000);
} }
}
}
);
// 安装系统服务
const onInstallService = () =>
handleServiceOperation({
beforeMsg: "Stopping Core...",
action: installService,
actionMsg: "Installing Service...",
successMsg: "Service Installed Successfully",
});
// 卸载系统服务
const onUninstallService = () =>
handleServiceOperation({
beforeMsg: "Stopping Core...",
action: uninstallService,
actionMsg: "Uninstalling Service...",
successMsg: "Service Uninstalled Successfully",
}); });
return ( return (
@@ -121,6 +161,21 @@ const SettingSystem = ({ onError }: Props) => {
</Button> </Button>
</Tooltip> </Tooltip>
)} )}
{
isServiceOk && (
<Tooltip title={t("Uninstall Service")}>
<Button
// variant="outlined"
color="secondary"
size="small"
onClick={onUninstallService}
sx={{ mr: 1, minWidth: "32px", p: "4px" }}
>
<DeleteForeverRounded fontSize="small" />
</Button>
</Tooltip>
)
}
</> </>
} }
> >

View File

@@ -131,6 +131,14 @@ export async function changeClashCore(clashCore: string) {
return invoke<string | null>("change_clash_core", { clashCore }); return invoke<string | null>("change_clash_core", { clashCore });
} }
export async function startCore() {
return invoke<void>("start_core");
}
export async function stopCore() {
return invoke<void>("stop_core");
}
export async function restartCore() { export async function restartCore() {
return invoke<void>("restart_core"); return invoke<void>("restart_core");
} }