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.
208 lines
7.9 KiB
208 lines
7.9 KiB
2 years ago
|
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
|
||
|
};
|
||
|
}
|
||
|
}
|