This commit is contained in:
紫云徽 2024-07-22 15:07:00 +08:00
parent 29cc87399e
commit efacb10259
4 changed files with 210 additions and 65 deletions

View File

@ -1 +1 @@
{"login":true,"host":"10.225.0.1","user":"lan","password":"xp258147","maincidr":"10.225.1.0/24","proxycidr":"10.225.2.0/24"} {"port":7000,"login":false,"host":"","user":"","password":"","maincidr":"","proxycidr":""}

View File

@ -27,7 +27,7 @@
main { main {
width: 100%; width: 100%;
max-width: 30rem; max-width: 60rem;
margin: auto; margin: auto;
text-align: center; text-align: center;
background-color: #ffffff; background-color: #ffffff;
@ -35,10 +35,20 @@
box-shadow: 0.5rem 0.5rem 1rem rgba(0, 0, 0, 0.2); box-shadow: 0.5rem 0.5rem 1rem rgba(0, 0, 0, 0.2);
} }
.container {
width: 100%;
overflow-x: auto;
}
table {
width: 100%;
min-width: 20rem;
}
.btn { .btn {
width: 3rem; width: 6rem;
height: 2rem; height: 2rem;
margin-bottom: 1rem; margin: 0.2rem;
border: none; border: none;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: #dfdfdf; background-color: #dfdfdf;
@ -54,24 +64,46 @@
box-shadow: 0 3px #666; box-shadow: 0 3px #666;
transform: translateY(2px); transform: translateY(2px);
} }
::-webkit-scrollbar {
display: none;
}
</style> </style>
</head> </head>
<body> <body>
<main> <main>
<h1 class="title">NetgateSwitch</h1> <h1 class="title">NetgateSwitch</h1>
<form> <div class="container">
<div class="text-area"> <table id="table">
</table>
<button class="btn" id="delcfg" style="margin-bottom: 1rem;">删除配置</button>
</div> </div>
<button class="btn" id="getlist">获取</button>
<button class="btn" id="switchaddr">更改</button>
</form>
</main> </main>
</body> </body>
<script> <script>
document.getElementById('getlist').addEventListener('click', async (event) => { document.getElementById("delcfg").addEventListener('click', async () => {
try {
let res = await fetch('./core/logout/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}, body: {}
});
if (!res.ok) {
alert(await res.text());
} else {
window.location.href = "./";
}
} catch (err) {
console.log(err);
}
});
getDHCPList();
async function getDHCPList() {
try { try {
let res = await fetch('./core/get/', { let res = await fetch('./core/get/', {
method: 'POST', method: 'POST',
@ -81,30 +113,89 @@
}); });
if (!res.ok) { if (!res.ok) {
alert(await res.text()); alert(await res.text());
} else {
showDevices(await res.json());
} }
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }
}); }
document.getElementById('switchaddr').addEventListener('click', async (event) => {
function showDevices(list) {
const tb = document.getElementById('table');
let trn = document.createElement('tr');
let td1 = document.createElement('td');
let td2 = document.createElement('td');
let td3 = document.createElement('td');
let td4 = document.createElement('td');
let btn = document.createElement('button');
while (tb.firstChild) {
tb.removeChild(tb.firstChild);
}
td1.setAttribute('scope', 'col');
td1.append('设备名');
td2.setAttribute('scope', 'col');
td2.append('IP地址');
td3.setAttribute('scope', 'col');
td3.append('MAC地址');
td4.setAttribute('scope', 'col');
td4.append('操作');
trn.append(td1, td2, td3, td4);
tb.append(trn);
for (let i in list) {
trn = document.createElement('tr');
td1 = document.createElement('td');
td2 = document.createElement('td');
td3 = document.createElement('td');
td4 = document.createElement('td');
btn1 = document.createElement('button');
btn1.setAttribute('class', 'btn swbtn');
btn1.setAttribute('cidrgroup', 'main');
btn1.setAttribute('deviceid', list[i].id);
btn1.append('切换至Main');
btn2 = document.createElement('button');
btn2.setAttribute('class', 'btn swbtn');
btn2.setAttribute('cidrgroup', 'proxy');
btn2.setAttribute('deviceid', list[i].id);
btn2.append('切换至Proxy');
td1.append(list[i].host);
td2.append(list[i].address);
td3.append(list[i].mac);
td4.append(btn1);
td4.append(btn2);
trn.append(td1, td2, td3, td4);
tb.append(trn);
}
bindEvent();
}
function bindEvent() {
document.querySelectorAll('.swbtn').forEach((button) => {
button.addEventListener('click', async () => {
try { try {
let res = await fetch('./core/switch/', { let res = await fetch('./core/switch/', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, body: JSON.stringify({ }, body: JSON.stringify({
id: 'a', id: button.getAttribute('deviceid'),
group: 'main', group: button.getAttribute('cidrgroup'),
}) })
}); });
console.log(button.getAttribute('cidrgroup'));
if (!res.ok) { if (!res.ok) {
alert(await res.text()); alert(await res.text());
} else {
alert('切换成功');
window.location.href = "./";
} }
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }
}); });
});
}
</script> </script>
</html> </html>

122
index.ts
View File

@ -1,16 +1,27 @@
import { serve } from "bun"; import { serve } from 'bun';
import { RouterOSAPI } from 'node-routeros'; import { RouterOSAPI } from 'node-routeros';
import cfg from "./config.json"; import cfg from './config.json';
let api = new RouterOSAPI({ let api = new RouterOSAPI({
host: cfg.host, host: cfg.host,
user: cfg.user, user: cfg.user,
password: cfg.password password: cfg.password
}); });
let haslogin = cfg.login;
const maincidr = cfg.maincidr; const maincidr = cfg.maincidr;
const proxycidr = cfg.proxycidr; const proxycidr = cfg.proxycidr;
let haslogin = cfg.login;
type Device = {
'id': string,
'address': string,
'mac': string,
'status': string,
'host': string,
'comment': string
}
let list: Device[] = [];
if (haslogin) { if (haslogin) {
if (!await connectAPI()) { if (!await connectAPI()) {
haslogin = false; haslogin = false;
@ -18,17 +29,17 @@ if (haslogin) {
} }
const server = serve({ const server = serve({
port: 3000, async fetch(request) { port: cfg.port, async fetch(request) {
const url = new URL(request.url); const url = new URL(request.url);
if (url.pathname === "/") { if (url.pathname === '/') {
let file = haslogin ? Bun.file("./index.html") : Bun.file("./login.html"); let file = haslogin ? Bun.file('./index.html') : Bun.file('./login.html');
return new Response(file); return new Response(file);
} }
if (url.pathname === "/core/login/") { if (url.pathname === '/core/login/') {
let data = await request.json(); let data = await request.json();
if (data.user === "" || data.password === "" || data.host === "") { if (data.user === '' || data.password === '' || data.host === '') {
return new Response("参数错误", { status: 400 }); return new Response('参数缺失', { status: 400 });
} }
api = new RouterOSAPI({ api = new RouterOSAPI({
host: data.host, host: data.host,
@ -37,71 +48,109 @@ const server = serve({
}); });
if (await connectAPI()) { if (await connectAPI()) {
writeConfig(data.host, data.user, data.password, data.main, data.proxy); writeConfig(data.host, data.user, data.password, data.main, data.proxy);
console.log("配置文件已更新"); console.log('配置文件已更新');
return new Response("登入成功"); return new Response('登入成功');
} else { } else {
return new Response("ROS登入失败", { status: 400 }); return new Response('ROS登入失败', { status: 400 });
} }
} }
if (url.pathname === "/core/get/") { if (url.pathname === '/core/get/') {
if (!haslogin) return new Response("ROS配置未设置", { status: 401 }); if (!haslogin) return new Response('ROS配置未设置', { status: 401 });
return new Response(JSON.stringify(await getDHCPList())); return new Response(JSON.stringify(await getDHCPList()));
} }
if (url.pathname === "/core/switch/") { if (url.pathname === '/core/switch/') {
if (!haslogin) return new Response("ROS配置未设置", { status: 401 }); if (!haslogin) return new Response('ROS配置未设置', { status: 401 });
let data = await request.json(); let data = await request.json();
let id = data.id; let id = data.id;
let mac = data.mac; let mac = data.mac;
let group = data.group; let group = data.group;
if ((id === "" && mac === "") || group === "") { if ((id === '' && mac === '')) {
return new Response("400 Bad Request", { status: 400 }); return new Response('参数缺失', { status: 401 });
}
let isExists: boolean = false;
let addr = '';
for (let i in list) {
if (list[i].id === id || list[i].mac === mac) {
id = list[i].id;
addr = list[i].address;
isExists = true;
}
}
if ((!isExists)) {
return new Response('设备不存在', { status: 401 });
}
if (group !== 'main' && group !== 'proxy') {
return new Response('group错误', { status: 401 });
}
if (await switchNetgate(id, addr, group)) {
return new Response('登入成功');
} else {
return new Response('切换失败', { status: 401 });
} }
switchNetgate('*458',group);
} }
if (url.pathname === "/core/logout/") { if (url.pathname === '/core/logout/') {
cleanConfig(); cleanConfig();
return new Response("已登出"); return new Response('已登出');
} }
return new Response("Page not found", { status: 404 }); return new Response('Page not found', { status: 404 });
} }
}); });
console.log(`Listening on http://localhost:${server.port} ...`); console.log(`前端已开启: http://localhost:${server.port} ...`);
async function connectAPI() { async function connectAPI() {
try { try {
await api.connect(); await api.connect();
console.log("API登入成功"); console.log('API登入成功');
return true; return true;
} catch (err) { } catch (err) {
console.log(err); console.log(err);
console.log("API登入失败"); console.log('API登入失败');
return false; return false;
} }
} }
async function getDHCPList() { async function getDHCPList() {
const result = await api.write('/ip/dhcp-server/lease/print'); const result = await api.write('/ip/dhcp-server/lease/print');
let list = []; list = [];
for (let eq in result) { for (let eq in result) {
list.push({ list.push({
'id': result[eq]['.id'], 'id': result[eq]['.id'],
'address': result[eq]['address'], 'address': result[eq]['address'],
'mac-address': result[eq]['mac-address'], 'mac': result[eq]['mac-address'],
'status': result[eq]['status'], 'status': result[eq]['status'],
'host-name': result[eq]['host-name'], 'host': result[eq]['host-name'],
'comment': result[eq]['comment'], 'comment': result[eq]['comment'],
}); });
} }
console.log(list);
return list; return list;
} }
async function switchNetgate(id:string,group:string) { async function switchNetgate(id: string, addr: string, group: string) {
const result = await api.write('/ip/dhcp-server/lease/set',['=.id='+id,'=address='+(group==='proxy'?'10.225.1.100':'10.225.0.100')]); try {
let mask = Number.parseInt(maincidr.split('/')[1]);
let targetcidr = (group === 'proxy' ? proxycidr : maincidr).split('/')[0].split('.');
let address = addr.split('.');
let num = 2;
if (mask == 16) {
num = 1;
} else if (mask == 8) {
num = 0;
}
for (let i = 0; i <= num; i++) {
address[i] = targetcidr[i];
}
console.log('原IP' + addr + '切换至' + address.join('.'));
const result = await api.write('/ip/dhcp-server/lease/set', ['=.id=' + id, '=address=' + address.join('.')]);
return true;
} catch (err) {
console.log(err);
return false;
}
} }
async function writeConfig(host: string, user: string, password: string, mcidr: string, pcidr: string) { async function writeConfig(host: string, user: string, password: string, mcidr: string, pcidr: string) {
@ -113,11 +162,16 @@ async function writeConfig(host: string, user: string, password: string, mcidr:
cfg.proxycidr = pcidr; cfg.proxycidr = pcidr;
haslogin = true; haslogin = true;
await Bun.write("./config.json", JSON.stringify(cfg)); await Bun.write('./config.json', JSON.stringify(cfg));
} }
async function cleanConfig() { async function cleanConfig() {
cfg.login = false;
haslogin = false; haslogin = false;
await Bun.write("./config.json", JSON.stringify(cfg)); cfg.login = false;
cfg.host = "";
cfg.user = "";
cfg.password = "";
cfg.maincidr = "";
cfg.proxycidr = "";
await Bun.write('./config.json', JSON.stringify(cfg));
} }

View File

@ -108,7 +108,7 @@
if(!res.ok){ if(!res.ok){
alert(await res.text()); alert(await res.text());
}else{ }else{
window.location.href("./"); window.location.href="./";
} }
}catch(err){ }catch(err){
console.log(err); console.log(err);