当前位置: 首页 > news >正文

泛微E9明细表Check框全选/反选功能实现与优化

1. 泛微E9明细表Check框功能痛点解析

第一次用泛微E9处理带明细表的表单时,我就被Check框操作效率惊到了。想象一下:采购申请单要勾选20个物料,财务报销单要选中15张发票,每个Checkbox都得手动点击。有次我测试批量审批功能,连续点击50多个Checkbox后手指都僵了——这体验简直像在用DOS系统办公。

明细表批量操作的核心矛盾在于:前端交互逻辑与后端数据结构的割裂。泛微原生支持明细行删除的批量操作(那个带垃圾桶图标的按钮),却奇怪地遗漏了Checkbox这种高频操作场景。实际项目中,这类需求出现频率高得惊人:

  • 人事部门的培训报名表(勾选多门课程)
  • 行政部门的资产领用单(选择多个物品)
  • 销售部门的合同审批(批量通过条款)

更麻烦的是,系统自带的Checkbox在移动端表现更差。有次我看到同事在手机上处理报销单,两根手指放大缩小页面就为了精准点到那个小方框,这操作成本高得离谱。

2. jQuery实现全选/反选的核心逻辑

解决这个问题的钥匙藏在泛微的WfForm对象里。先看最简实现方案:在明细表上方放个总开关,点击时遍历所有行修改值。这里有个关键细节——泛微的DOM结构动态生成规则。测试时我发现,明细表Checkbox的ID并不是简单的"字段名_rowIndex",而是经过WfForm.convertFieldNameToId方法转换的。

来看优化后的代码结构:

// 在表单加载完成后插入全选按钮 jQuery(document).ready(function(){ const container = jQuery("#formContainer"); container.prepend(` <div class="custom-checkbox-group"> <input type="checkbox" id="masterCheckbox"> <label for="masterCheckbox">全选/反选</label> </div> `); // 绑定点击事件 jQuery("#masterCheckbox").click(function(){ const fieldId = WfForm.convertFieldNameToId("approveFlag", "detail_1"); const rows = WfForm.getDetailAllRowIndexStr("detail_1").split(","); rows.forEach(row => { if(row){ const targetId = `${fieldId}_${row}`; WfForm.changeFieldValue(targetId, { value: this.checked ? "1" : "0", triggerChange: true // 确保触发字段变更事件 }); } }); }); });

这段代码有三个技术要点:

  1. DOM插入时机:必须在jQuery的ready事件中执行,避免泛微尚未完成表单渲染
  2. 字段定位机制:通过convertFieldNameToId转换后的ID才有效
  3. 值变更API:WfForm.changeFieldValue比直接操作DOM更可靠

3. 实际应用中的六大优化策略

原始方案在真实业务场景中会暴露不少问题。去年我给某制造企业实施时,就遇到了这些典型情况:

3.1 动态行处理

当明细表有"新增行"按钮时,原始方案会漏掉新增的行。解决方案是监听泛微的明细行变更事件:

WfForm.bind("detailrowchange", function(event, detailid, rowindex, type){ if(type === "add" && detailid === "detail_1"){ const masterState = jQuery("#masterCheckbox").prop("checked"); const fieldId = WfForm.convertFieldNameToId("approveFlag", detailid); WfForm.changeFieldValue(`${fieldId}_${rowindex}`, {value: masterState ? "1" : "0"}); } });

3.2 视觉反馈优化

单纯修改值不够直观,我增加了CSS动画效果:

.custom-checkbox-group { margin-bottom: 10px; padding: 8px; background: #f5f7fa; border-radius: 4px; } .custom-checkbox-group label { cursor: pointer; transition: color 0.3s; } .custom-checkbox-group input:checked + label { color: #1890ff; font-weight: bold; }

3.3 部分选中状态

借鉴Windows资源管理器的设计,当部分(非全部)行被选中时,主Checkbox显示为"-"状态:

function updateMasterCheckbox(){ const fieldId = WfForm.convertFieldNameToId("approveFlag", "detail_1"); const rows = WfForm.getDetailAllRowIndexStr("detail_1").split(","); let checkedCount = 0; rows.forEach(row => { if(row){ const val = WfForm.getFieldValue(`${fieldId}_${row}`); if(val === "1") checkedCount++; } }); const master = jQuery("#masterCheckbox"); if(checkedCount === 0){ master.prop("checked", false); master.prop("indeterminate", false); }else if(checkedCount === rows.length){ master.prop("checked", true); master.prop("indeterminate", false); }else{ master.prop("checked", false); master.prop("indeterminate", true); } } // 在每次明细表变更时调用 WfForm.bind("fieldvaluechanged", updateMasterCheckbox);

4. 企业级解决方案的进阶技巧

在给银行客户做定制开发时,我们遇到了更复杂的需求场景:

4.1 分页加载处理

当明细表启用分页时,原始方案只能操作当前页。解决方案是调用泛微后台接口:

function batchUpdateAllPages(checked){ const params = { formid: WfForm.getFormId(), fieldname: "approveFlag", detailid: "detail_1", value: checked ? "1" : "0" }; jQuery.ajax({ url: "/api/detail/batchUpdate", type: "POST", data: params, success: function(){ location.reload(); // 刷新同步最新状态 } }); }

4.2 权限控制集成

结合泛微的权限体系,实现不同角色看到不同操作按钮:

const userRoles = WfForm.getUserRoles(); if(userRoles.includes("财务审核员")){ jQuery("#masterCheckbox").show(); }else{ jQuery("#masterCheckbox").hide(); }

4.3 移动端适配方案

针对触屏操作优化交互方式:

jQuery("#masterCheckbox").on("touchstart", function(e){ e.preventDefault(); jQuery(this).trigger("click"); }).css({ "width": "24px", "height": "24px", "-webkit-appearance": "checkbox" });

5. 性能优化与异常处理

在数据量大的场景下(超过500行),直接操作DOM会导致浏览器卡死。我们最终采用的解决方案是:

5.1 分批处理机制

function batchUpdate(rows, fieldId, checked, batchSize=50){ let processed = 0; const total = rows.length; function processBatch(){ const batch = rows.slice(processed, processed + batchSize); batch.forEach(row => { if(row){ WfForm.changeFieldValue(`${fieldId}_${row}`, {value: checked}); } }); processed += batchSize; if(processed < total){ setTimeout(processBatch, 10); // 每批间隔10ms } } processBatch(); }

5.2 错误恢复机制

增加操作日志和状态回滚:

let originalStates = {}; function backupStates(){ const fieldId = WfForm.convertFieldNameToId("approveFlag", "detail_1"); const rows = WfForm.getDetailAllRowIndexStr("detail_1").split(","); rows.forEach(row => { if(row){ originalStates[row] = WfForm.getFieldValue(`${fieldId}_${row}`); } }); } function restoreStates(){ const fieldId = WfForm.convertFieldNameToId("approveFlag", "detail_1"); for(let row in originalStates){ WfForm.changeFieldValue(`${fieldId}_${row}`, {value: originalStates[row]}); } }

6. 实际部署注意事项

在三个不同客户环境部署后,我总结出这些实战经验:

  1. 浏览器兼容性:IE11需要额外polyfill
// 在入口文件添加 if(!Element.prototype.matches){ Element.prototype.matches = Element.prototype.msMatchesSelector; }
  1. 与其他插件的冲突处理:特别是与泛微官方插件的加载顺序
if(typeof WfForm === "undefined"){ let checkCount = 0; const checkReady = setInterval(() => { if(typeof WfForm !== "undefined"){ clearInterval(checkReady); initCheckbox(); } if(checkCount++ > 10){ clearInterval(checkReady); console.error("WfForm加载超时"); } }, 500); }
  1. 性能监控方案:添加执行时间日志
console.time("checkboxOperation"); // ...操作代码... console.timeEnd("checkboxOperation");
  1. 移动端特殊处理:防止触摸穿透
jQuery(".custom-checkbox-group").on("touchmove", function(e){ e.preventDefault(); });
http://www.jsqmd.com/news/530875/

相关文章:

  • 3个核心技巧让老旧Mac重获新生:OpenCore Legacy Patcher深度解析
  • FUTURE POLICE语音模型Python入门实战:10行代码调用语音分析API
  • 基于STM32单片机智能RFID技术的酒类商品防伪溯源WiFi无线APP设计26-073
  • 联想拯救者Y7000P IRX9清灰后WiFi变差?别急着重装系统,先检查这个不起眼的小接口
  • HunyuanVideo-Foley 开源模型社区:GitHub使用教程与协作规范
  • 3步实现智能心率监测:mebeats开源方案全解析
  • 论文降重工具哪个好?论文AI率检测+降AI率+论文润色全流程工具推荐(2026最新)
  • 如何选择最佳路径规划算法:23种算法实战对比与选择指南
  • AI 辅助开发实战:高效完成基于深度学习的毕设项目
  • 影墨·今颜模型部署排错指南:常见403 Forbidden等错误解决
  • Wan2GP V5版保姆级教程:8G显存也能玩转AI视频生成,手把手教你配置MMAudio配音
  • 企业会议记录福音:用ClearerVoice-Studio本地处理,数据安全又高效
  • 5步掌握163MusicLyrics:小白也能快速上手的完整歌词管理指南
  • 7步掌握云端3D计算:如何突破本地硬件限制?
  • 告别找图烦恼!FLUX.1+SDXL Prompt风格,快速生成原创配图教程
  • 诚信可曲挠橡胶接头行业优质推荐榜:卡箍式橡胶接头、卡箍式橡胶软接头、变径橡胶接头、变径橡胶软接头、可挠曲橡胶接头选择指南 - 优质品牌商家
  • Umi-OCR批量OCR功能模块的参数配置问题解析
  • ChatTTS 本地离线版实战:如何实现高效、低延迟的语音合成部署
  • 基于人工智能的电商智能客服系统:从架构设计到生产环境部署实战
  • 突破游戏定制边界:BepInEx让创意玩法触手可及
  • 别再手动敲字了!用Python的pytesseract+OpenCV,5分钟搞定图片文字批量提取
  • Llama-Factory实战指南:从SFT到KTO,解锁大模型高效对齐全流程
  • (11)ArcGIS Pro 地理处理工具高效使用:搜索·收藏·历史记录·批量执行全流程
  • 保姆级教程:手把手教你为SAMA5D4开发板移植Linux串口驱动(含设备树配置)
  • 7大技术特性深度解析:ExDark低光照图像数据集的创新价值与实战应用
  • MiniCPM-o-4.5-nvidia-FlagOS应用场景:政务文件扫描图理解+政策要点提取实践
  • 阴阳师智能自动化:重构游戏体验的效率工具
  • 如何在5分钟内完成Tectonic现代化TeX引擎的终极安装指南
  • Qwen3.5-4B-Claude-GGUF开源大模型部署教程:llama.cpp+FastAPI完整封装
  • InstructPix2Pix体验报告:自然语言修图到底有多方便?