🏗️ implement proxy management features and refactor related services
This commit is contained in:
parent
2edbbcb871
commit
9f46ea781d
@ -1,108 +0,0 @@
|
||||
import {ipcMain} from "electron";
|
||||
import { logDebug, logError, logInfo, LogModule, logWarn } from "../utils/log";
|
||||
|
||||
const {exec, spawn} = require("child_process");
|
||||
|
||||
type LocalPort = {
|
||||
protocol: string;
|
||||
ip: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
export const initLocalApi = () => {
|
||||
const command = process.platform === 'win32'
|
||||
? 'netstat -a -n'
|
||||
: 'netstat -an | grep LISTEN';
|
||||
|
||||
ipcMain.on("local.getLocalPorts", async (event, args) => {
|
||||
logInfo(LogModule.APP, "Starting to retrieve local ports");
|
||||
// 执行命令
|
||||
exec(command, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
logError(LogModule.APP, `getLocalPorts - error: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
if (stderr) {
|
||||
logWarn(LogModule.APP, `getLocalPorts - stderr: ${stderr}`);
|
||||
return;
|
||||
}
|
||||
|
||||
logDebug(LogModule.APP, `Command output: ${stdout}`);
|
||||
let ports = [];
|
||||
if (stdout) {
|
||||
if (process.platform === 'win32') {
|
||||
// window
|
||||
ports = stdout.split('\r\n')
|
||||
.filter(f => f.indexOf('TCP') !== -1 || f.indexOf('UDP') !== -1)
|
||||
.map(m => {
|
||||
const cols = m.split(' ')
|
||||
.filter(f => f != '')
|
||||
const local = cols[1]
|
||||
const s = local.lastIndexOf(":")
|
||||
let localIP = local.slice(0, s);
|
||||
let localPort = local.slice(s - local.length + 1);
|
||||
const singe: LocalPort = {
|
||||
protocol: cols[0],
|
||||
ip: localIP,
|
||||
port: localPort
|
||||
}
|
||||
|
||||
return singe;
|
||||
})
|
||||
} else if (process.platform === 'darwin') {
|
||||
// mac
|
||||
ports = stdout.split('\n')
|
||||
.filter(m => {
|
||||
const cols = m.split(' ')
|
||||
.filter(f => f != '')
|
||||
const local = cols[3]
|
||||
return local
|
||||
})
|
||||
.map(m => {
|
||||
const cols = m.split(' ')
|
||||
.filter(f => f != '')
|
||||
const local = cols[3]
|
||||
const s = local.lastIndexOf(".")
|
||||
let localIP = local.slice(0, s);
|
||||
let localPort = local.slice(s - local.length + 1);
|
||||
const singe: LocalPort = {
|
||||
protocol: cols[0],
|
||||
ip: localIP,
|
||||
port: localPort
|
||||
}
|
||||
return singe;
|
||||
})
|
||||
|
||||
} else if (process.platform === 'linux') {
|
||||
ports = stdout.split('\n')
|
||||
.filter(f =>
|
||||
f.indexOf('tcp') !== -1||
|
||||
f.indexOf('tcp6') !== -1||
|
||||
f.indexOf('udp') !== -1 ||
|
||||
f.indexOf('udp6') !== -1
|
||||
).map(m => {
|
||||
const cols = m.split(' ')
|
||||
.filter(f => f != '')
|
||||
const local = cols[3]
|
||||
const s = local.lastIndexOf(":")
|
||||
let localIP = local.slice(0, s);
|
||||
let localPort = local.slice(s - local.length + 1);
|
||||
const singe: LocalPort = {
|
||||
protocol: cols[0],
|
||||
ip: localIP,
|
||||
port: localPort
|
||||
}
|
||||
return singe;
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ports.sort((a, b) => a.port - b.port);
|
||||
|
||||
event.reply("local.getLocalPorts.hook", {
|
||||
data: ports
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
import { ipcMain } from "electron";
|
||||
import {
|
||||
deleteProxyById,
|
||||
getProxyById,
|
||||
insertProxy,
|
||||
listProxy,
|
||||
updateProxyById,
|
||||
updateProxyStatus
|
||||
} from "../storage/proxy";
|
||||
import { reloadFrpcProcess } from "./frpc";
|
||||
import { logError, logInfo, LogModule, logWarn } from "../utils/log";
|
||||
export const initProxyApi = () => {
|
||||
ipcMain.on("proxy.getProxys", async (event, args) => {
|
||||
logInfo(LogModule.APP, "Requesting to get proxies.");
|
||||
listProxy((err, documents) => {
|
||||
if (err) {
|
||||
logError(LogModule.APP, `Error retrieving proxies: ${err.message}`);
|
||||
} else {
|
||||
logInfo(LogModule.APP, "Proxies retrieved successfully.");
|
||||
}
|
||||
event.reply("Proxy.getProxys.hook", {
|
||||
err: err,
|
||||
data: documents
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("proxy.insertProxy", async (event, args) => {
|
||||
delete args["_id"];
|
||||
logInfo(LogModule.APP, "Inserting a new proxy.");
|
||||
insertProxy(args, (err, documents) => {
|
||||
if (err) {
|
||||
logError(LogModule.APP, `Error inserting proxy: ${err.message}`);
|
||||
} else {
|
||||
logInfo(LogModule.APP, "Proxy inserted successfully.");
|
||||
reloadFrpcProcess();
|
||||
}
|
||||
event.reply("Proxy.insertProxy.hook", {
|
||||
err: err,
|
||||
data: documents
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("proxy.deleteProxyById", async (event, args) => {
|
||||
logInfo(LogModule.APP, `Deleting proxy with ID: ${args._id}`);
|
||||
deleteProxyById(args, (err, documents) => {
|
||||
if (err) {
|
||||
logError(LogModule.APP, `Error deleting proxy: ${err.message}`);
|
||||
} else {
|
||||
logInfo(LogModule.APP, "Proxy deleted successfully.");
|
||||
reloadFrpcProcess();
|
||||
}
|
||||
event.reply("Proxy.deleteProxyById.hook", {
|
||||
err: err,
|
||||
data: documents
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("proxy.getProxyById", async (event, args) => {
|
||||
logInfo(LogModule.APP, `Requesting proxy with ID: ${args._id}`);
|
||||
getProxyById(args, (err, documents) => {
|
||||
if (err) {
|
||||
logError(LogModule.APP, `Error retrieving proxy: ${err.message}`);
|
||||
} else {
|
||||
logInfo(LogModule.APP, "Proxy retrieved successfully.");
|
||||
}
|
||||
event.reply("Proxy.getProxyById.hook", {
|
||||
err: err,
|
||||
data: documents
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("proxy.updateProxy", async (event, args) => {
|
||||
if (!args._id) {
|
||||
logWarn(LogModule.APP, "No proxy ID provided for update.");
|
||||
return;
|
||||
}
|
||||
logInfo(LogModule.APP, `Updating proxy with ID: ${args._id}`);
|
||||
updateProxyById(args, (err, documents) => {
|
||||
if (err) {
|
||||
logError(LogModule.APP, `Error updating proxy: ${err.message}`);
|
||||
} else {
|
||||
logInfo(LogModule.APP, "Proxy updated successfully.");
|
||||
reloadFrpcProcess();
|
||||
}
|
||||
event.reply("Proxy.updateProxy.hook", {
|
||||
err: err,
|
||||
data: documents
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("proxy.updateProxyStatus", async (event, args) => {
|
||||
logInfo(LogModule.APP, `Updating status for proxy ID: ${args._id}`);
|
||||
if (!args._id) {
|
||||
logWarn(LogModule.APP, "No proxy ID provided for status update.");
|
||||
return;
|
||||
}
|
||||
updateProxyStatus(args._id, args.status, (err, documents) => {
|
||||
if (err) {
|
||||
logError(LogModule.APP, `Error updating proxy status: ${err.message}`);
|
||||
} else {
|
||||
logInfo(LogModule.APP, "Proxy status updated successfully.");
|
||||
reloadFrpcProcess();
|
||||
}
|
||||
event.reply("Proxy.updateProxyStatus.hook", {
|
||||
err: err,
|
||||
data: documents
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
@ -1,5 +1,17 @@
|
||||
import BaseController from "./BaseController";
|
||||
import FrpcProcessService from "../service/FrpcProcessService";
|
||||
|
||||
class LaunchController extends BaseController {
|
||||
private readonly _frpcProcessService: FrpcProcessService;
|
||||
|
||||
constructor(frpcProcessService: FrpcProcessService) {
|
||||
super();
|
||||
this._frpcProcessService = frpcProcessService;
|
||||
}
|
||||
|
||||
launch(req: ControllerParam) {
|
||||
this._frpcProcessService.startFrpcProcess().then(r => {});
|
||||
}
|
||||
}
|
||||
|
||||
export default LaunchController;
|
@ -1,7 +1,53 @@
|
||||
import BaseController from "./BaseController";
|
||||
import ProxyService from "../service/ProxyService";
|
||||
import { success } from "../utils/response";
|
||||
import ProxyDao from "../dao/ProxyDao";
|
||||
|
||||
class ProxyController extends BaseController {
|
||||
constructor() {
|
||||
private readonly _proxyService: ProxyService;
|
||||
private readonly _proxyDao: ProxyDao;
|
||||
|
||||
constructor(proxyService: ProxyService, proxyDao: ProxyDao) {
|
||||
super();
|
||||
this._proxyService = proxyService;
|
||||
this._proxyDao = proxyDao;
|
||||
}
|
||||
|
||||
createProxy(req: ControllerParam) {
|
||||
this._proxyService.insertProxy(req.args).then(data => {
|
||||
req.event.reply(req.channel, success(data));
|
||||
});
|
||||
}
|
||||
|
||||
modifyProxy(req: ControllerParam) {
|
||||
this._proxyService.updateProxy(req.args).then(data => {
|
||||
req.event.reply(req.channel, success(data));
|
||||
});
|
||||
}
|
||||
|
||||
getAllProxies(req: ControllerParam) {
|
||||
this._proxyDao.findAll().then(data => {
|
||||
req.event.reply(req.channel, success(data));
|
||||
});
|
||||
}
|
||||
|
||||
deleteProxy(req: ControllerParam) {
|
||||
this._proxyService.deleteProxy(req.args).then(data => {
|
||||
req.event.reply(req.channel, success(data));
|
||||
});
|
||||
}
|
||||
|
||||
modifyProxyStatus(req: ControllerParam) {
|
||||
this._proxyDao.updateProxyStatus(req.args.id, req.args.status).then(() => {
|
||||
req.event.reply(req.channel, success());
|
||||
});
|
||||
}
|
||||
|
||||
getLocalPorts(req: ControllerParam) {
|
||||
this._proxyService.getLocalPorts().then(data => {
|
||||
req.event.reply(req.channel, success(data));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ProxyController;
|
||||
|
@ -1,19 +1,23 @@
|
||||
import BaseController from "./BaseController";
|
||||
import ServerService from "../service/ServerService";
|
||||
import { success } from "../utils/response";
|
||||
import FileService from "../service/FileService";
|
||||
import PathUtils from "../utils/PathUtils";
|
||||
|
||||
class ServerController extends BaseController {
|
||||
private readonly _serverService: ServerService;
|
||||
private readonly _fileService: FileService;
|
||||
|
||||
constructor(serverService: ServerService) {
|
||||
constructor(serverService: ServerService, fileService: FileService) {
|
||||
super();
|
||||
this._serverService = serverService;
|
||||
this._fileService = fileService;
|
||||
}
|
||||
|
||||
saveConfig(req: ControllerParam) {
|
||||
this._serverService.saveServerConfig(req.args).then(() => {
|
||||
req.event.reply(req.channel, success());
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
getServerConfig(req: ControllerParam) {
|
||||
@ -21,7 +25,12 @@ class ServerController extends BaseController {
|
||||
this._serverService.getServerConfig().then(data => {
|
||||
req.event.reply(req.channel, success(data));
|
||||
});
|
||||
}
|
||||
|
||||
openAppData(req: ControllerParam) {
|
||||
this._fileService.openLocalPath(PathUtils.getAppData()).then(data => {
|
||||
req.event.reply(req.channel, success(data));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,10 @@ class VersionController extends BaseController {
|
||||
req.event.reply(req.channel, fail());
|
||||
});
|
||||
}
|
||||
|
||||
importLocalFrpcVersion (){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default VersionController;
|
||||
|
@ -9,6 +9,11 @@ import VersionController from "../controller/VersionController";
|
||||
import FileService from "../service/FileService";
|
||||
import VersionDao from "../dao/VersionDao";
|
||||
import GitHubService from "../service/GitHubService";
|
||||
import FrpcProcessService from "../service/FrpcProcessService";
|
||||
import LaunchController from "../controller/LaunchController";
|
||||
import ProxyDao from "../dao/ProxyDao";
|
||||
import ProxyService from "../service/ProxyService";
|
||||
import ProxyController from "../controller/ProxyController";
|
||||
|
||||
export const ipcRouters: IpcRouters = {
|
||||
SERVER: {
|
||||
@ -48,6 +53,38 @@ export const ipcRouters: IpcRouters = {
|
||||
path: "version/deleteDownloadedVersion",
|
||||
controller: "versionController.deleteDownloadedVersion"
|
||||
}
|
||||
},
|
||||
LAUNCH: {
|
||||
launch: {
|
||||
path: "launch/launch",
|
||||
controller: "launchController.launch"
|
||||
}
|
||||
},
|
||||
PROXY: {
|
||||
createProxy: {
|
||||
path: "proxy/createProxy",
|
||||
controller: "proxyController.createProxy"
|
||||
},
|
||||
modifyProxy: {
|
||||
path: "proxy/modifyProxy",
|
||||
controller: "proxyController.modifyProxy"
|
||||
},
|
||||
deleteProxy: {
|
||||
path: "proxy/deleteProxy",
|
||||
controller: "proxyController.deleteProxy"
|
||||
},
|
||||
getAllProxies: {
|
||||
path: "proxy/getAllProxies",
|
||||
controller: "proxyController.getAllProxies"
|
||||
},
|
||||
modifyProxyStatus: {
|
||||
path: "proxy/modifyProxyStatus",
|
||||
controller: "proxyController.modifyProxyStatus"
|
||||
},
|
||||
getLocalPorts: {
|
||||
path: "proxy/getLocalPorts",
|
||||
controller: "proxyController.getLocalPorts"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -70,8 +107,9 @@ class IpcRouterConfigurate {
|
||||
private initializeBeans() {
|
||||
const serverDao = new ServerDao();
|
||||
const versionDao = new VersionDao();
|
||||
const proxyDao = new ProxyDao();
|
||||
const fileService = new FileService();
|
||||
const serverService = new ServerService(serverDao);
|
||||
const serverService = new ServerService(serverDao, proxyDao);
|
||||
const gitHubService = new GitHubService();
|
||||
const versionService = new VersionService(
|
||||
versionDao,
|
||||
@ -79,19 +117,31 @@ class IpcRouterConfigurate {
|
||||
gitHubService
|
||||
);
|
||||
const logService = new LogService(fileService);
|
||||
const serverController = new ServerController(serverService);
|
||||
const frpcProcessService = new FrpcProcessService(
|
||||
serverService,
|
||||
versionDao
|
||||
);
|
||||
const proxyService = new ProxyService(proxyDao);
|
||||
const serverController = new ServerController(serverService, fileService);
|
||||
const versionController = new VersionController(versionService, versionDao);
|
||||
const logController = new LogController(logService);
|
||||
const launchController = new LaunchController(frpcProcessService);
|
||||
const proxyController = new ProxyController(proxyService, proxyDao);
|
||||
|
||||
this._beans.set("serverDao", serverDao);
|
||||
this._beans.set("versionDao", versionDao);
|
||||
this._beans.set("proxyDao", proxyDao);
|
||||
this._beans.set("fileService", fileService);
|
||||
this._beans.set("serverService", serverService);
|
||||
this._beans.set("versionService", versionService);
|
||||
this._beans.set("logService", logService);
|
||||
this._beans.set("proxyService", proxyService);
|
||||
this._beans.set("frpcProcessService", frpcProcessService);
|
||||
this._beans.set("serverController", serverController);
|
||||
this._beans.set("versionController", versionController);
|
||||
this._beans.set("logController", logController);
|
||||
this._beans.set("launchController", launchController);
|
||||
this._beans.set("proxyController", proxyController);
|
||||
}
|
||||
|
||||
/**
|
||||
|
26
electron/dao/ProxyDao.ts
Normal file
26
electron/dao/ProxyDao.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import BaseDao from "./BaseDao";
|
||||
|
||||
class ProxyDao extends BaseDao<FrpcProxy> {
|
||||
constructor() {
|
||||
super("proxy");
|
||||
}
|
||||
|
||||
updateProxyStatus(id: string, status: number): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.db.update(
|
||||
{ _id: id },
|
||||
{ $set: { status: status } },
|
||||
{},
|
||||
(err, numberOfUpdated, upsert) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ProxyDao;
|
@ -12,7 +12,6 @@ import { release } from "node:os";
|
||||
import node_path, { join } from "node:path";
|
||||
import { initGitHubApi } from "../api/github";
|
||||
import { initConfigApi } from "../api/config";
|
||||
import { initProxyApi } from "../api/proxy";
|
||||
import {
|
||||
initFrpcApi,
|
||||
startFrpWorkerProcess,
|
||||
@ -21,7 +20,6 @@ import {
|
||||
import { initFileApi } from "../api/file";
|
||||
import { getConfig } from "../storage/config";
|
||||
import { initCommonApi } from "../api/common";
|
||||
import { initLocalApi } from "../api/local";
|
||||
import { initLog, logError, logInfo, LogModule } from "../utils/log";
|
||||
import { maskSensitiveData } from "../utils/desensitize";
|
||||
import IpcRouterConfigurate from "../core/IpcRouter";
|
||||
@ -201,8 +199,6 @@ app.whenReady().then(() => {
|
||||
initConfigApi(win);
|
||||
logInfo(LogModule.APP, `Config API initialized.`);
|
||||
|
||||
initProxyApi();
|
||||
logInfo(LogModule.APP, `Proxy API initialized.`);
|
||||
|
||||
initFrpcApi();
|
||||
logInfo(LogModule.APP, `FRPC API initialized.`);
|
||||
@ -215,8 +211,6 @@ app.whenReady().then(() => {
|
||||
initCommonApi();
|
||||
logInfo(LogModule.APP, `Common API initialized.`);
|
||||
|
||||
initLocalApi();
|
||||
logInfo(LogModule.APP, `Local API initialized.`);
|
||||
|
||||
// initUpdaterApi(win);
|
||||
logInfo(LogModule.APP, `Updater API initialization skipped.`);
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { shell } from "electron";
|
||||
import { dialog, shell } from "electron";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import zlib from "zlib";
|
||||
import admZip from "adm-zip";
|
||||
import GlobalConstant from "../core/GlobalConstant";
|
||||
|
||||
|
||||
// import tar from "tar";
|
||||
const tar = require("tar");
|
||||
|
||||
@ -28,6 +29,18 @@ class FileService {
|
||||
});
|
||||
}
|
||||
|
||||
openLocalPath(path: string) {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
shell.openPath(path).then(errorMessage => {
|
||||
if (errorMessage) {
|
||||
resolve(false);
|
||||
} else {
|
||||
reject(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
decompressZipFile(zipFilePath: string, targetPath: string) {
|
||||
if (!zipFilePath.endsWith(GlobalConstant.ZIP_EXT)) {
|
||||
throw new Error("The file is not a .zip file");
|
||||
@ -86,6 +99,18 @@ class FileService {
|
||||
// );
|
||||
});
|
||||
}
|
||||
|
||||
selectLocalFile(name: string, path: any) {
|
||||
dialog.showOpenDialogSync({
|
||||
properties: ["openFile"],
|
||||
filters: [
|
||||
{
|
||||
name: name,
|
||||
extensions: path
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default FileService;
|
||||
|
@ -1,13 +1,13 @@
|
||||
import ServerService from "./ServerService";
|
||||
import VersionDao from "../dao/VersionDao";
|
||||
import PathUtils from "../utils/PathUtils";
|
||||
import { frpcProcess } from "../api/frpc";
|
||||
import GlobalConstant from "../core/GlobalConstant";
|
||||
import { Notification } from "electron";
|
||||
import { logDebug, LogModule } from "../utils/log";
|
||||
|
||||
const { exec, spawn } = require("child_process");
|
||||
|
||||
class FrpProcessService {
|
||||
class FrpcProcessService {
|
||||
private readonly _serverService: ServerService;
|
||||
private readonly _versionDao: VersionDao;
|
||||
private _frpcProcess: any;
|
||||
@ -28,6 +28,7 @@ class FrpProcessService {
|
||||
config.frpcVersion
|
||||
);
|
||||
// todo genConfigfile.
|
||||
await this._serverService.genTomlConfig();
|
||||
const configPath = "";
|
||||
const command = `${PathUtils.getFrpcFilename()} -c ${configPath}`;
|
||||
this._frpcProcess = spawn(command, {
|
||||
@ -35,11 +36,11 @@ class FrpProcessService {
|
||||
shell: true
|
||||
});
|
||||
|
||||
frpcProcess.stdout.on("data", data => {
|
||||
// logDebug(LogModule.FRP_CLIENT, `Frpc process output: ${data}`);
|
||||
this._frpcProcess.stdout.on("data", data => {
|
||||
logDebug(LogModule.FRP_CLIENT, `Frpc process output: ${data}`);
|
||||
});
|
||||
|
||||
frpcProcess.stdout.on("error", data => {
|
||||
this._frpcProcess.stdout.on("error", data => {
|
||||
// logError(LogModule.FRP_CLIENT, `Frpc process error: ${data}`);
|
||||
// stopFrpcProcess(() => {});
|
||||
this.stopFrpcProcess();
|
||||
@ -71,4 +72,4 @@ class FrpProcessService {
|
||||
}
|
||||
}
|
||||
|
||||
export default FrpProcessService;
|
||||
export default FrpcProcessService;
|
132
electron/service/ProxyService.ts
Normal file
132
electron/service/ProxyService.ts
Normal file
@ -0,0 +1,132 @@
|
||||
import ProxyDao from "../dao/ProxyDao";
|
||||
|
||||
const { exec, spawn } = require("child_process");
|
||||
|
||||
class ProxyService {
|
||||
private readonly _proxyDao: ProxyDao;
|
||||
|
||||
constructor(proxyDao: ProxyDao) {
|
||||
this._proxyDao = proxyDao;
|
||||
}
|
||||
|
||||
async insertProxy(proxy: FrpcProxy) {
|
||||
return await this._proxyDao.insert(proxy);
|
||||
}
|
||||
|
||||
async updateProxy(proxy: FrpcProxy) {
|
||||
return await this._proxyDao.updateById(proxy._id, proxy);
|
||||
}
|
||||
|
||||
async deleteProxy(proxyId: string) {
|
||||
return await this._proxyDao.deleteById(proxyId);
|
||||
}
|
||||
|
||||
async getLocalPorts(): Promise<Array<LocalPort>> {
|
||||
const command =
|
||||
process.platform === "win32"
|
||||
? "netstat -a -n"
|
||||
: "netstat -an | grep LISTEN";
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(command, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
if (stderr) {
|
||||
reject(stderr);
|
||||
}
|
||||
let ports: Array<LocalPort> = [];
|
||||
if (stdout) {
|
||||
if (process.platform === "win32") {
|
||||
// window
|
||||
ports = stdout
|
||||
.split("\r\n")
|
||||
.filter(f => f.indexOf("TCP") !== -1 || f.indexOf("UDP") !== -1)
|
||||
.map(m => {
|
||||
const cols = m.split(" ").filter(f => f != "");
|
||||
const local = cols[1];
|
||||
const s = local.lastIndexOf(":");
|
||||
let localIP = local.slice(0, s);
|
||||
let localPort = local.slice(s - local.length + 1);
|
||||
const singe: LocalPort = {
|
||||
protocol: cols[0],
|
||||
ip: localIP,
|
||||
port: localPort
|
||||
};
|
||||
|
||||
return singe;
|
||||
});
|
||||
} else if (process.platform === "darwin") {
|
||||
// mac
|
||||
ports = stdout
|
||||
.split("\n")
|
||||
.filter(m => {
|
||||
const cols = m.split(" ").filter(f => f != "");
|
||||
const local = cols[3];
|
||||
return local;
|
||||
})
|
||||
.map(m => {
|
||||
const cols = m.split(" ").filter(f => f != "");
|
||||
const local = cols[3];
|
||||
const s = local.lastIndexOf(".");
|
||||
let localIP = local.slice(0, s);
|
||||
let localPort = local.slice(s - local.length + 1);
|
||||
const singe: LocalPort = {
|
||||
protocol: cols[0],
|
||||
ip: localIP,
|
||||
port: localPort
|
||||
};
|
||||
return singe;
|
||||
});
|
||||
} else if (process.platform === "linux") {
|
||||
ports = stdout
|
||||
.split("\n")
|
||||
.filter(
|
||||
f =>
|
||||
f.indexOf("tcp") !== -1 ||
|
||||
f.indexOf("tcp6") !== -1 ||
|
||||
f.indexOf("udp") !== -1 ||
|
||||
f.indexOf("udp6") !== -1
|
||||
)
|
||||
.map(m => {
|
||||
const cols = m.split(" ").filter(f => f != "");
|
||||
const local = cols[3];
|
||||
const s = local.lastIndexOf(":");
|
||||
let localIP = local.slice(0, s);
|
||||
let localPort = local.slice(s - local.length + 1);
|
||||
const singe: LocalPort = {
|
||||
protocol: cols[0],
|
||||
ip: localIP,
|
||||
port: localPort
|
||||
};
|
||||
return singe;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ports.sort((a, b) => a.port - b.port);
|
||||
|
||||
resolve(ports);
|
||||
});
|
||||
// exec(command, (error, stdout, stderr) => {
|
||||
// if (error) {
|
||||
// logError(LogModule.APP, `getLocalPorts - error: ${error.message}`);
|
||||
// return;
|
||||
// }
|
||||
// if (stderr) {
|
||||
// logWarn(LogModule.APP, `getLocalPorts - stderr: ${stderr}`);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// logDebug(LogModule.APP, `Command output: ${stdout}`);
|
||||
// let ports = [];
|
||||
|
||||
//
|
||||
// event.reply("local.getLocalPorts.hook", {
|
||||
// data: ports
|
||||
// });
|
||||
// });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ProxyService;
|
@ -1,33 +1,68 @@
|
||||
import BaseService from "./BaseService";
|
||||
import ServerDao from "../dao/ServerDao";
|
||||
import TOML from "smol-toml";
|
||||
import fs from "fs";
|
||||
import PathUtils from "../utils/PathUtils";
|
||||
import ProxyDao from "../dao/ProxyDao";
|
||||
|
||||
class ServerService extends BaseService<FrpcDesktopServer> {
|
||||
private readonly _serverDao: ServerDao;
|
||||
constructor(serverDao: ServerDao) {
|
||||
private readonly _proxyDao: ProxyDao;
|
||||
private readonly _serverId: string = "1";
|
||||
|
||||
constructor(serverDao: ServerDao, proxyDao: ProxyDao) {
|
||||
super();
|
||||
this._serverDao = serverDao;
|
||||
this._proxyDao = proxyDao;
|
||||
}
|
||||
|
||||
async saveServerConfig(
|
||||
frpcServer: FrpcDesktopServer
|
||||
): Promise<FrpcDesktopServer> {
|
||||
return await this._serverDao.updateById("1", frpcServer);
|
||||
frpcServer._id = this._serverId;
|
||||
return await this._serverDao.updateById(this._serverId, frpcServer);
|
||||
}
|
||||
|
||||
async getServerConfig(): Promise<FrpcDesktopServer> {
|
||||
return await this._serverDao.findById("1");
|
||||
return await this._serverDao.findById(this._serverId);
|
||||
}
|
||||
|
||||
hasServerConfig(): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._serverDao
|
||||
.exists("1")
|
||||
.exists(this._serverId)
|
||||
.then(r => {
|
||||
resolve(r);
|
||||
})
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
async genTomlConfig() {
|
||||
const server = await this.getServerConfig();
|
||||
const proxies = await this._proxyDao.findAll();
|
||||
const enabledProxies = proxies
|
||||
.filter(f => f.status === 1)
|
||||
.map(proxy => {
|
||||
const { _id, status, ...frpProxyConfig } = proxy;
|
||||
return frpProxyConfig
|
||||
});
|
||||
const { frpcVersion, _id, system, ...commonConfig } = server;
|
||||
const frpcConfig = { ...commonConfig };
|
||||
frpcConfig.log.to = PathUtils.getFrpcLogFilePath();
|
||||
const toml = TOML.stringify({ ...frpcConfig, enabledProxies });
|
||||
fs.writeFile(
|
||||
PathUtils.getTomlConfigFilePath(), // 配置文件目录
|
||||
toml, // 配置文件内容
|
||||
{ flag: "w" },
|
||||
err => {
|
||||
if (err) {
|
||||
} else {
|
||||
// callback(filename);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ServerService;
|
||||
|
@ -4,20 +4,21 @@ import GitHubService from "./GitHubService";
|
||||
import FileService from "./FileService";
|
||||
import frpReleasesJson from "../json/frp-releases.json";
|
||||
import { download } from "electron-dl";
|
||||
import { BrowserWindow } from "electron";
|
||||
import { BrowserWindow, dialog } from "electron";
|
||||
import GlobalConstant from "../core/GlobalConstant";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import SecureUtils from "../utils/SecureUtils";
|
||||
import PathUtils from "../utils/PathUtils";
|
||||
import FileUtils from "../utils/FileUtils";
|
||||
import frpChecksums from "../json/frp_all_sha256_checksums.json";
|
||||
|
||||
class VersionService extends BaseService<FrpcVersion> {
|
||||
private readonly _versionDao: VersionDao;
|
||||
private readonly _fileService: FileService;
|
||||
private readonly _gitHubService: GitHubService;
|
||||
private readonly _currFrpArch: Array<string>;
|
||||
private versions: Array<FrpcVersion> = [];
|
||||
private _versions: Array<FrpcVersion> = [];
|
||||
|
||||
constructor(
|
||||
versionDao: VersionDao,
|
||||
@ -34,7 +35,7 @@ class VersionService extends BaseService<FrpcVersion> {
|
||||
|
||||
downloadFrpVersion(githubReleaseId: number, onProgress: Function) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const version = this.versions.find(
|
||||
const version = this._versions.find(
|
||||
f => f.githubReleaseId === githubReleaseId
|
||||
);
|
||||
if (!version) {
|
||||
@ -133,8 +134,8 @@ class VersionService extends BaseService<FrpcVersion> {
|
||||
.then(async (releases: Array<GithubRelease>) => {
|
||||
const versions: Array<FrpcVersion> =
|
||||
await this.githubRelease2FrpcVersion(releases);
|
||||
// const versions: Array<FrpcVersion> = (this.versions = versions);
|
||||
this.versions = versions;
|
||||
// const _versions: Array<FrpcVersion> = (this._versions = _versions);
|
||||
this._versions = versions;
|
||||
resolve(versions);
|
||||
})
|
||||
.catch(err => reject(err));
|
||||
@ -158,6 +159,10 @@ class VersionService extends BaseService<FrpcVersion> {
|
||||
): Promise<Array<FrpcVersion>> {
|
||||
const allVersions = await this._versionDao.findAll();
|
||||
return releases
|
||||
.filter(release => {
|
||||
// only support toml version.
|
||||
return release.id > 124395282;
|
||||
})
|
||||
.filter(release => {
|
||||
return this.findCurrentArchitectureAsset(release.assets);
|
||||
})
|
||||
@ -197,6 +202,31 @@ class VersionService extends BaseService<FrpcVersion> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async importLocalFrpcVersion(win: BrowserWindow) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getFrpVersionByAssetName(assetName: string) {
|
||||
return this._versions.find(f => f.assetName === assetName);
|
||||
}
|
||||
}
|
||||
|
||||
export default VersionService;
|
||||
|
@ -18,6 +18,12 @@ class FileUtils {
|
||||
hash.update(fileBuffer);
|
||||
return hash.digest("hex");
|
||||
}
|
||||
|
||||
public static mkdir(path: string) {
|
||||
if (!fs.existsSync(path)) {
|
||||
fs.mkdirSync(path, { recursive: true, mode: 0o777 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default FileUtils;
|
||||
|
@ -2,29 +2,61 @@ import SecureUtils from "./SecureUtils";
|
||||
|
||||
import { app } from "electron";
|
||||
import path from "path";
|
||||
import FileUtils from "./FileUtils";
|
||||
|
||||
class PathUtils {
|
||||
public static getDownloadStoragePath() {
|
||||
return path.join(
|
||||
PathUtils.getAppData(),
|
||||
SecureUtils.calculateMD5("download")
|
||||
);
|
||||
const result = path.join(PathUtils.getAppData(), "download");
|
||||
FileUtils.mkdir(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static getVersionStoragePath() {
|
||||
return path.join(
|
||||
const result = path.join(
|
||||
PathUtils.getAppData(),
|
||||
SecureUtils.calculateMD5("frpc")
|
||||
);
|
||||
FileUtils.mkdir(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static getConfigStoragePath() {
|
||||
const result = path.join(
|
||||
PathUtils.getAppData(),
|
||||
// SecureUtils.calculateMD5("config")
|
||||
"config"
|
||||
);
|
||||
FileUtils.mkdir(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static getFrpcFilename() {
|
||||
return SecureUtils.calculateMD5("frpc")
|
||||
return SecureUtils.calculateMD5("frpc");
|
||||
}
|
||||
|
||||
public static getAppData() {
|
||||
return app.getPath("userData");
|
||||
}
|
||||
|
||||
public static getTomlConfigFilePath() {
|
||||
return path.join(
|
||||
PathUtils.getConfigStoragePath(),
|
||||
SecureUtils.calculateMD5("frpc") + ".toml"
|
||||
);
|
||||
}
|
||||
|
||||
public static getFrpcLogStoragePath() {
|
||||
const result = path.join(PathUtils.getAppData(), "log");
|
||||
FileUtils.mkdir(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static getFrpcLogFilePath() {
|
||||
return path.join(
|
||||
PathUtils.getFrpcLogStoragePath(),
|
||||
SecureUtils.calculateMD5("frpc-log") + ".log"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PathUtils;
|
||||
|
@ -85,6 +85,7 @@
|
||||
"snowflakify": "^1.0.5",
|
||||
"tar": "^6.2.0",
|
||||
"unused-filename": "^4.0.1",
|
||||
"uuid": "^10.0.0"
|
||||
"uuid": "^10.0.0",
|
||||
"smol-toml": "^1.3.1"
|
||||
}
|
||||
}
|
||||
|
@ -200,15 +200,12 @@ const handleSubmit = useDebounceFn(() => {
|
||||
if (valid) {
|
||||
loading.value = 1;
|
||||
const data = clone(formData.value);
|
||||
ipcRenderer.send("server/saveConfig", data);
|
||||
send(ipcRouters.SERVER.saveConfig, data);
|
||||
// ipcRenderer.send("server/saveConfig", data);
|
||||
}
|
||||
});
|
||||
}, 300);
|
||||
|
||||
const handleLoadVersions = () => {
|
||||
ipcRenderer.send("config.versions");
|
||||
};
|
||||
|
||||
const handleAuthMethodChange = e => {
|
||||
if (e === "multiuser") {
|
||||
ElMessageBox.alert(
|
||||
@ -242,12 +239,14 @@ const handleLoadSavedConfig = () => {
|
||||
send(ipcRouters.SERVER.getServerConfig);
|
||||
};
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
handleLoadDownloadedVersion();
|
||||
handleLoadSavedConfig();
|
||||
|
||||
on(ipcRouters.SERVER.getServerConfig, data => {
|
||||
console.log("data", data);
|
||||
formData.value = data;
|
||||
loading.value--;
|
||||
});
|
||||
|
||||
@ -256,6 +255,14 @@ onMounted(() => {
|
||||
versions.value = data;
|
||||
// checkAndResetVersion();
|
||||
});
|
||||
|
||||
on(ipcRouters.SERVER.saveConfig, data => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "保存成功"
|
||||
});
|
||||
loading.value--;
|
||||
});
|
||||
// ipcRenderer.send("config.getConfig");
|
||||
// handleLoadVersions();
|
||||
// ipcRenderer.on("Config.getConfig.hook", (event, args) => {
|
||||
|
@ -5,6 +5,8 @@ import { ipcRenderer } from "electron";
|
||||
import { ElMessageBox } from "element-plus";
|
||||
import router from "@/router";
|
||||
import { useDebounceFn, useIntervalFn } from "@vueuse/core";
|
||||
import { send } from "@/utils/ipcUtils";
|
||||
import { ipcRouters } from "../../../electron/core/IpcRouter";
|
||||
|
||||
defineComponent({
|
||||
name: "Home"
|
||||
@ -13,7 +15,8 @@ defineComponent({
|
||||
const running = ref(false);
|
||||
|
||||
const handleStartFrpc = () => {
|
||||
ipcRenderer.send("frpc.start");
|
||||
// ipcRenderer.send("frpc.start");
|
||||
send(ipcRouters.LAUNCH.launch);
|
||||
};
|
||||
|
||||
const handleStopFrpc = () => {
|
||||
|
@ -15,6 +15,8 @@ import { useClipboard, useDebounceFn } from "@vueuse/core";
|
||||
import IconifyIconOffline from "@/components/IconifyIcon/src/iconifyIconOffline";
|
||||
import commonIps from "./commonIp.json";
|
||||
import path from "path";
|
||||
import { on, removeRouterListeners, send } from "@/utils/ipcUtils";
|
||||
import { ipcRouters } from "../../../electron/core/IpcRouter";
|
||||
|
||||
defineComponent({
|
||||
name: "Proxy"
|
||||
@ -23,7 +25,7 @@ defineComponent({
|
||||
/**
|
||||
* 代理列表
|
||||
*/
|
||||
const proxys = ref<Array<Proxy>>([]);
|
||||
const proxys = ref<Array<FrpcProxy>>([]);
|
||||
/**
|
||||
* loading
|
||||
*/
|
||||
@ -44,11 +46,13 @@ const edit = ref({
|
||||
visible: false
|
||||
});
|
||||
|
||||
const defaultForm = ref<Proxy>({
|
||||
const defaultForm: FrpcProxy = {
|
||||
_id: "",
|
||||
hostHeaderRewrite: "",
|
||||
locations: [],
|
||||
name: "",
|
||||
type: "http",
|
||||
localIp: "",
|
||||
localIP: "",
|
||||
localPort: "8080",
|
||||
remotePort: "8080",
|
||||
customDomains: [""],
|
||||
@ -57,7 +61,6 @@ const defaultForm = ref<Proxy>({
|
||||
secretKey: "",
|
||||
bindAddr: "",
|
||||
bindPort: null,
|
||||
status: true,
|
||||
subdomain: "",
|
||||
basicAuth: false,
|
||||
httpUser: "",
|
||||
@ -67,13 +70,14 @@ const defaultForm = ref<Proxy>({
|
||||
https2http: false,
|
||||
https2httpCaFile: "",
|
||||
https2httpKeyFile: "",
|
||||
keepTunnelOpen: false
|
||||
});
|
||||
keepTunnelOpen: false,
|
||||
status: 1
|
||||
};
|
||||
|
||||
/**
|
||||
* 表单内容
|
||||
*/
|
||||
const editForm = ref<Proxy>(defaultForm.value);
|
||||
const editForm = ref<FrpcProxy>(defaultForm);
|
||||
|
||||
/**
|
||||
* 代理类型
|
||||
@ -104,7 +108,7 @@ const editFormRules = reactive<FormRules>({
|
||||
// }
|
||||
],
|
||||
type: [{ required: true, message: "请选择类型", trigger: "blur" }],
|
||||
localIp: [
|
||||
localIP: [
|
||||
{ required: true, message: "请输入内网地址", trigger: "blur" },
|
||||
{
|
||||
pattern: /^[\w-]+(\.[\w-]+)+$/,
|
||||
@ -247,7 +251,7 @@ const handleRangePort = () => {
|
||||
*/
|
||||
const handleSubmit = async () => {
|
||||
if (!editFormRef.value) return;
|
||||
await editFormRef.value.validate(valid => {
|
||||
editFormRef.value.validate(valid => {
|
||||
if (valid) {
|
||||
if (handleRangePort()) {
|
||||
const lc = handleGetPortCount(editForm.value.localPort);
|
||||
@ -278,9 +282,9 @@ const handleSubmit = async () => {
|
||||
loading.value.form = 1;
|
||||
const data = clone(editForm.value);
|
||||
if (data._id) {
|
||||
ipcRenderer.send("proxy.updateProxy", data);
|
||||
send(ipcRouters.PROXY.createProxy, data);
|
||||
} else {
|
||||
ipcRenderer.send("proxy.insertProxy", data);
|
||||
send(ipcRouters.PROXY.modifyProxy, data);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -305,97 +309,25 @@ const handleDeleteDomain = (index: number) => {
|
||||
* 加载代理
|
||||
*/
|
||||
const handleLoadProxys = () => {
|
||||
ipcRenderer.send("proxy.getProxys");
|
||||
send(ipcRouters.PROXY.getAllProxies);
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除代理
|
||||
* @param proxy
|
||||
*/
|
||||
const handleDeleteProxy = (proxy: Proxy) => {
|
||||
ipcRenderer.send("proxy.deleteProxyById", proxy._id);
|
||||
const handleDeleteProxy = (proxy: FrpcProxy) => {
|
||||
send(ipcRouters.PROXY.deleteProxy, proxy._id);
|
||||
// ipcRenderer.send("proxy.deleteProxyById", proxy._id);
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置表单
|
||||
*/
|
||||
const handleResetForm = () => {
|
||||
editForm.value = defaultForm.value;
|
||||
editForm.value = defaultForm;
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化回调
|
||||
*/
|
||||
const handleInitHook = () => {
|
||||
const InsertOrUpdateHook = (message: string, args: any) => {
|
||||
loading.value.form--;
|
||||
const { err } = args;
|
||||
if (!err) {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: message
|
||||
});
|
||||
handleResetForm();
|
||||
handleLoadProxys();
|
||||
edit.value.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
ipcRenderer.on("Proxy.insertProxy.hook", (event, args) => {
|
||||
InsertOrUpdateHook("新增成功", args);
|
||||
});
|
||||
ipcRenderer.on("Proxy.updateProxy.hook", (event, args) => {
|
||||
InsertOrUpdateHook("修改成功", args);
|
||||
});
|
||||
|
||||
ipcRenderer.on("Proxy.updateProxyStatus.hook", (event, args) => {
|
||||
if (args.data > 0) {
|
||||
handleLoadProxys();
|
||||
}
|
||||
console.log("更新结果", args);
|
||||
});
|
||||
|
||||
ipcRenderer.on("local.getLocalPorts.hook", (event, args) => {
|
||||
loading.value.localPorts--;
|
||||
localPorts.value = args.data;
|
||||
console.log("内网端口", localPorts.value);
|
||||
});
|
||||
// ipcRenderer.on("Proxy.updateProxy.hook", (event, args) => {
|
||||
// loading.value.form--;
|
||||
// const { err } = args;
|
||||
// if (!err) {
|
||||
// ElMessage({
|
||||
// type: "success",
|
||||
// message: "修改成功"
|
||||
// });
|
||||
// handleResetForm();
|
||||
// handleLoadProxys();
|
||||
// edit.value.visible = false;
|
||||
// }
|
||||
// });
|
||||
ipcRenderer.on("Proxy.getProxys.hook", (event, args) => {
|
||||
loading.value.list--;
|
||||
const { err, data } = args;
|
||||
if (!err) {
|
||||
data.forEach(f => {
|
||||
if (f.status === null || f.status === undefined) {
|
||||
f.status = true;
|
||||
}
|
||||
});
|
||||
proxys.value = data;
|
||||
}
|
||||
});
|
||||
ipcRenderer.on("Proxy.deleteProxyById.hook", (event, args) => {
|
||||
const { err, data } = args;
|
||||
if (!err) {
|
||||
handleLoadProxys();
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "删除成功"
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleOpenInsert = () => {
|
||||
edit.value = {
|
||||
title: "新增代理",
|
||||
@ -403,10 +335,10 @@ const handleOpenInsert = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const handleOpenUpdate = (proxy: Proxy) => {
|
||||
const handleOpenUpdate = (proxy: FrpcProxy) => {
|
||||
editForm.value = clone(proxy);
|
||||
if (!editForm.value.fallbackTimeoutMs) {
|
||||
editForm.value.fallbackTimeoutMs = defaultForm.value.fallbackTimeoutMs;
|
||||
editForm.value.fallbackTimeoutMs = defaultForm.fallbackTimeoutMs;
|
||||
}
|
||||
edit.value = {
|
||||
title: "修改代理",
|
||||
@ -414,17 +346,17 @@ const handleOpenUpdate = (proxy: Proxy) => {
|
||||
};
|
||||
};
|
||||
|
||||
const handleReversalUpdate = (proxy: Proxy) => {
|
||||
console.log("更新", proxy);
|
||||
ipcRenderer.send("proxy.updateProxyStatus", {
|
||||
_id: proxy._id,
|
||||
status: !proxy.status
|
||||
const handleReversalUpdate = (proxy: FrpcProxy) => {
|
||||
send(ipcRouters.PROXY.modifyProxyStatus, {
|
||||
id: proxy._id,
|
||||
status: proxy.status === 1 ? 0 : 1
|
||||
});
|
||||
};
|
||||
|
||||
const handleLoadLocalPorts = () => {
|
||||
loading.value.localPorts = 1;
|
||||
ipcRenderer.send("local.getLocalPorts");
|
||||
// ipcRenderer.send("local.getLocalPorts");
|
||||
send(ipcRouters.PROXY.getLocalPorts);
|
||||
};
|
||||
|
||||
const handleSelectLocalPort = useDebounceFn((port: number) => {
|
||||
@ -441,7 +373,7 @@ const handleOpenLocalPortDialog = () => {
|
||||
handleLoadLocalPorts();
|
||||
};
|
||||
|
||||
const allowCopyAccessAddress = (proxy: Proxy) => {
|
||||
const allowCopyAccessAddress = (proxy: FrpcProxy) => {
|
||||
if (
|
||||
(proxy.type === "http" || proxy.type === "https") &&
|
||||
(proxy.customDomains.length < 1 || !proxy.customDomains[0])
|
||||
@ -460,7 +392,7 @@ const allowCopyAccessAddress = (proxy: Proxy) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleCopyAccessAddress = (proxy: Proxy) => {
|
||||
const handleCopyAccessAddress = (proxy: FrpcProxy) => {
|
||||
if (
|
||||
(proxy.type === "http" || proxy.type === "https") &&
|
||||
(proxy.customDomains.length < 1 || !proxy.customDomains[0])
|
||||
@ -584,26 +516,79 @@ const handleSelectFile = (type: number, ext: string[]) => {
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
handleInitHook();
|
||||
handleLoadProxys();
|
||||
ipcRenderer.send("config.getConfig");
|
||||
ipcRenderer.on("Config.getConfig.hook", (event, args) => {
|
||||
const { err, data } = args;
|
||||
if (!err) {
|
||||
if (data) {
|
||||
frpcConfig.value = data;
|
||||
}
|
||||
}
|
||||
|
||||
on(ipcRouters.PROXY.getAllProxies, data => {
|
||||
console.log("allProxies", data);
|
||||
loading.value.list--;
|
||||
proxys.value = data;
|
||||
});
|
||||
|
||||
const insertOrUpdateHook = (message: string) => {
|
||||
loading.value.form--;
|
||||
// const { err } = args;
|
||||
// if (!err) {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: message
|
||||
});
|
||||
handleResetForm();
|
||||
handleLoadProxys();
|
||||
edit.value.visible = false;
|
||||
// }
|
||||
};
|
||||
|
||||
on(ipcRouters.PROXY.createProxy, data => {
|
||||
console.log("data", data);
|
||||
insertOrUpdateHook("新增成功");
|
||||
});
|
||||
|
||||
on(ipcRouters.PROXY.modifyProxy, data => {
|
||||
console.log("data", data);
|
||||
insertOrUpdateHook("修改成功");
|
||||
});
|
||||
|
||||
on(ipcRouters.PROXY.deleteProxy, () => {
|
||||
handleLoadProxys();
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "删除成功"
|
||||
});
|
||||
});
|
||||
|
||||
on(ipcRouters.PROXY.modifyProxyStatus, () => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "修改成功"
|
||||
});
|
||||
// handleResetForm();
|
||||
handleLoadProxys();
|
||||
// edit.value.visible = false;
|
||||
});
|
||||
|
||||
on(ipcRouters.PROXY.getLocalPorts, data => {
|
||||
loading.value.localPorts--;
|
||||
localPorts.value = data;
|
||||
});
|
||||
|
||||
// ipcRenderer.send("config.getConfig");
|
||||
// ipcRenderer.on("Config.getConfig.hook", (event, args) => {
|
||||
// const { err, data } = args;
|
||||
// if (!err) {
|
||||
// if (data) {
|
||||
// frpcConfig.value = data;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
ipcRenderer.removeAllListeners("Proxy.insertProxy.hook");
|
||||
ipcRenderer.removeAllListeners("Proxy.updateProxy.hook");
|
||||
ipcRenderer.removeAllListeners("Proxy.updateProxyStatus.hook");
|
||||
ipcRenderer.removeAllListeners("Proxy.deleteProxyById.hook");
|
||||
ipcRenderer.removeAllListeners("Proxy.getProxys.hook");
|
||||
ipcRenderer.removeAllListeners("local.getLocalPorts.hook");
|
||||
removeRouterListeners(ipcRouters.PROXY.createProxy);
|
||||
removeRouterListeners(ipcRouters.PROXY.modifyProxy);
|
||||
removeRouterListeners(ipcRouters.PROXY.deleteProxy);
|
||||
removeRouterListeners(ipcRouters.PROXY.getAllProxies);
|
||||
removeRouterListeners(ipcRouters.PROXY.modifyProxyStatus);
|
||||
removeRouterListeners(ipcRouters.PROXY.getLocalPorts);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
@ -641,7 +626,7 @@ onUnmounted(() => {
|
||||
<span>{{ proxy.name }}</span>
|
||||
</div>
|
||||
<el-tag
|
||||
v-if="!proxy.status"
|
||||
v-if="proxy.status === 0"
|
||||
class="mr-2"
|
||||
type="danger"
|
||||
size="small"
|
||||
@ -741,7 +726,7 @@ onUnmounted(() => {
|
||||
"
|
||||
>
|
||||
<p class="text-[#ADADAD] font-bold">内网地址</p>
|
||||
<p>{{ proxy.localIp }}</p>
|
||||
<p>{{ proxy.localIP }}</p>
|
||||
</div>
|
||||
|
||||
<div class="text-sm text-center" v-if="proxy.type === 'tcp'">
|
||||
@ -919,15 +904,15 @@ onUnmounted(() => {
|
||||
</el-col>
|
||||
<template v-if="!(isStcp || isXtcp || isSudp) || isStcpVisited">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="内网地址:" prop="localIp">
|
||||
<el-form-item label="内网地址:" prop="localIP">
|
||||
<el-autocomplete
|
||||
v-model="editForm.localIp"
|
||||
v-model="editForm.localIP"
|
||||
:fetch-suggestions="handleIpFetchSuggestions"
|
||||
clearable
|
||||
placeholder="127.0.0.1"
|
||||
/>
|
||||
<!-- <el-input-->
|
||||
<!-- v-model="editForm.localIp"-->
|
||||
<!-- v-model="editForm.localIP"-->
|
||||
<!-- placeholder="127.0.0.1"-->
|
||||
<!-- clearable-->
|
||||
<!-- />-->
|
||||
|
2
types/core.d.ts
vendored
2
types/core.d.ts
vendored
@ -31,6 +31,8 @@ enum IpcRouterKeys {
|
||||
SERVER = "SERVER",
|
||||
LOG = "LOG",
|
||||
VERSION = "VERSION",
|
||||
LAUNCH = "LAUNCH",
|
||||
PROXY = "PROXY",
|
||||
}
|
||||
|
||||
type IpcRouters = Record<
|
||||
|
22
types/frp.d.ts
vendored
22
types/frp.d.ts
vendored
@ -58,6 +58,24 @@ interface FrpcProxyConfig {
|
||||
name: string;
|
||||
type: string;
|
||||
localIP: string;
|
||||
localPort: number;
|
||||
remotePort: number;
|
||||
localPort: any;
|
||||
remotePort: any;
|
||||
customDomains: string[];
|
||||
locations: string[];
|
||||
hostHeaderRewrite: string;
|
||||
stcpModel: string;
|
||||
serverName: string;
|
||||
secretKey: string;
|
||||
bindAddr: string;
|
||||
bindPort: number;
|
||||
subdomain: string;
|
||||
basicAuth: boolean;
|
||||
httpUser: string;
|
||||
httpPassword: string;
|
||||
fallbackTo: string;
|
||||
fallbackTimeoutMs: number;
|
||||
https2http: boolean;
|
||||
https2httpCaFile: string;
|
||||
https2httpKeyFile: string;
|
||||
keepTunnelOpen: boolean;
|
||||
}
|
||||
|
14
types/frpc-desktop.d.ts
vendored
14
types/frpc-desktop.d.ts
vendored
@ -2,7 +2,7 @@ type FrpcDesktopProxy = FrpcProxyConfig & {};
|
||||
|
||||
interface BaseEntity {
|
||||
_id: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface FrpcSystemConfiguration {
|
||||
launchAtStartup: boolean;
|
||||
@ -10,9 +10,11 @@ interface FrpcSystemConfiguration {
|
||||
autoConnectOnStartup: boolean;
|
||||
}
|
||||
|
||||
type FrpcDesktopServer = FrpcCommonConfig & {
|
||||
frpcVersion: number;
|
||||
};
|
||||
type FrpcDesktopServer = BaseEntity &
|
||||
FrpcCommonConfig & {
|
||||
frpcVersion: number;
|
||||
system: any;
|
||||
};
|
||||
|
||||
type FrpcVersion = BaseEntity & {
|
||||
githubReleaseId: number;
|
||||
@ -30,4 +32,8 @@ type FrpcVersion = BaseEntity & {
|
||||
|
||||
type OpenSourceFrpcDesktopServer = FrpcDesktopServer & {
|
||||
system: FrpcSystemConfiguration;
|
||||
};
|
||||
|
||||
type FrpcProxy = BaseEntity & FrpcProxyConfig & {
|
||||
status: number; // 0: disable 1: enable
|
||||
};
|
Loading…
Reference in New Issue
Block a user