|
|
using System.Text;
|
|
|
using CncSimulator.Core;
|
|
|
|
|
|
namespace CncSimulator.Admin
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 管理页面HTML生成器。
|
|
|
/// 生成总管理页面和单地址管理页面的完整HTML+CSS+JS。
|
|
|
/// </summary>
|
|
|
public class AdminHandler
|
|
|
{
|
|
|
/// <summary>生成总管理页面(网关页面)</summary>
|
|
|
public string BuildGatewayPage(SimulatorEngine engine)
|
|
|
{
|
|
|
var sb = new StringBuilder();
|
|
|
sb.AppendLine("<!DOCTYPE html>");
|
|
|
sb.AppendLine("<html lang='zh-CN'><head><meta charset='utf-8'>");
|
|
|
sb.AppendLine("<meta name='viewport' content='width=device-width, initial-scale=1'>");
|
|
|
sb.AppendLine("<title>CNC 模拟采集服务 - 总管理</title>");
|
|
|
sb.AppendLine("<style>");
|
|
|
sb.AppendLine("* { margin:0; padding:0; box-sizing:border-box; }");
|
|
|
sb.AppendLine("body { font-family:'Microsoft YaHei',sans-serif; background:#f0f2f5; color:#333; }");
|
|
|
sb.AppendLine(".header { background:#1890ff; color:#fff; padding:16px 24px; display:flex; justify-content:space-between; align-items:center; }");
|
|
|
sb.AppendLine(".header h1 { font-size:20px; font-weight:600; }");
|
|
|
sb.AppendLine(".header-actions button { margin-left:8px; padding:6px 16px; border:none; border-radius:4px; cursor:pointer; font-size:14px; }");
|
|
|
sb.AppendLine(".btn-start { background:#52c41a; color:#fff; }");
|
|
|
sb.AppendLine(".btn-stop { background:#ff4d4f; color:#fff; }");
|
|
|
sb.AppendLine(".container { max-width:1200px; margin:20px auto; padding:0 20px; }");
|
|
|
sb.AppendLine(".section { background:#fff; border-radius:8px; padding:20px; margin-bottom:16px; box-shadow:0 1px 4px rgba(0,0,0,0.1); }");
|
|
|
sb.AppendLine(".section h2 { font-size:16px; margin-bottom:12px; padding-bottom:8px; border-bottom:1px solid #e8e8e8; }");
|
|
|
sb.AppendLine("table { width:100%; border-collapse:collapse; }");
|
|
|
sb.AppendLine("th,td { padding:10px 12px; text-align:left; border-bottom:1px solid #f0f0f0; font-size:14px; }");
|
|
|
sb.AppendLine("th { background:#fafafa; font-weight:600; color:#666; }");
|
|
|
sb.AppendLine(".status-dot { display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:6px; }");
|
|
|
sb.AppendLine(".status-running { background:#52c41a; }");
|
|
|
sb.AppendLine(".status-stopped { background:#d9d9d9; }");
|
|
|
sb.AppendLine(".btn-link { color:#1890ff; cursor:pointer; text-decoration:none; border:none; background:none; font-size:14px; }");
|
|
|
sb.AppendLine(".log-area { max-height:300px; overflow-y:auto; font-family:Consolas,monospace; font-size:13px; line-height:1.8; color:#666; }");
|
|
|
sb.AppendLine("</style></head><body>");
|
|
|
sb.AppendLine("<div class='header'>");
|
|
|
sb.AppendLine(" <h1>CNC 模拟采集服务</h1>");
|
|
|
sb.AppendLine(" <div class='header-actions'>");
|
|
|
sb.AppendLine(" <button class='btn-start' onclick='startAll()'>全部启动</button>");
|
|
|
sb.AppendLine(" <button class='btn-stop' onclick='stopAll()'>全部停止</button>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
sb.AppendLine("</div>");
|
|
|
sb.AppendLine("<div class='container'>");
|
|
|
sb.AppendLine(" <div class='section'><h2>地址列表</h2>");
|
|
|
sb.AppendLine(" <table><thead><tr><th>名称</th><th>端口</th><th>状态</th><th>设备数</th><th>数据频率</th><th>请求次数</th><th>操作</th></tr></thead>");
|
|
|
sb.AppendLine(" <tbody id='addressTable'></tbody></table>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
sb.AppendLine(" <div class='section'><h2>控制台日志</h2>");
|
|
|
sb.AppendLine(" <div class='log-area' id='logArea'>加载中...</div>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
sb.AppendLine("</div>");
|
|
|
sb.AppendLine("<script>");
|
|
|
sb.AppendLine("var logLines=[];var maxLogs=50;");
|
|
|
sb.AppendLine("function refresh(){");
|
|
|
sb.AppendLine(" fetch('/admin/api/status').then(r=>r.json()).then(data=>{");
|
|
|
sb.AppendLine(" var tb=document.getElementById('addressTable');tb.innerHTML='';");
|
|
|
sb.AppendLine(" data.forEach(function(a){");
|
|
|
sb.AppendLine(" var st=a.isRunning?'<span class=\"status-dot status-running\"></span>运行中':'<span class=\"status-dot status-stopped\"></span>已停止';");
|
|
|
sb.AppendLine(" tb.innerHTML+='<tr><td>'+a.name+'</td><td>'+a.port+'</td><td>'+st+'</td><td>'+a.onlineDevices+'/'+a.totalDevices+'台</td><td>'+a.dataChangeInterval+'秒</td><td>'+a.requestCount+'</td><td><a class=\"btn-link\" href=\"http://localhost:'+a.port+'/admin\" target=\"_blank\">管理</a></td></tr>';");
|
|
|
sb.AppendLine(" });");
|
|
|
sb.AppendLine(" }).catch(function(){});");
|
|
|
sb.AppendLine("}");
|
|
|
sb.AppendLine("function addLog(msg){var now=new Date();var ts=now.toTimeString().substr(0,8);logLines.unshift(ts+' '+msg);if(logLines.length>maxLogs)logLines.length=maxLogs;document.getElementById('logArea').innerHTML=logLines.join('<br>');}");
|
|
|
sb.AppendLine("function startAll(){fetch('/admin/api/start',{method:'POST'}).then(function(){addLog('全部启动');refresh()});}");
|
|
|
sb.AppendLine("function stopAll(){fetch('/admin/api/stop',{method:'POST'}).then(function(){addLog('全部停止');refresh()});}");
|
|
|
sb.AppendLine("setInterval(refresh,2000);refresh();");
|
|
|
sb.AppendLine("</script></body></html>");
|
|
|
return sb.ToString();
|
|
|
}
|
|
|
|
|
|
/// <summary>生成单地址管理页面</summary>
|
|
|
public string BuildSingleAddressPage(SimulatorServer server)
|
|
|
{
|
|
|
var sb = new StringBuilder();
|
|
|
sb.AppendLine("<!DOCTYPE html>");
|
|
|
sb.AppendLine("<html lang='zh-CN'><head><meta charset='utf-8'>");
|
|
|
sb.AppendLine("<meta name='viewport' content='width=device-width, initial-scale=1'>");
|
|
|
sb.AppendLine("<title>" + server.Name + " - 模拟管理</title>");
|
|
|
sb.AppendLine("<style>");
|
|
|
sb.AppendLine("* { margin:0; padding:0; box-sizing:border-box; }");
|
|
|
sb.AppendLine("body { font-family:'Microsoft YaHei',sans-serif; background:#f0f2f5; color:#333; }");
|
|
|
sb.AppendLine(".header { background:#1890ff; color:#fff; padding:16px 24px; display:flex; justify-content:space-between; align-items:center; }");
|
|
|
sb.AppendLine(".header h1 { font-size:18px; font-weight:600; }");
|
|
|
sb.AppendLine(".header-actions button { margin-left:8px; padding:6px 16px; border:none; border-radius:4px; cursor:pointer; font-size:14px; }");
|
|
|
sb.AppendLine(".btn-start { background:#52c41a; color:#fff; }");
|
|
|
sb.AppendLine(".btn-stop { background:#ff4d4f; color:#fff; }");
|
|
|
sb.AppendLine(".container { max-width:1200px; margin:20px auto; padding:0 20px; }");
|
|
|
sb.AppendLine(".section { background:#fff; border-radius:8px; padding:20px; margin-bottom:16px; box-shadow:0 1px 4px rgba(0,0,0,0.1); }");
|
|
|
sb.AppendLine(".section h2 { font-size:16px; margin-bottom:12px; padding-bottom:8px; border-bottom:1px solid #e8e8e8; }");
|
|
|
sb.AppendLine(".settings-row { display:flex; gap:24px; align-items:center; flex-wrap:wrap; margin-bottom:8px; }");
|
|
|
sb.AppendLine(".settings-row label { font-size:14px; color:#666; min-width:100px; }");
|
|
|
sb.AppendLine(".settings-row input[type=number] { width:80px; padding:4px 8px; border:1px solid #d9d9d9; border-radius:4px; }");
|
|
|
sb.AppendLine(".settings-row select { padding:4px 8px; border:1px solid #d9d9d9; border-radius:4px; }");
|
|
|
sb.AppendLine(".settings-row input[type=radio] { margin-right:4px; }");
|
|
|
sb.AppendLine(".device-cards { display:grid; grid-template-columns:repeat(auto-fill,minmax(320px,1fr)); gap:12px; }");
|
|
|
sb.AppendLine(".device-card { border:1px solid #e8e8e8; border-radius:6px; padding:12px; }");
|
|
|
sb.AppendLine(".device-card.offline { opacity:0.5; background:#fafafa; }");
|
|
|
sb.AppendLine(".device-card h3 { font-size:14px; margin-bottom:8px; }");
|
|
|
sb.AppendLine(".device-card .info { font-size:13px; color:#666; line-height:1.8; }");
|
|
|
sb.AppendLine(".device-card .actions { margin-top:8px; display:flex; flex-wrap:wrap; gap:4px; }");
|
|
|
sb.AppendLine(".device-card .actions button { padding:2px 8px; font-size:12px; border:1px solid #d9d9d9; border-radius:3px; background:#fff; cursor:pointer; }");
|
|
|
sb.AppendLine(".device-card .actions button:hover { border-color:#1890ff; color:#1890ff; }");
|
|
|
sb.AppendLine(".json-preview { max-height:200px; overflow:auto; background:#fafafa; padding:12px; border-radius:4px; font-family:Consolas,monospace; font-size:12px; white-space:pre-wrap; word-break:break-all; }");
|
|
|
sb.AppendLine(".log-table { width:100%; border-collapse:collapse; font-size:13px; }");
|
|
|
sb.AppendLine(".log-table th,.log-table td { padding:6px 8px; text-align:left; border-bottom:1px solid #f0f0f0; }");
|
|
|
sb.AppendLine(".log-table th { background:#fafafa; color:#666; font-weight:600; }");
|
|
|
sb.AppendLine(".stats-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:12px; }");
|
|
|
sb.AppendLine(".stat-item { text-align:center; padding:12px; background:#fafafa; border-radius:4px; }");
|
|
|
sb.AppendLine(".stat-item .value { font-size:24px; font-weight:600; color:#1890ff; }");
|
|
|
sb.AppendLine(".stat-item .label { font-size:13px; color:#999; margin-top:4px; }");
|
|
|
sb.AppendLine(".btn-apply { padding:4px 12px; border:1px solid #1890ff; border-radius:4px; background:#fff; color:#1890ff; cursor:pointer; }");
|
|
|
sb.AppendLine("</style></head><body>");
|
|
|
sb.AppendLine("<div class='header'>");
|
|
|
sb.AppendLine(" <h1>" + server.Name + " (端口 " + server.Port + ")</h1>");
|
|
|
sb.AppendLine(" <div class='header-actions'>");
|
|
|
sb.AppendLine(" <a href='http://localhost:" + server.Port + "/' target='_blank' style='color:#fff;margin-right:8px;font-size:14px;'>数据接口</a>");
|
|
|
sb.AppendLine(" <button class='btn-start' onclick='startSim()'>启动</button>");
|
|
|
sb.AppendLine(" <button class='btn-stop' onclick='stopSim()'>停止</button>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
sb.AppendLine("</div>");
|
|
|
sb.AppendLine("<div class='container'>");
|
|
|
// 全局设置
|
|
|
sb.AppendLine(" <div class='section'><h2>全局设置</h2>");
|
|
|
sb.AppendLine(" <div class='settings-row'>");
|
|
|
sb.AppendLine(" <label>数据变化频率:</label>");
|
|
|
sb.AppendLine(" <input type='number' id='intervalInput' min='1' max='300' value='" + server.Config.DataChangeInterval + "'> 秒");
|
|
|
sb.AppendLine(" <button class='btn-apply' onclick='setInterval2()'>应用</button>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
sb.AppendLine(" <div class='settings-row'>");
|
|
|
sb.AppendLine(" <label>剧本模式:</label>");
|
|
|
sb.AppendLine(" <label><input type='radio' name='mode' value='auto'" + (server.Config.ScenarioMode == "auto" ? " checked" : "") + "> 自动循环</label>");
|
|
|
sb.AppendLine(" <label><input type='radio' name='mode' value='manual'" + (server.Config.ScenarioMode == "manual" ? " checked" : "") + "> 手动触发</label>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
sb.AppendLine(" <div class='settings-row'>");
|
|
|
sb.AppendLine(" <label>网络异常模拟:</label>");
|
|
|
sb.AppendLine(" <select id='networkSelect' onchange='setNetwork(this.value)'>");
|
|
|
sb.AppendLine(" <option value='normal'>正常</option>");
|
|
|
sb.AppendLine(" <option value='http500'>HTTP 500</option>");
|
|
|
sb.AppendLine(" <option value='timeout'>连接超时(60s)</option>");
|
|
|
sb.AppendLine(" <option value='refuse'>拒绝连接</option>");
|
|
|
sb.AppendLine(" <option value='empty'>返回空数组</option>");
|
|
|
sb.AppendLine(" <option value='malformed'>畸形JSON</option>");
|
|
|
sb.AppendLine(" </select>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
// 设备状态卡片
|
|
|
sb.AppendLine(" <div class='section'><h2>设备状态卡片</h2>");
|
|
|
sb.AppendLine(" <div class='device-cards' id='deviceCards'>加载中...</div>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
// JSON预览
|
|
|
sb.AppendLine(" <div class='section'><h2>当前返回JSON预览</h2>");
|
|
|
sb.AppendLine(" <button class='btn-apply' onclick='refreshJson()' style='margin-bottom:8px;'>刷新</button>");
|
|
|
sb.AppendLine(" <div class='json-preview' id='jsonPreview'>加载中...</div>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
// 日志
|
|
|
sb.AppendLine(" <div class='section'><h2>返回数据日志(最近100条)</h2>");
|
|
|
sb.AppendLine(" <table class='log-table'>");
|
|
|
sb.AppendLine(" <thead><tr><th>#</th><th>时间</th><th>设备数</th><th>关键数据</th><th>耗时</th><th>操作</th></tr></thead>");
|
|
|
sb.AppendLine(" <tbody id='logTable'></tbody>");
|
|
|
sb.AppendLine(" </table>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
// 统计
|
|
|
sb.AppendLine(" <div class='section'><h2>统计</h2>");
|
|
|
sb.AppendLine(" <div class='stats-grid' id='statsGrid'>加载中...</div>");
|
|
|
sb.AppendLine(" </div>");
|
|
|
sb.AppendLine("</div>");
|
|
|
// JavaScript
|
|
|
sb.AppendLine("<script>");
|
|
|
sb.AppendLine("var scenarioNames={'machining':'正常加工','same_part':'同一零件','idle':'待机空闲','program_change':'换零件','manual_reset':'手动清零','power_off':'断电','power_on':'恢复开机','pause':'暂停加工'};");
|
|
|
sb.AppendLine("var runNames={0:'待机',1:'运行',3:'加工中'};");
|
|
|
sb.AppendLine("function refresh(){");
|
|
|
sb.AppendLine(" fetch('/admin/api/status').then(r=>r.json()).then(data=>{");
|
|
|
sb.AppendLine(" var cards=document.getElementById('deviceCards');cards.innerHTML='';");
|
|
|
sb.AppendLine(" data.devices.forEach(function(d){");
|
|
|
sb.AppendLine(" var cls=d.isOnline?'':'offline';");
|
|
|
sb.AppendLine(" var scName=scenarioNames[d.scenario]||d.scenario;");
|
|
|
sb.AppendLine(" var h='<div class=\"device-card '+cls+'\">';");
|
|
|
sb.AppendLine(" h+='<h3>'+d.deviceCode+' '+d.desc+(d.isOnline?'':' (离线)')+'</h3>';");
|
|
|
sb.AppendLine(" h+='<div class=\"info\">';");
|
|
|
sb.AppendLine(" h+='场景: '+scName+' ('+d.scenarioTick+'/'+d.scenarioDuration+')<br>';");
|
|
|
sb.AppendLine(" if(d.isOnline){");
|
|
|
sb.AppendLine(" h+='程序: '+d.programName+'<br>';");
|
|
|
sb.AppendLine(" h+='零件数: '+d.partCount+'<br>';");
|
|
|
sb.AppendLine(" h+='运行状态: '+d.runStatus+' ('+runNames[d.runStatus]+')<br>';");
|
|
|
sb.AppendLine(" h+='主轴: '+d.spindleSpeedActual+'/'+d.spindleSpeedSet+' 负载'+d.spindleLoad+'%<br>';");
|
|
|
sb.AppendLine(" h+='进给: '+d.feedSpeedActual+'/'+d.feedSpeedSet+'<br>';");
|
|
|
sb.AppendLine(" h+='加工: '+d.machiningStatus;");
|
|
|
sb.AppendLine(" } else { h+='(设备离线,不返回数据)'; }");
|
|
|
sb.AppendLine(" h+='</div>';");
|
|
|
|
|
|
// 按钮使用data属性避免转义问题
|
|
|
sb.AppendLine(" h+='<div class=\"actions\" data-device=\"'+d.deviceCode+'\">';");
|
|
|
sb.AppendLine(" h+='<button data-event=\"program_change\">换零件</button>';");
|
|
|
sb.AppendLine(" h+='<button data-event=\"manual_reset\">手动清零</button>';");
|
|
|
sb.AppendLine(" h+='<button data-event=\"power_off\">断电</button>';");
|
|
|
sb.AppendLine(" h+='<button data-event=\"pause\">暂停</button>';");
|
|
|
sb.AppendLine(" h+='<button data-event=\"power_on\">恢复</button>';");
|
|
|
sb.AppendLine(" h+='<button data-event=\"machining\">加工</button>';");
|
|
|
sb.AppendLine(" h+='<button data-event=\"idle\">待机</button>';");
|
|
|
sb.AppendLine(" h+='</div></div>';");
|
|
|
sb.AppendLine(" cards.innerHTML+=h;");
|
|
|
sb.AppendLine(" });");
|
|
|
|
|
|
// 事件委托处理按钮点击
|
|
|
sb.AppendLine(" document.querySelectorAll('.device-card .actions button').forEach(function(btn){");
|
|
|
sb.AppendLine(" btn.onclick=function(){");
|
|
|
sb.AppendLine(" var dev=this.parentElement.getAttribute('data-device');");
|
|
|
sb.AppendLine(" var evt=this.getAttribute('data-event');");
|
|
|
sb.AppendLine(" triggerEvent(dev,evt);");
|
|
|
sb.AppendLine(" };");
|
|
|
sb.AppendLine(" });");
|
|
|
|
|
|
// 统计
|
|
|
sb.AppendLine(" var sg=document.getElementById('statsGrid');");
|
|
|
sb.AppendLine(" sg.innerHTML='<div class=\"stat-item\"><div class=\"value\">'+data.requestCount+'</div><div class=\"label\">总请求次数</div></div>';");
|
|
|
sb.AppendLine(" sg.innerHTML+='<div class=\"stat-item\"><div class=\"value\">'+data.successCount+'</div><div class=\"label\">成功次数</div></div>';");
|
|
|
sb.AppendLine(" sg.innerHTML+='<div class=\"stat-item\"><div class=\"value\">'+data.failCount+'</div><div class=\"label\">失败次数</div></div>';");
|
|
|
sb.AppendLine(" sg.innerHTML+='<div class=\"stat-item\"><div class=\"value\">'+data.onlineDevices+'/'+data.totalDevices+'</div><div class=\"label\">在线/总设备</div></div>';");
|
|
|
sb.AppendLine(" sg.innerHTML+='<div class=\"stat-item\"><div class=\"value\">'+data.uptime+'</div><div class=\"label\">运行时长</div></div>';");
|
|
|
sb.AppendLine(" sg.innerHTML+='<div class=\"stat-item\"><div class=\"value\">'+data.dataChangeInterval+'s</div><div class=\"label\">数据频率</div></div>';");
|
|
|
sb.AppendLine(" }).catch(function(){});");
|
|
|
sb.AppendLine("}");
|
|
|
|
|
|
sb.AppendLine("function refreshJson(){");
|
|
|
sb.AppendLine(" fetch('/data').then(r=>r.text()).then(json=>{");
|
|
|
sb.AppendLine(" try{document.getElementById('jsonPreview').textContent=JSON.stringify(JSON.parse(json),null,2);}");
|
|
|
sb.AppendLine(" catch(e){document.getElementById('jsonPreview').textContent=json;}");
|
|
|
sb.AppendLine(" }).catch(function(e){document.getElementById('jsonPreview').textContent='请求失败: '+e.message;});");
|
|
|
sb.AppendLine("}");
|
|
|
|
|
|
sb.AppendLine("var allLogs=[];");
|
|
|
sb.AppendLine("function refreshLogs(){");
|
|
|
sb.AppendLine(" fetch('/admin/api/logs').then(r=>r.json()).then(logs=>{");
|
|
|
sb.AppendLine(" allLogs=logs;var tb=document.getElementById('logTable');tb.innerHTML='';");
|
|
|
sb.AppendLine(" logs.forEach(function(l){");
|
|
|
sb.AppendLine(" var tr=document.createElement('tr');");
|
|
|
sb.AppendLine(" tr.innerHTML='<td>'+l.index+'</td><td>'+l.timestamp+'</td><td>'+l.deviceCount+'</td><td>'+l.keyData+'</td><td>'+l.duration+'ms</td><td></td>';");
|
|
|
sb.AppendLine(" var btn=document.createElement('button');");
|
|
|
sb.AppendLine(" btn.textContent='完整JSON';btn.style.cssText='font-size:12px;padding:2px 6px;cursor:pointer;';");
|
|
|
sb.AppendLine(" btn.onclick=(function(idx){return function(){showJson(idx);};})(l.index);");
|
|
|
sb.AppendLine(" tr.cells[5].appendChild(btn);");
|
|
|
sb.AppendLine(" tb.appendChild(tr);");
|
|
|
sb.AppendLine(" });");
|
|
|
sb.AppendLine(" }).catch(function(){});");
|
|
|
sb.AppendLine("}");
|
|
|
|
|
|
sb.AppendLine("function showJson(idx){");
|
|
|
sb.AppendLine(" var l=allLogs.find(function(x){return x.index===idx;});");
|
|
|
sb.AppendLine(" if(l){try{document.getElementById('jsonPreview').textContent=JSON.stringify(JSON.parse(l.fullJson),null,2);}catch(e){document.getElementById('jsonPreview').textContent=l.fullJson;}}");
|
|
|
sb.AppendLine("}");
|
|
|
|
|
|
sb.AppendLine("function startSim(){fetch('/admin/api/start',{method:'POST'}).then(function(){refresh();});}");
|
|
|
sb.AppendLine("function stopSim(){fetch('/admin/api/stop',{method:'POST'}).then(function(){refresh();});}");
|
|
|
sb.AppendLine("function setInterval2(){var v=document.getElementById('intervalInput').value;fetch('/admin/api/interval',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({value:parseInt(v)})}).then(function(){refresh();});}");
|
|
|
sb.AppendLine("function setNetwork(type){fetch('/admin/api/network',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({type:type})}).then(function(){});}");
|
|
|
sb.AppendLine("function triggerEvent(deviceId,eventType){fetch('/admin/api/event',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({deviceId:deviceId,eventType:eventType})}).then(function(){setTimeout(refresh,500);});}");
|
|
|
|
|
|
sb.AppendLine("document.querySelectorAll('input[name=mode]').forEach(function(r){");
|
|
|
sb.AppendLine(" r.addEventListener('change',function(){");
|
|
|
sb.AppendLine(" fetch('/admin/api/mode',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mode:this.value})}).then(function(){});");
|
|
|
sb.AppendLine(" });");
|
|
|
sb.AppendLine("});");
|
|
|
|
|
|
sb.AppendLine("setInterval(function(){refresh();refreshJson();refreshLogs();},2000);");
|
|
|
sb.AppendLine("refresh();refreshJson();refreshLogs();");
|
|
|
sb.AppendLine("</script></body></html>");
|
|
|
return sb.ToString();
|
|
|
}
|
|
|
}
|
|
|
}
|