(function (global) { 'use strict'; function nodeId(n) { return String(n.uuid || n._id || n.name || ''); } /** * 先序遍历;fn 返回 false 时提前停止。 * @param {*} node * @param {function(*):boolean|void} fn * @returns {boolean} false 表示被 fn 中止 */ function walk(node, fn) { if (!node) return true; if (fn(node) === false) return false; var ch = node.children; if (!ch) return true; for (var i = 0; i < ch.length; i++) { if (walk(ch[i], fn) === false) return false; } return true; } /** 按 uuid / _id / name 查找节点,命中即停。 */ function findNodeByUuid(root, uuid) { if (!root || !uuid) return null; var found = null; walk(root, function (n) { if (nodeId(n) === uuid) { found = n; return false; } return true; }); return found; } function serializeNode(node, depth, maxDepth) { if (!node || depth > maxDepth) return null; var children = []; var ch = node.children || []; for (var i = 0; i < ch.length; i++) { var c = serializeNode(ch[i], depth + 1, maxDepth); if (c) children.push(c); } var comps = []; if (node.components) { for (var j = 0; j < node.components.length; j++) { var comp = node.components[j]; if (comp && comp.constructor) comps.push(comp.constructor.name || ''); } } return { uuid: nodeId(node), name: node.name || '(未命名)', active: node.active !== false, comps: comps, children: children, }; } function copySeries(series) { var out = {}; for (var k in series) { if (Object.prototype.hasOwnProperty.call(series, k)) out[k] = series[k].slice(); } return out; } function hierFingerprint(node) { if (!node) return ''; var parts = [node.uuid, node.name, node.active ? 1 : 0, (node.comps || []).length]; var ch = node.children || []; parts.push(ch.length); for (var i = 0; i < ch.length; i++) parts.push(hierFingerprint(ch[i])); return parts.join('/'); } global.PWAgentUtil = { nodeId: nodeId, walk: walk, findNodeByUuid: findNodeByUuid, serializeNode: serializeNode, copySeries: copySeries, hierFingerprint: hierFingerprint, }; })(window);