diff --git a/backend/IMTest/bin/Debug/net8.0/IMTest.dll b/backend/IMTest/bin/Debug/net8.0/IMTest.dll index 4c5461c..a4a7827 100644 Binary files a/backend/IMTest/bin/Debug/net8.0/IMTest.dll and b/backend/IMTest/bin/Debug/net8.0/IMTest.dll differ diff --git a/backend/IMTest/bin/Debug/net8.0/IMTest.pdb b/backend/IMTest/bin/Debug/net8.0/IMTest.pdb index a90a420..d7f873d 100644 Binary files a/backend/IMTest/bin/Debug/net8.0/IMTest.pdb and b/backend/IMTest/bin/Debug/net8.0/IMTest.pdb differ diff --git a/backend/IMTest/bin/Debug/net8.0/IM_API.dll b/backend/IMTest/bin/Debug/net8.0/IM_API.dll index 16a00ed..562d8b5 100644 Binary files a/backend/IMTest/bin/Debug/net8.0/IM_API.dll and b/backend/IMTest/bin/Debug/net8.0/IM_API.dll differ diff --git a/backend/IMTest/bin/Debug/net8.0/IM_API.exe b/backend/IMTest/bin/Debug/net8.0/IM_API.exe index fd67847..1292e00 100644 Binary files a/backend/IMTest/bin/Debug/net8.0/IM_API.exe and b/backend/IMTest/bin/Debug/net8.0/IM_API.exe differ diff --git a/backend/IMTest/bin/Debug/net8.0/IM_API.pdb b/backend/IMTest/bin/Debug/net8.0/IM_API.pdb index 6fb8b01..632c921 100644 Binary files a/backend/IMTest/bin/Debug/net8.0/IM_API.pdb and b/backend/IMTest/bin/Debug/net8.0/IM_API.pdb differ diff --git a/backend/IMTest/obj/Debug/net8.0/IMTest.AssemblyInfo.cs b/backend/IMTest/obj/Debug/net8.0/IMTest.AssemblyInfo.cs index ff595c8..1a591d3 100644 --- a/backend/IMTest/obj/Debug/net8.0/IMTest.AssemblyInfo.cs +++ b/backend/IMTest/obj/Debug/net8.0/IMTest.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("IMTest")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5274f0d22d4fe646d03a3bc0ea6621d299074816")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d855c8f8fb8edc48b6c55f08ee2ebf74415cc5ea")] [assembly: System.Reflection.AssemblyProductAttribute("IMTest")] [assembly: System.Reflection.AssemblyTitleAttribute("IMTest")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/backend/IMTest/obj/Debug/net8.0/IMTest.AssemblyInfoInputs.cache b/backend/IMTest/obj/Debug/net8.0/IMTest.AssemblyInfoInputs.cache index 815557e..4506613 100644 --- a/backend/IMTest/obj/Debug/net8.0/IMTest.AssemblyInfoInputs.cache +++ b/backend/IMTest/obj/Debug/net8.0/IMTest.AssemblyInfoInputs.cache @@ -1 +1 @@ -7390b702e3c578dad3a8fa4fa4cc93b25ccd34a9b353beca60372a7182717d73 +0e2c3a5367325662a3e7db912bec1cd772d661d101def6cb95abbceb77be09ff diff --git a/backend/IMTest/obj/Debug/net8.0/IMTest.csproj.AssemblyReference.cache b/backend/IMTest/obj/Debug/net8.0/IMTest.csproj.AssemblyReference.cache index a6386cf..033c9f3 100644 Binary files a/backend/IMTest/obj/Debug/net8.0/IMTest.csproj.AssemblyReference.cache and b/backend/IMTest/obj/Debug/net8.0/IMTest.csproj.AssemblyReference.cache differ diff --git a/backend/IMTest/obj/Debug/net8.0/IMTest.dll b/backend/IMTest/obj/Debug/net8.0/IMTest.dll index 4c5461c..a4a7827 100644 Binary files a/backend/IMTest/obj/Debug/net8.0/IMTest.dll and b/backend/IMTest/obj/Debug/net8.0/IMTest.dll differ diff --git a/backend/IMTest/obj/Debug/net8.0/IMTest.pdb b/backend/IMTest/obj/Debug/net8.0/IMTest.pdb index a90a420..d7f873d 100644 Binary files a/backend/IMTest/obj/Debug/net8.0/IMTest.pdb and b/backend/IMTest/obj/Debug/net8.0/IMTest.pdb differ diff --git a/backend/IMTest/obj/Debug/net8.0/ref/IMTest.dll b/backend/IMTest/obj/Debug/net8.0/ref/IMTest.dll index 5f6f5ea..79b0187 100644 Binary files a/backend/IMTest/obj/Debug/net8.0/ref/IMTest.dll and b/backend/IMTest/obj/Debug/net8.0/ref/IMTest.dll differ diff --git a/backend/IMTest/obj/Debug/net8.0/refint/IMTest.dll b/backend/IMTest/obj/Debug/net8.0/refint/IMTest.dll index 5f6f5ea..79b0187 100644 Binary files a/backend/IMTest/obj/Debug/net8.0/refint/IMTest.dll and b/backend/IMTest/obj/Debug/net8.0/refint/IMTest.dll differ diff --git a/backend/IM_API/Configs/MapperConfig.cs b/backend/IM_API/Configs/MapperConfig.cs index 01d9263..3d863f2 100644 --- a/backend/IM_API/Configs/MapperConfig.cs +++ b/backend/IM_API/Configs/MapperConfig.cs @@ -54,6 +54,7 @@ namespace IM_API.Configs .ForMember(dest => dest.ReceiverId, opt => opt.MapFrom(src => src.Recipient)) .ForMember(dest => dest.Content, opt => opt.MapFrom(src => src.Content)) .ForMember(dest => dest.TimeStamp, opt => opt.MapFrom(src => src.Created)) + .ForMember(dest => dest.GroupMemberId , opt => opt.MapFrom(src => src.GroupMemberId)) ; CreateMap() .ForMember(dest => dest.Sender, opt => opt.MapFrom(src => src.SenderId)) @@ -64,6 +65,7 @@ namespace IM_API.Configs .ForMember(dest => dest.Recipient, opt => opt.MapFrom(src => src.ReceiverId)) .ForMember(dest => dest.StreamKey, opt => opt.Ignore() ) .ForMember(dest => dest.StateEnum, opt => opt.MapFrom(src => MessageState.Sent)) + .ForMember(dest => dest.GroupMemberId, opt => opt.MapFrom(src => src.GroupMemberId)) .ForMember(dest => dest.ChatType, opt => opt.Ignore()) .ForMember(dest => dest.MsgType, opt => opt.Ignore()) ; @@ -102,6 +104,27 @@ namespace IM_API.Configs .ForMember(dest => dest.LastMessageTime, opt => opt.MapFrom(src => DateTime.Now)) ; + //创建会话对象 + CreateMap() + .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id)) + .ForMember(dest => dest.LastMessage, opt => opt.MapFrom(src => src.LastMessage)) + .ForMember(dest => dest.LastReadMessage, opt => opt.MapFrom(src => src.LastReadMessage)) + .ForMember(dest => dest.LastReadMessageId, opt => opt.MapFrom(src => src.LastReadMessageId)) + .ForMember(dest => dest.ChatType, opt => opt.MapFrom(src => src.ChatType)) + .ForMember(dest => dest.DateTime, opt => opt.MapFrom(src => src.LastMessageTime)) + .ForMember(dest => dest.TargetId, opt => opt.MapFrom(src => src.TargetId)) + .ForMember(dest => dest.UnreadCount, opt => opt.MapFrom(src => src.UnreadCount)) + .ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.UserId)); + + CreateMap() + .ForMember(dest => dest.TargetAvatar, opt => opt.MapFrom(src => src.Avatar)) + .ForMember(dest => dest.TargetName, opt => opt.MapFrom(src => src.RemarkName)); + + CreateMap() + .ForMember(dest => dest.TargetAvatar, opt => opt.MapFrom(src => src.Avatar)) + .ForMember(dest => dest.TargetName, opt => opt.MapFrom(src => src.Name)); + + } } } diff --git a/backend/IM_API/Controllers/ConversationController.cs b/backend/IM_API/Controllers/ConversationController.cs index bca8f94..61c98fd 100644 --- a/backend/IM_API/Controllers/ConversationController.cs +++ b/backend/IM_API/Controllers/ConversationController.cs @@ -28,6 +28,14 @@ namespace IM_API.Controllers var res = new BaseResponse>(list); return Ok(res); } + [HttpGet] + public async Task Get([FromQuery]int conversationId) + { + var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier); + var conversation = await _conversationSerivice.GetConversationByIdAsync(int.Parse(userIdStr), conversationId); + var res = new BaseResponse(conversation); + return Ok(res); + } [HttpPost] public async Task Clear() { diff --git a/backend/IM_API/Controllers/MessageController.cs b/backend/IM_API/Controllers/MessageController.cs index bb12e65..bfc40b6 100644 --- a/backend/IM_API/Controllers/MessageController.cs +++ b/backend/IM_API/Controllers/MessageController.cs @@ -3,6 +3,7 @@ using IM_API.Interface.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using System.ComponentModel.DataAnnotations; using System.Security.Claims; namespace IM_API.Controllers @@ -33,5 +34,13 @@ namespace IM_API.Controllers await _messageService.SendGroupMessageAsync(int.Parse(userIdstr), dto.ReceiverId, dto); return Ok(new BaseResponse()); } + [HttpGet] + public async Task GetMessageList([Required]int conversationId, int? msgId, int? pageSize) + { + var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier); + var msgList = await _messageService.GetMessagesAsync(int.Parse(userIdStr), conversationId, msgId, pageSize, false); + var res = new BaseResponse>(msgList); + return Ok(res); + } } } diff --git a/backend/IM_API/Dtos/ConversationDto.cs b/backend/IM_API/Dtos/ConversationDto.cs index 6d7842f..585bde6 100644 --- a/backend/IM_API/Dtos/ConversationDto.cs +++ b/backend/IM_API/Dtos/ConversationDto.cs @@ -46,6 +46,6 @@ namespace IM_API.Dtos /// 对方头像 /// public string? TargetAvatar { get; set; } - public virtual Message? LastReadMessage { get; set; } + public MessageBaseDto? LastReadMessage { get; set; } } } diff --git a/backend/IM_API/Dtos/MessageDto.cs b/backend/IM_API/Dtos/MessageDto.cs index 5953a7c..c7bcac6 100644 --- a/backend/IM_API/Dtos/MessageDto.cs +++ b/backend/IM_API/Dtos/MessageDto.cs @@ -1,5 +1,16 @@ namespace IM_API.Dtos { - public record MessageBaseDto( - string Type,string ChatType, string? MsgId,int SenderId,int ReceiverId,string Content,DateTime TimeStamp); + public record MessageBaseDto + { + // 使用 { get; init; } 确保对象创建后不可修改,且支持无参构造 + public string Type { get; init; } = default!; + public string ChatType { get; init; } = default!; + public string? MsgId { get; init; } + public int SenderId { get; init; } + public int ReceiverId { get; init; } + public int? GroupMemberId { get; init; } + public string Content { get; init; } = default!; + public DateTime TimeStamp { get; init; } + public MessageBaseDto() { } + } } diff --git a/backend/IM_API/Interface/Services/IConversationService.cs b/backend/IM_API/Interface/Services/IConversationService.cs index 10fb99d..228bbcb 100644 --- a/backend/IM_API/Interface/Services/IConversationService.cs +++ b/backend/IM_API/Interface/Services/IConversationService.cs @@ -29,5 +29,11 @@ namespace IM_API.Interface.Services /// /// Task> GetUserAllStreamKeyAsync(int userId); + /// + /// 获取单个conversation信息 + /// + /// + /// + Task GetConversationByIdAsync(int userId, int conversationId); } } diff --git a/backend/IM_API/Interface/Services/IMessageSevice.cs b/backend/IM_API/Interface/Services/IMessageSevice.cs index b42eed9..c49a949 100644 --- a/backend/IM_API/Interface/Services/IMessageSevice.cs +++ b/backend/IM_API/Interface/Services/IMessageSevice.cs @@ -21,24 +21,14 @@ namespace IM_API.Interface.Services /// Task SendGroupMessageAsync(int senderId,int groupId,MessageBaseDto dto); /// - /// 获取私聊消息列表 + /// 获取消息列表 /// - /// - /// - /// - /// + /// 会话id(用于获取指定用户间聊天消息) + /// 消息id + /// 获取消息数量 /// /// - Task> GetPrivateMessagesAsync(int userAId,int userBId,int page,int pageSize,bool desc); - /// - /// 获取群聊消息列表 - /// - /// - /// - /// - /// - /// - Task> GetGroupMessagesAsync(int groupId, int page, int pageSize, bool desc); + Task> GetMessagesAsync(int userId, int conversationId,int? msgId,int? pageSize,bool desc); /// /// 获取未读消息数 /// diff --git a/backend/IM_API/Models/ImContext.cs b/backend/IM_API/Models/ImContext.cs index 6d796cd..eac2179 100644 --- a/backend/IM_API/Models/ImContext.cs +++ b/backend/IM_API/Models/ImContext.cs @@ -1,16 +1,11 @@ using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore; -using Pomelo.EntityFrameworkCore.MySql.Scaffolding.Internal; namespace IM_API.Models; public partial class ImContext : DbContext { - public ImContext() - { - } - public ImContext(DbContextOptions options) : base(options) { @@ -50,10 +45,6 @@ public partial class ImContext : DbContext public virtual DbSet Users { get; set; } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) -#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263. - => optionsBuilder.UseMySql("server=frp-era.com;port=26582;database=IM;user=product;password=12345678", Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.44-mysql")); - protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder @@ -547,6 +538,9 @@ public partial class ImContext : DbContext entity.Property(e => e.Created) .HasComment("发送时间 ") .HasColumnType("datetime"); + entity.Property(e => e.GroupMemberId) + .HasComment("若为群消息则表示具体的成员id") + .HasColumnType("int(11)"); entity.Property(e => e.MsgType) .HasComment("消息类型\r\n(0:文本,1:图片,2:语音,3:视频,4:文件,5:语音聊天,6:视频聊天)") .HasColumnType("tinyint(4)"); diff --git a/backend/IM_API/Models/ImDbContext.cs b/backend/IM_API/Models/ImDbContext.cs deleted file mode 100644 index 67a195e..0000000 --- a/backend/IM_API/Models/ImDbContext.cs +++ /dev/null @@ -1,732 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore; -using Pomelo.EntityFrameworkCore.MySql.Scaffolding.Internal; - -namespace IM_API.Models; - -public partial class ImDbContext : DbContext -{ - public ImDbContext() - { - } - - public ImDbContext(DbContextOptions options) - : base(options) - { - } - - public virtual DbSet Admins { get; set; } - - public virtual DbSet Conversations { get; set; } - - public virtual DbSet Devices { get; set; } - - public virtual DbSet Files { get; set; } - - public virtual DbSet Friends { get; set; } - - public virtual DbSet FriendRequests { get; set; } - - public virtual DbSet Groups { get; set; } - - public virtual DbSet GroupInvites { get; set; } - - public virtual DbSet GroupMembers { get; set; } - - public virtual DbSet GroupRequests { get; set; } - - public virtual DbSet LoginLogs { get; set; } - - public virtual DbSet Messages { get; set; } - - public virtual DbSet Notifications { get; set; } - - public virtual DbSet Permissions { get; set; } - - public virtual DbSet Permissionaroles { get; set; } - - public virtual DbSet Roles { get; set; } - - public virtual DbSet Users { get; set; } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) -#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263. - => optionsBuilder.UseMySql("server=frp-era.com;port=26582;database=IM;user=product;password=12345678", Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.44-mysql")); - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .UseCollation("latin1_swedish_ci") - .HasCharSet("latin1"); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("admins") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.RoleId, "RoleId"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Created) - .HasComment("创建时间 ") - .HasColumnType("datetime"); - entity.Property(e => e.Password) - .HasMaxLength(50) - .HasComment("密码"); - entity.Property(e => e.RoleId) - .HasComment("角色") - .HasColumnType("int(11)"); - entity.Property(e => e.State) - .HasComment("状态(0:正常,2:封禁) ") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.Updated) - .HasComment("更新时间 ") - .HasColumnType("datetime"); - entity.Property(e => e.Username) - .HasMaxLength(50) - .HasComment("用户名"); - - entity.HasOne(d => d.Role).WithMany(p => p.Admins) - .HasForeignKey(d => d.RoleId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("admins_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("conversations") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.UserId, "Userid"); - - entity.HasIndex(e => e.LastReadMessageId, "lastReadMessageId"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.ChatType).HasColumnType("int(11)"); - entity.Property(e => e.LastReadMessageId) - .HasComment("最后一条已读消息ID ") - .HasColumnType("int(11)") - .HasColumnName("lastMessageId"); - entity.Property(e => e.StreamKey) - .HasMaxLength(255) - .HasComment("消息推送唯一标识符"); - entity.Property(e => e.TargetId) - .HasComment("对方ID(群聊为群聊ID,单聊为单聊ID) ") - .HasColumnType("int(11)"); - entity.Property(e => e.UnreadCount) - .HasComment("未读消息数 ") - .HasColumnType("int(11)"); - entity.Property(e => e.UserId) - .HasComment("用户") - .HasColumnType("int(11)"); - - entity.HasOne(d => d.User).WithMany(p => p.Conversations) - .HasForeignKey(d => d.UserId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("conversations_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("devices") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.UserId, "Userid"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Dtype) - .HasComment("设备类型(\r\n0:Android,1:Ios,2:PC,3:Pad,4:未知)") - .HasColumnType("tinyint(4)") - .HasColumnName("DType"); - entity.Property(e => e.LastLogin) - .HasComment("最后一次登录 ") - .HasColumnType("datetime"); - entity.Property(e => e.UserId) - .HasComment("设备所属用户 ") - .HasColumnType("int(11)"); - - entity.HasOne(d => d.User).WithMany(p => p.Devices) - .HasForeignKey(d => d.UserId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("devices_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("files") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.MessageId, "Messageld"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Created) - .HasComment("创建时间 ") - .HasColumnType("datetime"); - entity.Property(e => e.MessageId) - .HasComment("关联消息ID ") - .HasColumnType("int(11)"); - entity.Property(e => e.Name) - .HasMaxLength(50) - .HasComment("文件名 "); - entity.Property(e => e.Size) - .HasComment("文件大小(单位:KB) ") - .HasColumnType("int(11)"); - entity.Property(e => e.Type) - .HasMaxLength(10) - .HasComment("文件类型 "); - entity.Property(e => e.Url) - .HasMaxLength(100) - .HasComment("文件储存URL ") - .HasColumnName("URL"); - - entity.HasOne(d => d.Message).WithMany(p => p.Files) - .HasForeignKey(d => d.MessageId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("files_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("friends") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.Id, "ID"); - - entity.HasIndex(e => new { e.UserId, e.FriendId }, "Userld"); - - entity.HasIndex(e => e.FriendId, "用户2id"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Avatar) - .HasMaxLength(255) - .HasComment("好友头像"); - entity.Property(e => e.Created) - .HasComment("好友关系创建时间") - .HasColumnType("datetime"); - entity.Property(e => e.FriendId) - .HasComment("用户2ID") - .HasColumnType("int(11)"); - entity.Property(e => e.RemarkName) - .HasMaxLength(20) - .HasComment("好友备注名"); - entity.Property(e => e.Status) - .HasComment("当前好友关系状态\r\n(0:待通过,1:已添加,2:已拒绝,3:已拉黑)") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.UserId) - .HasComment("用户ID") - .HasColumnType("int(11)"); - - entity.HasOne(d => d.FriendNavigation).WithMany(p => p.FriendFriendNavigations) - .HasForeignKey(d => d.FriendId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("用户2id"); - - entity.HasOne(d => d.User).WithMany(p => p.FriendUsers) - .HasForeignKey(d => d.UserId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("用户id"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("friend_request") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.RequestUser, "RequestUser"); - - entity.HasIndex(e => e.ResponseUser, "ResponseUser"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Created) - .HasComment("申请时间 ") - .HasColumnType("datetime"); - entity.Property(e => e.Description) - .HasComment("申请附言 ") - .HasColumnType("text"); - entity.Property(e => e.RequestUser) - .HasComment("申请人 ") - .HasColumnType("int(11)"); - entity.Property(e => e.ResponseUser) - .HasComment("被申请人 ") - .HasColumnType("int(11)"); - entity.Property(e => e.State) - .HasComment("申请状态(0:待通过,1:拒绝,2:同意,3:拉黑) ") - .HasColumnType("tinyint(4)"); - - entity.HasOne(d => d.RequestUserNavigation).WithMany(p => p.FriendRequestRequestUserNavigations) - .HasForeignKey(d => d.RequestUser) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("friend_request_ibfk_1"); - - entity.HasOne(d => d.ResponseUserNavigation).WithMany(p => p.FriendRequestResponseUserNavigations) - .HasForeignKey(d => d.ResponseUser) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("friend_request_ibfk_2"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("groups") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.GroupMaster, "GroupMaster"); - - entity.HasIndex(e => e.Id, "ID"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.AllMembersBanned) - .HasComment("全员禁言(0允许发言,2全员禁言)") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.Announcement) - .HasComment("群公告") - .HasColumnType("text"); - entity.Property(e => e.Auhority) - .HasComment("群权限\r\n(0:需管理员同意,1:任意人可加群,2:不允许任何人加入)") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.Created) - .HasComment("群聊创建时间") - .HasColumnType("datetime"); - entity.Property(e => e.GroupMaster) - .HasComment("群主") - .HasColumnType("int(11)"); - entity.Property(e => e.Name) - .HasMaxLength(20) - .HasComment("群聊名称"); - entity.Property(e => e.Status) - .HasComment("群聊状态\r\n(1:正常,2:封禁)") - .HasColumnType("tinyint(4)"); - - entity.HasOne(d => d.GroupMasterNavigation).WithMany(p => p.Groups) - .HasForeignKey(d => d.GroupMaster) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("groups_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("group_invite") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.GroupId, "GroupId"); - - entity.HasIndex(e => e.InviteUser, "InviteUser"); - - entity.HasIndex(e => e.InvitedUser, "InvitedUser"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Created) - .HasComment("创建时间") - .HasColumnType("datetime"); - entity.Property(e => e.GroupId) - .HasComment("群聊编号") - .HasColumnType("int(11)"); - entity.Property(e => e.InviteUser) - .HasComment("邀请用户") - .HasColumnType("int(11)"); - entity.Property(e => e.InvitedUser) - .HasComment("被邀请用户") - .HasColumnType("int(11)"); - entity.Property(e => e.State) - .HasComment("当前状态(0:待被邀请人同意\r\n1:被邀请人已同意)") - .HasColumnType("tinyint(4)"); - - entity.HasOne(d => d.Group).WithMany(p => p.GroupInvites) - .HasForeignKey(d => d.GroupId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("group_invite_ibfk_2"); - - entity.HasOne(d => d.InviteUserNavigation).WithMany(p => p.GroupInviteInviteUserNavigations) - .HasForeignKey(d => d.InviteUser) - .HasConstraintName("group_invite_ibfk_1"); - - entity.HasOne(d => d.InvitedUserNavigation).WithMany(p => p.GroupInviteInvitedUserNavigations) - .HasForeignKey(d => d.InvitedUser) - .HasConstraintName("group_invite_ibfk_3"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("group_member") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.GroupId, "Groupld"); - - entity.HasIndex(e => e.Id, "ID"); - - entity.HasIndex(e => e.UserId, "Userld"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Created) - .HasDefaultValueSql("'1970-01-01 00:00:00'") - .HasComment("加入群聊时间") - .HasColumnType("datetime"); - entity.Property(e => e.GroupId) - .HasComment("群聊编号") - .HasColumnType("int(11)"); - entity.Property(e => e.Role) - .HasComment("成员角色(0:普通成员,1:管理员,2:群主)") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.UserId) - .HasComment("用户编号") - .HasColumnType("int(11)"); - - entity.HasOne(d => d.Group).WithMany(p => p.GroupMemberGroups) - .HasForeignKey(d => d.GroupId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("group_member_ibfk_2"); - - entity.HasOne(d => d.User).WithMany(p => p.GroupMemberUsers) - .HasForeignKey(d => d.UserId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("group_member_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("group_request") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.GroupId, "GroupId"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Created) - .HasComment("创建时间") - .HasColumnType("datetime"); - entity.Property(e => e.Description) - .HasComment("入群附言") - .HasColumnType("text"); - entity.Property(e => e.GroupId) - .HasComment("群聊编号\r\n") - .HasColumnType("int(11)"); - entity.Property(e => e.State) - .HasComment("申请状态(0:待管理员同意,1:已拒绝,2:已同意)") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.UserId) - .HasComment("申请人 ") - .HasColumnType("int(11)"); - - entity.HasOne(d => d.Group).WithMany(p => p.GroupRequests) - .HasForeignKey(d => d.GroupId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("group_request_ibfk_1"); - - entity.HasOne(d => d.GroupNavigation).WithMany(p => p.GroupRequests) - .HasForeignKey(d => d.GroupId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("group_request_ibfk_2"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("login_log") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.UserId, "Userld"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Dtype) - .HasComment("设备类型(通Devices/DType) ") - .HasColumnType("tinyint(4)") - .HasColumnName("DType"); - entity.Property(e => e.Logined) - .HasComment("登录时间 ") - .HasColumnType("datetime"); - entity.Property(e => e.State) - .HasComment("登录状态(0:登陆成功,1:未验证,2:已被拒绝) ") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.UserId) - .HasComment("登录用户 ") - .HasColumnType("int(11)"); - - entity.HasOne(d => d.User).WithMany(p => p.LoginLogs) - .HasForeignKey(d => d.UserId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("login_log_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("messages") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.Sender, "Sender"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.ChatType) - .HasComment("聊天类型\r\n(0:私聊,1:群聊)") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.Content) - .HasComment("消息内容 ") - .HasColumnType("text"); - entity.Property(e => e.Created) - .HasComment("发送时间 ") - .HasColumnType("datetime"); - entity.Property(e => e.MsgType) - .HasComment("消息类型\r\n(0:文本,1:图片,2:语音,3:视频,4:文件,5:语音聊天,6:视频聊天)") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.Recipient) - .HasComment("接收者(私聊为用户ID,群聊为群聊ID) ") - .HasColumnType("int(11)"); - entity.Property(e => e.Sender) - .HasComment("发送者 ") - .HasColumnType("int(11)"); - entity.Property(e => e.State) - .HasComment("消息状态(0:已发送,1:已撤回) ") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.StreamKey) - .HasMaxLength(255) - .HasComment("消息推送唯一标识符"); - - entity.HasOne(d => d.SenderNavigation).WithMany(p => p.Messages) - .HasForeignKey(d => d.Sender) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("messages_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("notifications") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.UserId, "Userld"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Content) - .HasComment("通知内容") - .HasColumnType("text"); - entity.Property(e => e.Created) - .HasComment("创建时间") - .HasColumnType("datetime"); - entity.Property(e => e.Ntype) - .HasComment("通知类型(0:文本)") - .HasColumnType("tinyint(4)") - .HasColumnName("NType"); - entity.Property(e => e.Title) - .HasMaxLength(40) - .HasComment("通知标题"); - entity.Property(e => e.UserId) - .HasComment("接收人(为空为全体通知)") - .HasColumnType("int(11)"); - - entity.HasOne(d => d.User).WithMany(p => p.Notifications) - .HasForeignKey(d => d.UserId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("notifications_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("permissions") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Code) - .HasComment("权限编码 ") - .HasColumnType("int(11)"); - entity.Property(e => e.Created) - .HasComment("创建时间 ") - .HasColumnType("datetime"); - entity.Property(e => e.Name) - .HasMaxLength(50) - .HasComment("权限名称 "); - entity.Property(e => e.Ptype) - .HasComment("权限类型(0:增,1:删,2:改,3:查) ") - .HasColumnType("int(11)") - .HasColumnName("PType"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("permissionarole") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.PermissionId, "Permissionld"); - - entity.HasIndex(e => e.RoleId, "Roleld"); - - entity.Property(e => e.Id) - .ValueGeneratedNever() - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.PermissionId) - .HasComment("权限 ") - .HasColumnType("int(11)"); - entity.Property(e => e.RoleId) - .HasComment("角色 ") - .HasColumnType("int(11)"); - - entity.HasOne(d => d.Permission).WithMany(p => p.Permissionaroles) - .HasForeignKey(d => d.PermissionId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("permissionarole_ibfk_2"); - - entity.HasOne(d => d.Role).WithMany(p => p.Permissionaroles) - .HasForeignKey(d => d.RoleId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("permissionarole_ibfk_1"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("roles") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Created) - .HasComment("创建时间 ") - .HasColumnType("datetime"); - entity.Property(e => e.Description) - .HasComment("角色描述 ") - .HasColumnType("text"); - entity.Property(e => e.Name) - .HasMaxLength(20) - .HasComment("角色名称 "); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Id).HasName("PRIMARY"); - - entity - .ToTable("users") - .HasCharSet("utf8mb4") - .UseCollation("utf8mb4_general_ci"); - - entity.HasIndex(e => e.Id, "ID"); - - entity.HasIndex(e => e.Username, "Username").IsUnique(); - - entity.Property(e => e.Id) - .HasColumnType("int(11)") - .HasColumnName("ID"); - entity.Property(e => e.Avatar) - .HasMaxLength(255) - .HasComment("用户头像链接"); - entity.Property(e => e.Created) - .HasDefaultValueSql("'1970-01-01 00:00:00'") - .HasComment("创建时间") - .HasColumnType("datetime"); - entity.Property(e => e.IsDeleted) - .HasComment("软删除标识\r\n0:账号正常\r\n1:账号已删除") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.NickName) - .HasMaxLength(50) - .HasComment("用户昵称"); - entity.Property(e => e.OnlineStatus) - .HasComment("用户在线状态\r\n0(默认):不在线\r\n1:在线") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.Password) - .HasMaxLength(50) - .HasComment("密码"); - entity.Property(e => e.Status) - .HasDefaultValueSql("'1'") - .HasComment("账户状态\r\n(0:未激活,1:正常,2:封禁)") - .HasColumnType("tinyint(4)"); - entity.Property(e => e.Updated) - .HasComment("修改时间") - .HasColumnType("datetime"); - entity.Property(e => e.Username) - .HasMaxLength(50) - .HasComment("唯一用户名"); - }); - - OnModelCreatingPartial(modelBuilder); - } - - partial void OnModelCreatingPartial(ModelBuilder modelBuilder); -} diff --git a/backend/IM_API/Models/Message.cs b/backend/IM_API/Models/Message.cs index fcd7e9f..49d7839 100644 --- a/backend/IM_API/Models/Message.cs +++ b/backend/IM_API/Models/Message.cs @@ -49,6 +49,11 @@ public partial class Message /// public string StreamKey { get; set; } = null!; + /// + /// 若为群消息则表示具体的成员id + /// + public int? GroupMemberId { get; set; } + public virtual ICollection Conversations { get; set; } = new List(); public virtual ICollection Files { get; set; } = new List(); diff --git a/backend/IM_API/Services/ConversationService.cs b/backend/IM_API/Services/ConversationService.cs index 41ae75f..8a24272 100644 --- a/backend/IM_API/Services/ConversationService.cs +++ b/backend/IM_API/Services/ConversationService.cs @@ -1,4 +1,5 @@ -using IM_API.Dtos; +using AutoMapper; +using IM_API.Dtos; using IM_API.Exceptions; using IM_API.Interface.Services; using IM_API.Models; @@ -10,9 +11,11 @@ namespace IM_API.Services public class ConversationService : IConversationService { private readonly ImContext _context; - public ConversationService(ImContext context) + private readonly IMapper _mapper; + public ConversationService(ImContext context, IMapper mapper) { _context = context; + _mapper = mapper; } #region 删除用户会话 public async Task ClearConversationsAsync(int userId) @@ -26,47 +29,41 @@ namespace IM_API.Services #region 获取用户会话列表 public async Task> GetConversationsAsync(int userId) { - var privateQuery = from c in _context.Conversations - join f in _context.Friends on new { c.UserId, c.TargetId} - equals new { UserId = f.UserId, TargetId = f.FriendId} - where c.UserId == userId && c.ChatType == (int)ChatType.PRIVATE - select new ConversationDto - { - Id = c.Id, - UserId = c.UserId, - TargetId = c.TargetId, - LastReadMessageId = c.LastReadMessageId, - LastReadMessage = c.LastReadMessage, - UnreadCount = c.UnreadCount, - ChatType = c.ChatType, - LastMessage = c.LastMessage, - TargetAvatar = f.Avatar, - TargetName = f.RemarkName, - DateTime = c.LastMessageTime + // 1. 获取私聊会话 + var privateList = await (from c in _context.Conversations + join f in _context.Friends on new { c.UserId, c.TargetId } + equals new { UserId = f.UserId, TargetId = f.FriendId } + where c.UserId == userId && c.ChatType == (int)ChatType.PRIVATE + select new { c, f.Avatar, f.RemarkName }) + .ToListAsync(); - }; + // 2. 获取群聊会话 + var groupList = await (from c in _context.Conversations + join g in _context.Groups on c.TargetId equals g.Id + where c.UserId == userId && c.ChatType == (int)ChatType.GROUP + select new { c, g.Avatar, g.Name }) + .ToListAsync(); - var groupQuery = from c in _context.Conversations - join g in _context.Groups on c.TargetId equals g.Id - where c.UserId == userId && c.ChatType == (int)ChatType.GROUP - select new ConversationDto - { - Id = c.Id, - UserId = c.UserId, - TargetId = c.TargetId, - LastReadMessageId = c.LastReadMessageId, - LastReadMessage = c.LastReadMessage, - UnreadCount = c.UnreadCount, - ChatType = c.ChatType, - LastMessage = c.LastMessage, - TargetAvatar = g.Avatar, - TargetName = g.Name, - DateTime = c.LastMessageTime - }; - return await privateQuery - .Concat(groupQuery) - .OrderByDescending(x => x.DateTime) - .ToListAsync(); + var privateDtos = privateList.Select(x => + { + var dto = _mapper.Map(x.c); + dto.TargetAvatar = x.Avatar; + dto.TargetName = x.RemarkName; + return dto; + }); + + var groupDtos = groupList.Select(x => + { + var dto = _mapper.Map(x.c); + dto.TargetAvatar = x.Avatar; + dto.TargetName = x.Name; + return dto; + }); + + // 4. 合并并排序 + return privateDtos.Concat(groupDtos) + .OrderByDescending(x => x.DateTime) + .ToList(); } #endregion #region 删除单个会话 @@ -81,6 +78,7 @@ namespace IM_API.Services #endregion + #region 获取用户所有统一聊天凭证 public async Task> GetUserAllStreamKeyAsync(int userId) { return await _context.Conversations.Where(x => x.UserId == userId) @@ -88,5 +86,37 @@ namespace IM_API.Services .Distinct() .ToListAsync(); } + #endregion + + #region 获取单个会话信息 + public async Task GetConversationByIdAsync(int userId, int conversationId) + { + var conversation = await _context.Conversations + .Include(x => x.LastReadMessage) + .FirstOrDefaultAsync( + x => x.UserId == userId && x.Id == conversationId + ); + if (conversation is null) throw new BaseException(CodeDefine.CONVERSATION_NOT_FOUND); + var dto = _mapper.Map(conversation); + //dto.LastReadMessage = _mapper.Map(conversation); + if(conversation.ChatType == (int)ChatType.PRIVATE) + { + var friendInfo = await _context.Friends.FirstOrDefaultAsync( + x => x.UserId == userId && x.FriendId == conversation.TargetId + ); + if (friendInfo is null) throw new BaseException(CodeDefine.FRIEND_RELATION_NOT_FOUND); + _mapper.Map(friendInfo,dto); + } + if(conversation.ChatType == (int)ChatType.GROUP) + { + var groupInfo = await _context.Groups.FirstOrDefaultAsync( + x => x.Id == conversation.TargetId + ); + if (groupInfo is null) throw new BaseException(CodeDefine.GROUP_NOT_FOUND); + _mapper.Map(groupInfo, dto); + } + return dto; + } + #endregion } } \ No newline at end of file diff --git a/backend/IM_API/Services/MessageService.cs b/backend/IM_API/Services/MessageService.cs index 2c13695..6f4c41f 100644 --- a/backend/IM_API/Services/MessageService.cs +++ b/backend/IM_API/Services/MessageService.cs @@ -20,14 +20,38 @@ namespace IM_API.Services _mapper = mapper; } - public Task> GetGroupMessagesAsync(int groupId, int page, int pageSize, bool desc) + public async Task> GetMessagesAsync(int userId, int conversationId, int? msgId, int? pageSize, bool desc) { - throw new NotImplementedException(); - } - - public Task> GetPrivateMessagesAsync(int userAId, int userBId, int page, int pageSize, bool desc) - { - throw new NotImplementedException(); + //获取会话信息,用于获取双方聊天的唯一标识streamkey + Conversation? conversation = await _context.Conversations.FirstOrDefaultAsync( + x => x.Id == conversationId && x.UserId == userId + ); + if (conversation is null) throw new BaseException(CodeDefine.CONVERSATION_NOT_FOUND); + var query = _context.Messages.AsQueryable(); + if(msgId != null) + { + query = query.Where( + x => x.StreamKey == conversation.StreamKey && x.Id < msgId.Value + ) + .OrderByDescending(x => x.Id); + } + else + { + query = query.Where( + x => x.StreamKey == conversation.StreamKey && x.Id > conversation.LastReadMessageId + ); + } + if(pageSize != null) + { + query = query.Take(pageSize.Value); + } + var msgList = await query + .ToListAsync(); + msgList = msgList + .OrderBy(x => x.Created) + .ThenBy(t => t.Id) + .ToList(); + return _mapper.Map>(msgList); } public Task GetUnreadCountAsync(int userId) diff --git a/docs/后端代码规范文档.md b/docs/后端代码规范文档.md index 69fd33b..aba6311 100644 --- a/docs/后端代码规范文档.md +++ b/docs/后端代码规范文档.md @@ -71,3 +71,12 @@ public WeatherForecastController(IDemo demo) ## 4. 模型类字段使用规范 ### 4.1 类中状态相关字段,例如:Status,返回值为sbyte。若类中有同名字段+后缀Enum,则优先使用后者,StatusEnum。 + +## 5.数据库相关 + +### 5.1 若数据库表结构更新,请在软件包控制台执行如下命令: + +```cmd +Scaffold-DbContext "Name=ConnectionStrings:DefaultConnection" Pomelo.EntityFrameworkCore.MySql -OutputDir Models -Context ImContext -Force -NoOnConfiguring +``` + diff --git a/frontend/web/src/router/index.js b/frontend/web/src/router/index.js index 6a254fb..a4fa55d 100644 --- a/frontend/web/src/router/index.js +++ b/frontend/web/src/router/index.js @@ -11,7 +11,10 @@ const routes = [ { path: '/', component: MainView, - + redirect: '/messages', + meta: { + requiresAuth: true + }, children: [ { path: '/messages', @@ -42,6 +45,7 @@ const routes = [ { path: '/index', component: MainView, + redirect: '/messages', meta: { requiresAuth: true } @@ -56,10 +60,18 @@ const router = createRouter({ router.beforeEach((to, from, next) => { const authStore = useAuthStore(); + if (to.path == '/auth/login') { + if (authStore.isLoggedIn) { + message.info('已登录,即将跳转...'); + next('/'); + } + next(); + } if (to.meta.requiresAuth && !authStore.isLoggedIn) { message.info('未登录,即将跳转...'); next('auth/login'); - } else { + } + else { next(); } }) diff --git a/frontend/web/src/services/message.js b/frontend/web/src/services/message.js index 491e7f6..9949563 100644 --- a/frontend/web/src/services/message.js +++ b/frontend/web/src/services/message.js @@ -11,5 +11,25 @@ export const messageService = { * 清空所有会话消息 * @returns */ - clearConversation: () => request.post('') + clearConversation: () => request.post(''), + /** + * 获取单个会话信息 + * @param {*} conversationId + * @returns + */ + getConversationById: (conversationId) => request.get(`/conversation/get?conversationId=${conversationId}`), + /** + * 获取历史消息列表 + * @param {*} conversationId 指定会话 + * @param {*} msgId + * @param {*} pageSize + * @returns + */ + getHistoryMessages: (conversationId, msgId, pageSize = 10) => request.get(`/message/getmessageList?conversationId=${conversationId}&msgId=${msgId}&pageSize=${pageSize}`), + /** + * 获取最新消息 + * @param {*} conversationId + * @returns + */ + getMessages: (conversationId) => request.get(`/message/getmessageList?conversationId=${conversationId}`) } \ No newline at end of file diff --git a/frontend/web/src/utils/codeHelper.js b/frontend/web/src/utils/codeHelper.js new file mode 100644 index 0000000..9428a61 --- /dev/null +++ b/frontend/web/src/utils/codeHelper.js @@ -0,0 +1,10 @@ +export function getChatCodeStr(code) { + switch (code) { + case 0: + return '私聊' + case 1: + return '群聊' + default: + return '未知类型' + } +} \ No newline at end of file diff --git a/frontend/web/src/utils/formatDate.js b/frontend/web/src/utils/formatDate.js new file mode 100644 index 0000000..6ac814e --- /dev/null +++ b/frontend/web/src/utils/formatDate.js @@ -0,0 +1,18 @@ +export function formatDate(dateStr) { + const date = new Date(dateStr); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); // 补零 + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + const nowDate = new Date(); + if (year == nowDate.getFullYear() && month == String(nowDate.getMonth() + 1).padStart(2, '0') && day == String(nowDate.getDate()).padStart(2, '0')) { + return `${hours}:${minutes}:${seconds}`; + } + if (year == nowDate.getFullYear()) { + return `${month}/${day} ${hours}:${minutes}:${seconds}`; + } + + return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; +} \ No newline at end of file diff --git a/frontend/web/src/views/contact/ContactList.vue b/frontend/web/src/views/contact/ContactList.vue index e9ebd99..1ffb39d 100644 --- a/frontend/web/src/views/contact/ContactList.vue +++ b/frontend/web/src/views/contact/ContactList.vue @@ -126,7 +126,6 @@ function handleGoToChat() { const loadContactList = async (page = 1,limit = 100) => { const res = await friendService.getFriendList(page,limit); contacts.value = res.data; - console.log(contacts.value) } diff --git a/frontend/web/src/views/messages/MessageContent.vue b/frontend/web/src/views/messages/MessageContent.vue index 8b5293a..eb97f96 100644 --- a/frontend/web/src/views/messages/MessageContent.vue +++ b/frontend/web/src/views/messages/MessageContent.vue @@ -1,7 +1,7 @@