using ce.autofac.extension;
using Infrastructure;
using Infrastructure.Extensions;
using Infrastructure.Helpers;
using Microsoft.Extensions.Configuration;
using OpenAuth.App.Base;
using OpenAuth.App.BasicQueryService;
using OpenAuth.App.Config;
using OpenAuth.App.Interface;
using OpenAuth.App.Request;
using OpenAuth.Repository;
using OpenAuth.Repository.Core;
using OpenAuth.Repository.Domain;
using SqlSugar;
using System.Data;
using System.Linq;
using Newtonsoft.Json;
using OpenAuth.App.BaseApp.Jobs;
using System.Text;
using DocumentFormat.OpenXml.Spreadsheet;
using Infrastructure.Utilities;
using OpenAuth.App.BaseApp.Base;
using System.Diagnostics;
using NPOI.Util;

namespace OpenAuth.App
{
    public partial class WFProcessApp : SqlSugarBaseApp<WFProcess, SugarDbContext>
    {
        ISqlSugarClient client;
        UserManager userManager;
        PositionManager positionManager;
        IConfiguration _configuration;
        OpenJobApp _job;
        public WFProcessApp(SqlSugar.ISugarUnitOfWork<SugarDbContext> unitWork,
            SqlSugar.ISimpleClient<WFProcess> repository,
            IAuth auth,
            UserManager userManager,
            OpenJobApp job,
            PositionManager positionManager,
            IConfiguration _configuration
            ) : base(unitWork, repository, auth)
        {
            client = base.Repository.AsSugarClient();
            this.userManager = userManager;
            this.positionManager = positionManager;
            this._configuration = _configuration;
            _job = job;
        }

        #region 获取数据
        /// <summary>
        /// 获取流程列表
        /// </summary>
        /// <param name="pagination">分页参数</param>
        /// <param name="searchParams">查询参数</param>
        /// <returns></returns>
        public async Task<PageInfo<List<WFProcess>>> GetPageList(PageReq pageReq, WFProcessSearchDto searchParams)
        {
            RefAsync<int> totalCount = 0;

            var exp = Expressionable.Create<WFProcess>()
                  .AndIF(!string.IsNullOrEmpty(searchParams.Keyword), t => t.Title.Contains(searchParams.Keyword) || t.SchemeName.Contains(searchParams.Keyword))
                  .AndIF(!string.IsNullOrEmpty(searchParams.Code), t => t.SchemeCode == searchParams.Code)
                  .AndIF(searchParams.StartDate != null && searchParams.EndDate != null, t => t.CreateDate >= searchParams.StartDate && t.CreateDate <= searchParams.EndDate);

            if (searchParams.Type == 3)
            {
                exp = exp.And(t => t.EnabledMark == 3);
            }
            else
            {
                exp = exp.And(t => t.EnabledMark == 1);

                if (searchParams.Type == 1)
                {
                    exp = exp.And(t => t.IsFinished == 1);
                }
                else
                {
                    exp = exp.And(t => t.IsFinished == 0);
                }
            }

            var list = await client.Queryable<WFProcess>()
                .Where(exp.ToExpression())
                .OrderByDescending(t => t.CreateDate)
                .ToPageListAsync(pageReq.page, pageReq.limit, totalCount);

            return new PageInfo<List<WFProcess>>
            {
                Items = list,
                Total = totalCount
            };
        }
        /// <summary>
        /// 获取我的流程
        /// </summary>
        /// <param name="pagination">分页参数</param>
        /// <param name="searchParams">查询参数</param>
        /// <param name="type"> 1正常2草稿3作废</param>
        /// <returns></returns>
        public async Task<PageInfo<List<WFProcess>>> GetMyPageList(PageReq pageReq, WFProcessSearchDto searchParams, int type)
        {
            RefAsync<int> totalCount = 0;

            var userId = _auth.GetUserId();
            var expression = Expressionable.Create<WFProcess>();
            expression = expression.And(t => t.CreateUserId == userId || t.UserId == userId);

            if (type == 2)
            {
                expression = expression.And(t => t.EnabledMark == 2);
            }
            else
            {
                expression = expression.And(t => t.EnabledMark != 2);
            }

            if (!string.IsNullOrEmpty(searchParams.Keyword))
            {
                expression = expression.And(t => t.Title.Contains(searchParams.Keyword) || t.SchemeName.Contains(searchParams.Keyword));
            }
            if (!string.IsNullOrEmpty(searchParams.Code))
            {
                expression = expression.And(t => t.SchemeCode == searchParams.Code);
            }
            if (searchParams.StartDate != null && searchParams.EndDate != null)
            {
                expression = expression.And(t => t.CreateDate >= searchParams.StartDate && t.CreateDate <= searchParams.EndDate);
            }

            var list = await client.Queryable<WFProcess>()
               .Where(expression.ToExpression())
               .OrderByDescending(t => t.CreateDate)
               .ToPageListAsync(pageReq.page, pageReq.limit, totalCount);

            return new PageInfo<List<WFProcess>>
            {
                Items = list,
                Total = totalCount
            };
        }
        /// <summary>
        /// 获取流程进程实体
        /// </summary>
        /// <param name="keyValue">主键</param>
        /// <returns></returns>
        public async Task<WFProcess> GetEntity(string keyValue)
        {
            return await base.Repository.GetByIdAsync(keyValue);
        }
        #endregion

        #region 保存更新删除
        /// <summary>
        /// 删除流程进程实体
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        public async Task<bool> DeleteEntity(string processId)
        {
            return await base.Repository.DeleteByIdAsync(processId);
        }
        #endregion

        #region 流程API
        /// <summary>
        /// 保存草稿
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        /// <param name="schemeCode">流程模板编码</param>
        /// <param name="userId">创建人</param>
        /// <param name="parentProcessId">父级流程进程主键</param>
        /// <param name="parentNodeId">父级流程节点Id</param>
        /// <param name="parentTaskId">父级任务id</param>
        /// <param name="isChild">是否为子流程</param>
        /// <param name="title">流程标题</param>
        /// <returns></returns>
        public async Task<Response<bool>> SaveDraft(string processId, string schemeCode, string userId, string instanceInfo, string parentProcessId, string parentNodeId, string parentTaskId, int isChild, string title = "")
        {
            var flag = false;

            var currentUser = _auth.GetCurrentUser().User;

            // 判断当前流程进程是否有保存过
            var processEntity = await GetEntity(processId);
            if (processEntity == null)
            {
                // 创建草稿，已经存在不做处理
                var schemeInfo = await client.Queryable<WFSchemeInfo>().FirstAsync(a => a.Code == schemeCode);
                WFProcess wfProcessEntity = new WFProcess()
                {
                    Id = processId,
                    SchemeCode = schemeCode,
                    SchemeId = schemeInfo.SchemeId,
                    SchemeName = schemeInfo.Name,
                    Title = title,
                    InstanceInfo = JsonConvert.DeserializeObject<WFInstanceInfo>(instanceInfo),
                    EnabledMark = 2,
                    IsAgain = 0,
                    IsFinished = 0,
                    IsChild = isChild,
                    IsStart = 0,
                    ParentNodeId = parentNodeId,
                    ParentProcessId = parentProcessId,
                    ParentTaskId = parentTaskId,
                    CreateUserId = currentUser.Id.ToString(),
                    CreateUserName = currentUser.Name,
                    CreateUserAccount = currentUser.Account,
                    UserId = currentUser.Id.ToString()
                };

                if (string.IsNullOrEmpty(title))
                {
                    wfProcessEntity.Title = currentUser.Name + "-" + schemeInfo.Name;
                }

                wfProcessEntity.CreateDate = DateTime.Now;
                wfProcessEntity.UserId = currentUser.Id.ToString();
                flag = await base.Repository.InsertAsync(wfProcessEntity);
            }
            else if (!string.IsNullOrEmpty(title) && processEntity.Title != title)
            {
                processEntity.Title = title;
                flag = await base.Repository.UpdateAsync(processEntity);
            }
            else
            {
                flag = true;
            }

            return new Response<bool>
            {
                Result = flag,
                Message = flag == true ? "success" : "error"
            };
        }
        /// <summary>
        /// 保存草稿-新版用户查询
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        /// <param name="schemeCode">流程模板编码</param>
        /// <param name="userId">创建人</param>
        /// <param name="parentProcessId">父级流程进程主键</param>
        /// <param name="parentNodeId">父级流程节点Id</param>
        /// <param name="parentTaskId">父级任务id</param>
        /// <param name="isChild">是否为子流程</param>
        /// <param name="title">流程标题</param>
        /// <returns></returns>
        public async Task<Response<bool>> SaveDraftWithUser(string processId, string schemeCode, string userName, string instanceInfo, string parentProcessId, string parentNodeId, string parentTaskId, int isChild, string title = "")
        {
            var flag = false;
            var currentUser = await client.Queryable<SysUser>().FirstAsync(r => r.Name == userName)
                      ?? new SysUser
                      {
                          Id = -1,
                          Account = Define.SYSTEM_USERNAME,
                          Name = "超级管理员",
                      };

            // 判断当前流程进程是否有保存过
            var processEntity = await GetEntity(processId);
            if (processEntity == null)
            {
                // 创建草稿，已经存在不做处理
                var schemeInfo = await client.Queryable<WFSchemeInfo>().FirstAsync(a => a.Code == schemeCode);
                WFProcess wfProcessEntity = new WFProcess()
                {
                    Id = processId,
                    SchemeCode = schemeCode,
                    SchemeId = schemeInfo.SchemeId,
                    SchemeName = schemeInfo.Name,
                    Title = title,
                    InstanceInfo = JsonConvert.DeserializeObject<WFInstanceInfo>(instanceInfo),
                    EnabledMark = 2,
                    IsAgain = 0,
                    IsFinished = 0,
                    IsChild = isChild,
                    IsStart = 0,
                    ParentNodeId = parentNodeId,
                    ParentProcessId = parentProcessId,
                    ParentTaskId = parentTaskId,
                    CreateUserId =  currentUser?.Id.ToString(),
                    CreateUserName = currentUser?.Name,
                    CreateUserAccount = currentUser?.Account,
                    UserId = currentUser?.Id.ToString()
                };

                if (string.IsNullOrEmpty(title))
                {
                    wfProcessEntity.Title = currentUser.Name + "-" + schemeInfo.Name;
                }

                wfProcessEntity.CreateDate = DateTime.Now;
                wfProcessEntity.UserId = currentUser.Id.ToString();
                flag = await base.Repository.InsertAsync(wfProcessEntity);
            }
            else if (!string.IsNullOrEmpty(title) && processEntity.Title != title)
            {
                processEntity.Title = title;
                flag = await base.Repository.UpdateAsync(processEntity);
            }

            return new Response<bool>
            {
                Result = flag,
                Message = flag == true ? "success" : "error"
            };
        }

        /// <summary>
        /// 删除草稿
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        public async Task<Response<bool>> DeleteDraft(string processId)
        {
            var flag = false;
            var response = new Response<bool>();

            var iWFEngine = await Bootstraper(string.Empty, processId, null);

            var scriptResult = await ExecuteScript(processId, "deleteDraft", iWFEngine.CreateUser,
                 iWFEngine.WFScheme.DeleteDraftType,
                 iWFEngine.WFScheme.DeleteDraftDbCode,
                 iWFEngine.WFScheme.DeleteDraftDbSQL,
                 iWFEngine.WFScheme.DeleteDraftUrl,
                 iWFEngine.WFScheme.DeleteDraftIOCName);

            if (scriptResult)
            {
                flag = await DeleteEntity(processId);
                if (flag)
                {
                    response.Result = true;
                    response.Message = "success";
                }
                else
                {
                    response.Result = false;
                    response.Message = "脚本执行成功，但流程信息删除失败";
                }
            }
            else
            {
                response.Result = false;
                response.Message = "error";
            }
            return response;
        }
        /// <summary>
        /// 创建流程
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        /// <param name="schemeCode">流程模板编码</param>
        /// <param name="userId">创建人</param>
        /// <param name="nextUsers">下一个节点审核人</param>
        /// <param name="title">流程标题</param>
        /// <returns></returns>
        public async Task<Response<bool>> Create(string processId, string schemeCode, string userId, Dictionary<string, string> nextUsers, string InstanceInfo, string title = "")
        {
            var flag = false;
            var userInfo = await GetUserInfo(userId);
            var iWFEngine = await Bootstraper(schemeCode, processId, userInfo, nextUsers);
            // 下一部需要执行的任务
            var taskList = await iWFEngine.GetTask(iWFEngine.StartNode.Id);
            //获取当前流程信息
            var process = await GetEntity(processId);
            // 处理任务并更新数据
            List<WFTask> myTaskList;

            using (var uwo = UnitWork.CreateContext())
            {

                var processEntity = GetWFProcessEntity(iWFEngine.Config.Params, title);
                processEntity.InstanceInfo = JsonConvert.DeserializeObject<WFInstanceInfo>(InstanceInfo);
                if (string.IsNullOrEmpty(processEntity.Title))
                {
                    processEntity.Title = userInfo.Name + "-" + processEntity.SchemeName;
                }
                processEntity.CreateDate = DateTime.Now;

                if (taskList.FindIndex(t => t.Type == 100) != -1)
                {
                    processEntity.IsFinished = 1;
                    if (process != null && process.IsChild == 1)
                    {
                        WFTask ts = new WFTask();
                        await ChildrenEndTask(process.ParentProcessId, process.ParentNodeId, "", ts, "");
                    }
                }

                if (process != null && process.IsChild == 1)
                {
                    var taskEntity = await client.Queryable<WFTask>().Where(a => a.Id == process.ParentTaskId).FirstAsync();
                    if (taskEntity != null)
                    {
                        taskEntity.State = 3;
                        if (taskEntity.Type == 7)
                        {
                            var currentUser = _auth.GetCurrentUser().User;
                            taskEntity.UserId = currentUser.Id.ToString();
                            taskEntity.UserName = currentUser.Name;
                        }
                        await uwo.WFTask.UpdateAsync(taskEntity);
                    }
                }

                if (!string.IsNullOrEmpty(schemeCode))
                {
                    await uwo.WFProcess.InsertAsync(processEntity);
                }
                else
                {
                    await uwo.WFProcess.UpdateAsync(processEntity);
                }

                myTaskList = await ExecuteWFTaskEntity(taskList, iWFEngine, processId, "create", "create");
                foreach (var item in myTaskList)
                {
                    if (item.Type == 7)
                    {
                        await uwo.WFTaskUser.InsertRangeAsync(item.WFTaskUser);
                    }
                    item.ProcessTitle = processEntity.Title;
                    await Add(item);
                }

                WFTaskLog wfTaskLogEntity = new WFTaskLog()
                {
                    OperationCode = "create",
                    OperationName = "提交流程",
                    TaskType = 0,
                    IsLast = 1,
                    Des = "提交流程",
                    ProcessId = processId,
                    UnitId = iWFEngine.StartNode.Id,
                    UnitName = string.IsNullOrEmpty(iWFEngine.StartNode.Name) ? "开始节点" : iWFEngine.StartNode.Name
                };
                await AddLog(wfTaskLogEntity);

                flag = uwo.Commit();
            }

            var respone = new Response<bool>();

            if (flag)
            {
                var scriptResults = new List<bool>();
                // 脚本执行
                var scriptTaskList = myTaskList.FindAll(t => t.Type == 10);
                foreach (var item in scriptTaskList)
                {
                    var result = await ExecuteScript(item, "create", processId, "", "",iWFEngine.CreateUser, iWFEngine, null,"");
                    scriptResults.Add(result);
                }

                if (scriptResults.Contains(false))
                {
                    respone.Result = false;
                    respone.Message = "流程信息存储成功，但脚本执行失败";
                }
                else
                {
                    respone.Result = true;
                    respone.Message = "success";
                }
            }
            else
            {
                respone.Result = false;
                respone.Message = "error";
            }
            return respone;
        }
        /// <summary>
        /// 创建流程
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        /// <param name="schemeCode">流程模板编码</param>
        /// <param name="userId">创建人</param>
        /// <param name="nextUsers">下一个节点审核人</param>
        /// <param name="title">流程标题</param>
        /// <returns></returns>
        public async Task<Response<bool>> CreateWithUser(string processId, string schemeCode, string userName, Dictionary<string, string> nextUsers, string InstanceInfo, string title = "")
        {
            var flag = false;
            //var userInfo = await client.Queryable<SysUser>().FirstAsync(r => r.Name == userName);
            var userInfo = await client.Queryable<SysUser>().FirstAsync(r => r.Name == userName)
                     ?? new SysUser
                     {
                         Id = -1,
                         Account = Define.SYSTEM_USERNAME,
                         Name = "超级管理员",
                     };
            var iWFEngine = await BootstraperWithUser(schemeCode, processId, userInfo, nextUsers);
            // 下一部需要执行的任务
            var taskList = await iWFEngine.GetTask(iWFEngine.StartNode.Id);
            //获取当前流程信息
            var process = await GetEntity(processId);
            // 处理任务并更新数据
            List<WFTask> myTaskList;

            using (var uwo = UnitWork.CreateContext())
            {

                var processEntity = GetWFProcessEntity(iWFEngine.Config.Params, title);
                processEntity.InstanceInfo = JsonConvert.DeserializeObject<WFInstanceInfo>(InstanceInfo);
                if (string.IsNullOrEmpty(processEntity.Title))
                {
                    processEntity.Title = userInfo.Name + "-" + processEntity.SchemeName;
                }
                processEntity.CreateDate = DateTime.Now;

                if (taskList.FindIndex(t => t.Type == 100) != -1)
                {
                    processEntity.IsFinished = 1;
                    if (process != null && process.IsChild == 1)
                    {
                        WFTask ts = new WFTask();
                        await ChildrenEndTask(process.ParentProcessId, process.ParentNodeId, "", ts, "");
                    }
                }

                if (process != null && process.IsChild == 1)
                {
                    var taskEntity = await client.Queryable<WFTask>().Where(a => a.Id == process.ParentTaskId).FirstAsync();
                    if (taskEntity != null)
                    {
                        taskEntity.State = 3;
                        if (taskEntity.Type == 7)
                        {
                            var currentUser = _auth.GetCurrentUser().User;
                            taskEntity.UserId = currentUser.Id.ToString();
                            taskEntity.UserName = currentUser.Name;
                        }
                        await uwo.WFTask.UpdateAsync(taskEntity);
                    }
                }

                if (!string.IsNullOrEmpty(schemeCode))
                {
                    await uwo.WFProcess.InsertAsync(processEntity);
                }
                else
                {
                    await uwo.WFProcess.UpdateAsync(processEntity);
                }

                myTaskList = await ExecuteWFTaskEntity(taskList, iWFEngine, processId, "create", "create");
                foreach (var item in myTaskList)
                {
                    if (item.Type == 7)
                    {
                        await uwo.WFTaskUser.InsertRangeAsync(item.WFTaskUser);
                    }
                    item.ProcessTitle = processEntity.Title;
                    await Add(item);
                }

                WFTaskLog wfTaskLogEntity = new WFTaskLog()
                {
                    OperationCode = "create",
                    OperationName = "提交流程",
                    TaskType = 0,
                    IsLast = 1,
                    Des = "提交流程",
                    ProcessId = processId,
                    UnitId = iWFEngine.StartNode.Id,
                    UnitName = string.IsNullOrEmpty(iWFEngine.StartNode.Name) ? "开始节点" : iWFEngine.StartNode.Name
                };
                await AddLog(wfTaskLogEntity);

                flag = uwo.Commit();
            }

            var respone = new Response<bool>();

            if (flag)
            {
                var scriptResults = new List<bool>();
                // 脚本执行
                var scriptTaskList = myTaskList.FindAll(t => t.Type == 10);
                foreach (var item in scriptTaskList)
                {
                    var result = await ExecuteScript(item, "create", processId, "", "",iWFEngine.CreateUser, iWFEngine, null, "");
                    scriptResults.Add(result);
                }

                if (scriptResults.Contains(false))
                {
                    respone.Result = false;
                    respone.Message = "流程信息存储成功，但脚本执行失败";
                }
                else
                {
                    respone.Result = true;
                    respone.Message = "success";
                }
            }
            else
            {
                respone.Result = false;
                respone.Message = "error";
            }
            return respone;
        }

        /// <summary>
        /// 重新创建流程
        /// </summary>
        /// <param name="processId">流程实例主键</param>
        /// <param name="des">备注</param>
        /// <returns></returns>
        public async Task<Response<bool>> CreateAgain(string processId, string des)
        {
            var flag = false;

            var iWFEngine = await Bootstraper("", processId, null, null);

            var unList = (List<WFTask>)await GetUnFinishTaskList(processId);
            var taskEntity = unList.Find(t => t.State == 1 && t.UnitId == iWFEngine.StartNode.Id);

            if (taskEntity == null)
            {
                throw (new Exception("找不到重新提交流程任务！"));
            }

            // 下一部需要执行的任务
            var taskList = await iWFEngine.GetTask(iWFEngine.StartNode.Id);

            // 处理任务并更新数据

            List<WFTask> myTaskList;

            using (var uwo = UnitWork.CreateContext())
            {
                await uwo.WFProcess.UpdateSetColumnsTrueAsync(a => new WFProcess() { IsCancel = 1, IsAgain = 0 }, a => a.Id == processId);
                await uwo.WFTask.UpdateSetColumnsTrueAsync(a => new WFTask() { State = 3 }, a => a.Id == taskEntity.Id);
                // 更新上一个流转过来的任务，提示他无法被撤销
                await CloseTaskLogCancel(taskEntity.ProcessId, taskEntity.PrevTaskId);

                myTaskList = await ExecuteWFTaskEntity(taskList, iWFEngine, processId, taskEntity.Token, taskEntity.Id);
                foreach (var item in myTaskList)
                {
                    if (item.Type == 7)
                    {
                        await uwo.WFTaskUser.InsertRangeAsync(item.WFTaskUser);
                    }
                    await Add(item);
                }

                await CreateTaskLog(taskEntity, "", "重新提交", des, "");

                //await _imMsgIBLL.VirtualDeleteByContentId(taskEntity.Token); // 更新消息

                flag = uwo.Commit();
            }


            var respone = new Response<bool>();

            if (flag)
            {
                var scriptResults = new List<bool>();
                // 脚本执行
                var scriptTaskList = myTaskList.FindAll(t => t.Type == 10);
                foreach (var item in scriptTaskList)
                {
                    var result = await ExecuteScript(item, "createAgain", processId, "", "",iWFEngine.CreateUser, iWFEngine, null, "");
                    scriptResults.Add(result);
                }

                if (scriptResults.Contains(false))
                {
                    respone.Result = false;
                    respone.Message = "流程信息存储成功，但脚本执行失败";
                }
                else
                {
                    respone.Result = true;
                    respone.Message = "success";
                }
            }
            else
            {
                respone.Result = false;
                respone.Message = "error";
            }
            return respone;
        }

        /// <summary>
        /// 撤销流程（只有在该流程未被处理的情况下）
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        public async Task<bool> RevokeFlow(string processId)
        {
            var iWFEngine = await Bootstraper(string.Empty, processId, null, null);

            if (iWFEngine.Config.Params.IsStart != 1)
            {
                // 获取脚本任务
                var scriptList = (List<WFTask>)await GetList(processId, 10, "create");
                foreach (var item in scriptList)
                {
                    await ExecuteRevokeScript(item.UnitId, item.UnitName, processId, iWFEngine.CreateUser, iWFEngine);
                }

                using (var uwo = UnitWork.CreateContext())
                {
                    await uwo.WFTask.DeleteAsync(a => a.ProcessId == processId);
                    await uwo.WFTaskLog.DeleteAsync(a => a.ProcessId == processId);
                    await uwo.WFProcess.UpdateSetColumnsTrueAsync(a => new WFProcess { EnabledMark = 2 }, a => a.Id == processId);

                    uwo.Commit();
                }

                await ExecuteScript(processId, "RevokeFlow", iWFEngine.CreateUser,
                iWFEngine.WFScheme.UndoType,
                iWFEngine.WFScheme.UndoDbCode,
                iWFEngine.WFScheme.UndoDbSQL,
                iWFEngine.WFScheme.UndoUrl,
                iWFEngine.WFScheme.UndoIOCName);

                return true;

            }

            return false;
        }

        /// <summary>
        /// 催办流程
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        public async Task<Response<bool>> UrgeFlow(string processId)
        {
            // var userInfo = await this.CurrentUser();
            var iWFEngine = await Bootstraper(string.Empty, processId, null, null);
            // 获取未完成的任务
            var taskList = await GetUnFinishTaskList(processId);

            using (var uwo = UnitWork.CreateContext())
            {

                foreach (var item in taskList)
                {
                    if (item.Type == 1 || item.Type == 3 || item.Type == 5 || item.Type == 6  || item.Type == 7)
                    {
                        item.IsUrge = 1;
                        item.UrgeTime = DateTime.Now;


                        // 发送消息
                        var msg = $"【审核】【催办】{item.ProcessTitle},{item.UnitName}";
                        var userList = new List<string>();
                        // todo 单体任务处理
                        userList.Add(item.UserId);
                        var node = iWFEngine.GetNode(item.UnitId);
                        //await _imMsgIBLL.SendMsg("IMWF", userList, msg, node.MessageType, item.F_Token);

                        await uwo.WFTask.UpdateAsync(item);
                    }
                }

                //await wfProcessSerive.Update(new WFProcessEntity() { F_IsUrge = 1, F_Id = processId });

                WFTaskLog wfTaskLogEntity = new WFTaskLog()
                {
                    Des = "催办审核",
                    TaskType = 98,
                    ProcessId = processId,
                    UnitId = iWFEngine.StartNode.Id,
                    UnitName = string.IsNullOrEmpty(iWFEngine.StartNode.Name) ? "开始节点" : iWFEngine.StartNode.Name
                };

                wfTaskLogEntity.CreateDate = DateTime.Now;
                wfTaskLogEntity.UserId = _auth.GetUserId();
                wfTaskLogEntity.UserName = _auth.GetUserNickName();
                wfTaskLogEntity.Id = Guid.NewGuid().ToString();
                await uwo.WFTaskLog.InsertAsync(wfTaskLogEntity);

                var flag = uwo.Commit();
                return new Response<bool>
                {
                    Result = flag,
                    Message = flag == true ? "success" : "error"
                };
            }
        }


        /// <summary>
        /// 审批流程
        /// </summary>
        /// <param name="taskId">流程任务主键</param>
        /// <param name="code">流程审批操作码agree 同意 disagree 不同意 lrtimeout 超时</param>
        /// <param name="name">流程审批操名称</param>
        /// <param name="des">审批意见</param>
        /// <param name="nextUsers">下一节点指定审核人</param>
        /// <param name="stampImg">盖章图片</param>
        /// <param name="stampPassWord">盖章图片密码</param>
        /// <param name="nextId">下一个审核节点</param>
        public async Task AuditFlow(string taskId, string code, string name, string des, Dictionary<string, string> nextUsers, string stampImg, string stampPassWord, string nextId)
        {
            var taskEntiy = await client.Queryable<WFTask>().Where(a => a.Id == taskId).FirstAsync();
            if (taskEntiy == null)
            {
                throw (new Exception("找不到对应流程任务！"));
            }
            else if (taskEntiy.State != 1)
            {
                if (taskEntiy.State == 3 || taskEntiy.State == 4)
                {
                    throw (new Exception("该任务已完成！"));
                }
                else
                {
                    throw (new Exception("该任务未被激活！"));
                }
            }

            //后期改
            stampImg = "";
            //stampImg = await _wFStampIBLL.ToWfImg(stampImg, stampPassWord);

            var iWFEngine = await Bootstraper("", taskEntiy.ProcessId, null, nextUsers);

            // 1.判断任务类型 1 普通任务 5 会签任务
            if (taskEntiy.Type == 1||taskEntiy.Type==7)
            {
                await AuditNode(iWFEngine, taskEntiy, code, name, des, stampImg, nextId);
            }
            else if (taskEntiy.Type == 5)
            {
                await AuditNodeByCountersign(iWFEngine, taskEntiy, code, name, des, stampImg);
            }
            else
            {
                throw (new Exception("该任务无法审核！"));
            }

            //await _imMsgIBLL.VirtualDeleteByContentId(taskEntiy.F_Token); // 更新消息

            // 发送消息
            var msg = $"【提醒】{iWFEngine.Config.Params.Title},{taskEntiy.UnitName}已被处理";
            var userList = new List<string>();
            userList.Add(iWFEngine.CreateUser.Id);
            var node = iWFEngine.StartNode;
            //await _imMsgIBLL.SendMsg("IMWF", userList, msg, node.MessageType, iWFEngine.Config.Params.ProcessId);
        }

        /// <summary>
        /// 批量审核（只有同意和不同意）
        /// </summary>
        /// <param name="code">操作码</param>
        /// <param name="taskIdList">任务id串</param>
        public async Task AuditFlows(string code, List<string> taskIdList)
        {
            foreach (var taskId in taskIdList)
            {
                string operationName = code == "agree" ? "同意" : "不同意";
                await AuditFlow(taskId, code, operationName, "批量审核", null, "", "", "");
            }
        }

        /// <summary>
        /// 撤销审核
        /// </summary>
        /// <param name="processId"></param>
        /// <param name="taskId">流程任务主键</param>
        /// <returns></returns>
        public async Task<Response<bool>> RevokeAudit(string processId, string taskId)
        {
            var iWFEngine = await Bootstraper(string.Empty, processId, null, null);
            WFTask taskEntity;
            WFProcess processEntity;
            if (string.IsNullOrEmpty(taskId))
            { //撤销重新提交任务
                processEntity = await GetEntity(processId);
                if (processEntity.IsCancel != 1)
                {
                    throw (new Exception("当前流程无法撤销！"));
                }

                var myTaskList = (List<WFTask>)await GetLastTaskList(processId, iWFEngine.StartNode.Id);
                taskEntity = myTaskList[0];

                processEntity.IsAgain = 1;
                processEntity.IsCancel = 0;
            }
            else
            {
                taskEntity = await client.Queryable<WFTask>().Where(a => a.Id == taskId).FirstAsync();

                if (taskEntity.State == 1)
                {
                    throw (new Exception("当前任务无法撤销！"));
                }

                var taskLogEntity = await GetLogEntity(taskId);

                if (taskLogEntity == null || taskLogEntity.IsCancel != 1)
                {
                    throw (new Exception("当前任务无法撤销！"));
                }
                processEntity = new WFProcess()
                {
                    Id = processId
                };
                processEntity.IsFinished = 0;
                processEntity.IsAgain = 0;
            }

            using (var uwo = UnitWork.CreateContext())
            {
                // 获取脚本任务
                var scriptList = await GetList(processId, 10, taskEntity.Id);
                foreach (var item in scriptList)
                {
                    await ExecuteRevokeScript(item.UnitId, item.UnitName, processId, iWFEngine.CreateUser, iWFEngine);
                    // 删除脚本任务执行日志
                    await DeleteLogByTaskId(item.Id);
                }


                // 删除所有生成的任务
                await Delete(processId, taskEntity.Id);

                // 如果是加签审核的，关闭最早的任务
                if (taskEntity.Type == 6)
                {
                    var myTaskEntiy = await GetTaskEntity(taskEntity.FirstId); // 原始审核任务
                    myTaskEntiy.State = 5;
                    await uwo.WFTask.UpdateAsync(myTaskEntiy);
                }


                // 如果是撤销转移任务
                if (taskEntity.State == 6)
                {
                    // 删除转移任务
                    await DeleteByFirstId(taskEntity.Id);
                }


                // 删除所有生成的日志
                await DeleteLog(processId, taskEntity.Id);

                // 更新等待任务状态
                await OpenTask(processId, taskEntity.UnitId, 21, taskEntity.Id);

                taskEntity.State = 1;
                await uwo.WFTask.UpdateAsync(taskEntity);

                await uwo.Db.Updateable(processEntity)
                    .IgnoreColumns(ignoreAllNullColumns: true)
                    .ExecuteCommandAsync();

                var flag = uwo.Commit();
                return new Response<bool>
                {
                    Result = flag,
                    Message = flag == true ? "success" : "error"
                };
            }

        }

        /// <summary>
        /// 流程加签
        /// </summary>
        /// <param name="taskId">流程任务主键</param>
        /// <param name="userId">加签人员</param>
        /// <param name="des">加签说明</param>
        public async Task<Response<bool>> SignFlow(string taskId, string userId, string des)
        {
            var taskEntiy = await GetTaskEntity(taskId);
            if (taskEntiy == null)
            {
                throw (new Exception("找不到对应流程任务！"));
            }
            else if (taskEntiy.State != 1)
            {
                if (taskEntiy.State == 3 || taskEntiy.State == 4)
                {
                    throw (new Exception("该任务已完成！"));
                }
                else
                {
                    throw (new Exception("该任务未被激活！"));
                }
            }

            using (var uwo = UnitWork.CreateContext())
            {

                // 更新任务状态
                taskEntiy.State = 5;
                await uwo.WFTask.UpdateAsync(taskEntiy);

                // 更新上一个流转过来的任务，提示他无法被撤销
                await CloseTaskLogCancel(taskEntiy.ProcessId, taskEntiy.PrevTaskId);

                // 填写日志
                await CreateTaskLog(taskEntiy, "sign", "加签", des, "");

                if (taskEntiy.Type != 6)
                {
                    taskEntiy.FirstId = taskEntiy.Id;
                }

                var userInfo = await uwo.User.GetByIdAsync(userId);

                // 添加加签任务
                taskEntiy.PrevTaskId = taskEntiy.Id;
                //taskEntiy.UserCompanyId = userInfo.CompanyId;
                //taskEntiy.UserDepartmentId = userInfo.DepartmentId;
                taskEntiy.UserId = userInfo.Id.ToString();
                taskEntiy.UserName = userInfo.Name;
                taskEntiy.Type = 6;
                taskEntiy.State = 1;
                await uwo.WFTask.InsertAsync(taskEntiy);

                var flag = uwo.Commit();
                return new Response<bool>
                {
                    Result = flag,
                    Message = flag == true ? "success" : "error"
                };
            }
        }

        /// <summary>
        /// 流程加签审核
        /// </summary>
        /// <param name="taskId">流程任务主键</param>
        /// <param name="code">操作码</param>
        /// <param name="name">流程审批操名称</param>
        /// <param name="des">审批意见</param>
        /// <returns></returns>
        public async Task<Response<bool>> SignAudit(string taskId, string code, string name, string des)
        {
            var taskEntiy = await GetTaskEntity(taskId);
            if (taskEntiy == null)
            {
                throw (new Exception("找不到对应流程任务！"));
            }
            else if (taskEntiy.State != 1)
            {
                if (taskEntiy.State == 3 || taskEntiy.State == 4)
                {
                    throw (new Exception("该任务已完成！"));
                }
                else
                {
                    throw (new Exception("该任务未被激活！"));
                }
            }

            using (var uwo = UnitWork.CreateContext())
            {
                var myTaskEntiy = await GetTaskEntity(taskEntiy.FirstId); // 原始审核任务
                myTaskEntiy.IsLast = 0;
                await uwo.WFTask.UpdateAsync(myTaskEntiy);
                myTaskEntiy.State = 1;
                myTaskEntiy.IsLast = 1;
                await Add(myTaskEntiy);

                // 更新任务状态
                taskEntiy.State = 3;
                if (taskEntiy.Type == 7)
                {
                    var currentUser = _auth.GetCurrentUser().User;
                    taskEntiy.UserId = currentUser.Id.ToString();
                    taskEntiy.UserName = currentUser.Name;
                }
                await uwo.WFTask.UpdateAsync(taskEntiy);

                // 填写日志
                await CreateTaskLog(taskEntiy, code, name, des, "");

                // 更新上一个流转过来的任务，提示他无法被撤销
                await CloseTaskLogCancel(taskEntiy.ProcessId, taskEntiy.PrevTaskId);

                var flag = uwo.Commit();
                return new Response<bool>
                {
                    Result = flag,
                    Message = flag == true ? "success" : "error"
                };
            }
        }

        /// <summary>
        /// 确认阅读
        /// </summary>
        /// <param name="taskId">流程任务主键</param>
        public async Task<Response<bool>> ReadFlow(string taskId)
        {
            var taskEntiy = await GetTaskEntity(taskId);
            if (taskEntiy == null)
            {
                throw (new Exception("找不到对应流程任务！"));
            }
            else if (taskEntiy.State == 1)
            {
                using (var uwo = UnitWork.CreateContext())
                {
                    taskEntiy.State = 3;
                    await uwo.WFTask.UpdateAsync(taskEntiy);

                    WFTaskLog wfTaskLogEntity = new WFTaskLog()
                    {
                        TaskType = taskEntiy.Type,
                        ProcessId = taskEntiy.ProcessId,
                        UnitId = taskEntiy.UnitId,
                        UnitName = taskEntiy.UnitName,
                        IsAgree = taskEntiy.IsAgree,
                        OperationCode = "read",
                        OperationName = "已阅",
                        Token = taskEntiy.Token,
                        PrevUnitId = taskEntiy.PrevUnitId,
                        PrevUnitName = taskEntiy.PrevUnitName,
                        TaskId = taskEntiy.Id,
                        IsCancel = 0
                    };
                    await AddLog(wfTaskLogEntity);

                    var flag = uwo.Commit();
                    return new Response<bool>
                    {
                        Result = flag,
                        Message = flag == true ? "success" : "error"
                    };
                }

            }
            else
            {
                return new Response<bool>
                {
                    Result = false,
                    Message = "error"
                };
            }
        }

        /// <summary>
        /// 转移流程
        /// </summary>
        /// <param name="taskId">任务id</param>
        /// <param name="userId">转移人用户id</param>
        /// <param name="des">说明</param>
        /// <returns></returns>
        public async Task<Response<bool>> TransferUser(string taskId, string userId, string des)
        {
            var taskEntiy = await GetTaskEntity(taskId);
            if (taskEntiy == null)
            {
                throw (new Exception("找不到对应流程任务！"));
            }
            else if (taskEntiy.State == 1)
            {
                using (var uwo = UnitWork.CreateContext())
                {
                    var userInfo = await uwo.User.GetByIdAsync(userId);

                    // 更新任务状态
                    taskEntiy.State = 6;
                    await uwo.WFTask.UpdateAsync(taskEntiy);

                    // 更新流程
                    WFProcess processEntity = new WFProcess()
                    {
                        Id = taskEntiy.ProcessId,
                        IsStart = 1,
                        IsCancel = 0,
                    };
                    await uwo.WFProcess.UpdateAsync(processEntity);

                    // 填写日志
                    await CreateTaskLog(taskEntiy, "transfer", "转移", des, "");

                    // 更新上一个流转过来的任务，提示他无法被撤销
                    await CloseTaskLogCancel(taskEntiy.ProcessId, taskEntiy.PrevTaskId);

                    // 新建任务
                    var newTask = taskEntiy; //.ToJson().ToObject<WFTaskEntity>();
                    newTask.State = 1;
                    newTask.PrevTaskId = taskEntiy.Id;
                    //newTask.UserCompanyId = userInfo.F_CompanyId;
                    //newTask.UserDepartmentId = userInfo.F_DepartmentId;
                    newTask.UserId = userInfo.Id.ToString();
                    newTask.UserName = userInfo.Name;

                    await uwo.WFTask.InsertAsync(newTask);

                    // 发送消息
                    var iWFEngine = await Bootstraper("", taskEntiy.ProcessId, null);
                    var msg = $"【审核】{taskEntiy.ProcessTitle},{taskEntiy.UnitName}";
                    var userList = new List<string>();
                    userList.Add(userInfo.Id.ToString());
                    var node = iWFEngine.GetNode(taskEntiy.UnitId);
                    //await _imMsgIBLL.SendMsg("IMWF", userList, msg, node.MessageType, newTask.F_Token);

                    var flag = uwo.Commit();

                    return new Response<bool>
                    {
                        Result = flag,
                        Message = flag == true ? "success" : "error"
                    };
                }
            }
            else
            {
                return new Response<bool>
                {
                    Result = false,
                    Message = "error"
                };
            }
        }

        /// <summary>
        /// 获取下一节点审核人
        /// </summary>
        /// <param name="code">流程模板编码</param>
        /// <param name="processId">流程进程主键</param>
        /// <param name="nodeId">流程节点Id</param>
        /// <param name="operationCode">流程操作代码</param>
        /// <param name="userId">创建人</param>
        /// <returns></returns>
        public async Task<Dictionary<string, List<WFUserInfo>>> GetNextAuditors(string code, string processId, string nodeId, string operationCode, string userId)
        {
            Dictionary<string, List<WFUserInfo>> res = new Dictionary<string, List<WFUserInfo>>();
            var userInfo = await client.Queryable<SysUser>().Where(a => a.Id.ToString() == userId).FirstAsync();
            var iWFEngine = await Bootstraper(code, processId, userInfo);

            // 下一部需要执行的任务
            var taskList = await iWFEngine.GetTask(nodeId, operationCode);

            foreach (var item in taskList)
            {
                if ((item.Type == 1 || item.Type == 3 || item.Type == 5||item.Type==7) && item.User.IsNew)
                {
                    if (!res.ContainsKey(item.UnitId))
                    {
                        res.Add(item.UnitId, new List<WFUserInfo>());
                    }
                    res[item.UnitId].Add(item.User);
                }
            }

            return res;
        }

        /// <summary>
        /// 作废流程
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        /// <returns></returns>
        public async Task<Response<bool>> DeleteProcess(string processId)
        {
            var flag = false;
            var iWFEngine = await Bootstraper(string.Empty, processId, null);

            using (var uwo = UnitWork.CreateContext())
            {
                // 更新流程状态
                WFProcess processEntity = new WFProcess()
                {
                    Id = processId,

                };
                await uwo.WFProcess.UpdateSetColumnsTrueAsync(a => new WFProcess { EnabledMark = 3 }, a => a.Id == processId);

                await uwo.WFTask.UpdateSetColumnsTrueAsync(a => new WFTask { State = 7 }, a => a.ProcessId == processId && a.State == 1);
                flag = uwo.Commit();
            }

            var response = new Response<bool>();

            if (flag)
            {
                var scriptResult = await ExecuteScript(processId, "delete", iWFEngine.CreateUser,
                 iWFEngine.WFScheme.DeleteType,
                 iWFEngine.WFScheme.DeleteDbCode,
                 iWFEngine.WFScheme.DeleteDbSQL,
                 iWFEngine.WFScheme.DeleteUrl,
                 iWFEngine.WFScheme.DeleteIOCName);

                if (scriptResult)
                {
                    response.Result = true;
                    response.Message = "success";
                }
                else
                {
                    response.Result = false;
                    response.Message = "流程状态更新成功，但脚本执行失败";
                }
            }
            else
            {
                response.Result = false;
                response.Message = "error";
            }
            return response;
        }

        /// <summary>
        /// 流程还原
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        /// <returns></returns>
        public async Task<Response<bool>> RecoverProcess(string processId)
        {
            var flag = false;
            var iWFEngine = await Bootstraper(string.Empty, processId, null);

            using (var uwo = UnitWork.CreateContext())
            {
                // 更新流程状态
                WFProcess processEntity = new WFProcess()
                {
                    Id = processId,

                };
                await uwo.WFProcess.UpdateSetColumnsTrueAsync(a => new WFProcess { EnabledMark = 1 }, a => a.Id == processId);

                await uwo.WFTask.UpdateSetColumnsTrueAsync(a => new WFTask { State = 1 }, a => a.ProcessId == processId && a.State == 7);
                flag = uwo.Commit();
            }

            var response = new Response<bool>();

            if (flag)
            {

                response.Result = true;
                response.Message = "success";
            }
            else {
                response.Result = false;
                response.Message = "error";
            }
          
            return response;
        }

        /// <summary>
        /// 指派流程审核人
        /// </summary>
        /// <param name="processId">流程进程主键</param>
        /// <param name="pointList">流程指派人信息</param>
        /// <returns></returns>
        public async Task<Response<bool>> PointUser(string processId, List<WFProcessPoint> pointList)
        {
            var list = await GetUnFinishTaskList(processId);
            Dictionary<string, List<WFTask>> map = new Dictionary<string, List<WFTask>>();
            foreach (var item in list)
            {
                if (!map.ContainsKey(item.UnitId))
                {
                    map.Add(item.UnitId, new List<WFTask>());
                }
                map[item.UnitId].Add(item);
            }

            var addList = new List<WFTask>();
            var iWFEngine = await Bootstraper("", processId, null);
            using (var uwo = UnitWork.CreateContext())
            {

                foreach (var item in pointList)
                {
                    if (map.ContainsKey(item.UnitId))
                    {
                        await CloseTask(processId, map[item.UnitId][0].Token, "");
                        var userIdList = item.UserIds.Split(",");
                        foreach (var userId in userIdList)
                        {
                            var addItem = Newtonsoft.Json.JsonConvert.SerializeObject(map[item.UnitId][0]).ToObject<WFTask>();
                            addItem.State = 1;
                            if (addItem.Type == 6)
                            {
                                addItem.Type = 1;
                            }

                            var userEntity = _auth.GetCurrentUser().User;

                            addItem.UserId = userId;
                            addItem.UserName = userEntity.Name;
                            //addItem.UserCompanyId = userEntity.F_CompanyId;
                            //addItem.UserDepartmentId = userEntity.F_DepartmentId;

                            // 发送消息
                            var msg = $"【审核】{addItem.ProcessTitle},{addItem.UnitName}";
                            var userList = new List<string>();
                            userList.Add(userId);
                            var node = iWFEngine.GetNode(addItem.UnitId);
                            //await _imMsgIBLL.SendMsg("IMWF", userList, msg, node.MessageType, addItem.F_Token);

                            addList.Add(addItem);
                        }
                    }
                    else
                    {
                        throw (new Exception("找不到指派任务节点！"));
                    }
                }

                foreach (var item in addList)
                {
                    await Add(item);
                }

                var flag = uwo.Commit();

                return new Response<bool>()
                {
                    Result = flag,
                    Message = flag == true ? "success" : "error"
                };
            }

        }
        #endregion

        #region
        /// <summary>
        /// 流程模板初始化
        /// </summary>
        /// <param name="code">流程模板</param>
        /// <param name="processId">流程实例</param>
        /// <param name="userInfo">提交人用户信息</param>
        /// <param name="nextUsers">下一个节点审核人</param>
        /// <returns></returns>
        private async Task<IWFEngine> Bootstraper(string code, string processId, SysUser userInfo, Dictionary<string, string> nextUsers = null)
        {

            WFEngineConfig wfEngineConfig = new WFEngineConfig();
            WFParams wfParams = new WFParams();
            wfEngineConfig.Params = wfParams;

            var currentUser = _auth.GetCurrentUser().User;
            wfParams.CurrentUser = new WFUserInfo()
            {
                Id = currentUser.Id.ToString(),
                Account = currentUser.Account,
                Name = currentUser.Name
                //CompanyId = currentUser.F_CompanyId,
                //DepartmentId = currentUser.F_DepartmentId
            };
            if (!string.IsNullOrEmpty(code))
            {
                var schemeInfo = await client.Queryable<WFSchemeInfo>().FirstAsync(a => a.Code == code);
                if (schemeInfo != null)
                {
                    var data = await client.Queryable<WFScheme>().FirstAsync(a => a.Id == schemeInfo.SchemeId);
                    if (data != null)
                    {
                        wfParams.Scheme = data.Content;
                        wfParams.SchemeCode = code;
                        wfParams.SchemeId = schemeInfo.SchemeId;
                        wfParams.SchemeName = schemeInfo.Name;
                        wfParams.ProcessId = processId;
                        wfParams.HasInstance = false;

                        wfParams.CreateUser = new WFUserInfo()
                        {
                            Id = userInfo.Id.ToString(),
                            Account = userInfo.Account,
                            Name = userInfo.Name
                            //CompanyId = userInfo.F_CompanyId,
                            //DepartmentId = userInfo.F_DepartmentId
                        };
                    }
                    else
                    {
                        throw new Exception(string.Format("无法获取对应的流程模板【{0}】", code));
                    }
                }
                else
                {
                    throw new Exception(string.Format("无法获取对应的流程模板【{0}】", code));
                }
            }
            else if (!string.IsNullOrEmpty(processId))
            {
                var processEntity = await GetEntity(processId);
                if (processEntity != null)
                {
                    var data = await client.Queryable<WFScheme>().FirstAsync(a => a.Id == processEntity.SchemeId);
                    if (data != null)
                    {
                        wfParams.Scheme = data.Content;
                        wfParams.SchemeCode = processEntity.SchemeCode;
                        wfParams.SchemeId = processEntity.SchemeId;
                        wfParams.SchemeName = processEntity.SchemeName;
                        wfParams.IsChild = processEntity.IsChild == 1;
                        wfParams.ParentProcessId = processEntity.ParentProcessId;
                        wfParams.ParentTaskId = processEntity.ParentTaskId;
                        wfParams.ParentNodeId = processEntity.ParentNodeId;
                        wfParams.ProcessId = processId;
                        wfParams.HasInstance = true;
                        wfParams.IsStart = processEntity.IsStart == 1 ? 1 : 0;
                        wfParams.Title = processEntity.Title;

                        wfParams.CreateUser = new WFUserInfo()
                        {
                            Id = processEntity.CreateUserId,
                            Account = processEntity.CreateUserAccount,
                            Name = processEntity.CreateUserName,
                            CompanyId = processEntity.CreateUserCompanyId,
                            DepartmentId = processEntity.CreateUserDepartmentId
                        };
                    }
                    else
                    {
                        throw new Exception(string.Format("无法获取流程模板【{0}】", processEntity.SchemeId));
                    }
                }
                else if (string.IsNullOrEmpty(wfParams.Scheme))
                {
                    throw new Exception(string.Format("无法获取实例数据【{0}】", processId));
                }
            }


            wfParams.NextUsers = nextUsers;


            // 注册委托方法
            wfEngineConfig.GetAwaitTaskList = GetAwaitTaskList;
            wfEngineConfig.GetUserList = GetUserList;
            wfEngineConfig.GetSystemUserList = GetSystemUserList;
            wfEngineConfig.GetPrevTaskUserList = GetPrevTaskUserList;
            wfEngineConfig.IsCountersignAgree = IsCountersignAgree;
            wfEngineConfig.GetPrevUnitId = GetPrevUnitId;


            IWFEngine iwfEngine = new WFEngine(wfEngineConfig, client);

            return iwfEngine;
        }

        /// <summary>
        /// 流程模板初始化
        /// </summary>
        /// <param name="code">流程模板</param>
        /// <param name="processId">流程实例</param>
        /// <param name="userInfo">提交人用户信息</param>
        /// <param name="nextUsers">下一个节点审核人</param>
        /// <returns></returns>
        private async Task<IWFEngine> BootstraperWithUser(string code, string processId, SysUser userInfo, Dictionary<string, string> nextUsers = null)
        {

            WFEngineConfig wfEngineConfig = new WFEngineConfig();
            WFParams wfParams = new WFParams();
            wfEngineConfig.Params = wfParams;

            var currentUser = userInfo;
            wfParams.CurrentUser = new WFUserInfo()
            {
                Id = currentUser.Id.ToString(),
                Account = currentUser.Account,
                Name = currentUser.Name
                //CompanyId = currentUser.F_CompanyId,
                //DepartmentId = currentUser.F_DepartmentId
            };
            if (!string.IsNullOrEmpty(code))
            {
                var schemeInfo = await client.Queryable<WFSchemeInfo>().FirstAsync(a => a.Code == code);
                if (schemeInfo != null)
                {
                    var data = await client.Queryable<WFScheme>().FirstAsync(a => a.Id == schemeInfo.SchemeId);
                    if (data != null)
                    {
                        wfParams.Scheme = data.Content;
                        wfParams.SchemeCode = code;
                        wfParams.SchemeId = schemeInfo.SchemeId;
                        wfParams.SchemeName = schemeInfo.Name;
                        wfParams.ProcessId = processId;
                        wfParams.HasInstance = false;

                        wfParams.CreateUser = new WFUserInfo()
                        {
                            Id = userInfo.Id.ToString(),
                            Account = userInfo.Account,
                            Name = userInfo.Name
                            //CompanyId = userInfo.F_CompanyId,
                            //DepartmentId = userInfo.F_DepartmentId
                        };
                    }
                    else
                    {
                        throw new Exception(string.Format("无法获取对应的流程模板【{0}】", code));
                    }
                }
                else
                {
                    throw new Exception(string.Format("无法获取对应的流程模板【{0}】", code));
                }
            }
            else if (!string.IsNullOrEmpty(processId))
            {
                var processEntity = await GetEntity(processId);
                if (processEntity != null)
                {
                    var data = await client.Queryable<WFScheme>().FirstAsync(a => a.Id == processEntity.SchemeId);
                    if (data != null)
                    {
                        wfParams.Scheme = data.Content;
                        wfParams.SchemeCode = processEntity.SchemeCode;
                        wfParams.SchemeId = processEntity.SchemeId;
                        wfParams.SchemeName = processEntity.SchemeName;
                        wfParams.IsChild = processEntity.IsChild == 1;
                        wfParams.ParentProcessId = processEntity.ParentProcessId;
                        wfParams.ParentTaskId = processEntity.ParentTaskId;
                        wfParams.ParentNodeId = processEntity.ParentNodeId;
                        wfParams.ProcessId = processId;
                        wfParams.HasInstance = true;
                        wfParams.IsStart = processEntity.IsStart == 1 ? 1 : 0;
                        wfParams.Title = processEntity.Title;

                        wfParams.CreateUser = new WFUserInfo()
                        {
                            Id = processEntity.CreateUserId,
                            Account = processEntity.CreateUserAccount,
                            Name = processEntity.CreateUserName,
                            CompanyId = processEntity.CreateUserCompanyId,
                            DepartmentId = processEntity.CreateUserDepartmentId
                        };
                    }
                    else
                    {
                        throw new Exception(string.Format("无法获取流程模板【{0}】", processEntity.SchemeId));
                    }
                }
                else if (string.IsNullOrEmpty(wfParams.Scheme))
                {
                    throw new Exception(string.Format("无法获取实例数据【{0}】", processId));
                }
            }


            wfParams.NextUsers = nextUsers;


            // 注册委托方法
            wfEngineConfig.GetAwaitTaskList = GetAwaitTaskList;
            wfEngineConfig.GetUserList = GetUserList;
            wfEngineConfig.GetSystemUserList = GetSystemUserList;
            wfEngineConfig.GetPrevTaskUserList = GetPrevTaskUserList;
            wfEngineConfig.IsCountersignAgree = IsCountersignAgree;
            wfEngineConfig.GetPrevUnitId = GetPrevUnitId;


            IWFEngine iwfEngine = new WFEngine(wfEngineConfig, client);

            return iwfEngine;
        }

        /// <summary>
        /// 获取等待任务
        /// </summary>
        /// <param name="processId">流程进程ID</param>
        /// <param name="unitId">流程单元ID</param>
        /// <returns></returns>
        private async Task<List<WorkFlow.WFTask>> GetAwaitTaskList(string processId, string unitId)
        {
            List<WorkFlow.WFTask> res = new List<WorkFlow.WFTask>();
            var list = await client.Queryable<WFTask>().Where(t => t.ProcessId == processId && t.UnitId == unitId && t.Type == 21 && t.State == 1).ToListAsync();

            foreach (var item in list)
            {
                res.Add(GetWFTask(item));
            }
            return res;
        }
        /// <summary>
        /// 获取设置人员
        /// </summary>
        /// <param name="auditorList">人员配置信息</param>
        /// <param name="createUser">流程发起人</param>
        /// <param name="processId">流程进程实例ID</param>
        /// <param name="startNode">开始节点</param>
        /// <returns></returns>
        private async Task<List<WFUserInfo>> GetUserList(List<WFAuditor> auditorList, WFUserInfo createUser, string processId, WFUnit startNode)
        {
            var res = new List<WFUserInfo>();
            List<string> userIds = new List<string>();
            foreach (var item in auditorList)
            {
                switch (item.Type)
                {
                    //岗位
                    case "1":
                        var rlist = await userManager.UserIdsByPosition("", item.Id);
                        foreach (var ritem in rlist)
                        {
                            userIds.Add(ritem);
                        }
                        break;
                    //角色
                    case "2":
                        var rlist2 = await userManager.UserIdsByRole(item.Id);
                        List<string> userIds2 = new List<string>();
                        foreach (var ritem2 in rlist2)
                        {
                            userIds2.Add(ritem2);
                        }
                        var userList2 = await GetListByKeyValues(userIds2.ToArray());
                        var userOrgs = await userManager.UserOrgsByUserIds(userIds2);
                        foreach (var userOrg in userOrgs)
                        {
                            var user2 = userList2.FirstOrDefault(a => a.Id.ToString() == userOrg.Key);
                            switch (item.Condition)
                            {
                                case "1":
                                    if ((userOrg.Value as List<string>).Contains(createUser.DepartmentId))
                                    {
                                        res.Add(GetWFUserInfo(user2));
                                    }
                                    break;
                                //case "2":
                                //    if (user2.CompanyId == createUser.CompanyId)
                                //    {
                                //        res.Add(GetWFUserInfo(user2));
                                //    }
                                //    break;
                                case "3":
                                    //// 获取当前用户的岗位
                                    var postList1 = await userManager.PositonsByUser(createUser.Id);// 发起人岗位
                                    var postList2 = await userManager.PositonsByUser(user2.Id.ToString());// 节点审核人岗位
                                                                                                          //if (await _postIBLL.IsUp(postList1, postList2))
                                    if (await positionManager.IsUp(postList1, postList2))
                                    {
                                        res.Add(GetWFUserInfo(user2));
                                    }
                                    break;
                                case "4":
                                    // 获取当前用户的岗位
                                    var postList3 = await userManager.PositonsByUser(createUser.Id);// 发起人岗位
                                    var postList4 = await userManager.PositonsByUser(user2.Id.ToString());// 节点审核人岗位
                                    if (await positionManager.IsDown(postList3, postList4))
                                    {
                                        res.Add(GetWFUserInfo(user2));
                                    }
                                    break;
                                default:
                                    res.Add(GetWFUserInfo(user2));
                                    break;
                            }
                        }
                        break;
                    //用户
                    case "3":
                        userIds.Add(item.Id);
                        break;
                    //上下级
                    case "4":
                        var postIds = await userManager.PositonsByUser(createUser.Id);// 发起人岗位
                        int level = Convert.ToInt32(item.Id);
                        List<string> postList;
                        if (level < 6)
                        {
                            postList = (await positionManager.GetUpIdList(postIds, level)).ToList();
                        }
                        else
                        {
                            level = level - 5;
                            postList = (await positionManager.GetDownIdList(postIds, level)).ToList();
                        }
                        var userRelationList4 = await userManager.UserIdsByPositions(postList);
                        userIds.AddRange(userRelationList4);
                        break;
                    //节点执行人
                    case "5":
                        if (item.Id == startNode.Id)
                        {
                            res.Add(createUser);
                        }
                        else
                        {
                            var taskList = await GetLastFinishTaskList(item.Id, processId);
                            foreach (var task in taskList)
                            {
                                userIds.Add(task.UserId);
                            }
                        }

                        break;
                    //数据库表字段
                    case "6":
                        using (var db = this.CodeClient(item.DbCode, _configuration))
                        {
                            DataTable dt = await db.Ado.GetDataTableAsync(string.Format("select {0} from {1} where {2} = @processId ", item.AuditorField, item.Table, item.Rfield), new { processId });
                            foreach (DataRow row in dt.Rows)
                            {
                                var userIdString = row[0].ToString();
                                if (!string.IsNullOrEmpty(userIdString))
                                {
                                    var userIdList = userIdString.Split(",");
                                    foreach (var userIdItem in userIdList)
                                    {
                                        userIds.Add(userIdItem);
                                    }
                                }
                            }
                            break;
                        }

                    //数据库表字段
                    case "7":
                        using (var db = this.CodeClient(item.DbCode, _configuration))
                        {
                            //获取数据id
                            var process = await client.Queryable<WFProcess>().FirstAsync(a => a.Id == processId);
                            WFInstanceInfo instanceInfo = null;
                            if (process != null)
                            {
                               // instanceInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<WFInstanceInfo>(process.InstanceInfo);
                               instanceInfo = process.InstanceInfo;
                            }
                            DataTable dt = await db.Ado.GetDataTableAsync(string.Format(item.Sql), new { pkeyValue = instanceInfo.pkeyValue });
                            foreach (DataRow row in dt.Rows)
                            {
                                var userIdString = row[0].ToString();
                                if (!string.IsNullOrEmpty(userIdString))
                                {
                                    var userIdList = userIdString.Split(",");
                                    foreach (var userIdItem in userIdList)
                                    {
                                        userIds.Add(userIdItem);
                                    }
                                }
                            }
                            break;
                        }
                }
            }
            var userList = await GetListByKeyValues(userIds.ToArray());
            foreach (var user in userList)
            {
                res.Add(GetWFUserInfo(user));
            }
            return res;
        }
        /// <summary>
        /// 获取单元上一次的审核人
        /// </summary>
        /// <param name="processId">流程进程ID</param>
        /// <param name="unitId">流程单元ID</param>
        /// <returns></returns>
        private async Task<List<WFUserInfo>> GetPrevTaskUserList(string processId, string unitId)
        {
            var res = new List<WFUserInfo>();
            var list = await GetLastTaskList(processId, unitId);
            foreach (var item in list)
            {
                if (!string.IsNullOrEmpty(item.UserId))
                {
                    res.Add(new WFUserInfo()
                    {
                        Id = item.UserId,
                        Name = item.UserName,
                        CompanyId = item.UserCompanyId,
                        DepartmentId = item.UserDepartmentId,
                        IsAgree = item.IsAgree == 1,
                        //Sort = item,
                        State = (int)item.State
                    });
                }
            }
            return res;
        }
        /// <summary>
        /// 获取系统管理员
        /// </summary>
        /// <returns></returns>
        private async Task<List<WFUserInfo>> GetSystemUserList()
        {
            var res = new List<WFUserInfo>();

            var user = new SysUser
            {
                Id = -1,
                Account = Define.SYSTEM_USERNAME,
                Name = "超级管理员"
            };
            res.Add(GetWFUserInfo(user));

            return res;
        }
        /// <summary>
        /// 判断会签是否通过
        /// </summary>
        /// <param name="processId">流程进程ID</param>
        /// <param name="unitId">流程单元ID</param>
        /// <returns></returns>
        private async Task<bool> IsCountersignAgree(string processId, string unitId)
        {
            var list = (List<WFTaskLog>)await GetLogList(processId, unitId);
            if (list.Count == 0)
            {
                return false;
            }
            return list[0].IsAgree == 1;
        }
        /// <summary>
        /// 获取上一个流入节点（不是驳回流入的）
        /// </summary>
        /// <param name="processId"></param>
        /// <param name="unitId"></param>
        /// <returns></returns>
        private async Task<string> GetPrevUnitId(string processId, string unitId)
        {
            var data = await GetLastNotRejectTask(processId, unitId);
            if (data != null)
            {
                return data.PrevUnitId;
            }
            else
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// 获取流程任务数据
        /// </summary>
        /// <param name="wfTaskEntity"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetWFTask(WFTask wfTaskEntity)
        {
            var res = new WorkFlow.WFTask()
            {
                UnitId = wfTaskEntity.UnitId,
                Name = wfTaskEntity.UnitName,
                PrevUnitId = wfTaskEntity.PrevUnitId,
                PrevUnitName = wfTaskEntity.PrevUnitName,
                Token = wfTaskEntity.Token,
                Type = (int)wfTaskEntity.Type
            };
            return res;
        }
        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="userEntity"></param>
        /// <returns></returns>
        private WFUserInfo GetWFUserInfo(SysUser userEntity)
        {
            var res = new WFUserInfo()
            {
                Id = userEntity.Id.ToString(),
                Name = userEntity.Name,
                Account = userEntity.Account,
                //DepartmentId = userEntity.F_DepartmentId,
                //CompanyId = userEntity.F_CompanyId,
                IsNew = true
            };
            return res;
        }
        /// <summary>
        /// 获取流程实例
        /// </summary>
        /// <param name="myParams">流程运行参数</param>
        /// <param name="title">标题</param>
        /// <returns></returns>
        private WFProcess GetWFProcessEntity(WFParams myParams, string title)
        {
            WFProcess wfProcessEntity = new WFProcess()
            {
                Id = myParams.ProcessId,
                SchemeCode = myParams.SchemeCode,
                SchemeId = myParams.SchemeId,
                SchemeName = myParams.SchemeName,
                Title = title,
                EnabledMark = 1,
                IsAgain = 0,
                IsFinished = 0,
                IsChild = myParams.IsChild ? 1 : 0,
                IsStart = 0,
                IsCancel = 1,
                ParentNodeId = myParams.ParentNodeId,
                ParentProcessId = myParams.ParentProcessId,
                ParentTaskId = myParams.ParentTaskId,
                CreateUserId = myParams.CreateUser.Id,
                CreateUserName = myParams.CreateUser.Name,
                CreateUserAccount = myParams.CreateUser.Account,
                CreateUserCompanyId = myParams.CreateUser.CompanyId,
                CreateUserDepartmentId = myParams.CreateUser.DepartmentId,
                UserId = _auth.GetUserId()
            };

            return wfProcessEntity;

        }

        /// <summary>
        /// 处理任务
        /// </summary>
        /// <param name="list">任务列表</param>
        /// <param name="iWFEngine"></param>
        /// <param name="processId">流程进程实例</param>
        /// <param name="prevToken">任务Token</param>
        /// <param name="taskId">任务id</param>
        /// <returns></returns>
        private async Task<List<WFTask>> ExecuteWFTaskEntity(List<WorkFlow.WFTask> list, IWFEngine iWFEngine, string processId, string prevToken, string taskId = "")
        {
            var res = new List<WFTask>();

            //单任务审核
            var tlist = list.Where(r => r.Type == 7).ToList();
            if (tlist.Count > 0)
            {
                var group = tlist.GroupBy(r => r.UnitId).ToList();
                foreach (var item in group)
                {
                    var taskuser = new List<WFTaskUser>();
                    var users = tlist.Where(r => r.UnitId == item.Key).ToList();
                    var userTask = new WFTask
                    {
                        Id = Guid.NewGuid().ToString(),
                        Type = users[0].Type,
                        ProcessId = processId,
                        Token = users[0].Token,
                        UnitId = users[0].UnitId,
                        UnitName = users[0].Name,
                        PrevUnitId = users[0].PrevUnitId,
                        PrevUnitName = users[0].PrevUnitName,
                        PrevToken = prevToken,
                        PrevTaskId = taskId,
                        UserId = users[0].User.Id,
                        UserName = users[0].User.Name,
                        UserDepartmentId = users[0].User.DepartmentId,
                        UserCompanyId = users[0].User.CompanyId,
                        State = users[0].User.IsAwait ? 2 : 1,
                        Sort = users[0].User.Sort,
                        IsReject = users[0].IsReject ? 1 : 0,
                        ChildProcessId = users[0].ChildSchemeInfoId,

                        TimeoutInterval = users[0].OvertimeMessageInterval,
                        TimeoutStrategy = users[0].OvertimeMessageType,

                        IsBatchAudit = users[0].IsBatchAudit ? 1 : 0,
                        ProcessUserId = iWFEngine.CreateUser.Id,
                        ProcessUserName = iWFEngine.CreateUser.Name,
                        ProcessCode = iWFEngine.Config.Params.SchemeCode,
                        ProcessTitle = iWFEngine.Config.Params.Title,
                        IsRetract=0
                    };
                    if (users[0].IsOvertimeMessage)
                    {
                        if (users[0].OvertimeGo > 0)
                        {
                            userTask.TimeoutAction = DateTime.Now.AddHours(users[0].OvertimeGo);
                        }
                        if (users[0].OvertimeMessageStart > 0)
                        {
                            userTask.TimeoutNotice = DateTime.Now.AddHours(users[0].OvertimeMessageStart);
                        }
                    }
                    foreach (var ts in users)
                    {
                        WFTaskUser tu = new WFTaskUser();
                        tu.UserId = ts.User.Id;
                        tu.TaskId = userTask.Id;
                        taskuser.Add(tu);
                    }
                    userTask.WFTaskUser = taskuser;
                    res.Add(userTask);
                }
            }
            foreach (var item in list)
            {
                if (!string.IsNullOrEmpty(item.MessageType))
                {
                    // 发送消息
                    var taskType = "";
                    switch (item.Type)
                    {
                        case 1:
                        case 5:
                        case 7:
                            taskType = "审核";
                            break;
                        case 2:
                            taskType = "查阅";
                            break;
                        case 3:
                            taskType = "提交";
                            break;
                        case 4:
                            taskType = "重新提交";
                            break;
                    }
                    if (!string.IsNullOrEmpty(taskType))
                    {
                        var msg = $"【{taskType}】{iWFEngine.Config.Params.Title},{item.Name}";
                        var userList = new List<string>();
                        userList.Add(item.User.Id);
                        //await _imMsgIBLL.SendMsg("IMWF", userList, msg, item.MessageType, item.Token);
                    }
                }

                string childSchemeInfoCode = "";
                if (item.Type == 3)
                {
                    var schemeInfo = await this.Repository.ChangeRepository<SugarRepositiry<WFSchemeInfo>>().GetByIdAsync(item.ChildSchemeInfoId);
                    if (schemeInfo != null)
                    {
                        childSchemeInfoCode = schemeInfo.Code;
                    }
                }

                switch (item.Type)
                {
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                        var userTask = new WFTask
                        {
                            Type = item.Type,
                            ProcessId = processId,
                            Token = item.Token,
                            UnitId = item.UnitId,
                            UnitName = item.Name,
                            PrevUnitId = item.PrevUnitId,
                            PrevUnitName = item.PrevUnitName,
                            PrevToken = prevToken,
                            PrevTaskId = taskId,
                            UserId = item.User.Id,
                            UserName = item.User.Name,
                            UserDepartmentId = item.User.DepartmentId,
                            UserCompanyId = item.User.CompanyId,
                            State = item.User.IsAwait ? 2 : 1,
                            Sort = item.User.Sort,
                            IsReject = item.IsReject ? 1 : 0,
                            ChildProcessId = item.ChildSchemeInfoId,
                            ChildSchemeInfoCode = childSchemeInfoCode,

                            TimeoutInterval = item.OvertimeMessageInterval,
                            TimeoutStrategy = item.OvertimeMessageType,

                            IsBatchAudit = item.IsBatchAudit ? 1 : 0,
                            ProcessUserId = iWFEngine.CreateUser.Id,
                            ProcessUserName = iWFEngine.CreateUser.Name,
                            ProcessCode = iWFEngine.Config.Params.SchemeCode,
                            ProcessTitle = iWFEngine.Config.Params.Title,
                            IsRetract=0
                        };
                        if (item.IsOvertimeMessage)
                        {
                            if (item.OvertimeGo > 0)
                            {
                                userTask.TimeoutAction = DateTime.Now.AddHours(item.OvertimeGo);
                            }
                            if (item.OvertimeMessageStart > 0)
                            {
                                userTask.TimeoutNotice = DateTime.Now.AddHours(item.OvertimeMessageStart);
                            }
                        }

                        res.Add(userTask);
                        break;
                    case 10:
                        // 执行脚本
                        res.Add(new WFTask
                        {
                            Type = item.Type,
                            ProcessId = processId,
                            Token = item.Token,
                            UnitId = item.UnitId,
                            UnitName = item.Name,
                            PrevUnitId = item.PrevUnitId,
                            PrevUnitName = item.PrevUnitName,
                            PrevToken = prevToken
                        });
                        break;
                    case 21:
                        res.Add(new WFTask
                        {
                            Type = item.Type,
                            ProcessId = processId,
                            Token = item.Token,
                            UnitId = item.UnitId,
                            UnitName = item.Name,
                            PrevUnitId = item.PrevUnitId,
                            PrevUnitName = item.PrevUnitName,
                            PrevToken = prevToken,
                            State = 1,
                        });
                        break;
                    case 22:
                        await CloseTask(processId, item.UnitId, 21, taskId);
                        break;
                    case 23:
                    case 24:
                        WFTaskLog wfTaskLogEntity = new WFTaskLog()
                        {
                            Des = "系统任务",
                            TaskType = item.Type,
                            Token = item.Token,
                            ProcessId = processId,
                            UnitId = item.UnitId,
                            UnitName = item.Name,
                            PrevUnitId = item.PrevUnitId,
                            PrevUnitName = item.PrevUnitName
                        };
                        await AddLog(wfTaskLogEntity);
                        break;
                    case 26:
                        // 更新任务状态
                        await Update(processId, item.UnitId);
                        break;
                }
            }
            return res;
        }

        public void AddOpenJob(WFTask task, DateTime outtime, DateTime overtime)
        {
            try
            {
                AddOrUpdateOpenJobReq req = new AddOrUpdateOpenJobReq();
                req.JobName = $"超时通知 {task.Id}";
                req.JobType = 0;
                req.JobCallParams = "{\"TaskId\":\"" + task.Id + "\"}";
                req.JobCall = "OpenAuth.App.BaseApp.Jobs.TaskTimeoutJob";
                req.Status = 1;
                req.Cron = GetCorn(outtime);
                req.Remark = $"{task.ProcessUserId}--{task.UnitName}";
                _job.AddStart(req);

                AddOrUpdateOpenJobReq req1 = new AddOrUpdateOpenJobReq();
                req1.JobName = $"严重超时通知 {task.Id}";
                req1.JobType = 0;
                req1.JobCallParams = "{\"TaskId\":\"" + task.Id + "\"}";
                req1.JobCall = "OpenAuth.App.BaseApp.Jobs.TaskOverTimeJob";
                req1.Status = 1;
                req1.Cron = GetCorn(overtime);
                req1.Remark = $"{task.ProcessUserId}--{task.UnitName}";
                _job.AddStart(req1);
            }
            catch
            {
                return;
            }
        }


        public string GetCorn(DateTime time)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(time.Second.ToString());
            sb.Append(" ");
            sb.Append(time.Minute.ToString());
            sb.Append(" ");
            sb.Append(time.Hour.ToString());
            sb.Append(" ");
            sb.Append(time.Day.ToString());
            sb.Append(" ");
            sb.Append(time.Month.ToString());
            sb.Append(" ");
            sb.Append("?");
            sb.Append(" ");
            sb.Append(time.Year.ToString());
            return sb.ToString();
        }
        /// <summary>
        /// 执行脚本
        /// </summary>
        /// <param name="task">脚本任务</param>
        /// <param name="code"></param>
        /// <param name="processId"></param>
        /// <param name="prevTaskId"></param>
        /// <param name="createUser"></param>
        /// <param name="iWFEngine"></param>
        /// <param name="preTask"></param>
        /// <returns></returns>
        private async Task<bool> ExecuteScript(WFTask task, string code, string processId, string prevTaskId,string nextid, WFUserInfo createUser, IWFEngine iWFEngine, WFTask preTask,string des)
        {
            SysUser userInfo;
            if (preTask == null)
            {
                userInfo = new SysUser()
                {
                    Id = long.Parse(createUser.Id),
                    Account = createUser.Account,
                    //CompanyId = createUser.CompanyId,
                    //F_DepartmentId = createUser.DepartmentId
                };
            }
            else
            {
                //userInfo = await this.CurrentUser(preTask.F_UserId);
                userInfo = _auth.GetCurrentUser().User;
            }
            string nextnode = "";
            if (!string.IsNullOrEmpty(nextid))
            {
                nextnode = iWFEngine.GetNode(nextid).Name;
            }

            var process = await client.Queryable<WFProcess>().FirstAsync(a => a.Id == processId);

            WFInstanceInfo instanceInfo = null;
            if (process != null)
            {
               // instanceInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<WFInstanceInfo>(process.InstanceInfo);
               instanceInfo = process.InstanceInfo;
            }

            var param = new
            {
                processId,
                parentprocessId=process.ParentProcessId,
                userId = createUser.Id,
                userAccount = createUser.Account,
                companyId = createUser.CompanyId,
                departmentId = createUser.DepartmentId,
                userName2 = userInfo.Name,
                userId2 = userInfo.Id.ToString(),
                userAccount2 = userInfo.Account,
                //companyId2 = userInfo.F_CompanyId,
                //departmentId2 = userInfo.F_DepartmentId,
                code,
                nodeName=nextnode,
                pkeyValue = instanceInfo == null ? "" : instanceInfo.pkeyValue,
                des=des
            };
            try
            {
                var node = iWFEngine.GetNode(task.UnitId);
                switch (node.ExecuteType)
                {
                    case "1":
                        if (!string.IsNullOrEmpty(node.SqlDb) && !string.IsNullOrEmpty(node.SqlStr))
                        {
                            //string sql = @"update drone_caseinfo set handle_status_id = '0',handle_status_name ='待办理',examiner_id = @userId2 ,examiner_name=@userAccount2, examine_time = (NOW())   where ""Id""=@pkeyValue";
                            await client.Ado.ExecuteCommandAsync(node.SqlStr, param);
                            //await wfProcessSerive.BaseRepository(node.SqlDb).ExecuteSql(node.SqlStr, param);
                        }
                        break;
                    case "2":
                        if (!string.IsNullOrEmpty(node.Ioc) && IocManager.Instance.IsRegistered<WorkFlow.IWorkFlowMethod>(node.Ioc))
                        {
                            WorkFlow.IWorkFlowMethod iWorkFlowMethod = IocManager.Instance.GetService<WorkFlow.IWorkFlowMethod>(node.Ioc);
                            WorkFlow.WfMethodParameter wfMethodParameter = new WorkFlow.WfMethodParameter()
                            {
                                ProcessId = processId,
                                UnitName = task.UnitName,
                                TaskId = prevTaskId,
                                Code = code,
                                UserId = createUser.Id,
                                UserAccount = createUser.Account,
                                CompanyId = createUser.CompanyId,
                                DepartmentId = createUser.DepartmentId
                            };
                            await iWorkFlowMethod.Execute(wfMethodParameter);
                        }
                        break;
                    case "3":
                        if (!string.IsNullOrEmpty(node.ApiUrl))
                        {
                            await HttpMethods.Post(node.ApiUrl, Json.ToJson(param));
                        }
                        break;

                }

                /*脚本执行成功*/
                WFTaskLog wfTaskLogEntity = new WFTaskLog()
                {
                    Des = "脚本执行成功",
                    TaskType = 99,
                    ProcessId = processId,
                    TaskId = task.Id,
                    UnitId = task.UnitId,
                    UnitName = task.UnitName
                };
                await AddLog(wfTaskLogEntity);
                return true;
            }
            catch (Exception ex)
            {
                WFTaskLog wfTaskLogEntity = new WFTaskLog()
                {
                    Des = string.Format("脚本执行异常:{0}", ex.Message),
                    TaskType = 99,
                    ProcessId = processId,
                    TaskId = task.Id,
                    UnitId = task.UnitId,
                    UnitName = task.UnitName
                };
                await AddLog(wfTaskLogEntity);
                return false;
            }
        }


        /// <summary>
        /// 执行脚本
        /// </summary>
        /// <param name="processId"></param>
        /// <param name="code"></param>
        /// <param name="createUser"></param>
        /// <param name="executeType"></param>
        /// <param name="sqlDb"></param>
        /// <param name="sqlStr"></param>
        /// <param name="apiUrl"></param>
        /// <param name="iocName"></param>
        /// <returns></returns>
        private async Task<bool> ExecuteScript(string processId, string code, WFUserInfo createUser, string executeType, string sqlDb, string sqlStr, string apiUrl, string iocName)
        {
            var param = new
            {
                processId,
                userId = createUser.Id,
                userAccount = createUser.Account,
                companyId = createUser.CompanyId,
                departmentId = createUser.DepartmentId,
                code
            };

            try
            {
                switch (executeType)
                {
                    case "1":
                        if (!string.IsNullOrEmpty(sqlDb) && !string.IsNullOrEmpty(sqlStr))
                        {
                            //await wfProcessSerive.BaseRepository(sqlDb).ExecuteSql(sqlStr, param);
                            await client.Ado.ExecuteCommandAsync(sqlStr, param);
                        }
                        break;
                    case "2":
                        if (!string.IsNullOrEmpty(iocName) && IocManager.Instance.IsRegistered<WorkFlow.IWorkFlowMethod>(iocName))
                        {
                            WorkFlow.IWorkFlowMethod iWorkFlowMethod = IocManager.Instance.GetService<WorkFlow.IWorkFlowMethod>(iocName);
                            WorkFlow.WfMethodParameter wfMethodParameter = new WorkFlow.WfMethodParameter()
                            {
                                ProcessId = processId,
                                Code = code,
                                UserId = createUser.Id,
                                UserAccount = createUser.Account,
                                CompanyId = createUser.CompanyId,
                                DepartmentId = createUser.DepartmentId
                            };
                            await iWorkFlowMethod.Execute(wfMethodParameter);
                        }
                        break;
                    case "3":
                        if (!string.IsNullOrEmpty(apiUrl))
                        {
                            await HttpMethods.Post(apiUrl, Json.ToJson(param));
                        }
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }


        /// <summary>
        /// 执行脚本(撤销)
        /// </summary>
        /// <param name="unitId"></param>
        /// <param name="unitName"></param>
        /// <param name="processId"></param>
        /// <param name="createUser"></param>
        /// <param name="iWFEngine"></param>
        /// <returns></returns>
        private async Task ExecuteRevokeScript(string unitId, string unitName, string processId, WFUserInfo createUser, IWFEngine iWFEngine)
        {
            var param = new
            {
                processId,
                userId = createUser.Id,
                userAccount = createUser.Account,
                companyId = createUser.CompanyId,
                departmentId = createUser.DepartmentId,
                code = "revoke",
            };
            try
            {
                var node = iWFEngine.GetNode(unitId);
                switch (node.ExecuteType)
                {
                    case "1":
                        if (!string.IsNullOrEmpty(node.SqlDb) && !string.IsNullOrEmpty(node.SqlStrRevoke))
                        {
                            //await wfProcessSerive.BaseRepository(node.SqlDb).ExecuteSql(node.SqlStrRevoke, param);
                            await client.Ado.ExecuteCommandAsync(node.SqlStrRevoke, param);
                        }
                        break;
                    case "2":
                        if (!string.IsNullOrEmpty(node.IocRevoke) && IocManager.Instance.IsRegistered<WorkFlow.IWorkFlowMethod>(node.IocRevoke))
                        {
                            WorkFlow.IWorkFlowMethod iWorkFlowMethod = IocManager.Instance.GetService<WorkFlow.IWorkFlowMethod>(node.IocRevoke);
                            WorkFlow.WfMethodParameter wfMethodParameter = new WorkFlow.WfMethodParameter()
                            {
                                ProcessId = processId,
                                UnitName = unitName,
                                Code = "revoke",
                                UserId = createUser.Id,
                                UserAccount = createUser.Account,
                                CompanyId = createUser.CompanyId,
                                DepartmentId = createUser.DepartmentId
                            };
                            await iWorkFlowMethod.Execute(wfMethodParameter);
                        }
                        break;
                    case "3":
                        if (!string.IsNullOrEmpty(node.ApiUrlRevoke))
                        {
                            await HttpMethods.Post(node.ApiUrlRevoke, Json.ToJson(param));
                        }
                        break;

                }
            }
            catch (Exception ex)
            {
                WFTaskLog wfTaskLogEntity = new WFTaskLog()
                {
                    Des = string.Format("脚本执行异常:{0}", ex.Message),
                    TaskType = 99,
                    ProcessId = processId,
                    UnitId = unitId,
                    UnitName = $"{unitName}-撤销"
                };
                await AddLog(wfTaskLogEntity);

            }

        }

        /// <summary>
        /// 普通审核
        /// </summary>
        /// <param name="iWFEngine"></param>
        /// <param name="taskEntity"></param>
        /// <param name="code"></param>
        /// <param name="name"></param>
        /// <param name="nextId">下一个节点</param>
        /// <param name="des"></param>
        /// <param name="stampImg"></param>
        /// <returns></returns>
        private async Task AuditNode(IWFEngine iWFEngine, WFTask taskEntity, string code, string name, string des, string stampImg, string nextId = "")
        {
            // 下一部需要执行的任务
            var taskList = await iWFEngine.GetTask(taskEntity.UnitId, code, nextId);
            if (taskList.FindAll(t => t.Type != 10).Count == 0)
            {
                throw (new Exception("找不到下一个流转节点！"));
            }

            List<WFTask> myTaskList;
            // 处理任务并更新数据
            using (var uwo = UnitWork.CreateContext())
            {
                var process = await uwo.WFProcess.GetByIdAsync(taskEntity.ProcessId);
                await uwo.Db.Updateable<WFProcess>()
                      .SetColumns(p => new WFProcess { IsStart = 1, IsCancel = 0 })
                      .SetColumnsIF(taskList.FindIndex(t => t.Type == 100) != -1, p => p.IsFinished == 1)
                      .SetColumnsIF(taskList.FindIndex(t => t.Type == 4) != -1, p => p.IsAgain == 1)
                      .Where(p => p.Id == taskEntity.ProcessId)
                      .ExecuteCommandAsync();
                if (taskList.FindIndex(t => t.Type == 100) != -1)
                {
                    if (process.IsChild == 1)
                    {
                        await ChildrenEndTask(process.ParentProcessId, process.ParentNodeId, code, taskEntity, nextId);
                    }
                }

                // 更新任务状态
                taskEntity.IsAgree = code == "disagree" ? 0 : 1;
                taskEntity.State = 3;
                if (taskEntity.Type == 7)
                {
                    var currentUser = _auth.GetCurrentUser().User;
                    taskEntity.UserId = currentUser.Id.ToString();
                    taskEntity.UserName = currentUser.Name;
                }
                await uwo.WFTask.UpdateAsync(taskEntity);

                // 更新上一个流转过来的任务，提示他无法被撤销
                await CloseTaskLogCancel(taskEntity.ProcessId, taskEntity.PrevTaskId);

                // 关闭同一个节点，其他人的任务
                await CloseTask(taskEntity.ProcessId, taskEntity.Token, taskEntity.Id);

                myTaskList = await ExecuteWFTaskEntity(taskList, iWFEngine, taskEntity.ProcessId, taskEntity.Token, taskEntity.Id);
                foreach (var item in myTaskList)
                {
                    if (item.Type == 7)
                    {
                        await uwo.WFTaskUser.InsertRangeAsync(item.WFTaskUser);
                    }
                    await Add(item);
                }

                await CreateTaskLog(taskEntity, code, name, des, stampImg);

                uwo.Commit();
            }


            // 脚本执行
            var scriptTaskList = myTaskList.FindAll(t => t.Type == 10);
            foreach (var item in scriptTaskList)
            {
                await ExecuteScript(item, code, taskEntity.ProcessId, taskEntity.Id, nextId, iWFEngine.CreateUser, iWFEngine, taskEntity,des);
            }
        }


        /// <summary>
        /// 子流程结束，获取父流程下一任务
        /// </summary>
        /// <param name="processId">父流程id</param>
        /// <param name="unitId">父流程的节点id</param>
        /// <param name="code">上一任务code（类似agress，degress）</param>
        /// <param name="taskEntity">任务</param>
        /// <param name="nextId">下一节点</param>
        /// <returns></returns>
        private async Task ChildrenEndTask(string processId, string unitId, string code, WFTask taskEntity, string nextId = "")
        {
            var process = await GetEntity(processId);
            var iWFEngine = await Bootstraper("", processId, null, null);
            // 下一部需要执行的任务
            var taskList = await iWFEngine.GetTask(unitId, code, nextId);
            if (taskList.FindAll(t => t.Type != 10).Count == 0)
            {
                throw (new Exception("找不到下一个流转节点！"));
            }

            // 处理任务并更新数据
            //wfProcessSerive.BeginTrans();
            List<WFTask> myTaskList;
            using (var uwo = UnitWork.CreateContext())
            {
                try
                {
                    // 更新流程状态
                    await uwo.Db.Updateable<WFProcess>()
                      .SetColumns(p => new WFProcess { IsStart = 1, IsCancel = 0 })
                      .SetColumnsIF(taskList.FindIndex(t => t.Type == 100) != -1, p => p.IsFinished == 1)
                      .SetColumnsIF(taskList.FindIndex(t => t.Type == 4) != -1, p => p.IsAgain == 1)
                      .Where(p => p.Id == processId)
                      .ExecuteCommandAsync();

                    if (taskList.FindIndex(t => t.Type == 100) != -1)
                    {
                        if (process.IsChild == 1)
                        {
                            await ChildrenEndTask(process.ParentProcessId, process.ParentNodeId, code, taskEntity, nextId);
                        }
                    }

                    myTaskList = await ExecuteWFTaskEntity(taskList, iWFEngine, processId, taskEntity.Token, taskEntity.Id);
                    foreach (var item in myTaskList)
                    {
                        if (item.Type == 7)
                        {
                            await uwo.WFTaskUser.InsertRangeAsync(item.WFTaskUser);
                        }
                        await Add(item);
                    }
                }
                catch
                {
                    throw;
                }
                uwo.Commit();
            }
            // 脚本执行
            var scriptTaskList = myTaskList.FindAll(t => t.Type == 10);
            foreach (var item in scriptTaskList)
            {
                await ExecuteScript(item, code, processId, taskEntity.Id, nextId, iWFEngine.CreateUser, iWFEngine, taskEntity,"");
            }
        }


        private async Task AuditNodeByCountersign(IWFEngine iWFEngine, WFTask taskEntiy, string code, string name, string des, string stampImg)
        {
            taskEntiy.IsAgree = code == "disagree" ? 0 : 1;
            var node = iWFEngine.GetNode(taskEntiy.UnitId);
            var list = (List<WFTask>)await GetLastTaskList(taskEntiy.ProcessId, taskEntiy.UnitId);
            var myIndex = list.FindIndex(t => t.Id == taskEntiy.Id);
            if (myIndex == -1)
            {
                throw (new Exception("会签任务记录异常无法审核！"));
            }

            if (taskEntiy.IsAgree == 0)
            {
                if (node.CountersignType == "1")
                {
                    // 并行
                    if (node.IsCountersignAll)
                    {
                        // 等待
                        if (list.FindIndex(t => t.Id != taskEntiy.Id && t.State == 1) != -1)
                        {
                            // 表示还有人没有审核
                            // 表示还有任务没有完成
                            using (var uwo = UnitWork.CreateContext())
                            {
                                WFProcess processEntity = new WFProcess()
                                {
                                    Id = taskEntiy.ProcessId,
                                    IsStart = 1,
                                    IsCancel = 0,
                                };
                                await uwo.WFProcess.UpdateAsync(processEntity);
                                taskEntiy.State = 3;
                                await uwo.WFTask.UpdateAsync(taskEntiy);
                                await CreateTaskLog(taskEntiy, code, name, des, stampImg);

                                uwo.Commit();
                            }
                        }
                        else
                        {
                            var num = await GetTaskUserMaxNum(taskEntiy.ProcessId, taskEntiy.UnitId);
                            var fnum = list.FindAll(t => t.State == 3 && t.IsAgree == 0).Count + 1;
                            if ((num - fnum) * 100 / num >= node.CountersignAllType)
                            {
                                await AuditNode(iWFEngine, taskEntiy, "agree", "同意", des, stampImg);
                            }
                            else
                            {
                                await AuditNode(iWFEngine, taskEntiy, code, name, des, stampImg);
                            }
                        }
                    }
                    else
                    {
                        // 不等待，每次都需要计算通过率
                        var num = await GetTaskUserMaxNum(taskEntiy.ProcessId, taskEntiy.UnitId);
                        var fnum = list.FindAll(t => t.State == 3 && t.IsAgree == 0).Count + 1;
                        if ((num - fnum) * 100 / num >= node.CountersignAllType)// 表示还有通过的希望
                        {
                            using (var uwo = UnitWork.CreateContext())
                            {
                                WFProcess processEntity = new WFProcess()
                                {
                                    Id = taskEntiy.ProcessId,
                                    IsStart = 1,
                                    IsCancel = 0,
                                };
                                await uwo.WFProcess.UpdateAsync(processEntity);
                                taskEntiy.State = 3;
                                await uwo.WFTask.UpdateAsync(taskEntiy);
                                await CreateTaskLog(taskEntiy, code, name, des, stampImg);

                                uwo.Commit();
                            }
                        }
                        else
                        {
                            await AuditNode(iWFEngine, taskEntiy, code, name, des, stampImg);
                        }
                    }
                }
                else
                {
                    // 串行
                    await AuditNode(iWFEngine, taskEntiy, code, name, des, stampImg);
                }
            }
            else
            {
                if (node.CountersignType == "1")
                {
                    // 并行

                    // 如果不等待，不同意直接跳转
                    if (node.IsCountersignAll)
                    {
                        if (list.FindIndex(t => t.Id != taskEntiy.Id && t.State == 1) != -1) // 表示还有人没有处理完
                        {
                            // 表示还有任务没有完成
                            using (var uwo = UnitWork.CreateContext())
                            {
                                WFProcess processEntity = new WFProcess()
                                {
                                    Id = taskEntiy.ProcessId,
                                    IsStart = 1,
                                    IsCancel = 0,
                                };
                                await uwo.WFProcess.UpdateAsync(processEntity);
                                taskEntiy.State = 3;
                                await uwo.WFTask.UpdateAsync(taskEntiy);
                                await CreateTaskLog(taskEntiy, code, name, des, stampImg);
                                uwo.Commit();
                            }
                        }
                        else
                        {
                            var num = await GetTaskUserMaxNum(taskEntiy.ProcessId, taskEntiy.UnitId);
                            var fnum = list.FindAll(t => t.State == 3 && t.IsAgree == 0).Count;
                            if ((num - fnum) * 100 / num >= node.CountersignAllType)
                            {
                                await AuditNode(iWFEngine, taskEntiy, "agree", "同意", des, stampImg);
                            }
                            else
                            {
                                await AuditNode(iWFEngine, taskEntiy, "disagree", "不同意", des, stampImg);
                            }
                        }
                    }
                    else
                    {
                        var num = await GetTaskUserMaxNum(taskEntiy.ProcessId, taskEntiy.UnitId);
                        var snum = list.FindAll(t => t.State == 3 && t.IsAgree == 1).Count;
                        if (snum * 100 / num >= node.CountersignAllType)
                        {
                            await AuditNode(iWFEngine, taskEntiy, "agree", "同意", des, stampImg);
                        }
                        else
                        {
                            using (var uwo = UnitWork.CreateContext())
                            {
                                WFProcess processEntity = new WFProcess()
                                {
                                    Id = taskEntiy.ProcessId,
                                    IsStart = 1,
                                    IsCancel = 0,
                                };
                                await uwo.WFProcess.UpdateAsync(processEntity);
                                taskEntiy.State = 3;
                                await uwo.WFTask.UpdateAsync(taskEntiy);
                                await CreateTaskLog(taskEntiy, code, name, des, stampImg);

                                uwo.Commit();
                            }
                        }
                    }
                }
                else
                {
                    // 串行
                    if (myIndex == list.Count - 1) // 表示最后一个人审核完成，然后往下执行
                    {
                        await AuditNode(iWFEngine, taskEntiy, code, name, des, stampImg);
                    }
                    else
                    {
                        // 表示还有任务没有完成
                        using (var uwo = UnitWork.CreateContext())
                        {
                            WFProcess processEntity = new WFProcess()
                            {
                                Id = taskEntiy.ProcessId,
                                IsStart = 1,
                                IsCancel = 0,
                            };
                            await uwo.WFProcess.UpdateAsync(processEntity);
                            taskEntiy.State = 3;
                            await uwo.WFTask.UpdateAsync(taskEntiy);
                            await CreateTaskLog(taskEntiy, code, name, des, stampImg);


                            if (node.CountersignType == "2")
                            {
                                // 串行，更新上一个任务的撤销操作，开启下一个任务
                                if (myIndex == 0)
                                {
                                    await CloseTaskLogCancel(taskEntiy.ProcessId, taskEntiy.PrevTaskId);
                                }
                                else
                                {
                                    await CloseTaskLogCancel(list[myIndex - 1].Id);
                                }
                                await uwo.WFTask.UpdateAsync(new WFTask { Id = list[myIndex + 1].Id, State = 1 });
                            }
                            var flag = uwo.Commit();
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 创建日志
        /// </summary>
        /// <param name="taskEntiy"></param>
        /// <param name="code"></param>
        /// <param name="name"></param>
        /// <param name="des"></param>
        /// <param name="stampImg"></param>
        /// <returns></returns>
        private async Task CreateTaskLog(WFTask taskEntiy, string code, string name, string des, string stampImg)
        {

            WFTaskLog wfTaskLogEntity = new WFTaskLog()
            {
                Des = $"【{name}】{des}",
                TaskType = taskEntiy.Type,
                ProcessId = taskEntiy.ProcessId,
                UnitId = taskEntiy.UnitId,
                UnitName = taskEntiy.UnitName,
                IsAgree = taskEntiy.IsAgree,
                OperationCode = code,
                OperationName = name,
                Token = taskEntiy.Token,
                PrevUnitId = taskEntiy.PrevUnitId,
                PrevUnitName = taskEntiy.PrevUnitName,
                TaskId = taskEntiy.Id,
                StampImg = stampImg,
                IsCancel = 1,
                IsLast = 1

            };

            await UpdateLog(taskEntiy.ProcessId, taskEntiy.UnitId);
            await AddLog(wfTaskLogEntity);
        }
        #endregion


        public async Task<Response<bool>> Supervise(string processId,int supervise = 1)
        {
            // todo 实现督办
          
            var iWFEngine = await Bootstraper(string.Empty, processId, null, null);
            // 获取未完成的任务
            var taskList = await GetUnFinishTaskList(processId);
            using (var uwo = UnitWork.CreateContext())
            {

                foreach (var item in taskList)
                {
                    if (item.Type == 1 || item.Type == 3 || item.Type == 5 || item.Type == 6  || item.Type == 7)
                    {
                     
                        // 督办时间督办标志
                        item.IsSupervise = supervise;
                        item.SuperviseTime = DateTime.Now;
                        item.SuperviseId = _auth.GetCurrentUser().User.Id;
                        // 发送消息
                        var msg = $"【审核】【督办】{item.ProcessTitle},{item.UnitName}";
                        var userList = new List<string>();
                        // todo 单体任务处理
                        userList.Add(item.UserId);
                        var node = iWFEngine.GetNode(item.UnitId);
                        //await _imMsgIBLL.SendMsg("IMWF", userList, msg, node.MessageType, item.F_Token);

                        await uwo.WFTask.UpdateAsync(item);
                    }
                }

                //await wfProcessSerive.Update(new WFProcessEntity() { F_IsUrge = 1, F_Id = processId });

                var wfTaskLogEntity = new WFTaskLog
                {
                    Des = "督办审核",
                    TaskType = 98,
                    ProcessId = processId,
                    UnitId = iWFEngine.StartNode.Id,
                    UnitName = string.IsNullOrEmpty(iWFEngine.StartNode.Name) ? "开始节点" : iWFEngine.StartNode.Name,
                    CreateDate = DateTime.Now,
                    UserId = _auth.GetUserId(),
                    UserName = _auth.GetUserNickName(),
                    Id = Guid.NewGuid().ToString()
                };

                await uwo.WFTaskLog.InsertAsync(wfTaskLogEntity);

                var flag = uwo.Commit();
                return new Response<bool>
                {
                    Result = flag,
                    Message = flag ? "success" : "error"
                };
            }

        }



        #region 撤回
        /// <summary>
        /// 撤回流程
        /// </summary>
        /// <param name="taskId">流程任务主键</param>
        /// <param name="code">流程审批操作码agree 同意 disagree 不同意 lrtimeout 超时</param>
        /// <param name="name">流程审批操名称</param>
        /// <param name="des">审批意见</param>
        /// <param name="nextUsers">下一节点指定审核人</param>
        /// <param name="stampImg">盖章图片</param>
        /// <param name="stampPassWord">盖章图片密码</param>
        /// <param name="nextId">下一个审核节点</param>
        public async Task RetractFlow(string taskId, string code, string name, string des, Dictionary<string, string> nextUsers, string stampImg, string stampPassWord, string nextId)
        {
            var taskEntiy = await client.Queryable<WFTask>().Where(a => a.Id == taskId).FirstAsync();
            if (taskEntiy == null)
            {
                throw (new Exception("找不到对应流程任务！"));
            }
            else if (taskEntiy.State != 3&& taskEntiy.State != 4)
            {
                    throw (new Exception("该任务未完成！"));
            }

            //后期改
            stampImg = "";
            //stampImg = await _wFStampIBLL.ToWfImg(stampImg, stampPassWord);

            var iWFEngine = await Bootstraper("", taskEntiy.ProcessId, null, nextUsers);

            // 1.判断任务类型 1 普通任务 5 会签任务
            if (taskEntiy.Type == 1 || taskEntiy.Type == 7)
            {
                await RetractNode(iWFEngine, taskEntiy, code, name, des, stampImg, nextId);
            }
            else
            {
                throw (new Exception("该任务无法审核！"));
            }

            //await _imMsgIBLL.VirtualDeleteByContentId(taskEntiy.F_Token); // 更新消息

            // 发送消息
            var msg = $"【提醒】{iWFEngine.Config.Params.Title},{taskEntiy.UnitName}已被撤回";
            var userList = new List<string>();
            userList.Add(iWFEngine.CreateUser.Id);
            var node = iWFEngine.StartNode;
            //await _imMsgIBLL.SendMsg("IMWF", userList, msg, node.MessageType, iWFEngine.Config.Params.ProcessId);
        }

        /// <summary>
        /// 撤回
        /// </summary>
        /// <param name="iWFEngine"></param>
        /// <param name="taskEntity"></param>
        /// <param name="code"></param>
        /// <param name="name"></param>
        /// <param name="nextId">下一个节点</param>
        /// <param name="des"></param>
        /// <param name="stampImg"></param>
        /// <returns></returns>
        private async Task RetractNode(IWFEngine iWFEngine, WFTask taskEntity, string code, string name, string des, string stampImg, string nextId = "")
        {
            // 下一部需要执行的任务
            var taskList = await iWFEngine.GetTask(taskEntity.UnitId, code, nextId);

            List<WFTask> myTaskList;
            //修改原有任务的IsLast状态
            await client.Updateable<WFTask>()
               .SetColumns(t => new WFTask() { IsLast = 0 })
                .Where(t => t.Id==taskEntity.Id)
                .ExecuteCommandAsync();

            //删除该节点之后生成的所有任务
            var dellist=client.Queryable<WFTask>().Where(r=>r.CreateDate>taskEntity.CreateDate&&r.ProcessId==taskEntity.ProcessId).ToList();
            await client.Deleteable<WFTask>(dellist).ExecuteCommandAsync();
            // 处理任务并更新数据
            using (var uwo = UnitWork.CreateContext())
            {
                var process = await uwo.WFProcess.GetByIdAsync(taskEntity.ProcessId);
                await uwo.Db.Updateable<WFProcess>()
                      .SetColumns(p => new WFProcess { IsStart = 1, IsCancel = 0 })
                      .SetColumns(p=>p.IsFinished==0)
                      .SetColumnsIF(taskList.FindIndex(t => t.Type == 100) != -1, p => p.IsFinished == 1)
                      .SetColumnsIF(taskList.FindIndex(t => t.Type == 4) != -1, p => p.IsAgain == 1)
                      .Where(p => p.Id == taskEntity.ProcessId)
                      .ExecuteCommandAsync();
                if (taskList.FindIndex(t => t.Type == 100) != -1)
                {
                    if (process.IsChild == 1)
                    {
                        await ChildrenEndTask(process.ParentProcessId, process.ParentNodeId, code, taskEntity, nextId);
                    }
                }

                var newTask = new WFTask
                {
                    Id = Guid.NewGuid().ToString(),
                    Type = taskEntity.Type,
                    ProcessId = taskEntity.ProcessId,
                    Token = Guid.NewGuid().ToString(),
                    UnitId = taskEntity.UnitId,
                    UnitName = taskEntity.UnitName,
                    PrevUnitId = taskEntity.PrevUnitId,
                    PrevUnitName = taskEntity.PrevUnitName,
                    PrevToken = taskEntity.Token,
                    PrevTaskId = taskEntity.Id,
                    UserId = taskEntity.UserId,
                    UserName = taskEntity.UserName,
                    UserDepartmentId = taskEntity.UserDepartmentId,
                    UserCompanyId = taskEntity.UserCompanyId,
                    State = 1,
                    Sort = taskEntity.Sort,
                    IsReject = 0,
                    ChildProcessId = taskEntity.ChildProcessId,
                    ChildSchemeInfoCode = taskEntity.ChildSchemeInfoCode,

                    TimeoutInterval = taskEntity.TimeoutInterval,
                    TimeoutStrategy = taskEntity.TimeoutStrategy,

                    IsBatchAudit = taskEntity.IsBatchAudit,
                    ProcessUserId = iWFEngine.CreateUser.Id,
                    ProcessUserName = iWFEngine.CreateUser.Name,
                    ProcessCode = iWFEngine.Config.Params.SchemeCode,
                    ProcessTitle = iWFEngine.Config.Params.Title,
                    CreateDate = DateTime.Now,
                    CreateUserId = _auth.GetUserId(),
                    CreateUserName = _auth.GetUserName(),
                    IsLast=1,
                    IsRetract=1
                };
                await uwo.WFTask.InsertAsync(newTask);

                // 更新上一个流转过来的任务，提示他无法被撤销
                await CloseTaskLogCancel(taskEntity.ProcessId, taskEntity.PrevTaskId);

                // 关闭同一个节点，其他人的任务
                await CloseTask(taskEntity.ProcessId, taskEntity.Token, taskEntity.Id);

                myTaskList = await ExecuteWFTaskEntity(taskList, iWFEngine, taskEntity.ProcessId, taskEntity.Token, taskEntity.Id);
                foreach (var item in myTaskList)
                {
                    if (item.Type == 7)
                    {
                        await uwo.WFTaskUser.InsertRangeAsync(item.WFTaskUser);
                    }
                    await Add(item);
                }

                await CreateTaskLog(taskEntity, code, name, des, stampImg);

                uwo.Commit();
            }


            // 脚本执行
            var scriptTaskList = myTaskList.FindAll(t => t.Type == 10);
            foreach (var item in scriptTaskList)
            {
                await ExecuteScript(item, code, taskEntity.ProcessId, taskEntity.Id, nextId, iWFEngine.CreateUser, iWFEngine, taskEntity, des);
            }
        }


        #endregion
    }
}
