致远互联 · 运维知识
一串姓名里,
怎么判断有没有他?
文本串 vs 选人控件,一个 Groovy 函数给出「是 / 否」
?? Groovy 自定义函数实战系列 · 第 3 期
这一系列只攻一件事,CAP 自定义函数。表单里那些翻来覆去手工干的活,配一次函数,往后就不用再管了。
这期聊 多人员姓名包含判断
?? 适用提示
适用产品:致远互联 CAP 表单(自定义函数)
适用场景:报名名单 · 登录人是否参与
关键字符:selfFunction / indexOf / replaceAll
难度指数:★★★☆☆(会写公式就能落地)
活动报名表里有两个字段特别拧巴。一个叫「报名人员」,是文本框,同事把七八个名字用顿号串成一行敲进去;另一个叫「登录人员」,是选人控件,点开组织架构挑出来的一个人。要回答的问题却很朴素——这个人,在那串名字里吗?
第一反应当然是配条件:报名人员「包含」登录人员。可这个想法在配置界面就会被拦下,文本控件的包含判断,值只能填固定内容,选不了表单控件。两个都是动态字段,配置这条路走不通。
走不通就换路:用一个自定义函数,把两边都拆成姓名,再逐个比。这篇把代码、挂公式、过审核,以及几个容易翻车的细节一次讲清。
PART01
适用场景:一串名单,一个人
活动报名表包含 3 个文本控件:活动名称、报名人员、是否参与,1 个选人控件:登录人员。报名人员字段中可能包含多人,当登录人员在报名人员名单中时,「是否参与」字段显示「是」,反之显示「否」。
?? 截图 · 表单设计:登录人员是选人控件,字段名「登录人员」
?? 一句话理解
「报名人员」存的是人手敲的一串姓名,「登录人员」存的是选人控件选出来的一个人。
「是否参与」不是手填的,它挂一条计算公式,值由函数返回。
函数只做字符串判断,不写库、不调接口。
PART02
先说结论:配置这条路走不通
两边的值长得就不一样,这是绕不过去的第一道坎。
配图:同样是「张三」,两边存的东西不一样
左边是一整串字符,分隔符全看敲字的人当时用的哪个键;右边是一个人员对象,值形如「ID::姓名」。拿字符串去等一个对象,怎么配都不会相等。
?? 截图 · 计算条件设置:值只能填固定内容
截图里那句红字:文本控件包含判断,值只能是固定内容,不支持表单控件选择。两个动态字段之间没法直接比,所以必须有一个函数在中间当翻译。
翻译之后的效果是这样——「是否参与」一列由函数自动给出:
?? 截图 · 效果展示:报名人员里的名字与登录人员比对后给出「是 / 否」
| 报名人员 | 登录人员 | 是否参与 |
| \技术支持\张三、李四, | 技术支持 | 是 |
| 张三、李四、王五、技术支持1, 技术支持组 赵六 | 技术支持 | 否 |
| 、 、张三丰, 王强 | 张三丰 | 是 |
| 、 、张三丰 王强 | 张三丰 | 否 |
| JUDYshaw/Mike | JudyShaw | 是 |
五条记录,五个结论,每一条都能在代码里找到出处:
?? 逐行对一遍
第 1 行给「否」:「技术支持」在名单最开头,前面没有顿号,补出来的「、技术支持、」自然找不到。
第 2 行也给「否」:「技术支持1」「技术支持组赵六」都带着尾巴,整词匹配不认这种近似。
第 3 行给「是」:顿号隔开,两头都能补上顿号,一下就命中。
第 4 行是反面教材:两个人名之间用了空格,空格会被删掉,「张三丰」和「王强」粘成一个名字,于是判成「否」。
第 5 行给「是」:英文名统一转小写再比,斜杠也算分隔符。
?? 注意
注意:多个姓名之间不要用空格分隔(代码会删除空格,导致姓名被拼接)。支持的分隔符 为:半角/全角逗号,,、顿号、、半角/全角分号;;、正斜杠/、反斜杠\,可混合或连续使用。
PART03
17 行代码,简短有效
整段函数不长,17 行,逻辑就是业务那句话:人在名单里返回「是」,否则返回「否」。
def p1 = param[0];def p2 = param[1];if (p1 == null || p2 == null) { return "否"; }String members = p1.toString().trim();String self = p2.toString().trim();if (members.length() == 0 || self.length() == 0) { return "否"; }int sp = self.indexOf("::");String target = self;if (sp > 0) { target = self.substring(sp + 2).trim(); }String norm = members.replaceAll("[\\s]+", "");norm = norm.replaceAll("[,,;;/\\\\]+", "、");String t = target.replaceAll("[\\s]+", "");String lower = norm.toLowerCase();t = t.toLowerCase();String w = "、" + lower + "、";if (w.indexOf("、" + t + "、") >= 0) { return "是"; }return "否";
PART04
装进表单:挂公式,过审核
第 1 步 在「是否参与」上配计算公式
「是否参与」是文本控件,在它的计算公式里调用自定义函数,把两个字段当参数传进去:
?? 截图 · 计算公式:selfFunction('isParticipant', {报名人员}, {登录人员})
?? 照图填这几项
函数名称:isParticipant(截图里就是这么命名的,可自行调整)。
参数设置:报名人员,登录人员(顺序别反,p1 是名单,p2 是登录人)。
代码类型:Groovy;返回类型:文本类型。
把上面的代码粘进函数体,点「确定」。
第 2 步 系统管理员后台审核
系统管理员后台页面 → 安全管理 → 安全审计 → CAP 自定义函数审核,找到新建的函数,逐一审核通过。
?? 截图 · CAP 自定义函数审核:勾选「审核通过」→ 确定
?? 提示
新建的函数需要审核通过后才能生效,否则表单运行时会报错。
PART05
五个坑,提前避开
?? 坑位清单
坑 1 · 拿空格当分隔符。空格会被 replaceAll 直接删掉,「张三丰 王强」变成一个人,判定结果直接翻。
坑 2 · 用 contains 直接比。不补两头的顿号,「张三」会命中「张三丰」,把没报名的人判成报名了。
坑 3 · 忘了剥选人控件的前缀。值形如「ID::姓名」,拿整串去比姓名,永远比不中。
坑 4 · 只建函数不看审核。函数没过审,表单运行时报错,排查半天才发现代码根本没上线。
坑 5 · 两个参数传反了。p1 和 p2 一换,名单被当成登录人,所有记录齐刷刷返回「否」。
前两个坑都跟分隔符有关,本质上是一件事:先把名单洗成统一格式,再做整词匹配。顺序反了,怎么调都调不出来。
写在最后
名单是一串手敲的文字,人员是组织架构里选出来的对象。格式从出生就不一样,指望两个下拉框把这件事配出来,注定要失望。
配置能解决的,别写代码;
配置解决不了的,一个函数就够了。
这 17 行换来的,是每一场报名都少一次人工核名单。
往期精彩
? 致远OA升级后启动不了?CAP自检没过 3 个救场方法
? V5 环境巡检工具实战
? 取日志不用再登服务器-致远OA日志打包实战
? 致远CAP实战:多个明细表去重拼接?
? 致远CAP实战:填了身份证号还要手填年龄性别?
?? 关于致远互联
? 北京致远互联软件股份有限公司 · 证券代码 688369
? 成立于 2002 年 · 2019 年科创板上市
? AI-COP 数智化协同运营平台
? 服务超 5 万家中大型政企客户
? ?? 服务热线:400-700-8822
? ?? 知识库:support.seeyon.com
关注公众号「致远互联微服务」
定期更新运维知识干货 ?
股票
板块
用户
资讯
评论 (0)