feat: create new dashboard button with auto-generated UUID

This commit is contained in:
2026-07-27 09:47:07 +08:00
parent b8f07c0cba
commit a6adedaadb
+18 -1
View File
@@ -141,6 +141,7 @@ const PageDashboard = {
document.getElementById('dash-search')?.addEventListener('input', () => this._loadThemes()); document.getElementById('dash-search')?.addEventListener('input', () => this._loadThemes());
document.getElementById('dash-sort')?.addEventListener('change', () => this._loadThemes()); document.getElementById('dash-sort')?.addEventListener('change', () => this._loadThemes());
document.getElementById('btn-new-dashboard')?.addEventListener('click', () => this._createNew());
document.getElementById('btn-import-dashboard')?.addEventListener('click', () => { document.getElementById('btn-import-dashboard')?.addEventListener('click', () => {
const input = document.createElement('input'); input.type = 'file'; input.accept = '.tsd'; const input = document.createElement('input'); input.type = 'file'; input.accept = '.tsd';
input.onchange = async (e) => { input.onchange = async (e) => {
@@ -305,12 +306,28 @@ const PageDashboard = {
</div>`; </div>`;
}, },
async _createNew() {
const name = prompt('仪表盘名称:', 'My Dashboard');
if (!name) return;
try {
const html = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>TurboSu - ' + name + '</title><style>*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}html,body{width:100%;height:100%;overflow:hidden;background:#0a0a0f;color:#fff;font-family:sans-serif}#root{width:100%;height:100%;display:flex;align-items:center;justify-content:center}#box{position:relative;overflow:hidden}#box.contain{max-width:100vw;max-height:100vh}#box.cover{min-width:100vw;min-height:100vh}#box.fill{width:100vw;height:100vh}</style></head><body><div id="root"><div id="box" class="contain"><div data-bind="speed_kmh" style="font-size:80px;font-weight:200">0</div></div></div><script>const M={aspect_ratio:"auto",render_mode:"contain"};(function(){const b=document.getElementById("box"),p=location.protocol==="https:"?"wss:":"ws:";let w,r;function a(){const rt=M.aspect_ratio==="auto"?null:(c=>{const p=c.split(":");return p.length===2?+p[0]/+p[1]:null})(M.aspect_ratio),md=M.render_mode||"contain";if(!rt){b.style.width="100vw";b.style.height="100vh";b.className="fill";return}const vw=window.innerWidth,vh=window.innerHeight,vr=vw/vh;let cw,ch;if(md==="cover"){cw=vw;ch=vw/rt;b.className="cover"}else{b.className="contain";cw=vr>rt?vh*rt:vw;ch=vr>rt?vh:vw/rt}b.style.width=cw+"px";b.style.height=ch+"px"}function c(){w=new WebSocket(p+"//"+location.host+"/ws");w.onopen=()=>{if(r){clearTimeout(r);r=null}};w.onmessage=(e)=>{try{const m=JSON.parse(e.data);if(m.type==="telemetry")document.querySelectorAll("[data-bind]").forEach(el=>{const v=m.data[el.getAttribute("data-bind")];if(v!==undefined)el.textContent=typeof v==="number"?v.toFixed(1):v})}catch(e){}};w.onclose=()=>{r=setTimeout(c,2000)}}a();window.addEventListener("resize",a);c()})();<\/script></body></html>';
const res = await fetch('/api/dashboards', {
method: 'POST', headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name, category: 'custom', author: 'Local', config: {icon: '📊', aspect_ratio: 'auto', render_mode: 'contain'}, index_html: html})
});
const data = await res.json();
if (data.id) { Toast.show('创建成功', 'success'); this._loadThemes(); }
else Toast.show('创建失败', 'error');
} catch (e) { Toast.show('创建失败', 'error'); }
},
_template() { _template() {
return ` return `
<div class="dashboard-layout"> <div class="dashboard-layout">
<div class="dashboard-sub-sidebar"> <div class="dashboard-sub-sidebar">
<div id="dash-category-list"></div> <div id="dash-category-list"></div>
<div style="padding:8px 12px;margin-top:auto"> <div style="padding:8px 12px;margin-top:auto;display:flex;flex-direction:column;gap:4px">
<button id="btn-new-dashboard" class="btn btn-sm btn-primary" style="width:100%;">+ 新建</button>
<button id="btn-import-dashboard" class="btn btn-sm btn-secondary" style="width:100%;">导入 .tsd</button> <button id="btn-import-dashboard" class="btn btn-sm btn-secondary" style="width:100%;">导入 .tsd</button>
</div> </div>
</div> </div>