修复组织树连线仅连接直接下属

This commit is contained in:
汤学会 2026-06-15 01:47:32 +08:00
parent 3313dc3bbb
commit dac7844d4c
2 changed files with 58 additions and 55 deletions

View File

@ -8,10 +8,13 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
const source = readFileSync(join(__dirname, "OrgPermissionTree.vue"), "utf8"); const source = readFileSync(join(__dirname, "OrgPermissionTree.vue"), "utf8");
describe("OrgPermissionTree hierarchy lines", () => { describe("OrgPermissionTree hierarchy lines", () => {
it("draws connector lines so parent-child hierarchy is easier to read", () => { it("draws connector lines only between each node and its direct children", () => {
assert.match(source, /\.org-tree-branch::before/); assert.match(source, /\.org-tree-children\s*>\s*\.org-tree-branch\s*>\s*\.org-tree-node::before/);
assert.match(source, /\.org-tree-node::before/); assert.match(source, /\.org-tree-children\s*>\s*\.org-tree-branch\s*>\s*\.org-tree-node::after/);
assert.doesNotMatch(source, /\.org-tree-children::before/);
assert.doesNotMatch(source, /\.org-tree-branch::before/);
assert.match(source, /--tree-connector-x/); assert.match(source, /--tree-connector-x/);
assert.match(source, /--tree-connector-color/); assert.match(source, /--tree-connector-color/);
assert.match(source, /--tree-connector-width:\s*2px/);
}); });
}); });

View File

@ -166,14 +166,14 @@ const OrgTreeBranch = defineComponent({
return () => return () =>
h("div", { h("div", {
class: ["org-tree-branch", { "org-tree-branch-root": branchProps.level === 0 }], class: ["org-tree-branch", { "org-tree-branch-root": branchProps.level === 0 }],
style: { "--tree-level": branchProps.level } style: treeLevelStyle(branchProps.level)
}, [ }, [
h( h(
"button", "button",
{ {
type: "button", type: "button",
class: ["org-tree-node", { active: isSelected.value }], class: ["org-tree-node", { active: isSelected.value }],
style: { "--tree-level": branchProps.level }, style: treeLevelStyle(branchProps.level),
onClick: selectCurrent, onClick: selectCurrent,
onContextmenu: openMenu onContextmenu: openMenu
}, },
@ -266,6 +266,13 @@ function organizationChildren(node) {
return (Array.isArray(node?.children) ? node.children : []).filter(isOrganizationNode); return (Array.isArray(node?.children) ? node.children : []).filter(isOrganizationNode);
} }
function treeLevelStyle(level) {
return {
"--tree-level": level,
"--tree-connector-x": `${15 + Number(level || 0) * 22}px`
};
}
function filterOrgTreeByKeyword(nodes, keyword) { function filterOrgTreeByKeyword(nodes, keyword) {
const normalizedKeyword = String(keyword || "").trim().toLowerCase(); const normalizedKeyword = String(keyword || "").trim().toLowerCase();
if (!normalizedKeyword) { if (!normalizedKeyword) {
@ -570,8 +577,9 @@ function removeEmployee(employee) {
} }
.org-tree-list { .org-tree-list {
--tree-connector-color: rgba(64, 158, 255, 0.34); --tree-connector-color: rgba(37, 99, 235, 0.74);
--tree-connector-x: calc(15px + var(--tree-level, 0) * 22px); --tree-connector-width: 2px;
--tree-connector-arm: 14px;
display: flex; display: flex;
flex: 1; flex: 1;
flex-direction: column; flex-direction: column;
@ -590,26 +598,6 @@ function removeEmployee(employee) {
gap: 2px; gap: 2px;
} }
.org-tree-branch::before {
content: "";
position: absolute;
top: -2px;
bottom: -2px;
left: var(--tree-connector-x);
width: 1px;
background: linear-gradient(180deg, transparent, var(--tree-connector-color) 12px, var(--tree-connector-color) calc(100% - 12px), transparent);
pointer-events: none;
}
.org-tree-branch-root::before {
content: none;
}
.org-tree-branch:not(.org-tree-branch-root):last-child::before {
bottom: calc(100% - 21px);
background: var(--tree-connector-color);
}
.org-tree-node { .org-tree-node {
position: relative; position: relative;
display: grid; display: grid;
@ -627,14 +615,29 @@ function removeEmployee(employee) {
transition: background 0.14s ease, color 0.14s ease, box-shadow 0.14s ease; transition: background 0.14s ease, color 0.14s ease, box-shadow 0.14s ease;
} }
.org-tree-branch:not(.org-tree-branch-root) > .org-tree-node::before { .org-tree-children > .org-tree-branch > .org-tree-node::before {
content: ""; content: "";
position: absolute; position: absolute;
top: 50%; top: 50%;
left: var(--tree-connector-x); left: calc(var(--tree-connector-x) - var(--tree-connector-width) / 2);
width: 14px; width: var(--tree-connector-arm);
height: 1px; height: var(--tree-connector-width);
background: var(--tree-connector-color); background: var(--tree-connector-color);
border-radius: 999px;
transform: translateY(-50%);
pointer-events: none;
}
.org-tree-children > .org-tree-branch > .org-tree-node::after {
content: "";
position: absolute;
top: calc(50% - 10px);
left: var(--tree-connector-x);
width: var(--tree-connector-width);
height: 20px;
background: var(--tree-connector-color);
border-radius: 999px;
transform: translateX(-50%);
pointer-events: none; pointer-events: none;
} }
@ -708,6 +711,7 @@ function removeEmployee(employee) {
} }
.org-tree-children { .org-tree-children {
position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 2px; gap: 2px;
@ -794,26 +798,6 @@ function removeEmployee(employee) {
gap: 2px; gap: 2px;
} }
:deep(.org-tree-branch::before) {
content: "";
position: absolute;
top: -2px;
bottom: -2px;
left: var(--tree-connector-x);
width: 1px;
background: linear-gradient(180deg, transparent, var(--tree-connector-color) 12px, var(--tree-connector-color) calc(100% - 12px), transparent);
pointer-events: none;
}
:deep(.org-tree-branch-root::before) {
content: none;
}
:deep(.org-tree-branch:not(.org-tree-branch-root):last-child::before) {
bottom: calc(100% - 21px);
background: var(--tree-connector-color);
}
:deep(.org-tree-node) { :deep(.org-tree-node) {
position: relative; position: relative;
display: grid; display: grid;
@ -832,14 +816,29 @@ function removeEmployee(employee) {
transition: background 0.14s ease, color 0.14s ease, box-shadow 0.14s ease; transition: background 0.14s ease, color 0.14s ease, box-shadow 0.14s ease;
} }
:deep(.org-tree-branch:not(.org-tree-branch-root) > .org-tree-node::before) { :deep(.org-tree-children > .org-tree-branch > .org-tree-node::before) {
content: ""; content: "";
position: absolute; position: absolute;
top: 50%; top: 50%;
left: var(--tree-connector-x); left: calc(var(--tree-connector-x) - var(--tree-connector-width) / 2);
width: 14px; width: var(--tree-connector-arm);
height: 1px; height: var(--tree-connector-width);
background: var(--tree-connector-color); background: var(--tree-connector-color);
border-radius: 999px;
transform: translateY(-50%);
pointer-events: none;
}
:deep(.org-tree-children > .org-tree-branch > .org-tree-node::after) {
content: "";
position: absolute;
top: calc(50% - 10px);
left: var(--tree-connector-x);
width: var(--tree-connector-width);
height: 20px;
background: var(--tree-connector-color);
border-radius: 999px;
transform: translateX(-50%);
pointer-events: none; pointer-events: none;
} }
@ -913,6 +912,7 @@ function removeEmployee(employee) {
} }
:deep(.org-tree-children) { :deep(.org-tree-children) {
position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 2px; gap: 2px;