From 6c409bfa00e2480173f4f1fb21699c495ea4908b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=99=E5=AD=90?= <454313500@qq.com> Date: Sat, 21 Dec 2024 18:00:43 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IServices/IFileService.cs | 14 +- .../Services/FileService.cs | 114 +++------------ .../Entities/FileAggregateRoot.cs | 131 ++++++++++++++++-- .../Managers/FileManager.cs | 84 +++++++++++ .../Managers/IFileManager.cs | 6 + 5 files changed, 243 insertions(+), 106 deletions(-) create mode 100644 Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/FileManager.cs create mode 100644 Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IFileManager.cs diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IFileService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IFileService.cs index d9fdc6c5..52132f84 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IFileService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IFileService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Volo.Abp.Application.Services; using Yi.Framework.Rbac.Application.Contracts.Dtos.FileManager; @@ -6,7 +7,16 @@ namespace Yi.Framework.Rbac.Application.Contracts.IServices { public interface IFileService : IApplicationService { - Task GetReturnPathAsync(Guid code, bool? isThumbnail); - Task> Post(IFormFileCollection file); + /// + /// 下载文件,支持缩略图 + /// + /// + Task Get([FromRoute] Guid code, [FromRoute] bool? isThumbnail); + + /// + /// 上传文件 + /// + /// + Task> Post([FromForm] IFormFileCollection file); } } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/FileService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/FileService.cs index 011be87f..f7be6221 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/FileService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/FileService.cs @@ -15,129 +15,55 @@ using Yi.Framework.Core.Helper; using Yi.Framework.Rbac.Application.Contracts.Dtos.FileManager; using Yi.Framework.Rbac.Application.Contracts.IServices; using Yi.Framework.Rbac.Domain.Entities; +using Yi.Framework.Rbac.Domain.Managers; namespace Yi.Framework.Rbac.Application.Services { public class FileService : ApplicationService, IFileService { private readonly IRepository _repository; - private IGuidGenerator _guidGenerator; - public FileService(IRepository repository, IGuidGenerator guidGenerator) + private readonly FileManager _fileManager; + + public FileService(IRepository repository, FileManager fileManager) { - _guidGenerator = guidGenerator; _repository = repository; + _fileManager = fileManager; } /// - /// 下载文件,是否缩略图 + /// 下载文件,支持缩略图 /// /// [Route("file/{code}/{isThumbnail?}")] public async Task Get([FromRoute] Guid code, [FromRoute] bool? isThumbnail) { - var path = await GetReturnPathAsync(code, isThumbnail); - - if (path is null||!File.Exists(path)) + var file = await _repository.GetAsync(x => x.Id == code); + var path = file.GetQueryFileSavePath(isThumbnail); + if (path is null || !File.Exists(path)) { return new NotFoundResult(); - // throw new UserFriendlyException("文件不存在",code:"404"); } - - var steam = await File.ReadAllBytesAsync(path); - - //考虑从路径中获取 - var fileContentType = MimeHelper.GetMimeMapping(Path.GetFileName(path)); - //设置附件下载,下载名称 - //_httpContext.FileAttachmentHandle(file.FileName); - return new FileContentResult(steam, fileContentType ?? @"text/plain"); + return new FileContentResult(steam, file.GetMimeMapping()); } - - public async Task GetReturnPathAsync(Guid code, bool? isThumbnail) - { - var file = await _repository.GetAsync(x => x.Id == code); - if (file is null) - { - return null; - // throw new UserFriendlyException("文件编号未匹配", "404"); - } - var path = file.FilePath; - //如果为缩略图,需要修改路径 - //if (isThumbnail is true) - //{ - // path = $"wwwroot/{FileTypeEnum.Thumbnail}/{file.Id}{Path.GetExtension(file.FileName)}"; - //} - //路径为: 文件路径/文件id+文件扩展名 - return path; - } - + /// /// 上传文件 - /// Todo: 可放入领域层 /// /// public async Task> Post([FromForm] IFormFileCollection file) { - if (file.Count() == 0) + var entities = await _fileManager.CreateAsync(file); + + for (int i = 0; i < file.Count; i++) { - throw new ArgumentException("文件上传为空!"); + var entity= entities[i]; + using (var steam = file[i].OpenReadStream()) + { + await _fileManager.SaveFileAsync(entity,steam); + } } - //批量插入 - List entities = new(); - - foreach (var f in file) - { - FileAggregateRoot data = new(_guidGenerator.Create()); - data.FileSize = (decimal)f.Length / 1024; - data.FileName = f.FileName; - - var type = MimeHelper.GetFileType(f.FileName); - - //落盘文件,文件名为雪花id+自己的扩展名 - string filename = data.Id.ToString() + Path.GetExtension(f.FileName); - string typePath = $"wwwroot/{type}"; - if (!Directory.Exists(typePath)) - { - Directory.CreateDirectory(typePath); - } - var filePath = Path.Combine(typePath, filename); - data.FilePath = filePath; - - - //生成文件 - using (var stream = new FileStream(filePath, FileMode.CreateNew, FileAccess.ReadWrite)) - { - await f.CopyToAsync(stream); - - //如果是图片类型,还需要生成缩略图,当然,如果图片很小,直接复制过去即可 - if (FileTypeEnum.Image.Equals(type)) - { - string thumbnailPath = $"wwwroot/{FileTypeEnum.Thumbnail}"; - if (!Directory.Exists(thumbnailPath)) - { - Directory.CreateDirectory(thumbnailPath); - } - string thumbnailFilePath = Path.Combine(thumbnailPath, filename); - try - { - // _imageSharpManager.ImageCompress(f.FileName, f.OpenReadStream(), thumbnailFilePath); - } - catch - { - var result = new byte[stream.Length]; - await stream.ReadAsync(result, 0, result.Length); - await File.WriteAllBytesAsync(thumbnailFilePath, result); - } - } - - - }; - entities.Add(data); - } - await _repository.InsertManyAsync(entities); return entities.Adapt>(); - - } } -} +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/FileAggregateRoot.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/FileAggregateRoot.cs index 16beb5c2..4ef11526 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/FileAggregateRoot.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/FileAggregateRoot.cs @@ -7,6 +7,8 @@ using SqlSugar; using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.Domain.Entities; +using Yi.Framework.Core.Enums; +using Yi.Framework.Core.Helper; namespace Yi.Framework.Rbac.Domain.Entities { @@ -17,28 +19,140 @@ namespace Yi.Framework.Rbac.Domain.Entities { } - public FileAggregateRoot(Guid fileId) + /// + /// 创建文件 + /// + /// 文件标识id + /// 文件名 + /// 文件大小 + public FileAggregateRoot(Guid fileId, string fileName, decimal fileSize) { this.Id = fileId; + this.FileSize = fileSize; + this.FileName = fileName; + + var type = GetFileType(); + + var savePath = GetSaveFilePath(); + var filePath = Path.Combine(savePath, this.FileName); + this.FilePath = filePath; } - [SugarColumn(IsPrimaryKey = true)] - public override Guid Id { get; protected set; } + /// + /// 检测目录是否存在,不存在便创建 + /// + public void CheckDirectoryOrCreate() + { + var savePath = GetSaveDirPath(); + if (!Directory.Exists(savePath)) + { + Directory.CreateDirectory(savePath); + } + } + + /// + /// 文件类型 + /// + /// + public FileTypeEnum GetFileType() + { + return MimeHelper.GetFileType(this.FileName); + } + + /// + /// 获取文件mime + /// + /// + public string GetMimeMapping() + { + return MimeHelper.GetMimeMapping(this.FileName)??@"text/plain"; + } + + /// + /// 落库目录路径 + /// + /// + public string GetSaveDirPath() + { + return $"wwwroot/{GetFileType()}"; + } + + /// + /// 落库文件路径 + /// + /// + public string GetSaveFilePath() + { + string savefileName = GetSaveFileName(); + return Path.Combine(GetSaveDirPath(), savefileName); + } + + /// + /// 获取保存的文件名 + /// + /// + public string GetSaveFileName() + { + return this.Id.ToString() + Path.GetExtension(this.FileName); + } + + /// + /// 检测,并且返回缩略图的保存路径 + /// + /// + /// + public string GetAndCheakThumbnailSavePath(bool isCheak=false) + { + string thumbnailPath = $"wwwroot/{FileTypeEnum.Thumbnail}"; + if (isCheak) + { + if (!Directory.Exists(thumbnailPath)) + { + Directory.CreateDirectory(thumbnailPath); + } + } + return Path.Combine(thumbnailPath, GetSaveFileName()); + } + + + /// + /// 获取查询的的文件路径 + /// + /// + /// + /// + public string? GetQueryFileSavePath(bool? isThumbnail) + { + string fileSavePath; + //如果为缩略图,需要修改路径 + if (isThumbnail is true) + { + fileSavePath = this.GetAndCheakThumbnailSavePath(); + } + else + { + fileSavePath = this.GetSaveFilePath(); + } + return fileSavePath; + } + /// /// 文件大小 /// [SugarColumn(ColumnName = "FileSize")] - public decimal FileSize { get; set; } + public decimal FileSize { get; internal set; } + /// /// 文件名 /// [SugarColumn(ColumnName = "FileName")] - public string FileName { get; set; } + public string FileName { get; internal set; } + /// /// 文件路径 /// [SugarColumn(ColumnName = "FilePath")] - public string FilePath { get; set; } + public string FilePath { get; internal set; } public DateTime CreationTime { get; set; } public Guid? CreatorId { get; set; } @@ -46,8 +160,5 @@ namespace Yi.Framework.Rbac.Domain.Entities public Guid? LastModifierId { get; set; } public DateTime? LastModificationTime { get; set; } - - [SugarColumn(IsIgnore=true)] - public override ExtraPropertyDictionary ExtraProperties { get; protected set; } } -} +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/FileManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/FileManager.cs new file mode 100644 index 00000000..d6698128 --- /dev/null +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/FileManager.cs @@ -0,0 +1,84 @@ +using Mapster; +using Microsoft.AspNetCore.Http; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Domain.Services; +using Volo.Abp.Guids; +using Yi.Framework.Core.Enums; +using Yi.Framework.Core.Helper; +using Yi.Framework.Rbac.Domain.Entities; + +namespace Yi.Framework.Rbac.Domain.Managers; + +public class FileManager : DomainService, IFileManager +{ + private IGuidGenerator _guidGenerator; + private readonly IRepository _repository; + + public FileManager(IGuidGenerator guidGenerator, IRepository repository) + { + _guidGenerator = guidGenerator; + _repository = repository; + } + + /// + /// 批量插入数据库 + /// + /// + /// + public async Task> CreateAsync(IEnumerable files) + { + if (files.Count() == 0) + { + throw new ArgumentException("文件上传为空!"); + } + + //批量插入 + List entities = new(); + foreach (var file in files) + { + FileAggregateRoot data = new(_guidGenerator.Create(), file.FileName, (decimal)file.Length / 1024); + data.CheckDirectoryOrCreate(); + entities.Add(data); + } + + await _repository.InsertManyAsync(entities); + return entities; + } + + + /// + /// 保存文件 + /// + /// + /// + public async Task SaveFileAsync(FileAggregateRoot file,Stream fileStream) + { + var filePath = file.GetSaveFilePath(); + + //生成文件 + using (var stream = new FileStream(filePath, FileMode.CreateNew, FileAccess.ReadWrite)) + { + await fileStream.CopyToAsync(stream); + + //如果是图片类型,还需要生成缩略图 + //这里根据自己需求变更,我们的需求是:原始文件与缩略图文件,都要一份 + var fileType=file.GetFileType();; + //如果文件类型是图片,尝试进行压缩 + if (FileTypeEnum.Image.Equals(fileType)) + { + var thumbnailSavePath= file.GetAndCheakThumbnailSavePath(true); + try + { + // _imageSharpManager.ImageCompress(f.FileName, f.OpenReadStream(), thumbnailFilePath); + } + catch + { + //如果失败了,直接复制一份到缩略图上即可 + var result = new byte[stream.Length]; + await stream.ReadAsync(result, 0, result.Length); + await File.WriteAllBytesAsync(thumbnailSavePath, result); + } + } + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IFileManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IFileManager.cs new file mode 100644 index 00000000..838476ab --- /dev/null +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IFileManager.cs @@ -0,0 +1,6 @@ +namespace Yi.Framework.Rbac.Domain.Managers; + +public interface IFileManager +{ + +} \ No newline at end of file From c00ada5aee77f93db8500e7b01ee7fbee3efc60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=99=E5=AD=90?= <454313500@qq.com> Date: Sat, 21 Dec 2024 23:00:43 +0800 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20=E5=AE=8C=E6=88=90=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=A8=A1=E5=9D=97=E4=BC=98=E5=8C=96=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Yi.Framework.Core/Enums/FileTypeEnum.cs | 10 +-- .../Yi.Framework.Core/Helper/MimeHelper.cs | 4 +- .../Entities/FileAggregateRoot.cs | 2 +- .../Managers/FileManager.cs | 64 ++++++++++++++----- .../Yi.Framework.Rbac.Domain.csproj | 3 +- .../YiFrameworkRbacDomainModule.cs | 4 +- 6 files changed, 61 insertions(+), 26 deletions(-) diff --git a/Yi.Abp.Net8/framework/Yi.Framework.Core/Enums/FileTypeEnum.cs b/Yi.Abp.Net8/framework/Yi.Framework.Core/Enums/FileTypeEnum.cs index 1776d35f..193f7909 100644 --- a/Yi.Abp.Net8/framework/Yi.Framework.Core/Enums/FileTypeEnum.cs +++ b/Yi.Abp.Net8/framework/Yi.Framework.Core/Enums/FileTypeEnum.cs @@ -11,10 +11,10 @@ namespace Yi.Framework.Core.Enums /// public enum FileTypeEnum { - File, - Image, - Thumbnail, - Excel, - Temp + file, + image, + thumbnail, + excel, + temp } } diff --git a/Yi.Abp.Net8/framework/Yi.Framework.Core/Helper/MimeHelper.cs b/Yi.Abp.Net8/framework/Yi.Framework.Core/Helper/MimeHelper.cs index d03bf16b..a89d9212 100644 --- a/Yi.Abp.Net8/framework/Yi.Framework.Core/Helper/MimeHelper.cs +++ b/Yi.Abp.Net8/framework/Yi.Framework.Core/Helper/MimeHelper.cs @@ -45,8 +45,8 @@ namespace Yi.Framework.Core.Helper { var extension = Path.GetExtension(fileName); if (ImageType.Contains(extension.ToLower())) - return FileTypeEnum.Image; - return FileTypeEnum.File; + return FileTypeEnum.image; + return FileTypeEnum.file; } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/FileAggregateRoot.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/FileAggregateRoot.cs index 4ef11526..7cb6faf9 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/FileAggregateRoot.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/FileAggregateRoot.cs @@ -103,7 +103,7 @@ namespace Yi.Framework.Rbac.Domain.Entities /// public string GetAndCheakThumbnailSavePath(bool isCheak=false) { - string thumbnailPath = $"wwwroot/{FileTypeEnum.Thumbnail}"; + string thumbnailPath = $"wwwroot/{FileTypeEnum.thumbnail}"; if (isCheak) { if (!Directory.Exists(thumbnailPath)) diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/FileManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/FileManager.cs index d6698128..4a39c846 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/FileManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/FileManager.cs @@ -1,8 +1,10 @@ using Mapster; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; using Volo.Abp.Guids; +using Volo.Abp.Imaging; using Yi.Framework.Core.Enums; using Yi.Framework.Core.Helper; using Yi.Framework.Rbac.Domain.Entities; @@ -13,11 +15,14 @@ public class FileManager : DomainService, IFileManager { private IGuidGenerator _guidGenerator; private readonly IRepository _repository; - - public FileManager(IGuidGenerator guidGenerator, IRepository repository) + private readonly IImageCompressor _imageCompressor; + public FileManager(IGuidGenerator guidGenerator, IRepository repository, + + IImageCompressor imageCompressor) { _guidGenerator = guidGenerator; _repository = repository; + _imageCompressor = imageCompressor; } /// @@ -51,7 +56,7 @@ public class FileManager : DomainService, IFileManager /// /// /// - public async Task SaveFileAsync(FileAggregateRoot file,Stream fileStream) + public async Task SaveFileAsync(FileAggregateRoot file, Stream fileStream) { var filePath = file.GetSaveFilePath(); @@ -59,25 +64,52 @@ public class FileManager : DomainService, IFileManager using (var stream = new FileStream(filePath, FileMode.CreateNew, FileAccess.ReadWrite)) { await fileStream.CopyToAsync(stream); + fileStream.Position = 0; + } - //如果是图片类型,还需要生成缩略图 - //这里根据自己需求变更,我们的需求是:原始文件与缩略图文件,都要一份 - var fileType=file.GetFileType();; - //如果文件类型是图片,尝试进行压缩 - if (FileTypeEnum.Image.Equals(fileType)) + + //如果是图片类型,还需要生成缩略图 + //这里根据自己需求变更,我们的需求是:原始文件与缩略图文件,都要一份 + var fileType = file.GetFileType(); + //如果文件类型是图片,尝试进行压缩 + if (FileTypeEnum.image==fileType) + { + var thumbnailSavePath = file.GetAndCheakThumbnailSavePath(true); + Stream compressImageStream=null; + try { - var thumbnailSavePath= file.GetAndCheakThumbnailSavePath(true); - try + //压缩图片 + var compressResult = await _imageCompressor.CompressAsync(fileStream, file.GetMimeMapping()); + if (compressResult.State == ImageProcessState.Done) { - // _imageSharpManager.ImageCompress(f.FileName, f.OpenReadStream(), thumbnailFilePath); + compressImageStream = + (await _imageCompressor.CompressAsync(fileStream, file.GetMimeMapping())).Result; } - catch + else if (compressResult.State == ImageProcessState.Canceled) { - //如果失败了,直接复制一份到缩略图上即可 - var result = new byte[stream.Length]; - await stream.ReadAsync(result, 0, result.Length); - await File.WriteAllBytesAsync(thumbnailSavePath, result); + throw new NotSupportedException($"当前图片无法再进行压缩,文件id:{file.Id}"); } + else + { + throw new NotSupportedException($"当前图片不支持压缩,文件id:{file.Id}"); + } + } + catch (Exception exception) when (exception is NotSupportedException) + { + this.LoggerFactory.CreateLogger().LogInformation(exception, exception.Message); + } + catch (Exception exception) + { + //如果失败了,直接复制一份到缩略图上即可 + compressImageStream = fileStream; + this.LoggerFactory.CreateLogger().LogError(exception, exception.Message); + } + + + using (var stream = new FileStream(thumbnailSavePath, FileMode.CreateNew, FileAccess.ReadWrite)) + { + await compressImageStream.CopyToAsync(stream); + compressImageStream.Position = 0; } } } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Yi.Framework.Rbac.Domain.csproj b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Yi.Framework.Rbac.Domain.csproj index 799e5d95..734dc0a1 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Yi.Framework.Rbac.Domain.csproj +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Yi.Framework.Rbac.Domain.csproj @@ -16,7 +16,8 @@ - + + diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/YiFrameworkRbacDomainModule.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/YiFrameworkRbacDomainModule.cs index a5568c1e..a5a61d92 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/YiFrameworkRbacDomainModule.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/YiFrameworkRbacDomainModule.cs @@ -2,6 +2,7 @@ using Volo.Abp.AspNetCore.SignalR; using Volo.Abp.Caching; using Volo.Abp.Domain; +using Volo.Abp.Imaging; using Volo.Abp.Modularity; using Yi.Framework.Caching.FreeRedis; using Yi.Framework.Mapster; @@ -18,7 +19,8 @@ namespace Yi.Framework.Rbac.Domain typeof(AbpAspNetCoreSignalRModule), typeof(AbpDddDomainModule), - typeof(AbpCachingModule) + typeof(AbpCachingModule), + typeof(AbpImagingImageSharpModule) )] public class YiFrameworkRbacDomainModule : AbpModule {