Files
aurora-admin/site/sources/tree/html.txt
T
aurora-admin c65a69c34e
Deploy to GitHub Pages / deploy (push) Failing after 16s
Regression / regression (push) Failing after 15m2s
feat(P4): precompute移植+app.js sources双向回填+回归1003/1003+验收体积/文件/data.json
2026-09-12 14:18:41 +08:00

140 lines
5.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Aurora Admin · Tree (H5)</title>
<link rel="stylesheet" href="../.design_library/aurora-admin/colors_and_type.css">
<style>
/* 对齐 组件2.txt Tree 规范:节点高32px、缩进16px/级、箭头12px、选中 #F0F5FF/#2F54EB */
.demo { padding: 24px; background: var(--au-color-page-bg); color: var(--au-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--au-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.aa-tree { min-width: 240px; border: 1px solid var(--au-color-border); border-radius: 8px; padding: 4px; background: var(--au-color-card-bg); }
.aa-tree-node {
display: flex; align-items: center; gap: 4px; height: 32px; border-radius: 4px;
cursor: pointer; user-select: none; font-size: 14px; color: var(--au-color-text-body); padding-right: 8px;
}
.aa-tree-node:hover { background: var(--au-color-page-bg); }
.aa-tree-node.is-selected { background: var(--au-color-brand-bg); color: var(--au-color-brand); }
.aa-tree-arrow {
display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px;
font-size: 12px; color: var(--au-color-text-secondary); transition: transform .15s; flex-shrink: 0;
}
.aa-tree-arrow.is-open { transform: rotate(90deg); }
.aa-tree-arrow-placeholder { width: 16px; flex-shrink: 0; }
.aa-tree-check { width: 14px; height: 14px; flex-shrink: 0; cursor: pointer; }
.aa-tree-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
</style>
</head>
<body>
<div class="demo">
<h1>Aurora Admin · Tree 组件(纯 H5)</h1>
<p class="sub">对齐 Tree 规范:节点高32px、缩进16px/级、箭头12px、选中态 #F0F5FF + 品牌色、支持复选框级联</p>
<label style="font-size:13px;color:var(--color-text-secondary);margin-right:16px;">
<input type="checkbox" id="chkToggle" checked onchange="checkable=this.checked; render();"> 启用复选框
</label>
<div class="aa-tree" role="tree" id="tree" style="margin-top:12px"></div>
</div>
<script>
const treeData = [
{ key: 'org', title: '某某科技', children: [
{ key: 'tech', title: '技术中心', children: [
{ key: 'fe', title: '前端组' },
{ key: 'be', title: '后端组' }
]},
{ key: 'product', title: '产品中心', children: [
{ key: 'pm', title: '产品组' },
{ key: 'ux', title: '设计组' }
]}
]}
];
let checkable = true;
let expanded = new Set(['org']);
let selected = new Set(['fe']);
let checked = new Set(['tech']);
function findNode(key, nodes = treeData) {
for (const n of nodes) {
if (n.key === key) return n;
if (n.children) { const f = findNode(key, n.children); if (f) return f; }
}
return null;
}
function descendantKeys(node) {
let out = [];
(node.children || []).forEach(c => { out.push(c.key); out = out.concat(descendantKeys(c)); });
return out;
}
function allChildrenChecked(node, set) {
if (!node.children || !node.children.length) return set.has(node.key);
return node.children.every(c => allChildrenChecked(c, set));
}
function hasChildren(n) { return n.children && n.children.length; }
function toggleExpand(key) {
expanded.has(key) ? expanded.delete(key) : expanded.add(key);
render();
}
function selectRow(key) {
selected = new Set([key]); render();
}
function toggleCheck(key) {
const node = findNode(key);
const willCheck = !checked.has(key);
const keys = [key, ...descendantKeys(node)];
keys.forEach(k => willCheck ? checked.add(k) : checked.delete(k));
// 向上级联:父节点 = 其所有子节点均勾选
propagateUp(node);
render();
}
function propagateUp(node) {
// 简单向上:遍历所有有父的节点
function walk(nodes, parent) {
nodes.forEach(n => {
if (parent && hasChildren(parent)) {
if (allChildrenChecked(parent, checked)) checked.add(parent.key);
else checked.delete(parent.key);
}
if (n.children) walk(n.children, n);
});
}
walk(treeData, null);
}
function visibleList() {
const out = [];
(function walk(nodes, depth) {
nodes.forEach(n => {
out.push({ node: n, depth });
if (hasChildren(n) && expanded.has(n.key)) walk(n.children, depth + 1);
});
})(treeData, 0);
return out;
}
function render() {
const root = document.getElementById('tree');
root.innerHTML = visibleList().map(({ node, depth }) => {
const open = expanded.has(node.key);
const arrow = hasChildren(node)
? `<span class="aa-tree-arrow ${open ? 'is-open' : ''}" role="tree" onclick="toggleExpand('${node.key}')">▸</span>`
: `<span class="aa-tree-arrow-placeholder"></span>`;
const check = checkable
? `<input type="checkbox" class="aa-tree-check" role="tree" ${checked.has(node.key) ? 'checked' : ''} onclick="event.stopPropagation();toggleCheck('${node.key}')">`
: '';
const sel = selected.has(node.key) ? ' is-selected' : '';
return `<div class="aa-tree-node${sel}" role="treeitem" tabindex="0" style="padding-left:${depth * 16 + 4}px" onclick="selectRow('${node.key}')">
${arrow}${check}<span class="aa-tree-label">${node.title}</span>
</div>`;
}).join('');
}
render();
</script>
</body>
</html>