diff --git a/electron/controller/ConfigController.ts b/electron/controller/ConfigController.ts index c638945..e44cd24 100644 --- a/electron/controller/ConfigController.ts +++ b/electron/controller/ConfigController.ts @@ -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 + }) + ); + }); + } }); - }); } } diff --git a/electron/controller/SystemController.ts b/electron/controller/SystemController.ts index 1721ee9..def4f06 100644 --- a/electron/controller/SystemController.ts +++ b/electron/controller/SystemController.ts @@ -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; diff --git a/electron/core/GlobalConstant.ts b/electron/core/GlobalConstant.ts index a803be9..6c041f5 100644 --- a/electron/core/GlobalConstant.ts +++ b/electron/core/GlobalConstant.ts @@ -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"; diff --git a/electron/core/IpcRouter.ts b/electron/core/IpcRouter.ts index f324eb1..c7275f5 100644 --- a/electron/core/IpcRouter.ts +++ b/electron/core/IpcRouter.ts @@ -102,6 +102,10 @@ export const ipcRouters: IpcRouters = { openAppData: { path: "system/openAppData", controller: "systemController.openAppData" + }, + selectLocalFile: { + path: "system/selectLocalFile", + controller: "systemController.selectLocalFile" } } }; diff --git a/electron/service/ServerService.ts b/electron/service/ServerService.ts index 3b351d5..125a73b 100644 --- a/electron/service/ServerService.ts +++ b/electron/service/ServerService.ts @@ -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 { 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 { { 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; diff --git a/electron/service/SystemService.ts b/electron/service/SystemService.ts index c45e820..a165672 100644 --- a/electron/service/SystemService.ts +++ b/electron/service/SystemService.ts @@ -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; diff --git a/src/utils/ipcUtils.ts b/src/utils/ipcUtils.ts index abfc240..6864861 100644 --- a/src/utils/ipcUtils.ts +++ b/src/utils/ipcUtils.ts @@ -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) => { +// 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) => { const { success, data, message } = args; diff --git a/src/views/config/index.vue b/src/views/config/index.vue index d95c558..c8bebb9 100644 --- a/src/views/config/index.vue +++ b/src/views/config/index.vue @@ -186,6 +186,7 @@ const pasteServerConfigBase64 = ref(); const formRef = ref(); 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;