mirror of
https://github.com/EasyTier/EasyTier.git
synced 2024-11-16 11:42:27 +08:00
Perf/optimize details (#106)
* 🎈 perf: details * 🎈 perf: optimize Style
This commit is contained in:
parent
65ac991d1c
commit
a5637003ad
|
@ -13,6 +13,7 @@ enable_vpn_portal: 启用VPN门户
|
|||
vpn_portal_listen_port: 监听端口
|
||||
vpn_portal_client_network: 客户端子网
|
||||
advanced_settings: 高级设置
|
||||
basic_settings: 基础设置
|
||||
listener_urls: 监听地址
|
||||
rpc_port: RPC端口
|
||||
config_network: 配置网络
|
||||
|
@ -43,7 +44,9 @@ peer_count: 已连接
|
|||
upload: 上传
|
||||
download: 下载
|
||||
show_vpn_portal_config: 显示VPN门户配置
|
||||
vpn_portal_config: VPN门户配置
|
||||
show_event_log: 显示事件日志
|
||||
event_log: 事件日志
|
||||
peer_info: 节点信息
|
||||
hostname: 主机名
|
||||
route_cost: 路由
|
||||
|
@ -54,3 +57,5 @@ loss_rate: 丢包率
|
|||
|
||||
run_network: 运行网络
|
||||
stop_network: 停止网络
|
||||
network_running: 运行中
|
||||
network_stopped: 已停止
|
||||
|
|
|
@ -13,6 +13,7 @@ enable_vpn_portal: Enable VPN Portal
|
|||
vpn_portal_listen_port: VPN Portal Listen Port
|
||||
vpn_portal_client_network: Client Sub Network
|
||||
advanced_settings: Advanced Settings
|
||||
basic_settings: Basic Settings
|
||||
listener_urls: Listener URLs
|
||||
rpc_port: RPC Port
|
||||
config_network: Config Network
|
||||
|
@ -43,7 +44,9 @@ peer_count: Connected
|
|||
upload: Upload
|
||||
download: Download
|
||||
show_vpn_portal_config: Show VPN Portal Config
|
||||
vpn_portal_config: VPN Portal Config
|
||||
show_event_log: Show Event Log
|
||||
event_log: Event Log
|
||||
peer_info: Peer Info
|
||||
route_cost: Route Cost
|
||||
hostname: Hostname
|
||||
|
@ -54,3 +57,5 @@ loss_rate: Loss Rate
|
|||
|
||||
run_network: Run Network
|
||||
stop_network: Stop Network
|
||||
network_running: running
|
||||
network_stopped: stopped
|
||||
|
|
|
@ -56,8 +56,8 @@ onMounted(async () => {
|
|||
<template>
|
||||
<div class="flex flex-column h-full">
|
||||
<div class="flex flex-column">
|
||||
<div class="w-10/12 max-w-fit self-center ">
|
||||
<Panel header="Basic Settings">
|
||||
<div class="w-7/12 self-center ">
|
||||
<Panel :header="$t('basic_settings')">
|
||||
<div class="flex flex-column gap-y-2">
|
||||
<div class="flex flex-row gap-x-9 flex-wrap">
|
||||
<div class="flex flex-column gap-2 basis-5/12 grow">
|
||||
|
@ -107,6 +107,22 @@ onMounted(async () => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Panel :header="$t('advanced_settings')" toggleable>
|
||||
<div class="flex flex-column gap-y-2">
|
||||
<div class="flex flex-row gap-x-9 flex-wrap">
|
||||
<div class="flex flex-column gap-2 basis-5/12 grow">
|
||||
<label for="hostname">{{ $t('hostname') }}</label>
|
||||
<InputText
|
||||
id="hostname" v-model="curNetwork.hostname" aria-describedby="hostname-help" :format="true"
|
||||
:placeholder="$t('hostname_placeholder', [osHostname])" @blur="validateHostname"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-x-9 flex-wrap w-full">
|
||||
<div class="flex flex-column gap-2 grow p-fluid">
|
||||
|
@ -144,14 +160,8 @@ onMounted(async () => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Panel :header="$t('advanced_settings')" toggleable>
|
||||
<div class="flex flex-column gap-y-2">
|
||||
<div class="flex flex-row gap-x-9 flex-wrap w-full">
|
||||
<div class="flex flex-row gap-x-9 flex-wrap">
|
||||
<div class="flex flex-column gap-2 grow p-fluid">
|
||||
<label for="listener_urls">{{ $t('listener_urls') }}</label>
|
||||
<Chips
|
||||
|
@ -170,20 +180,9 @@ onMounted(async () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row gap-x-9 flex-wrap">
|
||||
<div class="flex flex-column gap-2 basis-5/12 grow">
|
||||
<label for="hostname">{{ $t('hostname') }}</label>
|
||||
<InputText
|
||||
id="hostname" v-model="curNetwork.hostname" aria-describedby="hostname-help" :format="true"
|
||||
:placeholder="$t('hostname_placeholder', [osHostname])" @blur="validateHostname"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<Divider />
|
||||
|
||||
<div class="flex pt-4 justify-content-center">
|
||||
<Button
|
||||
:label="$t('run_network')" icon="pi pi-arrow-right" icon-pos="right" :disabled="configInvalid"
|
||||
|
|
|
@ -42,7 +42,7 @@ function resolveObjPath(path: string, obj = globalThis, separator = '.') {
|
|||
return properties.reduce((prev, curr) => prev?.[curr], obj)
|
||||
}
|
||||
|
||||
function statsCommon(info: any, field: string) {
|
||||
function statsCommon(info: any, field: string): number | undefined {
|
||||
if (!info.peer)
|
||||
return undefined
|
||||
|
||||
|
@ -73,8 +73,11 @@ function humanFileSize(bytes: number, si = false, dp = 1) {
|
|||
}
|
||||
|
||||
function latencyMs(info: any) {
|
||||
const lat_us_sum = statsCommon(info, 'stats.latency_us')
|
||||
return lat_us_sum ? `${lat_us_sum / 1000 / info.peer.conns.length}ms` : ''
|
||||
let lat_us_sum = statsCommon(info, 'stats.latency_us')
|
||||
if (lat_us_sum === undefined)
|
||||
return ''
|
||||
lat_us_sum = lat_us_sum / 1000 / info.peer.conns.length
|
||||
return `${lat_us_sum % 1 > 0 ? Math.round(lat_us_sum) + 1 : Math.round(lat_us_sum)}ms`
|
||||
}
|
||||
|
||||
function txBytes(info: any) {
|
||||
|
@ -236,6 +239,7 @@ onUnmounted(() => {
|
|||
|
||||
const dialogVisible = ref(false)
|
||||
const dialogContent = ref<any>('')
|
||||
const dialogHeader = ref('event_log')
|
||||
|
||||
function showVpnPortalConfig() {
|
||||
const my_node_info = myNodeInfo.value
|
||||
|
@ -244,6 +248,7 @@ function showVpnPortalConfig() {
|
|||
|
||||
const url = 'https://www.wireguardconfig.com/qrcode'
|
||||
dialogContent.value = `${my_node_info.vpn_portal_cfg}\n\n # can generate QR code: ${url}`
|
||||
dialogHeader.value = 'vpn_portal_config'
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
|
@ -253,13 +258,14 @@ function showEventLogs() {
|
|||
return
|
||||
|
||||
dialogContent.value = detail.events
|
||||
dialogHeader.value = 'event_log'
|
||||
dialogVisible.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Dialog v-model:visible="dialogVisible" modal header="Dialog" :style="{ width: '70%' }">
|
||||
<Dialog v-model:visible="dialogVisible" modal :header="$t(dialogHeader)" :style="{ width: '70%' }">
|
||||
<Panel>
|
||||
<ScrollPanel style="width: 100%; height: 400px">
|
||||
<pre>{{ dialogContent }}</pre>
|
||||
|
@ -267,7 +273,7 @@ function showEventLogs() {
|
|||
</Panel>
|
||||
<Divider />
|
||||
<div class="flex justify-content-end gap-2">
|
||||
<Button type="button" label="Close" @click="dialogVisible = false" />
|
||||
<Button type="button" :label="$t('close')" @click="dialogVisible = false" />
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
|
@ -292,7 +298,7 @@ function showEventLogs() {
|
|||
<div class="flex w-full flex-column gap-y-5">
|
||||
<div class="m-0 flex flex-row justify-center gap-x-5">
|
||||
<div
|
||||
class="rounded-full w-36 h-36 flex flex-column align-items-center pt-4"
|
||||
class="rounded-full w-32 h-32 flex flex-column align-items-center pt-4"
|
||||
style="border: 1px solid green"
|
||||
>
|
||||
<div class="font-bold">
|
||||
|
@ -304,7 +310,7 @@ function showEventLogs() {
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="rounded-full w-36 h-36 flex flex-column align-items-center pt-4"
|
||||
class="rounded-full w-32 h-32 flex flex-column align-items-center pt-4"
|
||||
style="border: 1px solid purple"
|
||||
>
|
||||
<div class="font-bold">
|
||||
|
@ -316,7 +322,7 @@ function showEventLogs() {
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="rounded-full w-36 h-36 flex flex-column align-items-center pt-4"
|
||||
class="rounded-full w-32 h-32 flex flex-column align-items-center pt-4"
|
||||
style="border: 1px solid fuchsia"
|
||||
>
|
||||
<div class="font-bold">
|
||||
|
@ -353,11 +359,11 @@ function showEventLogs() {
|
|||
<DataTable :value="peerRouteInfos" column-resize-mode="fit" table-style="width: 100%">
|
||||
<Column field="route.ipv4_addr" style="width: 100px;" :header="$t('virtual_ipv4')" />
|
||||
<Column field="route.hostname" style="max-width: 250px;" :header="$t('hostname')" />
|
||||
<Column :field="routeCost" style="width: 60px;" :header="$t('route_cost')" />
|
||||
<Column :field="routeCost" style="width: 100px;" :header="$t('route_cost')" />
|
||||
<Column :field="latencyMs" style="width: 80px;" :header="$t('latency')" />
|
||||
<Column :field="txBytes" style="width: 80px;" :header="$t('upload_bytes')" />
|
||||
<Column :field="rxBytes" style="width: 80px;" :header="$t('download_bytes')" />
|
||||
<Column :field="lossRate" style="width: 60px;" :header="$t('loss_rate')" />
|
||||
<Column :field="lossRate" style="width: 100px;" :header="$t('loss_rate')" />
|
||||
</DataTable>
|
||||
</template>
|
||||
</Card>
|
||||
|
|
|
@ -62,10 +62,6 @@ function addNewNetwork() {
|
|||
networkStore.curNetwork = networkStore.lastNetwork
|
||||
}
|
||||
|
||||
function networkMenuName(network: NetworkConfig) {
|
||||
return `${network.network_name} (${network.instance_id})`
|
||||
}
|
||||
|
||||
networkStore.$subscribe(async () => {
|
||||
networkStore.saveToLocalStorage()
|
||||
try {
|
||||
|
@ -150,6 +146,10 @@ function toggle_setting_menu(event: any) {
|
|||
onMounted(async () => {
|
||||
networkStore.loadFromLocalStorage()
|
||||
})
|
||||
|
||||
function isRunning(id: string) {
|
||||
return networkStore.networkInstanceIds.includes(id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -183,10 +183,38 @@ onMounted(async () => {
|
|||
<template #center>
|
||||
<div class="min-w-80 mr-20">
|
||||
<Dropdown
|
||||
v-model="networkStore.curNetwork" :options="networkStore.networkList"
|
||||
:option-label="networkMenuName" :placeholder="$t('select_network')" :highlight-on-select="true"
|
||||
:checkmark="true" class="w-full md:w-32rem"
|
||||
/>
|
||||
v-model="networkStore.curNetwork" :options="networkStore.networkList" :highlight-on-select="false"
|
||||
:placeholder="$t('select_network')" class="w-full"
|
||||
>
|
||||
<template #value="slotProps">
|
||||
<div class="flex items-start content-center">
|
||||
<div class="mr-3">
|
||||
<span>{{ slotProps.value.network_name }}</span>
|
||||
<span v-if="isRunning(slotProps.value.instance_id)" class="ml-3">
|
||||
{{ slotProps.value.virtual_ipv4 }}
|
||||
</span>
|
||||
</div>
|
||||
<Tag
|
||||
class="my-auto" :severity="isRunning(slotProps.value.instance_id) ? 'success' : 'info'"
|
||||
:value="$t(isRunning(slotProps.value.instance_id) ? 'network_running' : 'network_stopped')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #option="slotProps">
|
||||
<div class="flex flex-col items-start content-center">
|
||||
<div class="flex">
|
||||
<div class="mr-3">
|
||||
{{ $t('network_name') }}: {{ slotProps.option.network_name }}
|
||||
</div>
|
||||
<Tag
|
||||
class="my-auto" :severity="isRunning(slotProps.option.instance_id) ? 'success' : 'info'"
|
||||
:value="$t(isRunning(slotProps.option.instance_id) ? 'network_running' : 'network_stopped')"
|
||||
/>
|
||||
</div>
|
||||
<div>{{ slotProps.option.public_server_url }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -201,7 +229,7 @@ onMounted(async () => {
|
|||
</div>
|
||||
|
||||
<Stepper class="h-full overflow-y-auto" :active-step="activeStep">
|
||||
<StepperPanel :header="$t('config_network')" class="w">
|
||||
<StepperPanel :header="$t('config_network')">
|
||||
<template #content="{ nextCallback }">
|
||||
<Config
|
||||
:instance-id="networkStore.curNetworkId" :config-invalid="messageBarSeverity !== Severity.None"
|
||||
|
@ -233,11 +261,15 @@ onMounted(async () => {
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
<style scoped lang="postcss">
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.p-dropdown :deep(.p-dropdown-panel .p-dropdown-items .p-dropdown-item) {
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -75,20 +75,15 @@ export const useNetworkStore = defineStore('networkStore', {
|
|||
loadFromLocalStorage() {
|
||||
let networkList: NetworkConfig[]
|
||||
|
||||
try {
|
||||
networkList = JSON.parse(localStorage.getItem('networkList') || '[{}]')
|
||||
networkList = networkList.map((cfg) => {
|
||||
return { ...DEFAULT_NETWORK_CONFIG(), ...cfg } as NetworkConfig
|
||||
})
|
||||
// if localStorage default is [{}], instanceId will be undefined
|
||||
networkList = JSON.parse(localStorage.getItem('networkList') || '[]')
|
||||
networkList = networkList.map((cfg) => {
|
||||
return { ...DEFAULT_NETWORK_CONFIG(), ...cfg } as NetworkConfig
|
||||
})
|
||||
|
||||
// prevent a empty list from localStorage, should not happen
|
||||
if (networkList.length === 0) {
|
||||
networkList = [DEFAULT_NETWORK_CONFIG()]
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// prevent a empty list from localStorage, should not happen
|
||||
if (networkList.length === 0)
|
||||
networkList = [DEFAULT_NETWORK_CONFIG()]
|
||||
}
|
||||
|
||||
this.networkList = networkList
|
||||
this.curNetwork = this.networkList[0]
|
||||
|
|
Loading…
Reference in New Issue
Block a user