//-------------------------------------------------------------------- // 此代码由liquid模板自动生成 byzhouhang 20240909 // 生成时间 2025-03-27 06:13:33Z // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 //-------------------------------------------------------------------- using IRaCIS.Core.Domain.Models; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Infrastructure.Extention; using System.Threading.Tasks; using IRaCIS.Core.Infra.EFCore; using AutoMapper.Execution; using System.Linq; using IRaCIS.Core.Infrastructure; using DocumentFormat.OpenXml.Office2010.Excel; using MassTransit; using NPOI.POIFS.Properties; using Org.BouncyCastle.Crypto; using Microsoft.AspNetCore.Http; using IRaCIS.Core.Application.Contracts; using Microsoft.EntityFrameworkCore; using static Microsoft.Extensions.Logging.EventSource.LoggingEventSource; using NPOI.SS.Formula.Functions; using EFCore.BulkExtensions; namespace IRaCIS.Core.Application.Service; /// /// 稽查文档 /// /// [ApiExplorerSettings(GroupName = "FileRecord")] public class AuditDocumentService(IRepository _auditDocumentRepository, IRepository _auditRecordRepository, IRepository _auditRecordPermissionRepository, IRepository _auditRecordIdentityUserRepository, IRepository _auditDocumentClosureRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService { #region 稽查新增需求 /// /// 查看授权时间内的稽查 (admin qa 看所有 EA只看到自己参与的) /// /// /// [HttpPost] public async Task> GetAuditRecordSelectList(AuditRecordQuery inQuery) { var dateTimeNow = DateTime.Now; var isAdminOrQA = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.Admin || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.QA; var auditRecordQueryable = _auditRecordRepository.Where(t => t.BeginTime < dateTimeNow && t.EndTime > dateTimeNow && t.AuditState == AuditState.Ongoing) //过滤查看用户 .WhereIf(isAdminOrQA == false, t => t.AuditRecordIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId)) .WhereIf(inQuery.BeginAuditTime != null, t => t.AuditTime >= inQuery.BeginAuditTime) .WhereIf(inQuery.EndAuditTime != null, t => t.AuditTime <= inQuery.EndAuditTime) .WhereIf(inQuery.AuditState != null, t => t.AuditState == inQuery.AuditState) .WhereIf(inQuery.AuditType != null, t => t.AuditType == inQuery.AuditType) .WhereIf(inQuery.BeginTime != null, t => t.BeginTime >= inQuery.BeginTime) .WhereIf(inQuery.EndTime != null, t => t.EndTime <= inQuery.EndTime) .WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime) .WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime) .WhereIf(inQuery.IdentityUserName.IsNotNullOrEmpty(), t => t.AuditRecordIdentityUserList.Any(c => c.IdentityUser.UserName.Contains(inQuery.IdentityUserName) || c.IdentityUser.FullName.Contains(inQuery.IdentityUserName))) .WhereIf(inQuery.CompanyName.IsNotNullOrEmpty(), t => t.CompanyName.Contains(inQuery.CompanyName)) .WhereIf(inQuery.AuditContent.IsNotNullOrEmpty(), t => t.AuditContent.Contains(inQuery.AuditContent)) .ProjectTo(_mapper.ConfigurationProvider); var list = await auditRecordQueryable.OrderBy(t => t.AuditTime).ToListAsync(); return list; } /// /// 稽查记录 列表 /// /// /// [HttpPost] public async Task> GetAuditRecordList(AuditRecordQuery inQuery) { var auditRecordQueryable = _auditRecordRepository .WhereIf(inQuery.BeginAuditTime != null, t => t.AuditTime >= inQuery.BeginAuditTime) .WhereIf(inQuery.EndAuditTime != null, t => t.AuditTime <= inQuery.EndAuditTime) .WhereIf(inQuery.AuditState != null, t => t.AuditState == inQuery.AuditState) .WhereIf(inQuery.AuditType != null, t => t.AuditType == inQuery.AuditType) .WhereIf(inQuery.BeginTime != null, t => t.BeginTime >= inQuery.BeginTime) .WhereIf(inQuery.EndTime != null, t => t.EndTime <= inQuery.EndTime) .WhereIf(inQuery.BeginCreateTime != null, t => t.CreateTime >= inQuery.BeginCreateTime) .WhereIf(inQuery.EndCreateTime != null, t => t.CreateTime <= inQuery.EndCreateTime) .WhereIf(inQuery.IdentityUserName.IsNotNullOrEmpty(), t => t.AuditRecordIdentityUserList.Any(c => c.IdentityUser.UserName.Contains(inQuery.IdentityUserName) || c.IdentityUser.FullName.Contains(inQuery.IdentityUserName))) .WhereIf(inQuery.CompanyName.IsNotNullOrEmpty(), t => t.CompanyName.Contains(inQuery.CompanyName)) .WhereIf(inQuery.AuditContent.IsNotNullOrEmpty(), t => t.AuditContent.Contains(inQuery.AuditContent)) .ProjectTo(_mapper.ConfigurationProvider); var pageList = await auditRecordQueryable.ToPagedListAsync(inQuery); return pageList; } [HttpPost] public async Task AddOrUpdateAuditRecord(AuditRecordAddOrEdit addOrEditAuditRecord) { if (addOrEditAuditRecord.Id == null) { var entity = _mapper.Map(addOrEditAuditRecord); if (await _auditRecordRepository.AnyAsync(t => t.CompanyName == addOrEditAuditRecord.CompanyName && t.AuditContent == addOrEditAuditRecord.AuditContent && t.AuditTime == addOrEditAuditRecord.AuditTime, true)) { //---重复的稽查记录。 return ResponseOutput.NotOk(_localizer["AuditDocument_RepeatAuditRecord"]); } await _auditRecordRepository.AddAsync(entity, true); return ResponseOutput.Ok(entity.Id.ToString()); } else { if (await _auditRecordRepository.AnyAsync(t => t.CompanyName == addOrEditAuditRecord.CompanyName && t.AuditContent == addOrEditAuditRecord.AuditContent && t.AuditTime == addOrEditAuditRecord.AuditTime && t.Id != addOrEditAuditRecord.Id, true)) { //---重复的稽查记录。 return ResponseOutput.NotOk(_localizer["AuditDocument_RepeatAuditRecord"]); } var find = _auditRecordRepository.Where(t => t.Id == addOrEditAuditRecord.Id, true).Include(t => t.AuditRecordIdentityUserList).FirstOrDefault(); _mapper.Map(addOrEditAuditRecord, find); find.UpdateTime = DateTime.Now; var success = await _auditRecordRepository.SaveChangesAsync(); return ResponseOutput.Ok(find.Id.ToString()); } } [HttpPut] public async Task AddOrDeleteAuditRecordUser(AddOrDeleteAuditUserCommand inCommand) { if (inCommand.IsAdd) { foreach (var identityUserId in inCommand.IdentityUserIdList) { await _auditRecordIdentityUserRepository.AddAsync(new AuditRecordIdentityUser() { AuditRecordId = inCommand.AuditRecordId, IdentityUserId = identityUserId }); } } else { await _auditRecordIdentityUserRepository.BatchDeleteNoTrackingAsync(t => t.AuditRecordId == inCommand.AuditRecordId && inCommand.IdentityUserIdList.Contains(t.IdentityUserId)); } await _auditRecordIdentityUserRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } /// /// 删除稽查记录 /// /// /// [HttpDelete("{auditRecordId:guid}")] public async Task DeleteAuditRecord(Guid auditRecordId) { if (await _auditRecordRepository.Where(t => t.Id == auditRecordId).AnyAsync(u => u.AuditState != AuditState.NotStart)) { //未开始的才允许删除 return ResponseOutput.NotOk(_localizer["AuditDocument_CannotDeleteStartRecod"]); } var success = await _auditRecordRepository.DeleteFromQueryAsync(t => t.Id == auditRecordId, true); return ResponseOutput.Ok(); } /// /// 设置稽查记录某个文件 或者某个文件夹授权 /// /// /// public async Task SetAuditRecordPermission(SetAuditRecordPermissionCommand inCommand) { var list = await _auditDocumentRepository.Where(t => inCommand.AuditDocumentIdList.Contains(t.Id)).ToListAsync(); foreach (var item in list) { //闭包表中找到 设置Id为祖先的所有 后代 包括自己 var matchIdList = await _auditDocumentClosureRepository.Where(t => item.Id == t.AncestorId).Select(t => t.DescendantId).ToListAsync(); if (inCommand.IsAuthorization) { foreach (var matchItem in matchIdList) { await _auditRecordPermissionRepository.AddAsync(new AuditRecordPermission() { AuditRecordId = inCommand.AuditRecordId, AuditDocumentId = matchItem }); } } else { await _auditRecordPermissionRepository.BatchDeleteNoTrackingAsync(t => t.AuditRecordId == inCommand.AuditRecordId && matchIdList.Contains(t.AuditDocumentId)); } } await _auditRecordPermissionRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } #endregion #region 闭包修改 /// /// GPT 移动子树代码--适合一次提交事务 /// /// /// /// private async Task MoveSubtreeAsync(Guid subtreeRootId, Guid? newParentId) { // 1. 子树所有闭包关系(后代包含自身) var subtreeClosures = await _auditDocumentClosureRepository .Where(c => c.AncestorId == subtreeRootId) .ToListAsync(); var descendantIdsQuery = _auditDocumentClosureRepository .Where(c => c.AncestorId == subtreeRootId).Select(c => c.DescendantId); // 2. 删除原有祖先关系,保留自反关系和子树内部关系 await _auditDocumentClosureRepository.BatchDeleteNoTrackingAsync(c => descendantIdsQuery.Contains(c.DescendantId) && c.AncestorId != c.DescendantId && // 保留自反关系 !descendantIdsQuery.Contains(c.AncestorId) // 保留子树内部关系 ); // 3. 查新父节点祖先 var newParentClosures = newParentId.HasValue ? await _auditDocumentClosureRepository .Where(c => c.DescendantId == newParentId.Value) .ToListAsync() : new List(); // 4. 生成新关系 var newClosures = new List(); foreach (var pc in newParentClosures) { foreach (var sc in subtreeClosures) { newClosures.Add(new AuditDocumentClosure { AncestorId = pc.AncestorId, DescendantId = sc.DescendantId, Depth = pc.Depth + sc.Depth + 1 //深度公式:新深度 = 父祖先深度 + 子树原深度 + 1 }); } } // 5. 插入新关系 await _auditDocumentClosureRepository.AddRangeAsync(newClosures); await _auditDocumentClosureRepository.SaveChangesAsync(); } /// /// 插入闭包表关系 /// private async Task AddClosureRelationsAsync(Guid nodeId, Guid? parentId) { var closures = new List(); // 自身关系 closures.Add(new AuditDocumentClosure { AncestorId = nodeId, DescendantId = nodeId, Depth = 0 }); if (parentId.HasValue) { // 查出所有父级的祖先 var parentClosures = await _auditDocumentClosureRepository .Where(c => c.DescendantId == parentId.Value).Select(t => new { t.AncestorId, t.Depth }) .ToListAsync(); // 生成父级的所有祖先到新节点的关系 foreach (var pc in parentClosures) { closures.Add(new AuditDocumentClosure { AncestorId = pc.AncestorId, DescendantId = nodeId, Depth = pc.Depth + 1 }); } } await _auditDocumentClosureRepository.AddRangeAsync(closures); await _auditDocumentClosureRepository.SaveChangesAsync(); } /// /// 获取文件树形结构 (传Id 根节点就是自己) /// /// /// [HttpPost] public async Task> GetAuditDocumentData(GetAuditDocumentDataInDto inDto) { var defalutSortArray = new string[] { nameof(AuditDocumentData.AuditDocumentTypeEnum), nameof(AuditDocumentData.Name) }; if (inDto.SortField.IsNotNullOrEmpty()) { defalutSortArray = new string[] { nameof(AuditDocumentData.AuditDocumentTypeEnum), inDto.SortField + (inDto.Asc ? " asc" : " desc") }; inDto.SortField = string.Empty; } //匹配节点子查询 var matchedList = await _auditDocumentRepository.Where(x => x.AuditDocumentTypeEnum != AuditDocumentType.HistoricalVersion) .WhereIf(inDto.IsAuthorization != null, x => x.IsAuthorization == inDto.IsAuthorization) .WhereIf(inDto.AuditRecordId != null, x => x.IsAuthorization == inDto.IsAuthorization) .WhereIf(inDto.Name.IsNotNullOrEmpty(), n => n.Name.Contains(inDto.Name)) .SelectMany(t => t.AncestorList).Select(t => t.Ancestor)//祖先包含自己 .Distinct() //可能包含相同的祖先 .ProjectTo(_mapper.ConfigurationProvider) .SortToListAsync(defalutSortArray); #region 针对某次稽查 授权展示 //某个稽查记录 if (inDto.AuditRecordId != null) { //找到该稽查记录 授权文件的所有父节点Id var matchDocIdQuery = _auditRecordPermissionRepository.Where(t => t.AuditRecordId == inDto.AuditRecordId).Select(t => t.AuditDocumentId); var parentIdList = _auditDocumentClosureRepository.Where(t => matchDocIdQuery.Contains(t.DescendantId)).Select(t => t.AncestorId).Distinct().ToList(); //刚开始未授权,就是空的,默认展示所有 if (inDto.IsCurrentAuditRecordAuthorization == true) { //只查看授权的 matchedList = matchedList.Where(t => parentIdList.Contains((Guid)t.Id)).ToList(); } foreach (var ancestorId in parentIdList) { var find = matchedList.FirstOrDefault(t => t.Id == ancestorId); if (find != null) { //如果前端不想用新字段,那么就覆盖之前的授权字段 find.IsCurrentAuditRecordAuthorization = true; } } } #endregion // 构建字典并拼装树 var dict = matchedList.ToDictionary(n => n.Id, t => t); foreach (var node in dict.Values) { if (node.ParentId.HasValue && dict.TryGetValue(node.ParentId.Value, out var parent)) parent.Children.Add(node); } var query = dict.Values .WhereIf(inDto.SelfId != null, x => inDto.SelfId == x.Id) .WhereIf(inDto.Id != null, x => inDto.Id == x.ParentId) .WhereIf(inDto.Id == null && inDto.SelfId == null, x => x.ParentId == null); PageOutput result = new PageOutput() { PageIndex = inDto.PageIndex, PageSize = inDto.PageSize, TotalCount = query.Count(), }; var root = query.Skip(inDto.PageSize * (inDto.PageIndex - 1)).Take(inDto.PageSize).ToList(); result.CurrentPageData = root; return result; } /// /// 设置是否授权 /// /// /// [HttpPost] public async Task SetIsAuthorization(SetIsAuthorizationInDto inDto) { if (inDto.IsAuthorization) { //闭包表中找到 设置Id为祖先的所有 后代 包括自己 var matchIdQuery = _auditDocumentClosureRepository.Where(t => inDto.Ids.Contains(t.AncestorId)).Select(t => t.DescendantId); //闭包表中找到 设置Id为后代的所有 祖先 包括自己 var matchIdQuery2 = _auditDocumentClosureRepository.Where(t => inDto.Ids.Contains(t.DescendantId)).Select(t => t.AncestorId); var unionQuery = matchIdQuery.Union(matchIdQuery2); await _auditDocumentRepository.BatchUpdateNoTrackingAsync(t => unionQuery.Contains(t.Id), u => new AuditDocument() { IsAuthorization = inDto.IsAuthorization }); } else { //闭包表中找到 设置Id为祖先的所有 后代 包括自己 var matchIdQuery = _auditDocumentClosureRepository.Where(t => inDto.Ids.Contains(t.AncestorId)).Select(t => t.DescendantId); await _auditDocumentRepository.BatchUpdateNoTrackingAsync(t => matchIdQuery.Contains(t.Id), u => new AuditDocument() { IsAuthorization = inDto.IsAuthorization }); } return ResponseOutput.Ok(); } /// /// 删除稽查文档 /// /// /// [HttpPost] [UnitOfWork] public async Task DeleteAuditDocument(DeleteAuditDocumentInDto inDto) { var isNotOptHistoryFile = _auditDocumentRepository.Where(t => inDto.Ids.Contains(t.Id)).All(t => t.MainFileId == null); // 删除文件 或者文件夹里所有内容 (能在闭包表中找到) if (isNotOptHistoryFile) { //闭包表中找到 设置Id为祖先的所有 后代 包括自己 var matchList = _auditDocumentClosureRepository.Where(t => inDto.Ids.Contains(t.AncestorId)).Select(t => new { t.DescendantId, t.Descendant.MainFileId, IsExistOldVersion = t.Descendant.AuditDocumentOldVersionList.Any() }); var matchIdList = matchList.Select(t => t.DescendantId).Distinct(); //找到有版本的 var matchIdVersionList = matchList.Where(t => t.IsExistOldVersion).Select(t => t.DescendantId).Distinct(); //删除自己以及后代 (能在闭包表中找到的,肯定不是删除 当前历史版本的操作 和当前历史所有版本的操作,能在闭包包中找到,那么肯定是删除当前文件,和当前文件所有 版本文件) var success = await _auditDocumentRepository.DeleteFromQueryAsync(t => matchIdList.Contains(t.Id) || matchIdVersionList.Any(c => c == t.MainFileId)); // 删除原有闭包关系 await _auditDocumentClosureRepository.BatchDeleteNoTrackingAsync(t => matchIdList.Contains(t.DescendantId) || matchIdList.Contains(t.AncestorId)); } else { //删除历史版本操作 删除当前历史所有版本操作 var mainFileIdList = await _auditDocumentRepository.Where(t => inDto.Ids.Contains(t.Id)).Select(t => t.MainFileId).Distinct().ToListAsync(); //删除当前选择的历史版本 await _auditDocumentRepository.BatchDeleteNoTrackingAsync(t => inDto.Ids.Contains(t.Id)); foreach (var item in mainFileIdList) { var historicalVersionList = await _auditDocumentRepository.Where(x => x.MainFileId == item).OrderBy(x => x.Version).ToListAsync(); var num = 1; foreach (var historical in historicalVersionList) { await _auditDocumentRepository.UpdatePartialFromQueryAsync(historical.Id, x => new AuditDocument() { Version = num, }); num++; } } } await _auditDocumentRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } /// /// 把历史版本设置为当前版本--修改 维护闭包表,之间的闭包关系指向新版本文件 /// /// [HttpPost] public async Task SetCurrentVersion(SetCurrentVersionInDto inDto) { var file = await _auditDocumentRepository.Where(x => x.Id == inDto.Id).FirstNotNullAsync(); if (file.AuditDocumentTypeEnum != AuditDocumentType.HistoricalVersion) { throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotSetCurrentVersion"]); } var mainFile = await _auditDocumentRepository.Where(x => x.Id == file.MainFileId).FirstNotNullAsync(); var historicalVersionIds = await _auditDocumentRepository.Where(x => x.MainFileId == mainFile.Id && x.Id != inDto.Id).OrderBy(x => x.Version).Select(x => x.Id).ToListAsync(); historicalVersionIds.Add(mainFile.Id); await _auditDocumentRepository.UpdatePartialFromQueryAsync(inDto.Id, x => new AuditDocument() { MainFileId = null, ParentId = mainFile.ParentId, AuditDocumentTypeEnum = AuditDocumentType.File, }); int num = 1; foreach (var item in historicalVersionIds) { await _auditDocumentRepository.UpdatePartialFromQueryAsync(item, x => new AuditDocument() { MainFileId = inDto.Id, ParentId = null, Version = num, AuditDocumentTypeEnum = AuditDocumentType.HistoricalVersion }); num++; } await _auditDocumentRepository.SaveChangesAsync(); #region 闭包修改 //版本设计这里,当前版本才有parentId 不是当前版本就没有parentId->移动的时候还要维护历史版本的parentid //增加闭包,所以这里要维护闭包表 await _auditDocumentClosureRepository.BatchUpdateNoTrackingAsync(t => t.AncestorId == mainFile.Id, t => new AuditDocumentClosure() { AncestorId = inDto.Id }); await _auditDocumentClosureRepository.BatchUpdateNoTrackingAsync(t => t.DescendantId == mainFile.Id, t => new AuditDocumentClosure() { DescendantId = inDto.Id }); #endregion return ResponseOutput.Ok(); } /// /// 获取面包屑导航 (查询自己的祖先,不包括自己) /// /// /// [HttpPost] public async Task> GetBreadcrumbData(GetBreadcrumbDataInDto inDto) { //闭包表中找到 设置Id为后代的所有 祖先 Depth > 0 不包括自己 var list = await _auditDocumentClosureRepository.Where(t => inDto.Id == t.DescendantId /*&& t.Depth > 0*/) .OrderByDescending(t => t.Depth).Select(t => t.Ancestor).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); return list; #region 无闭包表废弃 //List result = new List(); //await findParent(result, inDto.Id); //async Task findParent(List datas, Guid id) //{ // var data = await _auditDocumentRepository.Where(x => x.Id == id).ProjectTo(_mapper.ConfigurationProvider).FirstNotNullAsync(); // datas.Add(data); // if (data.ParentId != null) // { // await findParent(datas, data.ParentId.Value); // } //} //result.Reverse(); //return result; #endregion } #endregion #region 闭包维护关系,只处理最底层调用 AddOrUpdateAuditDocument /// /// 移动文件或者文件夹 到其他文件夹 /// /// [HttpPost] public async Task MovieFileOrFolder(MovieFileOrFolderInDto inDto) { //闭包表中找到 设置Id为祖先的所有 后代 包括自己 var matchIdQuery = _auditDocumentClosureRepository.Where(t => inDto.Ids.Contains(t.AncestorId)).Select(t => t.DescendantId); //无法将当前文件夹移动到当前目录以及子文件夹 if (matchIdQuery.Any(t => t == inDto.ParentId)) { throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotMove"]); } #region 不考虑文件名重复 移动子树快速方法 //foreach (var item in inDto.Ids) //{ // var subtreeRoot = await _auditDocumentRepository.FirstOrDefaultAsync(t => t.Id == item); // subtreeRoot.ParentId = inDto.ParentId; // await MoveSubtreeAsync(item, inDto.ParentId); //} #endregion // 不能自动到自己父类这个文件夹 if (await _auditDocumentRepository.AnyAsync(x => x.ParentId == inDto.ParentId && inDto.Ids.Contains(x.Id))) { throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotMoveToParent"]); } await CopyFileOrFolder(inDto); await DeleteAuditDocument(new DeleteAuditDocumentInDto() { Ids = inDto.Ids }); return ResponseOutput.Ok(); } /// /// 复制文件或者文件夹 /// /// /// [HttpPost] public async Task CopyFileOrFolder(MovieFileOrFolderInDto inDto) { foreach (var item in inDto.Ids) { var data = (await GetAuditDocumentData(new GetAuditDocumentDataInDto() { SelfId = item, PageIndex = 1, PageSize = 1000 })).CurrentPageData; List auditDocumentAddOrEdits = _mapper.Map>(data); auditDocumentAddOrEdits.ForEach(x => { x.IsUpdate = false; x.IsAuthorization = false; x.Id = null; x.ParentId = inDto.ParentId; }); await addData(auditDocumentAddOrEdits); } async Task addData(List data) { foreach (var item in data) { item.Id = null; var result = await AddOrUpdateAuditDocument(item); item.Children.ForEach(x => { x.ParentId = result.Id; x.IsUpdate = false; x.Id = null; }); if (item.Children.Count() > 0) { await addData(item.Children); } } } return ResponseOutput.Ok(); } /// /// 修改稽查文档 /// /// /// [HttpPost] public async Task UpdateAuditDocument(AuditDocumentUpdateDto inDto) { AuditDocumentAddOrEdit addOrEdit = _mapper.Map(inDto); addOrEdit.IsUpdate = true; var result = await AddOrUpdateAuditDocument(addOrEdit); return ResponseOutput.Ok(result.Id); } /// /// 新增文件夹 /// /// /// /// [HttpPost] public async Task AddFolder(AuditDocumentAddOrEdit inDto) { if (await _auditDocumentRepository.AnyAsync(x => x.Name == inDto.Name && x.AuditDocumentTypeEnum == inDto.AuditDocumentTypeEnum && x.ParentId == inDto.ParentId)) { throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotAddFolder"]); } List auditDocumentAddOrEdits = new List(); auditDocumentAddOrEdits.Add(inDto); var result = await AddAuditDocument(auditDocumentAddOrEdits); return ResponseOutput.Ok(result); } /// /// 新增稽查文档 (批量上传文件时才是数组,文件夹时单个对象) /// /// /// [HttpPost] public async Task AddAuditDocument(List inDto) { List resultData = new List(); inDto.ForEach(x => x.IsUpdate = false); await addData(inDto); //构建父子关系,然后返回Id async Task addData(List data) { foreach (var item in data) { var result = await AddOrUpdateAuditDocument(item); resultData.Add(result.Id); item.Children.ForEach(x => { x.ParentId = result.Id; x.IsUpdate = false; }); if (item.Children.Count() > 0) { await addData(item.Children); } } } return ResponseOutput.Ok(resultData); } /// /// 通用方法 /// /// private async Task AddOrUpdateAuditDocument(AuditDocumentAddOrEdit inDto) { //同一层级不能加同名的文件 var alikeData = await _auditDocumentRepository.Where(x => x.Id != inDto.Id && x.ParentId == inDto.ParentId && x.Name == inDto.Name && x.AuditDocumentTypeEnum == inDto.AuditDocumentTypeEnum).FirstOrDefaultAsync(); //同层级找到了同名的 if (alikeData != null) { if (inDto.AuditDocumentTypeEnum == AuditDocumentType.Folder) { //更新 if (inDto.IsUpdate) { throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotAddFolder"]); } else { //添加相同目录,已存在,那么就不处理 return alikeData; } } else { //同名文件,那么作为版本处理(首先插入) var entityData = await _auditDocumentRepository.InsertOrUpdateAsync(inDto, true); //找到该同名文件的历史版本 var historicalVersionIds = await _auditDocumentRepository.Where(x => x.MainFileId == alikeData.Id).OrderBy(x => x.Version).Select(x => x.Id).ToListAsync(); //加上当前的同名文件 一起重新设置版本号 historicalVersionIds.Add(alikeData.Id); // 删除原有闭包关系 (重命的文件变成历史版本了) await _auditDocumentClosureRepository.BatchDeleteNoTrackingAsync(t => t.AncestorId == alikeData.Id || t.DescendantId == alikeData.Id); int num = 1; foreach (var item in historicalVersionIds) { await _auditDocumentRepository.UpdatePartialFromQueryAsync(item, x => new AuditDocument() { MainFileId = entityData.Id, ParentId = null, Version = num, AuditDocumentTypeEnum = AuditDocumentType.HistoricalVersion }); num++; await _auditDocumentRepository.SaveChangesAsync(); } // 针对版本文件是不需要维护闭包表的 if (inDto.Id == null && entityData.MainFileId == null) { //维护新增闭包关系 await AddClosureRelationsAsync(entityData.Id, entityData.ParentId); } return entityData; } } //同层级没找到同名的文件,那么走正常的新增 和更新 var entity = await _auditDocumentRepository.InsertOrUpdateAsync(inDto, true); if (inDto.Id == null && entity.MainFileId == null) { //维护新增闭包关系 await AddClosureRelationsAsync(entity.Id, entity.ParentId); } return entity; } #endregion #region 增加闭包设计 不用修改地方 /// /// 获取稽查文档 /// /// /// /// [HttpPost] public async Task> GetAuditDocumentList(AuditDocumentQuery inQuery) { var auditDocumentQueryable = _auditDocumentRepository .ProjectTo(_mapper.ConfigurationProvider); var pageList = await auditDocumentQueryable.ToPagedListAsync(inQuery); return pageList; } /// /// 获取历史版本 /// /// /// [HttpPost] public async Task> GetHistoricalVersion(GetHistoricalVersionInDto inDto) { List result = new List(); result = await _auditDocumentRepository.Where(x => x.MainFileId == inDto.Id).ProjectTo(_mapper.ConfigurationProvider).OrderByDescending(x => x.Version).ToListAsync(); var currentData = await _auditDocumentRepository.Where(x => x.Id == inDto.Id).ProjectTo(_mapper.ConfigurationProvider).FirstNotNullAsync(); currentData.IsCurrentVersion = true; result.Insert(0, currentData); return result; } #endregion #region 闭包后续废弃方法 ///// ///// 删除稽查文档 ///// ///// ///// //[HttpPost] //public async Task DeleteAuditDocument(DeleteAuditDocumentInDto inDto) //{ // var data = await _auditDocumentRepository.Select(x => new DeleteAudit() // { // Id = x.Id, // ParentId = x.ParentId, // MainFileId = x.MainFileId // }).ToListAsync(); // List DeleteId = inDto.Ids; // finId(inDto.Ids, data); // void finId(List deletids, List deletes) // { // DeleteId.AddRange(deletids); // var temp = deletes.Where(x => (x.ParentId != null && deletids.Contains(x.ParentId.Value)) || (x.MainFileId != null && deletids.Contains(x.MainFileId.Value))).Select(x => x.Id).ToList(); // if (temp.Count() > 0) // { // finId(temp, deletes); // } // } // DeleteId = DeleteId.Distinct().ToList(); // var mainFileId = await _auditDocumentRepository.Where(x => DeleteId.Contains(x.Id) && x.MainFileId != null).Select(x => x.MainFileId).Distinct().ToListAsync(); // var success = await _auditDocumentRepository.DeleteFromQueryAsync(t => DeleteId.Distinct().Contains(t.Id), true); // foreach (var item in mainFileId) // { // var historicalVersionList = await _auditDocumentRepository.Where(x => x.MainFileId == item).OrderBy(x => x.Version).ToListAsync(); // var num = 1; // foreach (var historical in historicalVersionList) // { // await _auditDocumentRepository.UpdatePartialFromQueryAsync(historical.Id, x => new AuditDocument() // { // Version = num, // }, true); // num++; // } // } // return ResponseOutput.Ok(); //} ///// ///// 获取文件树形结构 (传Id 根节点就是自己) ///// ///// ///// //[HttpPost] //public async Task> GetAuditDocumentData(GetAuditDocumentDataInDto inDto) //{ // var defalutSortArray = new string[] { nameof(AuditDocumentData.AuditDocumentTypeEnum), nameof(AuditDocumentData.Name) }; // if (inDto.SortField.IsNotNullOrEmpty()) // { // defalutSortArray = new string[] { nameof(AuditDocumentData.AuditDocumentTypeEnum), inDto.SortField + (inDto.Asc ? " asc" : " desc") }; // inDto.SortField = string.Empty; // } // // 新取出来排序 然后再找子项 // var data = (await _auditDocumentRepository // .Where(x => x.AuditDocumentTypeEnum != AuditDocumentType.HistoricalVersion) // .WhereIf(inDto.IsAuthorization != null, x => x.IsAuthorization == inDto.IsAuthorization) // .ProjectTo(_mapper.ConfigurationProvider).ToPagedListAsync(new PageInput() // { // PageIndex = 1, // PageSize = 999999, // }, defalutSortArray)).CurrentPageData.ToList(); // if (inDto.Name.IsNotNullOrEmpty()) // { // List findIds = new List(); // var findData = data.Where(x => x.Name.Contains(inDto.Name)).Select(x => x.Id.Value).ToList(); // GetParentId(findIds, findData, data); // findIds.AddRange(findData); // data = data.Where(x => findIds.Distinct().Contains(x.Id.Value)).ToList(); // } // var query = data // .WhereIf(inDto.SelfId != null, x => inDto.SelfId == x.Id) // .WhereIf(inDto.Id != null, x => inDto.Id == x.ParentId) // .WhereIf(inDto.Id == null && inDto.SelfId == null, x => x.ParentId == null); // PageOutput result = new PageOutput() // { // PageIndex = inDto.PageIndex, // PageSize = inDto.PageSize, // TotalCount = query.Count(), // }; // var root = query // .Skip(inDto.PageSize * (inDto.PageIndex - 1)).Take(inDto.PageSize).ToList(); // var historicalVersionList = await _auditDocumentRepository // .Where(x => x.AuditDocumentTypeEnum == AuditDocumentType.HistoricalVersion).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); // foreach (var item in root) // { // GetChildren(item, data, historicalVersionList); // } // result.CurrentPageData = root; // return result; //} //private void GetParentId(List parentIds, List ids, List dataList) //{ // var parentid = dataList.Where(x => ids.Contains(x.Id.Value) && x.ParentId != null).Select(x => x.ParentId.Value).ToList(); // if (parentid.Count() > 0) // { // parentIds.AddRange(parentid); // GetParentId(parentIds, parentid, dataList); // } //} //private void GetChildren(AuditDocumentData item, List dataList, List historyList) //{ // item.Children = dataList.Where(x => x.ParentId == item.Id).ToList(); // item.HistoricalVersionsCount = historyList.Where(x => x.MainFileId == item.Id).Count(); // foreach (var x in item.Children) // { // GetChildren(x, dataList, historyList); // } //} ///// ///// 移动文件或者文件夹 到其他文件夹 ///// ///// //[HttpPost] //public async Task MovieFileOrFolder(MovieFileOrFolderInDto inDto) //{ // var data = await _auditDocumentRepository.Select(x => new DeleteAudit() // { // Id = x.Id, // ParentId = x.ParentId, // AuditDocumentTypeEnum = x.AuditDocumentTypeEnum, // MainFileId = x.MainFileId // }).ToListAsync(); // foreach (var id in inDto.Ids) // { // var file = data.Where(x => x.Id == id).FirstOrDefault(); // if (file.AuditDocumentTypeEnum == AuditDocumentType.Folder) // { // if (finChild(new List { id }, inDto.ParentId, data)) // { // throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotMove"]); // } // } // } // bool finChild(List ids, Guid ChildId, List data) // { // var child = data.Where(x => x.ParentId != null && ids.Contains(x.ParentId.Value)).ToList(); // if (child.Count() == 0) // { // return false; // } // else if (child.Any(x => x.Id == ChildId)) // { // return true; // } // else // { // var newids = child.Select(x => x.Id).ToList(); // return finChild(newids, ChildId, data); // } // } // foreach (var id in inDto.Ids) // { // await _auditDocumentRepository.UpdatePartialFromQueryAsync(id, x => new AuditDocument() // { // ParentId = inDto.ParentId // }); // await _auditDocumentRepository.SaveChangesAsync(); // } // return ResponseOutput.Ok(); //} ///// ///// 复制文件或者文件夹 ///// ///// ///// //[HttpPost] //public async Task CopyFileOrFolder(MovieFileOrFolderInDto inDto) //{ // foreach (var item in inDto.Ids) // { // var data = (await GetAuditDocumentData(new GetAuditDocumentDataInDto() // { // SelfId = item, // PageIndex = 1, // PageSize = 1000 // })).CurrentPageData; // List auditDocumentAddOrEdits = _mapper.Map>(data); // auditDocumentAddOrEdits.ForEach(x => // { // x.IsUpdate = false; // x.Id = null; // x.ParentId = inDto.ParentId; // }); // await addData(auditDocumentAddOrEdits); // } // async Task addData(List data) // { // foreach (var item in data) // { // item.Id = null; // var result = await AddOrUpdateAuditDocument(item); // item.Children.ForEach(x => // { // x.ParentId = result.Id; // x.IsUpdate = false; // x.Id = null; // }); // if (item.Children.Count() > 0) // { // await addData(item.Children); // } // } // } // return ResponseOutput.Ok(); //} ///// ///// 设置是否授权 ///// ///// ///// //[HttpPost] //public async Task SetIsAuthorization(SetIsAuthorizationInDto inDto) //{ // var data = await _auditDocumentRepository.Select(x => new DeleteAudit() // { // Id = x.Id, // ParentId = x.ParentId, // MainFileId = x.MainFileId // }).ToListAsync(); // List allid = new List(); // findChild(allid, inDto.Ids, data); // if (inDto.IsAuthorization) // { // findParent(allid, inDto.Ids, data); // } // allid = allid.Distinct().ToList(); // await _auditDocumentRepository.UpdatePartialFromQueryAsync(t => allid.Contains(t.Id), x => new AuditDocument() // { // IsAuthorization = inDto.IsAuthorization // }); // await _auditDocumentRepository.SaveChangesAsync(); // return ResponseOutput.Ok(); // void findParent(List allId, List current, List data) // { // allId.AddRange(current); // var parent = data.Where(x => current.Contains(x.Id)).Select(x => x.ParentId).Where(x => x != null).Select(x => (Guid)x).ToList(); // if (parent.Count() > 0) // { // findParent(allId, parent, data); // } // } // void findChild(List allId, List current, List data) // { // allId.AddRange(current); // var child = data.Where(x => (x.ParentId != null && current.Contains(x.ParentId.Value)) || (x.MainFileId != null && current.Contains(x.MainFileId.Value))).Select(x => x.Id).ToList(); // if (child.Count() > 0) // { // findChild(allId, child, data); // } // } //} #endregion }