feat(web): add standalone HTML design demo with full layout + 3 dialog types + color tokens

This commit is contained in:
2026-05-19 08:25:44 +08:00
parent ffbb0652d9
commit 3dc71de739
@@ -0,0 +1,300 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CraftLabs 设计系统 Demo</title>
<style>
:root {
--brand: #2C3E6B; --brand-hover: #3D5A99; --page-bg: #EAEFFA;
--card-bg: #FFFFFF; --border: #E8ECF1; --border-input: #E0E3E8;
--text: #303133; --text2: #606266; --text3: #909399; --text4: #C0C4CC;
--th-bg: #F2F5FC; --danger: #F56C6C; --danger-bg: #FEF0F0;
--success: #1A7A3A; --success-bg: #E6F7EE; --warning: #E6A23C;
--warning-bg: #FDF6EC; --badge: #D54941; --search-bg: #F8F9FB;
--radius: 6px; --radius-sm: 4px; --radius-dlg: 8px;
}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:var(--page-bg);color:var(--text);font-size:14px;line-height:1.5}
button{cursor:pointer;font-family:inherit;border:none}
input,select{font-family:inherit;outline:none}
/* Header */
.header{height:60px;background:#fff;border-bottom:1px solid var(--border);display:flex;align-items:center;padding:0 20px;position:sticky;top:0;z-index:100}
.header-l{display:flex;align-items:center;gap:28px}
.logo{display:flex;align-items:center;gap:8px}
.logo-icon{width:28px;height:28px;background:linear-gradient(135deg,var(--brand),var(--brand-hover));border-radius:6px}
.logo-text{font-weight:700;font-size:16px;color:var(--brand)}
.nav-item{padding:0 16px;height:60px;line-height:60px;cursor:pointer;font-size:14px;color:var(--text2)}
.nav-item.active{color:var(--brand);font-weight:600;border-bottom:2px solid var(--brand)}
.header-r{margin-left:auto;display:flex;align-items:center;gap:10px}
.g-search{display:flex;align-items:center;border:1px solid var(--border-input);border-radius:var(--radius);padding:4px 10px;gap:6px;width:220px;background:var(--search-bg)}
.g-search input{border:none;outline:none;flex:1;font-size:13px;background:transparent;color:var(--text)}
.g-search span{color:var(--text4);font-size:13px}
.icon-btn{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:6px;cursor:pointer;font-size:14px;position:relative;color:var(--text2)}
.icon-btn:hover{background:var(--th-bg)}
.badge-dot{position:absolute;top:-2px;right:-5px;width:16px;height:16px;background:var(--badge);border-radius:50%;font-size:10px;color:#fff;line-height:16px;text-align:center;font-weight:600}
.user{display:flex;align-items:center;gap:6px;padding:4px 10px;border-radius:6px;cursor:pointer}
.user:hover{background:var(--th-bg)}
.avatar{width:28px;height:28px;border-radius:50%;background:var(--brand);color:#fff;text-align:center;line-height:28px;font-size:12px;font-weight:600;flex-shrink:0}
/* Layout */
.body{display:flex;height:calc(100vh - 60px)}
.sidebar{width:232px;background:#fff;border-right:1px solid var(--border);overflow-y:auto;flex-shrink:0;padding-top:8px}
.sec-label{padding:6px 20px;font-size:11px;color:var(--text4);text-transform:uppercase;font-weight:600;letter-spacing:.5px}
.menu-item{display:flex;align-items:center;gap:10px;padding:9px 20px;cursor:pointer;font-size:14px;color:var(--text2);border-right:3px solid transparent;transition:all .15s}
.menu-item:hover{background:var(--th-bg);color:var(--brand)}
.menu-item.act{background:var(--th-bg);color:var(--brand);font-weight:600;border-right-color:var(--brand)}
.menu-item .mi-badge{background:var(--badge);color:#fff;font-size:10px;padding:1px 6px;border-radius:10px;font-weight:600;margin-left:auto}
.s-footer{margin-top:auto;padding:12px 20px;border-top:1px solid var(--th-bg);font-size:11px;color:var(--text4)}
.content{flex:1;display:flex;flex-direction:column;overflow:hidden}
.breadcrumb{height:46px;background:#fff;border-bottom:1px solid var(--border);display:flex;align-items:center;padding:0 20px;gap:6px;font-size:13px;flex-shrink:0}
.bc-sep{color:var(--text4)}.bc-cur{color:var(--brand);font-weight:600}
.main{flex:1;overflow-y:auto;padding:16px 20px}
/* Shared */
.card{background:var(--card-bg);border-radius:var(--radius);border:1px solid var(--border);box-shadow:0 1px 2px rgba(0,0,0,.03)}
.btn{font-size:13px;font-weight:500;border-radius:var(--radius-sm);padding:6px 14px}
.btn-primary{background:var(--brand);color:#fff}.btn-primary:hover{background:var(--brand-hover)}
.btn-create{box-shadow:0 2px 6px rgba(44,62,107,.2);padding:7px 16px}
.btn-cancel{background:#fff;color:var(--text2);border:1px solid var(--border-input);padding:8px 20px;border-radius:var(--radius-sm);font-size:14px}
.btn-danger{background:var(--danger);color:#fff;padding:8px 20px;border-radius:var(--radius-sm);font-size:14px}
.tag{display:inline-block;padding:2px 8px;border-radius:3px;font-size:11px;font-weight:500}
.tag-ok{background:var(--success-bg);color:var(--success);border:1px solid #A8E6C1}
.tag-bad{background:var(--danger-bg);color:var(--danger);border:1px solid #FBC4C4}
.tag-warn{background:var(--warning-bg);color:var(--warning);border:1px solid #F5DAB1}
.tag-gray{background:#f4f4f5;color:var(--text3);border:1px solid #e9e9eb}
/* Page: license */
.license-page{display:flex;height:100%}
.tree-panel{width:280px;background:#fff;border-right:1px solid var(--border);flex-shrink:0;display:flex;flex-direction:column}
.tree-search{padding:12px 14px}
.tree-search .ts-inner{display:flex;align-items:center;border:1px solid var(--border-input);border-radius:var(--radius);padding:6px 10px;gap:6px;background:var(--search-bg)}
.tree-search input{border:none;outline:none;flex:1;font-size:12px;background:transparent}
.tree-search span{color:var(--text4);font-size:12px}
.tree-body{flex:1;overflow-y:auto;padding:4px 0}
.tn{display:flex;align-items:center;gap:6px;padding:5px 16px 5px 20px;cursor:pointer;font-size:13px;color:var(--text2)}
.tn:hover{background:var(--th-bg)}
.tn.act{background:var(--th-bg);color:var(--brand);font-weight:600;border-right:3px solid var(--brand)}
.tn .tn-count{margin-left:auto;font-size:11px;color:var(--text4)}
.tn .tn-arrow{font-size:11px;width:14px;text-align:center}
.main-panel{flex:1;overflow-y:auto;padding:16px 20px;display:flex;flex-direction:column;gap:12px}
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.st{cursor:default}
.st-num{font-size:28px;font-weight:700;text-align:center}
.st-label{font-size:12px;color:var(--text3);text-align:center;margin-top:4px}
.filter-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.filter-l{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.f-input{display:flex;align-items:center;border:1px solid var(--border-input);border-radius:var(--radius-sm);padding:6px 10px;gap:6px;background:var(--search-bg);width:220px}
.f-input input{border:none;outline:none;flex:1;font-size:13px;background:transparent}
.f-input span{color:var(--text4);font-size:13px}
.f-select{border:1px solid var(--border-input);border-radius:var(--radius-sm);padding:6px 10px;font-size:13px;color:var(--text2);background:#fff}
table.dt{width:100%;border-collapse:collapse;font-size:13px}
.dt th{padding:10px 12px;text-align:left;font-weight:600;font-size:12px;color:var(--brand);background:var(--th-bg);border-bottom:1px solid var(--border);white-space:nowrap}
.dt td{padding:9px 12px;border-bottom:1px solid var(--th-bg)}
.dt tr:hover td{background:#F8F9FB}
.td-mono{font-family:monospace;font-size:12px;color:var(--text)}
.td-secondary{color:var(--text2)}.td-center{text-align:center}.td-time{color:var(--text3);font-size:12px}
.td-action a{color:var(--brand);cursor:pointer;margin-right:10px;text-decoration:none;font-size:13px}
.td-action a.danger{color:var(--danger)}
.tf{padding:10px 16px;display:flex;justify-content:flex-end;font-size:12px;color:var(--text3);border-top:1px solid var(--th-bg)}
/* Dialog overlay */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:1000;display:none;align-items:center;justify-content:center}
.modal-overlay.show{display:flex}
.dialog{background:#fff;border-radius:var(--radius-dlg);box-shadow:0 8px 40px rgba(0,0,0,.15);animation:dIn .2s ease-out;max-height:85vh;overflow-y:auto}
.d-header{padding:16px 20px;border-bottom:1px solid var(--th-bg);display:flex;align-items:center;justify-content:space-between}
.d-title{font-size:16px;font-weight:600}
.d-close{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:4px;cursor:pointer;color:var(--text3);font-size:16px}
.d-close:hover{background:var(--th-bg);color:var(--text)}
.d-body{padding:20px}
.d-footer{padding:12px 20px 16px;display:flex;justify-content:flex-end;gap:10px;border-top:1px solid var(--th-bg)}
.form-g{margin-bottom:16px}
.form-l{display:block;font-size:13px;color:var(--text2);margin-bottom:4px;font-weight:500}
.form-i{width:100%;border:1px solid var(--border-input);border-radius:var(--radius-sm);padding:7px 12px;font-size:13px;color:var(--text)}
.form-i:focus{border-color:var(--brand)}
.form-row{display:flex;gap:12px}.form-row>div{flex:1}
.check-group{display:flex;flex-wrap:wrap;gap:10px 20px}
.check-group label{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:13px;color:var(--text2)}
.check-group input{accent-color:var(--brand)}
.detail-row{display:flex;padding:8px 0;border-bottom:1px solid var(--th-bg)}
.detail-l{width:100px;text-align:right;padding-right:16px;font-size:13px;color:var(--text3);flex-shrink:0}
.detail-v{flex:1;font-size:13px;color:var(--text)}
.info-box{padding:10px 12px;border-radius:var(--radius-sm);font-size:12px;margin-top:12px}
.info-box.gray{background:var(--search-bg);border:1px solid var(--border);color:var(--text2)}
.info-box.red{background:var(--danger-bg);border:1px solid #FBC4C4;color:var(--danger)}
@keyframes dIn{from{opacity:0;transform:scale(.96) translateY(-10px)}to{opacity:1;transform:scale(1) translateY(0)}}
/* Color showcase */
.swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}
.swatch{background:#fff;border-radius:var(--radius);border:1px solid var(--border);padding:14px;display:flex;align-items:center;gap:12px}
.swatch-box{width:48px;height:48px;border-radius:6px;border:1px solid var(--border);flex-shrink:0}
.swatch-info{flex:1}
.swatch-name{font-weight:600;font-size:13px}.swatch-hex{font-size:11px;color:var(--text3);font-family:monospace;margin-top:2px}
/* Tab */
.tabs{display:flex;gap:0;margin-bottom:16px;background:#fff;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border)}
.tab{cursor:pointer;padding:10px 20px;font-size:13px;color:var(--text2);border-bottom:2px solid transparent}
.tab.on{color:var(--brand);font-weight:600;border-bottom-color:var(--brand)}
.panel{display:none}.panel.show{display:block}
</style>
</head>
<body>
<!-- HEADER -->
<header class="header">
<div class="header-l">
<div class="logo"><div class="logo-icon"></div><span class="logo-text">CraftLabs</span></div>
<span class="nav-item active">授权平台</span>
<span class="nav-item">运营分析</span>
</div>
<div class="header-r">
<div class="g-search"><span>🔍</span><input placeholder="搜索许可证 / 客户 / 合同…"></div>
<div class="icon-btn"><span style="position:relative">🔔<span class="badge-dot">3</span></span></div>
<div class="icon-btn"><span>⚙️</span></div>
<div class="user"><span class="avatar"></span><span class="user-name">huangping</span></div>
</div>
</header>
<div class="body">
<!-- SIDEBAR -->
<aside class="sidebar">
<div class="sec-label">业务管理</div>
<div class="menu-item"><span>📊</span><span>工作台</span></div>
<div class="menu-item"><span>👥</span><span>客户管理</span></div>
<div class="menu-item"><span>📋</span><span>合同管理</span></div>
<div class="menu-item"><span>📦</span><span>交付管理</span></div>
<div class="menu-item"><span>🔑</span><span>许可 SN</span></div>
<div class="sec-label">授权运营</div>
<div class="menu-item act" onclick="switchTo('license')"><span>🛡️</span><span>许可证管理</span><span class="mi-badge">NEW</span></div>
<div class="menu-item" onclick="switchTo('callback')"><span>📨</span><span>Callback 收件箱</span><span class="mi-badge">3</span></div>
<div class="sec-label">集成配置</div>
<div class="menu-item"><span>🌐</span><span>集成环境</span></div>
<div class="menu-item"><span>📱</span><span>产品线</span></div>
<div class="sec-label">系统运维</div>
<div class="menu-item"><span>🔐</span><span>密钥管理</span></div>
<div class="s-footer">CraftLabs Platform v0.1.0</div>
</aside>
<!-- CONTENT -->
<div class="content">
<div class="breadcrumb"><span class="bc-cur" id="bcCur">授权运营 许可证管理</span></div>
<div class="main">
<!-- LICENSES PAGE -->
<div id="panel-license" class="panel show">
<div class="license-page" style="margin:-16px -20px;height:calc(100vh - 168px)">
<!-- Tree -->
<div class="tree-panel">
<div class="tree-search"><div class="ts-inner"><span>🔍</span><input placeholder="搜索客户/项目..."></div></div>
<div class="tree-body">
<div class="tn"><span class="tn-arrow"></span>🏢<span>创飞码头项目</span><span class="tn-count">12</span></div>
<div class="tn"><span class="tn-arrow"></span>🏫<span>学校合作项目</span><span class="tn-count">8</span></div>
<div class="tn"><span class="tn-arrow"></span>🔬<span>实验室项目</span><span class="tn-count">5</span></div>
<div class="tn"><span class="tn-arrow"></span>📐<span>内部测试</span><span class="tn-count">3</span></div>
</div>
</div>
<!-- Main -->
<div class="main-panel">
<div class="stats"><div class="card st"><div class="st-num">47</div><div class="st-label">总许可证</div></div><div class="card st"><div class="st-num">38</div><div class="st-label">活跃</div></div><div class="card st"><div class="st-num">6</div><div class="st-label">已吊销</div></div><div class="card st"><div class="st-num">3</div><div class="st-label">已过期</div></div></div>
<div class="card filter-bar">
<div class="filter-l"><div class="f-input"><span>🔍</span><input placeholder="搜索许可证 ID..."></div><select class="f-select"><option>全部类型</option><option>永久</option><option>订阅</option><option>试用</option></select><select class="f-select"><option>全部状态</option><option>活跃</option><option>已吊销</option><option>已过期</option></select><button class="btn btn-primary">查询</button></div>
<button class="btn btn-primary btn-create" onclick="openDlg('issue')"> 签发许可证</button>
</div>
<div class="card" style="padding:0;overflow:hidden">
<table class="dt"><thead><tr><th>许可证 ID</th><th>租户</th><th>产品</th><th>类型</th><th>终端</th><th>宽限</th><th>状态</th><th>签发时间</th><th style="width:110px">操作</th></tr></thead>
<tbody>
<tr><td class="td-mono">01JQNX...a1b2</td><td>craftlabs-wharf-prod</td><td class="td-secondary">wharf-inspection-v2</td><td>永久</td><td class="td-center">5</td><td class="td-center">7天</td><td><span class="tag tag-ok">活跃</span></td><td class="td-time">2026-05-10 08:00</td><td class="td-action"><a onclick="openDlg('detail')">详情</a><a class="danger" onclick="openDlg('revoke')">吊销</a></td></tr>
<tr><td class="td-mono">01JQNY...c3d4</td><td>school-district-west</td><td class="td-secondary">school-edge-ai</td><td>订阅</td><td class="td-center">20</td><td class="td-center">3天</td><td><span class="tag tag-ok">活跃</span></td><td class="td-time">2026-05-08 14:30</td><td class="td-action"><a onclick="openDlg('detail')">详情</a><a class="danger" onclick="openDlg('revoke')">吊销</a></td></tr>
<tr><td class="td-mono">01JQNZ...e5f6</td><td>floating-project-042</td><td class="td-secondary">floating-license</td><td>试用</td><td class="td-center">2</td><td class="td-center">1天</td><td><span class="tag tag-gray">已过期</span></td><td class="td-time">2026-01-15 10:00</td><td class="td-action"><a onclick="openDlg('detail')">详情</a></td></tr>
<tr><td class="td-mono">01JQPA...g7h8</td><td>craftlabs-demo</td><td class="td-secondary">demo-license</td><td>订阅</td><td class="td-center">10</td><td class="td-center">7天</td><td><span class="tag tag-bad">已吊销</span></td><td class="td-time">2026-03-20 09:15</td><td class="td-action"><a onclick="openDlg('detail')">详情</a></td></tr>
<tr><td class="td-mono">01JQPB...i9j0</td><td>internal-test</td><td class="td-secondary">test-license</td><td>永久</td><td class="td-center">1</td><td class="td-center">0天</td><td><span class="tag tag-ok">活跃</span></td><td class="td-time">2026-05-15 16:45</td><td class="td-action"><a onclick="openDlg('detail')">详情</a><a class="danger" onclick="openDlg('revoke')">吊销</a></td></tr>
</tbody></table>
<div class="tf">共 47 条 <span style="color:var(--brand);font-weight:600;margin:0 4px"></span> <b>1</b> 2 … 5 <span style="color:var(--text2);cursor:pointer;font-weight:600"></span></div>
</div>
</div>
</div>
</div>
<!-- CALLBACK PAGE (stub) -->
<div id="panel-callback" class="panel">
<div class="card filter-bar" style="margin-bottom:12px"><div class="filter-l"><select class="f-select"><option>全部状态</option></select><select class="f-select"><option>全部事件</option></select><button class="btn btn-primary">查询</button></div></div>
<div class="card" style="padding:0;overflow:hidden"><table class="dt"><thead><tr><th>来源</th><th>事件类型</th><th>SN</th><th>状态</th><th>收件时间</th><th style="width:80px">操作</th></tr></thead><tbody><tr><td>BitAnswer</td><td class="td-mono">sn:post_activate</td><td class="td-mono">SN-2026-A1B2</td><td><span class="tag tag-warn">待处理</span></td><td class="td-time">2026-05-18 14:30</td><td class="td-action"><a>详情</a></td></tr><tr><td>SelfHosted</td><td class="td-mono">license:heartbeat</td><td class="td-mono">01JQNX...a1b2</td><td><span class="tag tag-ok">已处理</span></td><td class="td-time">2026-05-18 10:00</td><td class="td-action"><a>详情</a></td></tr></tbody></table><div class="tf">共 127 条</div></div>
</div>
</div>
</div>
</div>
<!-- ISSUE LICENSE DIALOG -->
<div id="dlg-issue" class="modal-overlay" onclick="if(event.target===this)closeDlg('issue')">
<div class="dialog" style="width:560px">
<div class="d-header"><span class="d-title">签发许可证</span><span class="d-close" onclick="closeDlg('issue')"></span></div>
<div class="d-body">
<div class="form-g"><label class="form-l">租户 ID *</label><input class="form-i" placeholder="如 craftlabs-wharf-prod" value="craftlabs-wharf-prod"></div>
<div class="form-g"><label class="form-l">产品名称</label><input class="form-i" placeholder="如 wharf-inspection-v2" value="wharf-inspection-v2"></div>
<div class="form-row">
<div><label class="form-l">授权类型</label><select class="form-i" style="width:100%"><option>订阅 (subscription)</option><option>永久 (perpetual)</option><option>试用 (trial)</option></select></div>
<div><label class="form-l">有效期(天)</label><input class="form-i" type="number" value="365"></div>
</div>
<div class="form-row">
<div><label class="form-l">最大终端数</label><input class="form-i" type="number" value="5"></div>
<div><label class="form-l">离线宽限期(天)</label><input class="form-i" type="number" value="7"></div>
</div>
<div class="form-g"><label class="form-l">特性开关</label>
<div class="check-group"><label><input type="checkbox" checked>高级分析</label><label><input type="checkbox">实时监控</label><label><input type="checkbox" checked>API 导出</label><label><input type="checkbox">多租户</label></div>
</div>
<div class="info-box gray"><b>📐 弹框规范:</b> 宽 560px · 圆角 8px · 表单项距 16px · 按钮右对齐</div>
</div>
<div class="d-footer"><button class="btn-cancel" onclick="closeDlg('issue')">取消</button><button class="btn btn-primary" style="padding:8px 20px;font-size:14px" onclick="closeDlg('issue')">签发</button></div>
</div>
</div>
<!-- DETAIL DIALOG -->
<div id="dlg-detail" class="modal-overlay" onclick="if(event.target===this)closeDlg('detail')">
<div class="dialog" style="width:520px">
<div class="d-header"><span class="d-title">许可证详情</span><span class="d-close" onclick="closeDlg('detail')"></span></div>
<div class="d-body">
<div class="detail-row"><span class="detail-l">许可证 ID</span><span class="detail-v"><code style="font-size:12px">01JQNX...a1b2</code></span></div>
<div class="detail-row"><span class="detail-l">租户</span><span class="detail-v">craftlabs-wharf-prod</span></div>
<div class="detail-row"><span class="detail-l">产品</span><span class="detail-v">wharf-inspection-v2</span></div>
<div class="detail-row"><span class="detail-l">授权类型</span><span class="detail-v">永久</span></div>
<div class="detail-row"><span class="detail-l">最大终端</span><span class="detail-v">5</span></div>
<div class="detail-row"><span class="detail-l">离线宽限</span><span class="detail-v">7 天</span></div>
<div class="detail-row"><span class="detail-l">状态</span><span class="detail-v"><span class="tag tag-ok">活跃</span></span></div>
<div class="info-box gray"><b>📐 详情弹框:</b> 宽 520px · 标签 100px 右对齐 · monospace ID · 吊销按钮红色</div>
</div>
<div class="d-footer"><button class="btn-cancel" onclick="closeDlg('detail')">关闭</button><button class="btn-danger" onclick="closeDlg('detail')">吊销</button></div>
</div>
</div>
<!-- REVOKE DIALOG -->
<div id="dlg-revoke" class="modal-overlay" onclick="if(event.target===this)closeDlg('revoke')">
<div class="dialog" style="width:420px;text-align:center">
<div class="d-body" style="padding:32px 24px 20px">
<div style="font-size:48px;margin-bottom:16px">🛑</div>
<div style="font-size:16px;font-weight:600;margin-bottom:8px">确认吊销许可证</div>
<div style="font-size:13px;color:var(--text3)">确定要吊销 <b style="color:var(--text);font-family:monospace">01JQNX...a1b2</b> 吗?吊销后立即失效。</div>
<div class="info-box red"><b>📐 危险操作:</b> 宽 420px · 红色背景提示 · 确认按钮红色</div>
</div>
<div class="d-footer" style="justify-content:center;gap:12px"><button class="btn-cancel" onclick="closeDlg('revoke')">取消</button><button class="btn-danger" onclick="closeDlg('revoke')">确认吊销</button></div>
</div>
</div>
<!-- CREDITS -->
<footer style="text-align:center;padding:12px;font-size:11px;color:var(--text3);background:#fff;border-top:1px solid var(--border)">
CraftLabs Design System v1.0 · 基于 Figma「安徽地质博物馆 v2.0」· 2026-05
</footer>
<script>
function openDlg(id){document.getElementById('dlg-'+id).classList.add('show')}
function closeDlg(id){document.getElementById('dlg-'+id).classList.remove('show')}
function switchTo(name){
document.querySelectorAll('.panel').forEach(p=>p.classList.remove('show'));
document.getElementById('panel-'+name).classList.add('show');
document.getElementById('bcCur').textContent='授权运营 '+(name==='license'?'许可证管理':'Callback 收件箱');
document.querySelectorAll('.menu-item').forEach(m=>m.classList.remove('act'));
event.target.closest('.menu-item')?.classList.add('act');
}
</script>
</body>
</html>