feat: Добавить опцию агрессивной агрегации для IP-диапазонов, позволяющую сворачивать более 2 префиксов в одном /16; обновить интерфейс для управления этой настройкой
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m52s

This commit is contained in:
2025-08-26 20:29:26 +07:00
parent 213dc42124
commit b0009fbb1f
+36 -2
View File
@@ -228,7 +228,7 @@ function IPRangesManager() {
const [analysisResultsOpen, setAnalysisResultsOpen] = useState(false);
const [analysisPreview, setAnalysisPreview] = useState(null);
const [overwriteConfirmOpen, setOverwriteConfirmOpen] = useState(false);
const [analyzeFilters, setAnalyzeFilters] = useState({ community: '', minMask: 0, maxMask: 32, type: 'any' });
const [analyzeFilters, setAnalyzeFilters] = useState({ community: '', minMask: 0, maxMask: 32, type: 'any', supernet16: false });
const handlePreviewDiff = () => {
const valid = items.filter(i => isValidCidr(i.ipRange) && isValidCommunity(i.community))
@@ -437,6 +437,7 @@ function IPRangesManager() {
parts.push(`Маска: /${analyzeFilters.minMask}..../${analyzeFilters.maxMask}`);
const typeLabel = analyzeFilters.type === 'any' ? 'любой' : (analyzeFilters.type === 'private' ? 'только приватные' : (analyzeFilters.type === 'public' ? 'только публичные' : 'только CGNAT'));
parts.push(`Тип: ${typeLabel}`);
parts.push(`Агрегировать >2 префиксов в одном /16 до /16: ${analyzeFilters.supernet16 ? 'да' : 'нет'}`);
return parts.join('\n');
};
@@ -522,6 +523,28 @@ function IPRangesManager() {
return out;
};
// Агрессивная агрегация: если в одном /16 > 2 префиксов — свернуть в /16
const get16BaseCidr = (cidr) => {
const ip = String(cidr).split('/')[0];
const ipNum = ipToInt(ip);
const start = ipNum & (~0n << 16n);
return `${intToIp(start)}/16`;
};
const applySupernet16 = (cidrs) => {
const buckets = new Map();
for (const c of cidrs) {
const base16 = get16BaseCidr(c);
if (!buckets.has(base16)) buckets.set(base16, []);
buckets.get(base16).push(c);
}
const out = [];
for (const [base16, list] of buckets) {
if (list.length > 2) out.push(base16); else out.push(...list);
}
return Array.from(new Set(out));
};
const runAnalysis = () => {
const community = String(analyzeFilters.community || '').trim();
if (!community) { window.notify?.error?.('Выберите community'); return; }
@@ -539,7 +562,10 @@ function IPRangesManager() {
const unchanged = allForCommunity.filter(i => !filtered.includes(i));
const beforeCidrs = filtered.map(i => i.ipRange);
const afterCidrs = summarizeCidrs(beforeCidrs);
let afterCidrs = summarizeCidrs(beforeCidrs);
if (analyzeFilters.supernet16) {
afterCidrs = applySupernet16(afterCidrs);
}
const processedBefore = beforeCidrs.length;
const processedAfter = afterCidrs.length;
const totalAfter = processedAfter + unchanged.length;
@@ -1018,6 +1044,14 @@ function IPRangesManager() {
</div>
<div className="form-text">Определение типа по первому IP в CIDR.</div>
</div>
<div className="mb-3">
<label className="form-label">Агрессивная агрегация</label>
<label className="form-check">
<input className="form-check-input" type="checkbox" checked={analyzeFilters.supernet16} onChange={e => setAnalyzeFilters(f => ({ ...f, supernet16: e.target.checked }))} />
<span className="form-check-label">Если в одном /16 более 2 префиксов свернуть в /16</span>
</label>
<div className="form-text">Например: 157.240.12.0/23, 157.240.15.0/24, 157.240.16.0/23 157.240.0.0/16</div>
</div>
</div>
</div>
</div>