Polish navigation and pipeline flow

This commit is contained in:
iye
2026-05-28 15:35:32 +08:00
parent bbe29622c2
commit df7b90934a
8 changed files with 782 additions and 66 deletions
+33 -4
View File
@@ -8,6 +8,7 @@
============================================================ */
const ShellIcon = (name, opts) => window.IconKit ? window.IconKit.svg(name, opts) : '';
const SHELL_SIDEBAR_COLLAPSED_KEY = 'airshelf:sidebar-collapsed';
const NAV = [
{
@@ -64,7 +65,7 @@ const SHELL_COMMANDS = [
window.Shell = {
render({ active = '', crumbs = [], balance = '¥327.40', topActions = '' } = {}) {
const navHtml = NAV.map(n => `
<a href="${n.href}" class="${active === n.id ? 'active' : ''}">
<a href="${n.href}" class="${active === n.id ? 'active' : ''}" title="${n.label}" aria-label="${n.label}">
${n.icon}
<span>${n.label}</span>
${n.badge ? `<span class="pill-mini">${n.badge}</span>` : ''}
@@ -73,10 +74,16 @@ window.Shell = {
const sidebar = `
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="assets/logo.png" alt="Airshelf">
<div class="sidebar-head">
<a class="brand" href="index.html" aria-label="Airshelf 工作台">
<span class="brand-clip"><img class="brand-logo" src="assets/logo.png" alt="Airshelf"></span>
</a>
</div>
<div class="search-box" onclick="Shell.openCommandPalette()">
<button class="sidebar-toggle" type="button" onclick="Shell.toggleSidebarCollapse()" aria-label="收窄导航" title="收窄导航">
<span class="sidebar-toggle-icon sidebar-toggle-icon--collapse">${ShellIcon('chevronLeft', { size: 18, strokeWidth: 1.8 })}</span>
<span class="sidebar-toggle-icon sidebar-toggle-icon--expand">${ShellIcon('chevronRight', { size: 18, strokeWidth: 1.8 })}</span>
</button>
<div class="search-box" onclick="Shell.openCommandPalette()" title="搜索">
${ShellIcon('search')}
<input id="global-search" placeholder="搜索" readonly aria-label="打开全局搜索"/>
<span class="kbd">Ctrl K</span>
@@ -328,9 +335,11 @@ window.Shell = {
const app = document.createElement('div');
app.className = 'app';
app.innerHTML = sidebar + `<main>${decorations}${topbar}<div class="content" id="page-content">${cornerMarks}</div></main>`;
this.applySidebarCollapse(this.isSidebarCollapsed());
const src = document.getElementById('page');
document.body.prepend(app);
this.applySidebarCollapse(this.isSidebarCollapsed());
if (src) {
// 把页面 body 内容追加到 .content,保留 4 个 corner-mark SVG
document.getElementById('page-content').insertAdjacentHTML('beforeend', src.innerHTML);
@@ -352,6 +361,26 @@ window.Shell = {
this._bindGlobalChrome();
},
isSidebarCollapsed() {
return localStorage.getItem(SHELL_SIDEBAR_COLLAPSED_KEY) === '1';
},
applySidebarCollapse(collapsed) {
document.body.classList.toggle('sidebar-collapsed', !!collapsed);
const btn = document.querySelector('.sidebar-toggle');
if (!btn) return;
const label = collapsed ? '展开导航' : '收窄导航';
btn.setAttribute('aria-label', label);
btn.setAttribute('title', label);
btn.setAttribute('aria-pressed', collapsed ? 'true' : 'false');
},
toggleSidebarCollapse() {
const next = !this.isSidebarCollapsed();
localStorage.setItem(SHELL_SIDEBAR_COLLAPSED_KEY, next ? '1' : '0');
this.applySidebarCollapse(next);
},
_esc(s) {
return String(s ?? '').replace(/[&<>"']/g, c => ({
'&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'