This commit is contained in:
limil 2026-02-17 23:01:56 +08:00
parent 9f6b860f5f
commit 9933d56250
2 changed files with 48 additions and 20 deletions

View File

@ -61,30 +61,34 @@ function SubnetItem({index, subnets, setSubnets} : SubnetProps) : ReactNode {
toast.error("没有选择有效的节点");
return ;
}
const nodeId = selectedOption.value;
const nodecidr = (() => {
if(nodeSubnet.includes("/")) return nodeSubnet;
return `${nodeSubnet}/${nodeSubnet.includes(".") ? "32" : "128"}`;
})();
const result = IPUtils.parse(nodecidr);
const cidr = result.cidr;
if(!cidr) {
toast.error(`无法解析子网:${result.error}`);
return ;
}
if(!subnetInfo.subnet.contains(cidr)) {
toast.error("不在子网范围内");
return ;
}
if(subnetInfo.nodes.some(node => node.nodeId === nodeId)) {
toast.error(`节点已添加`);
return;
}
let cidr = undefined;
if(nodeSubnet) {
const nodecidr = (() => {
if(nodeSubnet.includes("/")) return nodeSubnet;
return `${nodeSubnet}/${nodeSubnet.includes(".") ? "32" : "128"}`;
})();
const result = IPUtils.parse(nodecidr);
cidr = result.cidr;
if(!cidr) {
toast.error(`无法解析子网:${result.error}`);
return ;
}
if(!subnetInfo.subnet.contains(cidr)) {
toast.error("不在子网范围内");
return ;
}
}
setSubnets(subnets.map((info, idx) => {
if(idx === index) {
return {...info, nodes: [...info.nodes, {nodeId: nodeId, cidr: cidr}]}

View File

@ -24,12 +24,36 @@ export class CIDR {
}
return `${octets.join('.')}/${this.mask}`;
} else {
// Split 128 bits into 8 blocks of 16 bits
const blocks = [];
// IPv6: split into 8 hex blocks (no leading zeros) and apply :: compression
const blocks: string[] = [];
for (let i = 0; i < 128; i += 16) {
blocks.push(parseInt(this.binary.slice(i, i + 16), 2).toString(16));
}
return `${blocks.join(':')}/${this.mask}`;
// find longest run of '0' blocks
let bestStart = -1, bestLen = 0;
for (let i = 0; i < blocks.length; ) {
if (blocks[i] !== '0') { i++; continue; }
let j = i + 1;
while (j < blocks.length && blocks[j] === '0') j++;
const len = j - i;
if (len > bestLen) { bestStart = i; bestLen = len; }
i = j;
}
let compact: string;
if (bestLen >= 2) {
const left = blocks.slice(0, bestStart).join(':');
const right = blocks.slice(bestStart + bestLen).join(':');
if (left && right) compact = `${left}::${right}`;
else if (left) compact = `${left}::`;
else if (right) compact = `::${right}`;
else compact = '::';
} else {
compact = blocks.join(':');
}
return `${compact}/${this.mask}`;
}
}
}