629 lines
20 KiB
HTML
629 lines
20 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>侧栏目录 + 右侧叶子 Tab Demo</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||
<style>
|
||
:root {
|
||
--primary: #10b981;
|
||
--primary-dark: #059669;
|
||
--primary-bg: #ecfdf5;
|
||
--text: #1e293b;
|
||
--text-muted: #64748b;
|
||
--border: #d9e8e2;
|
||
--bg-page: #f8fafc;
|
||
--surface: #ffffff;
|
||
--table-head: #f8fafc;
|
||
--row-alt: #f1f5f9;
|
||
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||
--radius: 10px;
|
||
--sidebar-w: 220px;
|
||
--header-h: 56px;
|
||
}
|
||
* { box-sizing: border-box; }
|
||
html, body { height: 100%; }
|
||
body {
|
||
margin: 0;
|
||
font-family: Inter, -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||
font-size: 14px;
|
||
line-height: 1.5;
|
||
color: var(--text);
|
||
background: var(--bg-page);
|
||
}
|
||
button { font-family: inherit; }
|
||
|
||
.page {
|
||
max-width: 1280px;
|
||
margin: 0 auto;
|
||
padding: 20px 20px 48px;
|
||
}
|
||
.intro h1 {
|
||
margin: 0 0 6px;
|
||
font-size: 20px;
|
||
font-weight: 700;
|
||
}
|
||
.intro p {
|
||
margin: 0 0 12px;
|
||
color: var(--text-muted);
|
||
font-size: 13px;
|
||
max-width: 860px;
|
||
}
|
||
.intro ul {
|
||
margin: 0 0 16px;
|
||
padding: 10px 14px 10px 28px;
|
||
background: #fff;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
font-size: 13px;
|
||
color: var(--text-muted);
|
||
}
|
||
.intro li { margin: 3px 0; }
|
||
.intro b { color: var(--text); font-weight: 600; }
|
||
|
||
.shell {
|
||
display: grid;
|
||
grid-template-columns: var(--sidebar-w) 1fr;
|
||
grid-template-rows: var(--header-h) minmax(560px, calc(100vh - 220px));
|
||
border: 1px solid var(--border);
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
background: var(--surface);
|
||
box-shadow: var(--shadow);
|
||
}
|
||
.header {
|
||
grid-column: 1 / -1;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
height: var(--header-h);
|
||
padding: 0 16px;
|
||
border-bottom: 1px solid var(--border);
|
||
background: #fff;
|
||
}
|
||
.brand {
|
||
width: var(--sidebar-w);
|
||
margin-left: -16px;
|
||
padding-left: 16px;
|
||
font-weight: 700;
|
||
color: var(--primary-dark);
|
||
}
|
||
.crumb {
|
||
color: var(--text-muted);
|
||
font-size: 13px;
|
||
}
|
||
.crumb strong { color: var(--text); font-weight: 600; }
|
||
|
||
.sidebar {
|
||
border-right: 1px solid var(--border);
|
||
background: #fff;
|
||
overflow: auto;
|
||
padding: 10px 8px 16px;
|
||
}
|
||
.side-label {
|
||
padding: 6px 10px 8px;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
letter-spacing: 0.04em;
|
||
color: var(--text-muted);
|
||
text-transform: uppercase;
|
||
}
|
||
.tree-item { margin: 2px 0; }
|
||
.tree-btn {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
border: 0;
|
||
background: transparent;
|
||
color: var(--text);
|
||
text-align: left;
|
||
padding: 8px 10px;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
}
|
||
.tree-btn:hover { background: var(--row-alt); }
|
||
.tree-btn.is-active {
|
||
background: var(--primary-bg);
|
||
color: var(--primary-dark);
|
||
font-weight: 600;
|
||
}
|
||
.tree-btn .chev {
|
||
width: 14px;
|
||
color: var(--text-muted);
|
||
font-size: 11px;
|
||
flex: 0 0 14px;
|
||
}
|
||
.tree-btn.is-active .chev { color: var(--primary-dark); }
|
||
.tree-btn.l1 { font-weight: 600; }
|
||
.tree-children {
|
||
padding-left: 18px;
|
||
display: none;
|
||
}
|
||
.tree-children.open { display: block; }
|
||
|
||
.main {
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-width: 0;
|
||
background: var(--bg-page);
|
||
}
|
||
.tabs {
|
||
display: flex;
|
||
padding: 12px 16px 8px;
|
||
overflow-x: auto;
|
||
}
|
||
.tabs-track {
|
||
display: inline-flex;
|
||
flex-wrap: wrap;
|
||
gap: 4px;
|
||
padding: 4px;
|
||
background: #fff;
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
box-shadow: 0 1px 2px rgba(30, 41, 59, 0.04), 0 8px 24px rgba(30, 41, 59, 0.04);
|
||
}
|
||
.tab {
|
||
appearance: none;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
height: 32px;
|
||
padding: 0 12px;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
color: #4b5563;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
background: transparent;
|
||
border: 0;
|
||
border-radius: 8px;
|
||
}
|
||
.tab:hover { color: var(--text); background: #f3f6f4; }
|
||
.tab.is-on {
|
||
color: var(--primary-dark);
|
||
font-weight: 600;
|
||
background: var(--primary-bg, #ecfdf5);
|
||
}
|
||
.tab .dot {
|
||
display: inline-block;
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 99px;
|
||
background: #cbd5e1;
|
||
margin-right: 6px;
|
||
vertical-align: middle;
|
||
}
|
||
.tab.is-on .dot { background: var(--primary); }
|
||
.tab.is-loaded .dot { background: #94a3b8; }
|
||
.tab.is-on.is-loaded .dot { background: var(--primary); }
|
||
|
||
.panel-wrap {
|
||
flex: 1;
|
||
position: relative;
|
||
overflow: auto;
|
||
padding: 16px;
|
||
}
|
||
.empty {
|
||
height: 100%;
|
||
min-height: 360px;
|
||
display: grid;
|
||
place-items: center;
|
||
color: var(--text-muted);
|
||
font-size: 13px;
|
||
border: 1px dashed var(--border);
|
||
border-radius: var(--radius);
|
||
background: #fff;
|
||
}
|
||
.view {
|
||
display: none;
|
||
background: #fff;
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius);
|
||
min-height: 360px;
|
||
overflow: hidden;
|
||
}
|
||
.view.is-show { display: block; }
|
||
.view-head {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 12px 16px;
|
||
border-bottom: 1px solid var(--border);
|
||
background: var(--table-head);
|
||
}
|
||
.view-head h2 {
|
||
margin: 0;
|
||
font-size: 15px;
|
||
font-weight: 700;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.view-head h2::before {
|
||
content: "";
|
||
width: 3px;
|
||
height: 14px;
|
||
border-radius: 2px;
|
||
background: var(--primary);
|
||
}
|
||
.badge {
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
color: var(--primary-dark);
|
||
background: var(--primary-bg);
|
||
border-radius: 999px;
|
||
padding: 2px 8px;
|
||
}
|
||
.view-body { padding: 16px; }
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 13px;
|
||
}
|
||
th, td {
|
||
padding: 10px 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
th {
|
||
color: var(--text-muted);
|
||
font-weight: 600;
|
||
background: var(--table-head);
|
||
}
|
||
tbody tr:nth-child(even) { background: #fafefe; }
|
||
.tag {
|
||
display: inline-block;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
color: #fff;
|
||
background: #059669;
|
||
}
|
||
.tag.warn { background: #d97706; }
|
||
.tag.info {
|
||
background: transparent;
|
||
color: var(--text);
|
||
border: 1px solid var(--border);
|
||
}
|
||
.kv {
|
||
display: grid;
|
||
grid-template-columns: 140px 1fr;
|
||
gap: 8px 16px;
|
||
font-size: 13px;
|
||
}
|
||
.kv dt { color: var(--text-muted); }
|
||
.kv dd { margin: 0; }
|
||
|
||
.mask {
|
||
display: none;
|
||
position: absolute;
|
||
inset: 16px;
|
||
border-radius: var(--radius);
|
||
background: rgba(255, 255, 255, 0.72);
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--text-muted);
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
}
|
||
.mask.show { display: flex; }
|
||
.spin {
|
||
width: 18px;
|
||
height: 18px;
|
||
border: 2px solid #cbd5e1;
|
||
border-top-color: var(--primary-dark);
|
||
border-radius: 50%;
|
||
margin-right: 8px;
|
||
animation: rot 0.8s linear infinite;
|
||
}
|
||
@keyframes rot { to { transform: rotate(360deg); } }
|
||
|
||
.log {
|
||
margin-top: 14px;
|
||
background: #fff;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 10px 12px;
|
||
font-size: 12px;
|
||
color: var(--text-muted);
|
||
max-height: 120px;
|
||
overflow: auto;
|
||
}
|
||
.log b { color: var(--text); }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="page">
|
||
<div class="intro">
|
||
<h1>侧栏非叶子目录 + 右侧叶子 Tab</h1>
|
||
<p>
|
||
交互演示(非真实业务页):左侧只展示目录(非叶子)。点击<strong>最后一层非叶子</strong>后,右侧用 Tab 打开其全部叶子菜单。
|
||
切换目录会清空上一组 Tab。默认加载第一个 Tab;再点哪个 Tab 才加载哪个界面。
|
||
</p>
|
||
<ul>
|
||
<li>试一下:点 <b>报销管理 → 基础配置</b>,再点 <b>备用金</b>,观察右侧 Tab 整组替换。</li>
|
||
<li>Tab 上的灰点表示尚未加载;点过一次后视为已加载(本 Demo 做缓存,切回不再重复请求)。</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="shell">
|
||
<header class="header">
|
||
<div class="brand">山峡化工</div>
|
||
<div class="crumb" id="crumb">请选择左侧最后一层目录</div>
|
||
</header>
|
||
<aside class="sidebar" id="sidebar"></aside>
|
||
<section class="main">
|
||
<div class="tabs" id="tabs"></div>
|
||
<div class="panel-wrap">
|
||
<div class="empty" id="empty">点击左侧「基础配置 / 备用金 / 报销 / 视图中心」打开叶子菜单 Tab</div>
|
||
<div id="views"></div>
|
||
<div class="mask" id="mask"><span class="spin"></span><span id="maskText">正在加载界面…</span></div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div class="log" id="log"><b>加载日志</b>:尚未操作</div>
|
||
</div>
|
||
|
||
<script>
|
||
const MENU = [
|
||
{
|
||
id: "bx",
|
||
title: "报销管理",
|
||
children: [
|
||
{
|
||
id: "bx-config",
|
||
title: "基础配置",
|
||
leaves: [
|
||
{ id: "expense-item", title: "费用项目管理", kind: "table",
|
||
rows: [["差旅费", "费用", "启用"], ["招待费", "费用", "启用"], ["运费", "费用", "停用"]] },
|
||
{ id: "wf-advance", title: "工作流配置(备用金)", kind: "kv",
|
||
fields: [["流程名称", "备用金审批流程"], ["状态", "启用"], ["节点", "部门负责人 → 财务"]] },
|
||
{ id: "wf-reimburse", title: "工作流配置(报销单)", kind: "kv",
|
||
fields: [["流程名称", "报销单审批流程"], ["状态", "启用"], ["节点", "直属上级 → 财务 → 出纳"]] }
|
||
]
|
||
},
|
||
{
|
||
id: "bx-advance",
|
||
title: "备用金",
|
||
leaves: [
|
||
{ id: "adv-apply", title: "备用金申请", kind: "table",
|
||
rows: [["BYJ20260819002", "汪璇", "50000.00", "已通过"], ["BYJ20260819001", "汪璇", "50768.30", "已驳回"]] },
|
||
{ id: "adv-approve", title: "备用金审批", kind: "table",
|
||
rows: [["BYJ20260722001", "汪璇", "待审批", "部门负责人"], ["BYJ20260806001", "汪璇", "待审批", "财务"]] },
|
||
{ id: "adv-issue", title: "备用金发放", kind: "table",
|
||
rows: [["BYJ20260522002", "汪璇", "50000.00", "已发放"], ["BYJ20260703001", "汪璇", "20000.00", "已发放"]] }
|
||
]
|
||
},
|
||
{
|
||
id: "bx-reimburse",
|
||
title: "报销",
|
||
leaves: [
|
||
{ id: "rb-apply", title: "报销申请", kind: "table",
|
||
rows: [["BX20260901001", "张三", "1280.00", "待提交"], ["BX20260902002", "李四", "3560.50", "审批中"]] },
|
||
{ id: "rb-approve", title: "报销审批", kind: "table",
|
||
rows: [["BX20260902002", "李四", "3560.50", "待审批"]] },
|
||
{ id: "rb-pay", title: "支付发放冲抵", kind: "table",
|
||
rows: [["BX20260815001", "王五", "890.00", "待发放"]] },
|
||
{ id: "inv-admin", title: "发票夹管理", kind: "kv",
|
||
fields: [["待核验", "12 张"], ["已入账", "86 张"], ["异常", "2 张"]] },
|
||
{ id: "inv-mine", title: "我的发票夹", kind: "kv",
|
||
fields: [["本月上传", "4 张"], ["可报销", "3 张"], ["已占用", "1 张"]] }
|
||
]
|
||
},
|
||
{
|
||
id: "bx-view",
|
||
title: "视图中心",
|
||
leaves: [
|
||
{ id: "view-mine", title: "我的视图", kind: "kv",
|
||
fields: [["默认视图", "本月报销汇总"], ["自定义", "2 个"]] },
|
||
{ id: "view-team", title: "部门视图", kind: "kv",
|
||
fields: [["可见范围", "本部门及下级"], ["刷新", "每日 08:00"]] }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
|
||
const sidebar = document.getElementById("sidebar")
|
||
const tabsEl = document.getElementById("tabs")
|
||
const viewsEl = document.getElementById("views")
|
||
const emptyEl = document.getElementById("empty")
|
||
const crumbEl = document.getElementById("crumb")
|
||
const maskEl = document.getElementById("mask")
|
||
const maskText = document.getElementById("maskText")
|
||
const logEl = document.getElementById("log")
|
||
|
||
let openL1 = "bx"
|
||
let activeGroupId = null
|
||
let activeLeafId = null
|
||
let loaded = new Set()
|
||
let loadTimer = null
|
||
const logs = []
|
||
|
||
function log(msg) {
|
||
const t = new Date().toLocaleTimeString("zh-CN", { hour12: false })
|
||
logs.unshift(t + " " + msg)
|
||
logEl.innerHTML = "<b>加载日志</b><br>" + logs.slice(0, 8).join("<br>")
|
||
}
|
||
|
||
function findGroup(id) {
|
||
for (const l1 of MENU) {
|
||
const g = l1.children.find((c) => c.id === id)
|
||
if (g) return { l1, g }
|
||
}
|
||
return null
|
||
}
|
||
|
||
function renderSidebar() {
|
||
sidebar.innerHTML = '<div class="side-label">业务目录</div>'
|
||
MENU.forEach((l1) => {
|
||
const wrap = document.createElement("div")
|
||
wrap.className = "tree-item"
|
||
wrap.innerHTML =
|
||
'<button class="tree-btn l1" data-l1="' + l1.id + '">' +
|
||
'<span class="chev">' + (openL1 === l1.id ? "▼" : "▶") + "</span>" +
|
||
l1.title + "</button>"
|
||
const kids = document.createElement("div")
|
||
kids.className = "tree-children" + (openL1 === l1.id ? " open" : "")
|
||
l1.children.forEach((g) => {
|
||
const b = document.createElement("button")
|
||
b.className = "tree-btn" + (g.id === activeGroupId ? " is-active" : "")
|
||
b.innerHTML = '<span class="chev"></span>' + g.title
|
||
b.addEventListener("click", () => openGroup(g.id))
|
||
kids.appendChild(b)
|
||
})
|
||
wrap.querySelector("[data-l1]").addEventListener("click", () => {
|
||
openL1 = openL1 === l1.id ? "" : l1.id
|
||
renderSidebar()
|
||
})
|
||
wrap.appendChild(kids)
|
||
sidebar.appendChild(wrap)
|
||
})
|
||
}
|
||
|
||
function openGroup(groupId) {
|
||
if (activeGroupId === groupId) return
|
||
const found = findGroup(groupId)
|
||
if (!found) return
|
||
loaded = new Set()
|
||
activeGroupId = groupId
|
||
activeLeafId = found.g.leaves[0].id
|
||
crumbEl.innerHTML =
|
||
"<strong>" + found.l1.title + "</strong> / " + found.g.title +
|
||
" · 叶子 " + found.g.leaves.length + " 个"
|
||
emptyEl.style.display = "none"
|
||
renderSidebar()
|
||
renderTabs(found.g)
|
||
renderViews(found.g)
|
||
log("切换目录「" + found.g.title + "」,清空上一组 Tab,准备打开 " +
|
||
found.g.leaves.map((x) => x.title).join(" / "))
|
||
loadLeaf(found.g.leaves[0], true)
|
||
}
|
||
|
||
function renderTabs(group) {
|
||
tabsEl.innerHTML = ""
|
||
if (!group || group.leaves.length <= 1) return
|
||
const track = document.createElement("div")
|
||
track.className = "tabs-track"
|
||
group.leaves.forEach((leaf) => {
|
||
const b = document.createElement("button")
|
||
b.className = "tab" +
|
||
(leaf.id === activeLeafId ? " is-on" : "") +
|
||
(loaded.has(leaf.id) ? " is-loaded" : "")
|
||
b.innerHTML = '<span class="dot"></span>' + leaf.title
|
||
b.addEventListener("click", () => selectLeaf(leaf.id))
|
||
track.appendChild(b)
|
||
})
|
||
tabsEl.appendChild(track)
|
||
}
|
||
|
||
function tableHtml(leaf) {
|
||
const isStatus = leaf.rows[0] && leaf.rows[0].length === 4
|
||
const heads = isStatus
|
||
? (leaf.id.indexOf("adv") === 0 || leaf.id.indexOf("rb") === 0
|
||
? ["单号", "申请人", leaf.rows[0][2].indexOf(".") >= 0 ? "金额" : "状态", "状态/节点"]
|
||
: ["名称", "类型", "状态"])
|
||
: ["列1", "列2", "列3"]
|
||
if (leaf.id === "expense-item") {
|
||
return headTable(["项目名称", "类型", "状态"], leaf.rows, (c, i) =>
|
||
i === 2 ? tagHtml(c) : escapeHtml(c))
|
||
}
|
||
if (leaf.rows[0].length === 4) {
|
||
return headTable(
|
||
leaf.id === "adv-approve"
|
||
? ["单号", "申请人", "状态", "当前节点"]
|
||
: ["单号", "申请人", "金额", "状态"],
|
||
leaf.rows,
|
||
(c, i) => i === 3 || (leaf.id === "adv-approve" && i === 2) ? tagHtml(c) : escapeHtml(c)
|
||
)
|
||
}
|
||
return headTable(heads, leaf.rows, (c) => escapeHtml(c))
|
||
}
|
||
|
||
function headTable(heads, rows, cellFn) {
|
||
let h = "<table><thead><tr>" + heads.map((x) => "<th>" + x + "</th>").join("") + "</tr></thead><tbody>"
|
||
rows.forEach((r) => {
|
||
h += "<tr>" + r.map((c, i) => "<td>" + cellFn(c, i) + "</td>").join("") + "</tr>"
|
||
})
|
||
return h + "</tbody></table>"
|
||
}
|
||
|
||
function tagHtml(text) {
|
||
const t = String(text)
|
||
let cls = "tag"
|
||
if (t.indexOf("驳回") >= 0 || t.indexOf("停用") >= 0) cls += " warn"
|
||
if (t.indexOf("待") >= 0) cls += " info"
|
||
return '<span class="' + cls + '">' + escapeHtml(t) + "</span>"
|
||
}
|
||
|
||
function kvHtml(leaf) {
|
||
return '<dl class="kv">' + leaf.fields.map(function (f) {
|
||
return "<dt>" + escapeHtml(f[0]) + "</dt><dd>" + escapeHtml(f[1]) + "</dd>"
|
||
}).join("") + "</dl>"
|
||
}
|
||
|
||
function escapeHtml(s) {
|
||
return String(s).replace(/[&<>]/g, function (ch) {
|
||
return ({ "&": "&", "<": "<", ">": ">" })[ch]
|
||
})
|
||
}
|
||
|
||
function renderViews(group) {
|
||
viewsEl.innerHTML = ""
|
||
group.leaves.forEach((leaf) => {
|
||
const el = document.createElement("div")
|
||
el.className = "view" + (leaf.id === activeLeafId ? " is-show" : "")
|
||
el.id = "view-" + leaf.id
|
||
const body = loaded.has(leaf.id)
|
||
? (leaf.kind === "kv" ? kvHtml(leaf) : tableHtml(leaf))
|
||
: '<p style="color:#64748b;margin:0">尚未加载。切换到该 Tab 后才会请求并渲染本界面。</p>'
|
||
el.innerHTML =
|
||
'<div class="view-head"><h2>' + escapeHtml(leaf.title) +
|
||
'</h2><span class="badge">' + (loaded.has(leaf.id) ? "已加载" : "未加载") +
|
||
"</span></div><div class=\"view-body\">" + body + "</div>"
|
||
viewsEl.appendChild(el)
|
||
})
|
||
}
|
||
|
||
function selectLeaf(leafId) {
|
||
const found = findGroup(activeGroupId)
|
||
if (!found) return
|
||
const leaf = found.g.leaves.find((x) => x.id === leafId)
|
||
if (!leaf) return
|
||
activeLeafId = leafId
|
||
renderTabs(found.g)
|
||
Array.from(viewsEl.children).forEach((el) => {
|
||
el.classList.toggle("is-show", el.id === "view-" + leafId)
|
||
})
|
||
if (loaded.has(leafId)) {
|
||
log("切换到「" + leaf.title + "」(已缓存,不再请求)")
|
||
return
|
||
}
|
||
loadLeaf(leaf, false)
|
||
}
|
||
|
||
function loadLeaf(leaf, isDefault) {
|
||
if (loadTimer) clearTimeout(loadTimer)
|
||
maskText.textContent = "正在加载「" + leaf.title + "」…"
|
||
maskEl.classList.add("show")
|
||
log((isDefault ? "默认打开第一个 Tab:" : "切换 Tab,按需加载:") + "「" + leaf.title + "」")
|
||
loadTimer = setTimeout(function () {
|
||
loaded.add(leaf.id)
|
||
maskEl.classList.remove("show")
|
||
const found = findGroup(activeGroupId)
|
||
renderTabs(found.g)
|
||
renderViews(found.g)
|
||
log("「" + leaf.title + "」加载完成")
|
||
}, 420)
|
||
}
|
||
|
||
renderSidebar()
|
||
</script>
|
||
</body>
|
||
</html>
|