mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-04 17:16:37 +08:00
feat: allow user custom inport with range validation
Entire-Checkpoint: fcd76aac10e9
This commit is contained in:
@@ -78,7 +78,7 @@ export default function AdminLayout({
|
||||
},
|
||||
{
|
||||
path: "/forward",
|
||||
label: "转发",
|
||||
label: "规则",
|
||||
icon: (
|
||||
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function H5Layout({ children }: { children: React.ReactNode }) {
|
||||
},
|
||||
{
|
||||
path: "/forward",
|
||||
label: "转发",
|
||||
label: "规则",
|
||||
icon: (
|
||||
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
|
||||
@@ -128,6 +128,8 @@ interface Tunnel {
|
||||
inNodeId?: Array<{ nodeId: number }>;
|
||||
inNodePortSta?: number;
|
||||
inNodePortEnd?: number;
|
||||
portRangeMin?: number;
|
||||
portRangeMax?: number;
|
||||
}
|
||||
|
||||
interface Node {
|
||||
@@ -682,6 +684,27 @@ export default function ForwardPage() {
|
||||
return (currentTunnel?.inNodeId?.length || 0) > 1;
|
||||
}, [allTunnels, form.tunnelId]);
|
||||
|
||||
const currentTunnelPortRange = useMemo(() => {
|
||||
if (!form.tunnelId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentTunnel = allTunnels.find(
|
||||
(tunnel) => tunnel.id === form.tunnelId,
|
||||
);
|
||||
|
||||
if (
|
||||
currentTunnel?.portRangeMin &&
|
||||
currentTunnel?.portRangeMax &&
|
||||
currentTunnel.portRangeMin > 0 &&
|
||||
currentTunnel.portRangeMax > 0
|
||||
) {
|
||||
return { min: currentTunnel.portRangeMin, max: currentTunnel.portRangeMax };
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [allTunnels, form.tunnelId]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
diagnosisAbortRef.current?.abort();
|
||||
@@ -1267,12 +1290,9 @@ export default function ForwardPage() {
|
||||
newErrors.tunnelId = "请选择关联隧道";
|
||||
}
|
||||
|
||||
// 验证入口端口(可选,如果填写则验证)
|
||||
if (form.inPort !== null && form.inPort !== undefined) {
|
||||
const port = Number(form.inPort);
|
||||
|
||||
if (isNaN(port) || port < 1 || port > 65535) {
|
||||
newErrors.inPort = "端口必须在 1-65535 之间";
|
||||
if (form.inPort !== null && form.inPort !== undefined && form.inPort > 0 && currentTunnelPortRange) {
|
||||
if (form.inPort < currentTunnelPortRange.min || form.inPort > currentTunnelPortRange.max) {
|
||||
newErrors.inPort = `端口 ${currentTunnelPortRange.min}-${currentTunnelPortRange.max} 超出允许范围`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1432,11 +1452,11 @@ export default function ForwardPage() {
|
||||
id: form.id,
|
||||
name: form.name,
|
||||
tunnelId: form.tunnelId,
|
||||
...(isAdmin ? { inPort: form.inPort } : {}),
|
||||
inPort: form.inPort,
|
||||
...(inIpTouched ? { inIp: form.inIp || "" } : {}),
|
||||
remoteAddr: processedRemoteAddr,
|
||||
strategy: addressCount > 1 ? form.strategy : "fifo",
|
||||
...(isAdmin ? { speedId: normalizedSpeedId } : {}),
|
||||
speedId: normalizedSpeedId,
|
||||
};
|
||||
|
||||
res = await updateForward(updateData);
|
||||
@@ -1444,13 +1464,12 @@ export default function ForwardPage() {
|
||||
const createData = {
|
||||
name: form.name,
|
||||
tunnelId: form.tunnelId,
|
||||
...(isAdmin ? { inPort: form.inPort } : {}),
|
||||
inPort: form.inPort,
|
||||
inIp: form.inIp || undefined,
|
||||
remoteAddr: processedRemoteAddr,
|
||||
strategy: addressCount > 1 ? form.strategy : "fifo",
|
||||
...(isAdmin ? { speedId: normalizedSpeedId } : {}),
|
||||
speedId: normalizedSpeedId,
|
||||
};
|
||||
|
||||
res = await createForward(createData);
|
||||
}
|
||||
|
||||
@@ -4347,26 +4366,28 @@ export default function ForwardPage() {
|
||||
))}
|
||||
</Select>
|
||||
|
||||
{isAdmin && (
|
||||
<Input
|
||||
description="指定入口端口,留空则从节点可用端口中自动分配"
|
||||
errorMessage={errors.inPort}
|
||||
isInvalid={!!errors.inPort}
|
||||
label="入口端口"
|
||||
placeholder="留空则自动分配可用端口"
|
||||
type="number"
|
||||
value={form.inPort !== null ? form.inPort.toString() : ""}
|
||||
variant="bordered"
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
<Input
|
||||
description={
|
||||
currentTunnelPortRange
|
||||
? `指定入口端口,留空自动分配 (允许范围: ${currentTunnelPortRange.min}-${currentTunnelPortRange.max})`
|
||||
: "指定入口端口,留空则从节点可用端口中自动分配"
|
||||
}
|
||||
errorMessage={errors.inPort}
|
||||
isInvalid={!!errors.inPort}
|
||||
label="入口端口"
|
||||
placeholder="留空则自动分配可用端口"
|
||||
type="number"
|
||||
value={form.inPort !== null ? form.inPort.toString() : ""}
|
||||
variant="bordered"
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
inPort: value ? parseInt(value) : null,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
inPort: value ? parseInt(value) : null,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
|
||||
<Select
|
||||
description={
|
||||
|
||||
Reference in New Issue
Block a user