ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

利用字段值动态控制明细表显隐:泛微ecology9实战指南

利用字段值动态控制明细表显隐:泛微ecology9实战指南 很多实施顾问第一次在泛微ecology9里接到这类需求都会觉得挺简单不就是根据某个字段的值把明细表藏起来或者显示出来嘛。但真正动手做的时候才会发现明细表不是普通字段它的显隐控制牵扯初始化时机、字段取数、校验联动、脏数据清理一串问题。这篇文章就用我在ecology9上做过的实际单子为例把“利用字段值动态控制明细表显示与隐藏”这件事从头到尾拆清楚。1. 这个需求长什么样一张单子里的三处真实业务场景先别急着写脚本把需求场景还原清楚。很多开发把“显示隐藏”当成一个纯前端问题结果做出来要么是页面加载时闪一下要么是隐藏之后校验还在要么是明细表数据被带进了保存逻辑。所以第一步一定是把业务分支梳理明白搞清楚这个明细表在什么条件下要出现、什么条件下必须消失。1.1 报销单里的“行程明细”一个最常见的例子最典型的是差旅报销单。报销类型下拉框选“差旅报销”时表单里要出现“行程明细表”里面有出发地、到达地、交通方式、里程数这些字段选“通讯费”或“业务招待费”时这个明细表就不该出现否则填单人会困惑审批人也会看到一堆无意义的空行。这个场景看着简单其实有个坑如果在字段变更时只是把明细表隐藏但明细表里的字段仍然是必填那么提交时表单照样报错。后面会专门说校验联动的问题这里先记住一个结论——显隐控制从来不是单点操作而是一组动作的组合。1.2 采购与合同场景明细表跟着业务类型走采购申请单里也常见这种需求。采购方式选“招标”时要显示“投标供应商明细表”选“单一来源”时不需要这个明细表但要把“供应商说明”单行文本框显示出来。合同审批里就更复杂了合同类型为“框架协议”时弹出一张“品类明细表”为“固定总价”时只留一个总金额字段。这类场景的共同点是主表字段值决定了后续表单结构。它不是某一行数据的显隐而是整个明细表区块的存废。如果做不好填单人要在隐藏的明细表里不停加空行或者审批人看到一张空白明细表不知道要不要填逻辑上完全是灾难。1.3 需求本质不是“做显示隐藏”而是“做业务分支”说白了这个需求的本质是让表单根据业务分支自我裁剪。在ecology9里明细表是一种集合型控件它天然比单行字段多出“行数管理”和“行内字段联动”这两层复杂性。所以做动态显隐时脑子里要有这根弦你控制的不是一个控件而是一块业务区域的进入条件。想清楚这件事后面所有代码逻辑都围绕“当业务类型为X时明细表区块应该处于什么状态”来写而不是机械地“加了段CSS隐藏掉”。思路对了代码才不会越写越乱。2. 先说结论配置能做到什么程度什么时候非写前端脚本不可接手这个需求后我先不建议一上来就写前端脚本而是先看看当前ecology9版本的表单配置能力够不够用。版本不同能白嫖的功能差别很大我见过不少顾问拿着老经验套新版本结果放着现成配置不用硬写了一段不稳定的JS这不是专业做法。2.1 明细表控件和普通字段在显隐规则上的本质差异在ecology9的表单设计器里普通字段的“显示/隐藏”很好配字段属性里就有相关选项甚至可以用正则表达式控制样式。但明细表不一样它本质上是一个容器内部还有一组子字段所以系统自带的显隐规则往往只对“整表”做控制做不到“根据字段值实时切场”。更麻烦的是如果只配置“明细表隐藏”隐藏状态下明细表里的必填字段是否继续参与前台校验不同版本的行为不一致。2.2 配置版在明细表属性里写显示条件的适用场景如果你用的ecology9版本较新明细表属性里会有“显示规则”或类似名称的配置项可以直接写主表字段等于某值的条件。这种方式的好处是零代码、维护简单适合“一个字段单值判断”的场景比如报销类型等于“差旅报销”时显示明细表。但它的局限也很明显一是不太容易实时联动字段值变了页面不一定立刻响应二是多个字段组合判断时配置表达式会很丑甚至配不出来。所以我把配置版定位成“表单结构简单、条件维度少”时的首选。2.3 前端脚本版绑定change事件实时驱动的适用场景当前台需要“选完下拉框明细表立刻出现或消失”这种交互时就得靠前端脚本了。脚本的实现逻辑也很直白监听主表字段的change事件每次值变化就拿新的值去判断然后操作明细表区块的DOM显示状态。同时控制明细表内字段的必填和只读状态避免校验冲突。2.4 一张表定方案三种实现方式对比与选型方案实现成本实时性多字段组合校验联动适用场景明细表显示规则配置低较差困难看版本单条件、结构固定前端JS绑定change中好灵活可完全控制交互要求高的表单后端接口兜底校验高提交时判断完全可控最可靠有数据一致性要求实际项目里我通常“配置脚本后端”三管齐下能用配置的先兜底交互细节用脚本调最后后端再验证一次。这里边的理由很简单前端不管做得多好都只是体验层业务数据的正确性最终得靠后端拿住。3. 用字段值驱动明细表显隐完整脚本与执行流程拆解这节是实操核心。我会从接口准备、初始化、事件绑定、显隐函数、校验联动到完整脚本示例一步步讲怎么实现。代码以ecology9常见的前端扩展方式为例适用于表单中通过JS控件或字段变更脚本维护的场景。3.1 动手前先搞清楚四个接口和两个DOM特征在ecology9里做前端联动绕不开几个基础接口。不同版本接口名多少有些差异但大体逻辑一致你只需要在浏览器控制台里试一下就能确认当前版本到底支持哪个。WfForm.getFieldValue(fieldname)获取主表字段值这是所有判断的入口。WfForm.bindFieldChangeEvent(fieldname, function(){})给字段绑定自定义变更事件。WfForm.getDetailRowNum(detail_1)获取明细表行数用于判断明细表里有没有已录入的数据。操作DOM隐藏明细表最常见的做法是直接拿明细表ID去隐藏外层容器即$(#detail_1).parent().hide()。操作DOM时有个关键点ecology9的明细表在页面上渲染成一个div外层还可能包着表格和表单行。直接hide明细表本身的div往往不彻底要一直往上找到能“一把藏住”的父容器。这个父容器长什么样跟版本和表单布局有关最快的方法是F12去看一眼找到明细表IDdetail_1沿着parent()往上试看到哪一层能把整个明细表区域都包住就记下那一层的特征。3.2 初始化页面打开时先按字段值定一次状态很多人写联动只写了change事件忘了初始化。结果就是新建表单时明明报销类型默认是“通讯费”行程明细表却大大咧咧显示在那里必须手动切换一下下拉框才消失。这就是初始化没做。我的习惯是封装一个toggleExpenseDetail()函数内部统一完成“判断字段值→切换显隐→调整必填状态”这一串动作。页面加载后先执行一次这个函数字段发生change时再执行一次。初始化时机上我会放到$(function(){})里并且加个setTimeout延迟几百毫秒因为明细表的DOM渲染不一定和主表字段同步完成太快操作DOM容易找不到节点。3.3 联动触发监听主表字段的change事件change事件的绑定优先用泛微自己的bindFieldChangeEvent因为它是表单框架层面的接口比直接给原生元素绑change更稳定切换浏览按钮、单元格跳转这些操作也能触发到。示例写法是这样的if (typeof WfForm ! undefined) { WfForm.bindFieldChangeEvent(sptype, function (fieldName, value) { toggleExpenseDetail(); }); }如果你的版本里这个接口不可用退而求其次直接在字段的“变更脚本”里调用toggleExpenseDetail()也行。坏处是逻辑分散在多个地方后期维护容易漏所以我更推荐集中到JS控件里统一管理。3.4 显隐函数同步控制明细表区块、行内编辑态与必填判断条件和显隐切换本身不复杂难的是同时把三个状态同步好明细表区块的显示与隐藏。明细表内部字段是否可编辑。明细表内部字段是否参与必填校验。下面这段是我在差旅报销单里用的核心函数注释里写了每一步的用意function toggleExpenseDetail() { // 获取主表字段值 var typeVal WfForm.getFieldValue(sptype); var showFlag (typeVal 差旅报销); // 找到明细表外层容器 var detailWrap $(#detail_1); if (!detailWrap.length) return; var box detailWrap.closest(.detail_div).length ? detailWrap.closest(.detail_div) : detailWrap.parent(); if (showFlag) { box.show(); // 明细表显示时把明细表里关键字段的必填打开 setDetailRequired(true); } else { box.hide(); // 明细表隐藏时把必填关掉否则提交会被卡住 setDetailRequired(false); } } function setDetailRequired(required) { var flag required ? 1 : 0; // 以明细表中的一个字段为例下面这种写法在多数版本中可用 try { WfForm.changeFieldValue(detail_1_traffic, { isMandatory: flag }); } catch (e) { // 如果接口不支持改用遍历明细行方式逐个设置 var rowNum WfForm.getDetailRowNum(detail_1); for (var i 1; i rowNum; i) { // 部分版本支持对单行字段做只读控制 } } }这段代码的核心思想是显隐只是表象状态一致性才是关键。如果你只控制显示隐藏不控制必填用户的体验会是“明细表已经藏起来了一点提交还是提示某字段不能为空”这种低级问题一旦上线反馈特别难看。3.5 完整脚本直接把逻辑拼进表单把上面几段拼起来形成一个完整的可直接使用的脚本。实际放到ecology9时可以在表单设计器里加一个“视图-自定义JS”控件把代码粘进去也可以在明细表属性里的相关扩展区域挂载。$(function () { setTimeout(function () { toggleExpenseDetail(); }, 300); if (typeof WfForm ! undefined) { WfForm.bindFieldChangeEvent(sptype, function (fieldName, value) { toggleExpenseDetail(); }); } }); function toggleExpenseDetail() { var typeVal WfForm.getFieldValue(sptype); var showFlag (typeVal 差旅报销); var detailWrap $(#detail_1); if (!detailWrap.length) return; var box detailWrap.closest(.detail_div).length ? detailWrap.closest(.detail_div) : detailWrap.parent(); if (showFlag) { box.show(); setDetailRequired(true); } else { box.hide(); setDetailRequired(false); } } function setDetailRequired(required) { var flag required ? 1 : 0; try { WfForm.changeFieldValue(detail_1_traffic, { isMandatory: flag }); } catch (e) { // 降级处理 } }真正部署前记得先用测试表单把“初始显示”“切换显示”“切换隐藏”“隐藏后提交”这四条路径各走一遍。不要只在设计器里看效果一定要把表单发布到测试账号上用真实流程去点一遍。4. 六个容易翻车的细节从字段取不到到隐藏后仍校验如果项目只要求“能跑”上面的代码就够了。但如果想让这个功能上线后真的少挨骂下面六个细节必须一个个排查。这些都是我实际踩过、或者帮别人擦过屁股的坑每一件都值得记在小本本上。4.1 字段值取不到先分清是取不到还是属性名不对WfForm.getFieldValue里传的参数是字段属性名不是字段显示名。有些表单设计器里显示名和属性名叫法不一样比如显示名是“报销类型”属性名可能叫sptype或field0001。这时候第一反应不是怀疑接口有问题而是进表单设计器把字段属性名抄出来核对一遍。还有一种情况是字段本身没绑定到主表而是放在了某个分区里取值接口拿不到。这种问题不太好排查我的建议是直接在浏览器控制台里跑一下WfForm.getFieldValue(sptype)看返回值是什么再判断是字段名问题还是渲染时机问题。4.2 下拉框选项存的是编码不是文本下拉框在ecology9里的存储值往往是选项编码不是显示文本。比如界面上显示“差旅报销”实际存的值可能是travel或1。如果你在判断里写死typeVal 差旅报销结果大概率永远进不了分支。最稳妥的办法是提前在控制台里打印出真实值或者干脆在表单设计器里把选项值固定成有意义的英文编码判断逻辑里使用编码比较var typeVal WfForm.getFieldValue(sptype); if (typeVal travel) { // 差旅报销 // show } else { // hide }切记不要在多个地方各写一遍判断条件最好统一定义一个常量或者配置对象后面改选项值的时候只动一处。4.3 初始化时机不对刷新时明细表闪一下不加setTimeout的话页面加载时会先看到明细表完整显示然后脚本执行后它才消失视觉上就是闪一下。这种现象在慢网络下尤其明显。但setTimeout也不是越多越好设置太长会让用户觉得表单“卡”。我的建议是把初始化绑到ready之后再等300毫秒左右。如果发现300毫秒还不够稳优先检查是不是直接用了旧版本的jQuery选择器或者明细表不是在页面初始渲染而是一步加载进来的。总之这个数值要实测调整别照抄。4.4 隐藏了明细表必填校验还在这是大家问得最多的问题。明细表用CSS隐藏后如果明细表内部某些字段设置了必填前台校验时仍然会检查这些字段导致用户根本看不到字段却被告知“不能为空”。处理方案就是我前面代码里的setDetailRequired显隐切换时同步把必填状态关掉。还有一种情况是明细表本身设置了“至少一行”的校验隐藏时这个校验也要绕过否则即使没有明细行也会触发。这一块在不同版本上表现差异很大需要实测确认。4.5 隐藏前要不要清空已有明细行如果用户在显示明细表的状态下加了两行数据然后切到隐藏分支这两行数据还在内存里。假如不处理提交后这些隐藏的明细行也会跟着保存进库。这算不算问题取决于业务要求。如果隐藏代表“这个明细表不参与本次业务”那就要在隐藏时清空明细行或者在后端保存时根据主表字段值不读取这段明细表数据。前端清空行的接口在部分版本里是WfForm.removeDetailRow但现场删除行会触发用户输入的永久丢失建议隐藏前弹一次确认或者做成“切换时清空并记录日志”。这比闷头清数据要稳妥得多。4.6 多明细表联动时别用固定ID硬编码同一张表单里有两张明细表、三个主表字段互相联动的情况不少见。比如A字段控制明细表1显隐B字段控制明细表2显隐C字段同时影响两张表。如果所有判断逻辑都散落在各字段的变更脚本里后期维护会非常痛苦。我的做法是写一个统一的状态管理函数把所有字段的当前值都读出来集中算出一个“表单形状”对象然后根据这个对象统一设置各明细表和字段的状态。这样做的好处是无论哪个字段变化最终都调用同一个函数重算整个表单状态永远不会出现“改了A忘了改B”的问题。5. 进阶玩法行内控制、多字段组合与后端兜底校验能走到这步说明基础显隐已经没问题了。接下来这三个方向是很多高级表单里真正“撑场面”的功能也是我最近在几个项目里被反复要求的点。5.1 多字段组合条件不只判断一个值有些单子的判断条件不是“报销类型差旅”这么简单而是“报销类型差旅且费用归属市场部或者报销类型通讯费且金额超过1000时才显示明细表”。这种组合逻辑用配置项做基本没戏用前端脚本写其实也不复杂无非是条件表达式长一点。关键在于把条件写成易于阅读的结构别堆在if里。可以先定义两个布尔变量再组合判断var isTravel (typeVal travel); var isHighAmount (amountVal 1000); var showFlag (isTravel isHighAmount) || (!isTravel amountVal 5000);这样逻辑一目了然后面同事接手也好改。如果条件后期频繁调整甚至可以做成后台配置项脚本动态读取配置来决定显隐但这个复杂度要看项目预算一般单子用不到。5.2 行内字段值控制单行显隐明细表内部联动有时不是整个明细表要隐藏而是明细表内的某一行要根据该行某个字段值来隐藏或置灰。比如采购明细表里有个“是否进口”字段选“否”的时候“进口国别”这一列就不要再显示选“是”了才出现。这比整表显隐更麻烦因为要监听明细表行的字段变更并操作单行的DOM。常见的实现方式是在明细表字段的变更脚本里通过获取当前行号和该行字段值去控制该行特定单元格的显示。接口层面可以用WfForm.getCellValue(detail_1, rowIndex, fieldname)获取行内值再用行号去定位DOM。注意明细表是可增删行的行号会变所以绑定事件时要动态监听不要写死在某个行号上。这里还有一个隐藏坑明细表支持复制行、批量填写这些操作触发的事件和手动单行编辑不是同一个测试时要覆盖到这些入口。5.3 后端兜底防止绕过前端直接提交前端显隐做得再好也只是浏览器层面的视觉和校验控制。如果有人通过调试工具强行把隐藏的明细表数据提交了或者调用后端接口绕过了表单页面那么前端的一切规则都会失效。这也是我为什么总强调后端兜底。在ecology9里可以在表单对应的保存动作流或后端接口中加入一个校验逻辑读取主表业务类型字段的值判断当前明细表是否应该为空如果业务类型是不需要明细表的分支却带上了明细数据就直接拒绝提交并给出明确提示。后端兜底虽然需要开发资源但它解决的是“数据一致性”的最底层问题。尤其涉及审批流程的表单一旦隐藏状态的明细表数据混进审批流后面的数据统计都是脏的代价远比写一个校验大得多。5.4 扩展按节点控制明细表编辑权限与外部数据回填最后再说两个我在实际项目里用得很爽的扩展方向虽然表面上看和显隐不搭边但底层逻辑一脉相承。一个是按审批节点控制明细表是否可编辑。比如前几步填单时可以改动明细表进入法务审批节点后明细表只读。这个用WorkflowEngine的节点权限配置能实现一部分但配合前面的显隐函数可以做到“只读节点下不仅不能改还能让明细表按字段值折叠起来只展示有用行”。这比单纯置灰体验好很多。另一个是外部数据回填后触发显隐。比如明细表数据是从主数据系统带过来的带过来之后根据主表某个字段去决定展示哪部分行。这时候不能只依赖用户手动切换下拉框了而是在回填函数完成后主动调用一次全局状态函数确保外部数据变化后表单形状也跟着更新。总之这个需求的精髓不是“隐藏”这个动作而是“数据状态驱动的表单自适应”。无论你当前需求是简单还是复杂只要把状态判断、显隐切换、校验联动、脏数据清理、后端兜底这五个层面想完整了表单在ecology9里就能做到真正好用。做的时候记得多用浏览器控制台验证真实字段值和DOM结构比对着接口文档猜一百遍都管用。
返回列表