アプリケーション開発プラットフォーム統合ワークフロー - プロセスモデリング機能のロールバックとジャンプ

背景

不親切なプロセス設定の問題については、国内のDingTalkがbpmnの仕様とは関係なく、プロセスモデリングモード一式を別途設計・実装しており、それを誰かが模倣してオープンソース化しました(https://github.com/StavinLi/ワークフロー -Vue3 ) の効果図は次のとおりです:

実装の一般原則は、無限にネストされた子ノードに基づいており、json データを出力し、それをバックエンドに渡します。バックエンドが解析した後、Camunda エンジンの API を呼び出します。それをプロセス モデルに変換し、永続化します。

**このモードは、Camunda に付属する bpmn2.0 仕様のプロセス モデリングと比較すると、はるかに使いやすいですが、新しい問題も発生し、リンク間に「ジャンプ フロー」を設定することは不可能です。**ここで言う「ジャンプ転送」には、実際には 2 つの方向の転送が含まれます。1 つは現在のリンクから非直接フォローアップ リンクにジャンプすることであり、もう 1 つは現在のリンクから特定の以前のリンクにフォールバックすることです。注文リンク。

上記の要件は、ルーティング分岐では解決できません。ネイティブ BPMN モデルの場合、開始ノードとターゲット ノードの間にエッジを描画し、エッジに条件を設定できます。この模倣 DingTalk プロセス モデリング モードのセットにより、基本的に「エッジの描画」の解決策は実行不可能です。どうすればよいですか?

実装のアイデア

既存のプロセスモデリングモードでは、ジャンプフローを実現するために適応する必要があり、具体的な実装アイデアとしては、ロールバックまたはスキップ可能なリンクをカスタム構成で各リンクに格納し、リンク構成部品として使用するというものです。
独自に設計するため自由度が高く、属性を付加することでフォールバックかジャンプかジャンプフローの種類を区別することができます。ネイティブ BPMN では、描画されるエッジにはタイプがありません。通常のエッジ、デフォルト エッジ、リターン エッジ、およびジャンプ エッジはすべて同じ方法で実装され、条件を追加できます。ロールバックとジャンプを区別するには、合意された条件を設定することによる ${reject==true} などの変数を設定してフォールバックをマークするなどの間接的な実装はエレガントではありません。

重要な問題について考える

デフォルト設定は開始リンクと前のリンクにフォールバックしますか?

ロールバックはユーザーを制限する設定によって実装でき、任意のロールバックは許可されません。ただし、開始リンクと以前のリンクにフォールバックするのは一般的な要件です。これら 2 つの状況がデフォルトでプラットフォームによって処理されるかどうか、つまり、設定なしでロールバックでき、その後、フォールバック リンクのみを設定します。処理する必要があるその他の状況は問題ありませんか?

システムのデフォルト構成は、確かに構成作業負荷の一部を軽減できますが、プロセス全体の制御性と標準化を破壊する可能性があります。たとえば、長いプロセスは管理上 3 つの大きな段階に分けられ、第 2 段階では開始リンクにフォールバックすることはできませんが、デフォルトの処理を追加すると、このビジネス上の制約は破られます。さらに、次の 2 つの状況では、ロールバックは許可されません。
1. すべての参加者が処理する前に、複数人が署名したリンク。
2. 現在ルーティング ブランチにあるリンクは、メイン ブランチのリンクに直接ロールバックされます。

上記のシナリオと制限を考慮して、システムはデフォルトでは構成されず、プロセス モデラーが実際のビジネス ニーズに応じて構成することが最終的に決定されました。

リンク名を重複して保存するかどうか

プロセスモデリングにおいて、あるリンクがジャンプ・フォールバックできるリンクのリストを構成する場合、論理判断にはリンク識別子を使用し、表示にはリンク名を使用しても問題ありません。問題は、リンク名を重複して保存する必要があるかどうかです。使いやすさの観点からは、冗長ストレージが必要です。ただし、ストレージを冗長化するには、更新を同期する必要があることを意味しますが、これを実現するのは簡単ではありません。ユーザーは最初にリンク ジャンプまたはロールバックを構成し、次にターゲット リンクの名前を変更します。リンク ジャンプまたはロールバックの構成は、実際には認識されません。

この問題を解決するには、2 つの解決策があります。1
つは、ジャンプとロールバックのリンク リスト構成にリンク名を重複して格納せず、リンク識別子のみを保存し、リンク名を動的に検索して表示することです。リンク名の一貫性をリアルタイムで確保できますが、その処理は複雑で、モデルの分析と処理が必要になります。
モデル保存リンクでは、トラバーサル更新、つまりクエリタイプは開始または処理のリンクであり、プロセス定義識別子とリンク識別子に従って、ジャンプ先およびフォールバック先のリンクはバッチで更新されます。

解決策 2 の問題は、バックエンド ライブラリのテーブルのデータは更新されますが、フロントエンドの JSON 形式のモデルは実際には更新されないことです。モデルをエクスポートしてからインポートすると、誤った結果が生じる可能性があります。モデルの移行結果。そのため、本来はフロントエンドから更新する必要があるのですが、それをフロントエンドから行うのはかなり面倒です。

この問題は当面保留され、同期更新は行わずに冗長ストレージが最初に実行され、リンク名が変更される可能性は低いです。同期更新が実装されていない場合は、設定を通じて手動で更新でき、作業負荷が軽減されます。小さいです。

フロントエンドの実装

構成拡張

フロントエンドは、構成情報をノードの config 属性に入れ、人事構成 personConfig と権限構成 PermissionConfig と並列して、backNodeList とジャンプ リンク リスト JumpNodeList を展開して追加します。理論的には、開始リンクと処理リンクの 2 種類のノードは手動で処理され、これには「ジャンピング転送」が必要になります。
backNodeList と JumpNodeList の構成は同じです。プロセスにより現在のリンクのロールバックまたは複数のリンクへのジャンプが許可されるため、ターゲット リンクの ID と名前を含む配列になります。2 つの主要な属性は Can です。

例は次のとおりです。

{
    
    
	"name": "填报",
	"id": "root",
	"type": "ROOT",
	"config": {
    
    
		"permissionConfig": [{
    
    
			"areaCode": "applyArea",
			"permission": "EDITABLE"
		}, {
    
    
			"areaCode": "organizationApproval",
			"permission": "READONLY"
		}, {
    
    
			"areaCode": "hrApproval",
			"permission": "INVISIBLE"
		}],
		"jumpNodeList": [{
    
    
			"id": "node2268_3ea5_a5db_15b0",
			"name": "人事审批"
		}]
	},
	"branchList": [],
	"child": {
    
    
		"name": "部门审批",
		"id": "node1938_8b28_c3ed_030f",
		"type": "HANDLE",
		"config": {
    
    
			"personConfig": {
    
    
				"mode": "COUNTERSIGN",
				"setAssigneeFlag": "YES",
				"userGroup": "99",
				"userGroupName": "系统管理员"
			},
			"permissionConfig": [{
    
    
				"areaCode": "applyArea",
				"permission": "READONLY"
			}, {
    
    
				"areaCode": "organizationApproval",
				"permission": "READONLY"
			}, {
    
    
				"areaCode": "hrApproval",
				"permission": "READONLY"
			}]
		},
		"child": {
    
    
			"name": "人事审批",
			"id": "node2268_3ea5_a5db_15b0",
			"type": "HANDLE",
			"config": {
    
    
				"personConfig": {
    
    
					"mode": "NORMAL",
					"setAssigneeFlag": "YES",
					"userGroup": "99",
					"userGroupName": "系统管理员"
				},
				"permissionConfig": [{
    
    
					"areaCode": "applyArea",
					"permission": "READONLY"
				}, {
    
    
					"areaCode": "organizationApproval",
					"permission": "READONLY"
				}, {
    
    
					"areaCode": "hrApproval",
					"permission": "READONLY"
				}],
				"backNodeList": [{
    
    
					"id": "root",
					"name": "填报"
				}, {
    
    
					"id": "node1938_8b28_c3ed_030f",
					"name": "部门审批"
				}]
			},
			"child": {
    
    }
		}
	}
}

リンク構成

開始リンクの場合、それはプロセスの開始点であり、ロールバックの問題はありません。ルーティング機能でジャンプは実現できますか?考えてみてください。実際には複数のシナリオがあります。
シナリオ 1: リストで、特定のルールが満たされると、中間の特定のリンクに直接ジャンプします。このルールは、システムが自動的に判断して処理できるほど明確ではない可能性があり、ジャンプすべきかどうかを手動で判断する必要があります。実行される。
シナリオ 2: 注文は一定の承認段階まで進み、問題がある場合は開始段階に戻り、申請者は調整を行います。拒否に直接ジャンプする 具体的なシナリオは契約の承認に似ており、財務、法務などの多部門がレビューに参加します。法的なレビュー プロセスで問題が見つかり、調整が必要な場合は、私はそのようなことはしません。もう一度財務審査プロセスを経たいと考えています。
要約すると、開始リンクではジャンプ リンク設定を行う必要があります。

処理リンクは手動プロセス リンクであり、ロールバック機能とジャンプ機能の両方が必要です。


画像.png
次の図に示すように、ジャンプ リンクの構成を例に挙げます。まず、[追加] ボタンをクリックすると、ジャンプできるすべてのターゲット リンクを表示するダイアログ ボックスが表示されます。ターゲット リンクは次の条件を満たす必要があります条件: 1.
タイプ 開始リンクと処理リンクのみにすることができ、ルーティング ノードにジャンプすることはできません。ルーティング ノードへのジャンプが許可されると、プロセスとしてのワークフローの規範性と制限性が著しく損なわれます。テンプレート。
2. 自分を除外したり、自分にジャンプしたり、無限ループする必要があります...
3. 自動処理リンク (メール送信など) など、後からノードの種類を拡張する必要があります。状況に応じて拡張でき、許可されます。ターゲットノードになります。

さらに、ここには別の場所があります。処理リンクについては、それが副署名である場合、ビジネスの観点からは、このリンクへのフォールバックまたはジャンプを許可する必要がありますが、Camunda の基礎となる関数を呼び出すとエラーが報告されます。 API. ここでは単なる言及にすぎず、次の章でこの問題について具体的に説明します。

バックエンドの実装

エンティティ構成

リンク構成のロールバック リンクとジャンプ リンクのエンティティ属性は、実際にはまったく同じです。同じデータベース テーブルがストレージに使用される場合、ロールバックとジャンプを区別するためにエンティティに追加の属性が必要です。追加のフィールドは次のとおりです。ライブラリテーブルに追加され、コードが追加論理判断されます。
プラットフォームのローコード構成の高効率に基づいて、最初にフォールバック リンクの構成エンティティを実現し、次に新しい関数をコピーすることでジャンプ リンクの構成を実現します。
以下は、フォールバック リンクの構成エンティティ情報属性リストです
画像.png

画像.png

モデルの解析と永続化

プロセス モデルが変換されると、読み取りリンクは config 属性の下の backNodeList 属性と連携します。

    private void configBackNodeList(String tempVersion, String id,String configString) {
    
    
        if(StringUtils.isNoneBlank(configString)) {
    
    

            List<WorkflowBackNodeConfig> backNodeList = new ArrayList<>();
            JSONArray jsonArray = JSON.parseArray(configString);
            for (int i = 0; i < jsonArray.size(); i++) {
    
    
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                WorkflowBackNodeConfig entity = new WorkflowBackNodeConfig();
                entity.setTargetNodeId(jsonObject.getString("id"));
                entity.setTargetNodeName(jsonObject.getString("name"));
                backNodeList.add(entity);
            }
            workflowBackNodeConfigService.updateConfig(tempVersion, id, backNodeList);
        }

    }

サービスメソッドupdateConfigは以下の通り、コンフィグレーションを一旦クリアしてから作成するモードを採用しており、ちなみにノード変更で残ったゴミデータをクリアします。

    @Override
    public void updateConfig(String processDefinitionId, String nodeId, List<WorkflowBackNodeConfig> jumpNodeList) {
    
    
        // 先清空配置
        QueryWrapper<WorkflowBackNodeConfig> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda().eq(WorkflowBackNodeConfig::getProcessDefinitionId,processDefinitionId)
                .eq(WorkflowBackNodeConfig::getNodeId,nodeId);
        remove(queryWrapper);
        // 后生成配置
        int orderNo=0;
        for(WorkflowBackNodeConfig entity:jumpNodeList){
    
    
            orderNo++;
            entity.setProcessDefinitionId(processDefinitionId);
            entity.setNodeId(nodeId);
            entity.setOrderNo(StringUtils.leftPad(String.valueOf(orderNo),2,"0"));
            add(entity);
        }

    }

開発プラットフォーム情報

プラットフォーム名: One Two Three 開発プラットフォーム
紹介: エンタープライズ レベルの総合開発プラットフォーム
設計情報: csdn コラム
オープン ソース アドレス: Gitee
オープン ソース プロトコル: MIT
オープン ソースは簡単ではありません。お気に入り、いいね、コメントへようこそ。

おすすめ

転載: blog.csdn.net/seawaving/article/details/132508061