diff --git a/vite-frontend/src/api/types.ts b/vite-frontend/src/api/types.ts
index cd3c5f0..1ff16cc 100644
--- a/vite-frontend/src/api/types.ts
+++ b/vite-frontend/src/api/types.ts
@@ -71,6 +71,9 @@ export interface ForwardApiItem {
userId?: number;
tunnelId?: number;
speedId?: number | null;
+ ipMaxConn?: number;
+ ipSpeedId?: number | null;
+ ipSpeedLimitName?: string;
maxConn?: number;
proxyProtocol?: number;
inx?: number;
@@ -372,6 +375,8 @@ export interface ForwardMutationPayload {
remoteAddr?: string;
strategy?: string;
speedId?: number | null;
+ ipMaxConn?: number;
+ ipSpeedId?: number | null;
maxConn?: number;
proxyProtocol?: number;
}
diff --git a/vite-frontend/src/pages/forward.tsx b/vite-frontend/src/pages/forward.tsx
index 2e86b78..3d23627 100644
--- a/vite-frontend/src/pages/forward.tsx
+++ b/vite-frontend/src/pages/forward.tsx
@@ -125,6 +125,9 @@ interface Forward {
userId?: number;
inx?: number;
speedId?: number | null;
+ ipMaxConn?: number;
+ ipSpeedId?: number | null;
+ ipSpeedLimitName?: string;
proxyProtocol?: number;
}
@@ -160,6 +163,8 @@ interface ForwardForm {
interfaceName?: string;
strategy: string;
speedId: number | null;
+ ipMaxConn?: number;
+ ipSpeedId: number | null;
maxConn?: number;
proxyProtocol?: number;
}
@@ -578,6 +583,16 @@ const mapForwardApiItems = (items: ForwardApiItem[]): Forward[] => {
typeof forward.speedId === "number" || forward.speedId === null
? forward.speedId
: undefined,
+ ipMaxConn:
+ typeof forward.ipMaxConn === "number" ? forward.ipMaxConn : undefined,
+ ipSpeedId:
+ typeof forward.ipSpeedId === "number" || forward.ipSpeedId === null
+ ? forward.ipSpeedId
+ : undefined,
+ ipSpeedLimitName:
+ typeof forward.ipSpeedLimitName === "string"
+ ? forward.ipSpeedLimitName
+ : undefined,
maxConn: typeof forward.maxConn === "number" ? forward.maxConn : undefined,
proxyProtocol:
typeof forward.proxyProtocol === "number"
@@ -1316,6 +1331,8 @@ export default function ForwardPage() {
interfaceName: "",
strategy: "fifo",
speedId: null,
+ ipMaxConn: 0,
+ ipSpeedId: null,
maxConn: 0,
proxyProtocol: 0,
});
@@ -2030,6 +2047,7 @@ export default function ForwardPage() {
};
const selectedSpeedId = normalizeSpeedId(form.speedId);
+ const selectedIPSpeedId = normalizeSpeedId(form.ipSpeedId);
const validateForm = (): boolean => {
const newErrors: { [key: string]: string } = {};
@@ -2105,6 +2123,8 @@ export default function ForwardPage() {
interfaceName: "",
strategy: "fifo",
speedId: null,
+ ipMaxConn: 0,
+ ipSpeedId: null,
proxyProtocol: 0,
});
setErrors({});
@@ -2126,6 +2146,8 @@ export default function ForwardPage() {
interfaceName: forward.interfaceName || "",
strategy: forward.strategy || "fifo",
speedId: normalizeSpeedId(forward.speedId),
+ ipMaxConn: forward.ipMaxConn ?? 0,
+ ipSpeedId: normalizeSpeedId(forward.ipSpeedId),
maxConn: forward.maxConn ?? 0,
proxyProtocol: forward.proxyProtocol ?? 0,
});
@@ -2245,6 +2267,8 @@ export default function ForwardPage() {
let res: { code: number; msg: string };
const normalizedSpeedId = normalizeSpeedId(form.speedId);
const speedLimitAutoCleared = isMissingSpeedLimit(form.speedId);
+ const normalizedIPSpeedId = normalizeSpeedId(form.ipSpeedId);
+ const ipSpeedLimitAutoCleared = isMissingSpeedLimit(form.ipSpeedId);
if (isEdit) {
const updateData = {
@@ -2256,6 +2280,8 @@ export default function ForwardPage() {
remoteAddr: processedRemoteAddr,
strategy: addressCount > 1 ? form.strategy : "fifo",
speedId: normalizedSpeedId,
+ ipMaxConn: form.ipMaxConn,
+ ipSpeedId: normalizedIPSpeedId,
maxConn: form.maxConn,
proxyProtocol: form.proxyProtocol,
};
@@ -2270,6 +2296,8 @@ export default function ForwardPage() {
remoteAddr: processedRemoteAddr,
strategy: addressCount > 1 ? form.strategy : "fifo",
speedId: normalizedSpeedId,
+ ipMaxConn: form.ipMaxConn,
+ ipSpeedId: normalizedIPSpeedId,
maxConn: form.maxConn,
proxyProtocol: form.proxyProtocol,
};
@@ -2297,6 +2325,12 @@ export default function ForwardPage() {
duration: 5000,
});
}
+ if (ipSpeedLimitAutoCleared) {
+ toast("所选每 IP 限速规则不存在,已自动清除为不限速", {
+ icon: "⚠️",
+ duration: 5000,
+ });
+ }
toast.success(isEdit ? "修改成功" : "创建成功");
setModalOpen(false);
await refreshForwardList(false);
@@ -4911,6 +4945,27 @@ export default function ForwardPage() {
setForm((prev) => ({ ...prev, maxConn: value }));
}}
/>
+ {
+ const value = Math.max(
+ Number(e.target.value) || 0,
+ 0,
+ );
+
+ setForm((prev) => ({ ...prev, ipMaxConn: value }));
+ }}
+ />