/** * 标准库树通用工具 * * 层级不固定:children 为 null / undefined / 空数组的节点即为「标准」叶子。 * 树路径统一由 " - " 连接,格式与历史实现逐字节保持一致: * 顶层真实节点的 parent 是 Element UI 的虚拟根,因此根节点会进入路径。 */ // 是否叶子(标准) export function isLeaf(data) { if (!data) return true; const children = data.children; return children === null || children === undefined || children.length === 0; } // 祖先 label 列表:含根,顺序为 根 -> 叶 export function getAncestorLabels(node) { const labels = []; let cur = node; while (cur && cur.parent) { labels.push(cur.label); cur = cur.parent; } labels.reverse(); return labels; } // 复刻原 getNodeParent 的路径格式 // leafMarker:标准库传 'null',下单侧传 '' // 叶子判定必须与 isLeaf 一致,否则 children 为 undefined / 空数组的叶子会丢失标记段 export function buildSelectTree(node, leafMarker = '') { const tokens = []; let cur = node; while (cur && cur.parent) { if (isLeaf(cur.data)) { tokens.push(cur.label, leafMarker); } else { tokens.push(cur.label); } cur = cur.parent; } tokens.reverse(); return tokens.join(' - '); } // 路径末段是否为叶子(标准):buildSelectTree 会在叶子前插入标记段 // 用它判断无需依赖 el-tree 节点对象,模板回填路径后同样适用 export function isLeafPath(path) { if (!path) return false; const tokens = path.split(' - '); if (tokens.length < 2) return false; const marker = tokens[tokens.length - 2]; return marker === '' || marker === 'null'; } // 按祖先位置映射订单实体字段 // 缺失的非叶子层级填空串,model 取叶子 label(叶子即标准) export function deriveTreeFields(node) { const labels = getAncestorLabels(node); const n = labels.length; const at = (i) => (i < n - 1 ? labels[i] : ''); return { labels, factory: at(0), laboratory: at(1), sampleType: at(2), sample: at(3), model: n ? labels[n - 1] : '', }; } // 去掉路径末段,用于「当前是叶子但查不到标准」时回退到父级查询 export function dropLastLabel(path) { if (!path) return ''; const idx = path.lastIndexOf(' - '); return idx === -1 ? '' : path.slice(0, idx); }