用友NC65客开实战:手把手教你给非产品发货单加个“运单信息”按钮

发布时间:2026/6/14 9:25:11

用友NC65客开实战:手把手教你给非产品发货单加个“运单信息”按钮 用友NC65客开实战非产品发货单运单信息功能深度定制指南在物流与供应链管理领域非产品类发货单的处理往往需要更灵活的运单信息关联功能。标准NC65系统虽然提供了完善的发货单管理模块但面对特殊业务场景时定制化按钮开发成为实施顾问的必备技能。本文将系统性地讲解如何在不修改标准代码的前提下通过客开方式为单据界面添加运单信息功能按钮并确保其完美融入现有业务流程。1. 业务场景分析与技术方案设计某大型家电企业的售后服务体系需要处理大量非产品类发货单如配件、赠品等物流部门要求在每个发货单界面直接查看关联的运单信息。标准NC65系统未提供此功能按钮需要通过客开实现。技术实现路径包含三个关键层面前端界面层在卡片和列表视图添加新按钮业务逻辑层处理按钮点击事件与运单数据关联数据持久层确保客开代码不影响标准数据存储结构重要原则所有客开必须遵循NC65的插件式开发规范避免直接修改标准代码文件2. 开发环境准备与基础配置2.1 开发工具要求Eclipse IDE for Java EE Developers版本≥2020-06NC65开发插件版本需与目标环境一致JDK 1.8配置JAVA_HOME环境变量Maven 3.6用于依赖管理2.2 项目结构初始化在Eclipse中创建模块开发项目建议采用以下目录结构nc65-customization/ ├── src/ │ ├── client/ │ │ └── nc/ui/so/m30/billui/ # 包路径与标准模块保持一致 │ ├── config/ │ └── META-INF/ ├── lib/ # 第三方依赖库 └── target/ # 编译输出目录3. 按钮功能实现全流程3.1 前端XML配置详解在src/client下创建PluginBeanConfigFilePath_shipinfo.xml文件关键配置如下?xml version1.0 encodingGBK? !DOCTYPE beans PUBLIC .//SPRING//DTD BEAN//EN http://www.springframework.org/dtd/spring-beans.dtd beans !-- 卡片视图按钮配置 -- bean classnc.ui.pubapp.plugin.action.InsertActionInfo property nameactionContainer refactionsOfCard / property nameactionType valuenotedit / property nametarget refprintActionGroup / property namepos valuebefore / property nameaction refShipInfoAction / /bean !-- 列表视图按钮配置 -- bean classnc.ui.pubapp.plugin.action.InsertActionInfo property nameactionContainer refactionsOfList / property nameactionType valuenotedit / property nametarget refprintActionGroup / property namepos valuebefore / property nameaction refShipInfoAction / /bean !-- 自定义按钮实现类 -- bean idShipInfoAction classnc.ui.so.m30.billui.action.ShipInfoAction property namemodel refmanageAppModel / property nameeditor refbillFormEditor / property namecode valueShipInfoAction / /bean /beans配置参数说明表参数名取值示例作用说明actionContaineractionsOfCard指定按钮显示在卡片视图actionTypenotedit非编辑状态显示按钮targetprintActionGroup按钮插入位置参照组posbefore按钮显示在参照组之前3.2 动作类开发实践创建ShipInfoAction.java实现核心业务逻辑package nc.ui.so.m30.billui.action; import nc.ui.uif2.NCAction; import nc.ui.uif2.UIState; import nc.ui.uif2.model.AbstractAppModel; import nc.ui.pubapp.uif2app.view.BillForm; import nc.ui.pub.beans.MessageDialog; import java.awt.event.ActionEvent; public class ShipInfoAction extends NCAction { private BillForm editor; private AbstractAppModel model; public ShipInfoAction() { super.setBtnName(运单信息); super.setCode(ShipInfoAction); } Override public void doAction(ActionEvent e) throws Exception { // 获取当前选中单据PK String billPk (String)model.getSelectedData(); // 调用运单查询服务 IShipInfoService service NCLocator.getInstance() .lookup(IShipInfoService.class); ShipInfoVO[] shipInfos service.queryByBillPk(billPk); // 显示运单信息对话框 new ShipInfoDialog(editor, shipInfos).showModal(); } // 标准getter/setter省略... }3.3 服务层接口设计创建运单查询服务接口package nc.itf.so.m30; import nc.vo.so.m30.billui.ShipInfoVO; public interface IShipInfoService { ShipInfoVO[] queryByBillPk(String billPk) throws BusinessException; void bindShipInfo(String billPk, String shipNo) throws BusinessException; }4. 高级功能扩展与性能优化4.1 批量运单信息处理对于列表视图下的批量操作需求可扩展动作类实现Override protected boolean isActionEnable() { // 允许在选中多行时操作 return model.getSelectedDatas() ! null model.getSelectedDatas().length 0; } Override public void doAction(ActionEvent e) throws Exception { Object[] selectedPks model.getSelectedDatas(); IShipInfoService service NCLocator.getInstance() .lookup(IShipInfoService.class); // 并行查询提升性能 ListFutureShipInfoVO[] futures new ArrayList(); for (Object pk : selectedPks) { futures.add(ThreadPool.submit(() - service.queryByBillPk((String)pk))); } // 合并查询结果 ListShipInfoVO allInfos new ArrayList(); for (FutureShipInfoVO[] future : futures) { allInfos.addAll(Arrays.asList(future.get())); } new BatchShipInfoDialog(editor, allInfos.toArray(new ShipInfoVO[0])).showModal(); }4.2 缓存策略实现为避免频繁查询数据库可添加Ehcache支持!-- 在Spring配置中添加 -- bean idshipInfoCache classorg.springframework.cache.ehcache.EhCacheFactoryBean property namecacheName valueshipInfoCache/ property nametimeToLive value3600/ !-- 1小时过期 -- /bean服务层实现类添加缓存注解Cacheable(valueshipInfoCache, key#billPk) public ShipInfoVO[] queryByBillPk(String billPk) { // 实际数据库查询逻辑 }5. 测试验证与部署方案5.1 单元测试要点编写JUnit测试用例验证关键功能public class ShipInfoActionTest { Test public void testSingleShipQuery() { ShipInfoAction action new ShipInfoAction(); action.setModel(createMockModel()); action.setEditor(createMockEditor()); // 模拟按钮点击 action.doAction(new ActionEvent(this, 0, test)); // 验证对话框是否弹出 verify(mockEditor).showModalDialog(any(ShipInfoDialog.class)); } // 其他测试方法省略... }5.2 生产环境部署清单确保部署包包含以下文件/META-INF/module.xml/config/PluginBeanConfigFilePath_shipinfo.xml/nc/ui/so/m30/billui/action/ShipInfoAction.class/nc/itf/so/m30/IShipInfoService.class/lib/ehcache-2.10.6.jar部署步骤停止NC65应用服务将编译好的jar包放入modules目录清理UAP中间件缓存重启应用服务6. 常见问题解决方案问题1按钮显示但点击无反应检查步骤确认XML中bean的class路径完全正确验证动作类是否继承自NCAction检查日志中是否有NoClassDefFoundError问题2按钮在特定状态下不显示调试方法检查actionType值是否符合预期edit/notedit确认model的uiState返回值重写isActionEnable()方法添加日志输出问题3性能瓶颈处理优化建议对批量查询实现分页加载添加查询超时机制建议3000ms考虑使用异步加载模式实际项目中我们曾遇到点击按钮后界面卡顿的情况通过分析发现是运单查询未使用索引导致的。解决方法是在数据库层面为bill_pk字段添加索引后响应时间从5秒降至200毫秒以内。

相关新闻