套打.二开案例.审批路线合并节点的处理人、处理意见

栏目:云星空知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

套打.二开案例.审批路线合并节点的处理人、处理意见

【场景】审批路线合并节点的处理人、处理意见 【说明】审批路线目前套打严格按照工作流流程界面的数据打印,如果只是简单调整人名、过滤,只需要简单修改每一行数据包; 一旦效果跟工作流流程界面的需求差异非常大时,只能自行实现工作流审批路线的数据获取进行处理,最终套打配置的过滤、动态字段、签章逻辑都需要在插件中自行计算实现 工作流数据逻辑[【套打】套打中审批路线、流程节点二开指南](https://vip.kingdee.com/link/s/lJxHn) 【案例】采购合同,前加签、处理人、后加签 合并为一行打印 (0)数据准备 ![image.webp](/download/0100e187970717a64ba8aca8cf19649d7293.webp) 没有配置插件前的打印效果 ![image.webp](/download/0100c057dc7d127c409f8301264e0a496081.webp) (1)配置插件调整审批路线的数据,仅提供思路和案例,部分细节需要自行调整;部分接口需要工作流模块的同事提供 ![image.webp](/download/0100829c08dc33c1441bba1d275bc9921df4.webp) ```csharp using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.NotePrint; using Kingdee.BOS.NotePrinting.Framework.Object; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.Orm.Metadata.DataEntity; using Kingdee.BOS.Util; using Kingdee.BOS.Workflow.Kernel; using Kingdee.BOS.Workflow.Models.Chart; using Kingdee.BOS.Workflow.Models.NotePrint; using Kingdee.BOS.Workflow.ServiceHelper; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DynamicFormPlugIn.NotePrint { [System.ComponentModel.Description("审批路线二开调整")] [Kingdee.BOS.Util.HotUpdate] public class NotePrintPlugIn_WorkFlowApproveLine : AbstractDynamicFormPlugIn { public override void OnPrepareNotePrintData(PreparePrintDataEventArgs e) { if (!string.Equals(e.NotePrintTplId, "6690568e-3a24-464d-aa7b-deb6bfdbe874", StringComparison.OrdinalIgnoreCase)) return; if (e.DataObjects == null) return; //工作流数据源默认以workflow作为数据源前缀 if (!e.DataSourceId.StartsWith("workflow.")) return; string workflowBillId = e.BillIds.FirstOrDefault(); if (workflowBillId.IsNullOrEmptyOrWhiteSpace()) return; string[] dataSourceArgs = e.DataSourceId.Split('.'); if (dataSourceArgs.Length < 2) return; //流程设计Id,判断是审批路线取数还是流程节点取数 string procDefId = dataSourceArgs[1]; if (procDefId.Equals("approveLine")) { //审批路线取数 var dataObjs = GetWorkFlowData(workflowBillId, e.DynamicObjectType); e.DataObjects = dataObjs.ToArray(); } else { //流程节点取数 } } /* * 套打的审批路线 数据包信息非常少,如果只是替换名字的逻辑可以直接使用 * 如果需要将多个节点合并,判断是否加签处理,都需要完全二开把审批路线替换掉 * 这里关联的工作流干预接口需要自行根据业务场景调整 */ /// <summary> /// 审批路线-处理人签章 /// </summary> internal const string KeyESignature = "FReceiverESignature"; /// <summary> /// 审批路线-处理人签章是否有权 /// </summary> internal const string KeyESignaturePermission = "FESignaturePermission"; /// <summary> /// 获取工作流审批路线 套打使用的数据包 /// </summary> /// <param name="billId"></param> /// <param name="workFlowObjType"></param> /// <returns></returns> private DynamicObjectCollection GetWorkFlowData(string billId, DynamicObjectType workFlowObjType) { // <0>根据单据内码、表单标识 获取流程实例id string formId = this.View.BillBusinessInfo.GetForm().Id; string processId = Kingdee.BOS.Workflow.ServiceHelper.WorkflowChartServiceHelper.GetProcInstIdByBillInst(Context, formId, billId); if (processId.IsNullOrEmptyOrWhiteSpace()) return null; // <1> todo 重新审核是否加载审批路线数据 // <2> 获取待办列表和已办的所有信息 List<ApproveRouteInfoObj> approveRouteInfoAdapterList = new List<ApproveRouteInfoObj>(); List<ChartActivityInfo> routeCollection = Kingdee.BOS.Workflow.ServiceHelper.WorkflowChartServiceHelper.GetProcessRouter(Context, processId); NotePrintEsignatureValidation validation = Kingdee.BOS.Workflow.ServiceHelper.ProcManageServiceHelper.GetEsignatureValidationByBillId(Context, formId, billId); foreach (ChartActivityInfo activityDetail in routeCollection) { var curApproveRouteList = CollectApproveRouteInfo(activityDetail); // <3> todo 自行实现过滤审批路线的逻辑 //if (!string.IsNullOrWhiteSpace(DataSource.FilterString)) //{ // curApproveRouteList = GetApproveRouteInfoByFilter(DataSource.FilterString, curApproveRouteList); //} if (curApproveRouteList == null) continue; approveRouteInfoAdapterList.AddRange(curApproveRouteList); } var result = FillDynamicObject(validation, approveRouteInfoAdapterList, workFlowObjType); return result; } /// <summary> /// 根据工作流审批路线信息生成套打对象 /// </summary> /// <param name="activityDetail"></param> /// <returns></returns> private List<ApproveRouteInfoObj> CollectApproveRouteInfo(ChartActivityInfo activityDetail) { List<ApproveRouteInfoObj> approveRouteInfoList = new List<ApproveRouteInfoObj>(); ApproveRouteInfo approveRouteInfoMain = new ApproveRouteInfo() { ActivityName = activityDetail.ActivityName, SourceActivityName = activityDetail.SourceActivityName, ActivityId = activityDetail.ActivityId, }; switch ((int)activityDetail.ActivityStateType) { case 1: case 3: case 5: case 6: approveRouteInfoMain.StatuDesc = "完成"; break; case 2: approveRouteInfoMain.StatuDesc = "当前"; break; case 4: approveRouteInfoMain.StatuDesc = "出错"; break; default: approveRouteInfoMain.StatuDesc = string.Empty; break; } for (int j = 0; j < activityDetail.ActionDetails.Count; j++) //第一次添加审批明细的时候在节点的同一行记录里,剩余的在新增行添加 { //已完成节点里面只展现已完成的待办任务信息 if (activityDetail.ActivityStateType != MapStateResult.Idled && !activityDetail.ActionDetails[j].IsCompleted) { continue; } ChartActionInfo action = activityDetail.ActionDetails[j]; #region ApproveRouteInfoDetail ApproveRouteInfoObj approveRouteInfoAdapter = CopyApproveRouteInfo(approveRouteInfoMain, activityDetail, action); var approveRouteInfo = approveRouteInfoAdapter.ApproveRouteInfo; approveRouteInfo.Title = action.Title; approveRouteInfo.ReceiverName = action.ReceiverName; approveRouteInfo.ActionResult = action.ActionResult; approveRouteInfo.DisPosition = action.DisPosition; approveRouteInfo.CompletedTime = action.CompleteTime; approveRouteInfo.ConsignNames = action.ConsignNames; approveRouteInfo.ActionResultId = action.ActionResultId; approveRouteInfo.Receivers = action.Receivers; #endregion ApproveRouteInfo //绑定工作流实体和套打实体的关系 approveRouteInfoList.Add(approveRouteInfoAdapter); } return approveRouteInfoList; } /// <summary> /// 得到一个计算用的审批路线对象 /// </summary> /// <param name="srcInfo"></param> /// <param name="activityInfo"></param> /// <param name="actionInfo"></param> /// <returns></returns> private ApproveRouteInfoObj CopyApproveRouteInfo(ApproveRouteInfo srcInfo, ChartActivityInfo activityInfo, ChartActionInfo actionInfo) { ApproveRouteInfo tgtInfo = new ApproveRouteInfo() { ActivityName = srcInfo.ActivityName, SourceActivityName = srcInfo.SourceActivityName, ActivityId = srcInfo.ActivityId, StatuDesc = srcInfo.StatuDesc, }; return new ApproveRouteInfoObj() { ApproveRouteInfo = tgtInfo, ActivityInfo = activityInfo, ActionInfo = actionInfo }; } /// <summary> /// 根据套打对象生成打印的数据包 /// </summary> /// <param name="validation"></param> /// <param name="objList"></param> /// <param name="approveType"></param> /// <returns></returns> private DynamicObjectCollection FillDynamicObject(NotePrintEsignatureValidation validation, List<ApproveRouteInfoObj> objList, DynamicObjectType approveType) { HashSet<string> activityInstIdSet = new HashSet<string>(); List<Tuple<DynamicObject, long>> esignUserDataList = new List<Tuple<DynamicObject, long>>(); bool useEsignature; //当前流程节点是否启用电子签章审批 string strUserId; //处理人字符串 long userId; //处理人内码 Dictionary<string, WorkflowNodeApproveInfo> nodeAprove = new Dictionary<string, WorkflowNodeApproveInfo>(); Dictionary<string, DynamicObject> instObj = new Dictionary<string, DynamicObject>(); Func<ApproveRouteInfo, ApproveRouteInfoObj, DynamicObject> fillWorkflowAct = (approveRouteInfo, infoObj) => { DynamicObject workFlowDataObj = null; useEsignature = validation != null && validation.UseEsignatureActIdFowrad.ContainsKey(approveRouteInfo.ActivityId); //第一次添加审批明细的时候在节点的同一行记录里,剩余的在新增行添加 //调整代码结构后,使用节点Id+动作实例Id去重 string activityKey = string.Format("{0}_{1}", approveRouteInfo.ActivityId, infoObj.ActivityInfo.ActInstId); //不是开始节点,检查是待办还是不是待办;有审批意见的待办才打印 if (approveRouteInfo.ActivityId != 0) { if (approveRouteInfo.ActionResultId.IsNullOrEmptyOrWhiteSpace()) return workFlowDataObj; } /* * 核心实现逻辑: * 将同一个节点的同一个实例的信息合并到一起 * */ List<long> addSignedReceivers = AssignmentServiceHelper.GetAddSignedReceiverIdByAssignId(this.Context, infoObj.ActionInfo.AssignId); strUserId = approveRouteInfo.Receivers.Split(',')[0]; if (!long.TryParse(strUserId, out userId)) return workFlowDataObj; WorkflowNodeApproveInfo nodeApproveInfo = null; if(!nodeAprove.TryGetValue(activityKey, out nodeApproveInfo)) { nodeApproveInfo = new WorkflowNodeApproveInfo(); nodeAprove[activityKey] = nodeApproveInfo; } WorkflowApproveItem approveItem = new WorkflowApproveItem() { UserId = userId, UserName = approveRouteInfo.ReceiverName, DisPosition = approveRouteInfo.DisPosition, }; // 判断是否加签人 bool returnObj = false; if (addSignedReceivers.Contains(userId)) { if (!nodeApproveInfo.ApproveItem.Any()) { //如果没有处理人意见,那么就是前加签 nodeApproveInfo.BeforeApprove.Add(approveItem); } else { //如果有处理人意见,那么就是后加签 nodeApproveInfo.AfterApprove.Add(approveItem); workFlowDataObj = instObj[activityKey]; } } else { //处理人意见 nodeApproveInfo.ApproveItem.Add(approveItem); if(instObj.TryGetValue(activityKey, out workFlowDataObj)) { } else { workFlowDataObj = new DynamicObject(approveType); instObj[activityKey] = workFlowDataObj; if (!activityInstIdSet.Contains(activityKey)) { workFlowDataObj["ac_approve_FActivityName"] = approveRouteInfo.ActivityName; workFlowDataObj["ac_approve_FActivityStatu"] = approveRouteInfo.StatuDesc; workFlowDataObj["ac_approve_FStartActivity"] = approveRouteInfo.SourceActivityName; workFlowDataObj["ac_approve_FTargetActivity"] = approveRouteInfo.ActivityName; activityInstIdSet.Add(activityKey); } workFlowDataObj["ac_approve_FActionName"] = approveRouteInfo.Title; workFlowDataObj["ac_approve_FReceiverName"] = approveRouteInfo.ReceiverName; workFlowDataObj["ac_approve_FActionResult"] = approveRouteInfo.ActionResult; workFlowDataObj["ac_approve_FDisposition"] = approveRouteInfo.DisPosition; workFlowDataObj["ac_approve_FCompletedTime"] = approveRouteInfo.CompletedTime; workFlowDataObj["ac_approve_FConsignNames"] = approveRouteInfo.ConsignNames; workFlowDataObj["ac_approve_" + KeyESignaturePermission] = "0"; returnObj = true; } } if (workFlowDataObj != null) { // 根据加签信息调整处理人,处理意见结果 workFlowDataObj["ac_approve_FReceiverName"] = nodeApproveInfo.GetAllUserName(); workFlowDataObj["ac_approve_FDisposition"] = nodeApproveInfo.GetAllUserDisPosition(); } if (returnObj) return workFlowDataObj; return null; #region 电子签章逻辑 //if (useEsignature && approveRouteInfo.ActionResultId != null && // validation.UseEsignatureActIdFowrad[approveRouteInfo.ActivityId].Contains( // approveRouteInfo.ActionResultId)) //启用电子签章且为正向节点(避免驳回也打印电子签章) //{ // if (approveRouteInfo.Receivers == null) // return; // strUserId = approveRouteInfo.Receivers.Split(',')[0]; // if (!long.TryParse(strUserId, out userId)) // return; // workFlowDataObj["ac_approve_" + KeyESignaturePermission] = "1"; // string ormKey = "ac_approve_" + KeyESignature; // if (workFlowDataObj.DynamicObjectType.Properties.ContainsKey(ormKey) && infoObj.ActionInfo != null && !infoObj.ActionInfo.MobileEsignature.IsEmpty()) // { // workFlowDataObj[ormKey] = infoObj.ActionInfo.MobileEsignature; // } // esignUserDataList.Add(new Tuple<DynamicObject, long>(workFlowDataObj, userId)); //} #endregion }; foreach (var approveRouteInfoAdapter in objList) { DynamicObject workFlowDataObj = fillWorkflowAct(approveRouteInfoAdapter.ApproveRouteInfo, approveRouteInfoAdapter); if (workFlowDataObj == null) continue; approveRouteInfoAdapter.DataObject = workFlowDataObj; } // todo 没有动态字段的逻辑,如果需要的话只能自行计算 //CalcDynamicField(objList); DynamicObjectCollection result = new DynamicObjectCollection(approveType); foreach (var obj in objList) { if (obj.DataObject == null) continue; result.Add(obj.DataObject); } // todo 处理人签章逻辑,需要的话根据当前节点用户id加载用户图片 //AppendApproveLineESignature(esignUserDataList); return result; } public class WorkflowNodeApproveInfo { public List<WorkflowApproveItem> BeforeApprove = new List<WorkflowApproveItem>(); public List<WorkflowApproveItem> ApproveItem = new List<WorkflowApproveItem>(); public List<WorkflowApproveItem> AfterApprove = new List<WorkflowApproveItem>(); public string GetAllUserName() { StringBuilder builder = new StringBuilder(); if (BeforeApprove.Any()) { builder.Append("前加签:"); builder.Append(string.Join(";", BeforeApprove.Select(x => x.UserName))); builder.AppendLine(); } if (ApproveItem.Any()) { builder.Append("常规处理:"); builder.Append(string.Join(";", ApproveItem.Select(x => x.UserName))); builder.AppendLine(); } if (AfterApprove.Any()) { builder.Append("后加签:"); builder.Append(string.Join(";", AfterApprove.Select(x => x.UserName))); builder.AppendLine(); } return builder.ToString(); } public string GetAllUserDisPosition() { StringBuilder builder = new StringBuilder(); if (BeforeApprove.Any()) { builder.Append("前加签:"); builder.Append(string.Join(";", BeforeApprove.Select(x => x.DisPosition))); builder.AppendLine(); } if (ApproveItem.Any()) { builder.Append("常规处理:"); builder.Append(string.Join(";", ApproveItem.Select(x => x.DisPosition))); builder.AppendLine(); } if (AfterApprove.Any()) { builder.Append("后加签:"); builder.Append(string.Join(";", AfterApprove.Select(x => x.DisPosition))); builder.AppendLine(); } return builder.ToString(); } } public class WorkflowApproveItem { public long UserId; public string UserName; public string DisPosition; } } } ``` (2)效果 ![image.webp](/download/01004ae1313bc34447a58830241b4e782588.webp)

套打.二开案例.审批路线合并节点的处理人、处理意见

【场景】审批路线合并节点的处理人、处理意见【说明】审批路线目前套打严格按照工作流流程界面的数据打印,如果只是简单调整人名、过滤,只...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息