🏗️ refactor file selection handling to improve response structure and utilize path data in SystemController
This commit is contained in:
parent
1882260096
commit
7515726a71
@ -3,6 +3,8 @@ import VersionService from "../service/VersionService";
|
|||||||
import ResponseUtils from "../utils/ResponseUtils";
|
import ResponseUtils from "../utils/ResponseUtils";
|
||||||
import VersionRepository from "../repository/VersionRepository";
|
import VersionRepository from "../repository/VersionRepository";
|
||||||
import Logger from "../core/Logger";
|
import Logger from "../core/Logger";
|
||||||
|
import { BrowserWindow, dialog } from "electron";
|
||||||
|
import BeanFactory from "../core/BeanFactory";
|
||||||
|
|
||||||
class VersionController extends BaseController {
|
class VersionController extends BaseController {
|
||||||
private readonly _versionService: VersionService;
|
private readonly _versionService: VersionService;
|
||||||
@ -81,15 +83,58 @@ class VersionController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
importLocalFrpcVersion(req: ControllerParam) {
|
importLocalFrpcVersion(req: ControllerParam) {
|
||||||
this._versionService
|
const win: BrowserWindow = BeanFactory.getBean("win");
|
||||||
.importLocalFrpcVersion()
|
dialog
|
||||||
.then(data => {
|
.showOpenDialog(win, {
|
||||||
req.event.reply(req.channel, ResponseUtils.success());
|
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);
|
Logger.error("VersionController.importLocalFrpcVersion", err);
|
||||||
req.event.reply(req.channel, ResponseUtils.fail(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 {
|
||||||
|
//
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
|
||||||
enum ResponseCode {
|
enum ResponseCode {
|
||||||
SUCCESS = "A1000:successful.",
|
SUCCESS = "A1000;successful.",
|
||||||
INTERNAL_ERROR = "B1000:internal error.",
|
INTERNAL_ERROR = "B1000;internal error.",
|
||||||
NOT_CONFIG = "B1001:未配置"
|
NOT_CONFIG = "B1001;未配置",
|
||||||
|
VERSION_EXISTS = "B1002;导入失败,版本已存在",
|
||||||
|
VERSION_ARGS_ERROR = "B1003;所选 frp 架构与操作系统不符",
|
||||||
|
UNKNOWN_VERSION = "B1004;无法识别文件"
|
||||||
}
|
}
|
||||||
|
|
||||||
class BusinessError extends Error {
|
class BusinessError extends Error {
|
||||||
@ -14,7 +17,7 @@ class BusinessError extends Error {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
constructor(bizErrorEnum: ResponseCode) {
|
constructor(bizErrorEnum: ResponseCode) {
|
||||||
const [bizCode, message] = bizErrorEnum.split(":");
|
const [bizCode, message] = bizErrorEnum.split(";");
|
||||||
super(message);
|
super(message);
|
||||||
this._bizCode = bizCode;
|
this._bizCode = bizCode;
|
||||||
this.name = "BusinessError";
|
this.name = "BusinessError";
|
||||||
|
@ -7,12 +7,14 @@ import treeKill from "tree-kill";
|
|||||||
import BeanFactory from "../core/BeanFactory";
|
import BeanFactory from "../core/BeanFactory";
|
||||||
import ResponseUtils from "../utils/ResponseUtils";
|
import ResponseUtils from "../utils/ResponseUtils";
|
||||||
import { BusinessError, ResponseCode } from "../core/BusinessError";
|
import { BusinessError, ResponseCode } from "../core/BusinessError";
|
||||||
|
import Logger from "../core/Logger";
|
||||||
|
|
||||||
class FrpcProcessService {
|
class FrpcProcessService {
|
||||||
private readonly _serverService: ServerService;
|
private readonly _serverService: ServerService;
|
||||||
private readonly _versionDao: VersionRepository;
|
private readonly _versionDao: VersionRepository;
|
||||||
private _frpcProcess: any;
|
private _frpcProcess: any;
|
||||||
private _frpcProcessListener: any;
|
private _frpcProcessListener: any;
|
||||||
|
private _frpcLastStartTime: number = -1;
|
||||||
|
|
||||||
constructor(serverService: ServerService, versionDao: VersionRepository) {
|
constructor(serverService: ServerService, versionDao: VersionRepository) {
|
||||||
this._serverService = serverService;
|
this._serverService = serverService;
|
||||||
@ -42,7 +44,6 @@ class FrpcProcessService {
|
|||||||
const version = await this._versionDao.findByGithubReleaseId(
|
const version = await this._versionDao.findByGithubReleaseId(
|
||||||
config.frpcVersion
|
config.frpcVersion
|
||||||
);
|
);
|
||||||
// todo genConfigfile.
|
|
||||||
const configPath = PathUtils.getTomlConfigFilePath();
|
const configPath = PathUtils.getTomlConfigFilePath();
|
||||||
await this._serverService.genTomlConfig(configPath);
|
await this._serverService.genTomlConfig(configPath);
|
||||||
const command = `./${PathUtils.getFrpcFilename()} -c "${configPath}"`;
|
const command = `./${PathUtils.getFrpcFilename()} -c "${configPath}"`;
|
||||||
@ -50,22 +51,33 @@ class FrpcProcessService {
|
|||||||
cwd: version.localPath,
|
cwd: version.localPath,
|
||||||
shell: true
|
shell: true
|
||||||
});
|
});
|
||||||
|
this._frpcLastStartTime = Date.now();
|
||||||
|
Logger.debug(
|
||||||
|
`FrpcProcessService.startFrpcProcess`,
|
||||||
|
`start command: ${command}`
|
||||||
|
);
|
||||||
this._frpcProcess.stdout.on("data", data => {
|
this._frpcProcess.stdout.on("data", data => {
|
||||||
console.log(`stdout: ${data}`);
|
Logger.debug(`FrpcProcessService.startFrpcProcess`, `stdout: ${data}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._frpcProcess.stderr.on("data", data => {
|
this._frpcProcess.stderr.on("data", data => {
|
||||||
console.error(`stderr: ${data}`);
|
Logger.debug(`FrpcProcessService.startFrpcProcess`, `stderr: ${data}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async stopFrpcProcess() {
|
async stopFrpcProcess() {
|
||||||
if (this._frpcProcess && this.isRunning()) {
|
if (this._frpcProcess && this.isRunning()) {
|
||||||
|
Logger.debug(
|
||||||
|
`FrpcProcessService.stopFrpcProcess`,
|
||||||
|
`pid: ${this._frpcProcess.pid}`
|
||||||
|
);
|
||||||
treeKill(this._frpcProcess.pid, (error: Error) => {
|
treeKill(this._frpcProcess.pid, (error: Error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
throw error;
|
throw error;
|
||||||
} else {
|
} else {
|
||||||
this._frpcProcess = null;
|
this._frpcProcess = null;
|
||||||
|
this._frpcLastStartTime = -1;
|
||||||
|
|
||||||
// clearInterval(this._frpcProcessListener);
|
// clearInterval(this._frpcProcessListener);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -80,12 +92,17 @@ class FrpcProcessService {
|
|||||||
// LogModule.FRP_CLIENT,
|
// LogModule.FRP_CLIENT,
|
||||||
// `Monitoring frpc process status: ${status}, Listener ID: ${frpcStatusListener}`
|
// `Monitoring frpc process status: ${status}, Listener ID: ${frpcStatusListener}`
|
||||||
// );
|
// );
|
||||||
console.log("running", running);
|
Logger.debug(
|
||||||
|
`FrpcProcessService.watchFrpcProcess`,
|
||||||
|
`running: ${running}`
|
||||||
|
);
|
||||||
if (!running) {
|
if (!running) {
|
||||||
new Notification({
|
if (this._frpcLastStartTime !== -1) {
|
||||||
title: app.getName(),
|
new Notification({
|
||||||
body: "Connection lost, please check the logs for details."
|
title: app.getName(),
|
||||||
}).show();
|
body: "Connection lost, please check the logs for details."
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
// logError(
|
// logError(
|
||||||
// LogModule.FRP_CLIENT,
|
// LogModule.FRP_CLIENT,
|
||||||
// "Frpc process status check failed. Connection lost."
|
// "Frpc process status check failed. Connection lost."
|
||||||
|
@ -65,6 +65,8 @@ class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
|
|||||||
const { frpcVersion, _id, system, ...commonConfig } = server;
|
const { frpcVersion, _id, system, ...commonConfig } = server;
|
||||||
const frpcConfig = { ...commonConfig };
|
const frpcConfig = { ...commonConfig };
|
||||||
frpcConfig.log.to = PathUtils.getFrpcLogFilePath();
|
frpcConfig.log.to = PathUtils.getFrpcLogFilePath();
|
||||||
|
frpcConfig.loginFailExit = false;
|
||||||
|
frpcConfig.webServer.addr = "127.0.0.1";
|
||||||
const toml = TOML.stringify({ ...frpcConfig, proxies: enabledProxies });
|
const toml = TOML.stringify({ ...frpcConfig, proxies: enabledProxies });
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
|
@ -3,7 +3,7 @@ import BaseService from "./BaseService";
|
|||||||
import GitHubService from "./GitHubService";
|
import GitHubService from "./GitHubService";
|
||||||
import frpReleasesJson from "../json/frp-releases.json";
|
import frpReleasesJson from "../json/frp-releases.json";
|
||||||
import { download } from "electron-dl";
|
import { download } from "electron-dl";
|
||||||
import { BrowserWindow, dialog } from "electron";
|
import { BrowserWindow } from "electron";
|
||||||
import GlobalConstant from "../core/GlobalConstant";
|
import GlobalConstant from "../core/GlobalConstant";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@ -12,7 +12,7 @@ import PathUtils from "../utils/PathUtils";
|
|||||||
import FileUtils from "../utils/FileUtils";
|
import FileUtils from "../utils/FileUtils";
|
||||||
import frpChecksums from "../json/frp_all_sha256_checksums.json";
|
import frpChecksums from "../json/frp_all_sha256_checksums.json";
|
||||||
import SystemService from "./SystemService";
|
import SystemService from "./SystemService";
|
||||||
import BeanFactory from "../core/BeanFactory";
|
import { BusinessError, ResponseCode } from "../core/BusinessError";
|
||||||
|
|
||||||
class VersionService extends BaseService<FrpcVersion> {
|
class VersionService extends BaseService<FrpcVersion> {
|
||||||
private readonly _versionDao: VersionRepository;
|
private readonly _versionDao: VersionRepository;
|
||||||
@ -165,36 +165,24 @@ class VersionService extends BaseService<FrpcVersion> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async importLocalFrpcVersion() {
|
async importLocalFrpcVersion(filePath: string) {
|
||||||
const win: BrowserWindow = BeanFactory.getBean("win");
|
const checksum = FileUtils.calculateFileChecksum(filePath);
|
||||||
const result = await dialog.showOpenDialog(win, {
|
const frpName = frpChecksums[checksum];
|
||||||
properties: ["openFile"],
|
if (frpName) {
|
||||||
filters: [
|
if (this._currFrpArch.every(item => frpName.includes(item))) {
|
||||||
{ name: "Frpc", extensions: ["tar.gz", "zip"] } // 允许选择的文件类型,分开后缀以确保可以选择
|
const version = this.getFrpVersionByAssetName(frpName);
|
||||||
]
|
const existsVersion = await this._versionDao.findByGithubReleaseId(
|
||||||
});
|
version.githubReleaseId
|
||||||
if (result.canceled) {
|
);
|
||||||
return;
|
if (existsVersion) {
|
||||||
} else {
|
throw new BusinessError(ResponseCode.VERSION_EXISTS);
|
||||||
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 架构与操作系统不符`);
|
|
||||||
}
|
}
|
||||||
|
return this.decompressFrp(version, filePath);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("导入失败,无法识别文件");
|
throw new BusinessError(ResponseCode.VERSION_ARGS_ERROR);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new BusinessError(ResponseCode.UNKNOWN_VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { BusinessError, ResponseCode } from "../core/BusinessError";
|
|||||||
|
|
||||||
class ResponseUtils {
|
class ResponseUtils {
|
||||||
public static success<T>(data?: any, message?: string) {
|
public static success<T>(data?: any, message?: string) {
|
||||||
const [bizCode, message2] = ResponseCode.SUCCESS.split(":");
|
const [bizCode, message2] = ResponseCode.SUCCESS.split(";");
|
||||||
const resp: ApiResponse<T> = {
|
const resp: ApiResponse<T> = {
|
||||||
bizCode: bizCode,
|
bizCode: bizCode,
|
||||||
data: data,
|
data: data,
|
||||||
@ -22,16 +22,16 @@ class ResponseUtils {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
public static fail(err: Error) {
|
public static fail(err: Error) {
|
||||||
let bizCode = "";
|
if (!(err instanceof BusinessError)) {
|
||||||
let message = "";
|
err = new BusinessError(ResponseCode.INTERNAL_ERROR);
|
||||||
if (err instanceof BusinessError) {
|
|
||||||
bizCode = (err as BusinessError).bizCode;
|
|
||||||
message = (err as BusinessError).message;
|
|
||||||
}
|
}
|
||||||
|
const bizCode = (err as BusinessError).bizCode;
|
||||||
|
const message = (err as BusinessError).message;
|
||||||
|
|
||||||
const resp: ApiResponse<any> = {
|
const resp: ApiResponse<any> = {
|
||||||
bizCode: bizCode,
|
bizCode: bizCode,
|
||||||
data: null,
|
data: null,
|
||||||
message: message || "internal error."
|
message: message
|
||||||
};
|
};
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
@ -133,14 +133,34 @@ onMounted(() => {
|
|||||||
handleLoadAllVersions();
|
handleLoadAllVersions();
|
||||||
});
|
});
|
||||||
|
|
||||||
on(ipcRouters.VERSION.importLocalFrpcVersion, () => {
|
on(
|
||||||
loading.value++;
|
ipcRouters.VERSION.importLocalFrpcVersion,
|
||||||
ElMessage({
|
data => {
|
||||||
type: "success",
|
const { canceled } = data;
|
||||||
message: "导入成功"
|
if (!canceled) {
|
||||||
});
|
loading.value++;
|
||||||
handleLoadAllVersions();
|
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 = () => {
|
const handleImportFrp = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user