Oinone
Product
Oinone
Oinone Framework
100% Metadata-Driven Enterprise Low-Code Framework
Aino
Aino
AI Innovation, Now I Know — Enterprise AI Agent Platform
Use CasesPricingCommunity
Resources
📖
Documentation
Developer docs & API reference
💬
Support
Technical support
📄
Changelog
Product release notes
🏡
About
About Us
0571-88757863

Button:How to Display Workflow Approval Buttons in Business Model Lists


I. Scenario Overview

When we need to display approval buttons in the list of a business model, we can complete the extension through customization. This allows direct clicking on the action button in business data to navigate to the workflow to-do detail page for handling approvals or filling out tasks.

II. Solutions

(Ⅰ) First, add the userTaskList field in the business data model to store the workflow to-do data of the record

@Model.model(DemoItem.MODEL_MODEL)
@Model(displayName = "Test Product")
public class DemoItem extends IdModel {

    @Field.one2many
    @Field(displayName = "Workflow Task List", store = NullableBoolEnum.FALSE, invisible = true)
    @Field.Relation(store = false)
    private List<WorkflowUserTask> userTaskList;
}

(Ⅱ) Query the data of the current logged-in user in workflow tasks within the query method of business data

@Function.Advanced(type = FunctionTypeEnum.QUERY, displayName = "Query List", timeout = 50000)
@Function.fun(FunctionConstants.queryPage)
@Function(openLevel = {FunctionOpenEnum.LOCAL, FunctionOpenEnum.REMOTE, FunctionOpenEnum.API})
public Pagination<DemoItem> queryPage(Pagination<DemoItem> page, QueryWrapper<DemoItem> queryWrapper) {
    new DemoItem().queryPage(page, queryWrapper);

    List<Long> bizIds = page.getContent().stream().map(DemoItem::getId).collect(Collectors.toList());

    LambdaQueryWrapper<WorkflowUserTask> userTaskWrapper = new LambdaQueryWrapper<>();
    userTaskWrapper.setModel(WorkflowUserTask.MODEL_MODEL);
    userTaskWrapper.select(WorkflowUserTask::getId, WorkflowUserTask::getNodeDataBizId);
    userTaskWrapper.eq(WorkflowUserTask::getUserId, PamirsSession.getUserId())
    .eq(WorkflowUserTask::getModel, DemoItem.MODEL_MODEL)
    .eq(WorkflowUserTask::getStatus, WorkflowUserStatusEnum.ACTIVE)
    .in(WorkflowUserTask::getNodeDataBizId, bizIds);

    Pagination<WorkflowUserTask> userTaskPagination = new Pagination<>();
    userTaskPagination.setCurrentPage(1);
    userTaskPagination.setSize(200L);
    userTaskPagination.setSort(new Sort().addOrder(SortDirectionEnum.DESC, WorkflowUserTask::getCreateDate));

    List<WorkflowUserTask> userTasks = new WorkflowUserTask().queryListByWrapper(userTaskPagination, userTaskWrapper);
    Map<Long, WorkflowUserTask> map = userTasks.stream().collect(Collectors.toMap(WorkflowUserTask::getNodeDataBizId, v -> v, (a, b) -> a));
    page.getContent().forEach((item) -> {
        WorkflowUserTask workflowUserTask = map.get(item.getId());
        if (workflowUserTask != null) {
            item.setUserTaskList(Lists.newArrayList(workflowUserTask));
        }
    });
    return page;
}

(Ⅲ) Drag a server-side action into the operation column in the interface designer

(Ⅳ) Drag the workflow task list field userTaskList into the table column and hide this field

(Ⅴ) Frontend custom action component for navigating to the workflow to-do detail page

import {
  ActionType,
  ActionWidget,
  ClickResult,
  executeViewAction, RuntimeViewAction,
  ServerActionWidget,
  SPI, ViewActionTarget, ViewType, Widget
} from '@oinone/kunlun-dependencies';

// name is the action name dragged from the interface designer
@SPI.ClassFactory(ActionWidget.Token({ actionType: ActionType.Server, model: 'demo.DemoItem', name: 'uiServer0358d42817d64fe7908fe48dfce084d3' }))
  class WorkflowJumpActionWidget extends ServerActionWidget {

    @Widget.Reactive()
    public get invisible(): boolean {
      if (!this.activeRecords?.[0]?.userTaskList?.[0]?.id) {
        return true;
      }
      return super.invisible;
    }

    protected async clickAction(): Promise<ClickResult> {
      const menu = {"selectedKeys":["WorkflowMenus_WorkBenchMenu_ActiveUserTaskMenu"],"openKeys":["WorkflowMenus_WorkBenchMenu","WorkflowMenus_WorkBenchMenu_ActiveUserTaskMenu"]};
      const userTaskId = this.activeRecords?.[0]?.userTaskList?.[0]?.id;
      if (!userTaskId) {
        return;
      }
      executeViewAction(
        {
          viewType: ViewType.Form,
          resModuleName: 'workflow',
          model: 'workbench.WorkBenchWorkflowUserTaskActive',
          name: 'workflow_wait',
          target: ViewActionTarget.OpenWindow,
          sessionPath: '/workflow/WorkflowMenus_WorkBenchMenu_ActiveUserTaskMenu'
        } as RuntimeViewAction,
        undefined,
        undefined,
        {
          id: userTaskId,
          menu: JSON.stringify(menu)
        }
      );
    }
  }
Edit this page
Last Updated:1/15/26, 4:02 AM
Prev
Application:Introducing Qiankun Micro-Frontend
Next
Button:Passing Extra Parameters Across Pages
默认页脚
Copyright © 2026 Mr.Hope