mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-15 10:25:40 +00:00
add configurable items for web/gui
enable_exit_node relay_all_peer_rpc multi_thread proxy_forward_by_system relay_network_whitelist manual_routes exit_nodes
This commit is contained in:
@@ -120,6 +120,23 @@ function searchListenerSuggestions(e: { query: string }) {
|
||||
listenerSuggestions.value = ret
|
||||
}
|
||||
|
||||
|
||||
const exitNodesSuggestions = ref([''])
|
||||
|
||||
function searchExitNodesSuggestions(e: { query: string }) {
|
||||
const ret = []
|
||||
ret.push(e.query)
|
||||
exitNodesSuggestions.value = ret
|
||||
}
|
||||
|
||||
const whitelistSuggestions = ref([''])
|
||||
|
||||
function searchWhitelistSuggestions(e: { query: string }) {
|
||||
const ret = []
|
||||
ret.push(e.query)
|
||||
whitelistSuggestions.value = ret
|
||||
}
|
||||
|
||||
interface BoolFlag {
|
||||
field: keyof NetworkConfig
|
||||
help: string
|
||||
@@ -133,6 +150,10 @@ const bool_flags: BoolFlag[] = [
|
||||
{ field: 'disable_p2p', help: 'disable_p2p_help' },
|
||||
{ field: 'bind_device', help: 'bind_device_help' },
|
||||
{ field: 'no_tun', help: 'no_tun_help' },
|
||||
{ field: 'enable_exit_node', help: 'enable_exit_node_help' },
|
||||
{ field: 'relay_all_peer_rpc', help: 'relay_all_peer_rpc_help' },
|
||||
{ field: 'multi_thread', help: 'multi_thread_help' },
|
||||
{ field: 'proxy_forward_by_system', help: 'proxy_forward_by_system_help' },
|
||||
]
|
||||
|
||||
</script>
|
||||
@@ -209,7 +230,7 @@ const bool_flags: BoolFlag[] = [
|
||||
<label> {{ t('flags_switch') }} </label>
|
||||
<div class="flex flex-row flex-wrap">
|
||||
|
||||
<div class="basis-64 flex" v-for="flag in bool_flags">
|
||||
<div class="basis-[20rem] flex items-center" v-for="flag in bool_flags">
|
||||
<Checkbox v-model="curNetwork[flag.field]" :input-id="flag.field" :binary="true" />
|
||||
<label :for="flag.field" class="ml-2"> {{ t(flag.field) }} </label>
|
||||
<span class="pi pi-question-circle ml-2 self-center" v-tooltip="t(flag.help)"></span>
|
||||
@@ -242,17 +263,20 @@ const bool_flags: BoolFlag[] = [
|
||||
<ToggleButton v-model="curNetwork.enable_vpn_portal" on-icon="pi pi-check" off-icon="pi pi-times"
|
||||
:on-label="t('off_text')" :off-label="t('on_text')" class="w-48" />
|
||||
<div v-if="curNetwork.enable_vpn_portal" class="items-center flex flex-row gap-x-4">
|
||||
<div class="min-w-64">
|
||||
<InputGroup>
|
||||
<InputText v-model="curNetwork.vpn_portal_client_network_addr"
|
||||
:placeholder="t('vpn_portal_client_network')" />
|
||||
<InputGroupAddon>
|
||||
<span>/{{ curNetwork.vpn_portal_client_network_len }}</span>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
|
||||
<InputNumber v-model="curNetwork.vpn_portal_listen_port" :allow-empty="false" :format="false"
|
||||
:min="0" :max="65535" class="w-8/12" fluid />
|
||||
<div class="flex flex-row gap-x-9 flex-wrap w-full">
|
||||
<div class="flex flex-col gap-2 basis-8/12 grow">
|
||||
<InputGroup>
|
||||
<InputText v-model="curNetwork.vpn_portal_client_network_addr"
|
||||
:placeholder="t('vpn_portal_client_network')" />
|
||||
<InputGroupAddon>
|
||||
<span>/{{ curNetwork.vpn_portal_client_network_len }}</span>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 basis-3/12 grow">
|
||||
<InputNumber v-model="curNetwork.vpn_portal_listen_port" :allow-empty="false" :format="false"
|
||||
:min="0" :max="65535" fluid />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -283,6 +307,56 @@ const bool_flags: BoolFlag[] = [
|
||||
:placeholder="t('dev_name_placeholder')" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-x-9 flex-wrap">
|
||||
<div class="flex flex-col gap-2 basis-5/12 grow">
|
||||
<div class="flex">
|
||||
<label for="relay_network_whitelist">{{ t('relay_network_whitelist') }}</label>
|
||||
<span class="pi pi-question-circle ml-2 self-center"
|
||||
v-tooltip="t('relay_network_whitelist_help')"></span>
|
||||
</div>
|
||||
<ToggleButton v-model="curNetwork.enable_relay_network_whitelist" on-icon="pi pi-check" off-icon="pi pi-times"
|
||||
:on-label="t('off_text')" :off-label="t('on_text')" class="w-48" />
|
||||
<div v-if="curNetwork.enable_relay_network_whitelist" class="items-center flex flex-row gap-x-4">
|
||||
<div class="min-w-64 w-full">
|
||||
<AutoComplete id="relay_network_whitelist" v-model="curNetwork.relay_network_whitelist"
|
||||
:placeholder="t('relay_network_whitelist')" class="w-full" multiple fluid
|
||||
:suggestions="whitelistSuggestions" @complete="searchWhitelistSuggestions" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-x-9 flex-wrap ">
|
||||
<div class="flex flex-col gap-2 grow">
|
||||
<div class="flex">
|
||||
<label for="routes">{{ t('manual_routes') }}</label>
|
||||
<span class="pi pi-question-circle ml-2 self-center" v-tooltip="t('manual_routes_help')"></span>
|
||||
</div>
|
||||
<ToggleButton v-model="curNetwork.enable_manual_routes" on-icon="pi pi-check" off-icon="pi pi-times"
|
||||
:on-label="t('off_text')" :off-label="t('on_text')" class="w-48" />
|
||||
<div v-if="curNetwork.enable_manual_routes" class="items-center flex flex-row gap-x-4">
|
||||
<div class="min-w-64 w-full">
|
||||
<AutoComplete id="routes" v-model="curNetwork.routes"
|
||||
:placeholder="t('chips_placeholder', ['192.168.0.0/16'])" class="w-full" multiple fluid
|
||||
:suggestions="inetSuggestions" @complete="searchInetSuggestions" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-x-9 flex-wrap w-full">
|
||||
<div class="flex flex-col gap-2 grow p-fluid">
|
||||
<div class="flex">
|
||||
<label for="exit_nodes">{{ t('exit_nodes') }}</label>
|
||||
<span class="pi pi-question-circle ml-2 self-center" v-tooltip="t('exit_nodes_help')"></span>
|
||||
</div>
|
||||
<AutoComplete id="exit_nodes" v-model="curNetwork.exit_nodes"
|
||||
:placeholder="t('chips_placeholder', ['192.168.8.8'])" class="w-full" multiple fluid
|
||||
:suggestions="exitNodesSuggestions" @complete="searchExitNodesSuggestions" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { NetworkInstance, type NodeInfo, type PeerRoutePair } from '../types/net
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { ipv4InetToString, ipv4ToString, ipv6ToString } from '../modules/utils';
|
||||
import { DataTable, Column, Tag, Chip, Button, Dialog, ScrollPanel, Timeline, Divider, Card, } from 'primevue';
|
||||
import { DataTable, Column, Tag, Chip, Button, Dialog, ScrollPanel, Timeline, Divider, Panel, } from 'primevue';
|
||||
|
||||
const props = defineProps<{
|
||||
curNetworkInst: NetworkInstance | null,
|
||||
@@ -318,107 +318,101 @@ function showEventLogs() {
|
||||
</Timeline>
|
||||
</Dialog>
|
||||
|
||||
<Card v-if="curNetworkInst?.error_msg">
|
||||
<template #title>
|
||||
<Panel v-if="curNetworkInst?.error_msg">
|
||||
<template #header>
|
||||
Run Network Error
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="flex flex-col gap-y-5">
|
||||
<div class="text-red-500">
|
||||
{{ curNetworkInst.error_msg }}
|
||||
</div>
|
||||
<div class="flex flex-col gap-y-5">
|
||||
<div class="text-red-500">
|
||||
{{ curNetworkInst.error_msg }}
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<template v-else>
|
||||
<Card>
|
||||
<template #title>
|
||||
<Panel>
|
||||
<template #header>
|
||||
{{ t('my_node_info') }}
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="flex w-full flex-col gap-y-5">
|
||||
<div class="m-0 flex flex-row justify-center gap-x-5">
|
||||
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid green">
|
||||
<div class="font-bold">
|
||||
{{ t('peer_count') }}
|
||||
</div>
|
||||
<div class="text-5xl mt-1">
|
||||
{{ peerCount }}
|
||||
</div>
|
||||
<div class="flex w-full flex-col gap-y-5">
|
||||
<div class="m-0 flex flex-row justify-center gap-x-5">
|
||||
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid green">
|
||||
<div class="font-bold">
|
||||
{{ t('peer_count') }}
|
||||
</div>
|
||||
|
||||
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid purple">
|
||||
<div class="font-bold">
|
||||
{{ t('upload') }}
|
||||
</div>
|
||||
<div class="text-xl mt-2">
|
||||
{{ txRate }}/s
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid fuchsia">
|
||||
<div class="font-bold">
|
||||
{{ t('download') }}
|
||||
</div>
|
||||
<div class="text-xl mt-2">
|
||||
{{ rxRate }}/s
|
||||
</div>
|
||||
<div class="text-5xl mt-1">
|
||||
{{ peerCount }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row items-center flex-wrap w-full max-h-40 overflow-scroll">
|
||||
<Chip v-for="(chip, i) in myNodeInfoChips" :key="i" :label="chip.label" :icon="chip.icon"
|
||||
class="mr-2 mt-2 text-sm" />
|
||||
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid purple">
|
||||
<div class="font-bold">
|
||||
{{ t('upload') }}
|
||||
</div>
|
||||
<div class="text-xl mt-2">
|
||||
{{ txRate }}/s
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="myNodeInfo" class="m-0 flex flex-row justify-center gap-x-5 text-sm">
|
||||
<Button severity="info" :label="t('show_vpn_portal_config')" @click="showVpnPortalConfig" />
|
||||
<Button severity="info" :label="t('show_event_log')" @click="showEventLogs" />
|
||||
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid fuchsia">
|
||||
<div class="font-bold">
|
||||
{{ t('download') }}
|
||||
</div>
|
||||
<div class="text-xl mt-2">
|
||||
{{ rxRate }}/s
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
|
||||
<div class="flex flex-row items-center flex-wrap w-full max-h-40 overflow-scroll">
|
||||
<Chip v-for="(chip, i) in myNodeInfoChips" :key="i" :label="chip.label" :icon="chip.icon"
|
||||
class="mr-2 mt-2 text-sm" />
|
||||
</div>
|
||||
|
||||
<div v-if="myNodeInfo" class="m-0 flex flex-row justify-center gap-x-5 text-sm">
|
||||
<Button severity="info" :label="t('show_vpn_portal_config')" @click="showVpnPortalConfig" />
|
||||
<Button severity="info" :label="t('show_event_log')" @click="showEventLogs" />
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Card>
|
||||
<template #title>
|
||||
<Panel>
|
||||
<template #header>
|
||||
{{ t('peer_info') }}
|
||||
</template>
|
||||
<template #content>
|
||||
<DataTable :value="peerRouteInfos" column-resize-mode="fit" table-class="w-full">
|
||||
<Column :field="ipFormat" :header="t('virtual_ipv4')" />
|
||||
<Column :header="t('hostname')">
|
||||
<template #body="slotProps">
|
||||
<div v-if="!slotProps.data.route.cost || !slotProps.data.route.feature_flag.is_public_server"
|
||||
v-tooltip="slotProps.data.route.hostname">
|
||||
{{
|
||||
slotProps.data.route.hostname }}
|
||||
</div>
|
||||
<div v-else v-tooltip="slotProps.data.route.hostname" class="space-x-1">
|
||||
<Tag v-if="slotProps.data.route.feature_flag.is_public_server" severity="info" value="Info">
|
||||
{{ t('status.server') }}
|
||||
</Tag>
|
||||
<Tag v-if="slotProps.data.route.feature_flag.avoid_relay_data" severity="warn" value="Warn">
|
||||
{{ t('status.relay') }}
|
||||
</Tag>
|
||||
</div>
|
||||
</template>
|
||||
</Column>
|
||||
<Column :field="routeCost" :header="t('route_cost')" />
|
||||
<Column :field="latencyMs" :header="t('latency')" />
|
||||
<Column :field="txBytes" :header="t('upload_bytes')" />
|
||||
<Column :field="rxBytes" :header="t('download_bytes')" />
|
||||
<Column :field="lossRate" :header="t('loss_rate')" />
|
||||
<Column :header="t('status.version')">
|
||||
<template #body="slotProps">
|
||||
<span>{{ version(slotProps.data) }}</span>
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
</template>
|
||||
</Card>
|
||||
<DataTable :value="peerRouteInfos" column-resize-mode="fit" table-class="w-full">
|
||||
<Column :field="ipFormat" :header="t('virtual_ipv4')" />
|
||||
<Column :header="t('hostname')">
|
||||
<template #body="slotProps">
|
||||
<div v-if="!slotProps.data.route.cost || !slotProps.data.route.feature_flag.is_public_server"
|
||||
v-tooltip="slotProps.data.route.hostname">
|
||||
{{
|
||||
slotProps.data.route.hostname }}
|
||||
</div>
|
||||
<div v-else v-tooltip="slotProps.data.route.hostname" class="space-x-1">
|
||||
<Tag v-if="slotProps.data.route.feature_flag.is_public_server" severity="info" value="Info">
|
||||
{{ t('status.server') }}
|
||||
</Tag>
|
||||
<Tag v-if="slotProps.data.route.feature_flag.avoid_relay_data" severity="warn" value="Warn">
|
||||
{{ t('status.relay') }}
|
||||
</Tag>
|
||||
</div>
|
||||
</template>
|
||||
</Column>
|
||||
<Column :field="routeCost" :header="t('route_cost')" />
|
||||
<Column :field="latencyMs" :header="t('latency')" />
|
||||
<Column :field="txBytes" :header="t('upload_bytes')" />
|
||||
<Column :field="rxBytes" :header="t('download_bytes')" />
|
||||
<Column :field="lossRate" :header="t('loss_rate')" />
|
||||
<Column :header="t('status.version')">
|
||||
<template #body="slotProps">
|
||||
<span>{{ version(slotProps.data) }}</span>
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
</Panel>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user