🏗️ refactor file selection handling to improve response structure and utilize path data in SystemController

This commit is contained in:
刘嘉伟 2025-02-26 11:49:55 +08:00
parent 1882260096
commit 7515726a71
7 changed files with 136 additions and 61 deletions

View File

@ -3,6 +3,8 @@ import VersionService from "../service/VersionService";
import ResponseUtils from "../utils/ResponseUtils";
import VersionRepository from "../repository/VersionRepository";
import Logger from "../core/Logger";
import { BrowserWindow, dialog } from "electron";
import BeanFactory from "../core/BeanFactory";
class VersionController extends BaseController {
private readonly _versionService: VersionService;
@ -81,15 +83,58 @@ class VersionController extends BaseController {
}
importLocalFrpcVersion(req: ControllerParam) {
this._versionService
.importLocalFrpcVersion()
.then(data => {
req.event.reply(req.channel, ResponseUtils.success());
const win: BrowserWindow = BeanFactory.getBean("win");
dialog
.showOpenDialog(win, {
properties: ["openFile"],
filters: [
{ name: "Frpc", extensions: ["tar.gz", "zip"] } // 允许选择的文件类型,分开后缀以确保可以选择
]
})
.catch((err: Error) => {
.then(result => {
if (result.canceled) {
req.event.reply(
req.channel,
ResponseUtils.success({
canceled: true
})
);
return;
} else {
const filePath = result.filePaths[0];
this._versionService
.importLocalFrpcVersion(filePath)
.then(data => {
req.event.reply(
req.channel,
ResponseUtils.success({
canceled: false
})
);
})
.catch((err: Error) => {
Logger.error("VersionController.importLocalFrpcVersion", err);
req.event.reply(req.channel, ResponseUtils.fail(err));
});
}
})
.catch(err => {
Logger.error("VersionController.importLocalFrpcVersion", err);
req.event.reply(req.channel, ResponseUtils.fail(err));
});
// const win: BrowserWindow = BeanFactory.getBean("win");
// const result = await dialog.showOpenDialog(win, {
// properties: ["openFile"],
// filters: [
// { name: "Frpc", extensions: ["tar.gz", "zip"] } // 允许选择的文件类型,分开后缀以确保可以选择
// ]
// });
// if (result.canceled) {
//
// }else {
//
// }
}
}

View File

@ -1,8 +1,11 @@
enum ResponseCode {
SUCCESS = "A1000:successful.",
INTERNAL_ERROR = "B1000:internal error.",
NOT_CONFIG = "B1001:未配置"
SUCCESS = "A1000;successful.",
INTERNAL_ERROR = "B1000;internal error.",
NOT_CONFIG = "B1001;未配置",
VERSION_EXISTS = "B1002;导入失败,版本已存在",
VERSION_ARGS_ERROR = "B1003;所选 frp 架构与操作系统不符",
UNKNOWN_VERSION = "B1004;无法识别文件"
}
class BusinessError extends Error {
@ -14,7 +17,7 @@ class BusinessError extends Error {
// }
constructor(bizErrorEnum: ResponseCode) {
const [bizCode, message] = bizErrorEnum.split(":");
const [bizCode, message] = bizErrorEnum.split(";");
super(message);
this._bizCode = bizCode;
this.name = "BusinessError";

View File

@ -7,12 +7,14 @@ import treeKill from "tree-kill";
import BeanFactory from "../core/BeanFactory";
import ResponseUtils from "../utils/ResponseUtils";
import { BusinessError, ResponseCode } from "../core/BusinessError";
import Logger from "../core/Logger";
class FrpcProcessService {
private readonly _serverService: ServerService;
private readonly _versionDao: VersionRepository;
private _frpcProcess: any;
private _frpcProcessListener: any;
private _frpcLastStartTime: number = -1;
constructor(serverService: ServerService, versionDao: VersionRepository) {
this._serverService = serverService;
@ -42,7 +44,6 @@ class FrpcProcessService {
const version = await this._versionDao.findByGithubReleaseId(
config.frpcVersion
);
// todo genConfigfile.
const configPath = PathUtils.getTomlConfigFilePath();
await this._serverService.genTomlConfig(configPath);
const command = `./${PathUtils.getFrpcFilename()} -c "${configPath}"`;
@ -50,22 +51,33 @@ class FrpcProcessService {
cwd: version.localPath,
shell: true
});
this._frpcLastStartTime = Date.now();
Logger.debug(
`FrpcProcessService.startFrpcProcess`,
`start command: ${command}`
);
this._frpcProcess.stdout.on("data", data => {
console.log(`stdout: ${data}`);
Logger.debug(`FrpcProcessService.startFrpcProcess`, `stdout: ${data}`);
});
this._frpcProcess.stderr.on("data", data => {
console.error(`stderr: ${data}`);
Logger.debug(`FrpcProcessService.startFrpcProcess`, `stderr: ${data}`);
});
}
async stopFrpcProcess() {
if (this._frpcProcess && this.isRunning()) {
Logger.debug(
`FrpcProcessService.stopFrpcProcess`,
`pid: ${this._frpcProcess.pid}`
);
treeKill(this._frpcProcess.pid, (error: Error) => {
if (error) {
throw error;
} else {
this._frpcProcess = null;
this._frpcLastStartTime = -1;
// clearInterval(this._frpcProcessListener);
}
});
@ -80,12 +92,17 @@ class FrpcProcessService {
// LogModule.FRP_CLIENT,
// `Monitoring frpc process status: ${status}, Listener ID: ${frpcStatusListener}`
// );
console.log("running", running);
Logger.debug(
`FrpcProcessService.watchFrpcProcess`,
`running: ${running}`
);
if (!running) {
new Notification({
title: app.getName(),
body: "Connection lost, please check the logs for details."
}).show();
if (this._frpcLastStartTime !== -1) {
new Notification({
title: app.getName(),
body: "Connection lost, please check the logs for details."
}).show();
}
// logError(
// LogModule.FRP_CLIENT,
// "Frpc process status check failed. Connection lost."

View File

@ -65,6 +65,8 @@ class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
const { frpcVersion, _id, system, ...commonConfig } = server;
const frpcConfig = { ...commonConfig };
frpcConfig.log.to = PathUtils.getFrpcLogFilePath();
frpcConfig.loginFailExit = false;
frpcConfig.webServer.addr = "127.0.0.1";
const toml = TOML.stringify({ ...frpcConfig, proxies: enabledProxies });
fs.writeFileSync(

View File

@ -3,7 +3,7 @@ import BaseService from "./BaseService";
import GitHubService from "./GitHubService";
import frpReleasesJson from "../json/frp-releases.json";
import { download } from "electron-dl";
import { BrowserWindow, dialog } from "electron";
import { BrowserWindow } from "electron";
import GlobalConstant from "../core/GlobalConstant";
import path from "path";
import fs from "fs";
@ -12,7 +12,7 @@ import PathUtils from "../utils/PathUtils";
import FileUtils from "../utils/FileUtils";
import frpChecksums from "../json/frp_all_sha256_checksums.json";
import SystemService from "./SystemService";
import BeanFactory from "../core/BeanFactory";
import { BusinessError, ResponseCode } from "../core/BusinessError";
class VersionService extends BaseService<FrpcVersion> {
private readonly _versionDao: VersionRepository;
@ -165,36 +165,24 @@ class VersionService extends BaseService<FrpcVersion> {
return false;
}
async importLocalFrpcVersion() {
const win: BrowserWindow = BeanFactory.getBean("win");
const result = await dialog.showOpenDialog(win, {
properties: ["openFile"],
filters: [
{ name: "Frpc", extensions: ["tar.gz", "zip"] } // 允许选择的文件类型,分开后缀以确保可以选择
]
});
if (result.canceled) {
return;
} else {
const filePath = result.filePaths[0];
const checksum = FileUtils.calculateFileChecksum(filePath);
const frpName = frpChecksums[checksum];
if (frpName) {
if (this._currFrpArch.every(item => frpName.includes(item))) {
const version = this.getFrpVersionByAssetName(frpName);
const existsVersion = await this._versionDao.findByGithubReleaseId(
version.githubReleaseId
);
if (existsVersion) {
throw new Error("导入失败,版本已存在");
}
return this.decompressFrp(version, filePath);
} else {
throw new Error(`导入失败,所选 frp 架构与操作系统不符`);
async importLocalFrpcVersion(filePath: string) {
const checksum = FileUtils.calculateFileChecksum(filePath);
const frpName = frpChecksums[checksum];
if (frpName) {
if (this._currFrpArch.every(item => frpName.includes(item))) {
const version = this.getFrpVersionByAssetName(frpName);
const existsVersion = await this._versionDao.findByGithubReleaseId(
version.githubReleaseId
);
if (existsVersion) {
throw new BusinessError(ResponseCode.VERSION_EXISTS);
}
return this.decompressFrp(version, filePath);
} else {
throw new Error("导入失败,无法识别文件");
throw new BusinessError(ResponseCode.VERSION_ARGS_ERROR);
}
} else {
throw new BusinessError(ResponseCode.UNKNOWN_VERSION);
}
}

View File

@ -2,7 +2,7 @@ import { BusinessError, ResponseCode } from "../core/BusinessError";
class ResponseUtils {
public static success<T>(data?: any, message?: string) {
const [bizCode, message2] = ResponseCode.SUCCESS.split(":");
const [bizCode, message2] = ResponseCode.SUCCESS.split(";");
const resp: ApiResponse<T> = {
bizCode: bizCode,
data: data,
@ -22,16 +22,16 @@ class ResponseUtils {
// }
public static fail(err: Error) {
let bizCode = "";
let message = "";
if (err instanceof BusinessError) {
bizCode = (err as BusinessError).bizCode;
message = (err as BusinessError).message;
if (!(err instanceof BusinessError)) {
err = new BusinessError(ResponseCode.INTERNAL_ERROR);
}
const bizCode = (err as BusinessError).bizCode;
const message = (err as BusinessError).message;
const resp: ApiResponse<any> = {
bizCode: bizCode,
data: null,
message: message || "internal error."
message: message
};
return resp;
}

View File

@ -133,14 +133,34 @@ onMounted(() => {
handleLoadAllVersions();
});
on(ipcRouters.VERSION.importLocalFrpcVersion, () => {
loading.value++;
ElMessage({
type: "success",
message: "导入成功"
});
handleLoadAllVersions();
});
on(
ipcRouters.VERSION.importLocalFrpcVersion,
data => {
const { canceled } = data;
if (!canceled) {
loading.value++;
ElMessage({
type: "success",
message: "导入成功"
});
handleLoadAllVersions();
}
},
(bizCode: string, message: string) => {
if (bizCode === "B1002") {
//
ElMessageBox.alert(`${message}`, `导入失败`);
}
if (bizCode === "B1003") {
// frp
ElMessageBox.alert(`${message}`, `导入失败`);
}
if (bizCode === "B1004") {
//
ElMessageBox.alert(`${message}`, `导入失败`);
}
}
);
});
const handleImportFrp = () => {