ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

NCC参照开发实战:类型解析、最小实现与排障清单

2026/9/18 16:59:39 拓冰建站 浏览量
NCC参照开发实战:类型解析、最小实现与排障清单 简介面向 NC Cloud 开发环境中的实施与开发顾问这份 PDF 系统梳理了 NCC 参照开发的核心脉络帮助读者掌握如何为档案字段创建列表参照、树表参照和树型参照。内容先从参照概念与主要类型展开再按“创建参照工具类—前端代码实现—前后端绑定”三步骤拆解并结合币种、供应商基本分类、客户信息等实际例子说明配置路径与请求访问关系。资源包为 1 个 PDF 文件压缩后大小约 1.68MB便于离线查阅。文档还附有前端 JS 代码示例、配置文件及后端工具类继承关系适合有一定 NC Cloud 开发基础、需要快速上手参照开发的中级顾问参考学习。已有 370 人浏览学习该资源整体而言这份资料从原理到实操都做了针对性总结可作为日常开发与团队内训的速查手册。1. NCC 参照开发先把它当成一套远程数据接口来理解看到“NCC 参照开发”这个主题大多数人第一反应是“做一个下拉框”。但在 NCC 平台上参照Refer真正的产物不是一个 UI 控件而是一套前后端协作的数据接口前端负责弹窗、渲染、多选勾选后端负责按关键词过滤、分页、返回行集中间还有一层注册信息把两者绑定起来。很多开发把精力花在样式上结果注册表里漏掉了缓存和权限参数上线后被业务方反复投诉数据不准。这篇文章面向 NCC 二次开发工程师和实施顾问讲清楚从概念、最小实现、参数调整到交付验证的完整路径读完可以直接照着配置。2. 做 NCC 参照开发先分清三种可扩展的参照类型在动手写代码之前要先把“参照”这个词拆开。NCC 平台里至少有三种对象都叫参照基础档案参照、单据参照、自定义参照。它们在前端都是同一个 Refer 控件但后端数据来源和注册方式完全不同。开发时如果混着来最常见的错误就是把自定义档案当成基础档案去查平台内置的档案表结果字段对不上、权限也拦不住。2.1 基础档案参照、单据参照与自定义参照的区别基础档案参照是平台已经实现的比如客户、供应商、人员、部门。这类参照在标准产品里已经注册好前端引用时只需要知道它的 refcode。单据参照则是把一张业务单据的头表或子表作为数据源典型场景是“选择一张未结算的销售订单”这种参照常要拼接业务状态过滤条件。自定义参照是三者里唯一需要从零搭建的它面向你自己建的档案表或业务表注册时指定数据来源查询入口平台再把它包装成标准参照。这三者前端都能显示成一样的弹窗但底层差别很大。基础档案参照改的是数据权限单据参照改的是查询 SQL自定义参照则要同时考虑建表、注册、查询、权限四条链路。所以接需求时先问一句“这个参照的数据源在哪张表”比问“用什么控件”更接近问题本质。2.2 开发自定义参照时元数据模型里实际登记了什么NCC 自研功能的元数据模型里参照字段并不保存一整套下拉选项它保存的是一个“引用入口”。这个入口在注册表里表现为一行配置参照编码、显示名称、查询入口、缓存开关、多选开关、最大返回行数。理解这一点很重要因为常规开发思维是先建字段再写查询NCC 参照开发是先注册入口再在界面字段上绑定 refcode。我一般会按下面这张表核对注册信息字段名在不同版本里略有出入但含义是稳定的配置项典型值作用常见误区refcodecustfile前端绑定的唯一编码也是 URL 请求里携带的编码多个环境编码不一致前端写死refname自定义档案弹窗标题与无障碍标识不填时弹窗显示空串refurl/ref/custfile后端查询 action 的映射路径路径少一个斜杠直接 404iscacheN / Y是否缓存首次查询结果开启后数据权限可能失效ismultiselectN / Y是否允许多选与前端控件的多选属性必须一致maxrowcount1000单次最大返回行数超了截断设成 0 导致结果集被整体截断这张表对应到开发里就是把“参照”抽象成了“注册表一行配置加一个查询接口”。后续所有排障都围绕这六个字段展开。2.3 一个引用关系幕后有哪些对象在协作当用户在单据上点击参照字段时前端 Refer 控件拼装一个查询请求带上关键词、页码、每页行数、组织主键和前端传入的过滤条件。后端收到后先做 count 查询再取当前页行集返回一个包含 totalCount 和 rows 的标准结构。前端拿到 rows 后按注册配置决定显示哪些列、是否多选。这个模型和普通列表查询几乎一样差别只在请求参数有约定。一次典型请求的参数类似下面这样开发时可以直接在浏览器开发者工具的 Network 面板里核对{ refcode: custfile, keyword: 北京, pageIndex: 1, pageSize: 50, orgPk: 1001A1100000000000Z, filterSql: status 1 }参数里 orgPk 是组织权限过滤的关键filterSql 是业务侧临时追加的条件。后端实现时要优先处理这两个参数而不是只处理 keyword否则参照能弹出来但业务方继续筛数据时结果就对不上了。2.4 选型什么时候用配置什么时候写代码不是所有参照需求都要开发。数据量在两千行以内、只按编码或名称模糊检索、权限要求不高的场景直接用平台自带的下拉参照配置就行把档案表配置成下拉数据的来源即可速度快也不占开发工时。但如果数据量上万、需要按组织过滤、还要带业务状态控制就必须写后端查询 action注册成自定义参照。我见过不少项目为了省事把几百行的档案做成普通下拉框结果一旦超过两千行页面渲染和模糊搜索都开始卡。反过来也有项目动不动就自研参照把平台标准功能绕过去维护成本明显偏高。选型的判断标准只有一个数据规模和过滤规则的复杂程度是否突破了平台默认参照的边界。如果下拉框里需要展示“编码加名称加辅助属性”三列以上就别用普通下拉了直接按参照做后面业务迟早会提这个需求。3. 在 NCC 开发工程里跑通参照开发的最小链路理论理顺后我一般会直接搭一条最小链路建一张新档案表写一个查询 action注册成自定义参照然后在一张测试单据上把它挂出来。这个链路跑通就说明工程环境、注册机制、前后端绑定三个环节都是通的之后往里面加权限、加缓存都不难。3.1 准备开发工程与热部署入口NCC 二次开发通常是在标准产品基础上扩展一个插件工程。前端代码放在对应模块的 uap 资源目录后端代码按模块拆成 jar。开发期可以让前端走热加载后端代码改动后重启本机的 cloud 服务。很多团队没有把热部署配好导致改一行 Java 代码要等两分钟效率极低。常见做法是先用 Maven 编译当前模块再把生成的 jar 同步到开发环境的 lib 目录并重启服务mvn -pl custfile-module -am clean package -DskipTests cp custfile-module/target/custfile-module.jar $NCC_HOME/modules/custfile/META-INF/lib/ # 之后重启本机 cloud 服务这段命令的作用是把 custfile-module 模块连同依赖一起打包然后替换到 NCC 的模块目录。实际运行时前端页面资源也会随 jar 一同加载所以前端热加载没配好的情况下改页面同样需要重启。建议先把这两条命令固化成脚本后面每天要跑很多次。3.2 在后端写一个返回分页数据的查询动作参照的后端查询本质上是一个分页接口。下面用一段示意代码展示核心逻辑类名和父类在不同 NCC 版本里略有差异但查询参数的名称基本一致。RequestMapping(/ref/custfile) ResponseBody public PageResult query(RefQueryParam param) { PageResult result new PageResult(); StringBuilder sql new StringBuilder( select pk_custfile, code, name, org_pk from bd_custfile where 11); ListObject args new ArrayList(); // 关键词同时匹配编码、名称需要时再拼 py 字段做首拼 if (StringUtils.hasText(param.getKeyword())) { sql.append( and (code like ? or name like ?)); args.add(% param.getKeyword() %); args.add(% param.getKeyword() %); } // 组织权限过滤orgPk 为空时通常走全部数据配置 if (StringUtils.hasText(param.getOrgPk())) { sql.append( and org_pk ?); args.add(param.getOrgPk()); } // 先查总量再取当前页避免前端分页出现空白页 int totalCount queryCount(sql.toString(), args); sql.append( order by code limit ?, ?); args.add((param.getPageIndex() - 1) * param.getPageSize()); args.add(param.getPageSize()); result.setTotalCount(totalCount); result.setRows(queryList(sql.toString(), args)); return result; }这段代码有三个点要重点说明。第一keyword 的处理建议同时匹配 code 和 name如果档案有拼音码字段还可以追加首拼匹配这部分是业务方感知最明显的检索体验。第二orgPk 过滤要在查询层做不能依赖前端传回过滤后的结果集否则数据权限形同虚设。第三pageIndex 以 1 还是 0 开始不同版本框架约定不同联调时用 Network 面板确认再把统一约定写进团队的开发规范。3.3 在注册表里登记参照并绑定 Reference 控件后端接口写好并验证能返回数据后接下来把它注册成参照。注册动作通常是一行 insert核心字段就是第 2 章表格里的那六个。INSERT INTO sm_refinfo (refcode, refname, refurl, iscache, ismultiselect, maxrowcount) VALUES (custfile, 自定义档案, /ref/custfile, N, N, 1000);插入后前端控件才能通过 refcode 找到这个查询入口。实际项目里这张表的物理表名和字段名可能带有模块前缀执行前先用 desc 命令确认表结构。开发阶段 iscache 一律设成 N等全部功能验证完再评估是否开缓存否则改代码后经常出现“明明改了却不生效”的假象。前端控件绑定在页面模板的 items 配置里把 refcode 挂在对应字段上{ items: [ { key: custfile, label: 自定义档案, controlType: refer, refcode: custfile, props: { isMultiSelect: false, remoteSearch: true, pageSize: 50 } } ] }这段配置的作用是告诉前端字段 custfile 使用参照控件数据入口的 refcode 是 custfile远程搜索开启每页显示 50 行。这里最容易出的问题是 refcode 与注册表里的值不一致比如环境变量把编码替换成了另一个值结果前端弹窗报“参照不存在”。排查时先对比这两处编码能省下不少时间。3.4 联调时最容易发现的三个问题第一个是返回字段和前端显示字段对不上。前端配置里指定显示 code、name 两列但后端 rows 里返回的是 pk、code、name、org_pk此时前端通常只取前几个字段表现为列显示错位。遇到这种情况先看 Network 面板里 response 的 rows 结构再调整后端返回的字段顺序。第二个问题是翻页后过滤条件丢失。部分前端组件在翻页时只会把 pageIndex 和 pageSize 传回去keyword 和 filterSql 是否继续传取决于配置。如果每次翻页后数据变成全量就到网络请求里对比两次请求的参数多半是 keyword 没带。第三个是缓存干扰。开发阶段如果不小心把 iscache 设成了 Y第一次查询成功后后续请求都从缓存里取后端打印的 SQL 根本不会出现。所以开发期统一设 N测试阶段再单独验证缓存场景。4. 参照开发必调的 4 个参数与 3 个隐藏坑最小链路跑通后进入真正的项目阶段调整参数、处理权限、排查线上反馈。这一章讲的是从“能弹出来”到“能上线”之间必须过的几个关卡。4.1 参数表缓存、多选、返回行数、远程过滤参照相关参数不少但项目里真正需要人工调的通常是四个iscache、ismultiselect、maxrowcount 和远程过滤开关。它们互相影响下面这张表是项目里默认可抄的配置建议。参数推荐值影响范围备注iscacheN查询性能与权限一致性开启后权限逻辑要在首次查询时全部生效ismultiselect按业务定前端勾选方式与返回行集必须和前端控件的多选属性一致maxrowcount1000超过后截断返回设 0 等于不限制但大数据量会卡remoteSearchtrue是否走远程过滤关闭后前端在本地过滤只适合几千行项目里常见的一种误用是依赖前端本地过滤。remoteSearch 设成 false 后前端首次拉取 maxrowcount 行用户输入关键词时只在本地筛选。数据量一旦超过一万行首次加载就慢而且用户永远搜不到第 1000 行以后的内容。所以只要参照的服务端有条件过滤能力就保持 remoteSearch 为 true。4.2 缓存开启后数据权限为什么失效这是上线后才容易被发现的坑。开启 iscache 后后端第一次查询会把结果集缓存在内存里后续同一个参照的请求都直接命中缓存不再执行权限过滤 SQL。也就是说用户 A 第一次查询时带着 orgPk 过滤了数据但用户 B 用同一个缓存的参照如果没走 SQL就会看到 A 的数据范围之外的行。正确的做法是安全优先凡是参照涉及数据权限、组织隔离就别开缓存如果确实要开确保缓存的 key 包含组织主键并在第一次查询时把权限条件固化进 SQL。有些版本里还要把缓存失效机制接进权限变动事件权限调整后主动清理缓存。这个参数要单独写进运维手册不要靠口头传。4.3 前端注册编码不一致为什么菜单上显示空白现象是参照弹窗能打开但列表空白或者前端控制台报 refer not found。十有八九是 refcode 不一致。常见原因有三个开发环境手工注册用的是 custfile但前端配置从测试环境同步成了 custfile_test或者注册后没有刷新元数据缓存再或者大小写不一致平台里编码是区分大小写的。排查时先看注册表里实际存在的编码再跟前端请求里的 refcode 做比对select refcode, refname, refurl, iscache from sm_refinfo where refcode like %custfile%;前端请求时用的编码可以从 Network 面板请求参数里抄出来。比对后修改其中一个保持统一。研发规范里应该写死一条注册编码只允许小写字母和数字杜绝大小写问题。4.4 字段受控导致参照字段只读有时候参照本身没问题但界面上的格子是灰色的点不进去。这通常是页面模板里字段的状态控制导致的。NCC 页面模板的编辑、浏览、新增三种状态下字段的可编辑、必填、只读属性是独立配置的而且可以叠加。开发时只在 edit 状态下把字段设为可编辑浏览态下就会显示为只读。检查方法在页面模板设计器里打开字段属性把新增状态和编辑状态下的可编辑开关都打开再确认参照控件的 editable 属性没有设置成 false。另外还要看动态状态控制脚本里有没有对该字段做赋值这属于更隐蔽的覆盖场景用浏览器检查 DOM 上字段的 disabled 状态能快速定位。4.5 排查用的三条 SQL 和日志命令下面三条命令覆盖最常遇到的注册、请求、缓存三类问题可以写进团队的排障手册。# 1. 查注册在数据库客户端里执行确认 refcode 和 refurl 是否和代码一致 select refcode, refname, refurl, iscache from sm_refinfo where refname like %自定义%; # 2. 看请求实时跟踪后端日志里的 SQL 和报错 tail -f $NCC_HOME/logs/cloud/run.log | grep -E custfile|ref/custfile # 3. 清缓存调用平台缓存清理接口cacheKey 换成目标 refcode curl -X POST http://localhost:8080/nccloud/cache/clearCache -d cacheKeycustfile第三条的接口路径在版本之间差异较大实际使用时先看平台缓存管理文档并按实际端口修改。排查时按顺序执行这三条能覆盖九成以上的线上问题。5. 参照开发交付前我会保留的一套最小验证清单功能做完只算完成一半。参照类功能最怕的是“开发环境好好的测试环境数据一多就崩”。所以每次交付前我都按下面这张清单过一遍半小时能跑完能挡掉绝大部分线上问题。验证项操作预期失败时看哪里关键词检索输入编码片段、名称片段、首拼三种方式都能命中后端 SQL 里 keyword 拼接分页与回填翻到第 3 页再选一条回填值正确过滤条件不丢请求参数 pageIndex、keyword多选边界开启 ismultiselect 后选 200 条能回填全部选中项maxrowcount、前端多选属性数据权限用两个不同组织账号查询结果集按组织隔离orgPk 是否进入后端 SQL缓存切换iscache 从 N 切 Y首次查询后不再打印 SQL缓存 key 是否含组织状态控制新增、编辑、浏览三个态只在指定状态可编辑页面模板字段状态配置清单里最容易被忽略的是最后两行。缓存切换这一项如果测试时没验证上线后出现权限越权责任就大了。状态控制这一项则是提测时最容易被 UI 测试漏掉的因为他们通常只在编辑界面点一下不会三种状态来回切。验证出现问题时先回到第 4 章的三条命令用 SQL 查注册、用日志看请求、用缓存清理接口复位再重新跑一条用例。反复出现同类问题时把证据截图连同 refcode 一起贴到工单里沟通成本会明显降低。最后把这一套验证清单连同三条排查命令直接附到 NCC 参照开发的交付文档里后续维护的人遇到问题不会再来打扰你。本文还有配套的精品资源点击获取