mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-07 18:26:37 +08:00
refactor(frontend): extract reusable hooks and page helper modules
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
export interface DiagnosisEntry {
|
||||
success: boolean;
|
||||
description: string;
|
||||
nodeName: string;
|
||||
nodeId: string;
|
||||
targetIp: string;
|
||||
targetPort?: number;
|
||||
message?: string;
|
||||
averageTime?: number;
|
||||
packetLoss?: number;
|
||||
fromChainType?: number;
|
||||
fromInx?: number;
|
||||
toChainType?: number;
|
||||
toInx?: number;
|
||||
}
|
||||
|
||||
export interface DiagnosisResult {
|
||||
tunnelName: string;
|
||||
tunnelType: string;
|
||||
timestamp: number;
|
||||
results: DiagnosisEntry[];
|
||||
}
|
||||
|
||||
export interface DiagnosisFallbackInput {
|
||||
tunnelName: string;
|
||||
tunnelType: number;
|
||||
description: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export const buildDiagnosisFallbackResult = ({
|
||||
tunnelName,
|
||||
tunnelType,
|
||||
description,
|
||||
message,
|
||||
}: DiagnosisFallbackInput): DiagnosisResult => {
|
||||
return {
|
||||
tunnelName,
|
||||
tunnelType: tunnelType === 1 ? "端口转发" : "隧道转发",
|
||||
timestamp: Date.now(),
|
||||
results: [
|
||||
{
|
||||
success: false,
|
||||
description,
|
||||
nodeName: "-",
|
||||
nodeId: "-",
|
||||
targetIp: "-",
|
||||
targetPort: 443,
|
||||
message,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
export const getDiagnosisQualityDisplay = (
|
||||
averageTime?: number,
|
||||
packetLoss?: number,
|
||||
): {
|
||||
text: string;
|
||||
color: "success" | "primary" | "warning" | "danger";
|
||||
} | null => {
|
||||
if (averageTime === undefined || packetLoss === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (averageTime < 30 && packetLoss === 0) {
|
||||
return { text: "🚀 优秀", color: "success" };
|
||||
}
|
||||
|
||||
if (averageTime < 50 && packetLoss === 0) {
|
||||
return { text: "✨ 很好", color: "success" };
|
||||
}
|
||||
|
||||
if (averageTime < 100 && packetLoss < 1) {
|
||||
return { text: "👍 良好", color: "primary" };
|
||||
}
|
||||
|
||||
if (averageTime < 150 && packetLoss < 2) {
|
||||
return { text: "😐 一般", color: "warning" };
|
||||
}
|
||||
|
||||
if (averageTime < 200 && packetLoss < 5) {
|
||||
return { text: "😟 较差", color: "warning" };
|
||||
}
|
||||
|
||||
return { text: "😵 很差", color: "danger" };
|
||||
};
|
||||
@@ -0,0 +1,110 @@
|
||||
interface TunnelChainNode {
|
||||
nodeId: number;
|
||||
}
|
||||
|
||||
interface TunnelFormInput {
|
||||
name: string;
|
||||
type: number;
|
||||
inNodeId: TunnelChainNode[];
|
||||
outNodeId?: TunnelChainNode[];
|
||||
trafficRatio: number;
|
||||
}
|
||||
|
||||
interface TunnelNodeInput {
|
||||
id: number;
|
||||
status: number;
|
||||
}
|
||||
|
||||
export const createTunnelFormDefaults = () => {
|
||||
return {
|
||||
name: "",
|
||||
type: 1,
|
||||
inNodeId: [],
|
||||
outNodeId: [],
|
||||
chainNodes: [],
|
||||
flow: 1,
|
||||
trafficRatio: 1.0,
|
||||
inIp: "",
|
||||
ipPreference: "",
|
||||
status: 1,
|
||||
};
|
||||
};
|
||||
|
||||
export const validateTunnelForm = (
|
||||
form: TunnelFormInput,
|
||||
nodes: TunnelNodeInput[],
|
||||
): Record<string, string> => {
|
||||
const errors: Record<string, string> = {};
|
||||
|
||||
if (!form.name.trim()) {
|
||||
errors.name = "请输入隧道名称";
|
||||
} else if (form.name.length < 2 || form.name.length > 50) {
|
||||
errors.name = "隧道名称长度应在2-50个字符之间";
|
||||
}
|
||||
|
||||
if (!form.inNodeId || form.inNodeId.length === 0) {
|
||||
errors.inNodeId = "请至少选择一个入口节点";
|
||||
} else {
|
||||
const offlineInNodes = form.inNodeId.filter((item) => {
|
||||
const node = nodes.find((n) => n.id === item.nodeId);
|
||||
|
||||
return node && node.status !== 1;
|
||||
});
|
||||
|
||||
if (offlineInNodes.length > 0) {
|
||||
errors.inNodeId = "所有入口节点必须在线";
|
||||
}
|
||||
}
|
||||
|
||||
if (form.trafficRatio <= 0 || form.trafficRatio > 100.0) {
|
||||
errors.trafficRatio = "流量倍率须大于0,支持小数(如 0.5)";
|
||||
}
|
||||
|
||||
if (form.type === 2) {
|
||||
if (!form.outNodeId || form.outNodeId.length === 0) {
|
||||
errors.outNodeId = "请至少选择一个出口节点";
|
||||
} else {
|
||||
const offlineOutNodes = form.outNodeId.filter((item) => {
|
||||
const node = nodes.find((n) => n.id === item.nodeId);
|
||||
|
||||
return node && node.status !== 1;
|
||||
});
|
||||
|
||||
if (offlineOutNodes.length > 0) {
|
||||
errors.outNodeId = "所有出口节点必须在线";
|
||||
}
|
||||
|
||||
const inNodeIds = form.inNodeId.map((item) => item.nodeId);
|
||||
const outNodeIds = form.outNodeId.map((item) => item.nodeId);
|
||||
const overlap = inNodeIds.filter((id) => outNodeIds.includes(id));
|
||||
|
||||
if (overlap.length > 0) {
|
||||
errors.outNodeId = "隧道转发模式下,入口和出口不能有相同节点";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
export const getTunnelTypeDisplay = (type: number) => {
|
||||
switch (type) {
|
||||
case 1:
|
||||
return { text: "端口转发", color: "primary" };
|
||||
case 2:
|
||||
return { text: "隧道转发", color: "secondary" };
|
||||
default:
|
||||
return { text: "未知", color: "default" };
|
||||
}
|
||||
};
|
||||
|
||||
export const getTunnelFlowDisplay = (flow: number) => {
|
||||
switch (flow) {
|
||||
case 1:
|
||||
return "单向计算";
|
||||
case 2:
|
||||
return "双向计算";
|
||||
default:
|
||||
return "未知";
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user