feat(ui): make port forward config responsive (#1530)

This commit is contained in:
Mg Pig
2025-10-31 23:23:36 +08:00
committed by GitHub
parent 26d002bc2b
commit 8ab98bba8f
3 changed files with 95 additions and 8 deletions

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import InputGroup from 'primevue/inputgroup'
import InputGroupAddon from 'primevue/inputgroupaddon'
import { SelectButton, Checkbox, InputText, InputNumber, AutoComplete, Panel, Divider, ToggleButton, Button, Password } from 'primevue'
import { SelectButton, Checkbox, InputText, InputNumber, AutoComplete, Panel, Divider, ToggleButton, Button, Password, Dialog } from 'primevue'
import {
addRow,
DEFAULT_NETWORK_CONFIG,
@@ -9,7 +9,7 @@ import {
NetworkingMethod,
removeRow
} from '../types/network'
import { defineProps, defineEmits, ref, } from 'vue'
import { defineProps, defineEmits, ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
const props = defineProps<{
@@ -172,6 +172,49 @@ const bool_flags: BoolFlag[] = [
const portForwardProtocolOptions = ref(["tcp", "udp"]);
const editingPortForward = ref(false);
const editingPortForwardIndex = ref(-1);
const editingPortForwardData = ref();
function openPortForwardEditor(index: number) {
editingPortForwardIndex.value = index;
// deep copy
editingPortForwardData.value = JSON.parse(JSON.stringify(curNetwork.value.port_forwards[index]));
editingPortForward.value = true;
}
function addPortForward() {
addRow(curNetwork.value.port_forwards)
if (isCompact.value) {
openPortForwardEditor(curNetwork.value.port_forwards.length - 1)
}
}
function savePortForward() {
curNetwork.value.port_forwards[editingPortForwardIndex.value] = editingPortForwardData.value;
editingPortForward.value = false;
}
const portForwardContainer = ref<HTMLElement | null>(null);
const isCompact = ref(false);
onMounted(() => {
if (portForwardContainer.value) {
let resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
isCompact.value = entry.contentRect.width < 540;
}
});
resizeObserver.observe(portForwardContainer.value);
return () => {
if (resizeObserver && portForwardContainer.value) {
resizeObserver.unobserve(portForwardContainer.value);
}
}
}
});
</script>
<template>
@@ -410,14 +453,15 @@ const portForwardProtocolOptions = ref(["tcp", "udp"]);
<Divider />
<Panel :header="t('port_forwards')" toggleable collapsed>
<div class="flex flex-col gap-y-2">
<div ref="portForwardContainer" class="flex flex-col gap-y-2">
<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="port_forwards">{{ t('port_forwards_help') }}</label>
</div>
<div v-for="(row, index) in curNetwork.port_forwards" class="form-row">
<div style="display: flex; gap: 0.5rem; align-items: flex-end;">
<div v-for="(row, index) in curNetwork.port_forwards" :key="index" class="form-row">
<!-- Wide screen view -->
<div v-if="!isCompact" class="flex gap-2 items-end">
<SelectButton v-model="row.proto" :options="portForwardProtocolOptions" :allow-empty="false" />
<div style="flex-grow: 4;">
<InputGroup>
@@ -444,11 +488,52 @@ const portForwardProtocolOptions = ref(["tcp", "udp"]);
rounded @click="removeRow(index, curNetwork.port_forwards)" />
</div>
</div>
<!-- Small screen view -->
<div v-else class="flex justify-between items-center p-2 border-b">
<span>{{ row.proto }}://{{ row.bind_ip }}:{{ row.bind_port }}/{{ row.dst_ip }}:{{
row.dst_port }}</span>
<div class="flex gap-2">
<Button icon="pi pi-pencil" class="p-button-sm" @click="openPortForwardEditor(index)" />
<Button icon="pi pi-trash" class="p-button-sm p-button-danger"
@click="removeRow(index, curNetwork.port_forwards)" />
</div>
</div>
</div>
<div class="flex justify-content-end mt-4">
<Button icon="pi pi-plus" :label="t('port_forwards_add_btn')" severity="success"
@click="addRow(curNetwork.port_forwards)" />
@click="addPortForward" />
</div>
<Dialog v-model:visible="editingPortForward" modal :header="t('edit_port_forward')"
:style="{ width: '90vw', maxWidth: '600px' }">
<div v-if="editingPortForwardData" class="flex flex-col gap-4">
<SelectButton v-model="editingPortForwardData.proto" :options="portForwardProtocolOptions"
:allow-empty="false" />
<InputGroup>
<InputText v-model="editingPortForwardData.bind_ip"
:placeholder="t('port_forwards_bind_addr')" />
<InputGroupAddon>
<span style="font-weight: bold">:</span>
</InputGroupAddon>
<InputNumber v-model="editingPortForwardData.bind_port" :format="false" :step="1" mode="decimal"
:min="1" :max="65535" class="max-w-20" />
</InputGroup>
<InputGroup>
<InputText v-model="editingPortForwardData.dst_ip" :placeholder="t('port_forwards_dst_addr')" />
<InputGroupAddon>
<span style="font-weight: bold">:</span>
</InputGroupAddon>
<InputNumber v-model="editingPortForwardData.dst_port" :format="false" :step="1" mode="decimal"
:min="1" :max="65535" class="max-w-20" />
</InputGroup>
</div>
<template #footer>
<Button :label="t('web.common.cancel')" icon="pi pi-times" @click="editingPortForward = false"
text />
<Button :label="t('web.common.save')" icon="pi pi-save" @click="savePortForward" />
</template>
</Dialog>
</div>
</div>
</div>

View File

@@ -164,6 +164,7 @@ port_forwards_help: "将本地端口转发到虚拟网络中的远程端口。
port_forwards_bind_addr: "绑定地址0.0.0.0"
port_forwards_dst_addr: "目标地址10.126.126.1"
port_forwards_add_btn: "添加"
edit_port_forward: "编辑端口转发"
mtu: MTU
mtu_help: |

View File

@@ -164,6 +164,7 @@ port_forwards_help: "forward local port to remote port in virtual network. e.g.:
port_forwards_bind_addr: "Bind address, e.g.: 0.0.0.0"
port_forwards_dst_addr: "Destination address, e.g.: 10.126.126.1"
port_forwards_add_btn: "Add"
edit_port_forward: "Edit Port Forward"
mtu: MTU
mtu_help: |