143 lines
2.7 KiB
HTML
143 lines
2.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh">
|
|
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<title>Tree</title>
|
|
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI";
|
|
background: #f5f7fa;
|
|
padding: 30px;
|
|
}
|
|
|
|
.tree {
|
|
width: 320px;
|
|
background: #fff;
|
|
padding: 10px;
|
|
border-radius: 10px;
|
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
|
|
}
|
|
|
|
.node {
|
|
padding: 6px 8px;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
transition: 0.2s;
|
|
}
|
|
|
|
.node:hover {
|
|
background: #f0f7ff;
|
|
color: #1677ff;
|
|
}
|
|
|
|
.node.active {
|
|
background: #e6f4ff;
|
|
color: #1677ff;
|
|
}
|
|
|
|
.arrow {
|
|
width: 14px;
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
transition: 0.2s;
|
|
}
|
|
|
|
.arrow.open {
|
|
transform: rotate(90deg);
|
|
}
|
|
|
|
.children {
|
|
margin-left: 18px;
|
|
overflow: hidden;
|
|
max-height: 0;
|
|
opacity: 0;
|
|
transition: all 0.25s ease;
|
|
}
|
|
|
|
.children.open {
|
|
max-height: 500px;
|
|
opacity: 1;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div class="tree">
|
|
|
|
<!-- 根 -->
|
|
<div class="tree-node">
|
|
|
|
<!-- ❗关键:整个 node 都可以选中 -->
|
|
<div class="node" onclick="selectNode(this)">
|
|
<span class="arrow" onclick="toggle(event, this)">▶</span>
|
|
系统管理
|
|
</div>
|
|
|
|
<div class="children open">
|
|
|
|
<div class="node" onclick="selectNode(this)">
|
|
用户管理
|
|
</div>
|
|
|
|
<div class="node" onclick="selectNode(this)">
|
|
角色管理
|
|
</div>
|
|
|
|
<!-- 父节点 -->
|
|
<div class="tree-node">
|
|
|
|
<div class="node" onclick="selectNode(this)">
|
|
<span class="arrow" onclick="toggle(event, this)">▶</span>
|
|
权限管理
|
|
</div>
|
|
|
|
<div class="children">
|
|
|
|
<div class="node" onclick="selectNode(this)">
|
|
菜单权限
|
|
</div>
|
|
|
|
<div class="node" onclick="selectNode(this)">
|
|
按钮权限
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
// ✅ 单选:保证父子都能选
|
|
function selectNode(el) {
|
|
document.querySelectorAll(".node.active")
|
|
.forEach(n => n.classList.remove("active"));
|
|
|
|
el.classList.add("active");
|
|
}
|
|
|
|
// ✅ 只控制展开(不影响选中)
|
|
function toggle(e, el) {
|
|
e.stopPropagation(); // ❗关键:阻止触发选中
|
|
|
|
const wrapper = el.closest(".tree-node");
|
|
const children = wrapper.querySelector(".children");
|
|
|
|
if (!children) return;
|
|
|
|
children.classList.toggle("open");
|
|
el.classList.toggle("open");
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html> |