10 changed files with 337 additions and 35 deletions
@ -0,0 +1,176 @@ |
|||||||
|
using AX.WebDrillServer.Data; |
||||||
|
using AX.WebDrillServer.Extensions; |
||||||
|
using AX.WebDrillServer.Middlewares.Jwts; |
||||||
|
using AX.WebDrillServer.Models; |
||||||
|
using AX.WebDrillServer.Services.FireDeductionHub; |
||||||
|
using Microsoft.AspNetCore.Authorization; |
||||||
|
using Microsoft.AspNetCore.SignalR; |
||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
using Microsoft.Extensions.Caching.Memory; |
||||||
|
using System.Collections.Concurrent; |
||||||
|
using System.Security.Claims; |
||||||
|
|
||||||
|
namespace AX.WebDrillServer.Hubs |
||||||
|
{ |
||||||
|
//[Authorize] |
||||||
|
public class FireDeductionHub : Hub |
||||||
|
{ |
||||||
|
private readonly RoomManager roomManager; |
||||||
|
|
||||||
|
private readonly ApplicationDbContext _dbContext; |
||||||
|
|
||||||
|
private readonly ILogger<FireDeductionHub> _logger; |
||||||
|
|
||||||
|
public FireDeductionHub( |
||||||
|
ApplicationDbContext dbContext, |
||||||
|
ILogger<FireDeductionHub> logger, |
||||||
|
RoomManager roomManager) |
||||||
|
{ |
||||||
|
_dbContext = dbContext; |
||||||
|
_logger = logger; |
||||||
|
this.roomManager = roomManager; |
||||||
|
} |
||||||
|
public async Task<FireDeductionRoom> CreateRoom(RoomCreateDto createInfo, FireDeductionUser user) |
||||||
|
{ |
||||||
|
FireDeductionRoom room = new FireDeductionRoom(); |
||||||
|
room.Owner = createInfo.UserId; |
||||||
|
room.RoomId = Guid.NewGuid().ToString(); |
||||||
|
room.RoomName = createInfo.RoomName; |
||||||
|
room.Password = createInfo.RoomPassword; |
||||||
|
room.Users.Add(user); |
||||||
|
await Groups.AddToGroupAsync(user.ConnectionId, room.RoomId); |
||||||
|
return room; |
||||||
|
} |
||||||
|
public async Task<bool> EnterRoom(string roomId, FireDeductionUser user, string? password = null) |
||||||
|
{ |
||||||
|
bool result = false; |
||||||
|
|
||||||
|
var room = roomManager.GetRoom(roomId); |
||||||
|
if (room != null && room.Password == password) |
||||||
|
{ |
||||||
|
if (!room.Users.Contains(user)) |
||||||
|
{ |
||||||
|
result = true; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw new NotImplementedException("房间中已经存在该用户!"); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw new NotImplementedException("房间信息有误!"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public async Task<bool> LeaveRoom(string roomId, string userId) |
||||||
|
{ |
||||||
|
bool result = false; |
||||||
|
await Task.Run(() => |
||||||
|
{ |
||||||
|
var room = roomManager.GetRoom(roomId); |
||||||
|
if (room != null) |
||||||
|
{ |
||||||
|
var user = room.Users.FirstOrDefault(u => u.UserId == userId); |
||||||
|
if (user != null) |
||||||
|
{ |
||||||
|
room.Users.Remove(user); |
||||||
|
if (room.Users.Count == 0) |
||||||
|
{ |
||||||
|
//TODO:保持空房间xx分钟 |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw new NotImplementedException("用户信息有误!"); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw new NotImplementedException("房间信息有误!"); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
public async Task RoomSendMessage(string RoomId, string Message) |
||||||
|
{ |
||||||
|
await Clients.Group(RoomId).SendAsync(Message); |
||||||
|
//TODO:保存数据 |
||||||
|
} |
||||||
|
|
||||||
|
public async Task SendMessage(string user, string Message) |
||||||
|
{ |
||||||
|
await Clients.All.SendAsync(Message); |
||||||
|
//TODO:保存数据 |
||||||
|
} |
||||||
|
|
||||||
|
public override async Task OnConnectedAsync() |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
var userId = Context.UserIdentifier; |
||||||
|
var userName = Context.GetNameOfCurrentUser(); |
||||||
|
FireDeductionUser? user = roomManager.GetUser(userId!); |
||||||
|
|
||||||
|
if (user != null) |
||||||
|
{ |
||||||
|
user.Online = true; |
||||||
|
var room = roomManager.GetRoomByUserId(user.UserId); |
||||||
|
if (room != null) |
||||||
|
{ |
||||||
|
//断线重连 |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
user = new FireDeductionUser(); |
||||||
|
user.ConnectionId = Context.ConnectionId; |
||||||
|
user.UserId = userId!; |
||||||
|
user.UserName = userName!; |
||||||
|
} |
||||||
|
_logger.LogInformation("[{userId}][{name}] connected", userId, userName); |
||||||
|
|
||||||
|
await base.OnConnectedAsync(); |
||||||
|
} |
||||||
|
catch (Exception) |
||||||
|
{ |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override async Task OnDisconnectedAsync(Exception? exception) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
var userId = Context.UserIdentifier; |
||||||
|
var userName = Context.User?.FindFirstValue(JwtClaimTypes.Name); |
||||||
|
if (userId == null) _logger.LogError("无效的 userId: [{userId}]!", userId); |
||||||
|
|
||||||
|
if (userId != null) |
||||||
|
{ |
||||||
|
var user = roomManager.GetUser(userId!); |
||||||
|
if (user != null) |
||||||
|
{ |
||||||
|
user.Online = false; |
||||||
|
var room = roomManager.GetRoomByUserId(user.UserId); |
||||||
|
if (room != null) |
||||||
|
{ |
||||||
|
//断线 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
await base.OnDisconnectedAsync(exception); |
||||||
|
_logger.LogInformation("[{userId}][{name}] 断开了连接", userId, userName); |
||||||
|
} |
||||||
|
catch (Exception) |
||||||
|
{ |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,21 +0,0 @@ |
|||||||
namespace AX.WebDrillServer.Models |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 房间表 |
|
||||||
/// </summary> |
|
||||||
public class Room : EntityBase |
|
||||||
{ |
|
||||||
/// <summary> |
|
||||||
/// 密码 |
|
||||||
/// </summary> |
|
||||||
public string? Password { get; set; } |
|
||||||
/// <summary> |
|
||||||
/// 所属 |
|
||||||
/// </summary> |
|
||||||
public User? Owner { get; set; } |
|
||||||
/// <summary> |
|
||||||
/// 用户 |
|
||||||
/// </summary> |
|
||||||
public ICollection<User>? Users { get; set; } |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,35 @@ |
|||||||
|
using Org.BouncyCastle.Asn1.X509; |
||||||
|
|
||||||
|
namespace AX.WebDrillServer.Services.FireDeductionHub |
||||||
|
{ |
||||||
|
public enum RoomState |
||||||
|
{ |
||||||
|
准备 = 0, |
||||||
|
进行中, |
||||||
|
结束 |
||||||
|
} |
||||||
|
/// <summary> |
||||||
|
/// 沙盘推演房间 |
||||||
|
/// </summary> |
||||||
|
public class FireDeductionRoom |
||||||
|
{ |
||||||
|
public string RoomId { get; set; } = null!; |
||||||
|
public string RoomName { get; set; } = null!; |
||||||
|
/// <summary> |
||||||
|
/// 房间密码 |
||||||
|
/// </summary> |
||||||
|
public string? Password; |
||||||
|
public RoomState State { get; set; } = RoomState.准备; |
||||||
|
/// <summary> |
||||||
|
/// 房间最大人数 |
||||||
|
/// </summary> |
||||||
|
public int MaxPersons = 100; |
||||||
|
/// <summary> |
||||||
|
/// 房间所属,默认是创建者 |
||||||
|
/// </summary> |
||||||
|
public string Owner { get; set; } = null!; |
||||||
|
public List<FireDeductionUser> Users { get; set; } = new List<FireDeductionUser>(); |
||||||
|
public Dictionary<DateTime, string>? FrameData { get; set; } |
||||||
|
public Dictionary<DateTime, string>? EventData { get; set; } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
namespace AX.WebDrillServer.Services.FireDeductionHub |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 沙盘推演用户 |
||||||
|
/// </summary> |
||||||
|
public class FireDeductionUser |
||||||
|
{ |
||||||
|
public string UserId { get; set; } = null!; |
||||||
|
public string UserName { get; set; } = null!; |
||||||
|
public bool Online { get; set; } = true; |
||||||
|
public bool Left { get; set; } |
||||||
|
public string ConnectionId { get; set; } = null!; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
namespace AX.WebDrillServer.Services.FireDeductionHub |
||||||
|
{ |
||||||
|
public class RoomCreateDto |
||||||
|
{ |
||||||
|
public string UserId { get; set; } = null!; |
||||||
|
public string? RoomPassword { get; set; } |
||||||
|
public string RoomName { get; set; } = null!; |
||||||
|
public int MaxPerson { get; set; } = 20; |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
namespace AX.WebDrillServer.Services.FireDeductionHub |
||||||
|
{ |
||||||
|
public class RoomManager |
||||||
|
{ |
||||||
|
|
||||||
|
private List<FireDeductionRoom> fireDeductionRooms = new List<FireDeductionRoom>(); |
||||||
|
private List<FireDeductionUser> fireDeductionUsers = new List<FireDeductionUser>(); |
||||||
|
|
||||||
|
|
||||||
|
public FireDeductionRoom? GetRoom(string roomId) |
||||||
|
{ |
||||||
|
lock (this) |
||||||
|
{ |
||||||
|
return fireDeductionRooms.Where(r => r.RoomId == roomId).SingleOrDefault(); |
||||||
|
} |
||||||
|
} |
||||||
|
public FireDeductionUser? GetUser(string userId) |
||||||
|
{ |
||||||
|
lock (this) |
||||||
|
{ |
||||||
|
return fireDeductionUsers.Where(r => r.UserId == userId).SingleOrDefault(); |
||||||
|
} |
||||||
|
} |
||||||
|
public FireDeductionRoom? GetRoomByUserId(string userId) |
||||||
|
{ |
||||||
|
lock (this) |
||||||
|
{ |
||||||
|
return fireDeductionRooms.Where(r => r.Users.Where(u => u.UserId == userId).SingleOrDefault() != null).SingleOrDefault(); |
||||||
|
} |
||||||
|
} |
||||||
|
public void AddRoom(FireDeductionRoom room) |
||||||
|
{ |
||||||
|
lock (this) |
||||||
|
{ |
||||||
|
if (!fireDeductionRooms.Contains(room)) |
||||||
|
{ |
||||||
|
fireDeductionRooms.Add(room); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
public void RemoveRoom(string roomId) |
||||||
|
{ |
||||||
|
lock (this) |
||||||
|
{ |
||||||
|
for (int i = 0; i < fireDeductionRooms.Count; i++) |
||||||
|
{ |
||||||
|
if (fireDeductionRooms[i].RoomId == roomId) |
||||||
|
{ |
||||||
|
fireDeductionRooms.RemoveAt(i); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void AddUser(FireDeductionUser user) |
||||||
|
{ |
||||||
|
lock (this) |
||||||
|
{ |
||||||
|
if (!fireDeductionUsers.Contains(user)) |
||||||
|
{ |
||||||
|
fireDeductionUsers.Add(user); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
public void RemoveUser(string userId) |
||||||
|
{ |
||||||
|
lock (this) |
||||||
|
{ |
||||||
|
for (int i = 0; i < fireDeductionUsers.Count; i++) |
||||||
|
{ |
||||||
|
if (fireDeductionUsers[i].UserId == userId) |
||||||
|
{ |
||||||
|
fireDeductionUsers.RemoveAt(i); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue