✨ 增加快捷选择本地端口
This commit is contained in:
parent
80d0b53759
commit
ef1b8c186e
70
electron/api/local.ts
Normal file
70
electron/api/local.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import {ipcMain} from "electron";
|
||||
import log from "electron-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 -tuln';
|
||||
|
||||
ipcMain.on("local.getLocalPorts", async (event, args) => {
|
||||
log.info("开始获取本地端口")
|
||||
// 执行命令
|
||||
exec(command, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
log.error(`getLocalPorts - error ${error.message}`)
|
||||
return;
|
||||
}
|
||||
if (stderr) {
|
||||
log.error(`getLocalPorts - stderr ${stderr}`)
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug(`sc ${stdout}`)
|
||||
let ports = [];
|
||||
if (stdout) {
|
||||
ports = stdout.split('\r\n')
|
||||
.filter(f => f.indexOf('TCP') > 0 || f.indexOf('UDP') > 0)
|
||||
.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);
|
||||
console.log(1)
|
||||
// if (local.indexOf('[') == -1) {
|
||||
// // ipv4
|
||||
// const tmp = cols[1].split(":")
|
||||
// localIP = tmp[0]
|
||||
// localPort = tmp[1]
|
||||
// } else {
|
||||
// // ipv6
|
||||
// console.log(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
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -7,10 +7,10 @@ import {initProxyApi} from "../api/proxy";
|
||||
import {initFrpcApi, startFrpWorkerProcess, stopFrpcProcess} from "../api/frpc";
|
||||
import {initLoggerApi} from "../api/logger";
|
||||
import {initFileApi} from "../api/file";
|
||||
import {initUpdaterApi} from "../api/update";
|
||||
import {getConfig} from "../storage/config";
|
||||
import log from "electron-log";
|
||||
import {initCommonApi} from "../api/common";
|
||||
import {initLocalApi} from "../api/local";
|
||||
// The built directory structure
|
||||
//
|
||||
// ├─┬ dist-electron
|
||||
@ -172,6 +172,7 @@ app.whenReady().then(() => {
|
||||
initLoggerApi();
|
||||
initFileApi();
|
||||
initCommonApi();
|
||||
initLocalApi();
|
||||
// initUpdaterApi(win);
|
||||
})
|
||||
});
|
||||
|
@ -814,20 +814,22 @@ onUnmounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="visibles.copyServerConfig" title="复制链接" width="500">
|
||||
<el-dialog v-model="visibles.copyServerConfig" title="复制链接" width="500" top="5%">
|
||||
<el-alert class="mb-4" title="生成内容包含服务器密钥等内容 请妥善保管 且链接仅在Frpc-Desktop中可用" type="warning"
|
||||
:closable="false"/>
|
||||
<el-input class="h-30" v-model="copyServerConfigBase64" type="textarea" :rows="8"></el-input>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="visibles.pasteServerConfig" title="导入链接" width="500">
|
||||
<el-dialog v-model="visibles.pasteServerConfig" title="导入链接" width="500" top="5%">
|
||||
<el-input class="h-30"
|
||||
v-model="pasteServerConfigBase64"
|
||||
type="textarea" placeholder="frp://......"
|
||||
:rows="8"></el-input>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button plain type="primary" @click="handlePasteServerConfigBase64">导入</el-button>
|
||||
|
||||
<el-button plain type="primary" @click="handlePasteServerConfigBase64">
|
||||
<Icon class="cursor-pointer mr-2" icon="material-symbols:label-important-rounded"/>导 入</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -5,6 +5,7 @@ import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue";
|
||||
import {ElMessage, FormInstance, FormRules} from "element-plus";
|
||||
import {ipcRenderer} from "electron";
|
||||
import {clone} from "@/utils/clone";
|
||||
import {useDebounceFn} from "@vueuse/core";
|
||||
|
||||
defineComponent({
|
||||
name: "Proxy"
|
||||
@ -20,6 +21,12 @@ type Proxy = {
|
||||
customDomains: string[];
|
||||
};
|
||||
|
||||
type LocalPort = {
|
||||
protocol: string;
|
||||
ip: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 代理列表
|
||||
*/
|
||||
@ -29,9 +36,13 @@ const proxys = ref<Array<Proxy>>([]);
|
||||
*/
|
||||
const loading = ref({
|
||||
list: 1,
|
||||
form: 0
|
||||
form: 0,
|
||||
localPorts: 1
|
||||
});
|
||||
|
||||
const localPorts = ref<Array<LocalPort>>([]);
|
||||
const listPortsVisible = ref(false);
|
||||
|
||||
/**
|
||||
* 弹出层属性
|
||||
*/
|
||||
@ -170,6 +181,12 @@ const handleInitHook = () => {
|
||||
ipcRenderer.on("Proxy.updateProxy.hook", (event, args) => {
|
||||
InsertOrUpdateHook("修改成功", 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;
|
||||
@ -216,6 +233,26 @@ const handleOpenUpdate = (proxy: Proxy) => {
|
||||
};
|
||||
};
|
||||
|
||||
const handleLoadLocalPorts = () => {
|
||||
loading.value.localPorts = 1;
|
||||
ipcRenderer.send("local.getLocalPorts")
|
||||
}
|
||||
|
||||
|
||||
const handleSelectLocalPort = useDebounceFn((port: number) => {
|
||||
editForm.value.localPort = port;
|
||||
handleCloseLocalPortDialog();
|
||||
})
|
||||
|
||||
const handleCloseLocalPortDialog = () => {
|
||||
listPortsVisible.value = false;
|
||||
}
|
||||
|
||||
const handleOpenLocalPortDialog = () => {
|
||||
listPortsVisible.value = true;
|
||||
handleLoadLocalPorts();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
handleInitHook();
|
||||
handleLoadProxys();
|
||||
@ -226,6 +263,7 @@ onUnmounted(() => {
|
||||
ipcRenderer.removeAllListeners("Proxy.updateProxy.hook");
|
||||
ipcRenderer.removeAllListeners("Proxy.deleteProxyById.hook");
|
||||
ipcRenderer.removeAllListeners("Proxy.getProxys.hook");
|
||||
ipcRenderer.removeAllListeners("local.getLocalPorts.hook");
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
@ -330,8 +368,8 @@ onUnmounted(() => {
|
||||
<el-dialog
|
||||
v-model="edit.visible"
|
||||
:title="edit.title"
|
||||
class="w-[400px]"
|
||||
top="30px"
|
||||
width="400"
|
||||
top="5%"
|
||||
>
|
||||
<el-form
|
||||
v-loading="loading.form"
|
||||
@ -357,21 +395,25 @@ onUnmounted(() => {
|
||||
<el-input v-model="editForm.name" placeholder="代理名称"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="内网地址:" prop="localIp">
|
||||
<el-input v-model="editForm.localIp" placeholder="127.0.0.1"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="内网端口:" prop="localPort">
|
||||
<el-input-number
|
||||
placeholder="8080"
|
||||
class="!w-full"
|
||||
class="local-port-input"
|
||||
:min="0"
|
||||
:max="65535"
|
||||
v-model="editForm.localPort"
|
||||
controls-position="right"
|
||||
/>
|
||||
<el-button class="ml-[10px]" plain type="primary" @click="handleOpenLocalPortDialog">
|
||||
<Icon class="cursor-pointer mr-2" icon="material-symbols:bring-your-own-ip-rounded"/>
|
||||
本地端口
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<template v-if="editForm.type === 'tcp' || editForm.type === 'udp'">
|
||||
@ -443,9 +485,12 @@ onUnmounted(() => {
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<div class="w-full flex justify-end">
|
||||
<el-button @click="edit.visible = false">关 闭</el-button>
|
||||
<el-button @click="edit.visible = false">
|
||||
<Icon class="cursor-pointer mr-2" icon="material-symbols:cancel-presentation"/>
|
||||
关 闭</el-button>
|
||||
<el-button plain type="primary" @click="handleSubmit"
|
||||
>保 存
|
||||
><Icon class="cursor-pointer mr-2" icon="material-symbols:save-rounded"/>
|
||||
保 存
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@ -453,6 +498,31 @@ onUnmounted(() => {
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="listPortsVisible"
|
||||
title="本地端口"
|
||||
width="600"
|
||||
top="5%">
|
||||
<el-table :data="localPorts" stripe
|
||||
v-loading="loading.localPorts"
|
||||
border height="400">
|
||||
<el-table-column label="协议" :width="60" prop="protocol"/>
|
||||
<el-table-column label="IP" prop="ip"/>
|
||||
<el-table-column label="端口" :width="80" prop="port"/>
|
||||
<el-table-column label="操作" :width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="text" @click="handleSelectLocalPort(scope.row.port)">
|
||||
<Icon class="cursor-pointer mr-2" icon="material-symbols:gesture-select"/>
|
||||
选择
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- <div class="h-[400px] overflow-y-scroll">-->
|
||||
<!-- -->
|
||||
<!-- </div>-->
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -477,6 +547,10 @@ onUnmounted(() => {
|
||||
width: calc(100% - 115px);
|
||||
}
|
||||
|
||||
.local-port-input {
|
||||
width: calc(100% - 120px);
|
||||
}
|
||||
|
||||
.domain-input-button {
|
||||
background: #5f3bb0;
|
||||
display: flex;
|
||||
|
Loading…
Reference in New Issue
Block a user