//--------------------------------------------------------------------
// 此代码由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
await CopyFileOrFolder(inDto);
await DeleteAuditDocument(new DeleteAuditDocumentInDto()
{
Ids = inDto.Ids
});
return ResponseOutput.Ok();
}
///
/// 复制文件或者文件夹
///
///
///
[HttpPost]
public async Task CopyFileOrFolder(MovieFileOrFolderInDto inDto)
{
#region 不考虑版本的话处理方式
////1、当前节点的后代(包括自己) 拷贝的节点以及子节点
//var nodeList = await _auditDocumentClosureRepository.Where(t => t.AncestorId == id).Select(t => t.Descendant).ToListAsync();
//// 2. 创建映射表 OldId -> NewId
//var oldToNewId = new Dictionary();
//// 3. 复制节点
//var newNodeList = nodeList.Clone();
//foreach (var node in newNodeList)
//{
// var newId = NewId.NextSequentialGuid();
// //存储旧Id 和新Id 关系
// oldToNewId[node.Id] = newId;
// //设置新节点Id
// node.Id = newId;
//}
//// 4. 调整 ParentId 指向新 Id
//foreach (var newNode in newNodeList)
//{
// if (newNode.ParentId.HasValue && oldToNewId.TryGetValue(newNode.ParentId.Value, out var newParentId))
// {
// newNode.ParentId = newParentId; // 指向新父节点
// }
// else
// {
// newNode.ParentId = inDto.ParentId; // 顶层节点指向目标父节点
// }
//}
//foreach (var node in newNodeList)
//{
// await _auditDocumentRepository.AddAsync(node);
// //建立新的闭包关系
// await AddClosureRelationsAsync(node.Id, inDto.ParentId);
//}
#endregion
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
}