using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using SqlSugar; using RainOpsMini.Helpers; using RainOpsMini.Models; using RainOpsMini.Helpers.SquadGameLog; using System.Collections.Generic; using System.Linq; using System; using RainOpsMini.Models; namespace RainOpsMini.Apis { public static class LogApi { public static void MapLogApis(this IEndpointRouteBuilder app) { // API: 获取游戏匹配日志 // 用于日志查询页面,支持分页和搜索 app.MapGet("/api/logs/game-match", (string? type, string? search, int? page, int? pageSize, HttpContext ctx) => { if (!ctx.User.HasClaim("Permission", "logs") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized(); int p = page ?? 1; int ps = pageSize ?? 20; if (ps > 100) ps = 100; // 限制最大页大小 int total; var logs = LogStorage.Instance.GetLogs(type, search, p, ps, out total); return Results.Ok(new { total = total, page = p, pageSize = ps, items = logs }); }); // API: 获取日志统计信息 // 用于仪表盘展示各类日志的数量 app.MapGet("/api/logs/stats", (HttpContext ctx) => { if (!ctx.User.HasClaim("Permission", "analytics") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized(); var stats = LogStorage.Instance.GetLogStats(); return Results.Json(stats); }); // API: 获取用户登录统计 // 用于分析用户活跃度 app.MapGet("/api/analytics/user-stats", (HttpContext ctx) => { if (!ctx.User.HasClaim("Permission", "analytics") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized(); using (var db = DbHelper.GetInstance()) { var stats = db.Queryable() .GroupBy(x => x.Username) .Select(x => new { Username = x.Username, Count = SqlFunc.AggregateCount(x.Id), LastLogin = SqlFunc.AggregateMax(x.LoginTime) }) .ToList(); // 按登录次数降序排序 var tableData = stats.OrderByDescending(x => x.Count).ToList(); return Results.Ok(new { tableData }); } }); // API: 获取对局历史列表 // 分页查询历史对局记录 app.MapGet("/api/matches", (int? page, int? pageSize, HttpContext ctx) => { if (!ctx.User.HasClaim("Permission", "logs") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized(); int p = page ?? 1; int ps = pageSize ?? 20; try { using (var db = DbHelper.GetInstance()) { var total = 0; var query = db.Queryable() .GroupBy(x => new { x.MatchId, x.MatchDate, x.MapName }) .Select(x => new { x.MatchId, x.MatchDate, x.MapName, PlayerCount = SqlFunc.AggregateCount(x.Id) }) .MergeTable(); // Merge result for pagination var list = query.OrderByDescending(x => x.MatchDate) .ToPageList(p, ps, ref total); return Results.Ok(new { total, page = p, pageSize = ps, items = list }); } } catch (Exception ex) { return Results.BadRequest(new { error = ex.Message }); } }); // API: 获取单场对局详情 // 根据 MatchID 查询该场对局的所有玩家数据 app.MapGet("/api/matches/{matchId}", (string matchId, HttpContext ctx) => { if (!ctx.User.HasClaim("Permission", "logs") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized(); if (string.IsNullOrEmpty(matchId)) return Results.BadRequest(); try { using (var db = DbHelper.GetInstance()) { var stats = db.Queryable() .Where(x => x.MatchId == matchId) .OrderByDescending(x => x.Kills) // Order by Kills by default .ToList(); return Results.Ok(stats); } } catch (Exception ex) { return Results.BadRequest(new { error = ex.Message }); } }); // API: 玩家活跃度分析 app.MapGet("/api/analytics/players", (string? start, string? end, int? days, HttpContext ctx) => { if (!ctx.User.HasClaim("Permission", "analytics") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized(); DateTime startDate; DateTime endDate = DateTime.Now; if (!string.IsNullOrEmpty(start) && DateTime.TryParse(start, out var s)) { startDate = s; } else { int d = days ?? 7; startDate = DateTime.Now.AddDays(-d); } if (!string.IsNullOrEmpty(end) && DateTime.TryParse(end, out var e)) { endDate = e.AddDays(1); // Include the end date } using (var db = DbHelper.GetInstance()) { var data = db.Queryable() .Where(x => x.Timestamp >= startDate && x.Timestamp < endDate) .OrderBy(x => x.Timestamp) .Select(x => new { x.Timestamp, x.PlayerCount, x.MapName }) .ToList(); return Results.Json(data); } }); // API: 地图热度分析 app.MapGet("/api/analytics/maps", (string? start, string? end, int? days, HttpContext ctx) => { if (!ctx.User.HasClaim("Permission", "analytics") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized(); DateTime startDate; DateTime endDate = DateTime.Now; if (!string.IsNullOrEmpty(start) && DateTime.TryParse(start, out var s)) { startDate = s; } else { int d = days ?? 7; startDate = DateTime.Now.AddDays(-d); } if (!string.IsNullOrEmpty(end) && DateTime.TryParse(end, out var e)) { endDate = e.AddDays(1); // Include the end date } using (var db = DbHelper.GetInstance()) { var data = db.Queryable() .Where(x => x.Timestamp >= startDate && x.Timestamp < endDate) .GroupBy(x => x.MapName) .Select(x => new { MapName = x.MapName, Count = SqlFunc.AggregateCount(x.Id) }) .ToList() .OrderByDescending(x => x.Count) .ToList(); return Results.Json(data); } }); // API: 获取 Tickrate 历史 // 查询服务器 Tickrate、玩家数量等历史数据 app.MapGet("/api/analytics/tickrate", (string? start, string? end, int? days, HttpContext ctx) => { if (ctx.User.Identity?.IsAuthenticated != true) return Results.Unauthorized(); DateTime startTime; DateTime endTime = DateTime.Now; if (!string.IsNullOrEmpty(start) && DateTime.TryParse(start, out var s)) { startTime = s; } else { int queryDays = days ?? 3; startTime = DateTime.Now.AddDays(-queryDays); } if (!string.IsNullOrEmpty(end) && DateTime.TryParse(end, out var e)) { endTime = e.AddDays(1); // Include the end date } using (var db = DbHelper.GetInstance()) { var data = db.Queryable() .Where(x => x.LogTime >= startTime && x.LogTime < endTime) .OrderBy(x => x.LogTime) .Select(x => new { LogTime = x.LogTime, TickRate = x.TickRate, PlayerCount = x.PlayerCount, MatchTime = x.MatchTime, MapName = x.MapName }) .ToList(); return Results.Ok(data); } }); } } }