🏗️ refactor file selection handling and enhance export configuration process

This commit is contained in:
刘嘉伟 2025-02-25 17:09:14 +08:00
parent 7a58500a92
commit 7da8bf025b
8 changed files with 168 additions and 53 deletions

View File

@ -6,6 +6,7 @@ import FrpcProcessService from "../service/FrpcProcessService";
import SystemService from "../service/SystemService";
import moment from "moment";
import ResponseUtils from "../utils/ResponseUtils";
import { dialog } from "electron";
class ConfigController extends BaseController {
private readonly _serverService: ServerService;
@ -70,14 +71,34 @@ class ConfigController extends BaseController {
}
exportConfig(req: ControllerParam) {
this._systemService.openDirectory().then(folder => {
const path = `${folder.filePaths[0]}/frpc-${moment(new Date()).format(
"YYYYMMDDhhmmss"
)}.toml`;
this._serverService.genTomlConfig(path).then(() => {
req.event.reply(req.channel, ResponseUtils.success(path));
dialog
.showOpenDialog({
properties: ["openDirectory"]
})
.then(result => {
if (result.canceled) {
req.event.reply(
req.channel,
ResponseUtils.success({
canceled: true,
path: ""
})
);
} else {
const path = `${result.filePaths[0]}/frpc-${moment(new Date()).format(
"YYYYMMDDhhmmss"
)}.toml`;
this._serverService.genTomlConfig(path).then(() => {
req.event.reply(
req.channel,
ResponseUtils.success({
canceled: false,
path: path
})
);
});
}
});
});
}
}

View File

@ -1,6 +1,8 @@
import SystemService from "../service/SystemService";
import ResponseUtils from "../utils/ResponseUtils";
import PathUtils from "../utils/PathUtils";
import { BrowserWindow, dialog } from "electron";
import BeanFactory from "../core/BeanFactory";
class SystemController {
private readonly _systemService: SystemService;
@ -31,6 +33,33 @@ class SystemController {
req.event.reply(req.channel, ResponseUtils.success());
});
}
selectLocalFile(req: ControllerParam) {
const { name, extensions } = req.args;
if (!extensions || extensions.length === 0) {
req.event.reply(req.channel, ResponseUtils.fail("可选择扩展名不能为空"));
}
const win: BrowserWindow = BeanFactory.getBean("win");
dialog
.showOpenDialog(win, {
properties: ["openFile"],
filters: [{ name: name, extensions: extensions }]
})
.then(result => {
if (result.canceled) {
// todo canceled
ResponseUtils.success({
canceled: true,
path: ""
});
} else {
ResponseUtils.success({
canceled: true,
path: result.filePaths[0]
});
}
});
}
}
export default SystemController;

View File

@ -2,6 +2,7 @@ import { app } from "electron";
class GlobalConstant {
public static ZIP_EXT = ".zip";
public static TOML_EXT = ".toml";
public static GZ_EXT = ".gz";
public static TAR_GZ_EXT = ".tar.gz";

View File

@ -102,6 +102,10 @@ export const ipcRouters: IpcRouters = {
openAppData: {
path: "system/openAppData",
controller: "systemController.openAppData"
},
selectLocalFile: {
path: "system/selectLocalFile",
controller: "systemController.selectLocalFile"
}
}
};

View File

@ -1,19 +1,31 @@
import BaseService from "./BaseService";
import ServerRepository from "../repository/ServerRepository";
import TOML from "smol-toml";
import fs from "fs";
import PathUtils from "../utils/PathUtils";
import ProxyRepository from "../repository/ProxyRepository";
import SystemService from "./SystemService";
import { BrowserWindow, dialog } from "electron";
import BeanFactory from "../core/BeanFactory";
import path from "path";
import GlobalConstant from "../core/GlobalConstant";
import TOML from "smol-toml";
class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
private readonly _serverDao: ServerRepository;
private readonly _proxyDao: ProxyRepository;
// private readonly _systemService: SystemService;
private readonly _serverId: string = "1";
constructor(serverDao: ServerRepository, proxyDao: ProxyRepository) {
constructor(
serverDao: ServerRepository,
proxyDao: ProxyRepository,
// systemService: SystemService
) {
super();
this._serverDao = serverDao;
this._proxyDao = proxyDao;
// this._systemService = systemService;
}
async saveServerConfig(
@ -61,6 +73,29 @@ class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
{ flag: "w" }
);
}
async importTomlConfig() {
const win: BrowserWindow = BeanFactory.getBean("win");
const result = await dialog.showOpenDialog(win, {
properties: ["openFile"],
filters: [
{ name: "Frpc", extensions: ["tar.gz", "zip"] } // 允许选择的文件类型,分开后缀以确保可以选择
]
});
if (result.canceled) {
const filePath = result.filePaths[0];
const fileExtension = path.extname(filePath);
if (fileExtension === GlobalConstant.TOML_EXT) {
const tomlData = fs.readFileSync(filePath, "utf-8");
const sourceConfig = TOML.parse(tomlData);
console.log('1');
// todo Persistent
} else {
throw new Error(`导入失败,暂不支持 ${fileExtension} 格式文件`);
}
return;
}
}
}
export default ServerService;

View File

@ -1,10 +1,9 @@
import { app, dialog, shell } from "electron";
import { app, shell } from "electron";
import GlobalConstant from "../core/GlobalConstant";
import path from "path";
import fs from "fs";
import zlib from "zlib";
import admZip from "adm-zip";
import Component from "../core/annotation/Component";
const tar = require("tar");
@ -108,23 +107,6 @@ class SystemService {
});
}
openFile(name: string, ext: any) {
return dialog.showOpenDialogSync({
properties: ["openFile"],
filters: [
{
name: name,
extensions: ext
}
]
});
}
async openDirectory() {
return await dialog.showOpenDialog({
properties: ["openDirectory"]
});
}
}
export default SystemService;

View File

@ -1,10 +1,26 @@
import { ipcRenderer } from "electron";
export const send = (router: IpcRouter, params?: any) => {
console.log(router, "send.router");
ipcRenderer.send(router.path, params);
};
// export const invoke = (router: IpcRouter, params?: any) => {
// return new Promise((resolve, reject) => {
// ipcRenderer
// .invoke(router.path, params)
// .then((args: ApiResponse<any>) => {
// const { success, data, message } = args;
// if (success) {
// resolve(data);
// } else {
// // reject(new Error(message));
// }
// })
// .catch(err => reject(err));
// });
// };
export const on = (router: IpcRouter, listerHandler: (data: any) => void) => {
ipcRenderer.on(`${router.path}:hook`, (event, args: ApiResponse<any>) => {
const { success, data, message } = args;

View File

@ -186,6 +186,7 @@ const pasteServerConfigBase64 = ref();
const formRef = ref<FormInstance>();
const protocol = ref("frp://");
const currSelectLocalFileType = ref();
const visibles = reactive({
copyServerConfig: false,
@ -264,6 +265,23 @@ onMounted(() => {
});
loading.value--;
});
on(ipcRouters.SYSTEM.selectLocalFile, data => {
switch (currSelectLocalFileType.value) {
case 1:
formData.value.transport.tls.certFile = data as string;
// tlsConfigCertFile = data;
break;
case 2:
formData.value.transport.tls.keyFile = data as string;
break;
case 3:
formData.value.transport.tls.trustedCaFile = data as string;
// formData.value.tlsConfigTrustedCaFile = data as string;
break;
}
})
// ipcRenderer.on("Config.getConfig.hook", (event, args) => {
// const { err, data } = args;
// if (!err) {
@ -362,7 +380,10 @@ onMounted(() => {
});
on(ipcRouters.SERVER.exportConfig, data => {
ElMessageBox.alert(`配置路径:${data}`, `🎉 导出成功`);
const { canceled, path } = data;
if (!canceled) {
ElMessageBox.alert(`配置路径:${path}`, `🎉 导出成功`);
}
// //
// confetti({
// zIndex: 12002,
@ -388,36 +409,42 @@ onMounted(() => {
});
const handleSelectFile = (type: number, ext: string[]) => {
ipcRenderer.invoke("file.selectFile", ext).then(r => {
switch (type) {
case 1:
formData.value.tlsConfigCertFile = r[0];
break;
case 2:
formData.value.tlsConfigKeyFile = r[0];
break;
case 3:
formData.value.tlsConfigTrustedCaFile = r[0];
break;
}
console.log(r);
currSelectLocalFileType.value = type;
send(ipcRouters.SYSTEM.selectLocalFile, {
name: "",
extensions: ext
});
// ipcRenderer.invoke("file.selectFile", ext).then(r => {
// switch (type) {
// case 1:
// formData.value.tlsConfigCertFile = r[0];
// break;
// case 2:
// formData.value.tlsConfigKeyFile = r[0];
// break;
// case 3:
// formData.value.tlsConfigTrustedCaFile = r[0];
// break;
// }
// console.log(r);
// });
};
/**
* 分享配置
*/
const handleCopyServerConfig2Base64 = useDebounceFn(() => {
const shareConfig: ShareLinkConfig = {
serverAddr: formData.value.serverAddr,
serverPort: formData.value.serverPort,
authMethod: formData.value.authMethod,
authToken: formData.value.authToken,
transportHeartbeatInterval: formData.value.transportHeartbeatInterval,
transportHeartbeatTimeout: formData.value.transportHeartbeatTimeout,
user: formData.value.user,
metaToken: formData.value.metaToken
};
// const shareConfig: ShareLinkConfig = {
// serverAddr: formData.value.serverAddr,
// serverPort: formData.value.serverPort,
// authMethod: formData.value.authMethod,
// authToken: formData.value.authToken,
// transportHeartbeatInterval: formData.value.transportHeartbeatInterval,
// transportHeartbeatTimeout: formData.value.transportHeartbeatTimeout,
// user: formData.value.user,
// metaToken: formData.value.metaToken
// };
const { _id, frpcVersion, ...shareConfig } = formData.value;
const base64str = Base64.encode(JSON.stringify(shareConfig));
copyServerConfigBase64.value = protocol.value + base64str;
visibles.copyServerConfig = true;