☰
SpringBoot3 + 达梦 DM8:RuoYi Office 用印申请与多级审批实战
2026/10/18 14:50:12 网站建设 项目流程

SpringBoot3 + 达梦 DM8:RuoYi Office 用印申请与多级审批实战

国产数据库上的 OA 验收,应让一张业务单真正经过提交、任务分配、多级审批和结果回写。RuoYi Office 在达梦 DM8 上完成了用印审批闭环;本文把这条产品路径和 JDBC、Flowable、业务状态设计连起来,说明怎样判断“适配到了业务层”。

▲ 用印单、审批角色和完成印记表达的是审批闭环。审批通过后还存在实际用章执行,不能把流程完结等同于印章已经使用。

引言:能登录达梦,为什么还要验证一张用印单?

登录成功,只覆盖认证相关查询与写入。它不一定触发业务主键生成、流程定义查找、任务持久化和
业务状态回调。

一张用印单把这些能力放进了同一条链路。申请人选择印章、填写用章时间和文件信息,提交后产生
流程实例;部门领导和保管员处理任务,最终业务单同步审批结果。

链路中的每一步都能从产品页面观察,也都可能暴露数据库适配问题。

用户动作数据库侧发生的事情常见失配
选择印章查询印章和组织资料schema、大小写或中文数据异常
保存申请生成主键、写业务表IDENTITY 策略与初始化结构不一致
提交审批查流程定义、创建实例与任务发布资源缺失、方言识别错误
审批通过更新任务、写历史与意见引擎 SQL 或关联数据异常
回到单据按业务键更新审批状态回调失败、关联字段缺失

因此本篇以业务单为主线,不把“国产库支持”停留在驱动坐标和 JDBC URL。

一、用印申请连接了哪些实际角色

RuoYi Office 的用印管理包含印章资料、申请单、审批和执行状态。申请人、部门领导与印章保管
人员需要不同的信息和动作。

申请人关心文件、事由、时间和用章方式;审批人关心业务合理性;保管员除了审批责任,还承担实
际用章、外借或归还的执行责任。

1. 申请详情保留业务语境

▲ 本地开发环境真实单据,用于展示字段和操作上下文;不是达梦实验单号的截图。达梦闭环证据在本文第三节列明。

若只把流程做成“标题 + 审批意见”,保管员很难判断需要哪枚印章、什么时间使用、是否外借,以
及文件份数与合同金额是否合理。

业务表单把这些信息结构化保存,审批流程引用其业务身份,而不是替代业务数据。

2. 表单与审批详情各有责任

▲ 既有开发环境用印记录的表单字段,展示业务信息布局。图中是已有记录,不是本次新填报或达梦测试单。

填写页面解决数据输入和业务校验,流程详情解决任务上下文与审批轨迹。两者共用同一张申请单的
业务身份,避免审批完成后还要人工另建业务记录。

产品能力使用角色实际价值
印章与保管资料申请人、保管员确认用章对象与责任
现场 / 外借方式申请人表达不同执行场景
文件信息与事由审批人保留审批依据
流程审批轨迹各审批角色查看处理过程
审批与用章状态保管员、管理人员区分授权与实际执行

二、提交后,一张单如何成为可审批任务

1. 保存业务单,再关联流程实例

当前提交服务会在单号为空时生成单号,对外借模式执行时间冲突校验,然后保存或更新申请单,设
置流程状态为运行中。

接下来将业务变量传入流程接口,使用申请单 ID 作为businessKey,并把返回的流程实例编号写
回业务单。

其中useMode会按配置导出为流程变量sealUseMode。业务字段名称与流程表达式的变量名称
不是必然相同,二者必须遵守模型约定。

下面摘取当前提交逻辑中“业务身份 → 流程身份”的核心部分,省略附件与其他外围处理。

// 保存或更新SealApplyBillDOsealApplyBill=BeanUtils.toBean(saveReqVO,SealApplyBillDO.class).setProcessStatus(BpmTaskStatusEnum.RUNNING.getStatus());sealApplyBillMapper.insertOrUpdate(sealApplyBill);// 智能提交 BPM 流程(如果流程实例不存在则创建,存在则审批发起人任务)// 标准字段 + 配置导出字段(默认 useMode→sealUseMode,与流程模型「流程变量字段」约定一致)Map<String,Object>processInstanceVariables=BpmProcessVariableUtils.buildBillVariables(saveReqVO,BpmProcessVariableUtils.ofFields("useMode",PV_SEAL_USE_MODE),null);StringprocessInstanceId=processInstanceApi.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(varconnection=configuration.getDataSource().getConnection()){StringproductName=connection.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 Flowable's 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_STATUS=2、STATE_=completed业务审批状态与历史流程一致

这是指定流程的工程证据。它没有自动覆盖全部审批模型、业务模块、附件上传或数据库高可用。

3. 审批完成,实际用章才进入待处理

当前回调在审批通过时,把useStatus设置为PENDING。这表明流程完成的是授权,后续仍需
执行实际用章。

@OverridepublicvoidupdateProcessStatus(StringbusinessKey,Integerstatus){Longid=Long.parseLong(businessKey);log.info("[updateProcessStatus] 更新用印申请单流程状态,id: {}, status: {}",id,status);// 校验用印申请单存在validateSealApplyBillExists(id);// 更新流程状态SealApplyBillDOupdateObj=newSealApplyBillDO();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 + Tengine:RuoYi Office 国产化部署实战
  • SpringBoot3 + openGauss:RuoYi Office 登录、流程发布与用印填报适配实战
  • 达梦 DM8 + openGauss:RuoYi Office 的 MySQL 数据转换与导入实践
  • 达梦 DM8、openGauss、人大金仓怎么选?RuoYi Office 国产数据库适配与验收指南
  • openEuler + 达梦 DM8 + openGauss:RuoYi Office 多库部署与运行维护实践

如果这篇对你有用,点个「在看」或收藏。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询