From c4e2783120d0db5782f31681cf5c69f510f474c5 Mon Sep 17 00:00:00 2001 From: qinglong Date: Thu, 11 Jun 2026 12:12:03 +0800 Subject: [PATCH] WebUI: MD3 projects/proxy pages, sidebar links, CSS animations - Add projects + proxy nav items to sidebar - Rewrite projects.html with MD3 cards + tabs + mgmt-cards - Rewrite proxy.html with MD3 form + mgmt-cards - CSS: button ripple, card elevation, page fade, tab slide, input glow, nav dot, status pulse, log entry fade, shimmer, scrollbar, badge bounce, card hover mouse-glow (428 lines) --- static/web_panel/css/style.css | 95 ++++++++++++++++++ static/web_panel/home.html | 8 ++ static/web_panel/pages/projects.html | 141 ++++++++------------------- static/web_panel/pages/proxy.html | 49 ++++++---- 4 files changed, 175 insertions(+), 118 deletions(-) diff --git a/static/web_panel/css/style.css b/static/web_panel/css/style.css index 2865df3..8a080fb 100644 --- a/static/web_panel/css/style.css +++ b/static/web_panel/css/style.css @@ -331,3 +331,98 @@ h3{font-size:1rem;font-weight:500;letter-spacing:.15px} font-size:20px;transition:.2s; } .theme-toggle:hover{background:rgba(208,188,255,.08)} + +/* ═══════════════════════════════════════════ + MD3 Animations & Micro-interactions + ═══════════════════════════════════════════ */ + +/* ── Button Ripple ── */ +.btn{position:relative;overflow:hidden;transform:translateZ(0)} +.btn::after{ + content:"";position:absolute;inset:0;background:radial-gradient(circle at center,currentColor 10%,transparent 10%); + background-size:0 0;background-repeat:no-repeat;opacity:0;transition:background-size .4s,opacity .3s; +} +.btn:active::after{background-size:300% 300%;opacity:.12;transition:0s} + +/* ── Card Elevation Transition ── */ +.card,.stat-card,.mgmt-card,.side-card{ + transition:box-shadow .3s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1),background .3s; +} +.card:hover,.stat-card:hover,.mgmt-card:hover{transform:translateY(-1px)} +.card:active{transform:translateY(0)} + +/* ── Page Transition Fade ── */ +.page-container{animation:pageIn .25s cubic-bezier(.4,0,.2,1)} +@keyframes pageIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}} + +/* ── Tab Indicator Slide ── */ +.tab{position:relative;transition:color .2s,background .25s} +.tab.active::after{ + content:"";position:absolute;bottom:0;left:25%;right:25%;height:2px; + background:var(--primary);border-radius:2px 2px 0 0; + animation:tabSlide .3s cubic-bezier(.4,0,.2,1) +} +@keyframes tabSlide{from{transform:scaleX(0)}to{transform:scaleX(1)}} + +/* ── Input Focus Glow ── */ +.input{transition:border-color .25s,box-shadow .25s,background .25s} +.input:focus{animation:inputGlow .6s ease-out} +@keyframes inputGlow{0%{box-shadow:0 0 0 0 rgba(208,188,255,.4)}100%{box-shadow:0 0 0 4px rgba(208,188,255,0)}} + +/* ── Sidebar Collapse ── */ +.sidebar{transition:width .3s cubic-bezier(.4,0,.2,1)} +.nav-item .nav-label{transition:opacity .25s,width .3s;opacity:1} +.app-frame.collapsed .nav-label{opacity:0;width:0} + +/* ── Nav Item Active Dot ── */ +.nav-item.active::before{ + content:"";position:absolute;left:0;top:50%;transform:translateY(-50%); + width:3px;height:20px;background:var(--primary);border-radius:0 3px 3px 0; + animation:navDotIn .3s cubic-bezier(.4,0,.2,1) +} +@keyframes navDotIn{from{height:0;opacity:0}to{height:20px;opacity:1}} + +/* ── Status Dot Pulse ── */ +.status-running{animation:statusPulse 2s ease-in-out infinite} +@keyframes statusPulse{0%,100%{box-shadow:0 0 4px rgba(158,206,106,.4)}50%{box-shadow:0 0 12px rgba(158,206,106,.7)}} + +/* ── Loading Skeleton Shimmer ── */ +.skeleton{background:linear-gradient(90deg,var(--bg-card) 25%,var(--bg-elevated) 50%,var(--bg-card) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:var(--shape-xs);height:1rem} +@keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}} + +/* ── Progress Bar ── */ +.progress-bar{transition:width .3s cubic-bezier(.4,0,.2,1),opacity .2s} + +/* ── Badge Bounce ── */ +@keyframes badgeIn{0%{transform:scale(0);opacity:0}60%{transform:scale(1.2)}100%{transform:scale(1);opacity:1}} +.badge{animation:badgeIn .3s cubic-bezier(.4,0,.2,1)} + +/* ── FAB Float ── */ +.fab{transition:box-shadow .3s,transform .2s cubic-bezier(.4,0,.2,1),filter .2s} +.fab:hover{transform:scale(1.05)} + +/* ── Log Entry Fade ── */ +.log-entry{animation:logIn .2s ease-out} +@keyframes logIn{from{opacity:0;transform:translateX(-8px)}to{opacity:1;transform:translateX(0)}} + +/* ── Toggle Theme Button Spin ── */ +.theme-toggle{transition:transform .3s cubic-bezier(.4,0,.2,1)} +.theme-toggle:hover{transform:rotate(30deg)} + +/* ── Scrollbar MD3 Style ── */ +::-webkit-scrollbar{width:6px} +::-webkit-scrollbar-track{background:transparent} +::-webkit-scrollbar-thumb{background:var(--outline);border-radius:3px} +::-webkit-scrollbar-thumb:hover{background:var(--text-dim)} + +/* ── Ripple on Management Cards ── */ +.mgmt-card,.plugin-card{position:relative;overflow:hidden} +.mgmt-card::before,.plugin-card::before{ + content:"";position:absolute;inset:0;background:radial-gradient(circle at var(--mouse-x,50%) var(--mouse-y,50%),rgba(208,188,255,.1) 0%,transparent 60%); + opacity:0;transition:opacity .3s +} +.mgmt-card:hover::before,.plugin-card:hover::before{opacity:1} + +/* ── Menu reveal animation for login error ── */ +.err-msg{transition:opacity .3s} + diff --git a/static/web_panel/home.html b/static/web_panel/home.html index e020abd..2828200 100644 --- a/static/web_panel/home.html +++ b/static/web_panel/home.html @@ -34,6 +34,14 @@ 插件管理 + + + 项目管理 + + + + 反向代理 +
diff --git a/static/web_panel/pages/projects.html b/static/web_panel/pages/projects.html index 7a73320..7b778fa 100644 --- a/static/web_panel/pages/projects.html +++ b/static/web_panel/pages/projects.html @@ -1,119 +1,60 @@ - -项目管理 - SenSu - - -

📦 项目管理

+
+

📦 项目管理

+
-
运行中
-
+ 添加项目
+
运行中
+
+ 添加项目
+
Git 部署
-
加载中...
+
加载中...
+ - \ No newline at end of file diff --git a/static/web_panel/pages/proxy.html b/static/web_panel/pages/proxy.html index c709612..8637ce0 100644 --- a/static/web_panel/pages/proxy.html +++ b/static/web_panel/pages/proxy.html @@ -1,19 +1,32 @@ -反向代理 - SenSu - -

🔀 反向代理

-

添加代理

-
-
-
-
-
加载中...
+
+

🔀 反向代理

+ +
+

添加代理

+
框架路径
+
目标 URL
+
描述 (可选)
+ +
+ +
加载中...
+
+ \ No newline at end of file +function refresh(){ + fetch("/SenSu/api/proxy").then(r=>r.json()).then(d=>{ + var h=""; + for(var p of d.proxies||[]){ + h+='
'+p.path+'
→ '+p.target+(p.description?" ("+p.description+")":"")+(p.external?" 🌐":"")+'
'; + } + document.getElementById("proxy-list").innerHTML=h||"暂无代理" + }) +} +function addP(){ + var p=document.getElementById("px-path").value,t=document.getElementById("px-target").value; + if(!p||!t){alert("请填写");return} + fetch("/SenSu/api/proxy",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:p,target:t,description:document.getElementById("px-desc").value})}).then(r=>r.json()).then(d=>{if(d.ok)refresh()}) +} +function delP(path){fetch("/SenSu/api/proxy/"+encodeURIComponent(path),{method:"DELETE"}).then(()=>refresh())} +refresh(); +