主要变更:
新增统一缓存封装:[AppCache.cs (line 12)](/E:/jiaowu/src/Jiaowu.Api/Infrastructure/Caching/AppCache.cs:12) 接入 HybridCache 和可选 Redis:[Program.cs (line 153)](/E:/jiaowu/src/Jiaowu.Api/Program.cs:153) 缓存学生激活选项、基础数据、公开课表和课表选项。 个人课表、选课容量、成绩、权限、通知和任务状态保持实时查询。 基础数据、课程、教师、教学任务、作息、考试和课表发布后自动失效相关缓存。 新增 /health/cache,Redis 故障不影响 /health/ready。 Compose 增加 256MB、allkeys-lfu、无持久化的 redis:8.8-alpine 服务;该镜像标签已由 Docker 官方镜像仓库核对。 更新 [.env.example (line 1)](/E:/jiaowu/.env.example:1) 和 [README.md (line 190)](/E:/jiaowu/README.md:190) 部署说明。
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Security.Claims;
|
||||
using Jiaowu.Api.Domain.Academic;
|
||||
using Jiaowu.Api.Domain.Identity;
|
||||
using Jiaowu.Api.Infrastructure.Auth;
|
||||
using Jiaowu.Api.Infrastructure.Caching;
|
||||
using Jiaowu.Api.Infrastructure.Persistence;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
@@ -17,35 +18,51 @@ namespace Jiaowu.Api.Controllers;
|
||||
public sealed class AuthController(
|
||||
AppDbContext db,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
ITokenService tokenService) : ControllerBase
|
||||
ITokenService tokenService,
|
||||
IAppCache cache) : ControllerBase
|
||||
{
|
||||
[AllowAnonymous]
|
||||
[HttpGet("activation-options")]
|
||||
public async Task<ActionResult> GetActivationOptions(CancellationToken cancellationToken)
|
||||
{
|
||||
var colleges = await db.Colleges.AsNoTracking()
|
||||
.Where(x => x.IsEnabled)
|
||||
.OrderBy(x => x.Code)
|
||||
.Select(x => new { x.Id, x.Code, x.Name })
|
||||
.ToListAsync(cancellationToken);
|
||||
var majors = await db.Majors.AsNoTracking()
|
||||
.Where(x => x.IsEnabled && x.College!.IsEnabled)
|
||||
.OrderBy(x => x.Code)
|
||||
.Select(x => new { x.Id, x.Code, x.Name, x.CollegeId })
|
||||
.ToListAsync(cancellationToken);
|
||||
var classes = await db.AdministrativeClasses.AsNoTracking()
|
||||
.Where(x => x.IsEnabled && x.Major!.IsEnabled && x.Major.College!.IsEnabled)
|
||||
.OrderByDescending(x => x.Grade)
|
||||
.ThenBy(x => x.Code)
|
||||
.Select(x => new { x.Id, x.Code, x.Name, x.Grade, x.MajorId })
|
||||
.ToListAsync(cancellationToken);
|
||||
return Ok(new
|
||||
{
|
||||
Colleges = colleges,
|
||||
Majors = majors,
|
||||
Classes = classes,
|
||||
Grades = classes.Select(x => x.Grade).Distinct().OrderByDescending(x => x)
|
||||
});
|
||||
var result = await cache.GetOrCreateAsync(
|
||||
AppCacheKeys.ActivationOptions,
|
||||
async token =>
|
||||
{
|
||||
var colleges = await db.Colleges.AsNoTracking()
|
||||
.Where(x => x.IsEnabled)
|
||||
.OrderBy(x => x.Code)
|
||||
.Select(x => new ActivationCollegeOption(x.Id, x.Code, x.Name))
|
||||
.ToListAsync(token);
|
||||
var majors = await db.Majors.AsNoTracking()
|
||||
.Where(x => x.IsEnabled && x.College!.IsEnabled)
|
||||
.OrderBy(x => x.Code)
|
||||
.Select(x => new ActivationMajorOption(
|
||||
x.Id, x.Code, x.Name, x.CollegeId))
|
||||
.ToListAsync(token);
|
||||
var classes = await db.AdministrativeClasses.AsNoTracking()
|
||||
.Where(x =>
|
||||
x.IsEnabled &&
|
||||
x.Major!.IsEnabled &&
|
||||
x.Major.College!.IsEnabled)
|
||||
.OrderByDescending(x => x.Grade)
|
||||
.ThenBy(x => x.Code)
|
||||
.Select(x => new ActivationClassOption(
|
||||
x.Id, x.Code, x.Name, x.Grade, x.MajorId))
|
||||
.ToListAsync(token);
|
||||
return new ActivationOptionsResponse(
|
||||
colleges,
|
||||
majors,
|
||||
classes,
|
||||
classes.Select(x => x.Grade)
|
||||
.Distinct()
|
||||
.OrderByDescending(x => x)
|
||||
.ToList());
|
||||
},
|
||||
AppCacheProfile.ReferenceData,
|
||||
[AppCacheTags.BaseData],
|
||||
cancellationToken);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
@@ -219,3 +236,24 @@ public sealed record CurrentUserResponse(
|
||||
IEnumerable<string> Roles,
|
||||
Guid? CollegeId,
|
||||
string EffectiveDataScope);
|
||||
|
||||
public sealed record ActivationOptionsResponse(
|
||||
IReadOnlyList<ActivationCollegeOption> Colleges,
|
||||
IReadOnlyList<ActivationMajorOption> Majors,
|
||||
IReadOnlyList<ActivationClassOption> Classes,
|
||||
IReadOnlyList<int> Grades);
|
||||
|
||||
public sealed record ActivationCollegeOption(Guid Id, string Code, string Name);
|
||||
|
||||
public sealed record ActivationMajorOption(
|
||||
Guid Id,
|
||||
string Code,
|
||||
string Name,
|
||||
Guid CollegeId);
|
||||
|
||||
public sealed record ActivationClassOption(
|
||||
Guid Id,
|
||||
string Code,
|
||||
string Name,
|
||||
int Grade,
|
||||
Guid MajorId);
|
||||
|
||||
Reference in New Issue
Block a user