1. 问题现场:A选完B没翻译,这个“小毛病”折腾了一下午
各位做普元EOS开发的朋友,尤其是从8.x版本一路用过来的老伙计,肯定对这种场景不陌生:流程表单里放两个下拉选择组件,A和B,数据源都挂的业务字典。A选完某个分类,通过值变化事件联动把对应值赋给B,然后流程暂存。等你再次打开这条待办、或者从流程中心把暂存数据捞回来一看——B组件要么显示一个光秃秃的编码,要么干脆空白,就是没有按字典把中文翻译出来。更诡异的是,如果你当场不暂存,A一选完B立刻是正常的,一旦走了“暂存 → 再打开”这条路,翻译就丢了。
这个事,说大不大,说小也不小。表单多达几十个字段的时候,偶尔一个下拉不翻译,用户虽然能猜出大概意思,但一旦涉及“状态”“类型”“优先级”这类核心业务字段,显示不对直接影响审批判断。更麻烦的是,这类问题不像报错那样有堆栈可查,界面上看不出“异常”,只是值不对,排查起来全靠经验和一点点运气。
我在这类问题上栽过跟头,也帮几个项目组擦过屁股。今天专门把EOS8.3.3里这个“值变化事件赋值 + 流程暂存 + 字典翻译失效”的组合问题,从头到尾拆一遍,把根因、复现步骤、解决办法和避坑经验一次性说清楚。
先说结论:这不是EOS的翻译功能坏了,而是你赋值给B组件的数据,在暂存后走反填时,根本没过字典翻译这道闸门。至于为什么没过,下文细说。这篇文章适合正在做EOS流程表单开发的实施工程师、二次开发人员,以及被业务人员追着问“这啥意思”的可怜项目经理。如果是刚接触EOS没多久,建议先把“业务字典”“组件绑定”“事件脚本”这几个基础概念过一遍,再回来看,效果更好。
2. 拆解根因:业务字典翻译机制的三个隐藏环节
2.1 字典翻译的本质:存编码、显文本、靠运行时翻译
要理解为什么不翻译,先得弄清楚EOS里业务字典到底是怎么工作的。可能很多人用了一两年,只知道“下拉绑个字典,显示中文,存库存编码”,但没细想过中间环节。
普元EOS的业务字典(BizDictionary)本质上是一组“编码—名称”的映射。比如字典“审批状态”,下面有APPROVED=已通过、REJECTED=已驳回、PENDING=待审。前端下拉组件绑定字典后,实际操作包含三层:
- 显示层:组件渲染时把每个字典项的
name(中文名称)显示在下拉列表里。 - 存储层:用户选中后,组件提交到表单数据模型的值,是
value(编码),除非你特殊配置成存name。 - 翻译层:当表单重新加载、数据反填时,组件拿到存储值编码,再通过字典反查对应的
name,显示到界面上。
也就是说,“显示中文”这件事,不是存的时候就存成中文了,而是“读出来”的时候现翻译的。这有点像国际化的思路——数据库里存ISO语言代码,页面上按当前语言翻译显示。
明白了这个三层结构,再回头看问题:如果B组件在反填时拿到的数据不是字典能识别的合法编码,或者数据根本没经过B组件的翻译逻辑,那它自然就“不翻译”了。这时候界面上显示出的是原始值,可能是A的编码,也可能是A的中文名,具体看你事件脚本怎么写的,反正都不是B字典里能查到的东西。
2.2 值变化事件赋值的三种写法和各自的坑
“在A中添加值变化事件时给B赋值”,这句话说起来轻巧,但落地写法差异巨大。我在不同项目里见过至少三种实现:
第一种:直接取A的选中值赋给B。
// 伪代码示意 var aValue = this.form.getFieldValue('A'); this.form.setFieldValue('B', aValue);这种写法最常见,也最危险。A和B如果用同一个字典,编码一致的话,暂存后反填时B拿到的编码在自己的字典里能查到,可能还能正常翻译。但如果A和B用的字典不同(哪怕枚举值长得一模一样、含义等价,只要字典ID不同),B拿到的编码在B的字典里大概率查不到,翻译必然失败。
第二种:取A的显示文本赋给B。
var aText = this.form.getFieldText('A'); // 拿到的是A选中的中文名 this.form.setFieldValue('B', aText);这种写法更隐蔽。即时编辑时,B组件收到的值是中文文本,因为我们通常设置了“可输入”或数据校验不严格,B可能会把中文文本直接显示出来,看起来一切正常。可一旦暂存再打开,反填逻辑按“编码 → 字典翻译”处理,它拿“已通过”这个中文去B的字典里找对应编码,找不到,只好原样输出——结果就是B显示中文文本(看上去正常)或显示空白/编码(看上去坏了)。更讽刺的是,有时候看起来正常反而是隐患,因为下次你再编辑保存,存进数据库的可能是显示文本而非编码,数据就开始乱套了。
第三种:通过联动配置或自定义Java方法赋值。
// 多见于服务编排或后端赋值 bizDictManager.getValueByName("B字典编号", aText); this.form.setFieldValue('B', bValue);这种相对靠谱,至少做了一次“文本 → 编码”的转换,但前提是转换逻辑写对了、字典编号传对了、异常分支兜住了。别的没问题,问题往往出现在极少数找不到映射的边界值上。
所以你看,“值变化事件给B赋值”这个动作本身没啥争议,争议在“赋什么”。赋值的数据形态,直接决定暂存后还能不能翻译回来。
2.3 流程暂存环节做了什么“手脚”
有人可能问:我明明把B的值赋成了合法编码,暂存前也是正常的,怎么暂存一圈回来就变了?
这就得说EOS流程引擎的暂存机制了。流程暂存(有时叫“草稿”“挂起”)做的事情,本质上是对当前表单数据做一次持久化快照。EOS 8.x里,表单数据通常以JSON结构存储到流程变量、业务表或独立的暂存表中。这个快照保存的是表单数据模型里的字段值,也就是“存储值”,而不是界面上的显示文本。
等你再次打开这条流程,平台会根据快照反填表单数据模型,然后由组件的渲染引擎负责把编码翻译成显示文本。关键在于:这个翻译动作的触发条件,是组件能正确识别自己绑定的字典和数据类型。如果B组件在数据模型中的值是一个来历不明的字符串,且不在字典枚举范围内,翻译逻辑找不到对应关系,绝大多数时候会采取“原样输出”的容错策略——也就是你看到的“不翻译”。
还有一层细节:如果你在赋值脚本或服务里,手动给B组件set了一个值,这个值在当前页面内存里的数据模型是合法存在的,但并没有走B组件的字典翻译链路。等于你给组件“喂”了一个它没见过的编码,它能做的只有照单全收。等表单重新初始化时,它才反应过来——这玩意我不认识。这就是为什么“当场看正常、暂存后看异常”的现象特别迷惑人。
总结一句:暂存本身没毛病,它只是把问题暴露了出来。真正的bug出在赋值环节的数据流没遵循“存储编码 → 翻译显示”的约定。
3. 排查矩阵:遇到不翻译,先定位是哪一类问题
3.1 六类典型原因对照表
为了不让你像我当年一样,一上来就对着事件脚本反复改、瞎试,我建议你先按下面的排查表对号入座。这六类是我在EOS8.3.3实际项目里收集整理的高频原因,基本覆盖90%以上的“暂存后下拉字典不翻译”场景:
| 原因类型 | 关键特征 | 验证方法 | 修复方向 |
|---|---|---|---|
| 赋值内容为中文文本 | B组件暂存后显示中文或乱码,数据库存中文 | 查业务表/暂存JSON,看B字段存的是“已通过”还是“PASS” | 赋值前做“名称转编码” |
| 赋值内容与B字典编码不匹配 | B显示空白,或显示A的编码 | 手动拿赋值结果去字典管理里查是否有该编码 | 改用B字典合法编码,或建立映射 |
| B组件字典绑定丢失 | B下拉列表本身都是空的,不翻译的同时也没可选值 | 检查B组件属性,确认“业务字典”是否选中 | 重新绑定字典ID |
| 暂存反填未触发翻译 | 反填后B显示编码,但下拉点击展开时选项又正常 | 看控制台是否有翻译服务报错 | 检查字典缓存/权限,调整加载时机 |
| 前后端口径不一致 | 同一字段前端用编码,后端Java代码覆盖为显示文本 | 打断点看后端返给前端的JSON值 | 统一前后端赋值标准 |
| 多级联动导致覆盖 | 暂存后再次打开时A触发事件又把B覆盖了一遍 | 断点调试事件脚本触发顺序 | 增加判断条件:仅在A有值时赋值 |
第三类“B组件字典绑定丢失”和第一、第二类有着本质区别:前者是组件配置问题,后者是数据赋值问题。但表现上都很相似——B没翻译。所以排查第一步不是改脚本,而是确认组件本身还是不是“活的”。
3.2 五分钟快速定位法:从数据库反查值开始
遇到现场问题,我习惯先做一步“数据层验证”,不走界面。具体操作如下:
- 打开数据库工具,找到该流程表单对应的业务表或暂存表。EOS的流程暂存数据一般存在
T_EP_WF_TASK_SAVE这类表里,或者存在流程变量(XML/JSON)中,根据你的项目架构来定。 - 捞出这条暂存记录的JSON串,找到A字段和B字段对应的值。
- 看B字段的值到底是:
- A的编码?→ 类型二,赋值映射不对。
- A的中文文本?→ 类型一,赋值没转码。
- 一个完整的、B字典里存在的合法编码?→ 类型四或五,问题出在翻译链路或配置上。
这一步能帮你把“赋值错误”和“翻译失败”区分开。如果数据库里存的值本身就是错的,那就别折腾翻译逻辑了,直接改赋值。如果数据库里存的值明明是对的,但页面不翻译,那才需要去查组件绑定、字典缓存、反填生命周期这些环节。
我见过不少同事,数据库里存的是中文名,却花了两小时去刷新字典缓存、重启服务,完全是南辕北辙。先看数据,再看逻辑,这个顺序能省掉一大半无头苍蝇式的工作。
4. 解决方案:三种场景的完整落地姿势
4.1 场景一:A和B同字典,直接赋值编码
恭喜你,这是最简单的情况。A和B如果挂了同一个业务字典,编码体系完全一致,只需要保证赋值给B的值是编码而非中文名即可。在A的值变化事件里,用标准写法:
// EOS8.3.3 Ajax事件脚本(前端) // 场景:A和B共用同一本字典 // 核心:取编码,不要取文本 var aValue = this.form.getFieldValue('A'); // 获取A选中的编码值 if (aValue && aValue !== '') { this.form.setFieldValue('B', aValue); // 直接把编码赋给B // 可选:同时禁用B,防止用户二次修改 this.form.setFieldProperty('B', 'readonly', true); } else { this.form.setFieldValue('B', ''); }这里有两个容易踩的细节。
第一,不要用getFieldText('A')。getFieldText返回的是A组件的显示文本,也就是字典名称,赋值给B等于把名称当编码存。同一个字典下,显示文本和编码也许存在某种对应关系,但翻译机制不认文本,只认编码,所以你存文本必定翻译失败。
第二,A清空时一定要同步清空B。很多人只写A有值时的赋值,忘写A清空时的处理,结果就是用户先选A、A赋给B后,又把A选了空,B还留着旧值,这种脏数据在后续流程流转时极难排查。加上else分支,成本极低,收益极大。
同字典场景其实还有一种更优解:如果B的业务含义就是A的子集或复制,那不如B组件直接绑定A的字典,甚至可以让B“只读”并动态隐藏,减少一次赋值操作。联动赋值必然引入“赋值时机”和“翻译链路”的问题,能少一个环节就少一个环节。这是我在重构表单时经常优先考虑的方向。
4.2 场景二:A和B不同字典,需要编码映射转换
这是最常见的踢皮球场景。比如A是“支出类型”,字典里有“餐饮、差旅、办公”;B是“费用科目”,字典里有“餐费、交通费、文具费”。两者业务上有从属关系,但字典编码完全独立,A选了“餐饮”,B要联动选“餐费”,这就要做映射了。
我推荐两条路,按项目情况二选一。
方案A:硬编码映射(简单粗暴,适合枚举少、变动不频繁的场景)
// EOS8.3.3 事件脚本中的映射赋值 var aValue = this.form.getFieldValue('A'); var bMap = { 'DINING': 'MEAL_FEE', // A的餐饮 → B的餐费 'TRAVEL': 'TRANSPORT', // A的差旅 → B的交通费 'OFFICE': 'STATIONERY' // A的办公 → B的文具费 }; if (bMap[aValue]) { this.form.setFieldValue('B', bMap[aValue]); }硬编码在初期最快,但千万在代码旁注释清楚映射来源。不然三个月后业务加了新枚举,你对着这张表一脸懵。说实话,硬编码真不是长久之计,尤其是业务字典经常调整的项目,这种代码维护起来能让人脑溢血。
方案B:动态查字典(推荐,适合业务变动频繁、映射规则多的场景)
EOS8.3.3提供了字典访问服务(比如com.primeton.dictionary.service一类的后端服务,或者前端调用this.DictionaryService这类内置对象),可以动态拿到指定字典的所有枚举项。然后你可以约定:A的编码与B的编码之间有一个公共的“映射标记”字段(例如字典项的扩展属性1),用这个标记来做匹配。实现思路是:
// 简化示意:动态获取B字典列表,按映射关系自动找到对应编码 var aValue = this.form.getFieldValue('A'); // 你可以在字典管理中给A和B的枚举项都配置一个相同的扩展属性,比如 outCode var bDictItems = this.form.getDictionaryItems('B_DICT_ID'); var matchedItem = null; for (var i = 0; i < bDictItems.length; i++) { var item = bDictItems[i]; if (item.extAttr1 === aValue || item.extAttr1 === getAItemExtAttr(aValue)) { matchedItem = item; break; } } if (matchedItem) { this.form.setFieldValue('B', matchedItem.value); }动态查字典的最大好处是,新增枚举项不需要改代码,只要在字典管理后台把映射关系配好,前端立刻生效。代价是代码复杂度上去了,但我觉得值得。
这里有个EOS特有的坑提醒一下:调用字典服务获取枚举项时,注意返回结果里value和name的顺序。我见过有同事把枚举项的name当value用,赋值后B翻译不出来。EOS不同版本、不同接口返回的字段名称有细微差异,好在8.3.3相对稳定,但建议在拿到结果后先console.log打印一下,确认字段对应关系再写匹配逻辑。
4.3 场景三:后端服务赋值或审批中改值,需统一翻译链路
有些流程不是前端事件联动,而是后端服务(流程节点服务、事件处理器)在审批过程中改了B的值。比如审批人调整了费用科目,后端的TaskEventHandler重新赋值了B。这种情况下,B不翻译的原因往往不是“赋值内容非法”,而是“后端赋值绕过了表单组件的更新机制”。
在EOS8.3.3的流程集成里,后端通过AssignmentHandler或业务服务修改流程变量,理论上应该同步更新表单数据模型。但实际项目中,我遇到过两种典型问题:
一是后端只更新了流程变量里的字段值,没有更新前端表单对应的数据项,导致前端加载流程变量时,B字段的“值”和“字典翻译依赖的上下文”不同步。解决思路是:后端改值的时候,明确设置表单字段值和对应字典ID,确保反填时组件能同时拿到值和字典信息。
二是后端把B字段值从编码偷偷换成了文本(常见于开发图省事,直接setString塞了个中文)。这个只能靠代码审查和规范约束来根治。我的建议是,在后端赋值代码里统一封装一个方法:
// Java后端工具方法示意 public void setDictFieldValue(String fieldName, String dictId, String value, DataContext ctx) { // 先校验value是否属于字典dictId的合法编码 if (DictService.isValidValue(dictId, value)) { ctx.setValue(fieldName, value); } else { // 尝试把文本值转换为编码 String code = DictService.getCodeByName(dictId, value); if (code != null) { ctx.setValue(fieldName, code); } else { // 记录日志,不允许非法值写入表单 throw new BizException("非法字典值:" + value); } } }这套“合法编码才写、非法值兜底转换、转不了就报错”的思路,能在源头堵住脏数据。比在下游反复排查翻译失效高效多了。
5. 实操记录:一次完整的问题复现与修复
5.1 复现工程搭建步骤
为了方便说明,我搭了一个最小可复现工程,完整还原了“A选择 → B联动 → 流程暂存 → 重新打开 → B不翻译”的链路。你们看这个过程,基本就是日常开发的真实缩影。
环境版本:EOS Platform 8.3.3,流程引擎采用标准流程定义,表单使用动态表单(xForm)模式。
步骤一:创建两个业务字典——DICT_A和DICT_B。DICT_A包含“北京、上海、广州”三个枚举项,编码分别为BJ、SH、GZ。DICT_B包含“华北、华东、华南”,编码分别为HB、HD、HN。
步骤二:表单上放置下拉组件A(绑定DICT_A)和下拉组件B(绑定DICT_B)。给A组件添加“值变化”事件,初始错误版本脚本如下:
// 错误示范:直接取文本赋给B var aText = this.form.getFieldText('A'); this.form.setFieldValue('B', aText);步骤三:发起流程,在表单中先选A(比如选“上海”),A的值变化事件触发,B被赋值为“上海”(中文文本)。此时界面看B,显示“上海”,看起来正常。
步骤四:点击“暂存”,关闭表单。从流程中心/草稿箱重新打开该流程。
步骤五:观察B组件,没有翻译成“华东”之类的字典名称,界面上显示一堆乱码似的中文,或者直接空白。
5.2 修复前数据验证 vs 修复后效果对照
不急着改代码,先做数据层验证。我查了暂存表的JSON,B字段存储的确实是“上海”这个中文文本,而不是HB/HD/HN中的任何一个。证据确凿:问题出在“赋值环节写入的数据不合法”。
修复方案,把值变化事件的脚本改为先做“文本→编码”的转换,再赋编码:
// 正确示范:把A的文本转成B字典的合法编码再赋值 var aValue = this.form.getFieldValue('A'); var mapping = { 'BJ': 'HB', // 北京 → 华北 'SH': 'HD', // 上海 → 华东 'GZ': 'HN' // 广州 → 华南 }; if (mapping[aValue]) { this.form.setFieldValue('B', mapping[aValue]); }改完后重新走一遍“发起流程 → 选A → 暂存 → 重新打开”的链路,B正常显示“华东”。
修复后我还顺手加了一个“B组件在A未选中时清空”的逻辑。因为实际业务里可能出现这样的情况:用户先选了A,联动给了B值,再回头把A清空了,B残存旧编码,流程数据就乱了。加上清空逻辑后,联动赋值才真正闭环。
实测下来,修完这一点之后,从暂存到重新打开,B组件的字典翻译一直稳定,没有出现偶发性失效。
5.3 关于“刷新页面反而不翻译了”的延伸复现
顺手再复现一个变种:A和B同字典,赋值编码本身是对的(比如A、B都绑定DICT_A,A选“北京”,赋给B的编码是BJ),但暂存后打开,B却显示BJ而不是“北京”。
这个变种我曾经一度怀疑是EOS 8.3.3的bug,后来发现是我在onload事件里加了一段自动触发A联动逻辑的代码,导致表单加载时A的值变化事件被错误触发,B在反填完成后再次被赋了一次编码——此时页面初始化还没完成,字典翻译上下文没就绪,B的显示值就被写死了。解决方案很简单:在A的值变化事件入口增加一个“表单是否已完成初始化”的守卫条件。
if (this.form.getParameter('_init_completed') !== 'true') { return; // 初始化完成前,不触发联动 }或者用EOS框架自带的form.phase之类的生命周期状态判断。这种问题不做完整链路复现,真的很难想到,写出来给大家省点排查时间。
6. 边界场景与后续扩展:不止是“不翻译”这么简单
6.1 暂存后值变了:从“不翻译”到“值错误”的进阶问题
“不翻译”只是第一层表象。接下来要警惕的是第二层问题:暂存后,B组件不只是不翻译,弹出的下拉选项也和当前值对不上,甚至用户重新选择会保存成一个完全错误的编码。
这种情况常见于A、B字典不同,但你用了“A的编码直接赋给B”的方式。比如A的“北京BJ”赋给了B,B字典里恰好也有一个BJ,但代表的意思是“标间”——好家伙,数据和语义全错了。
在字典设计中,不同字典各自独立,编码重复很正常。所以跨字典赋值时,切记不能直接复用编码,必须经过映射转换。这也是为什么我在前文反复强调“编码一致不等于语义一致”。业务字典的编码设计最好有点前缀习惯,比如AREA_BJ、ROOM_BJ,减少这种错误的机会。
6.2 多级联动:A→B→C,链路拉长后翻译失效面更大
如果表单里不只是A→B,而是A→B→C甚至A→B→C→D的多级联动,翻译失效的概率会成倍增长。原因很简单:每一级赋值都可能引入一次不合法的数据,错一路带到尾。
有次项目上三层联动,A选大区、B选省份、C选城市。实施工程师只保证了A→B正确,B→C写的时候偷懒复用了B的文本,结果城市下拉永远不翻译。而且因为C组件联动逻辑只在B变化时触发,一旦B值被暂存反填覆盖,C连联动都触发不了。
多层联动的建议:中间层级的值变化逻辑尽量用“编码传递 + 映射查找”,不要用“文本传递”。同时,每一层的赋值都做好“当前源值是否为空”的兜底,避免某个中间层清空导致下层残留脏值。
6.3 从“临时修复”到“规范固化”:字典翻译问题的根治思路
看到这里,如果你只是修一个表单,那第四节的代码够用了。但如果你手里有一整片流程平台,这种“下拉联动不翻译”的问题此起彼伏,那我建议从规范层面下手。
第一,统一封装一个“字典联动赋值”的前端工具方法。把“取源编码、查映射、转目标编码、赋值、清空兜底”这几步全封装好,页面里只调用工具方法,不再允许裸写setFieldValue。
第二,后端提供“字典值校验”服务。在流程暂存、提交、反填等关键节点统一校验,凡是写入表单字典字段的值,必须能通过目标字典的“编码合法性校验”。不合法就直接拒绝或告警,宁可让用户当时就发现报错,也不要事后悄悄出脏数据。
第三,定期复盘字典数据质量。我见过一个项目曾经因为字典项被删除,导致历史流程里几十条B字段反填全部失败。这其实不只是“不翻译”,而是“字典内容变化引发的存量数据失效”。字典管理员在删改枚举项之前,最好先查一下哪些流程还在用这些值,或者做好旧值的兼容映射。
这些规范层面的建议,说实话见效慢,但长期收益极大。我现在带团队做EOS项目,已经把这些内容写进开发规范文档里,上线后字典翻译类工单基本绝迹。
7. 常见问题排查速查表(直接抄作业)
最后,把我这些年积累的“EOS 8.3.3 下拉字典翻译/联动赋值”常见问题整理成速查表。遇到类似问题时,先打开这张表对照操作,能省下大半排查时间。
| 现象 | 可能原因 | 快速处理 |
|---|---|---|
| B显示中文文本,暂存后不翻译 | 赋值用了getFieldText,存的是显示名 | 改成getFieldValue取编码,或做文本转编码 |
| B显示空白,下拉选项也有但选中不了 | 赋值编码不在B字典枚举中 | 用字典接口验证值,修正映射 |
B显示编码(如HB),不是中文 | 反填未触发翻译,或字典缓存未刷新 | 刷新字典缓存;检查表单onload是否覆盖了B |
| B只在暂存后不翻译,不暂存正常 | 事件脚本赋值内容与字典翻译链路不匹配 | 先查暂存表数据的落库值,确认是否合法 |
| B下拉列表本身为空 | 组件字典绑定丢失或字典停用 | 重新绑定字典ID;检查字典启用状态 |
| 多级联动中E级不翻译 | 中间某级赋值用了文本 | 逐级打印赋值后的值,定位第一处异常 |
| 后端服务赋值后B不翻译 | 后端塞了文本或绕过了表单模型 | 统一走后端口径的字典校验+编码赋值 |
| 历史流程数据不翻译 | 字典枚举被删除或编码改动 | 做历史值兼容映射或字典归档 |
最重要的一条核心经验,再强调一遍:字典翻译的前提是“值必须合法”。所谓合法,就是能在目标字典的当前枚举里找到对应编码。一切赋值操作,不管是前端事件还是后端服务,都要先问一句:我这个值,放进去B组件的字典里,能不能查出中文名称?不能,就别往这里塞。别等暂存后界面“白茫茫一片真干净”了,才回来查自己代码的锅。
说个题外话。我见过好几个开发在遇到这个问题时,第一反应是“字典缓存有问题”“平台bug”。其实冷静想一想,平台翻译机制做了这么多年,核心链路是非常成熟的,出问题大概率是我们喂给它的数据不合规。“程序没问题,是人把参数传错了”这个残酷事实,搞IT的早晚都要接受。排查问题时,先怀疑自己,再怀疑平台,效率最高。
另外,如果你在修这个问题时发现B组件绑定字典没有问题、赋值也改成了合法编码,但暂存后依然不翻译,建议再检查一下EOS的字典缓存机制。8.3.3在某些部署方式下,字典项的加载存在一级缓存,修改字典后需要主动刷新缓存。这种问题现象是:原本好好的,字典管理员改了枚举,突然所有历史数据都不翻译了。此时重启服务和清缓存基本能解决,但根治方式还是“字典变更流程要管控,别随手改编码”。这块基本上不属于代码问题,而是运维规范问题。
最后分享一个实战中的“土办法”或者说保命招:表单里关键的字典翻译字段,在数据查询列表(比如流程待办列表、历史列表)中,尽量不要直接展示“存储编码”。哪怕你用了正确的字典翻译组件,也扛不住字典变更导致的历史数据失效。对关键字段,可以在后端查询结果里冗余一个“显示名”字段,保证列表页永远有中文可看,即使翻译组件抽风了,列表也至少不裸奔。这个做法不优雅,但给业务方的体验是稳稳的安全感。我个人测试下来,对避免“用户觉得系统坏了”的投诉非常有效。