diff --git a/明细搜索功能函数V1.js b/明细搜索功能函数V1.js index 536660b..cc4c472 100644 --- a/明细搜索功能函数V1.js +++ b/明细搜索功能函数V1.js @@ -1,190 +1,178 @@ //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------搜索功能开始 -/*all_search_field_id 为模糊搜索字段id, search_obj 为搜索对象。 -search_obj 中的 detail_field_id 为搜索对象在明细中的字段id, search_field_id 为搜索对象的搜索字段id, control_field_id 为控制搜索字段可选范围的字段id,控制功能只针对浏览框 -search_field_id 与 control_field_id 均为主表字段,均允许值为 undefined -当 search_field_id 为 undefined 时,表示该搜索对象仅为模糊搜索的对象,无需精准搜索 -当 control_field_id 为 undefined 时,表示该搜索对象的搜索字段可选范围不受明细已有值的影响 -当type: 'displayValue' // 指定获取显示值,这个代表是浏览框或者下拉框;type: 'rawValue' // 指定获取值,这个代表文本,显示值和实际值一致 -***如需控制浏览框搜索字段的可选范围,需在泛微对该浏览框做相应的选择范围设置,一般为数据id属于 control_field_id 字段值的范围!!! -***当前代码不支持对明细多选字段的搜索功能!!! -*/ -var searchDetailNum = 1; // 搜索明细序号设置 -var basic_info = {//搜索字段初始化 - all_search_field_id: 'field200841',//模糊搜索字段,此字段搜索search_obj里的detail_field_id对应字段内容的显示值均为: - search_obj: [ - { - detail_field_id: 'field198856',//证件号码 - search_field_id: 'field200844', - control_field_id: undefined, - type: 'rawValue' // 文本显示和实际值一致 - }, - { - detail_field_id: 'field199842',//姓名 - search_field_id: 'field205846', - control_field_id: 'field200344', - type: 'displayValue' // 浏览框 - }, - { - detail_field_id: 'field201352',//身份标签 - search_field_id: 'field200845', - control_field_id: undefined, - type: 'displayValue' // 浏览框 - }, - { - detail_field_id: 'field198858',//部门 - search_field_id: 'field223429', - control_field_id: undefined, - type: 'displayValue' // 浏览框 - }, - { - detail_field_id: 'field198857',//机构 - search_field_id: 'field223430', - control_field_id: undefined, - type: 'displayValue' // 浏览框 + var searchDetailNum = 1; // 搜索明细序号设置 + var basic_info = {//搜索字段初始化 + all_search_field_id: 'field268341',//模糊搜索字段,此字段搜索search_obj里的detail_field_id对应字段内容的显示值均为: + search_obj: [ + { + detail_field_id: 'field235347',//费用名称 + search_field_id: 'field268342', + control_field_id: undefined, + type: 'browser' // 浏览框 + }, + { + detail_field_id: 'field237848',//事务类型 + search_field_id: 'field268345', + control_field_id: undefined, + type: 'browser' // 浏览框 + }, + { + detail_field_id: 'field238884',//费用类型 + search_field_id: 'field268346', + control_field_id: undefined, + type: 'select' // 选择框 + } + ] } - ] -} -basic_info.search_obj.forEach(function (search) { - if (search.search_field_id) { - WfForm.changeFieldValue(search.search_field_id, { value: "" });//清空搜索字段 - } -}); -WfForm.changeFieldValue(basic_info.all_search_field_id, { value: "" });//清空模糊搜索字段 -WfForm.bindFieldChangeEvent(basic_info.all_search_field_id, function (obj, id, value) {//模糊搜索 - detailSearch(basic_info.all_search_field_id, value); -}); -$(".wf-input-" + basic_info.all_search_field_id).keydown(function (event) {//模糊搜索 - let value = event.target.value; - detailSearch(basic_info.all_search_field_id, value); -}); //搜索区间触发 -// 生成字段变化事件绑定字符串 -function getFieldChangeEventIds() { - return basic_info.search_obj - .filter(field => field.search_field_id) // 只保留有 search_field_id 的字段 - .map(field => field.search_field_id) // 提取 search_field_id - .join(","); // 拼接成逗号分隔的字符串,生成类似:field188336,field193852,field201846 -} -WfForm.bindFieldChangeEvent( - getFieldChangeEventIds(), // 动态生成的字段 ID 字符串 - function (obj, id, value) { - detailSearch(id, value); - } -); -$(".wf-input-" + basic_info.search_obj[0].search_field_id).keydown(function (event) {//证件号码 - let value = event.target.value; - detailSearch(basic_info.search_obj[0].search_field_id, value); -}); -//明细搜索函数 -function detailSearch(fieldid, value) { - Arrtmp = []; - if (fieldid == basic_info.all_search_field_id) {//---------------------------------------------------------------------模糊搜索 - var search = {}; - var rowArr = WfForm.getDetailAllRowIndexStr("detail_" + searchDetailNum).split(","); - rowArr.forEach(rowIndex => { - if (rowIndex !== "") { - let fieldValues = []; - basic_info.search_obj.forEach(field => { - if (field.detail_field_id) { - let fieldId = field.detail_field_id + "_" + rowIndex; - let fieldType = field.type; - let value; - if (fieldType == 'rawValue') {//实际值和显示值一致,如文本框 - value = WfForm.getFieldValue(fieldId); - } else if (fieldType == 'displayValue') {//浏览框 - value = WfForm.getBrowserShowName(fieldId); + /*all_search_field_id 为模糊搜索字段id, search_obj 为搜索对象。 + search_obj 中的 detail_field_id 为搜索对象在明细中的字段id, search_field_id 为搜索对象的搜索字段id, control_field_id 为控制搜索字段可选范围的字段id,控制功能只针对浏览框 + search_field_id 与 control_field_id 均为主表字段,均允许值为 undefined + 当 search_field_id 为 undefined 时,表示该搜索对象仅为模糊搜索的对象,无需精准搜索 + 当 control_field_id 为 undefined 时,表示该搜索对象的搜索字段可选范围不受明细已有值的影响 + 当type: 'browser' // 指定获取显示值,这个代表是浏览框或者下拉框;type: 'text' // 指定获取值,这个代表文本,显示值和实际值一致;type: 'select'选择框 + ***如需控制浏览框搜索字段的可选范围,需在泛微对该浏览框做相应的选择范围设置,一般为数据id属于 control_field_id 字段值的范围!!! + ***当前代码不支持对明细多选字段的搜索功能!!! + */ + basic_info.search_obj.forEach(function (search) { + if (search.search_field_id) { + WfForm.changeFieldValue(search.search_field_id, { value: "" });//清空搜索字段 + } + }); + WfForm.changeFieldValue(basic_info.all_search_field_id, { value: "" });//清空模糊搜索字段 + WfForm.bindFieldChangeEvent(basic_info.all_search_field_id, function (obj, id, value) {//模糊搜索 + searchFunction(basic_info.all_search_field_id, value); + }); + $(".wf-input-" + basic_info.all_search_field_id).keydown(function (event) {//模糊搜索 + let value = event.target.value; + searchFunction(basic_info.all_search_field_id, value); + }); //搜索区间触发 + // 生成字段变化事件绑定字符串 + function getFieldChangeEventIds() { + return basic_info.search_obj + .filter(field => field.search_field_id) // 只保留有 search_field_id 的字段 + .map(field => field.search_field_id) // 提取 search_field_id + .join(","); // 拼接成逗号分隔的字符串,生成类似:field188336,field193852,field201846 + } + WfForm.bindFieldChangeEvent( + getFieldChangeEventIds(), // 动态生成的字段 ID 字符串 + function (obj, id, value) { + searchFunction(id, value); + } + ); + //明细搜索函数 + function searchFunction(fieldid, value) { + Arrtmp = []; + if (fieldid == basic_info.all_search_field_id) {//---------------------------------------------------------------------模糊搜索 + var search = {}; + var rowArr = WfForm.getDetailAllRowIndexStr("detail_" + searchDetailNum).split(","); + rowArr.forEach(rowIndex => { + if (rowIndex !== "") { + let fieldValues = []; + basic_info.search_obj.forEach(field => { + if (field.detail_field_id) { + let fieldId = field.detail_field_id + "_" + rowIndex; + let fieldType = field.type; + let value; + if (fieldType == 'text') {//实际值和显示值一致,如文本框 + value = WfForm.getFieldValue(fieldId); + } else if (fieldType == 'browser') {//浏览框 + value = WfForm.getBrowserShowName(fieldId); + } else if (fieldType == 'select') {//选择框 + value = WfForm.getSelectShowName(fieldId); + } + fieldValues.push(value); + } + }); + let tmp = fieldValues.join(";") + ";"; + // 以分号分隔存入值 + search[rowIndex] = tmp; + } + }); + let tmp = value.trim().split(" "); + if (tmp[0].length > 0) { + tmp = tmp.filter((i) => i && i.trim()); + } + tmp.forEach((item) => { + let regex = new RegExp(item); + Object.keys(search).forEach((e) => { + if (regex.test(search[e])) { + Arrtmp.push(e); } - fieldValues.push(value); + }); + }); + if (value.trim() === "") { + // 如果value为空,显示所有明细行 + WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, "all", false); + } else { + WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, "all", true); // 全部隐藏 + WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, Arrtmp.join(), false); // 显示符合条件的行 + } + WfForm.checkDetailRow("detail_" + searchDetailNum, "", true); // 清空所有勾选项 + } else { + // 生成明细对象 + var search = {}; + var rowArr = WfForm.getDetailAllRowIndexStr("detail_" + searchDetailNum).split(","); + // 遍历所有明细行 + rowArr.forEach(rowIndex => { + if (rowIndex !== "") { + var detailObj = {}; + // 遍历 search_obj 获取每个字段的实际值,并存入 detailObj + basic_info.search_obj.forEach(field => { + if (field.detail_field_id) { + var fieldId = field.detail_field_id + "_" + rowIndex; + var fieldValue = WfForm.getFieldValue(fieldId); // 获取实际值 + detailObj[field.detail_field_id] = { + value: fieldValue, + detail_field_id: field.detail_field_id // 关联 detail_field_id + }; + } + }); + detailObj.rowIndex = rowIndex; + search[rowIndex] = detailObj; } }); - let tmp = fieldValues.join(";") + ";"; - // 以分号分隔存入值 - search[rowIndex] = tmp; - } - }); - let tmp = value.trim().split(" "); - if (tmp[0].length > 0) { - tmp = tmp.filter((i) => i && i.trim()); - } - tmp.forEach((item) => { - let regex = new RegExp(item); - Object.keys(search).forEach((e) => { - if (regex.test(search[e])) { - Arrtmp.push(e); - } - }); - }); - if (value.trim() === "") { - // 如果value为空,显示所有明细行 - WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, "all", false); - } else { - WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, "all", true); // 全部隐藏 - WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, Arrtmp.join(), false); // 显示符合条件的行 - } - WfForm.checkDetailRow("detail_" + searchDetailNum, "", true); // 清空所有勾选项 - } else { - // 生成明细对象 - var search = {}; - var rowArr = WfForm.getDetailAllRowIndexStr("detail_" + searchDetailNum).split(","); - // 遍历所有明细行 - rowArr.forEach(rowIndex => { - if (rowIndex !== "") { - var detailObj = {}; - // 遍历 search_obj 获取每个字段的实际值,并存入 detailObj + // 生成搜索值对象 + var searchValues = {}; basic_info.search_obj.forEach(field => { - if (field.detail_field_id) { - var fieldId = field.detail_field_id + "_" + rowIndex; - var fieldValue = WfForm.getFieldValue(fieldId); // 获取实际值 - detailObj[field.detail_field_id] = { - value: fieldValue, - detail_field_id: field.detail_field_id // 关联 detail_field_id - }; + if (field.search_field_id) { + let searchFieldId = field.search_field_id; + let searchValue = WfForm.getFieldValue(searchFieldId); // 获取实际值 + let type = field.type; // 获取字段的类型 + searchValues[field.detail_field_id] = { value: searchValue, type: type }; // 用 detail_field_id 作为键 } }); - detailObj.rowIndex = rowIndex; - search[rowIndex] = detailObj; - } - }); - // 生成搜索值对象 - var searchValues = {}; - basic_info.search_obj.forEach(field => { - if (field.search_field_id) { - let searchFieldId = field.search_field_id; - let searchValue = WfForm.getFieldValue(searchFieldId); // 获取实际值 - let type = field.type; // 获取字段的类型 - searchValues[field.detail_field_id] = { value: searchValue, type: type }; // 用 detail_field_id 作为键 - } - }); - // 遍历每个明细行,判断是否匹配 - Object.keys(search).forEach(key => { - let detail = search[key]; - let isMatch = true; - // 遍历每个字段进行匹配 - basic_info.search_obj.forEach(field => { - if (field.detail_field_id) { - let searchField = searchValues[field.detail_field_id]; - let detailValue = detail[field.detail_field_id].value; - if (searchField.type == 'rawValue') { - // 部分匹配 - isMatch = isMatch && (!searchField.value || detailValue.includes(searchField.value)); - } else if (searchField.type == 'displayValue') { - // 完整匹配,但处理多个逗号分隔的值 - let searchValuesArray = searchField.value.split(',').map(v => v.trim()); - isMatch = isMatch && (!searchField.value || searchValuesArray.includes(detailValue)); + // 遍历每个明细行,判断是否匹配 + Object.keys(search).forEach(key => { + let detail = search[key]; + let isMatch = true; + // 遍历每个字段进行匹配 + basic_info.search_obj.forEach(field => { + if (field.detail_field_id) { + let searchField = searchValues[field.detail_field_id]; + let detailValue = detail[field.detail_field_id].value; + if (searchField.type == 'text') { + // 支持模糊匹配 + isMatch = isMatch && (!searchField.value || detailValue.includes(searchField.value)); + } else if (searchField.type == 'browser' || searchField.type == 'select') { + // 多选匹配支持交集 + let searchValuesArray = (searchField.value || "").split(',').map(v => v.trim()).filter(v => v); + let detailValuesArray = (detailValue || "").split(',').map(v => v.trim()).filter(v => v); + let hasMatch = searchValuesArray.length === 0 || searchValuesArray.some(sv => detailValuesArray.includes(sv)); + isMatch = isMatch && hasMatch; + } + } + }); + if (isMatch) { + Arrtmp.push(detail.rowIndex); } + }); + // 显示符合条件的明细行 + if (Object.values(searchValues).every(v => !v.value.trim())) { + WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, "all", false); // 显示所有明细行 + } else { + WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, "all", true); // 全部隐藏 + WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, Arrtmp.join(), false); // 显示符合条件的行 } - }); - if (isMatch) { - Arrtmp.push(detail.rowIndex); + WfForm.checkDetailRow("detail_" + searchDetailNum, "", true); // 清空所有勾选项 } - }); - // 显示符合条件的明细行 - if (Object.values(searchValues).every(v => !v.value.trim())) { - WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, "all", false); // 显示所有明细行 - } else { - WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, "all", true); // 全部隐藏 - WfForm.controlDetailRowDisplay("detail_" + searchDetailNum, Arrtmp.join(), false); // 显示符合条件的行 } - WfForm.checkDetailRow("detail_" + searchDetailNum, "", true); // 清空所有勾选项 - } -} -//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------搜索功能结束 \ No newline at end of file + //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------搜索功能结束 \ No newline at end of file diff --git a/汇总函数.js b/汇总函数.js new file mode 100644 index 0000000..9025d07 --- /dev/null +++ b/汇总函数.js @@ -0,0 +1,128 @@ +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) }) + ); + } + //------------------------------------------------------------------------------------------------------------------------------汇总函数结束 \ No newline at end of file