diff --git a/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantDbContext.cs b/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantDbContext.cs index 9530f30..e2ac17e 100644 --- a/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantDbContext.cs +++ b/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantDbContext.cs @@ -54,5 +54,27 @@ namespace HuanMeng.DotNetCore.MultiTenant { this.TenantInfo = tenantInfo; } + + public override int SaveChanges() + { + if (TenantInfo?.TenantId != null) + { + var entries = ChangeTracker.Entries() + .Where(e => e.Entity is IMultiTenantEntity && + (e.State == EntityState.Added || e.State == EntityState.Modified)) + .Select(e => e.Entity as IMultiTenantEntity) + .ToList(); + + foreach (var entity in entries) + { + if (entity?.TenantId == null) + { + entity.TenantId = TenantInfo.TenantId; + } + } + } + return base.SaveChanges(); + } + } } diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs b/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs index acd94fd..52d8826 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs @@ -278,4 +278,31 @@ namespace HuanMeng.MiaoYu.Code.Base } #endregion } + + /// + /// 默认控制器类,日志实现 + /// + /// + public class MiaoYuBase : MiaoYuBase where T : class + { + public MiaoYuBase(IServiceProvider serviceProvider) : base(serviceProvider) + { + + } + #region 日志 + private Logger? _logger; + public Logger _Logger + { + + get + { + if (_logger == null) + { + _logger = _serviceProvider.GetRequiredService>(); + } + return _logger; + } + } + #endregion + } } diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Cache/MiaoYuCache.cs b/src/0-core/HuanMeng.MiaoYu.Code/Cache/MiaoYuCache.cs index 9560e76..52d5698 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Cache/MiaoYuCache.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Cache/MiaoYuCache.cs @@ -26,7 +26,7 @@ namespace HuanMeng.MiaoYu.Code.Cache /// /// 角色数据表 /// - public List CharactersList + public List CharacterInfoList { get { @@ -81,7 +81,7 @@ namespace HuanMeng.MiaoYu.Code.Cache { if (CharacterCache == null) { - + CharacterCache = new CharacterEntityCache(dao, mapper); } return CharacterCache.DataList ?? new List(); @@ -115,5 +115,60 @@ namespace HuanMeng.MiaoYu.Code.Cache } #endregion + + + #region 角色类型缓存表 + /// + ///角色类型缓存表 + /// + private static object CharacterTypeLock = new object(); + + /// + /// 角色类型缓存表 + /// + public MiaoYuDataEntityCache? CharacterTypeCache { get; set; } + /// + /// 角色类型 + /// + public List CharacterTypeList + { + get + { + if (CharacterTypeCache == null) + { + CharacterTypeCache = new MiaoYuDataEntityCache(dao, CharacterTypeLock); + } + return CharacterTypeCache.DataList ?? new List(); + } + } + + #endregion + + #region 角色类型缓存表 + /// + /// 类型中的角色缓存表 + /// + private static object CharacterTypeIntimacyLock = new object(); + + /// + /// 类型中的角色缓存表 + /// + public MiaoYuDataEntityCache? CharacterTypeIntimacyCache { get; set; } + /// + /// 类型中的角色 + /// + public List CharacterTypeIntimacyList + { + get + { + if (CharacterTypeIntimacyCache == null) + { + CharacterTypeIntimacyCache = new MiaoYuDataEntityCache(dao, CharacterTypeIntimacyLock); + } + return CharacterTypeIntimacyCache.DataList ?? new List(); + } + } + + #endregion } } diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Cache/Special/CharacterEntityCache.cs b/src/0-core/HuanMeng.MiaoYu.Code/Cache/Special/CharacterEntityCache.cs index ee7b1eb..8956385 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Cache/Special/CharacterEntityCache.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Cache/Special/CharacterEntityCache.cs @@ -52,7 +52,6 @@ namespace HuanMeng.MiaoYu.Code.Cache.Special var labels = labelCache.DataList; var labelRelationCache = new MiaoYuDataEntityCache(_dao, T_Character_Label_RelationLock); var labelRelations = labelRelationCache.DataList; - foreach (var characterCache in characterCaches) { var modelConfig = modelConfigs.FirstOrDefault(it => it.Id == characterCache.ModelConfigId); diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Category/CategoryBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Category/CategoryBLL.cs new file mode 100644 index 0000000..31cfba9 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Code/Category/CategoryBLL.cs @@ -0,0 +1,61 @@ +using HuanMeng.DotNetCore.Base; +using HuanMeng.MiaoYu.Model.Dto.Category; +using HuanMeng.MiaoYu.Model.Dto.Character; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Code.Category +{ + /// + /// 类别 + /// + public class CategoryBLL : MiaoYuBase + { + public CategoryBLL(IServiceProvider serviceProvider) : base(serviceProvider) + { + } + + /// + /// 获取类型集合 + /// + /// + public BaseResponse> GetCategoryList() + { + var list = MiaoYuCache.CharacterTypeList.Where(it => !it.IsNotCategoryShow).OrderBy(it => it.OrderBy).ToList(); + var rList = Mapper.Map>(list); + rList.Insert(0, new CategoryInfo + { + Id = 0, + Name = "发现" + }); + //Dao.daoDbMiaoYu.context.T_Character_Type.Where() + return new BaseResponse>(ResonseCode.Success, "", rList) { }; + } + + + /// + /// 获取类型中的角色信息 + /// + /// + public BaseResponse> GetCategoryInfoList(int CategoryId) + { + var list = MiaoYuCache.CharacterTypeIntimacyList.Where(it => it.TypeId == CategoryId).OrderBy(it => it.OrderBy).ToList(); + var list2 = MiaoYuCache.CharacterList; + var rList = new List(); + list.ForEach(it => + { + var model = list2.FirstOrDefault(item => item.Id == it.CharacterId); + if (model != null) + { + var su = Mapper.Map(model); + rList.Add(su); + } + }); + return new BaseResponse>(ResonseCode.Success, "", rList) { }; + } + } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs index 57f5bcd..bb5d3d4 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs @@ -237,8 +237,6 @@ namespace HuanMeng.MiaoYu.Code.Chat var response = await chat.MessagesAsync(baseChatParams); var claudeChatResponse = response as ClaudeChatResponse; #endregion - - T_Chat t_Chat = new T_Chat { CharacterId = charact.Id, @@ -261,6 +259,7 @@ namespace HuanMeng.MiaoYu.Code.Chat }; Dao.daoDbMiaoYu.context.Add(t_Chat1); Dao.daoDbMiaoYu.context.Add(t_Chat); + userChatSession.UpdateAt = DateTime.Now; await Dao.daoDbMiaoYu.context.SaveChangesAsync(); //claudeChatResponse. ChatMessageDto chatMessageDto = new ChatMessageDto() @@ -278,6 +277,7 @@ namespace HuanMeng.MiaoYu.Code.Chat chatListDto.RemainingChatCount = 999; return new BaseResponse(ResonseCode.Success, "", chatListDto); } + /// /// 删除聊天记录 /// @@ -315,5 +315,29 @@ namespace HuanMeng.MiaoYu.Code.Chat Dao.daoDbMiaoYu.context.SaveChanges(); return true; } + + /// + /// 获取消息聊天记录列表 + /// + /// + public async Task>> GetChatHistoryList() + { + var userChatSessions = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.UserId == _UserId && !it.IsDelete).ToListAsync(); + List chatHistoryInfos = new List(); + var charactersIds = MiaoYuCache.CharacterList.ToList(); + userChatSessions.ForEach(it => + { + var model = charactersIds.FirstOrDefault(item => item.Id == it.CharacterId); + if (model != null) + { + var info = Mapper.Map(model); + info.LastContactTime = it.UpdateAt; + chatHistoryInfos.Add(info); + } + + }); + chatHistoryInfos = chatHistoryInfos.OrderByDescending(it => it.LastContactTime).ToList(); + return new BaseResponse>(ResonseCode.Success, "", chatHistoryInfos) { }; + } } } diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs index 68b3107..d8a537d 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs @@ -58,6 +58,11 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext /// public virtual DbSet T_Character_Type { get; set; } + /// + /// 角色和角色类型关联表 + /// + public virtual DbSet T_Character_Type_Intimacy { get; set; } + /// /// 存储用户和角色之间的亲密值 /// @@ -203,9 +208,11 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext entity.Property(e => e.CreateTime) .HasComment("创建时间") .HasColumnType("datetime"); + entity.Property(e => e.IsNotCategoryShow).HasComment("分类页不显示"); entity.Property(e => e.Name) .HasMaxLength(255) .HasComment("类型名称"); + entity.Property(e => e.OrderBy).HasComment("序号"); entity.Property(e => e.TenantId).HasComment("租户id"); entity.Property(e => e.UpdateTime) .HasComment("更新时间") @@ -217,6 +224,30 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext } }); + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__T_Charac__3214EC077745C163"); + + entity.ToTable(tb => tb.HasComment("角色和角色类型关联表")); + + entity.Property(e => e.Id).HasComment("主键"); + entity.Property(e => e.CharacterId).HasComment("角色Id"); + entity.Property(e => e.CreateTime) + .HasComment("创建时间") + .HasColumnType("datetime"); + entity.Property(e => e.OrderBy).HasComment("类别表排序"); + entity.Property(e => e.TenantId).HasComment("租户"); + entity.Property(e => e.TypeId).HasComment("列表Id"); + entity.Property(e => e.UpdateTIme) + .HasComment("修改时间") + .HasColumnType("datetime"); + //添加全局筛选器 + if (this.TenantInfo != null) + { + entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId); + } + }); + modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("PK__T_Charac__3214EC079BEEBDEA"); diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character.cs index 35313c9..1adee90 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character_Type.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character_Type.cs index 13fb246..b5669f8 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character_Type.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character_Type.cs @@ -27,4 +27,14 @@ public partial class T_Character_Type: MultiTenantEntity /// public DateTime UpdateTime { get; set; } + + /// + /// 分类页不显示 + /// + public bool IsNotCategoryShow { get; set; } + + /// + /// 序号 + /// + public int OrderBy { get; set; } } diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character_Type_Intimacy.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character_Type_Intimacy.cs new file mode 100644 index 0000000..e899cff --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_Character_Type_Intimacy.cs @@ -0,0 +1,40 @@ +using System; + +namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; + +/// +/// 角色和角色类型关联表 +/// +public partial class T_Character_Type_Intimacy: MultiTenantEntity +{ + /// + /// 主键 + /// + public int Id { get; set; } + + + /// + /// 列表Id + /// + public int TypeId { get; set; } + + /// + /// 角色Id + /// + public int CharacterId { get; set; } + + /// + /// 修改时间 + /// + public DateTime UpdateTIme { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + + /// + /// 类别表排序 + /// + public int OrderBy { get; set; } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Category/CategoryInfo.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Category/CategoryInfo.cs new file mode 100644 index 0000000..99aaf1d --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Category/CategoryInfo.cs @@ -0,0 +1,29 @@ +using AutoMapper; + +using HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Model.Dto.Category +{ + /// + /// 分类 + /// + [AutoMap(typeof(T_Character_Type))] + public class CategoryInfo + { + /// + /// 类型id + /// + public int Id { get; set; } + + /// + /// 类型名称 + /// + public string Name { get; set; } + } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Character/CharacterCache.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Character/CharacterCache.cs index 93c7b88..36446ea 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Character/CharacterCache.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Character/CharacterCache.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; namespace HuanMeng.MiaoYu.Model.Dto.Character { /// - /// 模型 + /// 模型 /// [AutoMap(typeof(T_Character))] public class CharacterCache : T_Character diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Character/CharacterSummary.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Character/CharacterSummary.cs new file mode 100644 index 0000000..f1f7346 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Character/CharacterSummary.cs @@ -0,0 +1,52 @@ +using AutoMapper; + +using HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; +using HuanMeng.MiaoYu.Model.Dto.Label; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Model.Dto.Character +{ + [AutoMap(typeof(CharacterCache))] + public class CharacterSummary + { + + /// + /// 人物id + /// + public int Id { get; set; } + + /// + /// 人物名字 + /// + public string? Name { get; set; } + + /// + /// 人物简介 + /// + public string? Biography { get; set; } + /// + /// 多少人聊天过 + /// + public int LookCount { get; set; } + + /// + /// 背景图片 + /// + public string BgImage { get; set; } + + /// + /// 用户头像url + /// + public string IconImage { get; set; } + + /// + /// 标签 + /// + public List Label { get; set; } + } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs index be7fdc4..be6b663 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs @@ -17,7 +17,7 @@ namespace HuanMeng.MiaoYu.Model.Dto.Chat public List CharacterInfos { get; set; } } /// - /// 用户和人物信息 + /// 用户和人物信息 /// [AutoMap(typeof(CharacterCache))] public class CharacterInfoDto diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatHistoryInfo.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatHistoryInfo.cs new file mode 100644 index 0000000..eeef91f --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatHistoryInfo.cs @@ -0,0 +1,45 @@ +using AutoMapper; + +using HuanMeng.MiaoYu.Model.Dto.Character; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Model.Dto.Chat +{ + /// + /// 聊天历史 + /// + [AutoMap(typeof(CharacterCache))] + public class ChatHistoryInfo + { + /// + /// 人物id + /// + public int Id { get; set; } + + /// + /// 人物名字 + /// + public string? Name { get; set; } + + /// + /// 人物简介 + /// + public string? Biography { get; set; } + + /// + /// 用户头像url + /// + public string IconImage { get; set; } + + /// + /// 最后一次联系时间 + /// + public DateTime? LastContactTime { get; set; } + + } +} diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/AccountController.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/AccountController.cs index 999901d..a888601 100644 --- a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/AccountController.cs +++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/AccountController.cs @@ -19,7 +19,7 @@ using System.Text.RegularExpressions; namespace HuanMeng.MiaoYu.WebApi.Controllers { /// - /// 账号控制器 + /// 账号控制器 /// [Route("api/[controller]/[action]")] [ApiController] diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/CategoryController.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/CategoryController.cs new file mode 100644 index 0000000..ee0a2b2 --- /dev/null +++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/CategoryController.cs @@ -0,0 +1,48 @@ +using HuanMeng.DotNetCore.Base; +using HuanMeng.MiaoYu.Code.Cache; +using HuanMeng.MiaoYu.Code.Category; +using HuanMeng.MiaoYu.Model.Dto.Category; +using HuanMeng.MiaoYu.Model.Dto.Character; +using HuanMeng.MiaoYu.WebApi.Base; + +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace HuanMeng.MiaoYu.WebApi.Controllers +{ + /// + /// 分类页面控制器 + /// + [Route("api/[controller]/[action]")] + [ApiController] + public class CategoryController : MiaoYuControllerBase + { + public CategoryController(IServiceProvider _serviceProvider) : base(_serviceProvider) + { + } + + /// + /// 获取分类列表 + /// + /// + [HttpGet] + [AllowAnonymous] + public BaseResponse> GetCategoryList() + { + CategoryBLL categoryBLL = new CategoryBLL(ServiceProvider); + return categoryBLL.GetCategoryList(); + } + + /// + /// 获取类型中的角色信息 + /// + /// + [HttpGet] + [AllowAnonymous] + public BaseResponse> GetCategoryInfoList(int CategoryId) + { + CategoryBLL categoryBLL = new CategoryBLL(ServiceProvider); + return categoryBLL.GetCategoryInfoList(CategoryId); + } + } +} diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/ChatController.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/ChatController.cs index 33e2bb7..e245b48 100644 --- a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/ChatController.cs +++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/ChatController.cs @@ -1,4 +1,5 @@ using HuanMeng.DotNetCore.Base; +using HuanMeng.MiaoYu.Code.Cache; using HuanMeng.MiaoYu.Code.Character; using HuanMeng.MiaoYu.Code.Chat; using HuanMeng.MiaoYu.Model.Dto.Character; @@ -70,7 +71,7 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers [AllowAnonymous] public async Task>> GetChatInfo(int characterId) { - + ChatBLL chatBLL = new ChatBLL(ServiceProvider); var list = await chatBLL.GetChatMessage(characterId); @@ -121,5 +122,17 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers var obj = await _chatBLL.DelChat(delChatList.CharacterId); return new BaseResponse(ResonseCode.Success, "", obj); } + + + /// + /// 获取消息页面的聊天记录列表 + /// + /// + [HttpGet] + public async Task>> GetChatHistoryList() + { + var obj = await _chatBLL.GetChatHistoryList(); + return obj; + } } } diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs index b680f30..60d1fcb 100644 --- a/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs +++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs @@ -129,6 +129,8 @@ app.UseAuthorization(); //使用跨域 app.UseCors(_myAllowSpecificOrigins); app.MapControllers(); + +app.UseStaticFiles();//静态文件访问配置 //数据库中间件 app.UseMultiTenantMiaoYu(); //异常中间件