闭包针对稽查的修改
continuous-integration/drone/push Build is passing Details

Test_IRC_Net8
hang 2025-09-27 23:35:22 +08:00
parent 447e916564
commit d263ecbe2a
12 changed files with 21172 additions and 169 deletions

View File

@ -1483,7 +1483,7 @@
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditRecord},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditRecordPermission},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditRecordIdentityUser},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditDocument},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditRecord},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditRecordPermission},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditRecordIdentityUser},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditDocumentClosure},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
稽查文档
</summary>
@ -1510,12 +1510,72 @@
<param name="inCommand"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.AddClosureRelationsAsync(System.Guid,System.Nullable{System.Guid})">
<summary>
插入闭包表关系
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetAuditDocumentData_New(IRaCIS.Core.Application.ViewModel.GetAuditDocumentDataInDto)">
<summary>
获取文件树形结构 (传Id 根节点就是自己)
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.SetIsAuthorization_New(IRaCIS.Core.Application.ViewModel.SetIsAuthorizationInDto)">
<summary>
设置是否授权
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.CopyFileOrFolder_New(IRaCIS.Core.Application.ViewModel.MovieFileOrFolderInDto)">
<summary>
复制文件或者文件夹
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.MovieFileOrFolder_New(IRaCIS.Core.Application.ViewModel.MovieFileOrFolderInDto)">
<summary>
移动文件或者文件夹 到其他文件夹
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.DeleteAuditDocument_New(IRaCIS.Core.Application.ViewModel.DeleteAuditDocumentInDto)">
<summary>
删除稽查文档
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.SetCurrentVersion(IRaCIS.Core.Application.ViewModel.SetCurrentVersionInDto)">
<summary>
把历史版本设置为当前版本--修改 维护闭包表,之间的闭包关系指向新版本文件
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetAuditDocumentList(IRaCIS.Core.Application.ViewModel.AuditDocumentQuery)">
<summary>
获取稽查文档
</summary>
<param name="inQuery"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetHistoricalVersion(IRaCIS.Core.Application.ViewModel.GetHistoricalVersionInDto)">
<summary>
获取历史版本
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetBreadcrumbData(IRaCIS.Core.Application.ViewModel.GetBreadcrumbDataInDto)">
<summary>
获取面包屑导航
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.UpdateAuditDocument(IRaCIS.Core.Application.ViewModel.AuditDocumentUpdateDto)">
<summary>
@ -1534,7 +1594,7 @@
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.AddAuditDocument(System.Collections.Generic.List{IRaCIS.Core.Application.ViewModel.AuditDocumentAddOrEdit})">
<summary>
新增稽查文档
新增稽查文档 (批量上传文件时才是数组,文件夹时单个对象)
</summary>
<param name="inDto"></param>
<returns></returns>
@ -1545,9 +1605,9 @@
</summary>
<param name="inDto"></param>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetBreadcrumbData(IRaCIS.Core.Application.ViewModel.GetBreadcrumbDataInDto)">
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.DeleteAuditDocument(IRaCIS.Core.Application.ViewModel.DeleteAuditDocumentInDto)">
<summary>
获取面包屑导航
删除稽查文档
</summary>
<param name="inDto"></param>
<returns></returns>
@ -1559,13 +1619,6 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.DeleteAuditDocument(IRaCIS.Core.Application.ViewModel.DeleteAuditDocumentInDto)">
<summary>
删除稽查文档
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.MovieFileOrFolder(IRaCIS.Core.Application.ViewModel.MovieFileOrFolderInDto)">
<summary>
移动文件或者文件夹 到其他文件夹
@ -1579,19 +1632,6 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.GetHistoricalVersion(IRaCIS.Core.Application.ViewModel.GetHistoricalVersionInDto)">
<summary>
获取历史版本
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.SetCurrentVersion(IRaCIS.Core.Application.ViewModel.SetCurrentVersionInDto)">
<summary>
把历史版本设置为当前版本
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.AuditDocumentService.SetIsAuthorization(IRaCIS.Core.Application.ViewModel.SetIsAuthorizationInDto)">
<summary>
设置是否授权
@ -14298,6 +14338,14 @@
<param name="outEnrollTime"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.RebuildAuditDocumentClosureAsync(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditDocumentClosure},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.AuditDocument})">
<summary>
重建闭包表
</summary>
<param name="_auditDocumentClosureRepository"></param>
<param name="_auditDocumentRepository"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.TestService.DeleteConsistentDate(System.Guid,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskConsistentRule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingConsistentClinicalDataPDF},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingConsistentClinicalData})">
<summary>
清理一致性分析任务

View File

@ -20,6 +20,8 @@ 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;
namespace IRaCIS.Core.Application.Service;
@ -29,7 +31,7 @@ namespace IRaCIS.Core.Application.Service;
/// <returns></returns>
[ApiExplorerSettings(GroupName = "FileRecord")]
public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepository, IRepository<AuditRecord> _auditRecordRepository,
IRepository<AuditRecordPermission> _auditRecordPermissionRepository, IRepository<AuditRecordIdentityUser> _auditRecordIdentityUserRepository,
IRepository<AuditRecordPermission> _auditRecordPermissionRepository, IRepository<AuditRecordIdentityUser> _auditRecordIdentityUserRepository, IRepository<AuditDocumentClosure> _auditDocumentClosureRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
{
@ -131,9 +133,15 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
/// <returns></returns>
public async Task<IResponseOutput> SetAuditRecordPermission(SetAuditRecordPermissionCommand inCommand)
{
if (_auditRecordPermissionRepository.Any(t => t.AuditRecordId == inCommand.AuditRecordId && t.AuditDocumentId == inCommand.AuditDocumentId))
{
var find = _auditRecordPermissionRepository.FirstOrDefaultAsync(t => t.AuditRecordId == inCommand.AuditRecordId && t.AuditDocumentId == inCommand.AuditDocumentId);
if (find == null && inCommand.IsAuthorization)
{
await _auditRecordPermissionRepository.AddAsync(new AuditRecordPermission() { AuditRecordId = inCommand.AuditRecordId, AuditDocumentId = inCommand.AuditDocumentId }, true);
}
else
{
await _auditRecordPermissionRepository.DeleteFromQueryAsync(t => t.AuditRecordId == inCommand.AuditRecordId && t.AuditDocumentId == inCommand.AuditDocumentId, true);
}
return ResponseOutput.Ok();
@ -142,14 +150,331 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
#endregion
#region 闭包修改
/// <summary>
/// 插入闭包表关系
/// </summary>
private async Task AddClosureRelationsAsync(Guid nodeId, Guid? parentId)
{
var closures = new List<AuditDocumentClosure>();
// 自身关系
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();
}
/// <summary>
/// 获取文件树形结构 (传Id 根节点就是自己)
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<AuditDocumentData>> GetAuditDocumentData_New(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<AuditDocumentData>(_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.IsAuthorization == 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.Where(n => n.ParentId == null);
PageOutput<AuditDocumentData> result = new PageOutput<AuditDocumentData>()
{
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;
}
/// <summary>
/// 设置是否授权
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SetIsAuthorization_New(SetIsAuthorizationInDto inDto)
{
//闭包表中找到 设置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();
}
/// <summary>
/// 复制文件或者文件夹
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> CopyFileOrFolder_New(MovieFileOrFolderInDto inDto)
{
foreach (var id in inDto.Ids)
{
//当前节点的后代(包括自己) 拷贝的节点以及子节点
var nodeList = await _auditDocumentClosureRepository.Where(t => t.AncestorId == id).Select(t => t.Descendant).ToListAsync();
foreach (var node in nodeList)
{
//设置新节点Id
node.Id = NewId.NextSequentialGuid();
//建立新的闭包关系
await AddClosureRelationsAsync(node.Id, inDto.ParentId);
}
}
return ResponseOutput.Ok();
}
/// <summary>
/// 移动文件或者文件夹 到其他文件夹
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> MovieFileOrFolder_New(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"]);
}
foreach (var id in inDto.Ids)
{
//移动ParentId
var node = await _auditDocumentRepository.FirstOrDefaultAsync(t => t.Id == id);
node.ParentId = inDto.ParentId;
await _auditDocumentRepository.SaveChangesAsync();
// 删除原有闭包关系
await _auditDocumentClosureRepository.BatchDeleteNoTrackingAsync(t => t.DescendantId == id || t.AncestorId == id);
//建立新的闭包关系
await AddClosureRelationsAsync(node.Id, inDto.ParentId);
}
return ResponseOutput.Ok();
}
/// <summary>
/// 删除稽查文档
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> DeleteAuditDocument_New(DeleteAuditDocumentInDto inDto)
{
//闭包表中找到 设置Id为祖先的所有 后代 包括自己
var matchList = _auditDocumentClosureRepository.Where(t => inDto.Ids.Contains(t.AncestorId)).Select(t => new { t.DescendantId, t.Descendant.MainFileId });
//删除自己以及后代
var success = await _auditDocumentRepository.DeleteFromQueryAsync(t => matchList.Select(t => t.DescendantId).Distinct().Contains(t.Id), true);
//找到有版本的
var mainFileIdList = matchList.Where(t => t.MainFileId != null).ToList();
foreach (var item in mainFileIdList)
{
var historicalVersionList = await _auditDocumentRepository.Where(x => x.MainFileId == item.MainFileId).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();
}
/// <summary>
/// 把历史版本设置为当前版本--修改 维护闭包表,之间的闭包关系指向新版本文件
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> 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();
}
#endregion
#region 增加闭包设计 不用修改地方
/// <summary>
/// 获取稽查文档
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
///
[HttpPost]
public async Task<PageOutput<AuditDocumentView>> GetAuditDocumentList(AuditDocumentQuery inQuery)
{
@ -160,6 +485,65 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
return pageList;
}
/// <summary>
/// 获取历史版本
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<HistoricalVersionDto>> GetHistoricalVersion(GetHistoricalVersionInDto inDto)
{
List<HistoricalVersionDto> result = new List<HistoricalVersionDto>();
result = await _auditDocumentRepository.Where(x => x.MainFileId == inDto.Id).ProjectTo<HistoricalVersionDto>(_mapper.ConfigurationProvider).OrderByDescending(x => x.Version).ToListAsync();
var currentData = await _auditDocumentRepository.Where(x => x.Id == inDto.Id).ProjectTo<HistoricalVersionDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
currentData.IsCurrentVersion = true;
result.Insert(0, currentData);
return result;
}
/// <summary>
/// 获取面包屑导航
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<AuditDocumentUpdateDto>> GetBreadcrumbData(GetBreadcrumbDataInDto inDto)
{
List<AuditDocumentUpdateDto> result = new List<AuditDocumentUpdateDto>();
await findParent(result, inDto.Id);
async Task findParent(List<AuditDocumentUpdateDto> datas, Guid id)
{
var data = await _auditDocumentRepository.Where(x => x.Id == id).ProjectTo<AuditDocumentUpdateDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
datas.Add(data);
if (data.ParentId != null)
{
await findParent(datas, data.ParentId.Value);
}
}
result.Reverse();
return result;
}
#endregion
#region 闭包维护关系,只处理最底层调用 AddOrUpdateAuditDocument
/// <summary>
/// 修改稽查文档
/// </summary>
@ -198,8 +582,13 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
return ResponseOutput.Ok(result);
}
/// <summary>
/// 新增稽查文档
/// 新增稽查文档 (批量上传文件时才是数组,文件夹时单个对象)
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
@ -210,6 +599,8 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
inDto.ForEach(x => x.IsUpdate = false);
await addData(inDto);
//构建父子关系然后返回Id
async Task addData(List<AuditDocumentAddOrEdit> data)
{
foreach (var item in data)
@ -234,33 +625,41 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
return ResponseOutput.Ok(resultData);
}
/// <summary>
/// 通用方法
/// </summary>
/// <param name="inDto"></param>
private async Task<AuditDocument> 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);
int num = 1;
@ -272,44 +671,96 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
ParentId = null,
Version = num,
AuditDocumentTypeEnum = AuditDocumentType.HistoricalVersion
}, true);
});
num++;
await _auditDocumentRepository.SaveChangesAsync();
}
if (inDto.Id == null)
{
//维护新增闭包关系
await AddClosureRelationsAsync(entityData.Id, entityData.ParentId);
}
return entityData;
}
}
//同层级没找到同名的文件,那么走正常的新增 和更新
var entity = await _auditDocumentRepository.InsertOrUpdateAsync(inDto, true);
if (inDto.Id == null)
{
//维护新增闭包关系
await AddClosureRelationsAsync(entity.Id, entity.ParentId);
}
return entity;
}
#endregion
#region 闭包后续废弃方法
/// <summary>
/// 获取面包屑导航
/// 删除稽查文档
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<AuditDocumentUpdateDto>> GetBreadcrumbData(GetBreadcrumbDataInDto inDto)
public async Task<IResponseOutput> DeleteAuditDocument(DeleteAuditDocumentInDto inDto)
{
List<AuditDocumentUpdateDto> result = new List<AuditDocumentUpdateDto>();
await findParent(result, inDto.Id);
async Task findParent(List<AuditDocumentUpdateDto> datas, Guid id)
var data = await _auditDocumentRepository.Select(x => new DeleteAudit()
{
var data = await _auditDocumentRepository.Where(x => x.Id == id).ProjectTo<AuditDocumentUpdateDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
datas.Add(data);
if (data.ParentId != null)
Id = x.Id,
ParentId = x.ParentId,
MainFileId = x.MainFileId
}).ToListAsync();
List<Guid> DeleteId = inDto.Ids;
finId(inDto.Ids, data);
void finId(List<Guid> deletids, List<DeleteAudit> 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)
{
await findParent(datas, data.ParentId.Value);
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++;
}
}
result.Reverse();
return result;
return ResponseOutput.Ok();
}
@ -403,65 +854,6 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
GetChildren(x, dataList, historyList);
}
}
/// <summary>
/// 删除稽查文档
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> DeleteAuditDocument(DeleteAuditDocumentInDto inDto)
{
var data = await _auditDocumentRepository.Select(x => new DeleteAudit()
{
Id = x.Id,
ParentId = x.ParentId,
MainFileId = x.MainFileId
}).ToListAsync();
List<Guid> DeleteId = inDto.Ids;
finId(inDto.Ids, data);
void finId(List<Guid> deletids, List<DeleteAudit> 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();
}
/// <summary>
/// 移动文件或者文件夹 到其他文件夹
/// </summary>
@ -575,70 +967,6 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
return ResponseOutput.Ok();
}
/// <summary>
/// 获取历史版本
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<HistoricalVersionDto>> GetHistoricalVersion(GetHistoricalVersionInDto inDto)
{
List<HistoricalVersionDto> result = new List<HistoricalVersionDto>();
result = await _auditDocumentRepository.Where(x => x.MainFileId == inDto.Id).ProjectTo<HistoricalVersionDto>(_mapper.ConfigurationProvider).OrderByDescending(x => x.Version).ToListAsync();
var currentData = await _auditDocumentRepository.Where(x => x.Id == inDto.Id).ProjectTo<HistoricalVersionDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
currentData.IsCurrentVersion = true;
result.Insert(0, currentData);
return result;
}
/// <summary>
/// 把历史版本设置为当前版本
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> 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();
return ResponseOutput.Ok();
}
/// <summary>
/// 设置是否授权
@ -700,6 +1028,9 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
}
}
#endregion
}

View File

@ -104,6 +104,9 @@ public class GetAuditDocumentDataInDto : PageInput
public bool? IsAuthorization { get; set; }
public string Name { get; set; } = string.Empty;
//当前稽查记录Id
public Guid? AuditRecordId { get; set; }
}
public class GetAuditDocumentDataOutDto
@ -125,6 +128,9 @@ public class AuditDocumentData : AuditDocumentUpdateDto
public int HistoricalVersionsCount { get; set; }
public List<AuditDocumentData> Children { get; set; } = new List<AuditDocumentData>() { };
public bool? IsCurrentAuditRecordAuthorization { get; set; }
}
public class AuditDocumentView : AuditDocumentAddOrEdit

View File

@ -29,7 +29,8 @@ namespace IRaCIS.Core.Application.Service
CreateMap<AuditDocument, AuditDocumentUpdateDto>();
CreateMap<AuditDocument, HistoricalVersionDto>();
CreateMap<AuditDocumentUpdateDto, AuditDocumentAddOrEdit>();
CreateMap<AuditDocument, AuditDocumentData>();
CreateMap<AuditDocument, AuditDocumentData>()
.ForMember(d => d.HistoricalVersionsCount, u => u.MapFrom(s => s.AuditDocumentOldVersionList.Count()));
CreateMap<AuditDocument, AuditDocumentAddOrEdit>().ReverseMap();
CreateMap<SystemDocument, SystemDocumentView>()
.ForMember(d => d.AttachmentCount, u => u.MapFrom(s => s.SystemDocumentAttachmentList.Count()))

View File

@ -73,6 +73,63 @@ namespace IRaCIS.Core.Application.Service
ILogger<TestService> _logger, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
{
public static int IntValue = 100;
/// <summary>
/// 重建闭包表
/// </summary>
/// <param name="_auditDocumentClosureRepository"></param>
/// <param name="_auditDocumentRepository"></param>
/// <returns></returns>
[AllowAnonymous]
public async Task RebuildAuditDocumentClosureAsync([FromServices]IRepository<AuditDocumentClosure> _auditDocumentClosureRepository, [FromServices] IRepository<AuditDocument> _auditDocumentRepository)
{
var documents = await _auditDocumentRepository.Where().Select(t=>new {t.Id,t.ParentId}).ToListAsync();
var closures = new List<AuditDocumentClosure>();
// 建立一个字典,加快查找
var lookup = documents.ToDictionary(d => d.Id, d => d.ParentId);
foreach (var doc in documents)
{
// 1 自己 -> 自己 (depth = 0)
closures.Add(new AuditDocumentClosure
{
AncestorId = doc.Id,
DescendantId = doc.Id,
Depth = 0
});
// 2 递归向上找所有祖先
int depth = 1;
var currentParentId = doc.ParentId;
while (currentParentId.HasValue)
{
closures.Add(new AuditDocumentClosure
{
AncestorId = currentParentId.Value,
DescendantId = doc.Id,
Depth = depth
});
depth++;
// 继续向上查找
if (!lookup.TryGetValue(currentParentId.Value, out var nextParent))
break;
currentParentId = nextParent;
}
}
await _auditDocumentClosureRepository.AddRangeAsync(closures);
await _auditDocumentClosureRepository.SaveChangesAsync();
}
/// <summary>
/// 清理一致性分析任务
/// </summary>

View File

@ -11,7 +11,19 @@ namespace IRaCIS.Core.Domain.Models
[Table("AuditDocument")]
public class AuditDocument : BaseFullAuditEntity
{
// 0=自己, 1=直接子节点, 2=孙节点...
[JsonIgnore]
public List<AuditDocumentClosure> AncestorList { get; set; } = new List<AuditDocumentClosure>();
[JsonIgnore]
public List<AuditDocumentClosure> DescendantList { get; set; } = new List<AuditDocumentClosure>();
[JsonIgnore]
public List<AuditDocument> AuditDocumentOldVersionList { get; set; }
[JsonIgnore]
[ForeignKey(nameof(MainFileId))]
public AuditDocument MainAuditDocument { get; set; }
/// <summary>
/// 文件夹名或者文件名
/// </summary>
@ -81,6 +93,27 @@ namespace IRaCIS.Core.Domain.Models
}
/// <summary>
/// 稽查文档闭包表
/// </summary>
public class AuditDocumentClosure : Entity
{
[JsonIgnore]
public AuditDocument Ancestor { get; set; }
[JsonIgnore]
public AuditDocument Descendant { get; set; }
[Comment("祖先")]
public Guid AncestorId { get; set; }
[Comment("后代")]
public Guid DescendantId { get; set; }
public int Depth { get; set; } // 0=自己, 1=直接子节点, 2=孙节点...
}
public class AuditRecord : BaseFullAuditEntity
{

View File

@ -679,7 +679,9 @@ public class IRaCISDBContext : DbContext
public virtual DbSet<AuditRecordIdentityUser> AuditRecordIdentityUser { get; set; }
public virtual DbSet<AuditRecordPermission> AuditRecordPermission { get; set; }
public virtual DbSet<AuditDocumentClosure> AuditDocumentClosure { get; set; }
}
public class TestLength : Entity

View File

@ -0,0 +1,40 @@
using IRaCIS.Core.Domain.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace IRaCIS.Core.Infra.EFCore.EntityConfigration
{
public class AuditDocumentConfigration : IEntityTypeConfiguration<AuditDocument>
{
public void Configure(EntityTypeBuilder<AuditDocument> builder)
{
builder.HasMany(r => r.AncestorList).WithOne(t => t.Descendant).HasForeignKey(f => f.DescendantId);
builder.HasMany(r => r.DescendantList).WithOne(t => t.Ancestor).HasForeignKey(f => f.AncestorId);
builder.HasMany(r => r.AuditDocumentOldVersionList).WithOne(t => t.MainAuditDocument).HasForeignKey(f => f.MainFileId);
// builder.HasOne(r => r.WordFileRecord)
//.WithOne(t => t.WordFileRecord)
//.HasForeignKey<TrialFile>(t => t.WordFileRecordId)
//.OnDelete(DeleteBehavior.Cascade);
// builder.HasOne(r => r.PDFFileRecord).WithOne().HasForeignKey<TrialFile>(f => f.TrialFileTypeId);
// builder.HasOne(r => r.WordFileRecord).WithOne().HasForeignKey<TrialFile>(f => f.TrialFileTypeId);
// builder.HasOne(r => r.SignFileRecord).WithOne().HasForeignKey<TrialFile>(f => f.TrialFileTypeId);
// builder.HasOne(r => r.HistoryFileRecord).WithOne().HasForeignKey<TrialFile>(f => f.TrialFileTypeId);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class modifyAudictDoc : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AuditDocumentClosure",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
AncestorId = table.Column<Guid>(type: "uniqueidentifier", nullable: false, comment: "祖先"),
DescendantId = table.Column<Guid>(type: "uniqueidentifier", nullable: false, comment: "后代"),
Depth = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AuditDocumentClosure", x => x.Id);
table.ForeignKey(
name: "FK_AuditDocumentClosure_AuditDocument_AncestorId",
column: x => x.AncestorId,
principalTable: "AuditDocument",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AuditDocumentClosure_AuditDocument_DescendantId",
column: x => x.DescendantId,
principalTable: "AuditDocument",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AuditDocument_MainFileId",
table: "AuditDocument",
column: "MainFileId");
migrationBuilder.CreateIndex(
name: "IX_AuditDocumentClosure_AncestorId",
table: "AuditDocumentClosure",
column: "AncestorId");
migrationBuilder.CreateIndex(
name: "IX_AuditDocumentClosure_DescendantId",
table: "AuditDocumentClosure",
column: "DescendantId");
migrationBuilder.AddForeignKey(
name: "FK_AuditDocument_AuditDocument_MainFileId",
table: "AuditDocument",
column: "MainFileId",
principalTable: "AuditDocument",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AuditDocument_AuditDocument_MainFileId",
table: "AuditDocument");
migrationBuilder.DropTable(
name: "AuditDocumentClosure");
migrationBuilder.DropIndex(
name: "IX_AuditDocument_MainFileId",
table: "AuditDocument");
}
}
}

View File

@ -149,12 +149,39 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.HasIndex("CreateUserId");
b.HasIndex("MainFileId");
b.ToTable("AuditDocument", t =>
{
t.HasComment("稽查文档管理");
});
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditDocumentClosure", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AncestorId")
.HasColumnType("uniqueidentifier")
.HasComment("祖先");
b.Property<int>("Depth")
.HasColumnType("int");
b.Property<Guid>("DescendantId")
.HasColumnType("uniqueidentifier")
.HasComment("后代");
b.HasKey("Id");
b.HasIndex("AncestorId");
b.HasIndex("DescendantId");
b.ToTable("AuditDocumentClosure");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecord", b =>
{
b.Property<Guid>("Id")
@ -15369,7 +15396,32 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("IRaCIS.Core.Domain.Models.AuditDocument", "MainAuditDocument")
.WithMany("AuditDocumentOldVersionList")
.HasForeignKey("MainFileId");
b.Navigation("CreateUserRole");
b.Navigation("MainAuditDocument");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditDocumentClosure", b =>
{
b.HasOne("IRaCIS.Core.Domain.Models.AuditDocument", "Ancestor")
.WithMany("DescendantList")
.HasForeignKey("AncestorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("IRaCIS.Core.Domain.Models.AuditDocument", "Descendant")
.WithMany("AncestorList")
.HasForeignKey("DescendantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ancestor");
b.Navigation("Descendant");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecord", b =>
@ -19802,6 +19854,15 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Navigation("CreateUserRole");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditDocument", b =>
{
b.Navigation("AncestorList");
b.Navigation("AuditDocumentOldVersionList");
b.Navigation("DescendantList");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecord", b =>
{
b.Navigation("AuditRecordIdentityUserList");

View File

@ -185,5 +185,15 @@ namespace IRaCIS.Core.Infrastructure.Extention
}
public static async Task<List<T>> SortToListAsync<T>(this IQueryable<T> source, string[] sortArray = default, CancellationToken cancellationToken = default)
{
var sortString = string.Join(',', sortArray);
source = source.OrderBy(sortString);
return await source.ToListAsync(cancellationToken);
}
}
}