丸子·张丨OnesZhang | 一个小小IT工程师
type: channel
link: https://oneszhang.com/
description: 丸子·张（OnesZhang） - 一位热爱分享的小小IT工程师，提供实用技巧、软件推荐、网站资源、踩坑经验和泛微OA相关内容，探索更多精彩！
items: Top一个"EcologyOA工程师导航"网站
items: Top[EcologyEC9] 之ecodeSDK API文档
items: [泛微 Ecology10] 自定义一个可控的 Loading Message
items: 《别拿你的工作碰瓷我的热爱》
items: [泛微 Ecology10] 浏览按钮搜索按钮样式处理（真按钮）
items: [泛微Ecology10] 获取当前表单所有字段值的方法
items: [泛微Ecology10] 丸子的 E10 小本本
items: [泛微 E9] [ 高阶精华 ] 泛微 E9 新插件：kkfileview，让文件预览 “零门槛”
items: [泛微 EC9] GETE9LOG.jsp 直接查看当前E9日志
items: [泛微 EC9] 开发踩坑：weaver.conn.RecordSet-报错"字符串文字太长"
items: [泛微 EC9] 流程数据建模同表同步 & SQL插入建模数据
items: [泛微 E10] 明细表处理示例JS 1：字段联动后判断明细表数据隐藏选项

Top一个"EcologyOA工程师导航"网站
type: item
date: 2024-02-26T13:51:00+08:00
description: AI辅助制作标识 该文章由丸子引导AI辅助制作生成，如有改进意见，欢迎评论区留言。 引言作为一个泛微OA工程师，我深知在日常工作中寻找技术资料和解决方案的困难。因此，我决定创建一个专门为泛微OA工程师设计的导航网站——huahan.cc。本文旨在分享这一旅程的起点、过程以及网站的主要功能。点击访问“huahan.cc-泛微OA工程师导航”网站的创立初衷在泛微OA系统的开发和维护过程中，找到高质量、实用的资源一直是一个挑战。市面上虽有许多资源，但分散且不易找到。因此，我希望通过这个导航站，为同行们提供一个汇总这些资源的平台，让寻找资料变得更加简单和高效。网站内容与特色huahan.cc致力于为泛微OA工程师提供一个全面的资源导航站，无论是OA论坛、技术文档还是知识文档，这里都应有尽有。网站的设计旨在简化信息探索过程，加速个人和团队的成长。特色功能资源汇总：聚合多种泛微OA相关资源，包括官方文档、技术论坛和教程等。易用性设计：界面简洁，分类明确，便于快速找到所需资源。社区互动：提供反馈和建议通道，鼓励用户贡献资源，形成互助的社区氛围。未来展望我希望huahan.cc能持续成长，不仅限于现有资源的汇总，还将探索更多便利工程师工作和学习的新功能。我也期待更多同行的参与和反馈，一起打造更完善的泛微OA工程师社区。结语感谢每一位访问huahan.cc的朋友。我将继续努力，不断优化和扩展网站内容，希望能为泛微OA工程师的工作带来真正的便利。如果你有任何建议或想要申请友链，欢迎通过mail@oneszhang.com与我联系。 欢迎分享这篇文章，并在评论区留下你的看法和建议！

Top[EcologyEC9] 之ecodeSDK API文档
type: item
date: 2023-07-25T11:15:00+08:00
description: 写在前面主要内容本文档主要对泛微 ecodeSDK 的 API 列表和详细信息进行展示，以帮助开发人员更好地了解和使用该 SDK 的功能。由于未能找到完整的 SDK API 列表文档，因此制作此文档以记录供大家及自己使用。本文档包括以下内容：API 列表：提供 SDK 中可用的所有 API 的名称和功能简介。API 详细：提供每个 API 的详细信息，包括参数、返回值、使用示例等。使用示例：提供一些使用示例，以便开发人员更好地理解如何使用 SDK 中的 API。需要注意的是，由于文档可能存在更新和变化，建议在使用前再次查阅官方文档以获取最新的 SDK API 信息。 特别注意 本文档由丸子本人收集整理制作，内容多由丸子自行分析整理，部分来源自网络，难免存在错误和不详细之处，使用时请自行甄别；欢迎评论区反馈，引用请务必注明出处！ 泛微 ecode 简介ecode 是内嵌在 E-cology9 系统中，为了解决 E-cology9 所有标准界面无侵入定制和扩展二次开发的开发工具。泛微官方 ecode 使用说明：e-cloudstore.com 展开详情 ecode 核心是解决 EC 所有界面无侵入定制和扩展二次开发，采用动态注册，不直接修改源码的方案解决开发需求。除了新开发页面的之外，它还支持所有标准页面的修改。ecode 包含了整套前端编辑器、编译器，可以让用户无需搭建开发环境直接通过浏览器开始 single page 前端开发，同时采用 ecode 开发的内容都是插件化，支持一键共享、复用、二次封装。ecode 中可能用到的技术栈（Technology Stack）：PC 端：js、css、es6、react16.x、react-router3、mobxMOBILE 端：js、css、es6、react16.x、react-router4、mobx 关于如何使用 ecode 关于如何使用 ecode，官方已给出详细的使用说明，你可以直接点击上方链接或访问官方说明文档：https://e-cloudstore.com/doc.html 进行学习，丸子不在此进行过多介绍 * SDK API 列表ecodeSDK1. 数组排序（ecode 运行顺序）对 item 结构体数组按照 order 属性进行排序，该 API 无需使用ecodeSDK.ecodeQueueSort(arr)参数说明参数参数类型必须说明arritem 结构体数组是需要排序的数组样例let arr = [ { order: 3, name: "C" }, { order: 1, name: "A" }, { order: 4, name: "D" }, { order: 2, name: "B" } ]; ecodeSDK.ecodeQueueSort(arr);2. PC 端组件参数复写对 EC 全系统 PC 端组件参数进行复写，包含 组件站 PC 组件库 ecCom、antd 大部分组件 ，其中 Radio、Radio.Button、Tree.TreeNode、Menu.ItemGruop、Select.Option、Select.OptGroup、SelectNew.Option、SelectNew.OptGroup 暂不支持复写ecodeSDK.overwritePropsFnQueueMapSet(name,option)参数说明参数参数类型必须说明nameString是组件库 ecCom、antd 组件名称optionObject是复写配置option.fnFunction是复写钩子函数 (newProps)=>{}option.orderInteger否复写排序option.descString否复写说明样例ecodeSDK.overwritePropsFnQueueMapSet('WeaTop',{ //组件名 fn:(newProps)=>{ //newProps 代表组件参数 //建议添加进行位置判断操作 console.log('WeaTop:',newProps); //在这里输出日志，如果成功输出代表组件成功定位 }, order:1, //排序字段，如果存在同一个页面复写了同一个组件，控制顺序时使用 desc:'在这里写此复写的作用，在调试的时候方便查找' });3. PC 端组件重写对 EC 全系统 PC 端组件参数进行重写，重新定义的组件只要遵循原组件的交互要求，即可进行自由定义ecodeSDK.overwriteClassFnQueueMapSet(name,option)参数说明参数参数类型必须说明nameString是组件库 ecCom、antd 组件名称optionObject是重写配置option.fnFunction是重…

[泛微 Ecology10] 自定义一个可控的 Loading Message
type: item
date: 2025-12-11T13:05:00+08:00
description: Ecology E9 时代，antd.message.loading 是很多前端人的心头好——轻量、可控、非遮罩式、还能手动关闭。但到了 Ecology 10 ，UI 层全面转向 weappUi，只保留了 Spin 的全局遮罩样式。结果就是：异步任务的 Loading 不够友好，也缺乏 message 级别的可控 loading 提示。丸子用最简单的方式，实现了一个「伪 message.loading」效果：轻量、可关闭、不干扰页面交互。效果展示：方案：自己封装一个 message-like Loading核心思路：利用 weappUi.Dialog.message + weappUi.Spin 拼一个轻量提示，再返回可销毁实例。代码极简两行：window.showLoading = () => weappUi.Dialog.message({ type: 'custom', delay: 0, icon: React.createElement(weappUi.Spin, { spinning: true, size: 'small' }), content: '加载中...' }); window.hideLoading = (inst) => inst?.destroy();使用方式也与 antd 非常相似：const loadingInst = window.showLoading(); // 模拟异步任务 setTimeout(() => { window.hideLoading(loadingInst); }, 1500);Minimal. Elegant. 有手就行。为什么不用全局遮罩？原因很现实：Ecology10 的全局遮罩太“重”了遮住整个屏幕 → 用户无法操作对轻任务（接口查询、短轮询）不友好经常误导用户以为系统卡死影响复杂页面的交互体验很多时候，我们只是想来个“轻提示”，而不是把世界暂停。自定义 Loading 的优点 更轻量可控性强视觉一致代码极简 不阻断用户操作，比全屏 Spin 更自然。返回实例 → 我们想关就关，不用等待延时关闭。照样用 weappUi 的风格，不突兀。只两行代码，随处可复用。 写在最后Ecology10 虽然去掉了很多 E9 时代顺手的 Web 组件，但也给了前端更多自由度。轻量级 Loading 只是其中一个小例子。如果你也在 E10 做前端扩展，欢迎来丸子的博客看看

《别拿你的工作碰瓷我的热爱》
type: item
date: 2025-11-14T04:04:23+08:00
description: ·

[泛微 Ecology10] 浏览按钮搜索按钮样式处理（真按钮）
type: item
date: 2025-11-14T00:57:00+08:00
description: 效果对比：修改前修改后CSS代码/* 修改输入框长度 */ input[placeholder="Search Quickly"] { min-width: 100px !important; } /* 基础按钮样式 */ div.field1190285555456860160span .associative-search-icon { background-color: #5d9cec; border-radius: 4px; cursor: pointer; padding: 6px 12px; display: inline-flex; align-items: center; gap: 6px; min-width: 120px; max-height: 24px; } /* 修改图标颜色（与蓝色背景对比） */ div.field1190285555456860160span .associative-search-icon .ui-icon { color: white; } /* 添加文字（通过伪元素实现，无需改HTML） */ div.field1190285555456860160span .associative-search-icon::after { content: "Batch Select"; color: white; } /* hover效果增强 */ div.field1190285555456860160span .associative-search-icon:hover { background-color: #7bb0f2; }使用修改输入框长度代码中placeholder="Search Quickly"对应编辑时显示提示语field1190285555456860160span中的数字部分对应字段ID

[泛微Ecology10] 获取当前表单所有字段值的方法
type: item
date: 2025-11-14T00:34:00+08:00
description: 小白丸子一开始的做法（点击展开） /** * 获取表单内所有字段值 * @returns {Object} 包含主表字段和明细表数据的对象 */ const getAllFieldValues = () => { const formSdk = window.WeFormSDK.getWeFormInstance(); const fieldInfos = formSdk.listFieldInfo(); // 复用现有格式化逻辑 const formatFields = (fieldInfos) => { const result = { mainFields: [], detailTables: {} }; fieldInfos.forEach(field => { if (field.componentKey === 'DataTable') { result.detailTables[field.subFormId] = []; } else if (field.fieldId && /^\d+$/.test(field.fieldId)) { const target = field.subFormId && result.detailTables[field.subFormId] ? result.detailTables[field.subFormId] : result.mainFields; target.push(field.fieldId); } }); return result; }; // 复用现有数据获取逻辑 const getFormData = (fields) => { const result = { mainFields: {}, detailTables: {} }; fields.mainFields.forEach(fieldId => { try { result.mainFields[fieldId] = formSdk.getFieldObj(fieldId); } catch (error) { console.warn(`获取字段 ${fieldId} 失败:`, error); result.mainFields[fieldId] = null; } }); Object.keys(fields.detailTables).forEach(tableId => { try { result.detailTables[tableId] = formSdk.getDetailData(tableId) || []; } catch (error) { console.warn(`获取明细表 ${tableId} 失败:`, error); result.detailTables[tableId] = []; } }); return result; }; const fields = formatFields(fieldInfos); return getFormData(fields); }; 现在的做法formSdk.weFormApi.formStore.getFormData().dataDetails;

[泛微Ecology10] 丸子的 E10 小本本
type: item
date: 2025-11-14T00:32:00+08:00
description: 检查表单在打开后数据是否存在变更:window.WeaForm.getDataStatus();无刷(静默)保存：formSdk.weFormApi.formStore.submitFormData();获取整个表单数据: formSdk.weFormApi.formStore.getFormData().dataDetails;图片上传字段单图片上传样式优化：.ui-upload-line-of-row > div:nth-child(1):nth-last-child(2) { display: none !important ; }优化前优化后ESB调用const ebSdk=window.ebuilderSDK; ebSdk.callEsbFlow("1991410702295896092",{dept:"taet"},[]).then(res=>{/*动作流回调逻辑*/});// 1. 构造请求参数 const requestData = { customParams: { mainTable: { requestId: requestId } }, esbFlowId: "1981608218199199750" }; // 2. 发送POST请求到ESB接口 fetch('/api/esb/server/event/triggerActionFlow', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }) .then((response) => { // 3. 解析响应JSON（捕获HTTP错误状态） if (!response.ok) { throw new Error(`HTTP错误！状态码：${response.status}`); } return response.json(); }) .then((data) => { // 4. 请求成功回调 console.log('ESB流程触发成功:', data); // wffpSdk.showMessage('触发流程成功', 1, 3); // 成功提示（按需启用） }) .catch((error) => { // 5. 异常捕获（网络错误/HTTP错误/解析错误） console.error('ESB流程触发失败:', error); wffpSdk.showMessage('触发刷新合同失败', 2, 3); // 失败提示 });

[泛微 E9] [ 高阶精华 ] 泛微 E9 新插件：kkfileview，让文件预览 “零门槛”
type: item
date: 2025-10-20T12:13:00+08:00
description: 本博客只涉及部分核心操作，不是保姆级教学，希望你也能有自己的思路，感悟破局的乐趣。背景在日常办公中，文件预览是一个高频且重要的需求。传统的文件预览方案往往存在格式支持有限、体验不佳等问题。泛微E9自带的文档预览功能虽然基础，但在面对复杂格式或特殊需求时往往力不从心。今天给大家介绍如何通过集成开源的kkfileview项目，为泛微E9打造一个强大、统一的文档预览解决方案。功能亮点多格式支持：支持Office、PDF、图片、视频、音频等常见格式无缝集成：与泛微E9原有文档模块完美融合零客户端：基于Web的纯前端预览，无需安装任何插件高性能：基于Spring Boot构建，响应迅速开源免费：基于Apache 2.0协议，可自由使用和修改实施步骤第一步：部署kkfileview服务丸子采用的是从官方GitHub下载源码并自行编译打包的方式。如果你不想自己打包，可以私信丸子获取编译好的版本（有时间的话会分享）。启动成功后访问演示页：访问成功界面：第二步：泛微E9文档功能改造核心工具类首先创建一个工具类，用于生成文件下载的ddcode（这是泛微文档外发的核心知识）：package com.onestools; import weaver.docs.docs.util.DesUtils; public class getFileDownloadUrl { /** * 根据文件ID生成临时下载URL * @param fileid 文件ID * @return 下载URL */ public static String getFileDownloadUrl(int fileid) { try { String encrypt = new DesUtils().encrypt(1 + "_" + fileid); return "/weaver/weaver.file.FileDownload?fileid=" + fileid + "&download=1&ddcode=" + encrypt; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据文件ID和基础URL生成临时下载URL * @param fileid 文件ID * @param baseurl 基础URL * @return 下载URL */ public static String getFileDownloadUrl(int fileid, String baseurl) { try { String encrypt = new DesUtils().encrypt(1 + "_" + fileid); return baseurl + "/weaver/weaver.file.FileDownload?fileid=" + fileid + "&download=1&ddcode=" + encrypt; } catch (Exception e) { e.printStackTrace(); return null; } } }JSP页面改造在ecology目录下/docs/e9/index2file.jsp中增加kkfileview预览逻辑：增加引用：<%@ page import="com.onestools.getFileDownloadUrl" %> <%@ page import="sun.misc.BASE64Encoder" %>添加kkfileview预览逻辑：// 现在检查kkfileview配置 boolean useKKFileView = "1".equals(rs.getPropValue("kkfileview","IsUsekkFileView")); String kkFileViewUrl = rs.getPropValue("kkfileview","kkFileViewUrl"); // kkfileview服务地址 String e9BaseUrl = rs.getPropValue("kkfileview","E9BaseUrl"); // E9基础URL if(useKKFileView && !isEdit) { // KKFileView预览逻辑 if(!"".equals(Util.null2String(kkFileViewUrl)) && !"".equals(Util.null2String(e9BaseUrl))) { try { // 使用getFileDownloadUrl工具类生成下载链接 String originUrl = getFileDownloadUrl.getFileDownloadUrl(imagefil…

[泛微 EC9] GETE9LOG.jsp 直接查看当前E9日志
type: item
date: 2025-10-17T15:28:07+08:00
description: 为什么？ 无sysadmin限制，便于测试系统排查问题！速度！快！好看！ 怎么用？ 做一个xxxx.jsp，仍在ecology/目录下访问你的OA地址：/xxxx.jsp 注： 丸子直接用cursor写的！效果图上代码<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ page import="weaver.hrm.User" %> <%@ page import="weaver.hrm.HrmUserVarify" %> <%@ page import="java.io.File" %> <%@ page import="java.io.RandomAccessFile" %> <%@ page import="java.io.IOException" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %> <%@ page import="java.util.Collections" %> <%@ page import="weaver.hrm.User" %> <%@ page import="weaver.hrm.HrmUserVarify" %> <%@ page import="java.io.File" %> <%@ page import="java.io.RandomAccessFile" %> <%@ page import="java.io.IOException" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %> <%@ page import="java.util.Collections" %> <%-- 1. 登录验证：未登录跳转到登录页 --%> <% User user = HrmUserVarify.getUser(request, response); if (user == null) { response.sendRedirect("/login/Login.jsp"); return; } // 方案A：页面与请求保持UTF-8 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 源日志编码（默认GBK，可传GB2312/GB18030） String srcCharset = request.getParameter("srcCharset"); if (srcCharset == null || srcCharset.trim().isEmpty()) { srcCharset = "GBK"; } // 2. 核心参数：当前ecology日志路径（固定路径，无需日期） String logDirPath = request.getRealPath("/") + "log" + File.separator; File logFile = new File(logDirPath + "ecology"); // 3. 显示行数设置：默认100行，限制10-1000行 String lineCountStr = request.getParameter("lineCount"); int lineCount = 100; if (lineCountStr != null && !lineCountStr.trim().isEmpty()) { try { lineCount = Integer.parseInt(lineCountStr.trim()); lineCount = Math.max(10, lineCount); lineCount = Math.min(1000, lineCount); } catch (NumberFormatException e) { lineCount = 100; } } List<String> logContent = new ArrayList<>(); String errorMsg = ""; // 日志级别统计 int infoCount = 0, errorCount = 0, warnCount = 0, debugCount = 0; if ("POST".equalsIgnoreCase(request.getMethod())) { try { if (!logFile…

[泛微 EC9] 开发踩坑：weaver.conn.RecordSet-报错"字符串文字太长"
type: item
date: 2025-10-17T09:51:00+08:00
description: AI辅助制作标识 该文章由丸子引导AI辅助制作生成，如有改进意见，欢迎评论区留言。 记录一次为泛微OA集成AI流程审查功能时遇到的技术难题与解决历程问题背景在最近为泛微OA系统集成AI流程智能审查功能的开发过程中，遇到了一个令人困扰的问题：当尝试将AI返回的审查结果写入数据库时，表单赋值操作始终无法成功完成。经过仔细排查系统日志，发现了关键的错误信息：2025-04-29 19:01:51,512 ERROR A2 - [null] resin-port-8081-363-363[weaver.conn.RecordSet:1908] - weaver.conn.RecordSet java.sql.SQLSyntaxErrorException: ORA-01704: 字符串文字太长这个错误表明，AI返回的字符串内容长度超过了4000字符，导致数据库写入失败。问题排查过程第一阶段：数据库字段类型检查首先检查了数据库表结构，发现目标字段确实是CLOB类型，理论上应该能够存储大文本数据：-- 检查字段类型 SELECT column_name, data_type FROM user_tab_columns WHERE table_name = 'FORMTABLE_MAIN_314' AND column_name = 'AISHJG';结果显示字段类型为CLOB，这让我们一度感到困惑——既然字段类型正确，为什么还会出现长度限制的错误？第二阶段：技术原理探究经过深入研究和测试，终于找到了问题的根源：RecordSet在更新CLOB字段时的局限性在Oracle数据库环境下，SQL语句在执行之前会将所有字符类型的数据隐式转换为VARCHAR2类型，而VARCHAR2类型的最大长度限制为4000字符。当字符串长度超过这个限制时，转换就会失败，抛出ORA-01704: 字符串文字太长异常。即使目标字段是CLOB类型，使用RecordSet的更新方法仍然会受到这个限制的影响。解决方案错误做法 ❌// 以下是会导致错误的代码示例 RecordSet rs = new RecordSet(); String sql = "update formtable_main_314 set aishjg= ? where requestid=12345"; rs.executeUpdate(sql, longContent);正确做法 ✅使用ConnStatement来更新大字段：ConnStatement st = null; try { st = new ConnStatement(); st.setStatementSql("update formtable_main_314 set aishjg=? where requestid=?"); // 设置参数值 st.setString(1, aiResultContent); // 支持CLOB大字段 st.setInt(2, 12345); // 请求ID st.executeUpdate(); } catch(Exception e) { // 异常处理 e.printStackTrace(); } finally { // 资源释放 if (st != null) { st.close(); } }重要技术说明泛微OA字段类型与数据库存储关系在Oracle数据库环境下：多行文本字段（未勾选HTML编辑）：存储为VARCHAR2(4000)多行文本字段（勾选HTML编辑）：存储为CLOB类型最佳实践建议预判内容长度：在处理可能包含大文本的场景（如AI返回结果、富文本内容、日志信息等）时，优先考虑使用ConnStatement。统一的数据库操作封装：public class DatabaseUtil { /** * 更新CLOB字段的通用方法 */ public static boolean updateClobField(String tableName, String clobField, String value, String whereCondition) { ConnStatement st = null; try { st = new ConnStatement(); String sql = "update " + tableName + " set " + clobField + "=? where " + whereCondition; st.setStatementSql(sql); st.setString(1, value); return st.executeUpdate() > 0; } catch(Exception e) { e.printStackTrac…

[泛微 EC9] 流程数据建模同表同步 & SQL插入建模数据
type: item
date: 2025-09-17T12:13:00+08:00
description: 泛微 EC9 流程数据建模实战：2 招搞定数据同步，formmodeid 是关键！ AI辅助制作标识 该文章由丸子引导AI辅助制作生成，如有改进意见，欢迎评论区留言。 在泛微 EC9 的日常运维中，流程数据与建模模块的数据打通，常常是让人头疼的难题——要么需要复杂的转数据操作，要么手动插入数据后建模模块“看不见”。其实，解开这个困局的钥匙，就藏在 formmodeid 这一个字段里。今天就分享两个“ALL IN BOOM”的实用技巧，让流程与建模数据同步变得简单直接。一、流程与建模“同表共用”：零转换，数据实时同步很多时候，我们希望流程中新增的数据，能直接在建模模块中显示，省去中间的“流程转数据”步骤。核心思路就是让流程和建模“共用一张数据表”，而 formmodeid 就是让建模“识别”数据的关键。操作步骤拆解：创建建模模块，绑定流程数据表新建建模模块时，在“数据表配置”环节，直接选择与目标流程相同的数据表（比如流程使用的表是 formtable_main_474，建模就直接绑定这张表）。创建完成后，务必记住这个建模模块的 ID（比如示例中的“92”），这就是后续要用的 formmodeid 值。流程节点执行 DML，给数据“贴标签”在流程设计的某个节点（通常是“结束节点”或“数据提交节点”），添加一个“执行 SQL”的动作，通过 update 语句给表中的数据统一赋值 formmodeid。通用 SQL 模板：update 【流程数据表名】 set formmodeid = '【建模模块 ID】' where 1=1示例（对应表 formtable_main_474、建模 ID“92”）：update formtable_main_474 set formmodeid = '92' where 1=1效果立竿见影：流程中新增的数据，会自动带上 formmodeid = 92 的“标签”，而建模模块因为绑定了同一张表，且默认只识别对应 formmodeid 的数据，所以流程数据会直接在建模中显示，不需要任何额外的转换或同步操作。说白了：建模模块“看不见”数据，往往就差给数据赋上正确的 formmodeid 这一步。二、SQL 直接插入建模数据：formmodeid 是“通行证”无论是二次开发中需要批量导入数据，还是通过 DML 语句手动插入数据，想要让数据在泛微 EC9 建模模块中正常显示，核心还是不能漏掉 formmodeid 字段。关键操作：在写 insert 语句时，除了要插入业务字段（如姓名、日期、金额等），必须额外加上 formmodeid = 【建模模块 ID】 的赋值。示例（向建模模块 ID 为“92”的模块插入数据）：insert into formtable_main_474 (field1, field2, formmodeid) values ('业务数据 1', '业务数据 2', '92')原理很简单：泛微 EC9 的建模模块，会通过 formmodeid 来区分不同模块的数据归属。如果插入数据时没有指定 formmodeid，或者值错误，数据虽然会进入数据表，但建模模块无法“认领”它，自然就不会显示。这就像给数据办了一张“通行证”，formmodeid 就是通行证上的“目的地”，只有目的地正确，数据才能顺利“进入”建模模块。总结：formmodeid——流程与建模数据打通的“核心密钥”泛微 EC9 中流程与建模的数据同步，看似复杂，实则只要抓住 formmodeid 这个核心字段，就能化繁为简：同表共用时，用 update 给数据赋对 formmodeid，实现“数据即同步”；SQL 插入时，给数据带上 formmodeid，让建模模块“认得出”数据。不用纠结复杂的配置，也不用写大量代码，聚焦 formmodeid 这一个字段，就能轻松搞定流程与建模的数据打通，效率直接拉满！

[泛微 E10] 明细表处理示例JS 1：字段联动后判断明细表数据隐藏选项
type: item
date: 2025-07-09T11:00:19+08:00
description: 在表单开发中，明细表（动态表格）的字段联动和数据控制是常见需求。比如当某个字段的值满足特定条件时，需要动态隐藏另一个字段的部分选项。本文通过一个简化的 Demo，演示如何实现这一功能。场景说明假设我们有一个“学生成绩表”明细表，包含两个字段：成绩类型（type）：下拉选择框，选项为 ["优秀(0)", "良好(1)", "及格(2)", "不及格(3)"]分数（score）：数字输入框需求：当“分数”字段的值为空或 0 时，自动隐藏“成绩类型”中的“优秀”和“良好”选项（即移除选项值为 0 和 1 的选项）。实现思路获取明细表及字段的标识（ID）监听数据联动事件（如分数变化后触发）遍历明细表的每一行，判断分数值是否符合条件若符合条件，隐藏当前行“成绩类型”的指定选项Demo 代码实现// 明细表标识（实际开发中通常由表单 SDK 自动生成） const detailTableId = "student_score_table"; // 获取明细表中字段的 ID（参数：字段名，明细表 ID） const typeFieldId = formSdk.convertFieldNameToId("type", detailTableId); const scoreFieldId = formSdk.convertFieldNameToId("score", detailTableId); // 监听数据联动事件（当字段值变化时触发） formSdk.registerAction(window.WeFormSDK.ACTION_DATA_LINKAGE, (data) => { // 获取明细表所有行的 ID 字符串（格式："row1,row2,row3"） const allRowIdsStr = formSdk.getDetailAllRowIndexStr(detailTableId); if (!allRowIdsStr) return; // 无数据行时直接返回 // 解析行 ID 为数组 const rowIds = allRowIdsStr.split(','); // 遍历每一行 rowIds.forEach(rowId => { // 拼接当前行的分数字段 ID（格式：字段 ID_行 ID） const currentScoreField = `${scoreFieldId}_${rowId}`; // 获取当前行的分数值 const scoreValue = formSdk.getFieldValue(currentScoreField); // 判断分数是否为空或 0 if (scoreValue === '' || scoreValue === '0' || scoreValue === 0) { // 拼接当前行的成绩类型字段 ID const currentTypeField = `${typeFieldId}_${rowId}`; // 移除选项值为 0 和 1 的选项（即"优秀"和"良好"） formSdk.removeSelectOption(currentTypeField, "0,1"); } }); });代码解析字段标识获取通过 formSdk.convertFieldNameToId 方法，将字段名转换为表单内部使用的 ID，需传入字段名和明细表 ID（确保在明细表中唯一）。事件监听使用 formSdk.registerAction 监听 ACTION_DATA_LINKAGE 事件，该事件在数据联动（如字段值变化、表单加载完成等场景）时触发，确保逻辑在数据更新后执行。行遍历处理通过 formSdk.getDetailAllRowIndexStr 获取所有行的 ID 字符串，拆分后得到每一行的唯一标识（rowId）。对每一行，通过 formSdk.getFieldValue 获取分数值，判断是否为空或 0。选项隐藏当条件满足时，调用 formSdk.removeSelectOption 方法，传入当前行的“成绩类型”字段 ID 和需要移除的选项值（"0,1"），实现选项的动态隐藏。关键 API 说明方法作用convertFieldNameToId(fieldName, detailTableId)将字段名转换为表单内部 ID（明细表字段需传入明细表 ID）registerAction(actionName, callback)注册事件监听，这里监听数据联动事件getDetailAllRowIndexStr(detailTableId)获取明细表所有行的 ID 字符串（格式："row1,row2"）getFieldValue(fieldId)获取指定字段的值removeSelectOption(…