using System.Diagnostics; using System.Text.Json; using Admin.NET.Core; using Admin.NET.Plugin.AiDOP.Service; using Admin.NET.Plugin.ApprovalFlow; using Admin.NET.Plugin.ApprovalFlow.Service; using Yitter.IdGenerator; using ApprovalFlowEntity = Admin.NET.Plugin.ApprovalFlow.ApprovalFlow; namespace Admin.NET.Plugin.AiDOP.Infrastructure; /// /// 智慧诊断改善计划正式审批流与角色基线。 /// public static class AidopImprovementApprovalSeed { public static void EnsureSeed(ISqlSugarClient db) { try { db.CodeFirst.InitTables( typeof(ApprovalBizType), typeof(ApprovalFlowEntity), typeof(ApprovalFlowVersion)); EnsureBizType(db); EnsureBaselineRoles(db); EnsurePublishedFlow(db); } catch (Exception ex) { Trace.TraceWarning("Ai-DOP improvement approval seed: " + ex); } } public static void EnsureBaselineRoles(ISqlSugarClient db, long? onlyTenantId = null) { var tenantIds = onlyTenantId is > 0 ? new List { onlyTenantId.Value } : db.Queryable() .ClearFilter() .Where(x => x.Id > 1 && x.Id != SqlSugarConst.DefaultTenantId) .Select(x => x.Id) .ToList(); var now = DateTime.Now; foreach (var tenantId in tenantIds.Where(x => x > 1 && x != SqlSugarConst.DefaultTenantId).Distinct()) { foreach (var (code, name, orderNo) in SmartOpsImprovementApprovalRules.BaselineRoles) { var exists = db.Queryable() .ClearFilter() .Any(r => r.TenantId == tenantId && r.Code == code); if (exists) continue; db.Insertable(new SysRole { Id = YitIdHelper.NextId(), TenantId = tenantId, Name = name, Code = code, OrderNo = orderNo, DataScope = DataScopeEnum.Self, Status = StatusEnum.Enable, Remark = "智慧诊断改善计划审批角色基线", CreateTime = now, }).ExecuteCommand(); } } } private static void EnsureBizType(ISqlSugarClient db) { var exists = db.Queryable() .Any(x => x.Code == SmartOpsImprovementBizHandler.BizTypeCode); if (exists) return; db.Insertable(new ApprovalBizType { Id = YitIdHelper.NextId(), Code = SmartOpsImprovementBizHandler.BizTypeCode, Name = "智慧诊断改善计划", Remark = "智慧运营诊断问题生成的改善计划审批", IsEnabled = true, CreateTime = DateTime.Now, UpdateTime = DateTime.Now, }).ExecuteCommand(); } private static void EnsurePublishedFlow(ISqlSugarClient db) { var orgIds = db.Queryable() .Select(x => x.Id) .ToList() .Where(x => x > 0) .Distinct() .ToList(); if (orgIds.Count == 0) orgIds.Add(0); var now = DateTime.Now; var flowJson = BuildFormalFlowJson(); foreach (var orgId in orgIds) { var existing = db.Queryable() .Where(x => x.BizType == SmartOpsImprovementBizHandler.BizTypeCode && x.OrgId == orgId && !x.IsDelete) .OrderByDescending(x => x.IsPublished) .OrderByDescending(x => x.Version) .First(); if (existing == null) { InsertFlow(db, orgId, flowJson, 2, now); continue; } if (!SmartOpsImprovementApprovalRules.IsLegacyInitiatorFallback(existing.FlowJson) && existing.FlowJson != null && existing.FlowJson.Contains(SmartOpsImprovementApprovalRules.DeptHeadRole, StringComparison.Ordinal)) { if (!existing.IsPublished) { existing.IsPublished = true; existing.UpdateTime = now; db.Updateable(existing).ExecuteCommand(); } continue; } existing.FlowJson = flowJson; existing.Version = Math.Max(existing.Version, 1) + 1; existing.IsPublished = true; existing.Status = 1; existing.Remark = "正式流程:黄/红/跨部门网关,按角色解析审批人"; existing.UpdateTime = now; db.Updateable(existing).ExecuteCommand(); db.Insertable(new ApprovalFlowVersion { Id = YitIdHelper.NextId(), FlowId = existing.Id, Version = existing.Version, FlowJson = existing.FlowJson, FormJson = existing.FormJson, PublishTime = now, PublisherName = "系统升级", CreateTime = now, UpdateTime = now, }).ExecuteCommand(); } } private static void InsertFlow(ISqlSugarClient db, long orgId, string flowJson, int version, DateTime now) { var flow = new ApprovalFlowEntity { Id = YitIdHelper.NextId(), Code = $"SOI_{orgId}", Name = "智慧诊断改善计划审批", BizType = SmartOpsImprovementBizHandler.BizTypeCode, FormJson = "{}", FlowJson = flowJson, Status = 1, Remark = "正式流程:黄/红/跨部门网关,按角色解析审批人", Version = version, IsPublished = true, OrgId = orgId, CreateTime = now, UpdateTime = now, }; db.Insertable(flow).ExecuteCommand(); db.Insertable(new ApprovalFlowVersion { Id = YitIdHelper.NextId(), FlowId = flow.Id, Version = flow.Version, FlowJson = flow.FlowJson, FormJson = flow.FormJson, PublishTime = now, PublisherName = "系统初始化", CreateTime = now, UpdateTime = now, }).ExecuteCommand(); } public static string BuildFormalFlowJson() { var item = new ApprovalFlowItem { Nodes = new List { Node("start", "bpmn:startEvent", 80, 200, "开始"), new() { Id = "routeGw", Type = "bpmn:exclusiveGateway", X = 220, Y = 200, Properties = new FlowProperties { NodeName = "问题分级", Conditions = new List { new() { TargetNodeId = "deptHeadYellow", Expression = "route == yellow", Label = "黄色" }, new() { TargetNodeId = "deptHeadRed", Expression = "route == red", Label = "红色" }, new() { TargetNodeId = "deptHeadGlobal", Expression = "", Label = "跨部门/S9", IsDefault = true }, }, }, Text = new FlowTextItem { X = 220, Y = 234, Value = "问题分级" }, }, RoleNode("deptHeadYellow", 420, 80, "责任部门负责人", SmartOpsImprovementApprovalRules.DeptHeadRole), RoleNode("deptHeadRed", 420, 200, "责任部门负责人", SmartOpsImprovementApprovalRules.DeptHeadRole), RoleNode("opsRed", 620, 200, "运营负责人", SmartOpsImprovementApprovalRules.OpsOwnerRole), RoleNode("deptHeadGlobal", 420, 320, "责任部门负责人", SmartOpsImprovementApprovalRules.DeptHeadRole), RoleNode("moduleGlobal", 620, 320, "模块负责人", SmartOpsImprovementApprovalRules.ModuleOwnerRole), RoleNode("opsGlobal", 820, 320, "运营负责人", SmartOpsImprovementApprovalRules.OpsOwnerRole), Node("end", "bpmn:endEvent", 1020, 200, "结束"), }, Edges = new List { BuildEdge("e-start-gw", "start", "routeGw", 120, 200, 180, 200), BuildEdge("e-gw-y", "routeGw", "deptHeadYellow", 250, 180, 380, 80), BuildEdge("e-gw-r", "routeGw", "deptHeadRed", 260, 200, 380, 200), BuildEdge("e-gw-g", "routeGw", "deptHeadGlobal", 250, 220, 380, 320), BuildEdge("e-y-end", "deptHeadYellow", "end", 460, 80, 980, 180), BuildEdge("e-r-ops", "deptHeadRed", "opsRed", 460, 200, 580, 200), BuildEdge("e-ops-end", "opsRed", "end", 660, 200, 980, 200), BuildEdge("e-g-mod", "deptHeadGlobal", "moduleGlobal", 460, 320, 580, 320), BuildEdge("e-mod-ops", "moduleGlobal", "opsGlobal", 660, 320, 780, 320), BuildEdge("e-gops-end", "opsGlobal", "end", 860, 320, 980, 220), } }; return JsonSerializer.Serialize(item); } private static ApprovalFlowNodeItem Node(string id, string type, float x, float y, string name) => new() { Id = id, Type = type, X = x, Y = y, Properties = new FlowProperties { NodeName = name }, Text = new FlowTextItem { X = x, Y = y + 34, Value = name }, }; private static ApprovalFlowNodeItem RoleNode(string id, float x, float y, string name, string roleCode) => new() { Id = id, Type = "bpmn:userTask", X = x, Y = y, Properties = new FlowProperties { NodeName = name, ApproverType = nameof(ApproverTypeEnum.Role), ApproverIds = roleCode, ApproverNames = name, MultiApproveMode = "Any", TimeoutHours = 72, TimeoutAction = "Notify", }, Text = new FlowTextItem { X = x, Y = y + 34, Value = name }, }; private static ApprovalFlowEdgeItem BuildEdge(string id, string source, string target, float sx, float sy, float ex, float ey) { return new ApprovalFlowEdgeItem { Id = id, Type = "bpmn:sequenceFlow", SourceNodeId = source, TargetNodeId = target, StartPoint = new FlowEdgePointItem { X = sx, Y = sy }, EndPoint = new FlowEdgePointItem { X = ex, Y = ey }, Properties = new FlowProperties(), PointsList = new List { new() { X = sx, Y = sy }, new() { X = ex, Y = ey }, }, }; } }