ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用友U8二次开发实战:从U8SDK到WebAPI的完整技术指南

用友U8二次开发实战:从U8SDK到WebAPI的完整技术指南 简介这份完整的用友U8二次开发培训课件由作者花费不少代价从多个渠道收集而来并重新整理成便于学习的资料包面向用友U8实施顾问、ERP开发工程师以及需要进行个性化定制的企业信息化人员。课件内容注重从基础概念到实践应用的完整覆盖按照培训讲稿的思路组织知识点便于读者循序渐进地掌握二次开发的主要方法和关键流程既适合零基础者入门也能帮助有经验的开发者在实际项目中快速查阅参考。整套课件以培训讲解为主穿插示例与操作说明可当作自学教材也可用于企业内部集中培训。资源包约12.67MB采用rar格式压缩因下载页未标注文件总数与类型明细这里无法具体列出但资料整体按模块归整使用起来较为方便。目前已有1827人学习下载整体来看这是一套系统性和实用性兼备的二次开发学习材料值得相关从业者收藏参考。 用友U8的二次开发在制造业、流通业的信息化圈子里是个老生常谈又绕不开的话题。很多企业上了标准版U8之后用着用着就会发现“标准功能不够用了”要么是报表格式不满足领导要求要么是业务流程和现有单据对不上这时候就得有人下手做二次开发。今天我把这几年带团队做U8二开的经验和内部培训课件核心内容整理出来从技术架构、开发方式、完整案例到踩坑记录一次性说透。这篇文章适合谁看如果你是要接手企业U8二开运维的IT人员或者是被分派了报表、接口开发任务的软件工程师又或者是想评估“U8到底能不能满足我们业务需求”的项目经理都可以把这篇文章当一本快速上手手册。我尽量用实际操作来带路理论只讲必要的部分目标是你看完之后能直接打开Visual Studio连上U8数据库动手干活。1. U8二次开发的整体设计与切入思路1.1 二次开发到底解决什么问题很多人一听“用友U8二次开发”以为就是要改用友的源代码这是个误区。U8产品本身的代码是封闭的我们说的二开核心是在标准产品之外扩展功能解决三类典型问题。第一类是报表类问题。U8标准报表、账表往往格式固定比如余额表、收发存汇总表企业希望按自己的格式增加列、增加统计口径或者把数据导出到Excel再加工。第二类是与外部系统的数据交互比如MES、WMS、OA、条码系统希望和U8做单据传递而不是人工重复录入。第三类是业务流程补强比如在单据保存时自动校验、自动带出某些字段或者在标准界面上增加自定义按钮和操作。理解清楚了“我们不是改U8而是围绕U8做增量开发”后续所有的方案设计都会顺很多。你碰到的很多企业项目其实都是这三类的组合拳。1.2 技术路线选型的底层逻辑选技术方案本质上是选“隔得远不远”。隔得越远越稳定、越容易升级但功能实现受限制隔得越近功能越灵活但升级维护风险越大。我通常把U8二开技术路线分为四层。最远的一层是直接读写U8的SQL Server数据库优点是灵活什么都能做缺点是绕过了U8的业务逻辑容易产生脏数据。再近一层是调用U8的WebAPI、EAI接口这是官方支持的集成方式数据安全性有保障适合系统对接。更近一层是使用UAP平台做单据模板和业务流设计不写代码靠配置实现。最近的一层是用U8的插件机制直接嵌入到U8客户端进程里。真实项目里这几层常常混着用。我见过不少团队一上来就想写插件结果连U8的基础数据表结构都没搞明白反而开发周期被拖得很长。更务实的做法是“报表类优先用UAP或SQL报表接口类优先用WebAPI流程类再考虑插件”。2. 环境准备与底层数据认知2.1 开发环境搭建要点U8二开的环境没有想象中复杂但有几个坑必须先避掉。开发机建议安装与生产环境一致的U8客户端版本号最好精确到小版本比如U8 16.5和U8 15.0的数据库表可能会有细微差别。数据库客户端工具推荐SQL Server Management Studio连接U8的数据库实例。需要注意U8的数据分为系统库UFSystem和账套库UFData_xxx_年份很多初学者总是连错库导致查不到业务数据。如果用Visual Studio做.NET开发建议安装U8安装盘中自带的“U8SDK”它提供了很多二次开发需要的程序集和接口文档。我在培训课件里反复强调在动手写代码之前先把“U8SDK开发指南”里关于基础档案、库存、销售、采购的接口看一遍可以省掉大量重复造轮子的时间。另外开发机上一定要装好IIS或Web部署环境因为我们写的很多接口服务最终是要挂到服务器上给其他系统调用的。2.2 必须掌握的核心表与视图U8数据库里的表有上千张没有人能全部记住但有一些核心的基础表和业务表做二开的人必须形成肌肉记忆。基础档案类Inventory存货档案、Department部门档案、Person人员档案、Customer客户档案、Vendor供应商档案、Warehouse仓库档案。业务单据类RdRecord收发记录主表、RdRecords收发记录子表、SO_SOMain销售订单主表、SO_SODetails销售订单子表、PO_POMain采购订单主表、PO_PODetails采购订单子表。库存相关CurrentStock现存量表、St_TotalAccount库存总账、InVouch存货单据。这里必须强调一个容易踩雷的点U8有一些“中间表”或者“临时表”数据实时性很强比如现存量表CurrentStock它可能因为未记账、未审核的异常状态而产生误差。直接基于物理表开发报表的时候就要注意数据准确性不能盲目把CurrentStock的数据当成业务事实。我在实际项目中碰到过很多次开发人员直接用select sum(quantity) from RdRecord结果把红字入库和蓝字出库加错了方向。所以二开人员一定要先读懂U8中“现存量、可用量、预计入库量、预计出库量”之间的关系再去动SQL。2.3 学习路径建议如果团队里有新人我会建议按这样的顺序学习先用两个月时间把U8的前台操作摸熟比如做一遍采购到货、入库、销售出库、库存盘点然后学习数据字典自己写SQL查单据流水第三阶段学习UAP报表设计能画出符合业务要求的基本报表最后才进入WebAPI和插件开发。这个顺序看起来慢实际是最快的。因为U8二开最大的成本不在代码而在理解业务和数据结构。很多开发人员技术很强但是不懂财务和供应链逻辑写出来的功能业务部门根本不能用。3. 核心开发方式与关键细节3.1 UAP报表与自定义报表开发UAP是用友的报表设计平台在U8的“企业应用平台”里能找到。做UAP报表的好处是无需写太多代码报表能直接嵌到U8菜单里并且继承U8的权限控制。设计UAP报表的关键是数据集的SQL写法。我举个例子如果要做一个“部门收发存汇总表”典型的SQL是这样的SELECT d.cDepName AS 部门, inv.cInvCode AS 存货编码, inv.cInvName AS 存货名称, ISNULL(SUM(CASE WHEN rdr.bRDFlag 0 AND rdr.iType IN (1, 2) THEN rdr.iQuantity ELSE 0 END), 0) AS 入库数量, ISNULL(SUM(CASE WHEN rdr.bRDFlag 1 AND rdr.iType IN (11, 12) THEN rdr.iQuantity ELSE 0 END), 0) AS 出库数量 FROM RdRecord rdr INNER JOIN RdRecords rds ON rdr.ID rds.ID INNER JOIN Inventory inv ON rds.cInvCode inv.cInvCode INNER JOIN Department d ON rds.cDepCode d.cDepCode GROUP BY d.cDepName, inv.cInvCode, inv.cInvName写这种SQL时最关键的是理解bRDFlag和iType字段的含义。bRDFlag是收发标志0代表入库、1代表出库iType是收发类型不同取值对应采购入库、产成品入库、销售出库、材料出库等。搞反了这两个字段的组合报表数据对不上账到时候查起来极其痛苦。在设计UAP报表时还要注意“数据权限”的问题UAP报表默认支持数据权限控制但需要在数据集SQL中引入权限表否则所有用户都能看到全公司的数据这在财务场景是绝对不允许的。3.2 插件开发与单据界面扩展当你需要在U8的单据界面上加按钮、加校验逻辑或者在保存时自动做某些操作插件开发就是首选。U8的插件框架基于.NET的接口机制官方文档里有详细的开发说明。开发一个简单的销售订单保存插件大致分这几步在Visual Studio中创建类库项目引用U8相关程序集实现接口编译后把DLL放到U8客户端目录下在U8中注册插件。核心代码结构像是这样public class SalesOrderPlugin : IPlugin { public void Exec(string ruleID, object obj) { // 获取单据对象 BillBase bill obj as BillBase; if (bill null) return; var head bill.GetHead(); // 校验订单金额 decimal totalAmount Convert.ToDecimal(head.GetValue(iMoney)); if (totalAmount 0) { throw new Exception(订单金额不能为负数); } } }这只是展示框架逻辑实际开发中要读哪些字段、在哪个时机触发都需要对照U8SDK的开发者文档。一个值得注意的坑是插件异常会直接影响U8主程序所以插件代码里的异常处理一定要做充分无论如何不能把原始异常直接抛到界面上否则用户会以为U8崩溃了。我这边带项目时立了一条规矩所有插件代码必须做日志记录哪怕只是写一行文本记录一下执行时间和关键参数。因为插件一旦出问题没有日志就只能靠猜排查效率特别低。3.3 外部系统集成与WebAPI接口U8与其他系统对接现在是越来越常见的需求。U8提供了WebAPI接口用于处理单据的新增、查询、审核等操作支持标准RESTful风格的调用。对接开发前务必先明确“主数据同步还是单据集成”。主数据同步就是把客户、存货档案从U8导出到MES或WMS单据集成则是把外部系统生成的生产订单、销售订单推送到U8。两种场景的方案设计完全不同。主数据同步相对简单核心是找到正确的接口或直接查数据字典中的基础档案视图。单据集成就要复杂一些因为U8接口对单据的必填项、编码规则、审核流程有严格要求一次错误的调用可能导致单据在U8中处于“半成品”状态。我给团队的建议是在测试账套里先把所有场景的接口调用串联一遍确认无误后再切到生产环境。如果是通过数据库层直接对接有一条原则必须守死只做新增和查询不要轻易做修改和删除。U8的业务数据表之间存在复杂的关联关系直接写SQL去改单据主表、子表很容易造成单据不一致后续用友服务工程师都不一定敢帮你恢复。4. 一个完整实操案例自定义库存台账报表4.1 需求梳理与方案选型有一次客户的生产部提出领导层要每天查看各车间的原材料库存台账要求包含存货编码、名称、规格型号、单位、期初数量、当天入库、当天出库、结存数量还要能按车间和库房筛选。U8标准的现存量查询做不到“期初、当天发生、结存”这种动态口径而且界面也不太友好于是决定做二次开发。我评估后没有选UAP报表而是选了一个独立报表程序。原因是这个报表要作为中间页嵌入到客户已有的Web门户里领导直接从浏览器打开不需要登录U8客户端。方案定了用ASP.NET Core WebApi SQL Server数据直接查U8数据库前端用简单的HTML表格展示。4.2 核心SQL实现这个报表最核心的部分是SQL或存储过程。设计思路是传入日期、仓库、部门等参数然后分别算期初、当期入库、当期出库、结存。核心SQL片段大致如下DECLARE QueryDate DATETIME 2025-02-20; DECLARE WarehouseCode NVARCHAR(20) NULL; -- 期初数量查询日期之前的累计入库 - 累计出库 SELECT inv.cInvCode, inv.cInvName, inv.cInvStd, ISNULL(SUM(CASE WHEN rdr.bRDFlag 0 AND rdr.dDate QueryDate THEN rds.iQuantity ELSE 0 END), 0) - ISNULL(SUM(CASE WHEN rdr.bRDFlag 1 AND rdr.dDate QueryDate THEN rds.iQuantity ELSE 0 END), 0) AS BeginQty INTO #TempBegin FROM RdRecord rdr INNER JOIN RdRecords rds ON rdr.ID rds.ID INNER JOIN Inventory inv ON rds.cInvCode inv.cInvCode WHERE (WarehouseCode IS NULL OR rds.cWhCode WarehouseCode) GROUP BY inv.cInvCode, inv.cInvName, inv.cInvStd;这里引入临时表是因为一次性JOIN所有数据会导致大表扫描特别慢在几百万条记录的RdRecords上尤其明显。我习惯的做法是分三个临时表分别算期初、入库、出库最后再FULL JOIN到一起。这样每个SQL块都简单清晰也好排查问题。需要注意的是iQuantity在U8中默认就是正数方向由bRDFlag控制所以不要在SQL里再乘以负一之类的操作否则看到负数会一头雾水。4.3 参数处理与前端展示后端接口接收queryDate、whCode、deptCode参数参数校验是第一个要处理的问题。queryDate必须精确到天比如2025-02-20这里有个小细节如果直接传字符串2025-02-20SQL Server会转成当天0点那么当天发生的单据也会被算进期初导致当天发生数少算。我在这里踩过坑解决办法是在C#端把日期格式化成yyyy-MM-dd并且在SQL里处理时间范围时用和而不是只查等于日期。string sql SELECT ... FROM RdRecord rdr WHERE rdr.dDate BeginDate AND rdr.dDate DATEADD(DAY, 1, EndDate) ;这个写法能确保把查询日期当天所有单据都包含进去不会漏掉当天出库或入库。前端展示我用了简单的Bootstrap表格再加上一个日期选择器和一个仓库下拉框。开发成本不高但效果很直观领导打开页面直接选日期就能看数据。实际上线后客户反馈很好还提了新需求加一个导出Excel的按钮。这个实现也简单后端把DataTable转成CSV或Excel二进制流返回给前端下载即可。4.4 这个案例的经验总结这个报表从需求确认到上线前后大概花了三天时间。里面没有用任何用友的高级接口就是“SQLServer WebApi HTML”但由于理解了U8的数据结构和业务语义做出来的东西非常稳。也正因为这个项目相对简单我拿它当培训课的第一个案例。新人跟着做一遍能迅速建立对U8核心表结构的感觉后面做更复杂的采购、销售、生产类二开时就不会无处下手。5. 常见问题与排查技巧实录5.1 用友U8余额表打不开“U8余额表打不开”是个出现概率极高的运维问题很多企业的IT人员接到过这种报障。用户点了总账余额表或库存余额表界面一直转圈要么报错要么直接没反应。根据我排查的经验这个问题有几种常见原因。第一数据库中存在不一致的数据比如某个账套的期间表或科目余额表和凭证表数据对不上第二UFSystem库中的任务表或异常任务记录过多导致读取卡死第三U8客户端缓存损坏。处理办法一般是到数据库执行下面的脚本清理异常任务USE UFSystem; DELETE FROM UA_Task; DELETE FROM UA_TaskLog;这两张表存的是U8的并发任务和日志系统异常退出后容易残留脏数据导致后续任务卡住。清理前最好确认当前没有正在跑的关键业务否则会影响在线用户。如果清任务表不行就要检查账套库的余额表相关表比如总账模块的GL_AccountSum表、库存模块的St_TotalAccount表看是否有大量NULL值或者负数异常。最稳妥的方案是用用友自带的“数据库修复工具”或者让顾问帮忙检查不建议随便动数据。这个问题我在内部培训时专门讲过核心结论就一句话余额表打不开八成是异常任务残留或数据一致性出问题先清任务再查数据不要一上来就重装客户端。5.2 数据库连接串配置错误U8的WebAPI和自研程序连接U8数据库时连接串的配置有个小坑。U8数据库账套库名通常是UFData_216_2025这种格式中间的数字是账套号后面是年度。如果你直接写死连接串到了2026年就会连不上新账套因为年度账套库变了。我通常的做法是在配置文件中读取账套号和年度动态拼数据库名或者通过UFSystem库中的UA_Account表查询账套信息。这样可以避免每年年初都要改一次连接串的问题。这种“配置灵活化”的思想在做U8二开时特别重要因为U8的版本演进很快数据库结构可能随补丁变化把配置全部外置后续升级时能减少很多麻烦。5.3 权限与数据安全问题做U8二开权限和数据安全一定是高优先级事项。自研程序连接数据库时不要使用sa账号而应新建一个只读账号或最小权限账号。如果程序只需要查询业务数据就只赋予db_datareader权限不要给写入权限这样即使程序被外部攻击影响范围也有限。另外如果自研报表要嵌入到已有系统不要把U8的账套密码写在配置文件的明文里至少要用加密的方式保存。我见过不少企业U8库的密码直接写在了一个共享文档里这样内部人员能访问但如果被离职人员拿到风险非常大。数据权限方面如果企业有多个公司或事业部而每个部门只能看自己的数据二开程序的SQL里一定要带部门或仓库的过滤条件并且这个条件要从登录用户信息中获取不能由前端随意传参否则一个普通用户就能通过改参数看到全公司数据。6. 一些值得养成的开发习惯最后再分享几个我踩过坑之后沉淀下来的习惯。第一所有涉及U8数据库的查询第一版先做小数据量验证用TOP 100跑通结构再放开全量查询否则一个笛卡尔积就能让U8服务器CPU瞬间飙满。第二操作U8数据前务必先备份相关表或者至少备份数据库尤其是做触发器、存储过程这类会影响业务逻辑的开发。第三建议把U8每个版本的“数据字典”下载下来存成PDF或网页随时查阅这比每次遇到字段含义不明就发帖问人高效得多。如果你正在给企业做U8二开或者正准备接手这类项目可以从今天这篇文章里的报表案例入手在自己电脑上装一个U8测试环境把表结构和SQL跑一遍。动手永远比看文档有效等你能熟练地写出收发存报表的SQL时你基本已经进入了U8二开的正常轨道。后面再接触插件、WebAPI难度会小非常多。本文还有配套的精品资源点击获取
返回列表