SpringBoot3 + 达梦 DM8:RuoYi Office 用印申请与多级审批实战 SpringBoot3 达梦 DM8RuoYi Office 用印申请与多级审批实战国产数据库上的 OA 验收应让一张业务单真正经过提交、任务分配、多级审批和结果回写。RuoYi Office 在达梦 DM8 上完成了用印审批闭环本文把这条产品路径和 JDBC、Flowable、业务状态设计连起来说明怎样判断“适配到了业务层”。▲ 用印单、审批角色和完成印记表达的是审批闭环。审批通过后还存在实际用章执行不能把流程完结等同于印章已经使用。引言能登录达梦为什么还要验证一张用印单登录成功只覆盖认证相关查询与写入。它不一定触发业务主键生成、流程定义查找、任务持久化和业务状态回调。一张用印单把这些能力放进了同一条链路。申请人选择印章、填写用章时间和文件信息提交后产生流程实例部门领导和保管员处理任务最终业务单同步审批结果。链路中的每一步都能从产品页面观察也都可能暴露数据库适配问题。用户动作数据库侧发生的事情常见失配选择印章查询印章和组织资料schema、大小写或中文数据异常保存申请生成主键、写业务表IDENTITY 策略与初始化结构不一致提交审批查流程定义、创建实例与任务发布资源缺失、方言识别错误审批通过更新任务、写历史与意见引擎 SQL 或关联数据异常回到单据按业务键更新审批状态回调失败、关联字段缺失因此本篇以业务单为主线不把“国产库支持”停留在驱动坐标和 JDBC URL。一、用印申请连接了哪些实际角色RuoYi Office 的用印管理包含印章资料、申请单、审批和执行状态。申请人、部门领导与印章保管人员需要不同的信息和动作。申请人关心文件、事由、时间和用章方式审批人关心业务合理性保管员除了审批责任还承担实际用章、外借或归还的执行责任。1. 申请详情保留业务语境▲ 本地开发环境真实单据用于展示字段和操作上下文不是达梦实验单号的截图。达梦闭环证据在本文第三节列明。若只把流程做成“标题 审批意见”保管员很难判断需要哪枚印章、什么时间使用、是否外借以及文件份数与合同金额是否合理。业务表单把这些信息结构化保存审批流程引用其业务身份而不是替代业务数据。2. 表单与审批详情各有责任▲ 既有开发环境用印记录的表单字段展示业务信息布局。图中是已有记录不是本次新填报或达梦测试单。填写页面解决数据输入和业务校验流程详情解决任务上下文与审批轨迹。两者共用同一张申请单的业务身份避免审批完成后还要人工另建业务记录。产品能力使用角色实际价值印章与保管资料申请人、保管员确认用章对象与责任现场 / 外借方式申请人表达不同执行场景文件信息与事由审批人保留审批依据流程审批轨迹各审批角色查看处理过程审批与用章状态保管员、管理人员区分授权与实际执行二、提交后一张单如何成为可审批任务1. 保存业务单再关联流程实例当前提交服务会在单号为空时生成单号对外借模式执行时间冲突校验然后保存或更新申请单设置流程状态为运行中。接下来将业务变量传入流程接口使用申请单 ID 作为businessKey并把返回的流程实例编号写回业务单。其中useMode会按配置导出为流程变量sealUseMode。业务字段名称与流程表达式的变量名称不是必然相同二者必须遵守模型约定。下面摘取当前提交逻辑中“业务身份 → 流程身份”的核心部分省略附件与其他外围处理。// 保存或更新SealApplyBillDOsealApplyBillBeanUtils.toBean(saveReqVO,SealApplyBillDO.class).setProcessStatus(BpmTaskStatusEnum.RUNNING.getStatus());sealApplyBillMapper.insertOrUpdate(sealApplyBill);// 智能提交 BPM 流程如果流程实例不存在则创建存在则审批发起人任务// 标准字段 配置导出字段默认 useMode→sealUseMode与流程模型「流程变量字段」约定一致MapString,ObjectprocessInstanceVariablesBpmProcessVariableUtils.buildBillVariables(saveReqVO,BpmProcessVariableUtils.ofFields(useMode,PV_SEAL_USE_MODE),null);StringprocessInstanceIdprocessInstanceApi.submitProcessInstance(Long.valueOf(saveReqVO.getCreator()),newBpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(OaBillTypeEnum.OA_SEAL_APPLY_BILL.getProcessDefinitionKey()).setVariables(processInstanceVariables).setStartUserSelectAssignees(saveReqVO.getStartUserSelectAssignees()).setBusinessKey(String.valueOf(sealApplyBill.getId()))).getCheckedData();// 将工作流的编号更新到单据中sealApplyBillMapper.updateById(newSealApplyBillDO().setId(sealApplyBill.getId()).setProcessInstanceId(processInstanceId));businessKey让流程结果能够找回业务单processInstanceId让业务详情能够打开流程。两边都保存关联便于查询、回调和排查。但调用顺序本身不能证明所有步骤已处于同一个事务。现场应补充“流程启动失败后是否留下运行中业务单”的异常验收结合实际事务配置判断恢复方式。不能因为正常路径跑通就宣称网络失败、回调失败与重复提交全部得到验证。2. 流程设计与部署资源要一起存在模型编辑器中的记录不等于存在可启动的流程定义。Flowable 的模型、部署、流程定义与二进制资源承担不同责任。部署数据丢失时菜单和模型列表仍可能有内容但发起流程找不到激活定义。这就是为什么迁移不能只核对ACT_RE_MODEL。▲ 既有开发环境费用申请的真实流程图说明已完成与当前节点的观察方法不是达梦历史用印测试单据。核对时应确认指定流程 key 存在激活定义定义对应部署资源完整再检查实际创建的任务。3. 达梦需要识别到匹配的引擎方言MyBatis 能连接数据库不代表 Flowable 会自动选对自身 SQL 字典。引擎会读取 JDBC 数据库产品名决定使用哪一套 SQL。当前配置将DM DBMS/DM映射为 Flowable 的oracle类型。这里选择的是该引擎的 SQL方言路径不是在宣称 DM8 与 Oracle 的全部功能等价。returnconfiguration-{// openGauss is PostgreSQL-compatible, but Flowable cannot infer that from its JDBC product name.try(varconnectionconfiguration.getDataSource().getConnection()){StringproductNameconnection.getMetaData().getDatabaseProductName();if(openGauss.equalsIgnoreCase(productName)||GaussDB.equalsIgnoreCase(productName)){configuration.setDatabaseType(postgres);}elseif(DM DBMS.equalsIgnoreCase(productName)||DM.equalsIgnoreCase(productName)){// DM8 is Oracle-compatible for Flowables SQL dictionary and paging.configuration.setDatabaseType(oracle);}}catch(SQLExceptionex){thrownewIllegalStateException(Failed to determine the Flowable database type,ex);}// 注册监听器例如说 BpmActivityEventListenerconfiguration.setEventListeners(ListUtil.toList(listeners.iterator()));// 设置 ActivityBehaviorFactory 实现类用于流程任务的审核人的自定义configuration.setActivityBehaviorFactory(bpmActivityBehaviorFactory);// 设置自定义的函数configuration.setCustomFlowableFunctionDelegates(ListUtil.toList(customFlowableFunctionDelegates.stream().iterator()));};这个映射要与当前 Flowable 版本和实际数据库结果一起理解。换引擎版本、数据库版本或初始化结构后仍要重新验证流程创建与审批。同一段配置也处理 openGauss但这不能让两库共享完全相同的验收结论。三、审批闭环怎样形成可信证据1. 任务通过不等于业务单已经同步审批人在页面点击通过后流程任务会结束或转到后续节点。最终流程结束时业务回调根据businessKey更新申请单。如果只看审批按钮提示成功可能遗漏历史写入或业务回调问题。应继续核对业务单的审批状态与流程实例的历史状态。▲ 既有开发环境费用申请的真实审批轨迹展示角色、动作与时间不是用印测试单国产库结论使用实验室记录核对。2. 实验记录使用双状态核对2026 年 9 月 3 日达梦环境完成了用印提交和部门领导、两级保管员审批。记录中的单号是OA103-2026090300004。验证项历史实验结果对应判断数据导入782 张表、72 个用户记录目标基线具备基础数据流程仓库deployment / procdef 各 168发布资源并非只剩模型激活定义用印 key 有激活版本存在可启动定义业务提交返回申请单 ID 和单号业务写入与流程创建通过多级审批部门领导及两级保管员通过任务流转通过最终结果PROCESS_STATUS2、STATE_completed业务审批状态与历史流程一致这是指定流程的工程证据。它没有自动覆盖全部审批模型、业务模块、附件上传或数据库高可用。3. 审批完成实际用章才进入待处理当前回调在审批通过时把useStatus设置为PENDING。这表明流程完成的是授权后续仍需执行实际用章。OverridepublicvoidupdateProcessStatus(StringbusinessKey,Integerstatus){LongidLong.parseLong(businessKey);log.info([updateProcessStatus] 更新用印申请单流程状态id: {}, status: {},id,status);// 校验用印申请单存在validateSealApplyBillExists(id);// 更新流程状态SealApplyBillDOupdateObjnewSealApplyBillDO();updateObj.setId(id);updateObj.setProcessStatus(status);// 如果审批通过设置用印状态为待处理if(APPROVE.getStatus().equals(status)){updateObj.setUseStatus(SealUseStatusEnum.PENDING.getStatus());}sealApplyBillMapper.updateById(updateObj);log.info([updateProcessStatus] 用印申请单流程状态更新成功id: {}, status: {},id,status);}业务状态不能被一个流程状态替代。现场用章可能等待保管员执行外借用章还可能经历借出、归还和逾期。状态维度回答的问题典型情况processStatus这张申请是否获准运行中、通过、拒绝useStatus获准后实际执行到哪一步待处理、已完成、外借中、已归还任务状态某个审批节点是否已处理当前任务结束后续任务仍存在因此本篇“单据完结”指历史验收中的审批链路完结。不能据此推断实际用章、外借归还已经全部完成。这一区分能帮助客户避免报表误读审批通过数、实际用章数与当前外借数是三个不同的业务统计口径。四、从业务关系看达梦适配重点1. 一张业务单连接印章与流程历史▲ 业务单通过印章 ID 和流程实例 ID 建立逻辑关联流程通过 businessKey 反向定位业务单。图中关系不代表数据库已经声明物理外键。核心字段作用国产库核对点id申请单业务身份主键策略与类型seal_id关联印章资料查询结果与基础资料完整性bill_code用户可识别单号中文与字符串保存process_instance_id打开流程详情与实例身份匹配process_status审批结果回调是否落业务表use_status实际用章进度不与审批状态混用expected_use_time预计用章时间JSON 与数据库时间一致性Java 实体仍保留KeySequence而达梦 Profile 明确采用AUTO。不能看到实体上有序列注解就直接推断当前达梦运行时一定走序列生成。判断主键路径应同时看数据库结构、当前 Profile 和框架选用策略。2. 审批时序串起产品与持久化▲ 从业务提交到引擎任务再回到业务状态流程历史完成与业务回写需要分别观察。设计决策当前做法保持的业务语义业务身份单据 ID 作为 businessKey审批结果能定位原申请流程变量标准变量与配置导出字段模型分支引用正确业务值引擎方言达梦产品名映射 oracle使用可运行的引擎 SQL 路径回写状态审批状态与用章状态分开授权完成不冒充执行完成初始化结构Flowable 不自动建表数据结构变更显式交付五、为什么达梦导入要关注长文本与流程二进制审批模型不仅是几条普通记录。流程资源可能包含 XML、JSON 和二进制内容转换后的 SQL 长度与字面量表达也会变化。历史实验采用 DM JDBC 作为权威导入路径对大 BLOB 使用PreparedStatement.setBytes。这样不把命令行物理行长度作为流程资源能否完整保留的隐含条件。导入器仍需正确处理字符串中的分号、函数定义结束符和执行异常。不是用了 JDBC就可以跳过对象和内容核对。有些恢复或导入过程采用分批提交。若后续批次失败前面的数据可能已提交因此“失败即停”与“全量自动回滚”并不是一回事。交付应记录失败位置与目标库状态决定重建或继续修复不能盲目重复执行所有脚本。六、把验收扩展到异常路径完整业务验收不仅有“全部通过”一条正常路径。客户上线前应按实际启用功能选择以下场景而不是把本篇历史闭环视为这些场景的通过证明。场景应观察的结果原因审批拒绝单据与流程结果一致检查非通过回调外借时间冲突按业务规则拦截验证实际用章约束重复提交不产生非预期实例检查业务身份与提交入口流程启动失败可识别残留单据状态检查失败恢复附件打开内容可访问且权限正确文件链路不随数据库自动迁移原有 MySQL 环境代表用例仍正常适配不应改变默认业务语义日期字段也需要独立观察。当前LocalDateTime默认以毫秒时间戳交互前端时间组件要使用对应格式数据库返回正常并不能替代前后端契约校验。按一张测试单复核正常结果之外的四个业务问题代表单据的价值在于让业务身份、流程身份和页面结果能够同时核对。现场使用自己的获准测试样本不直接修改历史实验单据。申请数据有没有被原样保留记录测试单的印章、用章方式、时间、文件份数和事由。提交后重新打开详情确认与输入一致而不是只看提交按钮返回成功。再查看流程变量中的用章方式确认模型所用变量名与服务导出约定一致。如果分支走错先查变量和值不要立即修改通用引擎行为。这是业务输入到流程条件的契约检查能把“SQL 正常”推进到“业务判断正确”。谁实际处理了审批任务部门领导与保管员只是角色名称具体人员来自模型与候选人策略。测试应记录任务实际分配给谁再按对应身份处理。所有节点都由管理员代办可能掩盖人员、权限和数据范围问题。如果客户采用会签或多人审批任务数量与完成条件也需要单独验收。本篇的历史多级审批不能替代所有候选人策略的验证。流程结果是否正确落回业务单最终任务结束后分别观察历史实例与业务单。若实例 completed、业务单仍显示审批中应优先检查回调定位和状态更新。若业务单显示通过、实例仍有活动任务应先核对是否存在人工改状态或错误关联。两边都异常时再检查事务、接口错误和运行时 SQL。观察结果优先检查避免误判实例完成单据未回写businessKey 与回调不直接归入前端显示问题单据通过实例仍运行实例身份与状态来源不把标签当流程证明提交失败单据仍运行中保存与启动失败处理不反复点击提交新增主键冲突IDENTITY / 序列不手改历史 ID 绕过角色看不到任务候选人和权限不统一用管理员验收实际用章有没有被错误提前完成当前设计在审批通过后进入用章待处理保管人员随后执行实际动作。验收可以核对这次状态变化证明审批授权没有冒充业务执行。对于外借场景借出、归还与逾期各自需要事实依据。如果系统把审批结束时间直接当作归还时间报表会失去实际库存和责任信息。实际执行的时间、人员和状态应来自执行动作而非对审批结果的推断。拒绝与再次提交怎样观察拒绝后业务单应按实际流程规则进入对应状态并保留审批意见。再次提交可能创建新实例也可能处理发起人任务当前接口有智能提交语义现场要按使用路径检查。不要只按单号相同来判断是不是同一个实例。记录每次提交后的实例 ID、任务与业务状态可以区分合理重提和重复实例。这也是为什么业务编号、业务主键与流程实例号需要各自保留。附件失败是否需要回滚审批附件上传、业务关联和流程审批是不同动作。客户应明确附件是否为提交必需项以及访问失败如何处理。若业务单仍在但文件资源丢失应核对文件目录或对象存储而不是先重跑业务表初始化。当前达梦闭环没有把文件上传作为通过项现场应把这条边界转成明确的补充测试。一份可复核记录至少包含什么记录项建议内容环境数据库、驱动、应用与数据基线业务身份单号、主键、用章方式流程身份定义 key、实例、版本处理身份节点与实际审批人结果历史状态、业务状态、用章状态异常失败位置、恢复动作与复测结果把记录与已有单据关联后下一位实施人员可以从产品页面复核而不必只相信“当时已经通过”。外借冲突还需要一项并发判断当前提交会查询相同印章的外借时间冲突阻止不符合规则的申请。但一次应用层查询不自动等于数据库层已经提供排他保护。两个请求接近同时提交时需要结合事务隔离与实际并发控制判断结果。不能因为单人测试正确就宣称高并发下绝不会出现重复占用。现场可在获准测试范围中使用同一印章、重叠时间与两个申请身份观察实际结果。若存在冲突应先定性问题落在业务约束、事务还是执行环节再选择最小修复面。查询拦截、审批授权与实际借出也不必然属于同一个时间点。客户应明确“占用”从哪一步开始到哪一步释放避免审批通过后才发现两个授权互相冲突。这项并发用例属于后续业务验收本文不把历史达梦审批记录扩大为并发验证。七、快速体验使用admin / admin123登录依次查看“OA → 用印管理”的已有申请详情、流程中心的已有审批轨迹和流程图。在线演示用于体验产品界面不作为达梦实例。部署达梦时应使用匹配初始化资产、专用 Profile与 JDBC 参数再按本篇业务路径验证。建议先阅读已有单据再用获准的测试账号执行代表流程。避免把“体验产品”和“修改正式业务数据”混为同一步。常见问题FAQ达梦上可以完成 RuoYi Office 用印多级审批吗指定实验基线已经完成。2026 年 9 月记录包含提交、部门领导与两级保管员审批最终业务审批状态为 2、流程 completed。为什么模型列表有数据流程仍不能发起模型记录与已部署流程定义承担不同责任。需要核对部署、定义、资源字节及激活状态不能只看模型表有数据。审批通过表示已经完成实际用章吗不表示。当前业务回调把审批通过后的用章状态设置为待处理实际用章、外借与归还需要后续执行动作。换成达梦是否只需修改 JDBC URL还需匹配驱动、schema、主键策略、初始化结构、Flowable 方言和运行时 SQL并完成代表业务回归。结语把“支持达梦”落实到业务单据达梦适配的说服力来自同一张业务单的连续证据它能提交任务能流转历史能查询业务状态能回写。RuoYi Office 保留业务领域与流程引擎的分工让数据库替换后的办公流程仍然可理解、可观察。这比列出一串兼容名称更接近实施人员和客户真正需要的答案。你们的用印验收会分别统计“审批通过”和“实际用章完成”吗这个细节往往决定了流程系统能否真正接入业务台账。系列阅读openEuler 毕昇 JDK TengineRuoYi Office 国产化部署实战SpringBoot3 openGaussRuoYi Office 登录、流程发布与用印填报适配实战达梦 DM8 openGaussRuoYi Office 的 MySQL 数据转换与导入实践达梦 DM8、openGauss、人大金仓怎么选RuoYi Office 国产数据库适配与验收指南openEuler 达梦 DM8 openGaussRuoYi Office 多库部署与运行维护实践如果这篇对你有用点个「在看」或收藏。