xiangning 5332ff3867 refactor(monitoring): 重构监控模块数据库表名和查询处理
- 将监控模块表前缀从 mon_ 改为 b_
- 为工作流审批任务处理器添加流程引擎图加载逻辑
- 移除外部系统相关DTO和查询类的直接引用改为查询对象模式
- 为脚本执行服务添加模块程序集诊断日志
- 为分享表单提交功能增加密码验证支持
- 集成脚本模块数据库迁移支持
- 更新通知服务测试以兼容IOptionsMonitor接口变化
2026-07-19 13:09:43 +08:00

94 lines
4.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text.Json;
using Workflow.Domain.Engine;
using Workflow.Domain.Entities;
namespace Workflow.Application.Engine;
/// <summary>
/// WorkflowGraph(X6 JSON 强类型)与 WorkflowNode/WorkflowEdge(领域实体)的双向适配层。
/// 使 ProcessEngine 从「读关系表」切换到「读 X6 JSON 快照」时,下游所有 Process*Async 方法零改动——
/// 引擎启动时把图映射成内存实体集合,FindNodeAsync/GetOutgoingEdges 等改查内存集合即可。
///
/// ID 兼容约定(见技术方案文档 5.7):X6 节点/边 id 用纯 Guid 字符串(前端 crypto.randomUUID() 生成),
/// 不带 "node_" 前缀,保证 Guid ↔ string 无损往返(WorkflowToken.NodeId 是 Guid)。
/// </summary>
public static class WorkflowGraphAdapter
{
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
/// <summary>把 WorkflowGraph 映射成内存 WorkflowNode 集合(供 ProcessEngine 查询)。</summary>
public static List<WorkflowNode> ToNodes(WorkflowGraph graph, Guid definitionId)
{
var nodes = new List<WorkflowNode>(graph.Nodes.Count);
foreach (var gn in graph.Nodes)
{
var nodeType = WorkflowShapeMap.ToNodeType(gn.Shape);
if (nodeType is null) continue; // 未知 shape 跳过(发布校验已拦截)
nodes.Add(new WorkflowNode
{
Id = ParseGuid(gn.Id),
DefinitionId = definitionId,
NodeType = nodeType.Value,
Name = gn.GetTitle() ?? nodeType.Value.ToString(),
// Config:把 data 对象序列化回字符串,复用现有 NodeConfigParser 解析链
Config = gn.Data is { ValueKind: JsonValueKind.Object or JsonValueKind.Array } data
? data.GetRawText()
: null,
// 审批节点绑定的表单定义 id(钉钉式树编译进 data.formDefinitionId)。
// ApproveTaskCommandHandler.SaveNodeFormDataAsync 据此加载表单做字段权限校验。
FormDefinitionId = TryGetFormDefinitionId(gn.Data),
PositionX = (int)Math.Round(gn.X),
PositionY = (int)Math.Round(gn.Y),
// 审计字段填充非空默认值(实体是 IFullAudit,避免下游 null 引用)
CreatedBy = "system",
UpdatedBy = "system",
});
}
return nodes;
}
/// <summary>把 WorkflowGraph 映射成内存 WorkflowEdge 集合(供 ProcessEngine 查询)。</summary>
public static List<WorkflowEdge> ToEdges(WorkflowGraph graph, Guid definitionId)
{
var edges = new List<WorkflowEdge>(graph.Edges.Count);
foreach (var ge in graph.Edges)
{
var sourceId = ParseGuid(ge.Source.Cell);
var targetId = ParseGuid(ge.Target.Cell);
if (sourceId == Guid.Empty || targetId == Guid.Empty) continue;
edges.Add(new WorkflowEdge
{
Id = ParseGuid(ge.Id),
DefinitionId = definitionId,
SourceNodeId = sourceId,
TargetNodeId = targetId,
EdgeType = ge.GetEdgeType(),
Label = null, // 引擎不读 Label
Condition = ge.GetCondition(),
Order = ge.GetOrder(),
CreatedBy = "system",
UpdatedBy = "system",
});
}
return edges;
}
/// <summary>纯 Guid 字符串解析为 Guid;非法返回 Guid.Empty(适配层会跳过)。</summary>
private static Guid ParseGuid(string? id)
{
if (string.IsNullOrWhiteSpace(id)) return Guid.Empty;
return Guid.TryParse(id, out var g) ? g : Guid.Empty;
}
/// <summary>从节点 data.formDefinitionId(钉钉式树编译产物)提取表单定义 id。</summary>
private static Guid? TryGetFormDefinitionId(System.Text.Json.JsonElement? data)
{
if (data is not { ValueKind: System.Text.Json.JsonValueKind.Object } obj) return null;
if (!obj.TryGetProperty("formDefinitionId", out var prop)) return null;
var raw = prop.ValueKind == System.Text.Json.JsonValueKind.String ? prop.GetString() : null;
return Guid.TryParse(raw, out var g) ? g : null;
}
}