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 多库部署与运行维护实践
如果这篇对你有用,点个「在看」或收藏。