mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Add VLAN overview table to VLAN configuration page
Below the configuration form, a new table lists all configured VLANs with their port memberships: Member, Tagged, Untagged, and PVID columns. Port ranges are formatted compactly (e.g. "1-2,5"). Port-to-bit mapping uses the existing physToLogPort[] array populated by /status.json, so the table is consistent with the icon view in fetchVLAN() and works on any supported machine. Each row has a delete button that sends "vlan N d" via /cmd, with a confirmation dialog. VLAN 1 cannot be deleted (no button shown). Table and dropdown both refresh automatically after Update/Create and after delete via a new refreshVlanViews() helper. The N+1 request pattern (1x /vlanlist + Nx /vlan.json) keeps the backend simple and avoids buffer overflow risks for systems with many VLANs. For typical configurations (<50 VLANs), page load remains under one second.
This commit is contained in:
+90
-1
@@ -83,6 +83,95 @@ function fetchVLAN() {
|
||||
sendXHTTP(xhttp);
|
||||
}
|
||||
|
||||
function portsToRange(mask, nPorts) {
|
||||
var parts = [];
|
||||
var start = -1, prev = -1;
|
||||
for (var p = 1; p <= nPorts; p++) {
|
||||
var bit = physToLogPort[p - 1];
|
||||
if ((mask >> bit) & 1) {
|
||||
if (start < 0) start = p;
|
||||
prev = p;
|
||||
} else {
|
||||
if (start >= 0) {
|
||||
parts.push(start === prev ? String(start) : start + '-' + prev);
|
||||
start = -1; prev = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (start >= 0)
|
||||
parts.push(start === prev ? String(start) : start + '-' + prev);
|
||||
return parts.length ? parts.join(',') : '-';
|
||||
}
|
||||
|
||||
async function loadVlanTable() {
|
||||
var tbody = document.getElementById('vlanTableBody');
|
||||
if (!tbody) return;
|
||||
tbody.innerHTML = '';
|
||||
var resp;
|
||||
try { resp = await fetch('/vlanlist'); } catch(e) { return; }
|
||||
if (!resp.ok) return;
|
||||
var vlans = await resp.json();
|
||||
for (var i = 0; i < vlans.length; i++) {
|
||||
var v = vlans[i];
|
||||
var vresp;
|
||||
try { vresp = await fetch('/vlan.json?vid=' + v.id); } catch(e) { continue; }
|
||||
if (!vresp.ok) continue;
|
||||
var s = await vresp.json();
|
||||
var m = parseInt(s.members, 16);
|
||||
var members = m & 0x3FF;
|
||||
var untag = (m >> 10) & 0x3FF;
|
||||
var tagged = members & ~untag;
|
||||
var pvid = parseInt(s.pvid, 16) & 0x3FF;
|
||||
var tr = document.createElement('tr');
|
||||
var td, a, btn;
|
||||
td = document.createElement('td');
|
||||
a = document.createElement('a');
|
||||
a.href = '#';
|
||||
a.textContent = v.id;
|
||||
(function(vid) {
|
||||
a.onclick = function(e) {
|
||||
e.preventDefault();
|
||||
document.getElementById('vid').value = vid;
|
||||
fetchVLAN();
|
||||
};
|
||||
})(v.id);
|
||||
td.appendChild(a); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = v.name || ''; tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = portsToRange(members, numPorts); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = portsToRange(tagged, numPorts); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = portsToRange(untag, numPorts); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
td.textContent = portsToRange(pvid, numPorts); tr.appendChild(td);
|
||||
td = document.createElement('td');
|
||||
if (v.id !== 1) {
|
||||
btn = document.createElement('button');
|
||||
btn.textContent = '✕';
|
||||
(function(vid) {
|
||||
btn.onclick = function() { deleteVlan(vid); };
|
||||
})(v.id);
|
||||
td.appendChild(btn);
|
||||
}
|
||||
tr.appendChild(td);
|
||||
tbody.appendChild(tr);
|
||||
}
|
||||
}
|
||||
|
||||
function deleteVlan(id) {
|
||||
if (!confirm('Delete VLAN ' + id + '?')) return;
|
||||
fetch('/cmd', { method: 'POST', body: 'vlan ' + id + ' d' })
|
||||
.then(function() { refreshVlanViews(); })
|
||||
.catch(function(err) { console.error('Delete failed:', err); });
|
||||
}
|
||||
|
||||
function refreshVlanViews() {
|
||||
loadVlanList();
|
||||
loadVlanTable();
|
||||
}
|
||||
|
||||
function loadVlanList() {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
@@ -112,7 +201,7 @@ function loadVlanList() {
|
||||
window.addEventListener("load", function() {
|
||||
update( () => {
|
||||
vlanForm();
|
||||
loadVlanList();
|
||||
refreshVlanViews();
|
||||
document.getElementById('vlanSelect').onchange = function() {
|
||||
document.getElementById('vid').value = this.value;
|
||||
fetchVLAN();
|
||||
|
||||
Reference in New Issue
Block a user