Оптимизирована загрузка имен игроков с помощью пакетного запроса и переработан интерфейс работы окна MentorHelp.
This commit is contained in:
parent
30ea82a02b
commit
4670886c44
4 changed files with 99 additions and 20 deletions
|
|
@ -1,8 +1,9 @@
|
||||||
<DefaultWindow xmlns="https://spacestation14.io"
|
<DefaultWindow
|
||||||
xmlns:mentorHelp="clr-namespace:Content.Client._Sunrise.MentorHelp"
|
HeaderClass="windowHeaderHelp"
|
||||||
SetSize="900 700"
|
SetSize="1100 700"
|
||||||
HeaderClass="windowHeaderHelp"
|
Title="{Loc 'mentor-help-window-title'}"
|
||||||
TitleClass="windowTitleHelp"
|
TitleClass="windowTitleHelp"
|
||||||
Title="{Loc 'mentor-help-window-title'}" >
|
xmlns="https://spacestation14.io"
|
||||||
<mentorHelp:MentorHelpControl Name="MentorHelp" Access="Public"/>
|
xmlns:mentorHelp="clr-namespace:Content.Client._Sunrise.MentorHelp">
|
||||||
|
<mentorHelp:MentorHelpControl Access="Public" Name="MentorHelp" />
|
||||||
</DefaultWindow>
|
</DefaultWindow>
|
||||||
|
|
|
||||||
|
|
@ -700,6 +700,40 @@ namespace Content.Server.Database
|
||||||
return record == null ? null : MakePlayerRecord(record);
|
return record == null ? null : MakePlayerRecord(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Dictionary<Guid, string>> GetPlayerNamesBatchAsync(IEnumerable<Guid> userIds, CancellationToken cancel)
|
||||||
|
{
|
||||||
|
await using var db = await GetDb();
|
||||||
|
|
||||||
|
var userIdList = userIds.ToList();
|
||||||
|
if (userIdList.Count == 0)
|
||||||
|
return new Dictionary<Guid, string>();
|
||||||
|
|
||||||
|
var records = await db.DbContext.Player
|
||||||
|
.Where(p => userIdList.Contains(p.UserId))
|
||||||
|
.Select(p => new { p.UserId, p.LastSeenUserName })
|
||||||
|
.ToListAsync(cancel);
|
||||||
|
|
||||||
|
var result = new Dictionary<Guid, string>();
|
||||||
|
foreach (var record in records)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(record.LastSeenUserName))
|
||||||
|
{
|
||||||
|
result[record.UserId] = record.LastSeenUserName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill missing names with "Unknown"
|
||||||
|
foreach (var userId in userIdList)
|
||||||
|
{
|
||||||
|
if (!result.ContainsKey(userId))
|
||||||
|
{
|
||||||
|
result[userId] = "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
protected async Task<bool> PlayerRecordExists(DbGuard db, NetUserId userId)
|
protected async Task<bool> PlayerRecordExists(DbGuard db, NetUserId userId)
|
||||||
{
|
{
|
||||||
return await db.DbContext.Player.AnyAsync(p => p.UserId == userId);
|
return await db.DbContext.Player.AnyAsync(p => p.UserId == userId);
|
||||||
|
|
@ -1898,41 +1932,37 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||||
public async Task<List<MentorHelpTicket>> GetMentorHelpTicketsByPlayerAsync(Guid playerId)
|
public async Task<List<MentorHelpTicket>> GetMentorHelpTicketsByPlayerAsync(Guid playerId)
|
||||||
{
|
{
|
||||||
await using var db = await GetDb();
|
await using var db = await GetDb();
|
||||||
return (await db.DbContext.MentorHelpTickets
|
return await db.DbContext.MentorHelpTickets
|
||||||
.Where(t => t.PlayerId == playerId)
|
.Where(t => t.PlayerId == playerId)
|
||||||
.ToListAsync())
|
|
||||||
.OrderByDescending(t => t.CreatedAt)
|
.OrderByDescending(t => t.CreatedAt)
|
||||||
.ToList();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<MentorHelpTicket>> GetOpenMentorHelpTicketsAsync()
|
public async Task<List<MentorHelpTicket>> GetOpenMentorHelpTicketsAsync()
|
||||||
{
|
{
|
||||||
await using var db = await GetDb();
|
await using var db = await GetDb();
|
||||||
return (await db.DbContext.MentorHelpTickets
|
return await db.DbContext.MentorHelpTickets
|
||||||
.Where(t => t.Status != MentorHelpTicketStatus.Closed)
|
.Where(t => t.Status != MentorHelpTicketStatus.Closed)
|
||||||
.ToListAsync())
|
|
||||||
.OrderByDescending(t => t.UpdatedAt)
|
.OrderByDescending(t => t.UpdatedAt)
|
||||||
.ToList();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<MentorHelpTicket>> GetAssignedMentorHelpTicketsAsync(Guid mentorId)
|
public async Task<List<MentorHelpTicket>> GetAssignedMentorHelpTicketsAsync(Guid mentorId)
|
||||||
{
|
{
|
||||||
await using var db = await GetDb();
|
await using var db = await GetDb();
|
||||||
return (await db.DbContext.MentorHelpTickets
|
return await db.DbContext.MentorHelpTickets
|
||||||
.Where(t => t.AssignedToUserId == mentorId && t.Status != MentorHelpTicketStatus.Closed)
|
.Where(t => t.AssignedToUserId == mentorId && t.Status != MentorHelpTicketStatus.Closed)
|
||||||
.ToListAsync())
|
|
||||||
.OrderByDescending(t => t.UpdatedAt)
|
.OrderByDescending(t => t.UpdatedAt)
|
||||||
.ToList();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<MentorHelpTicket>> GetClosedMentorHelpTicketsAsync()
|
public async Task<List<MentorHelpTicket>> GetClosedMentorHelpTicketsAsync()
|
||||||
{
|
{
|
||||||
await using var db = await GetDb();
|
await using var db = await GetDb();
|
||||||
return (await db.DbContext.MentorHelpTickets
|
return await db.DbContext.MentorHelpTickets
|
||||||
.Where(t => t.Status == MentorHelpTicketStatus.Closed)
|
.Where(t => t.Status == MentorHelpTicketStatus.Closed)
|
||||||
.ToListAsync())
|
|
||||||
.OrderByDescending(t => t.UpdatedAt)
|
.OrderByDescending(t => t.UpdatedAt)
|
||||||
.ToList();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddMentorHelpMessageAsync(MentorHelpMessage message)
|
public async Task AddMentorHelpMessageAsync(MentorHelpMessage message)
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,7 @@ namespace Content.Server.Database
|
||||||
ImmutableTypedHwid? hwId);
|
ImmutableTypedHwid? hwId);
|
||||||
Task<PlayerRecord?> GetPlayerRecordByUserName(string userName, CancellationToken cancel = default);
|
Task<PlayerRecord?> GetPlayerRecordByUserName(string userName, CancellationToken cancel = default);
|
||||||
Task<PlayerRecord?> GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel = default);
|
Task<PlayerRecord?> GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel = default);
|
||||||
|
Task<Dictionary<Guid, string>> GetPlayerNamesBatchAsync(IEnumerable<Guid> userIds, CancellationToken cancel = default);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Connection Logs
|
#region Connection Logs
|
||||||
|
|
@ -693,6 +694,12 @@ namespace Content.Server.Database
|
||||||
return RunDbCommand(() => _db.GetPlayerRecordByUserId(userId, cancel));
|
return RunDbCommand(() => _db.GetPlayerRecordByUserId(userId, cancel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<Dictionary<Guid, string>> GetPlayerNamesBatchAsync(IEnumerable<Guid> userIds, CancellationToken cancel = default)
|
||||||
|
{
|
||||||
|
DbReadOpsMetric.Inc();
|
||||||
|
return RunDbCommand(() => _db.GetPlayerNamesBatchAsync(userIds, cancel));
|
||||||
|
}
|
||||||
|
|
||||||
public Task<int> AddConnectionLogAsync(
|
public Task<int> AddConnectionLogAsync(
|
||||||
NetUserId userId,
|
NetUserId userId,
|
||||||
string userName,
|
string userName,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
|
|
@ -362,10 +363,25 @@ namespace Content.Server._Sunrise.MentorHelp
|
||||||
tickets = openTickets.Concat(closedTickets).ToList();
|
tickets = openTickets.Concat(closedTickets).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect all unique user IDs for batch loading
|
||||||
|
var userIds = new HashSet<Guid>();
|
||||||
|
foreach (var ticket in tickets)
|
||||||
|
{
|
||||||
|
userIds.Add(ticket.PlayerId);
|
||||||
|
if (ticket.AssignedToUserId.HasValue)
|
||||||
|
userIds.Add(ticket.AssignedToUserId.Value);
|
||||||
|
if (ticket.ClosedByUserId.HasValue)
|
||||||
|
userIds.Add(ticket.ClosedByUserId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all player names in one batch query
|
||||||
|
var playerNames = await _dbManager.GetPlayerNamesBatchAsync(userIds);
|
||||||
|
|
||||||
|
// Convert tickets to data using cached names
|
||||||
var ticketDataList = new List<MentorHelpTicketData>();
|
var ticketDataList = new List<MentorHelpTicketData>();
|
||||||
foreach (var ticket in tickets)
|
foreach (var ticket in tickets)
|
||||||
{
|
{
|
||||||
ticketDataList.Add(await ConvertToTicketDataAsync(ticket));
|
ticketDataList.Add(ConvertToTicketData(ticket, playerNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
RaiseNetworkEvent(new MentorHelpTicketsListMessage(ticketDataList), session.Channel);
|
RaiseNetworkEvent(new MentorHelpTicketsListMessage(ticketDataList), session.Channel);
|
||||||
|
|
@ -527,6 +543,31 @@ namespace Content.Server._Sunrise.MentorHelp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private MentorHelpTicketData ConvertToTicketData(MentorHelpTicket ticket, Dictionary<Guid, string> playerNames)
|
||||||
|
{
|
||||||
|
playerNames.TryGetValue(ticket.PlayerId, out var playerName);
|
||||||
|
var assignedToName = ticket.AssignedToUserId.HasValue && playerNames.TryGetValue(ticket.AssignedToUserId.Value, out var assignedName) ? assignedName : null;
|
||||||
|
var closedByName = ticket.ClosedByUserId.HasValue && playerNames.TryGetValue(ticket.ClosedByUserId.Value, out var closedName) ? closedName : null;
|
||||||
|
|
||||||
|
return new MentorHelpTicketData
|
||||||
|
{
|
||||||
|
Id = ticket.Id,
|
||||||
|
PlayerId = new NetUserId(ticket.PlayerId),
|
||||||
|
PlayerName = playerName ?? "Unknown",
|
||||||
|
AssignedToUserId = ticket.AssignedToUserId.HasValue ? new NetUserId(ticket.AssignedToUserId.Value) : null,
|
||||||
|
AssignedToName = assignedToName,
|
||||||
|
Subject = ticket.Subject,
|
||||||
|
Status = ticket.Status,
|
||||||
|
CreatedAt = ticket.CreatedAt.DateTime,
|
||||||
|
UpdatedAt = ticket.UpdatedAt.DateTime,
|
||||||
|
ClosedAt = ticket.ClosedAt?.DateTime,
|
||||||
|
ClosedByUserId = ticket.ClosedByUserId.HasValue ? new NetUserId(ticket.ClosedByUserId.Value) : null,
|
||||||
|
ClosedByName = closedByName,
|
||||||
|
RoundId = ticket.RoundId,
|
||||||
|
HasUnreadMessages = false // Would need to implement read tracking
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<MentorHelpTicketData> ConvertToTicketDataAsync(MentorHelpTicket ticket)
|
private async Task<MentorHelpTicketData> ConvertToTicketDataAsync(MentorHelpTicket ticket)
|
||||||
{
|
{
|
||||||
var playerName = await GetPlayerNameAsync(ticket.PlayerId);
|
var playerName = await GetPlayerNameAsync(ticket.PlayerId);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue