🔍 防止重复提交
This commit is contained in:
parent
c0519e7a5a
commit
d6fc767077
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {defineComponent, onMounted, onUnmounted, reactive, ref} from "vue";
|
import {defineComponent, onMounted, onUnmounted, reactive, ref} from "vue";
|
||||||
import {ipcRenderer} from "electron";
|
import {ipcRenderer} from "electron";
|
||||||
import {ElMessage, FormInstance, FormRules} from "element-plus";
|
import {ElMessage, ElMessageBox, FormInstance, FormRules} from "element-plus";
|
||||||
import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue";
|
import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue";
|
||||||
import {useDebounceFn} from "@vueuse/core";
|
import {useDebounceFn} from "@vueuse/core";
|
||||||
import {clone} from "@/utils/clone";
|
import {clone} from "@/utils/clone";
|
||||||
@ -80,7 +80,7 @@ const rules = reactive<FormRules>({
|
|||||||
{required: true, message: "请输入多用户令牌", trigger: "blur"}
|
{required: true, message: "请输入多用户令牌", trigger: "blur"}
|
||||||
],
|
],
|
||||||
authMethod: [{required: true, message: "请选择验证方式", trigger: "blur"}],
|
authMethod: [{required: true, message: "请选择验证方式", trigger: "blur"}],
|
||||||
authToken: [{required: true, message: "请输入token值 ", trigger: "blur"}],
|
authToken: [{required: true, message: "请输入 Token 值 ", trigger: "blur"}],
|
||||||
logLevel: [{required: true, message: "请选择日志级别 ", trigger: "blur"}],
|
logLevel: [{required: true, message: "请选择日志级别 ", trigger: "blur"}],
|
||||||
logMaxDays: [{required: true, message: "请输入日志保留天数 ", trigger: "blur"}],
|
logMaxDays: [{required: true, message: "请输入日志保留天数 ", trigger: "blur"}],
|
||||||
tlsConfigEnable: [{required: true, message: "请选择 TLS 状态", trigger: "change"}],
|
tlsConfigEnable: [{required: true, message: "请选择 TLS 状态", trigger: "change"}],
|
||||||
@ -120,6 +120,17 @@ const handleLoadVersions = () => {
|
|||||||
ipcRenderer.send("config.versions");
|
ipcRenderer.send("config.versions");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAuthMethodChange = e => {
|
||||||
|
if (e === 'multiuser') {
|
||||||
|
ElMessageBox.alert("多用户插件需要 Frp版本 >= <span class=\"font-black text-[#5A3DAA]\">v0.31.0</span> 请自行选择正确版本", "提示", {
|
||||||
|
// if you want to disable its autofocus
|
||||||
|
autofocus: false,
|
||||||
|
confirmButtonText: "知道了",
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
ipcRenderer.send("config.getConfig");
|
ipcRenderer.send("config.getConfig");
|
||||||
handleLoadVersions();
|
handleLoadVersions();
|
||||||
@ -184,7 +195,7 @@ onUnmounted(() => {
|
|||||||
:rules="rules"
|
:rules="rules"
|
||||||
label-position="right"
|
label-position="right"
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
label-width="140"
|
label-width="130"
|
||||||
>
|
>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
@ -229,6 +240,23 @@ onUnmounted(() => {
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="服务器地址:" prop="serverAddr">
|
<el-form-item label="服务器地址:" prop="serverAddr">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
Frps服务端地址 <br/> 支持 <span class="font-black text-[#5A3DAA]">域名</span>、<span
|
||||||
|
class="font-black text-[#5A3DAA]">IP</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
服务器地址:
|
||||||
|
</template>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formData.serverAddr"
|
v-model="formData.serverAddr"
|
||||||
placeholder="127.0.0.1"
|
placeholder="127.0.0.1"
|
||||||
@ -249,17 +277,53 @@ onUnmounted(() => {
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="验证方式:" prop="authMethod">
|
<el-form-item label="验证方式:" prop="authMethod">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
width="200"
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">auth.method</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
验证方式:
|
||||||
|
</template>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="formData.authMethod"
|
v-model="formData.authMethod"
|
||||||
placeholder="请选择验证方式"
|
placeholder="请选择验证方式"
|
||||||
|
@change="handleAuthMethodChange"
|
||||||
clearable
|
clearable
|
||||||
>
|
>
|
||||||
<el-option label="token" value="token"></el-option>
|
<el-option label="令牌(token)" value="token"></el-option>
|
||||||
|
<el-option label="多用户" value="multiuser"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24" v-if="formData.authMethod === 'token'">
|
<el-col :span="24" v-if="formData.authMethod === 'token'">
|
||||||
<el-form-item label="token:" prop="authToken">
|
<el-form-item label="令牌:" prop="authToken">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
width="200"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">auth.token</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
令牌:
|
||||||
|
</template>
|
||||||
<el-input
|
<el-input
|
||||||
placeholder="token"
|
placeholder="token"
|
||||||
type="password"
|
type="password"
|
||||||
@ -267,6 +331,56 @@ onUnmounted(() => {
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="12" v-if="formData.authMethod === 'multiuser'">
|
||||||
|
<el-form-item label="用户:" prop="user">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">user</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
用户:
|
||||||
|
</template>
|
||||||
|
<el-input
|
||||||
|
placeholder="请输入用户"
|
||||||
|
v-model="formData.user"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12" v-if="formData.authMethod === 'multiuser'">
|
||||||
|
<el-form-item label="用户令牌:" prop="metaToken">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
width="200"
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">meta_token</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
用户令牌:
|
||||||
|
</template>
|
||||||
|
<el-input
|
||||||
|
placeholder="请输入用户令牌"
|
||||||
|
type="password"
|
||||||
|
v-model="formData.metaToken"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<div class="h2">TSL Config</div>
|
<div class="h2">TSL Config</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -280,7 +394,24 @@ onUnmounted(() => {
|
|||||||
</el-col>
|
</el-col>
|
||||||
<template v-if="formData.tlsConfigEnable">
|
<template v-if="formData.tlsConfigEnable">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="TLS证书文件:" prop="tlsConfigCertFile">
|
<el-form-item label="TLS证书文件:" prop="tlsConfigCertFile" label-width="180">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
width="260"
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">transport.tls.certFile</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
TLS 证书文件:
|
||||||
|
</template>
|
||||||
<el-input
|
<el-input
|
||||||
class="button-input"
|
class="button-input"
|
||||||
v-model="formData.tlsConfigCertFile"
|
v-model="formData.tlsConfigCertFile"
|
||||||
@ -291,7 +422,24 @@ onUnmounted(() => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="TLS密钥文件:" prop="tlsConfigKeyFile">
|
<el-form-item label="TLS密钥文件:" prop="tlsConfigKeyFile" label-width="180">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
width="260"
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">transport.tls.keyFile</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
TLS 密钥文件:
|
||||||
|
</template>
|
||||||
<el-input
|
<el-input
|
||||||
class="button-input"
|
class="button-input"
|
||||||
v-model="formData.tlsConfigKeyFile"
|
v-model="formData.tlsConfigKeyFile"
|
||||||
@ -302,7 +450,24 @@ onUnmounted(() => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="CA证书文件:" prop="tlsConfigTrustedCaFile">
|
<el-form-item label="CA证书文件:" prop="tlsConfigTrustedCaFile" label-width="180">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
width="310"
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">transport.tls.trustedCaFile</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
CA 证书文件:
|
||||||
|
</template>
|
||||||
<el-input
|
<el-input
|
||||||
class="button-input"
|
class="button-input"
|
||||||
v-model="formData.tlsConfigTrustedCaFile"
|
v-model="formData.tlsConfigTrustedCaFile"
|
||||||
@ -313,7 +478,24 @@ onUnmounted(() => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="TLS Server名称:" prop="tlsConfigServerName">
|
<el-form-item label="TLS Server 名称:" prop="tlsConfigServerName" label-width="180">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
width="300"
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">transport.tls.serverName</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
TLS Server 名称:
|
||||||
|
</template>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formData.tlsConfigServerName"
|
v-model="formData.tlsConfigServerName"
|
||||||
placeholder="请输入TLS Server 名称"
|
placeholder="请输入TLS Server 名称"
|
||||||
@ -335,6 +517,23 @@ onUnmounted(() => {
|
|||||||
<template v-if="formData.proxyConfigEnable">
|
<template v-if="formData.proxyConfigEnable">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="代理地址:" prop="proxyConfigProxyUrl">
|
<el-form-item label="代理地址:" prop="proxyConfigProxyUrl">
|
||||||
|
<template #label>
|
||||||
|
<div class="h-full flex items-center mr-1">
|
||||||
|
<el-popover
|
||||||
|
width="300"
|
||||||
|
placement="top"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<template #default>
|
||||||
|
对应参数:<span class="font-black text-[#5A3DAA]">transport.proxyURL</span>
|
||||||
|
</template>
|
||||||
|
<template #reference>
|
||||||
|
<Icon class="text-base" color="#5A3DAA" icon="material-symbols:info"/>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
代理地址:
|
||||||
|
</template>
|
||||||
<el-input v-model="formData.proxyConfigProxyUrl"
|
<el-input v-model="formData.proxyConfigProxyUrl"
|
||||||
placeholder="http://user:pwd@192.168.1.128:8080"/>
|
placeholder="http://user:pwd@192.168.1.128:8080"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -5,6 +5,7 @@ import moment from "moment";
|
|||||||
import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue";
|
import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue";
|
||||||
import {Icon} from "@iconify/vue";
|
import {Icon} from "@iconify/vue";
|
||||||
import {ElMessage} from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
|
import {useDebounceFn} from "@vueuse/core";
|
||||||
|
|
||||||
defineComponent({
|
defineComponent({
|
||||||
name: "Download"
|
name: "Download"
|
||||||
@ -39,21 +40,21 @@ const handleLoadVersions = () => {
|
|||||||
* 下载
|
* 下载
|
||||||
* @param version
|
* @param version
|
||||||
*/
|
*/
|
||||||
const handleDownload = (version: Version) => {
|
const handleDownload = useDebounceFn((version: Version) => {
|
||||||
ipcRenderer.send("github.download", version.id);
|
ipcRenderer.send("github.download", version.id);
|
||||||
downloading.value.set(version.id, 0);
|
downloading.value.set(version.id, 0);
|
||||||
};
|
}, 300);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除下载
|
* 删除下载
|
||||||
* @param version
|
* @param version
|
||||||
*/
|
*/
|
||||||
const handleDeleteVersion = (version: Version) => {
|
const handleDeleteVersion = useDebounceFn((version: Version) => {
|
||||||
ipcRenderer.send("github.deleteVersion", {
|
ipcRenderer.send("github.deleteVersion", {
|
||||||
id: version.id,
|
id: version.id,
|
||||||
absPath: version.absPath
|
absPath: version.absPath
|
||||||
});
|
});
|
||||||
}
|
}, 300);
|
||||||
|
|
||||||
const handleInitDownloadHook = () => {
|
const handleInitDownloadHook = () => {
|
||||||
ipcRenderer.on("Download.frpVersionHook", (event, args) => {
|
ipcRenderer.on("Download.frpVersionHook", (event, args) => {
|
||||||
|
@ -5,6 +5,7 @@ import {ipcRenderer} from "electron";
|
|||||||
import {Icon} from "@iconify/vue";
|
import {Icon} from "@iconify/vue";
|
||||||
import {ElMessageBox} from "element-plus";
|
import {ElMessageBox} from "element-plus";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
import {useDebounceFn} from "@vueuse/core";
|
||||||
|
|
||||||
defineComponent({
|
defineComponent({
|
||||||
name: "Home"
|
name: "Home"
|
||||||
@ -20,13 +21,13 @@ const handleStopFrpc = () => {
|
|||||||
ipcRenderer.send("frpc.stop");
|
ipcRenderer.send("frpc.stop");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleButtonClick = () => {
|
const handleButtonClick = useDebounceFn(() => {
|
||||||
if (running.value) {
|
if (running.value) {
|
||||||
handleStopFrpc();
|
handleStopFrpc();
|
||||||
} else {
|
} else {
|
||||||
handleStartFrpc();
|
handleStartFrpc();
|
||||||
}
|
}
|
||||||
};
|
}, 300);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
@ -95,7 +96,8 @@ onUnmounted(() => {
|
|||||||
<div class="pl-8 h-28 w-52 flex flex-col justify-between">
|
<div class="pl-8 h-28 w-52 flex flex-col justify-between">
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<div class="font-bold text-2xl text-center">
|
<div class="font-bold text-2xl text-center">
|
||||||
<Icon v-if="running" class="text-[#7EC050] inline-block relative top-1" icon="material-symbols:check-circle-rounded" />
|
<Icon v-if="running" class="text-[#7EC050] inline-block relative top-1"
|
||||||
|
icon="material-symbols:check-circle-rounded"/>
|
||||||
<Icon v-else class="text-[#E47470] inline-block relative top-1" icon="material-symbols:error"/>
|
<Icon v-else class="text-[#E47470] inline-block relative top-1" icon="material-symbols:error"/>
|
||||||
Frpc {{ running ? "已启动" : "已断开" }}
|
Frpc {{ running ? "已启动" : "已断开" }}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user