Files
squad-rain-ops-mini/Apis/LogApi.cs

251 lines
10 KiB
C#

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<RainOpsMini.Models.UserLoginLog>()
.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<MatchPlayerStats>()
.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<MatchPlayerStats>()
.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<ServerInfoLog>()
.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<ServerInfoLog>()
.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<Log_Tick>()
.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);
}
});
}
}
}