using System.Text.Json; using System.Text.Json.Serialization; using Workflow.Domain.Enums; namespace Workflow.Domain.Engine; /// /// X6 graph 的强类型模型,与 X6 toJSON/fromJSON 原生格式兼容。 /// 替代裸 JsonDocument,供 ProcessEngine / 校验器 / 迁移脚本统一读写。 /// 顶层结构为 { nodes: [], edges: [] }(X6 fromJSON 支持的两种等价格式之一)。 /// public sealed class WorkflowGraph { [JsonPropertyName("nodes")] public List Nodes { get; set; } = new(); [JsonPropertyName("edges")] public List Edges { get; set; } = new(); /// 空图工厂(容错用)。 public static WorkflowGraph Empty() => new(); } /// /// X6 节点。shape 决定渲染器并反推 NodeType(见 ); /// 业务配置统一进 data;x/y/width/height/ports 为几何与渲染信息。 /// public sealed class GraphNode { [JsonPropertyName("id")] public string Id { get; set; } = string.Empty; [JsonPropertyName("shape")] public string Shape { get; set; } = string.Empty; [JsonPropertyName("x")] public double X { get; set; } [JsonPropertyName("y")] public double Y { get; set; } [JsonPropertyName("width")] public double? Width { get; set; } [JsonPropertyName("height")] public double? Height { get; set; } [JsonPropertyName("angle")] public double? Angle { get; set; } [JsonPropertyName("visible")] public bool? Visible { get; set; } /// 业务数据(节点配置)。替代旧 WorkflowNode.Config 字符串字段。 [JsonPropertyName("data")] public JsonElement? Data { get; set; } /// 显示名(对应旧 WorkflowNode.Name)。 public string? GetTitle() => Data.TryGetString("title"); [JsonPropertyName("ports")] public JsonElement? Ports { get; set; } } /// /// X6 边。source/target 用 { cell, port } 结构;几何信息(vertices/router/connector)放顶层; /// 业务字段(edgeType/condition/order)放 data。 /// public sealed class GraphEdge { [JsonPropertyName("id")] public string Id { get; set; } = string.Empty; [JsonPropertyName("shape")] public string? Shape { get; set; } [JsonPropertyName("source")] public GraphEndpoint Source { get; set; } = new(); [JsonPropertyName("target")] public GraphEndpoint Target { get; set; } = new(); /// 业务数据:edgeType / condition / order。 [JsonPropertyName("data")] public JsonElement? Data { get; set; } [JsonPropertyName("label")] public JsonElement? Label { get; set; } [JsonPropertyName("vertices")] public List? Vertices { get; set; } [JsonPropertyName("router")] public JsonElement? Router { get; set; } [JsonPropertyName("connector")] public JsonElement? Connector { get; set; } /// 边类型(Normal=0/Approved=1/Rejected=2)。缺省为 Normal。 public EdgeType GetEdgeType() => Data.TryGetInt32("edgeType") is { } v ? (EdgeType)v : EdgeType.Normal; /// 条件表达式(Condition/ExclusiveGateway 出边)。 public string? GetCondition() => Data.TryGetString("condition"); /// 分支评估顺序(值小优先)。 public int GetOrder() => Data.TryGetInt32("order") ?? 0; } public sealed class GraphEndpoint { /// 节点 id(对应 GraphNode.Id)。 [JsonPropertyName("cell")] public string? Cell { get; set; } /// 端口 id(top/right/bottom/left)。 [JsonPropertyName("port")] public string? Port { get; set; } } public sealed class GraphPoint { [JsonPropertyName("x")] public double X { get; set; } [JsonPropertyName("y")] public double Y { get; set; } } /// /// JsonElement? 安全取值扩展:统一处理 Nullable 解构与 ValueKind 校验, /// 避免 WorkflowGraph 各 getter 重复 null 检查。 /// internal static class GraphJsonExtensions { public static string? TryGetString(this JsonElement? element, string name) => element is { ValueKind: JsonValueKind.Object } el && el.TryGetProperty(name, out var p) && p.ValueKind == JsonValueKind.String ? p.GetString() : null; public static int? TryGetInt32(this JsonElement? element, string name) => element is { ValueKind: JsonValueKind.Object } el && el.TryGetProperty(name, out var p) && (p.ValueKind == JsonValueKind.Number || p.ValueKind == JsonValueKind.String) && p.TryGetInt32(out var n) ? n : null; }