interface-calc/index.html
2026-06-19 06:21:26 +00:00

146 lines
6.3 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Interface Parser — JunOS</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font:15px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;background:#f0f2f5;color:#0F1218;padding:32px 24px}
.container{max-width:1100px;margin:0 auto}
h1{font-size:28px;font-weight:800;margin-bottom:4px}
.sub{color:#5B6573;font-size:15px;margin-bottom:28px}
.layout{display:grid;grid-template-columns:1fr 1fr;gap:24px}
.panel{background:#fff;border-radius:16px;padding:24px;box-shadow:0 2px 12px rgba(0,0,0,.04)}
.panel h2{font-size:17px;font-weight:700;margin-bottom:12px}
textarea{width:100%;height:400px;padding:14px;border:2px solid #d0d5dd;border-radius:10px;font:13px/1.5 "SF Mono","Fira Code","Courier New",monospace;resize:vertical;outline:none;transition:.15s}
textarea:focus{border-color:#0F1218}
button{padding:12px 28px;background:#0F1218;color:#fff;border:none;border-radius:10px;font-size:15px;font-weight:700;cursor:pointer;margin-top:12px;transition:.15s}
button:hover{background:#2a2f3a}
.stats{margin-top:12px;display:flex;gap:16px;flex-wrap:wrap}
.stat{font-size:13px;color:#5B6573;background:#f6f8fa;padding:6px 14px;border-radius:6px}
table{width:100%;border-collapse:collapse;font-size:13px}
thead th{background:#f6f8fa;padding:10px 12px;text-align:left;font-weight:600;font-size:12px;color:#5B6573;border-bottom:2px solid #e8eaed;position:sticky;top:0}
tbody td{padding:10px 12px;border-bottom:1px solid #f0f2f5;vertical-align:top}
tbody tr:hover{background:#f8faff}
tr.disabled td{opacity:.5}
.intf{font-weight:600;font-family:monospace;white-space:nowrap}
.desc{color:#0F1218;max-width:260px;word-break:break-all}
.status{display:inline-block;padding:2px 10px;border-radius:12px;font-size:11px;font-weight:600}
.status.off{background:#fee8e8;color:#c0392b}
.status.on{background:#e8f8e8;color:#27ae60}
.mode{font-family:monospace;font-size:12px;padding:2px 8px;border-radius:4px;background:#f0f2f5}
.portmap{font-size:12px;color:#5B6573;font-family:monospace}
.empty{text-align:center;padding:60px 20px;color:#9aa3b2}
.empty p{font-size:15px;margin-top:8px}
@media(max-width:768px){.layout{grid-template-columns:1fr}.panel{padding:16px}textarea{height:250px}}
</style>
</head>
<body>
<div class="container">
<h1>🔌 Interface Parser — JunOS</h1>
<p class="sub">Вставь конфиг JunOS — получи таблицу интерфейсов</p>
<div class="layout">
<div class="panel">
<h2>📄 Конфиг</h2>
<textarea id="configInput" placeholder='Вставь сюда вывод "show configuration interfaces" или set-команды...&#10;&#10;Пример:&#10;set interfaces ge-0/0/1 description Kazteleport/8117714/12mb&#10;set interfaces ge-0/0/1 disable&#10;set interfaces ge-0/0/1 unit 0 family ethernet-switching port-mode access&#10;set interfaces ge-0/0/1 unit 0 family ethernet-switching vlan members vlan1793&#10;set interfaces ge-0/0/2 unit 0 family ethernet-switching port-mode access'></textarea>
<button onclick="parse()">Разобрать конфиг</button>
<div class="stats" id="stats"></div>
</div>
<div class="panel">
<h2>📊 Интерфейсы</h2>
<div id="result"><div class="empty"><div style="font-size:48px">📋</div><p>Вставь конфиг слева и нажми «Разобрать»</p></div></div>
<div id="portmap"></div>
</div>
</div>
</div>
<script>
const PORTS_PER = 16;
const TOTAL = 84;
function parse(){
const text=document.getElementById('configInput').value;
const stats=document.getElementById('stats');
const result=document.getElementById('result');
const portmap=document.getElementById('portmap');
const lines=text.split('\n').map(l=>l.trim()).filter(l=>l&&l.startsWith('set interfaces'));
if(!lines.length){
result.innerHTML='<div class="empty"><div style="font-size:48px">⚠️</div><p>Ничего не найдено. Вставь строки начинающиеся с set interfaces</p></div>';
stats.innerHTML='';
portmap.innerHTML='';
return;
}
const ifaces={};
const order=[];
lines.forEach(line=>{
// Parse: set interfaces ge-0/0/X ...
const match=line.match(/set interfaces (ge-\d+\/\d+\/\d+)/);
if(!match)return;
const name=match[1];
if(!ifaces[name]){
ifaces[name]={name,descr:'',disabled:false,mode:'',vlan:''};
order.push(name);
}
const iface=ifaces[name];
if(/ description /.test(line)){
const d=line.match(/description (.+)$/);
if(d)iface.descr=d[1];
}
if(/ disable$/.test(line)){
iface.disabled=true;
}
if(/ no-traps/.test(line)){
// no change to status
}
if(/ port-mode /.test(line)){
const m=line.match(/port-mode (\w+)/);
if(m)iface.mode=m[1];
}
if(/ vlan members /.test(line)){
const v=line.match(/vlan members (\S+)/);
if(v)iface.vlan=v[1];
}
});
stats.innerHTML=`
<span class="stat">📡 ${order.length} интерфейсов</span>
<span class="stat">🔴 ${order.filter(n=>ifaces[n].disabled).length} disabled</span>
<span class="stat">🟢 ${order.filter(n=>!ifaces[n].disabled).length} active</span>
`;
if(!order.length){
result.innerHTML='<div class="empty"><div style="font-size:48px">⚠️</div><p>Не удалось распознать интерфейсы. Проверь формат.</p></div>';
portmap.innerHTML='';
return;
}
let table='<table><thead><tr><th>Интерфейс</th><th>Описание</th><th>Статус</th><th>Режим</th><th>VLAN</th></tr></thead><tbody>';
order.forEach(name=>{
const i=ifaces[name];
table+=`<tr class="${i.disabled?'disabled':''}">
<td class="intf">${name}</td>
<td class="desc">${i.descr||'—'}</td>
<td><span class="status ${i.disabled?'off':'on'}">${i.disabled?'off':'on'}</span></td>
<td>${i.mode?`<span class="mode">${i.mode}</span>`:'—'}</td>
<td>${i.vlan||'—'}</td>
</tr>`;
});
table+='</tbody></table>';
result.innerHTML=table;
// cassette/port mapping for first 16 intfs
portmap.innerHTML='';
}
document.getElementById('configInput').addEventListener('keydown',e=>{if((e.ctrlKey||e.metaKey)&&e.key==='Enter')parse()});
</script>
</body>
</html>