用户审批意见回填到审批表单

需求

将审批同意时填写的审批意见以及图片回填到审批表单中。(填写节点同理)

用户审批意见回填到审批表单

实现方式一

通过审批后置函数操作流程参数的数据,并将流程参数数据回写到流程中。

流程设计

  1. 流程参数中自定义需要传递的字段。
    用户审批意见回填到审批表单

  2. 审批节点设计审批后置函数,后置函数由后端定义。
    用户审批意见回填到审批表单

  3. 添加更新数据节点,选择需要更新的业务表单字段,并在表达式中选择流程参数中自定义的字段。我这里更新审批意见和图片两个字段。
    用户审批意见回填到审批表单
    用户审批意见回填到审批表单

后置函数定义:

    /**
     * 审批后数据处理
     *
     * @param approvalNode 审批节点
     * @param context      上下文
     * @param dataJson     审批提交数据
     * @param result       审批结果
     */
    @Function(name = "approvalDataProcessFun", openLevel = API)
    @Function.Advanced(type = FunctionTypeEnum.QUERY, displayName = "审批后数据处理", category = FunctionCategoryEnum.CUSTOM_DESIGNER)
    public void approvalDataProcessFun(ApprovalNode approvalNode, WorkflowContext context, String dataJson, Boolean result) {
        List<WorkflowUserTask> workflowUserTasks = Models.origin().queryListByWrapper(Pops.<WorkflowUserTask>lambdaQuery()
                .from(WorkflowUserTask.MODEL_MODEL)
                .eq(WorkflowUserTask::getTaskId, context.getLastTaskInstanceId())
        );
        // 获取审批意见等放入流程参数
        for (WorkflowUserTask userTask : workflowUserTasks) {
            String remark = userTask.getRemark();
            List<String> pics = userTask.getPics();
            List<PamirsFile> attachments = userTask.getAttachments();

            Map<String, Object> paramMap = (Map<String, Object>) context.getContext().getOrDefault(ParamNode.PARAM_PREFIX, new HashMap<String, Object>());
            paramMap.put("remark", remark);
            paramMap.put("pics", pics);
        }

    }

实现方式二

通过审批动作(WorkflowUserTaskAction )扩展点实现

1、扩展点的定义

package pro.shushi.pamirs.work.core.extpoint;

import pro.shushi.pamirs.meta.annotation.Ext;
import pro.shushi.pamirs.meta.annotation.ExtPoint;
import pro.shushi.pamirs.workflow.app.api.model.WorkflowUserTask;

// @see:pro.shushi.pamirs.workflow.app.core.action.WorkflowUserTaskAction
/**
 *  Oinone所有的函数都提供了默认的前置扩展点、重载扩展点和后置扩展点,
 *  其技术名称的规则是所扩展函数的函数编码fun加上“Before”、“Override”和“After”后缀
  *  
  *  根据实际情况保留扩展点的接口和实现(可增加、可删减)
 */
@Ext(WorkflowUserTask.class)
public interface WorkflowUserTaskDealExtPoint {

    // 实际需要几个扩展点根据业务情况自行 增加 和 删除
    @ExtPoint(displayName = "审批同意后")
    WorkflowUserTask approveAgreeAfter(WorkflowUserTask workflowUserTask);

    @ExtPoint(displayName = "审批撤销后")
    WorkflowUserTask recallAfter(WorkflowUserTask workflowUserTask);

    @ExtPoint(displayName = "审批转审后")
    WorkflowUserTask approveTrangerAfter(WorkflowUserTask workflowUserTask);

    @ExtPoint(displayName = "审批转审前")
    WorkflowUserTask approveFallbackBefore(WorkflowUserTask workflowUserTask);

    @ExtPoint(displayName = "审批拒绝后")
    WorkflowUserTask approveRejustAfter(WorkflowUserTask workflowUserTask);

    @ExtPoint(displayName = "审批转审后")
    WorkflowUserTask approveFallbackAfter(WorkflowUserTask workflowUserTask);

    // …………
}

2、扩展点的实现

package pro.shushi.pamirs.work.core.extpoint;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.meta.annotation.Ext;
import pro.shushi.pamirs.meta.annotation.ExtPoint;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.util.JsonUtils;
import pro.shushi.pamirs.work.api.model.monthplan.WorkMonthlyPlan;
import pro.shushi.pamirs.work.api.model.monthplan.WorkPlanDelayApplication;
import pro.shushi.pamirs.workflow.app.api.model.WorkflowUserTask;

/**
 * 流程审操作扩展  @see:pro.shushi.pamirs.workflow.app.core.action.WorkflowUserTaskAction
 *  Oinone所有的函数都提供了默认的前置扩展点、重载扩展点和后置扩展点,
 *  其技术名称的规则是所扩展函数的函数编码fun加上“Before”、“Override”和“After”后缀
  *  
  *  根据实际情况保留扩展点的接口和实现 (可增加、可删减)
 */
@Ext(WorkflowUserTask.class)
@Component
@Slf4j
public class WorkflowUserTaskDealExtPointImpl implements WorkflowUserTaskDealExtPoint {

    // 根据实际情况是否保留
    @ExtPoint.Implement
    @Override
    public WorkflowUserTask approveRejustAfter(WorkflowUserTask userTask) {
        userTask.getNodeDataBizId();
        userTask.getModel();
         // 业务数据ID:userTask.getNodeDataBizId();
        log.info("=====================approveRejustAfter============================");
        return userTask;
    }

    @ExtPoint.Implement
    @Override
    public WorkflowUserTask approveAgreeAfter(WorkflowUserTask userTask) {
        log.info("=====================approveAgreeAfter============================");
        // WorkPlanDelayApplication 是具体的业务模型,根据事情情况修改。 其他的模型直接写else分支
        if (WorkPlanDelayApplication.MODEL_MODEL.equals(userTask.getModel())) {
            WorkPlanDelayApplication workPlanDelayApplication = JsonUtils.parseObject(userTask.getNodeContext(), WorkPlanDelayApplication.class);
            workPlanDelayApplication.setAuditRemark(userTask.getRemark());
            workPlanDelayApplication.setAuditAttachments(userTask.getAttachments());
            userTask.setPics(userTask.getPics());
            workPlanDelayApplication.updateById();
            userTask.setContent(JsonUtils.toJSONString(workPlanDelayApplication));
        } else if (WorkMonthlyPlan.MODEL_MODEL.equals(userTask.getModel())) {
            // WorkMonthlyPlan逻辑 ………… 其他模版类似
        }

        return userTask;
    }

    // 根据实际情况是否保留
    @ExtPoint.Implement
    @Override
    public WorkflowUserTask recallAfter(WorkflowUserTask userTask) {
        log.info("=====================recallAfter============================");
        return userTask;
    }

    // 根据实际情况是否保留
    @ExtPoint.Implement
    @Override
    public WorkflowUserTask approveTrangerAfter(WorkflowUserTask workflowUserTask) {
        return workflowUserTask;
    }

    // 根据实际情况是否保留
    @ExtPoint.Implement
    @Override
    public WorkflowUserTask approveFallbackBefore(WorkflowUserTask workflowUserTask) {
        return workflowUserTask;
    }

    // 根据实际情况是否保留
    @ExtPoint.Implement
    @Override
    public WorkflowUserTask approveFallbackAfter(WorkflowUserTask workflowUserTask) {
        return workflowUserTask;
    }

}

更多后置函数参考:自定义函数示例代码汇总

Oinone社区 作者:yexiu原创文章,如若转载,请注明出处:https://doc.oinone.top/other/25502.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
yexiu's avataryexiu数式员工
Previous 2026年1月7日 pm3:51
Next 2026年3月12日 pm7:53

相关推荐

  • 前端 快速查询并替换默认组件

    可以借助vue的调试工具快速找到对应的组件,请参考这篇文章 使用vue调试工具快速找到对应的组件 Mask默认组件 重写Mask组件 重写AppSwitcherWidget import Com from './com.vue' /** * SPI注册条件保持根 AppSwitcherWidget 一致,即可覆盖 */ @SPI.ClassFactory( MaskWidget.Token({ widget: 'app-switcher' }) ) export class CustomAppSwitcherWidget extends AppSwitcherWidget { /** * 如果需要重写vue组件,那么可以通过重写initialize方法来实现,如果是修改数据或者逻辑,那么可以删除这个函数 */ public initialize(props: any) { super.initialize(props); this.setComponent(Com) return this } } 重写 MenuWidget import Com from './com.vue' /** * SPI注册条件保持根 MenuWidget 一致,即可覆盖 */ @SPI.ClassFactory(MaskWidget.Token({ widget: 'nav-menu' })) export class CustomMenuWidget extends MenuWidget { /** * 如果需要重写vue组件,那么可以通过重写initialize方法来实现,如果是修改数据或者逻辑,那么可以删除这个函数 */ public initialize(props: any) { super.initialize(props); this.setComponent(Com) return this } } 重写 NotificationWidget import Com from './com.vue' /** * SPI注册条件保持根 NotificationWidget 一致,即可覆盖 */ @SPI.ClassFactory(MaskWidget.Token({ widget: 'notification' })) export class CustomNotificationWidget extends NotificationWidget { /** * 如果需要重写vue组件,那么可以通过重写initialize方法来实现,如果是修改数据或者逻辑,那么可以删除这个函数 */ public initialize(props: any) { super.initialize(props); this.setComponent(Com) return this } } 重写 LanguageWidget import Com from './com.vue' /** * SPI注册条件保持根 LanguageWidget 一致,即可覆盖 */ @SPI.ClassFactory(MaskWidget.Token({ widget: 'language' })) export class CustomLanguageWidget extends LanguageWidget { /** * 如果需要重写vue组件,那么可以通过重写initialize方法来实现,如果是修改数据或者逻辑,那么可以删除这个函数 */ public initialize(props: any) { super.initialize(props); this.setComponent(Com) return this } } 重写 UserWidget import Com from './com.vue' /** * SPI注册条件保持根 UserWidget 一致,即可覆盖 */ @SPI.ClassFactory(MaskWidget.Token({ widget: 'user' })) export class CustomUserWidget extends UserWidget { /** * 如果需要重写vue组件,那么可以通过重写initialize方法来实现,如果是修改数据或者逻辑,那么可以删除这个函数 */ public initialize(props: any) { super.initialize(props);…

    2025年8月14日
    90600
  • 如何使用源码的方式配置表达式

    自定义占位符定义表达式 数据权限定义表达式: ${thisTeacherName} 界面设计器查询条件定义:$#{thisTeacherName}需要加上#号 以上配置都可以通过查看queryWrapper里面的originRsql查看占位符是否被正确替换。 显隐、过滤条件表达式定义 显隐、过滤都可以加载字段注解里以及xml定义里 显隐: invisible="$!{activeRecord.deadline}" / invisible = true @Field.String @Field(displayName = "视图/页面", invisible = true) private String viewName; 过滤。 domain = " code == ${activeRecord.id} " / domain = "code == '111' " @Field.one2many @Field(displayName = "子订单列表", summary = "子订单列表") @Field.Relation(relationFields = {"code"}, referenceFields = {"code"}, domain = "code != '1234'") private List<ChildOrder> orderList; 更多获取视图数据的写法参考文章上下文在字段和动作中的应用 rsql表达式定义 参考:oinone的rsql与传统sql语法对照表

    2025年3月13日
    1.0K00
  • 数式Oinone培训前注意事项

    一、快速上手 (建议至少预习 6 小时) 在正式培训之前,建议需要完成以下任务,以便对培训内容有基本了解: 点击阅读:快速启动入门 该文档为学员提供了从入门到实现 demo 的全过程说明,涵盖了开发工具、框架搭建、常见问题解答等内容 开始培训前,请参与人员确保完成以下任务 阅读并理解文档中的每个步骤。 配置好前后端开发环境。 完成 demo 的基础框架搭建,验证是否能够成功运行。 二、预期成果 通过上述预习,大家完成以下事项:• 成功搭建本地开发环境,并能运行前后端的基本 demo。• 对前后端技术栈有初步了解,为正式培训中的深度学习打下基础,并且提出对应的疑问点 三、其他准备工作 1.技术工具检查:请确在本地已安装并配置好必要的开发工具和环境(如 IDE、Node.js、数据库等);2.参与者反馈:在预习过程中,学员如遇到困难或无法解决的问题(前后端疑问),请提前记录并提交,以便培训期间重点解答;3.版本是否是最新的版本,且建议研发人员版本一致,且类型是 mini; ps:部署包相关信息,联系数式相关人员获取

    未分类 2024年8月2日
    3.3K00
  • 打印支持非存储数据导出

    介绍 平台提供的默认打印功能没有支持非存储数据的导出。我们可以自定义打印导出功能,以满足业务中个性化的需求。 实现思路 重写打印任务模型,添加业务数据字段 自定义打印动作,前端将导出数据放到业务数据字段中 使用导出数据扩展点机制修改导出数据 代码示例 继承平台的打印任务模型,加上需要业务数据字段,这个字段用于传输需要打印的表单数据,但是需要自定义打印的表单往往不止一个,所以需要定义为通用的Object字段。 @Model.model(TransientPdfPrintTask.MODEL_MODEL) @Model(displayName = "传输模型Pdf打印任务") public class TransientPdfPrintTask extends PdfPrintTask { public static final String MODEL_MODEL="demo.TransientPdfPrintTask"; @Field(displayName = "业务数据") private Object businessData; } 自定义打印动作 @Model.model(TransientPdfPrintTask.MODEL_MODEL) @Component public class TransientPdfPrintTaskAction extends AbstractPdfPrintTaskAction<TransientPdfPrintTask> { @Resource private PdfFileService pdfFileService; @Action(displayName = "打印", contextType = ActionContextTypeEnum.CONTEXT_FREE, bindingType = {ViewTypeEnum.TABLE}) @Override public TransientPdfPrintTask createPrintTask(TransientPdfPrintTask data) { return super.createPrintTask(data); } @Override protected void doExport(TransientPdfPrintTask exportTask, PdfDefinitionContext context) { pdfFileService.doExportSync(exportTask, context); } @Function.Advanced(type = FunctionTypeEnum.QUERY) @Function(openLevel = FunctionOpenEnum.API) public TransientPdfPrintTask construct(TransientPdfPrintTask data) { String model = FetchUtil.fetchVariables(PdfConstants.MODEL); data.construct(); data.setModel(model); return data; } } 本篇文章只介绍同步打印,如果异步需要修改doExport方法。 编写导出的数据处理逻辑 @Ext(PdfPrintTask.class) public class PrintExportExt extends AbstractPdfExportFetchDataExtPointImpl implements PdfExportFetchDataExtPoint { // 这里使用扩展点表达式匹配需要打印的非存储模型,只有表达式为true才会走这段逻辑。 @Override @ExtPoint.Implement(expression = "context.model==\"" + ProductPricingClientTransient.MODEL_MODEL + "\"") public List<Object> fetchExportData(PdfPrintTask exportTask, PdfDefinitionContext context) { List<Object> result = new ArrayList<>(); List<Object> dataList = new ArrayList<>(); TransientPdfPrintTask transientPdfPrintTask = new TransientPdfPrintTask(); transientPdfPrintTask.set_d(exportTask.get_d()); dataList.add(transientPdfPrintTask.getBusinessData()); result.add(dataList); return result; } } 前端自定义打印按钮,将数据提交给业务数据字段,并使用同步导出打印。

    2025年10月13日
    86700
  • 如何通过业务数据拿到工作流用户任务待办

    在模型里面建一个非存储字段,用来传输工作流用户任务待办ID。。 界面设计器把这个字段拖到列表页里,并在跳转动作上配置上下文参数,把任务待办id传到表单页里。 重写教师模型的queryPage,通过业务数据id查询出每条业务数据的工作流用户任务待办id返回给前端。 @Function.Advanced(displayName = "查询教师列表", type = FunctionTypeEnum.QUERY, category = FunctionCategoryEnum.QUERY_PAGE, managed = true) @Function(openLevel = {FunctionOpenEnum.LOCAL, FunctionOpenEnum.REMOTE, FunctionOpenEnum.API}) public Pagination<Teacher> queryPage(Pagination<Teacher> page, IWrapper<Teacher> queryWrapper) { Pagination<Teacher> teacherPagination = new Teacher().queryPage(page, queryWrapper); List<Teacher> content = teacherPagination.getContent(); if (CollectionUtils.isEmpty(content)) { return teacherPagination; } List<Long> teacherIds = content.stream().map(Teacher::getId).collect(Collectors.toList()); List<WorkflowUserTask> workflowUserTasks = Models.data().queryListByWrapper(Pops.<WorkflowUserTask>lambdaQuery() .from(WorkflowUserTask.MODEL_MODEL) .in(WorkflowUserTask::getNodeDataBizId, teacherIds) .orderByDesc(WorkflowUserTask::getCreateDate) ); if (CollectionUtils.isEmpty(workflowUserTasks)) { return teacherPagination; } Map<Long/*业务id*/, WorkflowUserTask> userTaskMap = workflowUserTasks.stream().collect(Collectors.toMap( WorkflowUserTask::getNodeDataBizId, a -> a, (old, n) -> old) ); for (Teacher teacher : content) { if (userTaskMap.containsKey(teacher.getId())) { teacher.setWorkflowUserTaskId(userTaskMap.get(teacher.getId()).getId()); } } return teacherPagination; } 查看效果,任务待办id成功传到表单里面。

    2025年1月10日
    2.5K00

Leave a Reply

Please Login to Comment