feat:增加查询消息接口模块
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
using FreeSql;
|
using FreeSql;
|
||||||
|
using System.Reflection;
|
||||||
|
using Yitter.IdGenerator;
|
||||||
|
|
||||||
namespace SweetChatService.Config
|
namespace SweetChatService.Config
|
||||||
{
|
{
|
||||||
@@ -6,14 +8,29 @@ namespace SweetChatService.Config
|
|||||||
{
|
{
|
||||||
public static IFreeSql CreateFreeSql(string connectionString)
|
public static IFreeSql CreateFreeSql(string connectionString)
|
||||||
{
|
{
|
||||||
return new FreeSqlBuilder()
|
var fsql = new FreeSqlBuilder()
|
||||||
.UseConnectionString(DataType.MySql, connectionString)
|
.UseConnectionString(DataType.MySql, connectionString)
|
||||||
.UseAutoSyncStructure(false)
|
.UseAutoSyncStructure(false)
|
||||||
.UseMonitorCommand(cmd =>
|
//.UseMonitorCommand(cmd =>
|
||||||
{
|
//{
|
||||||
Console.WriteLine(cmd.CommandText);
|
// Console.WriteLine(cmd.CommandText);
|
||||||
})
|
//})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
fsql.Aop.AuditValue += (_, e) =>
|
||||||
|
{
|
||||||
|
var hasSnowflake = e.Property.GetCustomAttribute<SnowflakeAttribute>(false) != null;
|
||||||
|
|
||||||
|
if (e.Column.CsType == typeof(long) && hasSnowflake)
|
||||||
|
{
|
||||||
|
if (e.Value == null || e.Value.ToString() == "0")
|
||||||
|
{
|
||||||
|
e.Value = YitIdHelper.NextId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return fsql;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
SweetChatService/Config/SnowflakeAttribute.cs
Normal file
4
SweetChatService/Config/SnowflakeAttribute.cs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
namespace SweetChatService.Config
|
||||||
|
{
|
||||||
|
public class SnowflakeAttribute : Attribute { }
|
||||||
|
}
|
||||||
@@ -11,11 +11,7 @@
|
|||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
app.UseEndpoints(endpoints => endpoints.MapControllers());
|
||||||
app.UseEndpoints(endpoints =>
|
|
||||||
{
|
|
||||||
endpoints.MapControllers();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,9 @@ namespace SweetChatService.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class AuthController : ControllerBase
|
public class AuthController(UserService userService) : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly UserService _userService;
|
private readonly UserService _userService = userService;
|
||||||
|
|
||||||
public AuthController(UserService userService)
|
|
||||||
{
|
|
||||||
_userService = userService;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("login")]
|
[HttpPost("login")]
|
||||||
public IActionResult Login([FromBody] LoginDto dto)
|
public IActionResult Login([FromBody] LoginDto dto)
|
||||||
@@ -31,7 +26,7 @@ namespace SweetChatService.Controllers
|
|||||||
{
|
{
|
||||||
return Ok(new
|
return Ok(new
|
||||||
{
|
{
|
||||||
userId = user.Id
|
user
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
SweetChatService/Controllers/MessageController.cs
Normal file
24
SweetChatService/Controllers/MessageController.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using SweetChatService.Services;
|
||||||
|
|
||||||
|
namespace SweetChatService.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class MessageController(MessageService messageService) : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly MessageService _messageService = messageService;
|
||||||
|
|
||||||
|
[HttpGet("session/{userId}")]
|
||||||
|
public IActionResult QueryChatSession(long userId)
|
||||||
|
{
|
||||||
|
return Ok(_messageService.QueryChatSession(userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("session/{conversationId}/detail")]
|
||||||
|
public IActionResult QueryChatMessage(long conversationId)
|
||||||
|
{
|
||||||
|
return Ok(_messageService.QueryChatMessage(conversationId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,14 +7,9 @@ namespace SweetChatService.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class UserController : ControllerBase
|
public class UserController(UserService userService) : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly UserService _userService;
|
private readonly UserService _userService = userService;
|
||||||
|
|
||||||
public UserController(UserService userService)
|
|
||||||
{
|
|
||||||
_userService = userService;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("friend/{userId}")]
|
[HttpGet("friend/{userId}")]
|
||||||
public IActionResult QueryFriendByUserId(long userId)
|
public IActionResult QueryFriendByUserId(long userId)
|
||||||
|
|||||||
8
SweetChatService/Dockerfile
Normal file
8
SweetChatService/Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
|
||||||
|
WORKDIR /app
|
||||||
|
COPY ./publish .
|
||||||
|
EXPOSE 5050
|
||||||
|
EXPOSE 5051
|
||||||
|
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||||
|
RUN echo 'Asia/Shanghai' > /etc/timezone
|
||||||
|
ENTRYPOINT ["dotnet", "SweetChatService.dll"]
|
||||||
14
SweetChatService/Dto/ChatMessageDto.cs
Normal file
14
SweetChatService/Dto/ChatMessageDto.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace SweetChatService.Dto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 会话消息
|
||||||
|
/// </summary>
|
||||||
|
public class ChatMessageDto
|
||||||
|
{
|
||||||
|
public long MsgId { get; set; }
|
||||||
|
public long SenderId { get; set; }
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
public byte MsgType { get; set; }
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
48
SweetChatService/Dto/ChatSessionDto.cs
Normal file
48
SweetChatService/Dto/ChatSessionDto.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
namespace SweetChatService.Dto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 会话列表项
|
||||||
|
/// </summary>
|
||||||
|
public class ChatSessionDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 会话ID
|
||||||
|
/// </summary>
|
||||||
|
public long ConversationId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对方用户ID
|
||||||
|
/// </summary>
|
||||||
|
public long TargetUserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对方昵称(优先备注名)
|
||||||
|
/// </summary>
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对方头像
|
||||||
|
/// </summary>
|
||||||
|
public string AvatarUrl { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最后一条消息类型
|
||||||
|
/// </summary>
|
||||||
|
public int MsgType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最后一条消息内容
|
||||||
|
/// </summary>
|
||||||
|
public string LastMessageContent { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最后一条消息时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime LastMessageTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 未读消息数
|
||||||
|
/// </summary>
|
||||||
|
public int UnreadCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
26
SweetChatService/Entity/Conversation.cs
Normal file
26
SweetChatService/Entity/Conversation.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using FreeSql.DataAnnotations;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace SweetChatService.Entity
|
||||||
|
{
|
||||||
|
[Table(Name = "conversation")]
|
||||||
|
[Description("会话表")]
|
||||||
|
public class Conversation
|
||||||
|
{
|
||||||
|
[Column(Name = "id", IsPrimary = true, IsIdentity = true)]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "type")]
|
||||||
|
[Description("1单聊 2群聊")]
|
||||||
|
public byte Type { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "last_msg_id")]
|
||||||
|
public long LastMsgId { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "create_time", ServerTime = DateTimeKind.Local, CanInsert = true, CanUpdate = false)]
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "update_time", ServerTime = DateTimeKind.Local)]
|
||||||
|
public DateTime UpdateTime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
28
SweetChatService/Entity/ConversationMember.cs
Normal file
28
SweetChatService/Entity/ConversationMember.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using FreeSql.DataAnnotations;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace SweetChatService.Entity
|
||||||
|
{
|
||||||
|
[Table(Name = "conversation_member")]
|
||||||
|
[Description("会话成员表")]
|
||||||
|
public class ConversationMember
|
||||||
|
{
|
||||||
|
[Column(Name = "conversation_id", IsPrimary = true)]
|
||||||
|
public long ConversationId { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "user_id", IsPrimary = true)]
|
||||||
|
public long UserId { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "unread_count")]
|
||||||
|
public int UnreadCount { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "last_read_msg_id")]
|
||||||
|
public long LastReadMsgId { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "create_time", ServerTime = DateTimeKind.Local, CanInsert = true, CanUpdate = false)]
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "update_time", ServerTime = DateTimeKind.Local)]
|
||||||
|
public DateTime UpdateTime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
34
SweetChatService/Entity/Message.cs
Normal file
34
SweetChatService/Entity/Message.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using FreeSql.DataAnnotations;
|
||||||
|
using SweetChatService.Config;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace SweetChatService.Entity
|
||||||
|
{
|
||||||
|
[Table(Name = "message")]
|
||||||
|
[Description("消息表")]
|
||||||
|
public class Message
|
||||||
|
{
|
||||||
|
[Column(Name = "msg_id", IsPrimary = true, IsIdentity = false)]
|
||||||
|
[Snowflake]
|
||||||
|
public long MsgId { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "conversation_id")]
|
||||||
|
public long ConversationId { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "sender_id")]
|
||||||
|
public long SenderId { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "content")]
|
||||||
|
public string Content { get; set; } = "";
|
||||||
|
|
||||||
|
[Column(Name = "msg_type")]
|
||||||
|
[Description("1文本 2图片 3语音")]
|
||||||
|
public byte MsgType { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "create_time", ServerTime = DateTimeKind.Local, CanInsert = true, CanUpdate = false)]
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "update_time", ServerTime = DateTimeKind.Local)]
|
||||||
|
public DateTime UpdateTime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,9 @@
|
|||||||
using Microsoft.AspNetCore.WebUtilities;
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using SuperSocket.WebSocket;
|
using SuperSocket.WebSocket;
|
||||||
using SuperSocket.WebSocket.Server;
|
using SuperSocket.WebSocket.Server;
|
||||||
using SweetChatService.Models;
|
using SweetChatService.Models;
|
||||||
using SweetChatService.Services;
|
using SweetChatService.Services;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace SweetChatService.Handlers
|
namespace SweetChatService.Handlers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace SweetChatService.Models
|
namespace SweetChatService.Models
|
||||||
{
|
{
|
||||||
internal class ImMessage
|
public class ImMessage
|
||||||
{
|
{
|
||||||
[JsonPropertyName("type")]
|
[JsonPropertyName("type")]
|
||||||
public ImMessageType Type { get; set; }
|
public ImMessageType Type { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("title")]
|
||||||
|
public string Title { get; set; } = default!;
|
||||||
|
|
||||||
[JsonPropertyName("from")]
|
[JsonPropertyName("from")]
|
||||||
public string From { get; set; } = default!;
|
public string From { get; set; } = default!;
|
||||||
|
|
||||||
@@ -22,6 +25,7 @@ namespace SweetChatService.Models
|
|||||||
return new ImMessage
|
return new ImMessage
|
||||||
{
|
{
|
||||||
Type = ImMessageType.SYSTEM,
|
Type = ImMessageType.SYSTEM,
|
||||||
|
Title = "系统通知",
|
||||||
From = "SYSTEM",
|
From = "SYSTEM",
|
||||||
To = to,
|
To = to,
|
||||||
Content = content
|
Content = content
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace SweetChatService.Models
|
namespace SweetChatService.Models
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||||
internal enum ImMessageType
|
public enum ImMessageType
|
||||||
{
|
{
|
||||||
CHAT_PRIVATE,
|
CHAT_PRIVATE,
|
||||||
CHAT_GROUP,
|
CHAT_GROUP,
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
<targets async="true">
|
<targets async="true">
|
||||||
<target name="fluentbit" xsi:type="Network"
|
<target name="fluentbit" xsi:type="Network"
|
||||||
newLine="true" lineEnding="LF"
|
newLine="true" lineEnding="LF"
|
||||||
address="tcp://60.247.145.200:5170">
|
address="tcp://host.docker.internal:5170">
|
||||||
<layout xsi:type="JsonLayout">
|
<layout xsi:type="JsonLayout">
|
||||||
<attribute name="topic" layout="message-hub"/>
|
<attribute name="topic" layout="sweet-chat"/>
|
||||||
<attribute name="timestamp" layout="${longdate:universalTime=true}"/>
|
<attribute name="timestamp" layout="${longdate:universalTime=true}"/>
|
||||||
<attribute name="level" layout="${level:uppercase=true}"/>
|
<attribute name="level" layout="${level:uppercase=true}"/>
|
||||||
<attribute name="logger" layout="${logger}"/>
|
<attribute name="logger" layout="${logger}"/>
|
||||||
@@ -27,6 +27,6 @@
|
|||||||
</targets>
|
</targets>
|
||||||
|
|
||||||
<rules>
|
<rules>
|
||||||
<logger name="*" minlevel="Info" writeTo="stdout"/>
|
<logger name="*" minlevel="Info" writeTo="stdout, fluentbit"/>
|
||||||
</rules>
|
</rules>
|
||||||
</nlog>
|
</nlog>
|
||||||
@@ -4,6 +4,7 @@ using SuperSocket.WebSocket.Server;
|
|||||||
using SweetChatService.Config;
|
using SweetChatService.Config;
|
||||||
using SweetChatService.Handlers;
|
using SweetChatService.Handlers;
|
||||||
using SweetChatService.Services;
|
using SweetChatService.Services;
|
||||||
|
using Yitter.IdGenerator;
|
||||||
|
|
||||||
var host = Host.CreateDefaultBuilder(args)
|
var host = Host.CreateDefaultBuilder(args)
|
||||||
.ConfigureWebHostDefaults(webBuilder =>
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
@@ -12,6 +13,9 @@ var host = Host.CreateDefaultBuilder(args)
|
|||||||
})
|
})
|
||||||
.ConfigureServices((context, services) =>
|
.ConfigureServices((context, services) =>
|
||||||
{
|
{
|
||||||
|
var options = new IdGeneratorOptions(6);
|
||||||
|
YitIdHelper.SetIdGenerator(options);
|
||||||
|
|
||||||
services.AddSingleton<WsMsgHandler>();
|
services.AddSingleton<WsMsgHandler>();
|
||||||
services.AddSingleton<WsSessionManager>();
|
services.AddSingleton<WsSessionManager>();
|
||||||
|
|
||||||
@@ -19,6 +23,7 @@ var host = Host.CreateDefaultBuilder(args)
|
|||||||
|
|
||||||
services.AddSingleton(FreeSqlSetup.CreateFreeSql(context.Configuration["ConnectionStrings:Default"]));
|
services.AddSingleton(FreeSqlSetup.CreateFreeSql(context.Configuration["ConnectionStrings:Default"]));
|
||||||
services.AddSingleton<UserService>();
|
services.AddSingleton<UserService>();
|
||||||
|
services.AddSingleton<MessageService>();
|
||||||
})
|
})
|
||||||
.AsMultipleServerHostBuilder()
|
.AsMultipleServerHostBuilder()
|
||||||
.AddWebSocketServer(builder =>
|
.AddWebSocketServer(builder =>
|
||||||
|
|||||||
141
SweetChatService/Services/MessageService.cs
Normal file
141
SweetChatService/Services/MessageService.cs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
using SweetChatService.Dto;
|
||||||
|
using SweetChatService.Entity;
|
||||||
|
using SweetChatService.Models;
|
||||||
|
|
||||||
|
namespace SweetChatService.Services
|
||||||
|
{
|
||||||
|
public class MessageService
|
||||||
|
{
|
||||||
|
private readonly IFreeSql _fsql;
|
||||||
|
|
||||||
|
public MessageService(IFreeSql fsql) => _fsql = fsql;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取或创建单聊会话
|
||||||
|
/// </summary>
|
||||||
|
public async Task<bool> SavePrivateMessageAsync(ImMessage msg)
|
||||||
|
{
|
||||||
|
long userId1 = long.Parse(msg.From);
|
||||||
|
long userId2 = long.Parse(msg.To);
|
||||||
|
|
||||||
|
var ids = new[] { userId1, userId2 };
|
||||||
|
Array.Sort(ids);
|
||||||
|
|
||||||
|
// 1️ 查询是否已存在会话
|
||||||
|
|
||||||
|
// 先从ConversationMember把包含用户1和用户2的找到
|
||||||
|
// 然后按照ConversationId分组
|
||||||
|
// 如果正好这个组里面的个数为2,则说明只有1和2,否则是其他的,比如群
|
||||||
|
var convId = await _fsql
|
||||||
|
.Select<ConversationMember>()
|
||||||
|
.Where(m => new[] { userId1, userId2 }.Contains(m.UserId))
|
||||||
|
.GroupBy(m => m.ConversationId)
|
||||||
|
.Having(g => g.Count() == 2)
|
||||||
|
.FirstAsync(g => g.Key);
|
||||||
|
|
||||||
|
// 2. 如果没查到
|
||||||
|
if (convId <= 0)
|
||||||
|
{
|
||||||
|
// 则先新增1条会话记录
|
||||||
|
var conversation = new Conversation
|
||||||
|
{
|
||||||
|
Type = 1
|
||||||
|
};
|
||||||
|
conversation.Id = await _fsql.Insert(conversation).ExecuteIdentityAsync();
|
||||||
|
|
||||||
|
// 然后新增2条会话成员记录
|
||||||
|
var conversation_member = new[]
|
||||||
|
{
|
||||||
|
// 一条是user1的
|
||||||
|
new ConversationMember
|
||||||
|
{
|
||||||
|
ConversationId = conversation.Id,
|
||||||
|
UserId = ids[0],
|
||||||
|
UnreadCount = 0
|
||||||
|
},
|
||||||
|
// 一条是user2的
|
||||||
|
new ConversationMember
|
||||||
|
{
|
||||||
|
ConversationId = conversation.Id,
|
||||||
|
UserId = ids[1],
|
||||||
|
UnreadCount = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await _fsql.Insert(conversation_member).ExecuteAffrowsAsync();
|
||||||
|
|
||||||
|
// 重新赋值
|
||||||
|
convId = conversation.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 插入消息表
|
||||||
|
var message = new Message
|
||||||
|
{
|
||||||
|
ConversationId = convId,
|
||||||
|
SenderId = userId1,
|
||||||
|
Content = msg.Content,
|
||||||
|
MsgType = 1,
|
||||||
|
CreateTime = DateTime.Now
|
||||||
|
};
|
||||||
|
|
||||||
|
message.MsgId = await _fsql.Insert(message).ExecuteIdentityAsync();
|
||||||
|
|
||||||
|
// 更新会话表
|
||||||
|
await _fsql.Update<Conversation>()
|
||||||
|
.Set(c => c.LastMsgId, message.MsgId)
|
||||||
|
.Set(c => c.UpdateTime, DateTime.Now)
|
||||||
|
.Where(c => c.Id == convId)
|
||||||
|
.ExecuteAffrowsAsync();
|
||||||
|
|
||||||
|
// 接收方未读+1
|
||||||
|
await _fsql.Update<ConversationMember>()
|
||||||
|
.Set(a => a.UnreadCount + 1)
|
||||||
|
.Where(w => w.ConversationId == convId && w.UserId == userId2)
|
||||||
|
.ExecuteAffrowsAsync();
|
||||||
|
|
||||||
|
// 发送方更新已读位置
|
||||||
|
await _fsql.Update<ConversationMember>()
|
||||||
|
.Set(a => a.LastReadMsgId, message.MsgId)
|
||||||
|
.Where(w => w.ConversationId == convId && w.UserId == userId1)
|
||||||
|
.ExecuteAffrowsAsync();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ChatSessionDto> QueryChatSession(long userId)
|
||||||
|
{
|
||||||
|
return _fsql.Select<ConversationMember, Conversation, ConversationMember, User, Message>()
|
||||||
|
.LeftJoin((cm, c, cmo, u, m) => cm.ConversationId == c.Id && c.Type == 1)
|
||||||
|
.LeftJoin((cm, c, cmo, u, m) => cmo.ConversationId == c.Id && cmo.UserId != cm.UserId)
|
||||||
|
.LeftJoin((cm, c, cmo, u, m) => u.Id == cmo.UserId)
|
||||||
|
.LeftJoin((cm, c, cmo, u, m) => c.LastMsgId == m.MsgId)
|
||||||
|
.Where((cm, _, _, _, _) => cm.UserId == userId)
|
||||||
|
.OrderByDescending((_, _, _, _, m) => m.CreateTime)
|
||||||
|
.ToList((cm, c, cmo, u, m) => new ChatSessionDto
|
||||||
|
{
|
||||||
|
ConversationId = c.Id,
|
||||||
|
TargetUserId = u.Id,
|
||||||
|
Title = u.Nickname,
|
||||||
|
AvatarUrl = u.AvatarUrl,
|
||||||
|
MsgType = m.MsgType,
|
||||||
|
LastMessageContent = m.Content ?? "",
|
||||||
|
LastMessageTime = m.CreateTime,
|
||||||
|
UnreadCount = cm.UnreadCount
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ChatMessageDto> QueryChatMessage(long conversationId)
|
||||||
|
{
|
||||||
|
return _fsql.Select<Message>()
|
||||||
|
.Where(m => m.ConversationId == conversationId)
|
||||||
|
.OrderBy(m => m.MsgId)
|
||||||
|
.ToList((m) => new ChatMessageDto
|
||||||
|
{
|
||||||
|
MsgId = m.MsgId,
|
||||||
|
SenderId = m.SenderId,
|
||||||
|
Content = m.Content,
|
||||||
|
MsgType = m.MsgType,
|
||||||
|
CreateTime = m.CreateTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,15 @@ using SweetChatService.Models;
|
|||||||
|
|
||||||
namespace SweetChatService.Services
|
namespace SweetChatService.Services
|
||||||
{
|
{
|
||||||
internal class PrivateChatService(WsSessionManager wsSessionManager)
|
internal class PrivateChatService(WsSessionManager wsSessionManager, MessageService messageService)
|
||||||
{
|
{
|
||||||
private readonly WsSessionManager _wsSessionManager = wsSessionManager;
|
private readonly WsSessionManager _wsSessionManager = wsSessionManager;
|
||||||
|
private readonly MessageService _messageService = messageService;
|
||||||
|
|
||||||
public async Task HandleAsync(ImMessage msg)
|
public async Task HandleAsync(ImMessage msg)
|
||||||
{
|
{
|
||||||
|
await _messageService.SavePrivateMessageAsync(msg);
|
||||||
|
|
||||||
// 推送给对方
|
// 推送给对方
|
||||||
if (_wsSessionManager.TryGet(msg.To, out var toSession))
|
if (_wsSessionManager.TryGet(msg.To, out var toSession))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,9 +11,17 @@
|
|||||||
<PackageReference Include="FreeSql.Provider.MySqlConnector" Version="3.5.310" />
|
<PackageReference Include="FreeSql.Provider.MySqlConnector" Version="3.5.310" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.0" />
|
||||||
<PackageReference Include="NLog.Extensions.Hosting" Version="6.1.3" />
|
<PackageReference Include="NLog.Extensions.Hosting" Version="6.1.3" />
|
||||||
|
<PackageReference Include="NLog.Targets.Network" Version="6.0.4" />
|
||||||
<PackageReference Include="SuperSocket" Version="2.0.2" />
|
<PackageReference Include="SuperSocket" Version="2.0.2" />
|
||||||
<PackageReference Include="SuperSocket.WebSocket" Version="2.1.0" />
|
<PackageReference Include="SuperSocket.WebSocket" Version="2.1.0" />
|
||||||
<PackageReference Include="SuperSocket.WebSocket.Server" Version="2.1.0" />
|
<PackageReference Include="SuperSocket.WebSocket.Server" Version="2.1.0" />
|
||||||
|
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Update="NLog.config">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -23,6 +31,9 @@
|
|||||||
<None Update="NLog.config">
|
<None Update="NLog.config">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="Properties\launchSettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
6
SweetChatService/Yitter/YitIdHelper.cs
Normal file
6
SweetChatService/Yitter/YitIdHelper.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Yitter
|
||||||
|
{
|
||||||
|
internal class YitIdHelper
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"Default": "Server=localhost;Port=3306;Database=sweet_chat;Uid=root;Pwd=estun@medical;Charset=utf8mb4;"
|
"Default": "Server=host.docker.internal;Port=3306;Database=sweet_chat;Uid=root;Pwd=19940822Cxx@1213;Charset=utf8mb4;"
|
||||||
|
},
|
||||||
|
"Kestrel": {
|
||||||
|
"Endpoints": {
|
||||||
|
"Http": {
|
||||||
|
"Url": "http://+:5051"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"serverOptions": {
|
"serverOptions": {
|
||||||
"WebSocketServer": {
|
"WebSocketServer": {
|
||||||
|
|||||||
Reference in New Issue
Block a user