You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
7.9 KiB
207 lines
7.9 KiB
using AX.FireTrainingSys.DTOs; |
|
using AX.FireTrainingSys.Models; |
|
using Microsoft.AspNetCore.Authorization; |
|
using Microsoft.AspNetCore.Http; |
|
using Microsoft.AspNetCore.Mvc; |
|
using Microsoft.EntityFrameworkCore; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Security.Claims; |
|
using System.Threading.Tasks; |
|
|
|
namespace AX.FireTrainingSys.Controllers |
|
{ |
|
/// <summary> |
|
/// 学习记录控制器。 |
|
/// </summary> |
|
[Produces("application/json")] |
|
[Route("api/[controller]")] |
|
[ApiVersion("1.0")] |
|
[ApiController] |
|
public class StudyRecordsController : ControllerBase |
|
{ |
|
private readonly DriveDbContext dbContext; |
|
|
|
public StudyRecordsController(DriveDbContext dbContext) |
|
{ |
|
this.dbContext = dbContext; |
|
} |
|
|
|
/// <summary> |
|
/// 获得所有学习记录。 |
|
/// </summary> |
|
/// <param name="options">查询条件</param> |
|
/// <returns></returns> |
|
[Authorize(Roles = nameof(RoleType.Admin))] |
|
[ProducesResponseType(StatusCodes.Status400BadRequest)] |
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)] |
|
[ProducesResponseType(StatusCodes.Status403Forbidden)] |
|
[ProducesResponseType(StatusCodes.Status200OK)] |
|
[HttpGet] |
|
public async Task<ActionResult<Page<StudyRecordInfo>>> Get([FromQuery] StudyRecordQueryOptions options) |
|
{ |
|
var rangeEnd = DateTimeOffset.Now; |
|
var rangeStart = rangeEnd.AddYears(-1); |
|
|
|
if (string.IsNullOrEmpty(options.Name)) |
|
return BadRequest($"{nameof(options.Name)} can not be empty."); |
|
|
|
if (options.StartTime != default && (options.StartTime < rangeStart || options.StartTime > rangeEnd)) |
|
return BadRequest($"{nameof(options.StartTime)} is out of range."); |
|
|
|
if (options.EndTime != default && (options.EndTime < rangeStart || options.EndTime > rangeEnd)) |
|
return BadRequest($"{nameof(options.EndTime)} is out of range."); |
|
|
|
if (options.EndTime == default) |
|
options.EndTime = rangeEnd; |
|
|
|
if (options.StartTime == default) |
|
options.StartTime = options.EndTime.Value.AddMonths(-1); |
|
|
|
if (options.PageNumber == default) |
|
options.PageNumber = 1; |
|
|
|
if (options.PageSize == default) |
|
options.PageSize = 100; |
|
|
|
var query = dbContext.StudyRecords |
|
.Include(e => e.User) |
|
.AsNoTracking(); |
|
|
|
query = query.Where(e => e.User.Name == options!.Name); |
|
query = query.Where(e => e.CreationTime >= options.StartTime!.Value.UtcDateTime); |
|
query = query.Where(e => e.CreationTime <= options.EndTime!.Value.UtcDateTime); |
|
|
|
if (!string.IsNullOrEmpty(options.PostName)) |
|
query = query.Where(e => e.PostName == options.PostName); |
|
|
|
if (!string.IsNullOrEmpty(options.Catalog)) |
|
query = query.Where(e => e.Catalog == options.Catalog); |
|
|
|
var count = await query.CountAsync(); |
|
|
|
query = query.OrderByDescending(e => e.CreationTime); |
|
|
|
if (options.PageNumber > 1) |
|
query = query.Skip((options.PageNumber.Value - 1) * options.PageSize.Value); |
|
|
|
query = query.Take(options.PageSize.Value); |
|
|
|
var items = await query.Select(e => e.ToDTO()) |
|
.ToListAsync(); |
|
|
|
var page = new Page<StudyRecordInfo> |
|
{ |
|
PageNumber = (int)options.PageNumber, |
|
PageSize = (int)options.PageSize, |
|
TotalPages = (int)Math.Ceiling((double)count / (int)options.PageSize), |
|
TotalCount = count, |
|
Items = items |
|
}; |
|
|
|
return Ok(page); |
|
} |
|
|
|
/// <summary> |
|
/// 统计学习记录。 |
|
/// </summary> |
|
/// <param name="options">查询条件</param> |
|
/// <returns></returns> |
|
[Authorize(Roles = nameof(RoleType.Admin))] |
|
[ProducesResponseType(StatusCodes.Status400BadRequest)] |
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)] |
|
[ProducesResponseType(StatusCodes.Status403Forbidden)] |
|
[ProducesResponseType(StatusCodes.Status200OK)] |
|
[HttpGet("[action]")] |
|
public async Task<ActionResult<List<StudyStatisticsInfo>>> Statistics([FromQuery] StudyStatisticsQueryOptions options) |
|
{ |
|
var rangeEnd = DateTimeOffset.Now; |
|
var rangeStart = rangeEnd.AddYears(-1); |
|
|
|
if (string.IsNullOrEmpty(options.Name)) |
|
return BadRequest($"{nameof(options.Name)} can not be empty."); |
|
|
|
if (options.StartTime != default && (options.StartTime < rangeStart || options.StartTime > rangeEnd)) |
|
return BadRequest($"{nameof(options.StartTime)} is out of range."); |
|
|
|
if (options.EndTime != default && (options.EndTime < rangeStart || options.EndTime > rangeEnd)) |
|
return BadRequest($"{nameof(options.EndTime)} is out of range."); |
|
|
|
if (options.EndTime == default) |
|
options.EndTime = rangeEnd; |
|
|
|
if (options.StartTime == default) |
|
options.StartTime = options.EndTime.Value.AddMonths(-1); |
|
|
|
var query = dbContext.StudyRecords |
|
.Include(e => e.User) |
|
.AsNoTracking(); |
|
|
|
query = query.Where(e => e.User.Name == options!.Name); |
|
query = query.Where(e => e.CreationTime >= options.StartTime!.Value.UtcDateTime); |
|
query = query.Where(e => e.CreationTime <= options.EndTime!.Value.UtcDateTime); |
|
|
|
var result = await query.GroupBy(e => new { e.PostName, e.Catalog }) |
|
.Select(g => new StudyStatisticsInfo |
|
{ |
|
PostName = g.Key.PostName, |
|
Catalog = g.Key.Catalog, |
|
Count = g.Count() |
|
}) |
|
.OrderBy(e => e.PostName) |
|
.ThenBy(e => e.Catalog) |
|
.ToListAsync(); |
|
|
|
return Ok(result); |
|
} |
|
|
|
/// <summary> |
|
/// 创建学习记录。 |
|
/// </summary> |
|
/// <param name="info">用户信息</param> |
|
/// <returns></returns> |
|
[Authorize(Roles = "Profile")] |
|
[ProducesResponseType(StatusCodes.Status400BadRequest)] |
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)] |
|
[ProducesResponseType(StatusCodes.Status403Forbidden)] |
|
[ProducesResponseType(StatusCodes.Status201Created)] |
|
[HttpPost] |
|
public async Task<ActionResult<StudyRecordInfo>> Post([FromBody] StudyRecordInfo info) |
|
{ |
|
var userid = HttpContext.User.FindFirstValue(JwtClaimTypes.Subject); |
|
var model = info.ToModel(userid); |
|
|
|
dbContext.StudyRecords.Add(model); |
|
|
|
await dbContext.SaveChangesAsync(); |
|
|
|
info.Id = model.Id; |
|
info.CreationTime = model.CreationTime.ToLocalTime(); |
|
|
|
return CreatedAtAction(nameof(Post), info); |
|
} |
|
} |
|
|
|
internal static partial class Extensions |
|
{ |
|
public static StudyRecord ToModel(this StudyRecordInfo info, string userid) => new StudyRecord |
|
{ |
|
Operation = info.Operation, |
|
PostName = info.PostName, |
|
Catalog = info.Catalog, |
|
Target = info.Target, |
|
UserId = userid |
|
}; |
|
|
|
public static StudyRecordInfo ToDTO(this StudyRecord model) => new StudyRecordInfo |
|
{ |
|
Id = model.Id, |
|
CreationTime = model.CreationTime.ToLocalTime(), |
|
Operation = model.Operation, |
|
PostName = model.PostName, |
|
Catalog = model.Catalog, |
|
Target = model.Target |
|
}; |
|
} |
|
}
|
|
|