简介:用友UAP NC65开发主子表单据的完整实操指南,面向刚入门的ERP二次开发人员,解决从数据库建表、界面布局到前后台联动交互的落地难题。资源围绕“主子表单据”这一典型场景,给出可运行工程与源码解析,涵盖主表/子表设计、DataGrid数据绑定、外键关联及增删改查事件处理等关键环节,可帮助新手避开配置与编码中的常见坑。压缩包共126个文件、4.56MB,以37个Java源码和37个Class编译文件为主体,另含16个SQL脚本、6个properties配置,以及bmf、bpf、func、menu等UAP元数据与功能注册文件,便于对照Java代码、数据库脚本和表单定义同步理解。随包附带的源码与工程文件相互印证,读者可按向导流程边看边练,逐步掌握用友UAP中子表外键绑定、主表切换联动、保存校验等实现方法,理解企业级单据开发的基本套路。该资源已有1677人学习下载,在同类NC开发资料中具有一定参考性,适合需要快速上手UAP平台的新手参考实践。
1. 向导生成主子表单据:先看值不值,再看怎么走
NC65 里的主子表单据跟普通单表单据最大的区别,是它同时维护一张主表和一张子表,典型的像采购订单、销售出库单这类业务,表头负责单据主体信息,表体承载明细行。用 UAP 的向导方式做主子单,能一次性把数据库表、VO、界面模板、Action 类全都生成出来,省掉手工建表和写维护代码的大半工作量。这套流程适合两类人:没有深度接触过 NC65 元数据开发,但被要求快速交付业务单据的实施顾问;以及熟悉 Java 后端、却被 UAP 设计器的界面操作绕晕的开发。本文按我从空白工程到跑通单据全流程的顺序写,包含每一步的配置参数和最常见的翻车点。
2. 把向导拆开看:选主子模板之前,先搞懂职责边界
2.1 UAP 向导到底替你做了哪几件事
UAP 的向导不是一个万能代码生成器,它更像一个元数据装配工具。一次主子表单据向导,本质上完成四件事:在数据库生成主表与子表的物理表结构;在元数据仓库里登记主实体、子实体及二者关联关系;生成一套符合 NC65 标准接口的 VO 类与 Action 类;组装一个带主表区和子表区的前端画面模板。这部分工作对应到传统开发里,是建表、写实体、写 Service、画界面四件事同时发生,所以向导的核心价值不在代码量,而在“一致性和可被后续维护工具识别”。
有一个关键概念要提前明确:NC65 的运行机制是元数据驱动。数据库表结构、界面字段、按钮行为都不是写死在前端代码里的,而是由存储在元数据仓库里的定义驱动。这意味着向导生成完并不等于开发完成,后面所有手工定制——比如加字段、改按钮权限、加审批流——都是在这个元数据体系上追加修改。理解这一点之后,你就能明白为什么一张向导生成的单子,要改的东西反而分布在数据库脚本、XML 定义、Java 代码三个位置。
2.2 环境与入口:在哪个界面里找向导
进入向导之前,先确认你的开发环境装了 UAP Studio。常见开发模式是在 Eclipse 基础上安装 UAP 插件,打开 UAP 设计器透视图。设计器里左侧是资源树,常见入口顺序为:新建——自建数据源——单据模板。不同补丁版本菜单叫法略有差异,有的版本叫“单据模板向导”,有的叫“主子表单据模板”,我遇到过部分环境里入口藏在“业务对象”菜单下,找不到时用设计器右上角的搜索功能直接搜“向导”。
运行向导前要先把数据源配置好。数据源指 NC 元数据仓库对应的数据库连接,通常在你第一次打开设计器时就要配置,配置不对会导致后面生成数据库表脚本失败。检查方式很简单:在设计器的数据源管理窗口里点“测试连接”,能通再继续,这一步 30 秒能救你两小时。
2.3 主子表模板的字段配置顺序
创建主子表单据模板时,操作顺序我建议固定为:先建主实体,再建子实体,最后配置主子关联。反过来操作会频繁遇到子实体引用主实体主键时提示找不到参照信息的问题。
主实体字段至少要包含业务主键和主表编号字段。业务主键通常选择字符串类型,长度 36 位,对应 NC65 常见的主键策略“UUID”;主表编号选择字符串类型,长度 30 位,表单号每天重置的业务要单独再建一个日期字段。子实体必须包含一个引用主实体主键的字段,这个字段建议命名为“主表主键ID”或系统自动生成的关联字段,让向导自动绑定主外键关系。两个实体都建完后,在主子关系配置页里选择子实体,并指定关联字段,这里选错字段是后续子表数据保存不上的头号原因。
2.4 我用过的参数组合(可直接抄)
我习惯用一个相对稳定的参数组合跑第一版,后续再根据需求微调,具体如下表。
| 配置项 | 我的默认值 | 说明 |
|---|---|---|
| 主实体名称 | 业务对象名 + Head | 例如采购申请Head |
| 子实体名称 | 业务对象名 + Detail | 不同明细类型建议加后缀区分 |
| 主实体主键 | 字符串 36 位 | 向导默认生成 |
| 子实体外键 | 字符串 36 位 | 必须与主实体主键类型一致 |
| 主表编号 | 字符串 30 位 | 设置唯一性校验 |
| 子表行号 | 整数 | 用于明细行排序 |
| 是否生成数据库脚本 | 勾选 | 不勾选则不会自动建表 |
| 是否生成前端模板 | 勾选 | 生成后才能在节点管理里挂载 |
表里的字段名和长度不是强制标准,但类型不一致是主子表关联失效的常见原因,尤其是主键和外键的长度、类型两处,必须完全一致。另外行号字段建议保留,后续做明细行上下移动或导入导出排序时要用。
2.5 生成结果包含什么
向导跑完后,通常在指定包路径下生成 VO 类、Action 类,以及在数据库中生成了两张物理表。VO 类继承 SuperVO,包含主表和子表的属性及 getter/setter;主表 VO 中一般会包含一个“子表数据集合”属性,例如名为 children 的字段,存储子表 VO 数组。Action 类继承标准基类,提供增删改查和提交等方法。数据库表命名通常由你在向导里填写的英文代码自动转换,主表名类似业务代码 + _b,子表名类似业务代码 + _b_detail。
生成完之后不要着急去数据库里手改表结构,所有字段增删都回到设计器里做,改完重新生成或增量更新,否则元数据与数据库结构会产生不一致,运行期报错会非常难查。
3. 从向导到数据库:两条表的物理落地与校验
3.1 数据库脚本不是只执行一遍就完
向导生成的数据库脚本,正常会输出在开发工程的 script 目录下。脚本包含建表语句、主键约束、外键约束和注释。我一般不会直接整份脚本一次性执行,而是拆成两步:先执行建表语句,确认两张表都建立成功;再执行外键和索引语句,确认约束无误。
执行完成后,用下面这个简单的查询确认两张表都存在。
SELECT table_name, table_comment FROM information_schema.tables WHERE table_schema = '你的数据库名' AND table_name IN ('你的主表表名', '你的子表表名');这条语句能同时确认表存在与否以及注释是否生成正确。表注释没生成多半是向导阶段没填中文名称,返回设计器补上再重新生成脚本即可,不要手工改数据库注释。
3.2 主外键约束要不要保留
向导生成的脚本里一般会把主外键约束一起建出来,但我在两个正式项目里都选择删掉数据库层面的外键约束,只保留普通索引。原因很实际:NC65 默认使用 UUID 作为主键,数据写入高频且主子表数据由事务统一控制,数据库外键在这种场景下收益极小,反而可能在高并发插入时产生锁竞争。
删掉外键约束后,主子表关系由应用层的元数据关联维护,也就是向导里配置的那条关联关系。这样做之后,数据校验和级联删除都要靠业务代码和底层框架保证。如果你所在的团队强制要求保留数据库外键,那就保留,但要做好出现锁等待时的排查预案。另外主表主键和子表外键一定要建索引,这个我从没省过。
ALTER TABLE 你的子表表名 ADD INDEX idx_detail_fk (子表外键字段);这个索引对主子表联动查询影响很大。NC65 保存主表时,框架会先插主表再批量插子表;查询时则按主表主键反查子表明细,没有索引的关联字段会导致列表加载明细、单据打开回显整套动作都变慢。
3.3 表结构与元数据对不上时的排查路径
向导多次重新生成后,偶尔会出现数据库表结构比元数据多字段或少字段的情况。表现为打开单据报“字段不存在”或保存时报“列名无效”,但查看数据字典时字段确实存在。
常见做法是先跑一次元数据与物理表的对比检查,对比项是字段名、字段类型、长度、是否可空四项。类型不一致是最难发现的,例如元数据中某字段是字符串 36 位,物理表却是 64 位,做查询和更新时一般不会报错,但做精确匹配时结果会诡异。遇到这类问题,回到设计器修改元数据字段定义再重新生成,不要直接改库。
# 如果数据库是 MySQL 系列,可以导出表结构对比 mysqldump -u用户名 -p密码 数据库名 你的主表表名 > 主表结构备份.sql3.4 一行数据都还没插,先看两件事
表建完、关联字段确认完后,先不要着急在界面上点保存,按顺序做两件验证再做单据测试:查询主表和子表字段数是否和设计器一致;对子表外键字段手工插一条指向不存在主表的数据,确认应用层能拦住。
这种“破坏性测试”看着多余,但实际很值得做。向导生成的 Action 里默认会校验子表对应主表是否合法,我遇到过因为关联字段名配置错误,导致这个校验直接不生效、脏数据能静默插进去的情况。宁可提前在 SQL 层面验证,也不要在正式环境回收数据。
4. 把向导产物挂成“可用单据”:节点、模板与按钮三件套
4.1 为什么到这一步才讲功能注册
很多第一次做 NC65 开发的同事,在向导生成后急着找功能注册入口,结果发现单据模板还没跟节点绑定,注册完节点打开是空白页。正确的顺序是:先把单据模板挂到对应节点,再注册功能,最后分配权限。
我先按常见惯例说一遍:NC65 的功能注册在“系统管理——功能注册”里完成,新增一个功能节点,节点类型选“单据维护”,然后指定对应的单据模板标识。这里有个容易懵的点——单据模板标识不是你在向导里填的实体英文名,而是向导生成的模板编码,一般在模板管理界面能看到。
4.2 单据模板与节点的绑定细节
绑定操作要在 UAP 模板管理界面完成。找到模板后,把模板状态改为“启用”,然后分配到对应的功能节点下。分配完成后,打开系统管理里的功能节点树查看,确认节点下能看到该模板编码。
这一步完成后,你只是在元数据层面建立了“节点——模板”的关系,前端还没有任何可见权限。所以不要因为节点树里能看到就认为开发完成,权限分配是下一段的事。
4.3 角色权限与按钮权限分配
权限分配分三层,任何一层缺了,在界面上表现都一样:看不到节点或打开后一片空白。这三层分别是功能权限、数据权限、按钮权限。
功能权限分配在“系统管理——权限管理——角色管理”里,把刚刚注册的功能节点勾选给对应角色。数据权限决定这个角色能看到哪些组织、哪些人的数据。按钮权限要单独在“权限分配——按钮权限”里配置,不在功能节点勾选里一起完成。
按钮权限这里有个我被坑过的细节:向导生成的单据界面默认会带“新增”“修改”“删除”“保存”“提交”等标准按钮,但这些按钮默认都未分配权限。如果你在角色管理里勾了节点,但没给按钮分配权限,用户进来能打开单据,但工具条上全是灰色的,只能看不能动。
-- 常见排查:确认按钮权限表里已经有当前节点记录 SELECT * FROM sm_permission_button WHERE node_code = '你的节点编码';这个查询在不同版本里表名可能有差异,但思路通用。如果查询返回为空,说明按钮权限还没分配,回到权限管理界面分配一次再回来看。
4.4 组织与库存组织这些参数怎么设
单据上的“组织”不是单纯的一个展示字段。NC65 单据多数跟业务组织绑定,保存时要写库存组织、采购组织等 HR 组织维度。向导不会替你生成这些内容,需要在模板字段里把组织参照字段关联到标准组织数据字典。
具体参数上,我通常给主表加“库存组织”字段,类型为参照型,参照对象选组织数据源;子表不做组织字段,继承主表组织维度。保存时 Action 里要能从主表 VO 中取出组织 PK 并传给子表插入逻辑,这部分要自己补代码,向导不直接生成。
4.5 校验“所见即所得”的完整路径
做完节点、模板、按钮三层分配后,建议用完整路径做一遍验证:新建用户并分配角色——用该用户登录系统——找到功能节点并打开——点击新增——验证主子表字段可编辑——点保存——提交审批。
这一趟走完,才算真正把“向导生成”变成了“业务可用”。走到这里常见的现象是:新增按钮可点,但保存后列表刷新不出来。这种现象多半是列表模板和编辑模板不是一个模板,或列表模板没有配置查询 SQL。回到模板管理界面,检查列表模板的查询 SQL 是否存在,我遇到过一次列表模板的 SQL 为空,导致怎么保存都显示不了数据。
5. 避坑与排查:主子表单据最常见的五个坑
5.1 保存子表数据丢失
现象:点击保存后主表数据插入成功,子表数据一条都没有。
原因:向导生成的主表 VO 中,子表数据集合的 setter 方法没有被赋值,或者前端传入的子表数据 JSON 中字段名与 VO 属性不匹配。
解决:先在生成的 Action 类的保存方法里打断点或加日志,打印请求参数中是否包含子表数据。如果参数里有但集合为空,检查前端模板中子表引用字段的映射,确认子表 VO 的 key 与前端页面子表 grid 配置的字段名一致。
5.2 子表显示“无权限”
现象:主表能打开,子表区域提示“没有权限”或整个表体不可编辑。
原因:子表模板的按钮权限没有单独分配,或者子表模板关联的节点与主表模板不同。
解决:到模板管理中确认子表模板是否启用;再到权限分配界面对子表模板对应的节点做按钮权限分配。这里提醒一点,子表模板若用了独立的模板编码,必须确认它也被分配到了同一节点下。
5.3 提交审批时提示“未找到审批流”
现象:保存成功,点提交时提示未找到对应流程。
原因:审批流确实没部署,或审批流绑定的单据类型与当前单据模板的单据类型编码不一致。
解决:进入审批流定义界面,新建审批流并绑定到当前单据类型编码,注意大小写和空格都会被当作不同编码。部署后回到单据节点,重新打开单据再提交。
5.4 字段在数据库存在但界面不显示
现象:向导里能看到字段,数据库里也有列,但前端编辑界面上找不到。
原因:编辑模板里没有把字段拖进画面,这只是元数据层面的问题,与数据库无关。
解决:回到 UAP 模板编辑界面,找到编辑模板设计器,把缺少的字段从字段列表中拖到表单布局中,保存后重新发布模板。
5.5 增删改按钮是灰的
现象:角色功能权限已分配,节点能打开,但工具条按钮灰色。
原因:按钮权限没有对角色开放,或者是按钮模板引用的父节点与当前菜单节点不一致。
解决:在按钮权限管理里把“新增”“删除”“修改”“保存”“提交”等按钮分配给对应角色。分配后清掉前端缓存再试,NC65 的前端权限有缓存机制,清理缓存这步最容易被忽略。
6. 上线前用最小脚本做一次回归,剩下的交给习惯
做多了这类单子之后,我形成了一个固定的上线前检查习惯,每次走完向导加手工配置,都会用几个最小脚本做一遍可量化的回归。这套检查不是验证全部功能,而是在最短时间内确认最底层的基础设施没断。
先确认两张物理表的关联字段索引都在,再确认模板启用的状态数据正确。
SELECT templatecode, templatename, isenable FROM md_template WHERE templatecode = '你的模板编码';这一步能确认数据库层面的元数据登记存在,且当前模板是启用状态。如果这一条都查不到,说明向导生成时元数据写入失败,后面所有排查都无从谈起。
再确认当前节点在功能表中已经注册成功。
SELECT node_code, node_name, template_code FROM sm_funcregister WHERE node_code = '你的节点编码';确认节点编码与模板编码的绑定关系正确后,再清理缓存,用测试账号登录走一遍“新增—保存—提交”的最小链路。这一趟只要跑通,剩下的字段级校验、审批流分支、打印模板都可以在后续版本里继续叠。
从那以后,我做任何一份 NC65 主子表单据,上线前都强制走一遍这三个最小验证:表存在、模板启用、审批流绑定。这三个点看起来基础,但每一层断掉都足以让整个单据在用户面前变成废品。这套习惯帮我把主从单据交付的返工率降了很多,每次换新环境做新单,心里也稳当得多。希望这些过程里的经验和踩坑能帮到你,让你少走一段我已经走过的弯路。
本文还有配套的精品资源,点击获取