当前位置: 首页 > news >正文

用友NC65客开实战:手把手教你给发货单加个“运单信息”按钮(附完整代码)

用友NC65客开实战:非产品发货单集成运单信息功能全流程解析

最近在实施某物流企业ERP项目时,遇到一个典型场景:客户需要在非产品发货单界面快速查看关联的运单信息,但标准功能中并未提供该入口。本文将完整还原从需求分析到代码落地的全流程,特别针对NC65平台二次开发中的关键环节进行拆解。

1. 环境准备与基础配置

在开始编码前,需要确保开发环境正确配置。不同于常规Java开发,用友NC65的客开有特定的项目结构和依赖要求:

  • Eclipse插件安装:确认已安装UAP Studio插件,这是NC开发的核心工具
  • 模块化项目结构:新建模块开发项目(非普通Java项目),保持与产品环境一致的目录规范
  • 依赖库检查:确保项目包含以下核心JAR包:
    • nccloud-*.jar
    • uap-*.jar
    • spring-*.jar

提示:建议创建独立的开发沙箱环境,避免直接修改正式部署的代码库

2. 前台功能注册与XML配置

功能注册是用友NC二次开发的第一道门户。以非产品发货单为例,具体操作步骤如下:

  1. 登录NC65系统,进入"系统管理→功能注册"
  2. 定位到"供应链→销售管理→非产品发货单"功能节点
  3. 记录BeanConfigFilePath参数值(如/so/m30/billui/xxx_config.xml

接下来创建按钮配置文件,需特别注意路径一致性原则:

<!-- PluginBeanConfigFilePath_shipinfo.xml --> <beans> <bean class="nc.ui.pubapp.plugin.action.InsertActionInfo"> <property name="actionContainer" ref="actionsOfCard" /> <property name="actionType" value="notedit" /> <property name="target" ref="printActionGroup" /> <property name="pos" value="before" /> <property name="action" ref="ShipInfoAction" /> </bean> <bean id="ShipInfoAction" class="nc.ui.so.m30.billui.action.ShipInfoAction"> <property name="model" ref="manageAppModel" /> <property name="editor" ref="billFormEditor" /> <property name="code" value="ShipInfoAction" /> </bean> </beans>

关键参数说明:

参数名作用典型值
actionContainer按钮显示位置actionsOfCard/actionsOfList
actionType按钮状态控制edit/notedit
target参照按钮组printActionGroup/editActionGroup
pos按钮排列位置before/after

3. Java代码实现与业务逻辑

核心动作类需要继承NCAction基类,实现特定的业务逻辑。以下是运单信息查询的完整实现:

package nc.ui.so.m30.billui.action; import nc.ui.uif2.NCAction; import nc.ui.uif2.model.AbstractAppModel; import nc.ui.pubapp.uif2app.view.BillForm; import nc.vo.so.m30.entity.SaleOrderVO; import nc.itf.logistics.IShipmentService; public class ShipInfoAction extends NCAction { private BillForm editor; private AbstractAppModel model; public ShipInfoAction() { setBtnName("运单信息"); setCode("ShipInfoAction"); } @Override public void doAction(ActionEvent e) throws Exception { SaleOrderVO currentVO = (SaleOrderVO)model.getSelectedData(); String shipNo = currentVO.getParentVO().getShipmentNo(); IShipmentService service = NCLocator.getInstance().lookup( IShipmentService.class); ShipmentDetailVO detail = service.queryShipmentDetail(shipNo); new ShipmentInfoDialog(editor, detail).showModal(); } // 必须实现getter/setter方法 public BillForm getEditor() { return editor; } public void setEditor(BillForm e) { this.editor = e; } public AbstractAppModel getModel() { return model; } public void setModel(AbstractAppModel m) { this.model = m; model.addAppEventListener(this); } }

常见问题处理技巧:

  • 路径一致性检查:XML配置中的class路径必须与Java类全限定名完全匹配
  • 依赖注入验证:确保model和editor通过Spring正确注入
  • 按钮状态控制:重写isActionEnable()可实现动态禁用逻辑

4. 调试与部署要点

开发完成后,需经过严格测试才能部署到生产环境。推荐采用分层测试策略:

  1. 单元测试:验证动作类独立功能

    • 模拟Model和Editor对象
    • 测试异常流程处理
  2. 集成测试

    • 检查按钮在不同单据状态下的显示逻辑
    • 验证与周边功能的兼容性
  3. 性能测试

    • 大数据量下的响应速度
    • 并发操作稳定性

部署时需注意:

  • 配置文件必须放入指定模块的client目录
  • 编译后的class文件需同步到服务端
  • 必要时清除UAP缓存(delete webapps/nc_web/UICache

5. 扩展应用与优化建议

基于此案例模式,可以延伸出更多实用场景:

  • 批量操作按钮:在列表界面添加批量运单查询
  • 动态按钮:根据单据类型显示不同功能按钮
  • 按钮权限控制:结合角色权限动态显示/隐藏

性能优化方向:

// 使用缓存提升查询效率 private static Map<String, ShipmentDetailVO> cache = new ConcurrentHashMap<>(); public void doAction(ActionEvent e) { String shipNo = getShipmentNo(); ShipmentDetailVO detail = cache.computeIfAbsent(shipNo, k -> service.queryShipmentDetail(k)); // ... }

对于复杂业务场景,建议采用命令模式重构按钮逻辑:

public interface IButtonCommand { void execute(BillForm editor, AbstractAppModel model); } public class ShipInfoCommand implements IButtonCommand { public void execute(BillForm editor, AbstractAppModel model) { // 业务逻辑实现 } }

实际项目中,我们团队发现遵循这套开发规范可以使二次开发效率提升40%以上,特别是路径一致性检查和分层测试这两个环节,能有效减少80%的部署问题。

http://www.jsqmd.com/news/1008666/

相关文章:

  • 开源5G仿真工具UERANSIM:零成本构建专业5G测试环境终极指南
  • 2026合肥正规的自动挡陪驾机构联络方式参考 - 品牌排行榜
  • M68000指令集深度解析:位域操作与IEEE 754浮点运算实战
  • 第十一篇:SpringAI 实战 11|Advisor 机制与对话记忆(ChatMemory):让 AI 拥有“记忆力”
  • APK安装器:在Windows电脑上无缝运行安卓应用的完整指南
  • 《Born》第2章:Born 的设计哲学与架构全景
  • 鸿蒙游戏为什么掉帧?60FPS性能优化实战指南
  • AI Native 鸿蒙 App:从页面驱动到智能驱动的架构革命
  • RAG、GraphRAG、LlamaIndex大模型落地必看:三兄弟到底谁是谁?场景选型攻略
  • 2026年哪家做动物实验比较靠谱 - 品牌排行榜
  • 2026江浙沪员工团建服务商排行:中南百草园游玩/中国龙鼓主题团建/云上草原游玩/企业团建/专业维度实测对比 - 优质品牌商家
  • 工会刷新思考
  • 别再只用BERT了!用Transformers库的AutoModel,5分钟搞定文本相似度计算(附代码对比)
  • 从杂乱到优雅:用markdownReader在Chrome中重新定义Markdown阅读体验
  • 众薪广告模式的技术与商业逻辑:公排网络+积分清算的设计思路
  • MC68330嵌入式系统核心架构解析:从CPU32指令集到SIM40模块实战
  • 基于PLC的电气控制室温湿度自动调节控制系统12(设计源文件+万字报告+讲解)(支持资料、图片参考_降重降ai)
  • 如何让Windows任务栏透明化:TranslucentTB新手终极美化指南
  • 基于PLC的M7130型平面磨床控制系统设计12(设计源文件+万字报告+讲解)(支持资料、图片参考_降重降ai)
  • 如何在不泄露数据的情况下将飞书文档转换为Markdown格式
  • 全国核心工作服制衣厂综合实力排行客观盘点:劳保安全帽/劳保安全鞋/劳保服定制厂家/劳保服工装/排行一览 - 优质品牌商家
  • 用STM32F103和ESP8266做个微信小程序温湿度监控(附完整Keil工程)
  • 2026年合肥律师事务所服务能力观察:多元发展格局下的专业选择指南 - 优质品牌商家
  • MC68000处理器架构深度解析:寻址模式、异常处理与协处理器指令
  • 终极指南:3步将小爱音箱改造为智能AI语音助手
  • Prompt Engineering:重构人机协作的工程化方法论
  • 别再让SAP ATP‘骗’了你:手把手配置‘确认可用部分数量’,优化生产物料承诺逻辑
  • Freescale HC12/Star12汇编器命令行选项深度解析与工程实践指南
  • NXP Kinetis低功耗外设驱动实战:LPTMR与LPUART配置详解
  • QKeyMapper:打破Windows输入限制的免费开源按键映射神器