let detNum = 1; let isUpdating = false; let detcompCodeFI = "field247341";//综合能力编码 let detexamScoreFI = "field247353";//考试得分 let detminScoreFI = "field247343";//最低分 let detmaxScoreFI = "field247344";//最高分 let ScoreFI = "field246848";//职级评定分数 WfForm.bindDetailFieldChangeEvent(detexamScoreFI, function (id, rowIndex, value) {//考评得分汇总 let rdname = WfForm.getFieldValue(rdnameFI); let rowArr = WfForm.getDetailAllRowIndexStr("detail_" + detNum).split(","); if (rowArr.length > 0 && rdname != "") { if (!isUpdating) {//手动修改判断 updateScores(rowIndex);// 执行更新金额操作 } } }); //------------------------------------------------------------------------------------------------------------------------------汇总函数开始 function updateScores(rowIndex) { if (isUpdating) return; isUpdating = true; let compCode = WfForm.getFieldValue(detcompCodeFI + "_" + rowIndex); let scoreStr = WfForm.getFieldValue(detexamScoreFI + "_" + rowIndex); let score = scoreStr != "" ? parseFloat(scoreStr) : null; // 保持未填写状态 let minScore = parseFloat(WfForm.getFieldValue(detminScoreFI + "_" + rowIndex)) || 0; let maxScore = parseFloat(WfForm.getFieldValue(detmaxScoreFI + "_" + rowIndex)) || 0; // **评分超范围检查** if (score != null && (score < minScore || score > maxScore)) { WfForm.showMessage(`评分必须在 ${minScore} - ${maxScore} 之间!`, 2, 3); //错误信息,3s后消失 WfForm.changeFieldValue(detexamScoreFI + "_" + rowIndex, { value: "" }); } // 第一步:形成初始数据 let rowArr = WfForm.getDetailAllRowIndexStr("detail_" + detNum).split(","); let nodeMap = {}; // 用 "本级编码" 作为 key 存储节点数据 rowArr.forEach(rowIndex => { let code = WfForm.getFieldValue(detcompCodeFI + "_" + rowIndex); // 本级编码 let value = WfForm.getFieldValue(detexamScoreFI + "_" + rowIndex); // 数值 nodeMap[code] = { rowIndex, code, value: parseFloat(value) || 0, // 确保是数值 parentCode: null, // 暂时空 rootId: null // 暂时空 }; }); // 第二步:为每个节点确定其直接上级编码(parentCode) for (let code in nodeMap) { let node = nodeMap[code]; // 当前节点对象 let candidate = code; // 从当前编码开始尝试向上找父级 // 尝试逐级截断后两位,查找是否存在合法父节点 while (candidate.length > 2) { candidate = candidate.slice(0, -2); // 去掉末尾两位,尝试变成父级编码 if (nodeMap[candidate]) { // 如果该编码在 nodeMap 中存在,说明是合法父节点 node.parentCode = candidate; // 记录父级编码 break; // 找到后退出循环 } } } // 第三步:每个节点查询roorid for (let code in nodeMap) { let rootCode = code; while (nodeMap[rootCode] && nodeMap[rootCode].parentCode) { rootCode = nodeMap[rootCode].parentCode; // 向上找父节点 } nodeMap[code].rootId = rootCode; // 给当前节点赋值根节点ID } // 第四步:以 rootId 分组,形成平铺结构 const groupedByRoot = {}; for (let code in nodeMap) { const node = nodeMap[code]; if (!groupedByRoot[node.rootId]) { groupedByRoot[node.rootId] = []; } groupedByRoot[node.rootId].push(node); // 平铺加入该 rootId 的分组 } // console.log("按 rootId 分组的节点集合:", groupedByRoot); //查询出受影响的rootid let rootId = nodeMap[compCode].rootId; let chain = getAffectedChain(groupedByRoot[rootId], compCode);//受影响的节点 // console.log("受影响的链路(修改前原始值):", chain.map(node => ({ ...node }))); sumDirectChildrenValue(groupedByRoot[rootId], chain);//更新受影响数值 updateDetailFormValues(chain, detexamScoreFI);//更新明细表数值 // 获取所有 rootId 对应的“根节点对象” let rootNodes = Object.values(nodeMap).filter(node => node.code == node.rootId); // 汇总根节点的得分 let totalTopScore = rootNodes.reduce((sum, node) => { return sum + (parseFloat(node.value) || 0); }, 0); // 写入主表字段(如:总得分) WfForm.changeFieldValue(ScoreFI, { value: totalTopScore }); isUpdating = false; } //------------------------------------------------------------------------------------------------------------------------------获取从指定节点 compCode 一直向上的链路,直到根节点,返回包含所有这些节点的数组 function getAffectedChain(nodes, compCode) { const map = {}; // 初始化一个映射对象,用于存储 code -> 节点对象 的映射 // 遍历所有节点,将它们以 code 为键存入 map 中,方便后续快速查找父节点 nodes.forEach(node => { map[node.code] = node; }); const chain = []; // 用于存储从 compCode 到 root 的链路节点数组 let currentCode = compCode; // 当前处理的节点编码,初始为 compCode // 当当前编码存在并且在映射中能找到对应节点时,一直向上查找 parentCode while (currentCode && map[currentCode]) { chain.push(map[currentCode]); // 将当前节点对象加入链路数组中 currentCode = map[currentCode].parentCode; // 更新当前编码为当前节点的 parentCode,继续向上查找 } return chain; // 返回从 compCode 到 root 的链路节点数组(顺序是从子到父) } //------------------------------------------------------------------------------------------------------------------------------汇总金额 function sumDirectChildrenValue(nodes, chain) { // 遍历链路中从上级开始的节点(不包含第一个节点,即受影响的“当前节点”) for (let i = 1; i < chain.length; i++) { const node = chain[i]; // 找当前节点的直接子节点 const children = nodes.filter(n => n.parentCode == node.code); // 汇总子节点的 value 值 const total = children.reduce((sum, child) => sum + (Number(child.value) || 0), 0); // 更新当前节点的 value 字段 node.value = total; } } //------------------------------------------------------------------------------------------------------------------------------修改明细的额函数 function updateDetailFormValues(chain, fieldPrefix) { chain.forEach(node => WfForm.changeFieldValue(`${fieldPrefix}_${node.rowIndex}`, { value: String(node.value) }) ); } //------------------------------------------------------------------------------------------------------------------------------汇总函数结束