diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageDto.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageDto.cs new file mode 100644 index 00000000..28327a89 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageDto.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Application.Dtos; + +namespace Yi.Framework.AiHub.Application.Contracts.Dtos; + +public class MessageDto : FullAuditedEntityDto +{ + public Guid UserId { get; set; } + public Guid SessionId { get; set; } + public string Content { get; set; } + public string Role { get; set; } + public decimal DeductCost { get; set; } + public decimal TotalTokens { get; set; } + public string ModelId { get; set; } + public string Remark { get; set; } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageGetListInput.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageGetListInput.cs new file mode 100644 index 00000000..89af105c --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageGetListInput.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; +using Yi.Framework.Ddd.Application.Contracts; + +namespace Yi.Framework.AiHub.Application.Contracts.Dtos; + +public class MessageGetListInput:PagedAllResultRequestDto +{ + [Required] + public Guid SessionId { get; set; } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageInputDto.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageInputDto.cs new file mode 100644 index 00000000..e0ec143a --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/MessageInputDto.cs @@ -0,0 +1,11 @@ +namespace Yi.Framework.AiHub.Application.Contracts.Dtos; + +public class MessageInputDto +{ + public string Content { get; set; } + public string Role { get; set; } + public decimal DeductCost { get; set; } + public decimal TotalTokens { get; set; } + public string ModelId { get; set; } + public string Remark { get; set; } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SendMessageInput.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SendMessageInput.cs index 91486e94..90dce103 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SendMessageInput.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SendMessageInput.cs @@ -4,6 +4,8 @@ public class SendMessageInput { public List Messages { get; set; } public string Model { get; set; } + + public Guid? SessionId{ get; set; } } public class Message diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionDto.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionDto.cs new file mode 100644 index 00000000..a4162aa0 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionDto.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Application.Dtos; + +namespace Yi.Framework.AiHub.Application.Contracts.Dtos; + +public class SessionDto : FullAuditedEntityDto +{ + public string SessionTitle { get; set; } + public string SessionContent { get; set; } + public string Remark { get; set; } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionGetListInput.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionGetListInput.cs new file mode 100644 index 00000000..c37fe840 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionGetListInput.cs @@ -0,0 +1,6 @@ +namespace Yi.Framework.AiHub.Application.Contracts.Dtos; + +public class SessionGetListInput +{ + +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionInputDto.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionInputDto.cs new file mode 100644 index 00000000..94537954 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/SessionInputDto.cs @@ -0,0 +1,9 @@ +namespace Yi.Framework.AiHub.Application.Contracts.Dtos; + +public class SessionInputDto +{ + public Guid UserId { get; set; } + public string SessionTitle { get; set; } + public string SessionContent { get; set; } + public string Remark { get; set; } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiChatService.cs similarity index 86% rename from Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiService.cs rename to Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiChatService.cs index 1ba9eb9d..cfe70772 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiService.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/AiChatService.cs @@ -6,21 +6,28 @@ using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using OpenAI.Chat; using Volo.Abp.Application.Services; +using Volo.Abp.Users; using Yi.Framework.AiHub.Application.Contracts.Dtos; using Yi.Framework.AiHub.Application.Contracts.Options; using Yi.Framework.AiHub.Domain.Managers; namespace Yi.Framework.AiHub.Application.Services; -public class AiService : ApplicationService +/// +/// ai服务 +/// +public class AiChatService : ApplicationService { private readonly AiGateWayOptions _options; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly AiMessageManager _aiMessageManager; - public AiService(IOptions options, IHttpContextAccessor httpContextAccessor) + public AiChatService(IOptions options, IHttpContextAccessor httpContextAccessor, + AiMessageManager aiMessageManager) { _options = options.Value; this._httpContextAccessor = httpContextAccessor; + _aiMessageManager = aiMessageManager; } @@ -75,7 +82,7 @@ public class AiService : ApplicationService } var gateWay = LazyServiceProvider.GetRequiredService(); - var completeChatResponse = gateWay.CompleteChatAsync(input.Model, history,cancellationToken); + var completeChatResponse = gateWay.CompleteChatAsync(input.Model, history, cancellationToken); await using var writer = new StreamWriter(response.Body, Encoding.UTF8, leaveOpen: true); await foreach (var data in completeChatResponse) { @@ -88,10 +95,24 @@ public class AiService : ApplicationService await writer.WriteLineAsync($"data: {message}\n"); await writer.FlushAsync(cancellationToken); // 确保立即推送数据 } - + //断开连接 await writer.WriteLineAsync($"data: done\n"); await writer.FlushAsync(cancellationToken); // 确保立即推送数据 + + if (CurrentUser.IsAuthenticated && input.SessionId.HasValue) + { + // 等待接入token + // await _aiMessageManager.CreateMessageAsync(CurrentUser.GetId(), input.SessionId.Value, new MessageInputDto + // { + // Content = null, + // Role = null, + // DeductCost = 0, + // TotalTokens = 0, + // ModelId = null, + // Remark = null + // }); + } } diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/MessageService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/MessageService.cs new file mode 100644 index 00000000..5efd7636 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/MessageService.cs @@ -0,0 +1,40 @@ +using Mapster; +using Microsoft.AspNetCore.Authorization; +using SqlSugar; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Users; +using Yi.Framework.AiHub.Application.Contracts.Dtos; +using Yi.Framework.AiHub.Domain.Entities; +using Yi.Framework.SqlSugarCore.Abstractions; + +namespace Yi.Framework.AiHub.Application.Services; + +public class MessageService : ApplicationService +{ + private readonly ISqlSugarRepository _repository; + + public MessageService(ISqlSugarRepository repository) + { + _repository = repository; + } + + /// + /// 查询消息 + /// 需要会话id + /// + /// + /// + [Authorize] + public async Task> GetListAsync(MessageGetListInput input) + { + RefAsync total = 0; + var userId = CurrentUser.GetId(); + var entities = await _repository._DbQueryable + .Where(x => x.SessionId == input.SessionId) + .Where(x=>x.UserId == userId) + .OrderByDescending(x => x.Id) + .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); + return new PagedResultDto(total, entities.Adapt>()); + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/SessionService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/SessionService.cs new file mode 100644 index 00000000..d83099a6 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/SessionService.cs @@ -0,0 +1,83 @@ +using Mapster; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Users; +using Yi.Framework.AiHub.Application.Contracts.Dtos; +using Yi.Framework.AiHub.Domain.Entities; +using Yi.Framework.SqlSugarCore.Abstractions; + +namespace Yi.Framework.AiHub.Application.Services; + +public class SessionService : CrudAppService +{ + private readonly ISqlSugarRepository _repository; + public readonly ISqlSugarRepository _messageRepository; + public SessionService(ISqlSugarRepository repository, ISqlSugarRepository messageRepository) : base(repository) + { + _repository = repository; + _messageRepository = messageRepository; + } + + /// + /// 创建会话 + /// + /// + /// + [Authorize] + public override async Task CreateAsync(SessionDto input) + { + var entity = await MapToEntityAsync(input); + entity.UserId = CurrentUser.GetId(); + await _repository.InsertAsync(entity); + return entity.Adapt(); + } + + /// + /// 详情会话 + /// + /// + /// + [Authorize] + public override Task GetAsync(Guid id) + { + return base.GetAsync(id); + } + + /// + /// 编辑会话 + /// + /// + /// + /// + [Authorize] + public override Task UpdateAsync(Guid id, SessionDto input) + { + return base.UpdateAsync(id, input); + } + + /// + /// 删除会话 + /// + /// + /// + [Authorize] + public override async Task DeleteAsync(Guid id) + { + await base.DeleteAsync(id); + //对应的消息一起删除 + await _messageRepository.DeleteAsync(x => x.SessionId == id); + } + + /// + /// 查询会话 + /// + /// + /// + [Authorize] + public override Task> GetListAsync(SessionGetListInput input) + { + return base.GetListAsync(input); + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/MessageAggregateRoot.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/MessageAggregateRoot.cs new file mode 100644 index 00000000..302076b4 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/MessageAggregateRoot.cs @@ -0,0 +1,31 @@ +using SqlSugar; +using Volo.Abp.Domain.Entities.Auditing; + +namespace Yi.Framework.AiHub.Domain.Entities; + +[SugarTable("Ai_Message")] +[SugarIndex($"index_{{table}}_{nameof(UserId)}", $"{nameof(UserId)}", OrderByType.Asc)] +public class MessageAggregateRoot : FullAuditedAggregateRoot +{ + public MessageAggregateRoot() + { + } + + public MessageAggregateRoot(Guid userId, Guid sessionId, string content, string role, string modelId) + { + UserId = userId; + SessionId = sessionId; + Content = content; + Role = role; + ModelId = modelId; + } + + public Guid UserId { get; set; } + public Guid SessionId { get; set; } + public string Content { get; set; } + public string Role { get; set; } + public decimal DeductCost { get; set; } + public decimal TotalTokens { get; set; } + public string ModelId { get; set; } + public string Remark { get; set; } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/SessionAggregateRoot.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/SessionAggregateRoot.cs new file mode 100644 index 00000000..daa57d21 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/SessionAggregateRoot.cs @@ -0,0 +1,14 @@ +using SqlSugar; +using Volo.Abp.Domain.Entities.Auditing; + +namespace Yi.Framework.AiHub.Domain.Entities; + +[SugarTable("Ai_Session")] +[SugarIndex($"index_{{table}}_{nameof(UserId)}",$"{nameof(UserId)}", OrderByType.Asc)] +public class SessionAggregateRoot : FullAuditedAggregateRoot +{ + public Guid UserId { get; set; } + public string SessionTitle { get; set; } + public string SessionContent { get; set; } + public string Remark { get; set; } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiMessageManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiMessageManager.cs new file mode 100644 index 00000000..67333e44 --- /dev/null +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiMessageManager.cs @@ -0,0 +1,30 @@ +using Volo.Abp.Domain.Services; +using Volo.Abp.Users; +using Yi.Framework.AiHub.Application.Contracts.Dtos; +using Yi.Framework.AiHub.Domain.Entities; +using Yi.Framework.SqlSugarCore.Abstractions; + +namespace Yi.Framework.AiHub.Domain.Managers; + +public class AiMessageManager : DomainService +{ + private readonly ISqlSugarRepository _repository; + + public AiMessageManager(ISqlSugarRepository repository) + { + _repository = repository; + } + + /// + /// 创建消息 + /// + /// + /// + /// + /// + public async Task CreateMessageAsync(Guid userId, Guid sessionId, MessageInputDto input) + { + var message = new MessageAggregateRoot(userId, sessionId, input.Content, input.Role, input.ModelId); + await _repository.InsertAsync(message); + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IAccountService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IAccountService.cs index e06151a8..1b402033 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IAccountService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IAccountService.cs @@ -10,7 +10,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.IServices Task GetAsync(); Task GetCaptchaImageAsync(); Task PostLoginAsync(LoginInputVo input); - Task PostRegisterAsync(RegisterDto input); + Task PostRegisterAsync(RegisterDto input); Task RestPasswordAsync(Guid userId, RestPasswordDto input); /// @@ -25,7 +25,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.IServices /// /// /// - Task GetAsync(string? userName,long? phone); + Task GetAsync(string? userName, long? phone); /// /// 校验电话验证码,需要与电话号码绑定 @@ -40,4 +40,4 @@ namespace Yi.Framework.Rbac.Application.Contracts.IServices /// Task PostTempRegisterAsync(RegisterDto input); } -} +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs index df84f7f8..9393a96a 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs @@ -5,11 +5,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using SqlSugar; -using Volo.Abp; using Volo.Abp.Application.Services; using Volo.Abp.Authorization; using Volo.Abp.Caching; @@ -81,8 +77,8 @@ namespace Yi.Framework.Rbac.Application.Services /// /// 校验图片登录验证码,无需和账号绑定 /// - [RemoteService(isEnabled:false)] - public void ValidationImageCaptcha(string? uuid,string? code ) + [RemoteService(isEnabled: false)] + private void ValidationImageCaptcha(string? uuid, string? code) { if (_rbacOptions.EnableCaptcha) { @@ -109,7 +105,7 @@ namespace Yi.Framework.Rbac.Application.Services } //校验验证码 - ValidationImageCaptcha(input.Uuid,input.Code); + ValidationImageCaptcha(input.Uuid, input.Code); UserAggregateRoot user = new(); //校验 @@ -174,7 +170,7 @@ namespace Yi.Framework.Rbac.Application.Services /// /// 验证电话号码 /// - /// + /// private async Task ValidationPhone(string phone) { var res = Regex.IsMatch(phone, @"^\d{11}$"); @@ -207,7 +203,7 @@ namespace Yi.Framework.Rbac.Application.Services { return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.RetrievePassword, input); } - + /// /// 手机验证码-绑定 /// @@ -219,20 +215,20 @@ namespace Yi.Framework.Rbac.Application.Services { return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.Bind, input); } - + /// /// 手机验证码-需通过图形验证码 /// /// - [RemoteService(isEnabled:false)] + [RemoteService(isEnabled: false)] private async Task PostCaptchaPhoneAsync(ValidationPhoneTypeEnum validationPhoneType, PhoneCaptchaImageDto input) { //验证uuid 和 验证码 - ValidationImageCaptcha(input.Uuid,input.Code); - + ValidationImageCaptcha(input.Uuid, input.Code); + await ValidationPhone(input.Phone); - + if (validationPhoneType == ValidationPhoneTypeEnum.Register && await _userRepository.IsAnyAsync(x => x.Phone.ToString() == input.Phone)) { @@ -310,7 +306,7 @@ namespace Yi.Framework.Rbac.Application.Services /// [AllowAnonymous] [UnitOfWork] - public async Task PostRegisterAsync(RegisterDto input) + public async Task PostRegisterAsync(RegisterDto input) { if (_rbacOptions.EnableRegister == false) { @@ -321,20 +317,22 @@ namespace Yi.Framework.Rbac.Application.Services { throw new UserFriendlyException("手机号不能为空"); } + //临时账号 if (input.UserName.StartsWith("ls_")) { throw new UserFriendlyException("注册账号不能以ls_字符开头"); } - + if (_rbacOptions.EnableCaptcha) { //校验验证码,根据电话号码获取 value,比对验证码已经uuid await ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.Register, input.Phone.Value, input.Code); } - //注册领域逻辑 - await _accountManager.RegisterAsync(input.UserName, input.Password, input.Phone, input.Nick); + //注册之后,免再次登录,直接给前端token + var userId = await _accountManager.RegisterAsync(input.UserName, input.Password, input.Phone, input.Nick); + return await this.PostLoginAsync(userId); } /// @@ -342,7 +340,7 @@ namespace Yi.Framework.Rbac.Application.Services /// 不需要验证,为了给第三方使用,例如微信小程序,后续可通过绑定操作,进行账号合并 /// /// - [RemoteService(isEnabled:false)] + [RemoteService(isEnabled: false)] public async Task PostTempRegisterAsync(RegisterDto input) { //注册领域逻辑 @@ -423,13 +421,17 @@ namespace Yi.Framework.Rbac.Application.Services { //将后端菜单转换成前端路由,组件级别需要过滤 output = - ObjectMapper.Map, List>(menus.Where(x=>x.MenuSource==MenuSourceEnum.Ruoyi).ToList()).Vue3RuoYiRouterBuild(); + ObjectMapper + .Map, List>(menus + .Where(x => x.MenuSource == MenuSourceEnum.Ruoyi).ToList()).Vue3RuoYiRouterBuild(); } else if (routerType == "pure") { //将后端菜单转换成前端路由,组件级别需要过滤 output = - ObjectMapper.Map, List>(menus.Where(x=>x.MenuSource==MenuSourceEnum.Pure).ToList()).Vue3PureRouterBuild(); + ObjectMapper + .Map, List>(menus + .Where(x => x.MenuSource == MenuSourceEnum.Pure).ToList()).Vue3PureRouterBuild(); } return output; diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs index f2b393ec..ca933563 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs @@ -272,11 +272,12 @@ namespace Yi.Framework.Rbac.Domain.Managers /// /// /// - public async Task RegisterAsync(string userName, string password, long? phone,string? nick) + public async Task RegisterAsync(string userName, string password, long? phone,string? nick) { var user = new UserAggregateRoot(userName, password, phone,nick); - await _userManager.CreateAsync(user); + var userId=await _userManager.CreateAsync(user); await _userManager.SetDefautRoleAsync(user.Id); + return userId; } } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IAccountManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IAccountManager.cs index 4e9b246f..d4b8c59d 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IAccountManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IAccountManager.cs @@ -14,7 +14,7 @@ namespace Yi.Framework.Rbac.Domain.Managers string CreateRefreshToken(Guid userId); Task GetTokenByUserIdAsync(Guid userId,Action? getUserInfo=null); Task LoginValidationAsync(string userName, string password, Action? userAction = null); - Task RegisterAsync(string userName, string password, long? phone,string? nick); + Task RegisterAsync(string userName, string password, long? phone,string? nick); Task RestPasswordAsync(Guid userId, string password); Task UpdatePasswordAsync(Guid userId, string newPassword, string oldPassword); } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/UserManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/UserManager.cs index cb057052..5bcf9ce9 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/UserManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/UserManager.cs @@ -29,9 +29,16 @@ namespace Yi.Framework.Rbac.Domain.Managers private readonly IGuidGenerator _guidGenerator; private IUserRepository _userRepository; private ILocalEventBus _localEventBus; - public UserManager(ISqlSugarRepository repository, ISqlSugarRepository repositoryUserRole, ISqlSugarRepository repositoryUserPost, IGuidGenerator guidGenerator, IDistributedCache userCache, IUserRepository userRepository, ILocalEventBus localEventBus, ISqlSugarRepository roleRepository) => - (_repository, _repositoryUserRole, _repositoryUserPost, _guidGenerator, _userCache, _userRepository, _localEventBus, _roleRepository) = - (repository, repositoryUserRole, repositoryUserPost, guidGenerator, userCache, userRepository, localEventBus, roleRepository); + + public UserManager(ISqlSugarRepository repository, + ISqlSugarRepository repositoryUserRole, + ISqlSugarRepository repositoryUserPost, IGuidGenerator guidGenerator, + IDistributedCache userCache, IUserRepository userRepository, + ILocalEventBus localEventBus, ISqlSugarRepository roleRepository) => + (_repository, _repositoryUserRole, _repositoryUserPost, _guidGenerator, _userCache, _userRepository, + _localEventBus, _roleRepository) = + (repository, repositoryUserRole, repositoryUserPost, guidGenerator, userCache, userRepository, + localEventBus, roleRepository); /// /// 给用户设置角色 @@ -56,6 +63,7 @@ namespace Yi.Framework.Rbac.Domain.Managers { userRoleEntities.Add(new UserRoleEntity() { UserId = userId, RoleId = roleId }); } + //一次性批量添加 await _repositoryUserRole.InsertRangeAsync(userRoleEntities); } @@ -88,7 +96,6 @@ namespace Yi.Framework.Rbac.Domain.Managers //一次性批量添加 await _repositoryUserPost.InsertRangeAsync(userPostEntities); } - } } @@ -96,7 +103,7 @@ namespace Yi.Framework.Rbac.Domain.Managers /// 创建用户 /// /// - public async Task CreateAsync(UserAggregateRoot userEntity) + public async Task CreateAsync(UserAggregateRoot userEntity) { //校验用户名 ValidateUserName(userEntity); @@ -111,7 +118,6 @@ namespace Yi.Framework.Rbac.Domain.Managers if (await _repository.IsAnyAsync(x => x.Phone == userEntity.Phone)) { throw new UserFriendlyException(UserConst.Phone_Repeat); - } } @@ -123,10 +129,8 @@ namespace Yi.Framework.Rbac.Domain.Managers var entity = await _repository.InsertReturnEntityAsync(userEntity); - userEntity = entity; await _localEventBus.PublishAsync(new UserCreateEventArgs(entity.Id)); - - + return entity.Id; } @@ -174,37 +178,43 @@ namespace Yi.Framework.Rbac.Domain.Managers { throw new AbpAuthorizationException(); } + //data.Menus.Clear(); // output = data; return data; // var output = await GetInfoByCacheAsync(userId); // return output; } + private async Task GetInfoByCacheAsync(Guid userId) { //此处优先从缓存中获取 UserRoleMenuDto output = null; - var tokenExpiresMinuteTime = LazyServiceProvider.GetRequiredService>().Value.ExpiresMinuteTime; + var tokenExpiresMinuteTime = + LazyServiceProvider.GetRequiredService>().Value.ExpiresMinuteTime; var cacheData = await _userCache.GetOrAddAsync(new UserInfoCacheKey(userId), - async () => - { - var user = await _userRepository.GetUserAllInfoAsync(userId); - var data = EntityMapToDto(user); - //系统用户数据被重置,老前端访问重新授权 - if (data is null) - { - throw new AbpAuthorizationException(); - } - //data.Menus.Clear(); - output = data; - return new UserInfoCacheItem(data); - }, - () => new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(tokenExpiresMinuteTime) }); + async () => + { + var user = await _userRepository.GetUserAllInfoAsync(userId); + var data = EntityMapToDto(user); + //系统用户数据被重置,老前端访问重新授权 + if (data is null) + { + throw new AbpAuthorizationException(); + } + + //data.Menus.Clear(); + output = data; + return new UserInfoCacheItem(data); + }, + () => new DistributedCacheEntryOptions + { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(tokenExpiresMinuteTime) }); if (cacheData is not null) { output = cacheData.Info; } + return output!; } @@ -221,14 +231,13 @@ namespace Yi.Framework.Rbac.Domain.Managers { output.Add(await GetInfoByCacheAsync(userId)); } + return output; } - private UserRoleMenuDto EntityMapToDto(UserAggregateRoot user) { - var userRoleMenu = new UserRoleMenuDto(); //首先获取到该用户全部信息,导航到角色、菜单,(菜单需要去重,完全交给Set来处理即可) if (user is null) @@ -236,6 +245,7 @@ namespace Yi.Framework.Rbac.Domain.Managers //为了解决token前端缓存,后端数据库重新dbseed throw new UserFriendlyException($"数据错误,查询用户不存在,请重新登录"); } + user.EncryPassword.Password = string.Empty; user.EncryPassword.Salt = string.Empty; @@ -264,6 +274,7 @@ namespace Yi.Framework.Rbac.Domain.Managers { userRoleMenu.PermissionCodes.Add(menu.PermissionCode); } + userRoleMenu.Menus.Add(menu.Adapt()); } } @@ -279,5 +290,4 @@ namespace Yi.Framework.Rbac.Domain.Managers return userRoleMenu; } } - } \ No newline at end of file