using JNPF.Common.Core.Manager; using JNPF.Common.Core.Manager.Files; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Filter; using JNPF.Common.Models.WorkFlow; using JNPF.Common.Security; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.FriendlyException; using JNPF.LinqBuilder; using JNPF.Systems.Entitys.Permission; using JNPF.Systems.Entitys.System; using JNPF.Systems.Interfaces.Permission; using JNPF.Systems.Interfaces.System; using JNPF.VisualDev.Entitys; using JNPF.WorkFlow.Entitys.Dto.FlowTemplate; using JNPF.WorkFlow.Entitys.Entity; using JNPF.WorkFlow.Entitys.Model; using JNPF.WorkFlow.Entitys.Model.Properties; using JNPF.WorkFlow.Interfaces.Repository; using JNPF.WorkFlow.Interfaces.Service; using Mapster; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using SqlSugar; namespace JNPF.WorkFlow.Service; /// /// 流程设计. /// [ApiDescriptionSettings(Tag = "WorkflowTemplate", Name = "FlowTemplate", Order = 301)] [Route("api/workflow/Engine/[controller]")] public class FlowTemplateService : IFlowTemplateService, IDynamicApiController, ITransient { private readonly ISqlSugarRepository _repository; private readonly IFlowTaskRepository _flowTaskRepository; private readonly IDictionaryDataService _dictionaryDataService; private readonly IUserManager _userManager; private readonly IFileManager _fileManager; private readonly ITenant _db; public FlowTemplateService( ISqlSugarRepository repository, IFlowTaskRepository flowTaskRepository, IDictionaryDataService dictionaryDataService, IUserManager userManager, IFileManager fileManager, ISqlSugarClient context) { _repository = repository; _flowTaskRepository = flowTaskRepository; _dictionaryDataService = dictionaryDataService; _userManager = userManager; _fileManager = fileManager; _db = context.AsTenant(); } #region GET /// /// 列表. /// /// 请求参数. /// [HttpGet("")] public async Task GetList([FromQuery] FlowTemplateListQuery input) { var objList = _flowTaskRepository.GetCurrentUserObjId(); var list = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.Id == b.FlowId)) .Where(a => a.DeleteMark == null) .WhereIF(_userManager.User.IsAdministrator == 0, (a, b) => a.CreatorUserId == _userManager.UserId || (objList.Contains(b.OperatorId) && b.Type == "2")) .WhereIF(input.category.IsNotEmptyOrNull(), a => a.Category == input.category) .WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword)) .Select(a => new FlowTemplateListOutput { category = SqlFunc.Subqueryable().Where(d => d.Id == a.Category).Select(d => d.FullName), id = a.Id, creatorTime = a.CreatorTime, creatorUser = SqlFunc.Subqueryable().Where(u => u.Id == a.CreatorUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)), enCode = a.EnCode, enabledMark = a.EnabledMark, fullName = a.FullName, icon = a.Icon, iconBackground = a.IconBackground, lastModifyTime = a.LastModifyTime, lastModifyUser = SqlFunc.Subqueryable().Where(u => u.Id == a.LastModifyUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)), sortCode = a.SortCode, type = a.Type, hasAssistBtn = SqlFunc.IIF((_userManager.UserId == a.CreatorUserId || _userManager.User.IsAdministrator == 1), 1, 0), }).Distinct().MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) .OrderByIF(!string.IsNullOrEmpty(input.keyword), t => t.lastModifyTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } /// /// 列表(树形). /// /// [HttpGet("ListAll")] public async Task GetListAll() { //var list1 = await GetFlowFormList(0); var list1 = await _repository.AsSugarClient().Queryable() .Where(a => a.DeleteMark == null && a.EnabledMark == 1) .Select(a => new FlowTemplateTreeOutput { id = a.Id, creatorTime = a.CreatorTime, enCode = a.EnCode, enabledMark = a.EnabledMark, fullName = a.FullName, icon = a.Icon, iconBackground = a.IconBackground, lastModifyTime = a.LastModifyTime, sortCode = a.SortCode, parentId = a.Category, category = a.Category, type = a.Type, }).Distinct().MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) .OrderBy(t => t.lastModifyTime, OrderByType.Desc).ToListAsync(); if (list1.Any()) { var dicDataInfo = await _dictionaryDataService.GetInfo(list1.FirstOrDefault().parentId); var dicDataList = await _dictionaryDataService.GetList(dicDataInfo.DictionaryTypeId); var list2 = new List(); foreach (var item in dicDataList) { list2.Add(new FlowTemplateTreeOutput() { fullName = item.FullName, parentId = "0", id = item.Id, num = list1.FindAll(x => x.category == item.EnCode).Count }); } var output = list1.Union(list2).ToList().ToTree(); return new { list = output }; } else { return new { list = new List() }; } } /// /// 列表(分页). /// /// 请求参数. /// [HttpGet("PageListAll")] public async Task GetListPageAll([FromQuery] FlowTemplateListQuery input) { //var data = await GetFlowFormList(input.flowType.ParseToInt()); //if (input.category.IsNotEmptyOrNull()) // data = data.FindAll(x => x.category == input.category); //if (input.keyword.IsNotEmptyOrNull()) // data = data.FindAll(o => o.fullName.Contains(input.keyword) || o.enCode.Contains(input.keyword)); //var pageList = new SqlSugarPagedList() //{ // list = data.Skip((input.currentPage - 1) * input.pageSize).Take(input.pageSize).ToList(), // pagination = new Pagination() // { // PageIndex = input.currentPage, // PageSize = input.pageSize, // Total = data.Count // } //}; //return PageResult.SqlSugarPageResult(pageList); var list = await _repository.AsSugarClient().Queryable() .Where(a => a.DeleteMark == null && a.Type == 0 && a.EnabledMark == 1) .WhereIF(input.category.IsNotEmptyOrNull(), a => a.Category == input.category) .WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword)) .Select(a => new FlowTemplateListOutput { id = a.Id, creatorTime = a.CreatorTime, enCode = a.EnCode, enabledMark = a.EnabledMark, fullName = a.FullName, icon = a.Icon, iconBackground = a.IconBackground, lastModifyTime = a.LastModifyTime, sortCode = a.SortCode, type = a.Type, }).Distinct().MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) .OrderByIF(!string.IsNullOrEmpty(input.keyword), t => t.lastModifyTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } /// /// 流程版本列表. /// /// 请求参数. /// [HttpGet("{id}/FlowJsonList")] public async Task GetFlowJsonList(string id, [FromQuery] FlowTemplateListQuery input) { var flowJosnEntity = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == input.flowId && x.DeleteMark == null); if (flowJosnEntity.IsNullOrEmpty()) { var pageList = new SqlSugarPagedList() { list = new List(), pagination = new Pagination() { CurrentPage = input.currentPage, PageSize = input.pageSize, Total = 0 } }; return PageResult.SqlSugarPageResult(pageList); } var whereLambda = LinqExpression.And(); whereLambda = whereLambda.And(x => x.DeleteMark == null && x.TemplateId == flowJosnEntity.TemplateId && x.FullName == flowJosnEntity.FullName); var start = new DateTime(); var end = new DateTime(); if (input.endTime != null && input.startTime != null) { start = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime())); end = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime())); whereLambda = whereLambda.And(x => SqlFunc.Between(x.CreatorTime, start, end)); } if (input.keyword.IsNotEmptyOrNull()) { whereLambda = whereLambda.And(x => x.Version.Contains(input.keyword)); } var list = await _repository.AsSugarClient().Queryable() .Where(whereLambda) .Select((a) => new FlowTemplateJsonInfoOutput { id = a.Id, fullName = a.FullName, version = a.Version, enabledMark = a.EnabledMark, creatorUser = SqlFunc.Subqueryable().Where(u => u.Id == a.CreatorUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)), creatorTime = a.CreatorTime, lastModifyTime = a.LastModifyTime, flowTemplateJson = a.FlowTemplateJson, }).MergeTable().OrderBy(a => a.enabledMark, OrderByType.Desc).OrderBy(a => a.creatorTime, OrderByType.Desc) .OrderByIF(!string.IsNullOrEmpty(input.keyword), t => t.lastModifyTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } /// /// 信息. /// /// 主键值. /// [HttpGet("{id}")] public async Task GetInfo(string id) { //var output = (await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null)).Adapt(); //output.onlineDev = _repository.AsSugarClient().Queryable().Any(x => x.Id == id && x.DeleteMark == null); //var flowJsonList = await _repository.AsSugarClient().Queryable().Where(x => x.TemplateId == id && x.EnabledMark == 1 && x.DeleteMark == null).Select(x => new { id = x.Id, flowId = x.Id, fullName = x.FullName, flowTemplateJson = x.FlowTemplateJson }).ToListAsync(); //output.flowTemplateJson = flowJsonList.ToJsonString(); //return output; var output = (await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null)).Adapt(); var flowFormEntity = _repository.AsSugarClient().Queryable().First(x => x.FlowId == id && x.FlowType == 1 && x.FormType == 2 && x.DeleteMark == null); if (flowFormEntity.IsNotEmptyOrNull()) { output.onlineDev = true; output.onlineFormId = flowFormEntity.Id; } var flowJsonList = new List(); var flowTemplateJsonEntityList = await _repository.AsSugarClient().Queryable().Where(x => x.TemplateId == id && x.EnabledMark == 1 && x.DeleteMark == null).OrderBy(x => x.SortCode).ToListAsync(); foreach (var item in flowTemplateJsonEntityList) { var flowJosn = new FlowJsonInfo(); flowJosn.id = item.Id; flowJosn.flowId = item.Id; flowJosn.fullName = item.FullName; var flowIds = _repository.AsSugarClient().Queryable().Where(x => x.GroupId == item.GroupId && x.DeleteMark == null).Select(x => x.Id).ToList(); flowJosn.isDelete = await _flowTaskRepository.AnyFlowTask(x => x.DeleteMark == null && flowIds.Contains(x.FlowId)); flowJosn.flowTemplateJson = item.FlowTemplateJson?.ToObject(); flowJsonList.Add(flowJosn); } output.flowTemplateJson = flowJsonList.ToJsonString(); return output; } /// /// 列表(子流程选择流程). /// /// (预留字段). /// [HttpGet("Selector")] public async Task ListSelect([FromQuery] int type) { var list1 = await GetOutList(0); if (type.IsEmpty()) list1 = list1.FindAll(x => x.formType == type); var dicDataInfo = await _dictionaryDataService.GetInfo(list1.First().parentId); var dicDataList = (await _dictionaryDataService.GetList(dicDataInfo.DictionaryTypeId)).FindAll(x => x.EnabledMark == 1); var list2 = new List(); foreach (var item in dicDataList) { var index = list1.FindAll(x => x.category == item.EnCode).Count; if (index > 0) { list2.Add(new FlowTemplateTreeOutput() { fullName = item.FullName, parentId = "0", id = item.Id, num = index }); } } var output = list1.Union(list2).ToList().ToTree(); return new { list = output }; } /// /// 列表(子流程选择流程). /// /// (预留字段). /// [HttpGet("PageChildListAll")] public async Task PageChildListAll([FromQuery] FlowTemplateListQuery input) { var list = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Right, a.Id == b.TemplateId)) .Where((a, b) => a.DeleteMark == null && a.EnabledMark == 1 && a.Type == input.flowType && b.DeleteMark == null && b.EnabledMark == 1) .WhereIF(input.keyword.IsNotEmptyOrNull(), (a, b) => b.FullName.Contains(input.keyword)) .Select((a, b) => new FlowTemplateTreeOutput { id = b.Id, fullName = b.FullName, creatorTime = a.CreatorTime, lastModifyTime = a.LastModifyTime, sortCode = a.SortCode, }).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) .OrderBy(a => a.lastModifyTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } /// /// 导出. /// /// /// [HttpGet("{id}/Actions/ExportData")] public async Task ActionsExport(string id) { var importModel = new FlowTemplateImportOutput(); importModel.flowTemplate = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null); importModel.flowTemplateJson = await _repository.AsSugarClient().Queryable().Where(x => x.TemplateId == id && x.EnabledMark == 1 && x.DeleteMark == null).ToListAsync(); var flowJsonIds = importModel.flowTemplateJson.Select(x => x.Id).ToList(); importModel.visibleList = await _repository.AsSugarClient().Queryable().Where(x => flowJsonIds.Contains(x.FlowId)).ToListAsync(); var jsonStr = importModel.ToJsonString(); return await _fileManager.Export(jsonStr, importModel.flowTemplate.FullName, ExportFileType.ffe); } /// /// 表单主表属性. /// /// 主键. /// [HttpGet("{id}/FormInfo")] public async Task GetFormInfo(string id) { var flowJson = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == id && x.DeleteMark == null); if (flowJson.IsNullOrEmpty()) return null; var formId = flowJson.FlowTemplateJson.ToObject().properties.ToObject().formId; var formEntity = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == formId && x.DeleteMark == null); return formEntity.Adapt(); } /// /// 流程协管列表. /// /// 主键. /// [HttpGet("{id}/assistList")] public async Task GetAssistList(string id) { var output = await _repository.AsSugarClient().Queryable().Where(a => a.FlowId == id && a.Type == "2").Select(a => a.OperatorId).ToListAsync(); return new { list = output }; } /// /// 委托流程列表(所有流程). /// /// [HttpGet("getflowAll")] public async Task GetFlowAll([FromQuery] FlowTemplateListQuery input) { var list = await _repository.AsSugarClient().Queryable() .Where(a => a.DeleteMark == null && a.EnabledMark == 1) .WhereIF(input.category.IsNotEmptyOrNull(), a => a.Category == input.category) .WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword)) .Select(a => new FlowTemplateTreeOutput { id = a.Id, category = a.Category, enCode = a.EnCode, fullName = a.FullName, sortCode = a.SortCode, creatorTime = a.CreatorTime, lastModifyTime = a.LastModifyTime, type = a.Type, }).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) .OrderBy(a => a.lastModifyTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } /// /// 委托流程列表(所有流程). /// /// [HttpPost("getflowList")] public async Task GetflowList([FromBody] List input) { return (await _repository.GetListAsync(x => input.Contains(x.Id))).Adapt>(); } /// /// 通过编码获取流程id. /// /// [HttpGet("getFlowIdByCode/{code}")] public async Task GetflowCode(string code) { var entity = await _repository.GetFirstAsync(x => x.EnCode == code && x.DeleteMark == null); if (entity == null) Oops.Oh(ErrorCode.COM1005); return entity.Id; } /// /// 发起流程列表(下拉). /// /// [HttpGet("FlowJsonList/{teplateId}")] public async Task GetFlowJsonList(string teplateId, string type) { var flowJsonList = (await _repository.AsSugarClient().Queryable().Where(x => x.TemplateId == teplateId && x.EnabledMark == 1 && x.DeleteMark == null).OrderBy(x => x.SortCode).ToListAsync()).Adapt>(); if (!flowJsonList.Any()) throw Oops.Oh(ErrorCode.COM1016); if (!_userManager.IsAdministrator && type == "1") { // 判断当前用户是否有发起权限 foreach (var item in flowJsonList.FindAll(x => x.visibleType == 1)) { // 指定发起人. var visibleUserList = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.OperatorId == b.ObjectId || a.OperatorId == b.UserId)) .Where((a, b) => a.FlowId == item.id && a.Type == "1").Select((a, b) => b.UserId).Distinct().ToListAsync(); if (!visibleUserList.Contains(_userManager.UserId)) { flowJsonList.Remove(item); } } } if (!flowJsonList.Any()) throw Oops.Oh(ErrorCode.WF0049); return flowJsonList; } #endregion #region POST /// /// 删除. /// /// 主键值. /// [HttpDelete("{id}")] public async Task Delete(string id) { var flowTemplateEntity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null); if (flowTemplateEntity == null) throw Oops.Oh(ErrorCode.COM1005); var flowTemplateJsonIdList = await _repository.AsSugarClient().Queryable().Where(x => x.TemplateId == id).Select(x => x.Id).ToListAsync(); if (await _flowTaskRepository.AnyFlowTask(x => x.DeleteMark == null && flowTemplateJsonIdList.Contains(x.FlowId))) throw Oops.Oh(ErrorCode.WF0037); if (await _repository.AsSugarClient().Queryable().AnyAsync(x => x.FlowId == id)) throw Oops.Oh(ErrorCode.WF0052); _db.BeginTran(); await _repository.AsSugarClient().Deleteable(a => flowTemplateJsonIdList.Contains(a.FlowId)).ExecuteCommandHasChangeAsync(); await _repository.AsSugarClient().Deleteable(a => flowTemplateJsonIdList.Contains(a.Id)).ExecuteCommandHasChangeAsync(); await _repository.AsSugarClient().Deleteable(a => a.FlowId == id).ExecuteCommandHasChangeAsync(); await _repository.AsSugarClient().Updateable().SetColumns(x => x.FlowId == null).Where(x => x.FlowId == id).ExecuteCommandAsync(); var isOk = await _repository.AsUpdateable(flowTemplateEntity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync(); _db.CommitTran(); if (!isOk) throw Oops.Oh(ErrorCode.COM1002); } /// /// 新建. /// /// 请求参数. /// [HttpPost("")] public async Task Create([FromBody] FlowTemplateInfoOutput input) { if (await _repository.IsAnyAsync(x => (x.EnCode == input.enCode || x.FullName == input.fullName) && x.DeleteMark == null)) throw Oops.Oh(ErrorCode.COM1004); var flowTemplateEntity = input.Adapt(); var result = await Create(flowTemplateEntity, input.flowTemplateJson); _ = result ?? throw Oops.Oh(ErrorCode.COM1000); } /// /// 更新. /// /// 主键值. /// 请求参数. /// [HttpPut("{id}")] public async Task Update(string id, [FromBody] FlowTemplateInfoOutput input) { if (await _repository.IsAnyAsync(x => x.Id != id && (x.EnCode == input.enCode || x.FullName == input.fullName) && x.DeleteMark == null)) throw Oops.Oh(ErrorCode.COM1004); var flowTemplateEntity = input.Adapt(); var result = await Update(flowTemplateEntity, input.flowTemplateJson, input.onlineFormId); if (result.IsNullOrEmpty()) throw Oops.Oh(ErrorCode.COM1001); return result; } /// /// 复制. /// /// 主键值. /// [HttpPost("{id}/Actions/Copy")] public async Task ActionsCopy(string id) { var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null); if (entity == null) throw Oops.Oh(ErrorCode.COM1005); var random = RandomExtensions.NextLetterAndNumberString(new Random(), 5).ToLower(); entity.FullName = string.Format("{0}副本{1}", entity.FullName, random); entity.EnCode = string.Format("{0}{1}", entity.EnCode, random); if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50) throw Oops.Oh(ErrorCode.COM1009); var flowJsonList = new List(); var flowTemplateJsonEntityList = await _repository.AsSugarClient().Queryable().Where(x => x.TemplateId == id && x.EnabledMark == 1 && x.DeleteMark == null).ToListAsync(); foreach (var item in flowTemplateJsonEntityList) { var flowJosn = new FlowJsonInfo(); flowJosn.id = item.Id; flowJosn.flowId = item.Id; flowJosn.fullName = item.FullName; flowJosn.isDelete = await _flowTaskRepository.AnyFlowTask(x => x.DeleteMark == null && x.FlowId == item.Id); flowJosn.flowTemplateJson = item.FlowTemplateJson?.ToObject(); flowJsonList.Add(flowJosn); } var result = await Create(entity, flowJsonList.ToJsonString()); _ = result ?? throw Oops.Oh(ErrorCode.WF0002); } /// /// 导入. /// /// /// [HttpPost("Actions/ImportData")] public async Task ActionsImport(IFormFile file) { var fileType = Path.GetExtension(file.FileName).Replace(".", string.Empty); if (!fileType.ToLower().Equals(ExportFileType.ffe.ToString())) throw Oops.Oh(ErrorCode.D3006); var josn = _fileManager.Import(file); FlowTemplateImportOutput model; try { model = josn.ToObject(); } catch { throw Oops.Oh(ErrorCode.D3006); } if (model == null) throw Oops.Oh(ErrorCode.D3006); await ImportData(model); } /// /// 发布. /// /// 主键值. /// [HttpPost("Release/{id}")] public async Task Release(string id) { var entity = await GetInfo(id); if (entity == null) throw Oops.Oh(ErrorCode.COM1005); var flowJson = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.TemplateId == id && x.EnabledMark == 1 && x.DeleteMark == null); if (flowJson.IsNotEmptyOrNull() && flowJson.FlowTemplateJson.IsNotEmptyOrNull()) { var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => it.EnabledMark == 1).Where(it => it.Id == id).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1003); } else { throw Oops.Oh(ErrorCode.WF0038); } } /// /// 停止. /// /// 主键值. /// [HttpPost("Stop/{id}")] public async Task Stop(string id) { var entity = await GetInfo(id); if (entity == null) throw Oops.Oh(ErrorCode.COM1005); var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => it.EnabledMark == 0).Where(it => it.Id == id).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1003); } /// /// 设置主版本. /// /// 主键值. /// [HttpPost("{id}/MainVersion")] public async Task MainVersion(string id) { foreach (var item in id.Split(",")) { var jsonInfo = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == item && x.DeleteMark == null); await _repository.AsSugarClient().Updateable().SetColumns(it => new FlowTemplateJsonEntity() { EnabledMark = 0, LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.EnabledMark == 1 && it.TemplateId == jsonInfo.TemplateId && it.FullName == jsonInfo.FullName).ExecuteCommandHasChangeAsync(); var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => new FlowTemplateJsonEntity() { EnabledMark = 1, LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id == item && it.TemplateId == jsonInfo.TemplateId && it.FullName == jsonInfo.FullName).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1003); } } /// /// 删除版本. /// /// 主键值. /// [HttpDelete("{id}/FlowJson")] public async Task DeleteFlowJson(string id) { if (await _flowTaskRepository.AnyFlowTask(x => x.DeleteMark == null && x.FlowId == id)) throw Oops.Oh(ErrorCode.WF0037); var jsonInfo = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == id && x.DeleteMark == null); var launchFormIdList = new List(); GetFormIdList(jsonInfo.FlowTemplateJson.ToObject(), launchFormIdList); await _repository.AsSugarClient().Deleteable(a => a.FlowId == id && launchFormIdList.Contains(a.FormId)).ExecuteCommandHasChangeAsync(); var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => new FlowTemplateJsonEntity() { DeleteMark = 1, DeleteTime = SqlFunc.GetDate(), DeleteUserId = _userManager.UserId }).Where(it => it.Id == id).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1003); } /// /// 流程协管. /// /// 主键值. /// [HttpPost("assist")] public async Task SaveAssist([FromBody] FlowTemplateAssistQuery input) { var visibleList = new List(); var flowTemplateEntity = await _repository.GetFirstAsync(x => x.Id == input.templateId && x.DeleteMark == null); foreach (var item in input.list) { var visibleEntity = new FlowEngineVisibleEntity() { OperatorId = item, FlowId = input.templateId, Type = "2" }; visibleList.Add(visibleEntity); } await _repository.AsSugarClient().Deleteable(a => a.FlowId == input.templateId && a.Type == "2").ExecuteCommandHasChangeAsync(); if (visibleList.Any()) { await _repository.AsSugarClient().Insertable(visibleList).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); } } #endregion #region PublicMethod /// /// 发起列表. /// /// [NonAction] public async Task> GetFlowFormList(int flowType, string userId = null) { var list = await GetOutList(flowType); var IsAdministrator = false; if (userId.IsNullOrEmpty()) { userId = _userManager.UserId; IsAdministrator = _userManager.User.IsAdministrator == 0; } else { IsAdministrator = _repository.AsSugarClient().Queryable().Any(x => x.Id == userId && x.IsAdministrator == 0); } if (IsAdministrator) { var data = await GetVisibleFlowList(userId, flowType); data = data.Union(list.FindAll(x => x.visibleType == 0)).ToList(); return data; } else { return list; } } #endregion #region PrivateMethod /// /// 新增流程. /// /// 流程实例. /// 可见范围. /// [NonAction] private async Task Create(FlowTemplateEntity entity, string flowTemplateJson) { try { _db.BeginTran(); var formIdList = new List(); entity.Id = SnowflakeIdHelper.NextId(); entity.EnabledMark = 0; if (flowTemplateJson.IsNotEmptyOrNull()) { var index = 0; foreach (var item in flowTemplateJson.ToObject>()) { var flowTemplateJsonEntity = new FlowTemplateJsonEntity(); flowTemplateJsonEntity.Id = SnowflakeIdHelper.NextId(); flowTemplateJsonEntity.TemplateId = entity.Id; flowTemplateJsonEntity.Version = "1"; flowTemplateJsonEntity.FlowTemplateJson = item.flowTemplateJson.ToJsonString(); flowTemplateJsonEntity.FullName = item.fullName; flowTemplateJsonEntity.SortCode = index++; flowTemplateJsonEntity.GroupId = SnowflakeIdHelper.NextId(); var visibleList = GetFlowEngineVisibleList(item.flowTemplateJson.ToJsonString()); flowTemplateJsonEntity.VisibleType = visibleList.Count == 0 ? 0 : 1; foreach (var visible in visibleList) { visible.FlowId = flowTemplateJsonEntity.Id; visible.SortCode = visibleList.IndexOf(visible); visible.Type = "1"; } if (visibleList.Count > 0) await _repository.AsSugarClient().Insertable(visibleList).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); await _repository.AsSugarClient().Insertable(flowTemplateJsonEntity).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync(); #region 功能流程则要回写到对应的表单表中 if (entity.Type == 1) { var formId = item.flowTemplateJson.properties.ToObject()?.formId; if (formIdList.Any() && !formIdList.Contains(formId)) { throw Oops.Oh(ErrorCode.WF0043); } else { formIdList.Add(formId); } if (await _repository.AsSugarClient().Queryable().AnyAsync(x => x.Id == formId && x.FlowId != entity.Id && !SqlFunc.IsNullOrEmpty(x.FlowId))) throw Oops.Oh(ErrorCode.WF0043); await _repository.AsSugarClient().Updateable().SetColumns(x => x.FlowId == entity.Id).Where(x => x.Id == formId).ExecuteCommandAsync(); } else { var launchFormIdList = new List(); GetFormIdList(item.flowTemplateJson, launchFormIdList); foreach (var launchFormId in launchFormIdList) { var formRelationEntity = new FlowFormRelationEntity { Id = SnowflakeIdHelper.NextId(), FlowId = entity.Id, FormId = launchFormId }; await _repository.AsSugarClient().Insertable(formRelationEntity).ExecuteReturnEntityAsync(); } } #endregion } } var result = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync(); if (result == null) throw Oops.Oh(ErrorCode.COM1005); _db.CommitTran(); return result; } catch (AppFriendlyException ex) { _db.RollbackTran(); throw Oops.Oh(ex.ErrorCode); } } /// /// 修改流程. /// /// 流程实体. /// 可见范围. /// [NonAction] private async Task Update(FlowTemplateEntity entity, string flowTemplateJson, string onlineFormId) { try { _db.BeginTran(); var flag = false; var isMainVersionId = new List(); var formIdList = new List(); var groupIdList = new List(); // 未删除的分组id. if (flowTemplateJson.IsNotEmptyOrNull()) { var index = 0; foreach (var item in flowTemplateJson.ToObject>()) { var flowTemplateJsonEntity = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == item.id && x.DeleteMark == null); var visibleList = GetFlowEngineVisibleList(item.flowTemplateJson.ToJsonString()); if (flowTemplateJsonEntity.IsNullOrEmpty()) { flowTemplateJsonEntity = new FlowTemplateJsonEntity(); flowTemplateJsonEntity.Id = SnowflakeIdHelper.NextId(); flowTemplateJsonEntity.TemplateId = entity.Id; flowTemplateJsonEntity.Version = "1"; flowTemplateJsonEntity.FlowTemplateJson = item.flowTemplateJson.ToJsonString(); flowTemplateJsonEntity.FullName = item.fullName; flowTemplateJsonEntity.SortCode = index++; flowTemplateJsonEntity.VisibleType = visibleList.Count == 0 ? 0 : 1; flowTemplateJsonEntity.GroupId = SnowflakeIdHelper.NextId(); foreach (var visible in visibleList) { visible.FlowId = flowTemplateJsonEntity.Id; visible.SortCode = visibleList.IndexOf(visible); visible.Type = "1"; } if (visibleList.Count > 0) await _repository.AsSugarClient().Insertable(visibleList).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); await _repository.AsSugarClient().Insertable(flowTemplateJsonEntity).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync(); groupIdList.Add(flowTemplateJsonEntity.GroupId); } else { // 清空就模板关联表单数据 if (entity.Type == 1) { string oldFormId = flowTemplateJsonEntity.FlowTemplateJson.ToObject().properties.ToObject().formId; await _repository.AsSugarClient().Updateable().SetColumns(x => x.FlowId == null).Where(x => x.Id == oldFormId).ExecuteCommandAsync(); } else { await _repository.AsSugarClient().Deleteable().Where(x => x.FlowId == entity.Id).ExecuteCommandAsync(); } if (!groupIdList.Contains(flowTemplateJsonEntity.GroupId)) { groupIdList.Add(flowTemplateJsonEntity.GroupId); } var isCreate = flowTemplateJsonEntity.FlowTemplateJson.Equals(item.flowTemplateJson.ToJsonString());//流程json是否变更 flowTemplateJsonEntity.FlowTemplateJson = item.flowTemplateJson.ToJsonString(); flowTemplateJsonEntity.SortCode = index++; flowTemplateJsonEntity.FullName = item.fullName; flowTemplateJsonEntity.VisibleType = visibleList.Count == 0 ? 0 : 1; if ((await _flowTaskRepository.AnyFlowTask(x => x.DeleteMark == null && x.FlowId == flowTemplateJsonEntity.Id)) && !isCreate) { flag = true; await _repository.AsSugarClient().Updateable(flowTemplateJsonEntity).UpdateColumns(it => new { it.FullName, it.SortCode }).ExecuteCommandHasChangeAsync(); flowTemplateJsonEntity.Version = ((await _repository.AsSugarClient().Queryable().Where(x => x.TemplateId == entity.Id && x.FullName == item.fullName).Select(x => SqlFunc.AggregateMax(SqlFunc.ToInt64(x.Version))).FirstAsync()).ParseToInt() + 1).ToString(); flowTemplateJsonEntity.Id = SnowflakeIdHelper.NextId(); flowTemplateJsonEntity.EnabledMark = 0; flowTemplateJsonEntity.LastModifyTime = null; flowTemplateJsonEntity.LastModifyUserId = null; await _repository.AsSugarClient().Insertable(flowTemplateJsonEntity).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync(); isMainVersionId.Add(flowTemplateJsonEntity.Id); } else { await _repository.AsSugarClient().Updateable(flowTemplateJsonEntity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync(); await _repository.AsSugarClient().Deleteable(a => a.FlowId == flowTemplateJsonEntity.Id).ExecuteCommandHasChangeAsync(); } } foreach (var visible in visibleList) { visible.FlowId = flowTemplateJsonEntity.Id; visible.SortCode = visibleList.IndexOf(visible); visible.Type = "1"; } if (visibleList.Count > 0) await _repository.AsSugarClient().Insertable(visibleList).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); if (entity.Type == 1) { var formId = item.flowTemplateJson.properties.ToObject()?.formId; if (formIdList.Any() && !formIdList.Contains(formId)) { throw Oops.Oh(ErrorCode.WF0043); } else { formIdList.Add(formId); } if ((await _repository.AsSugarClient().Queryable().AnyAsync(x => x.Id == formId && x.FlowId != entity.Id && !SqlFunc.IsNullOrEmpty(x.FlowId))) && formId != onlineFormId) throw Oops.Oh(ErrorCode.WF0043); await _repository.AsSugarClient().Updateable().SetColumns(x => x.FlowId == entity.Id).Where(x => x.Id == formId).ExecuteCommandAsync(); } else { // 发起流程表单id var launchFormIdList = new List(); GetFormIdList(item.flowTemplateJson, launchFormIdList); foreach (var launchFormId in launchFormIdList) { var formRelationEntity = new FlowFormRelationEntity { Id = SnowflakeIdHelper.NextId(), FlowId = entity.Id, FormId = launchFormId }; await _repository.AsSugarClient().Insertable(formRelationEntity).ExecuteReturnEntityAsync(); } } } // 删除未使用的流程 await _repository.AsSugarClient().Deleteable().Where(x => x.TemplateId == entity.Id && !groupIdList.Contains(x.GroupId)).ExecuteCommandAsync(); } var isOk = await _repository.AsSugarClient().Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync(); _db.CommitTran(); return new { isMainVersion = flag, id = string.Join(",", isMainVersionId) }; } catch (Exception ex) { _db.RollbackTran(); return null; } } /// /// 解析流程可见参数. /// /// /// private List GetFlowEngineVisibleList(string josnStr) { var output = new List(); if (josnStr.IsNotEmptyOrNull()) { // 发起节点属性. var pro = josnStr.ToObject().properties.ToObject(); if (pro.initiator.Any()) { var list = pro.initiator.Select(x => new FlowEngineVisibleEntity() { OperatorId = x, OperatorType = "user" }).ToList(); output.AddRange(list); } if (pro.initiatePos.Any()) { var list = pro.initiatePos.Select(x => new FlowEngineVisibleEntity() { OperatorId = x, OperatorType = "Position" }).ToList(); output.AddRange(list); } if (pro.initiateRole.Any()) { var list = pro.initiateRole.Select(x => new FlowEngineVisibleEntity() { OperatorId = x, OperatorType = "Role" }).ToList(); output.AddRange(list); } if (pro.initiateGroup.Any()) { var list = pro.initiateGroup.Select(x => new FlowEngineVisibleEntity() { OperatorId = x, OperatorType = "Group" }).ToList(); output.AddRange(list); } if (pro.initiateOrg.Any()) { var list = pro.initiateOrg.Select(x => new FlowEngineVisibleEntity() { OperatorId = x, OperatorType = "Organize" }).ToList(); output.AddRange(list); } } return output; } /// /// 获取当前用户可见流程. /// /// [NonAction] private async Task> GetVisibleFlowList(string userId, int flowType) { return await _repository.AsSugarClient().Queryable((a, b, c, d) => new JoinQueryInfos(JoinType.Left, a.OperatorId == b.ObjectId, JoinType.Left, a.FlowId == c.Id, JoinType.Left, c.TemplateId == d.Id)) .Where((a, b, c, d) => (a.OperatorId == userId || b.UserId == userId) && c.DeleteMark == null && c.EnabledMark == 1 && d.Type == flowType) .Select((a, b, c, d) => new FlowTemplateTreeOutput { category = d.Category, id = c.Id, description = d.Description, creatorTime = d.CreatorTime, creatorUser = SqlFunc.Subqueryable().Where(u => u.Id == d.CreatorUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)), enCode = d.EnCode, enabledMark = d.EnabledMark, fullName = d.FullName, icon = d.Icon, iconBackground = d.IconBackground, lastModifyTime = d.LastModifyTime, lastModifyUser = SqlFunc.Subqueryable().Where(u => u.Id == c.LastModifyUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)), sortCode = a.SortCode, type = d.Type, visibleType = c.VisibleType, parentId = d.Category, templateId = a.Id }).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) .OrderBy(a => a.lastModifyTime, OrderByType.Desc).ToListAsync(); } /// /// 流程列表. /// /// private async Task> GetOutList(int flowType) { return await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.Id == b.TemplateId)) .Where((a, b) => a.DeleteMark == null && a.EnabledMark == 1 && a.Type == flowType && b.DeleteMark == null && b.EnabledMark == 1) .Select((a, b) => new FlowTemplateTreeOutput { category = a.Category, id = a.Id, description = a.Description, creatorTime = a.CreatorTime, creatorUser = SqlFunc.Subqueryable().Where(u => u.Id == a.CreatorUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)), enCode = a.EnCode, enabledMark = a.EnabledMark, fullName = a.FullName, icon = a.Icon, iconBackground = a.IconBackground, lastModifyTime = a.LastModifyTime, lastModifyUser = SqlFunc.Subqueryable().Where(u => u.Id == a.LastModifyUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)), sortCode = a.SortCode, type = a.Type, visibleType = b.VisibleType, parentId = a.Category, templateId = a.Id }).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) .OrderBy(a => a.lastModifyTime, OrderByType.Desc).ToListAsync(); } /// /// 导入数据. /// /// 导入实例. /// private async Task ImportData(FlowTemplateImportOutput model) { try { _db.BeginTran(); await _repository.AsSugarClient().Storageable(model.flowTemplate).ExecuteCommandAsync(); await _repository.AsSugarClient().Storageable(model.flowTemplateJson).ExecuteCommandAsync(); await _repository.AsSugarClient().Storageable(model.visibleList).ExecuteCommandAsync(); _db.CommitTran(); } catch (Exception ex) { _db.RollbackTran(); throw Oops.Oh(ErrorCode.D3006); } } /// /// 递归模板获取formid. /// /// /// private void GetFormIdList(FlowTemplateJsonModel template, List formIdList) { if (template.IsNotEmptyOrNull() && !template.type.Equals("subFlow") && !template.type.Equals("timer")) { if (template.properties["formId"].ToString().IsNotEmptyOrNull()) { formIdList.Add(template.properties["formId"].ToString()); } if (template.childNode.IsNotEmptyOrNull()) { GetFormIdList(template.childNode, formIdList); } } } #endregion }