第 4 部分 - 让 Usertask 确定 UI 布局

flowable 流程实例新增临时节点 flowable 流程实例新增临时节点需求目的flowable 自带实现方式结果分析:**解决方案**功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowch... 阅读详情

本系列介绍了由 Elsa 工作流引擎驱动的用户界面的实现。 在这一部分中,我们将进一步研究引擎如何成为 UI 的驱动力。 这个想法是工作流可以规定 UI 应提供哪些数据条目。

在上一部分 - 添加从用户任务返回数据的功能中,这是一个可以输入数据的简单工作流程列表。 在这一部分中,它将进一步扩展。

我们将引入一个显示用户任务详细信息的新页面。 用户任务屏幕可以根据用户任务的需要进行完全定制。

@page "/WorkflowInstances/{workflowinstanceid}"
@using ElsaDrivenWebApp.Shared.Components

@inject UsertaskService userTaskService
@inject ProcessService processService

@if (usertask != null)
{
    switch (usertask.Signal)
    {
        case "usertasksample2":
            <Usertasksample2 Task=usertask OnFinished="TaskFinished"></Usertasksample2>
            break;
        case "usertasksample2a":
            <Usertasksample2a Task=usertask OnFinished="TaskFinished"></Usertasksample2a>
            break;
        default:
            <button @onclick="() => SendSignal(usertask)">Finalize @usertask.TaskTitle</button>
            break;
    }
}

@code {

    [Parameter]
    public string workflowinstanceid { get; set; } = string.Empty;

    private UsertaskViewModel? usertask;

    protected async override Task OnParametersSetAsync()
    {
        await LoadTask();

    }

    private async Task LoadTask()
    {
        var workflowInstance = await userTaskService.GetUsertasksFor(workflowinstanceid);
        usertask = workflowInstance?.UserTasks?.FirstOrDefault();
    }

    private async Task SendSignal(UsertaskViewModel task)
    {
        await userTaskService.MarkAsCompleteAsync(task.WorkflowInstanceId, task.Signal, null);
        await LoadTask();
    }

    private async Task TaskFinished()
    {
        await LoadTask();
    }
}

此实现与之前的版本没有太大不同。 唯一的区别是有一个特定的页面用于处理用户任务。
根据信号名称选择组件。 它将获取数据并将其返回给引擎。

如果信号未知,则回退方案只是发送完整的信号而不发送任何数据。

此信号和 UI 耦合显示了当前实现的问题之一。 引擎的配置和 UI 之间存在紧密耦合。 引擎决定信号并假设 UI 将按预期提供数据。 UI考虑到在某些情况下,它可以在不发送任何数据的情况下完成任务。

这种耦合并不是什么新鲜事。 大多数情况下,UI 和后端之间会存在紧密耦合。 如果您了解这一点,则可以设置部署它们的 DevOps 环境。

在用户任务活动的实现中,有更多的属性我们到现在为止还没有使用过。

  [ActivityInput(
            Hint = "The definition of the data expected to be returned",
            UIHint = ActivityInputUIHints.MultiLine,
            Category = "Task",
            SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid })]
        public string UIDefinition { get; set; }

UIDefinition

该属性允许配置用户任务保存 UI 定义。 这是 UI 工作流程的建议。 UI 是否遵守它不是工作流程关心的问题。

在当前的实现中,UI-Definition 由dynamicUserTaskComponent 使用。 该组件利用动态 Blazor 表单的功能。
Dynamic Blazor Form 是一个实验性组件,可创建基于 JSON 结构的表单。 表单中的输入会生成 JSON 对象。

(稍后我也会写一系列关于这个组件的文档)

在下一个代码片段中可以看到 UI 定义的示例。

{
  "groups": [
    {
      "name": "demo",
      "layoutHint": "",
      "subGroups": [
        {
          "layoutHint": "",
          "index": 1,
          "items": [
            {
              "index": 1,
              "span": 4,
              "path": "$.number",
              "typeName": "NumberInput",
              "layoutHint": "",
              "text": "number",
              "groups": [

              ],
              "customData": {

              }
            },
            {
              "index": 2,
              "span": 8,
              "path": "$.myText",
              "typeName": "TextInput",
              "layoutHint": "",
              "text": "initial text",
              "groups": [

              ],
              "customData": {

              }
            }
          ]
        },
        {
          "layoutHint": "",
          "index": 2,
          "items": [
            {
              "index": 1,
              "span": 4,
              "path": "$.datefield",
              "typeName": "DateInput",
              "layoutHint": "",
              "text": "date",
              "groups": [

              ],
              "customData": {

              }
            },
            {
              "index": 2,
              "span": 8,
              "path": "$.otherText",
              "typeName": "TextInput",
              "layoutHint": "",
              "text": "next text",
              "groups": [

              ],
              "customData": {

              }
            }
          ]
        }
      ]
    }
  ],
  "title": "random text"
}

包含建议的 UI 结构的 Json 被转换为表单。 JSONPath — XPath for JSON (goessner.net) 表示法确定每个元素结果的结构。

DynamicUserTask

@inject UsertaskService userTaskService
@if(Usertask !=null)
{
<DynamicForm @ref="df" Layout="@(GetLayout())"  @bind-Value=taskData></DynamicForm>

<div class="row">
    <div class="col-md-12 text-right">
         <button @onclick="() => SendSignalAndData()">Continue</button>
    </div>
</div>
}

@code {

    [Parameter]
    public UsertaskViewModel? Usertask { get; set; }


    [Parameter]
    public EventCallback OnFinished { get; set; }

    private JToken taskData { get; set; } = new JObject();
    private DynamicForm df { get; set; }


    private DynamicLayout? GetLayout()
    {
        return JsonConvert.DeserializeObject<DynamicLayout>(Usertask.UIDefinition);
    }

    private async Task SendSignalAndData()
    {
        await userTaskService.MarkAsCompleteAsync(Usertask.WorkflowInstanceId, Usertask.Signal, taskData);
        Usertask = null;
        taskData = new JObject();
        df.ResetData();
        await OnFinished.InvokeAsync();
    }
}

该组件的工作非常简单。 它获取布局,生成表单,并在绑定上,只要表单的输入字段更改其值,组件就会更新结果模型。

Dynamic Blazor 表单允许您定义要在表单内使用的 UI 组件的实现。 您可以利用默认的 HTML 组件或使用 Radzen 组件库等。 混合和匹配,甚至创建您的类型,都是可能的。

您要使用的组件需要在startup.cs中注册。

builder.Services.AddScoped(sp =>
    new DynamicElementsRepository()
        .GetHTMLDefaultSettings()
        .Add("TextInput", typeof(TextInput))
        .Add("NumberInput", typeof(NumberInput))
        .Add("BoolInput", typeof(BoolInput))
        .Add("DateInput", typeof(DateInput)));

这意味着可以在 UI 定义中添加新组件,并让 UI 映射到这些类型的特定组件。

当使用已知的 UI 定义名称创建新的用户任务时,无需更新 Web 应用程序。 应用程序现在可以创建表单并将结果发送回引擎。

时机问题

在工作流详细信息页面的实现中,UI 组件激活任务完成事件。 该组件将带有数据的信号发送到引擎。 之后,它将引发 TaskFinished 事件。 详细信息页面将通过加载下一个用户任务来对此进行操作。

但如果

  • 引擎还没有完成任务。
    • 详细信息页面将再次显示相同的用户任务。
  • 工作流程已结束
    • 没有什么可展示的。
  • 下一步的执行是一个长时间运行的后台活动
    • —用户必须等待,但是在这种情况下要显示什么?

有一些解决方案可以缓解这些问题。 不幸的是,他们中的大多数人都求助于在引擎和客户端之间进行更多的通信。 例如,了解工作流的上次执行时间。 因此,在发送信号时,客户端知道工作流何时更新,因为执行时间会有所不同。 但这也意味着客户端需要保存状态。

调度还是执行?

有时,由于工作流程的目的,问题并不那么严重。 例如,当所有活动都是用户任务时,可以将信号发送为“执行”。这种类型的请求意味着该请求将触发工作流的执行,只有当工作流停止运行时才会返回结果。 这个执行方法是同步调用。 此方案适用于类似向导的流程,其中数据存储在工作流实例本身中,并且不依赖于可能运行缓慢的活动。

如果工作流包含长时间运行的步骤,则调度是最佳选择,但这需要某种同步。 或者,使用丑陋的轮询方法或用于检索下一步的任务延迟。 假设在一定时间内,工作流将被执行。

幸运的是,有一种机制可以优雅地处理客户端和引擎之间的通信。 SignalR 实现可以处理它。

下一部分将介绍SignalR 的实现。

flowable 6.4.2 - 流程定义动态化的支持(DynamicBpmnService) 1、injectParallelUserTask --- 给《任务实例》加入《子任务》 2、injectParallelEmbeddedSubProcess --- 给《任务实例》加入《子流程》 3、injectUserTaskInProcessInstance --- 给《流程实例》加入《子任务》 4、injectEmbeddedSubProcessInProcessInstance --- 给《流程实例》加入《子流程》 . // injectParallelUserTask --- 给《任务实例 阅读详情

相关推荐

WinForm异步编程实战:async/await解决UI卡顿与线程阻塞

在桌面应用开发中,UI线程阻塞是导致界面卡顿、用户体验下降的常见问题。其核心原理在于事件驱动的GUI框架(如WinForm)依赖单一主线程处理消息循环,一旦执行耗时同步操作,便会阻塞消息泵,造成程序“假死”。为解决此问题,C#引入了基于任务的异步模式(TAP)与async/await关键字,通过编译器生成状态机,在等待I/O操作时释放UI线程,待操作完成后自动返回原始同步上下文执行后续代码,从而在保持代码线性逻辑的同时实现非阻塞异步。这项技术对于提升应用响应性、简化多线程编程具有重要价值,尤其适用于需要处理

weixin_33696822的博客 358

Activiti工作流之任务

回顾: Activiti工作流之简介与环境搭建 Activiti工作流之流程部署和相关操作 Activiti工作流之任务的运行/查询/完成 Activiti工作流之流程变量 Activiti工作流之历史查询 Activiti工作流之流程分支 Activiti工作流之网关 11张表: select * from act_re_deployment; select * from ...

C8WATER 1049

Unity游戏模组加载器MelonLoader:从原理到实战的完整指南

在游戏模组开发领域,模组加载器是连接原生游戏与玩家自定义内容的关键桥梁。其核心原理在于通过动态链接库注入、运行时劫持等技术,在游戏进程初始化阶段介入,为第三方代码创建安全的执行环境。这一技术对于扩展游戏生命周期、丰富玩家体验具有重要价值,尤其在支持玩家社区创作的Unity游戏中应用广泛。针对Unity游戏常见的Mono和Il2Cpp两种运行时架构,模组加载器需要采用不同的技术方案:对于Mono架构,可利用其反射机制直接加载程序集;而对于性能更高、安全性更强的Il2Cpp AOT编译架构,则需通过Il2Cpp

weixin_33979203的博客 450

第 2 部分 - 创建用户任务活动

本系列介绍了由 Elsa 工作流引擎驱动的用户界面的实现。几个不同的步骤将导致全面有效的实施。此实现可能无法为您提供满足您的特定需求的灵丹妙药。尽管如此,它仍将提供对各种选项的见解。在,讨论了基本解决方案设置。在这一部分中,我们将创建本系列中使用的用户任务活动。。它是一个.Net6类库。该项目将添加用户任务活动所需的所有元素。该应用程序将依赖于三个包。将活动创建为名为的类。该类将从Activity类继承。

极客神殿 714

基于bpmn-js构建企业级流程设计器:从架构解析到深度定制实战

流程引擎是现代企业应用的核心组件,它通过将业务流程逻辑从硬编码中解耦,实现了规则的可视化配置与动态管理,从而显著提升系统灵活性和开发效率。其技术原理在于采用标准化的建模语言(如BPMN)定义流程元素与流转语义,并通过设计器与引擎的协作驱动实例运行。在工程实践中,基于Web的前端流程设计器成为构建低代码平台和复杂业务系统(如OA、ERP)的关键。bpmn-js作为实现BPMN标准的领先前端库,提供了强大的可视化编排内核和模块化扩展能力。开发者可通过其依赖注入架构,深度定制调色板、属性面板和渲染器,并解决元素I

weixin_34050519的博客 390

从零构建WebOA系统:Spring Boot+Vue3全栈实战与架构设计

办公自动化(OA)系统是企业信息化建设的核心,旨在通过技术手段优化审批、协同与文档管理等业务流程,提升组织效率。其技术原理通常基于B/S架构,实现浏览器端的便捷访问与服务器端的集中处理。在技术价值层面,自研OA系统能深度契合企业个性化流程,实现数据自主可控与灵活扩展,避免了商业化产品常见的定制成本高与流程僵化问题。典型的应用场景包括请假报销审批、公文流转、任务管理与知识共享等内部协同办公。本文聚焦于使用Spring Boot和Vue3等技术栈,深入剖析如何设计并实现一个轻量级、可定制的WebOA系统,涵盖权

weixin_33829657的博客 385

【Elsa 3】Elsa 3 中的一些基本概念梳理

作为一名视觉工程师,见过很多成熟的视觉软件,都是基于拖拉拽的,通过托选构成整个流程。这样可以解放视觉工程师,把拖拉拽的任务可以交给售后工程师。这个拖拉拽形成流程的过程,就是工作流的概念。ps:不得不说,后端服务开发的一些新的技术概念往往走在工业软件开发的前面。Elsa 3 就是为数不多面向C#的优秀的工作流框架(还有很多出名的工作流框架都是面向java的)。Elsa 3 更多的是面向后台服务的开发的。但是并不影响我将他引入视觉软件的开发。 前面说到,很多成熟的视觉软件,都是基于拖拉拽的,比如海康的的视觉软件

songhuangong123的博客 2610

Vue3集成BPMN.js:从零构建工作流可视化设计器

工作流引擎是现代企业应用实现业务流程自动化的核心技术,其前端可视化设计器则是提升配置效率的关键。BPMN(业务流程模型与标注)作为国际标准,为流程定义提供了统一的图形化语言。BPMN.js是基于此标准的前端库,通过模块化架构提供画布渲染、交互与建模能力。结合Vue3的响应式系统与Composition API,能够高效管理设计器的复杂状态与交互逻辑,实现流程图的拖拽创建、属性编辑与标准BPMN 2.0 XML的生成与解析。本文聚焦于在Vue3项目中深度集成BPMN.js,涵盖环境搭建、核心功能实现、模块化定

weixin_30243533的博客 389

Blazor实现高级表单功能

思路 添加Form组件类,提供Validate,OnSubmit等 添加Field组件基类,提供Id,Label,Value等 添加Field子组件Text、Password等表单字段组件 添加FormContext类,存储表单及字段数据 使用级联值组件传递FormContext实例(关键) Form组件 public class FormContext { public Dictionary<string, Field> Fields { get; } } public clas

knownchen的专栏 548

zed(Rust)开源项目完整源码

「zed(Rust)开源项目完整源码」是开源项目(Rust)。项目简介:Code at the speed of thought – Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.源码完整,下载解压即可查看使用,适合学习参考、课程设计与二次开发。

IEC 63281-3-1:2024 电动运输车 - 第3-1部分:考虑实际使用温度条件的电动滑板车总运行时间性能测试方法 - 完整英文电子版(30页)

IEC 63281-3-1:2024规定了电动滑板车单人运输总运行时间的测试方法,考虑了用户在不同温度下驾驶时的实际使用温度条件,用于公路或公共场所。 本文件不涵盖残障人士或老年人的电动滑板车。此外,本文件不包括货运电动滑板车。

Elsa-审批流实现

一、新建项目:ElsaFlowDemo <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> <ItemGroup> <Proje

码农的专栏 5523

YOLO26算法表面凹坑与条纹检测+训练好的模型+610张数据集+pyqt可视化界面.zip

附训练好的 YOLO 权重与 PyQt 可视化检测界面,页面底部含可视化效果预览,毕设/课设开箱即用。 【数据集概况】 · 检测类别(中文):[未获取()] 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 100 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.7184** mAP50-95 | 0.4372 Precision | 0.6793 Recall | 0.7024 train/box_loss | 1.1399 train/cls_loss | 0.7578 val/box_loss | 1.3453 val/cls_loss | 1.0488 【训练过程分析】 记得从开始第一轮训练起,那曲线就一直像坐滑梯一样,很快地就下滑到了低谷值。大概到第 10 轮时,模型就开始缓慢而持续地从 0.5 左右的 mAP50 走向平稳上升的通道。整个训练过程,除了初期的那股势如破竹的气势外,中间部分的曲线就变得起伏不定,有时还会在某个阶段停滞不前,似乎在寻找下一个前进的方向。而到了后期,曲线又慢慢开始平稳下来,从第 80 轮开始,mAP50 的提升逐渐减缓,这时候,我不得不面对一个问题:是继续等待模型自行收敛,还是尝试更多的调参策略。在经过一轮轮的观察和思考后,我觉得继续等待已经不太可能有显著的进步,于是决定在第 95 轮时停下了脚步,最终完成了总共 100 轮的训练任务。 在训练过程的后半程,我注意到 loss 曲线虽然总体下降趋势明显,但在某些阶段却出现了停滞,特别是在第 70 轮到... 使用场景:毕业设计、课程设计、深度学习入门、工业场景落地验证。

Activiti 判断当前UserTask用户任务是否为多实例 版本6.0.0.4

Activiti 判断当前UserTask用户任务是否为多实例 版本6.0.0.4判断当前任务是否为多实例 判断当前任务是否为多实例 //当前TaskEntity为执行期的manage中科查询到的对象 private boolean isMultiInstance(TaskEntity task) { // 获取流程定义id boolean flag = false; String processDefinitionId = task.getProcessDe

hatricks的播客 1850

编程语言扩展与跨边界架构设计:五种组合方式、统一判定与框架开发(20章)

本资源是一份 20章系统化技术长文,围绕“宿主语言如何借外部力量获得自身不具备的能力”展开,建立 “脚本解释器核心—适配层—被组合组件”三层统一模型,系统拆解 进程级、函数级、协议级、语言级、数据级 五种边界,并给出可复用的 三问拆解法、跨边界四要素、适配层厚薄定律与横向判定规则。内容覆盖 Shell 管道、Python import、requests/psycopg2、setuptools entry_points、Make/CMake、CI/CD、Lua 嵌入式脚本、Airflow DAG 等八个典型实例,深入讲解进程通信、ABI/FFI、动态库加载、import 协议、插件发现与入口点、HTTP 与数据库线协议、序列化与 Schema、构建编排、任务调度与数据管道等机制。文档同时包含混合系统主导/从属方式判定、选型决策树、反模式批判、框架开发清单、插件 SDK 设计、隔离策略、性能预算、可观测治理、综合实例、术语表、原文核心内容收录与交付校验清单。本资源适合 架构师、框架/平台开发者、插件系统设计者、跨语言集成工程师、后端与数据平台工程师、技术负责人 阅读,可作为技术选型、架构评审、插件体系设计、跨边界排障与团队内训的参考手册。关键词: 编程语言扩展、跨边界架构、五种边界、三层模型、进程级组合、函数级组合、协议级组合、语言级组合、数据级组合、插件系统、FFI、ABI、import机制、HTTP、数据库线协议、CI/CD、Lua、Airflow、框架设计、技术选型。

植物大战僵尸神人版-手机版-arm64-2026.10.30-手机版.apk.1

植物大战僵尸神人版-手机版-arm64-2026.10.30-手机版.apk.1

不平衡电网下自抗扰顺序模型预测PWM整流器控制仿真模型(Simulink仿真实现)

不平衡电网下自抗扰顺序模型预测PWM整流器控制仿真模型(Simulink仿真实现)

跨平台烧录实战:RKDevTool在Windows/Linux/MacOS下的统一与差异

本文详细解析了RKDevTool在Windows、Linux和macOS三大操作系统下的固件烧录实践,重点介绍了RK3576开发板的环境配置、工具链选择、烧录模式切换及常见问题解决方案,帮助开发者构建稳定可靠的跨平台烧录工作流。

cnn8visionary的博客 201
上一篇: 第 3 部分 - 添加从用户任务返回数据的功能
下一篇: 第 5 部分 — 使用通知更新用户界面
.NET跨平台
博客等级 码龄15年 6066粉丝 738原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值