2.3.0-rc2
This commit is contained in:
@@ -1639,13 +1639,25 @@ public sealed class CourseSelectionsController(
|
||||
var students = await LoadTeachingTaskRosterAsync(id, cancellationToken);
|
||||
var bytes = ExcelWorkbookHelper.Create(
|
||||
"教学班名单",
|
||||
["学号", "姓名", "班级", "专业", "进入方式", "选课时间"],
|
||||
[
|
||||
"学号", "姓名", "班级", "专业", "联系电话", "电子邮箱",
|
||||
"微信", "紧急联系人", "与本人关系", "紧急联系电话",
|
||||
"特殊标记", "特殊情况说明", "进入方式", "选课时间"
|
||||
],
|
||||
students.Select(student => new List<object?>
|
||||
{
|
||||
student.StudentNumber,
|
||||
student.Name,
|
||||
student.ClassName,
|
||||
student.MajorName,
|
||||
student.Phone,
|
||||
student.Email,
|
||||
student.WeChat,
|
||||
student.EmergencyContactName,
|
||||
student.EmergencyContactRelationship,
|
||||
student.EmergencyContactPhone,
|
||||
student.SpecialTags,
|
||||
student.SpecialNeeds,
|
||||
student.EnrolledAt.HasValue ? "选课" : "行政班关联",
|
||||
student.EnrolledAt?.ToString("yyyy-MM-dd HH:mm") ?? "-"
|
||||
}).ToList<IReadOnlyList<object?>>());
|
||||
@@ -1754,6 +1766,14 @@ public sealed class CourseSelectionsController(
|
||||
x.Name,
|
||||
x.AdministrativeClass!.Name,
|
||||
x.AdministrativeClass.Major!.Name,
|
||||
x.Phone,
|
||||
x.Email,
|
||||
x.WeChat,
|
||||
x.EmergencyContactName,
|
||||
x.EmergencyContactRelationship,
|
||||
x.EmergencyContactPhone,
|
||||
x.SpecialTags,
|
||||
x.SpecialNeeds,
|
||||
db.CourseEnrollments
|
||||
.Where(enrollment =>
|
||||
enrollment.StudentId == x.Id &&
|
||||
@@ -2154,6 +2174,14 @@ public sealed class CourseSelectionsController(
|
||||
string Name,
|
||||
string ClassName,
|
||||
string MajorName,
|
||||
string? Phone,
|
||||
string? Email,
|
||||
string? WeChat,
|
||||
string? EmergencyContactName,
|
||||
string? EmergencyContactRelationship,
|
||||
string? EmergencyContactPhone,
|
||||
string? SpecialTags,
|
||||
string? SpecialNeeds,
|
||||
DateTime? EnrolledAt);
|
||||
}
|
||||
|
||||
|
||||
@@ -224,6 +224,12 @@ public sealed class PersonnelController(
|
||||
[FromQuery] PersonnelQuery query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var roles = currentUserDataScope.Current.Roles;
|
||||
var canReadFullProfile = roles.Any(role =>
|
||||
role is SystemRoles.SuperAdmin or
|
||||
SystemRoles.AcademicAdmin or
|
||||
SystemRoles.CollegeAdmin or
|
||||
SystemRoles.Counselor);
|
||||
var page = NormalizePage(query.Page);
|
||||
var pageSize = NormalizePageSize(query.PageSize);
|
||||
var source = ApplyStudentScope(db.Students.AsNoTracking());
|
||||
@@ -268,9 +274,26 @@ public sealed class PersonnelController(
|
||||
x.EnrollmentDate,
|
||||
x.Status,
|
||||
x.DateOfBirth,
|
||||
EnglishName = canReadFullProfile ? x.EnglishName : null,
|
||||
IdCardNumber = canReadFullProfile ? x.IdCardNumber : null,
|
||||
Nationality = canReadFullProfile ? x.Nationality : null,
|
||||
Ethnicity = canReadFullProfile ? x.Ethnicity : null,
|
||||
PoliticalStatus = canReadFullProfile ? x.PoliticalStatus : null,
|
||||
NativePlace = canReadFullProfile ? x.NativePlace : null,
|
||||
HouseholdAddress = canReadFullProfile ? x.HouseholdAddress : null,
|
||||
CurrentAddress = canReadFullProfile ? x.CurrentAddress : null,
|
||||
PostalCode = canReadFullProfile ? x.PostalCode : null,
|
||||
x.Phone,
|
||||
x.Email,
|
||||
x.Notes,
|
||||
Qq = canReadFullProfile ? x.Qq : null,
|
||||
x.WeChat,
|
||||
x.EmergencyContactName,
|
||||
x.EmergencyContactRelationship,
|
||||
x.EmergencyContactPhone,
|
||||
x.SpecialTags,
|
||||
x.SpecialNeeds,
|
||||
Biography = canReadFullProfile ? x.Biography : null,
|
||||
Notes = canReadFullProfile ? x.Notes : null,
|
||||
x.UserId,
|
||||
x.CreatedAt
|
||||
})
|
||||
@@ -304,8 +327,26 @@ public sealed class PersonnelController(
|
||||
EnrollmentDate = request.EnrollmentDate,
|
||||
Status = request.Status,
|
||||
DateOfBirth = request.DateOfBirth,
|
||||
EnglishName = Normalize(request.EnglishName),
|
||||
IdCardNumber = Normalize(request.IdCardNumber),
|
||||
Nationality = Normalize(request.Nationality),
|
||||
Ethnicity = Normalize(request.Ethnicity),
|
||||
PoliticalStatus = Normalize(request.PoliticalStatus),
|
||||
NativePlace = Normalize(request.NativePlace),
|
||||
HouseholdAddress = Normalize(request.HouseholdAddress),
|
||||
CurrentAddress = Normalize(request.CurrentAddress),
|
||||
PostalCode = Normalize(request.PostalCode),
|
||||
Phone = Normalize(request.Phone),
|
||||
Email = Normalize(request.Email),
|
||||
Qq = Normalize(request.Qq),
|
||||
WeChat = Normalize(request.WeChat),
|
||||
EmergencyContactName = Normalize(request.EmergencyContactName),
|
||||
EmergencyContactRelationship = Normalize(
|
||||
request.EmergencyContactRelationship),
|
||||
EmergencyContactPhone = Normalize(request.EmergencyContactPhone),
|
||||
SpecialTags = Normalize(request.SpecialTags),
|
||||
SpecialNeeds = Normalize(request.SpecialNeeds),
|
||||
Biography = Normalize(request.Biography),
|
||||
Notes = Normalize(request.Notes)
|
||||
};
|
||||
db.Students.Add(entity);
|
||||
@@ -343,8 +384,26 @@ public sealed class PersonnelController(
|
||||
entity.EnrollmentDate = request.EnrollmentDate;
|
||||
entity.Status = request.Status;
|
||||
entity.DateOfBirth = request.DateOfBirth;
|
||||
entity.EnglishName = Normalize(request.EnglishName);
|
||||
entity.IdCardNumber = Normalize(request.IdCardNumber);
|
||||
entity.Nationality = Normalize(request.Nationality);
|
||||
entity.Ethnicity = Normalize(request.Ethnicity);
|
||||
entity.PoliticalStatus = Normalize(request.PoliticalStatus);
|
||||
entity.NativePlace = Normalize(request.NativePlace);
|
||||
entity.HouseholdAddress = Normalize(request.HouseholdAddress);
|
||||
entity.CurrentAddress = Normalize(request.CurrentAddress);
|
||||
entity.PostalCode = Normalize(request.PostalCode);
|
||||
entity.Phone = Normalize(request.Phone);
|
||||
entity.Email = Normalize(request.Email);
|
||||
entity.Qq = Normalize(request.Qq);
|
||||
entity.WeChat = Normalize(request.WeChat);
|
||||
entity.EmergencyContactName = Normalize(request.EmergencyContactName);
|
||||
entity.EmergencyContactRelationship = Normalize(
|
||||
request.EmergencyContactRelationship);
|
||||
entity.EmergencyContactPhone = Normalize(request.EmergencyContactPhone);
|
||||
entity.SpecialTags = Normalize(request.SpecialTags);
|
||||
entity.SpecialNeeds = Normalize(request.SpecialNeeds);
|
||||
entity.Biography = Normalize(request.Biography);
|
||||
entity.Notes = Normalize(request.Notes);
|
||||
return await SaveNoContentAsync(cancellationToken);
|
||||
}
|
||||
@@ -522,8 +581,25 @@ public sealed record StudentRequest(
|
||||
DateOnly EnrollmentDate,
|
||||
StudentStatus Status,
|
||||
DateOnly? DateOfBirth,
|
||||
[MaxLength(100)] string? EnglishName,
|
||||
[MaxLength(30)] string? IdCardNumber,
|
||||
[MaxLength(50)] string? Nationality,
|
||||
[MaxLength(50)] string? Ethnicity,
|
||||
[MaxLength(50)] string? PoliticalStatus,
|
||||
[MaxLength(100)] string? NativePlace,
|
||||
[MaxLength(300)] string? HouseholdAddress,
|
||||
[MaxLength(300)] string? CurrentAddress,
|
||||
[MaxLength(20)] string? PostalCode,
|
||||
[MaxLength(30)] string? Phone,
|
||||
[EmailAddress, MaxLength(100)] string? Email,
|
||||
[MaxLength(30)] string? Qq,
|
||||
[MaxLength(60)] string? WeChat,
|
||||
[MaxLength(50)] string? EmergencyContactName,
|
||||
[MaxLength(30)] string? EmergencyContactRelationship,
|
||||
[MaxLength(30)] string? EmergencyContactPhone,
|
||||
[MaxLength(300)] string? SpecialTags,
|
||||
[MaxLength(1000)] string? SpecialNeeds,
|
||||
[MaxLength(1000)] string? Biography,
|
||||
[MaxLength(500)] string? Notes);
|
||||
|
||||
public sealed record TeacherAccountActivationRequest(
|
||||
|
||||
@@ -31,6 +31,9 @@ public sealed class PersonnelExcelController(
|
||||
SystemRoles.AcademicAdmin + "," +
|
||||
SystemRoles.CollegeAdmin;
|
||||
|
||||
private const string ExportRoles =
|
||||
WriteRoles + "," + SystemRoles.Counselor;
|
||||
|
||||
private static readonly string[] TeacherHeaders =
|
||||
[
|
||||
"工号", "姓名", "性别", "学院编码", "职称", "任职状态",
|
||||
@@ -40,7 +43,10 @@ public sealed class PersonnelExcelController(
|
||||
private static readonly string[] StudentHeaders =
|
||||
[
|
||||
"学号", "姓名", "性别", "行政班编码", "入学年级", "入学日期",
|
||||
"学籍状态", "出生日期", "联系电话", "电子邮箱", "备注"
|
||||
"学籍状态", "出生日期", "英文姓名", "证件号码", "国籍", "民族",
|
||||
"政治面貌", "籍贯", "户籍地址", "现居住地址", "邮政编码",
|
||||
"联系电话", "电子邮箱", "QQ", "微信", "紧急联系人", "与本人关系",
|
||||
"紧急联系电话", "特殊标记", "特殊情况说明", "个人简介", "备注"
|
||||
];
|
||||
|
||||
[HttpGet("{kind}/template")]
|
||||
@@ -66,6 +72,7 @@ public sealed class PersonnelExcelController(
|
||||
}
|
||||
|
||||
[HttpGet("{kind}/export")]
|
||||
[Authorize(Roles = ExportRoles)]
|
||||
public async Task<IActionResult> Export(
|
||||
string kind,
|
||||
[FromQuery] PersonnelQuery query,
|
||||
@@ -96,7 +103,12 @@ public sealed class PersonnelExcelController(
|
||||
.Select(x => Row(
|
||||
x.StudentNumber, x.Name, GenderName(x.Gender),
|
||||
x.AdministrativeClass!.Code, x.EnrollmentYear, x.EnrollmentDate,
|
||||
StudentStatusName(x.Status), x.DateOfBirth, x.Phone, x.Email, x.Notes))
|
||||
StudentStatusName(x.Status), x.DateOfBirth, x.EnglishName,
|
||||
x.IdCardNumber, x.Nationality, x.Ethnicity, x.PoliticalStatus,
|
||||
x.NativePlace, x.HouseholdAddress, x.CurrentAddress, x.PostalCode,
|
||||
x.Phone, x.Email, x.Qq, x.WeChat, x.EmergencyContactName,
|
||||
x.EmergencyContactRelationship, x.EmergencyContactPhone,
|
||||
x.SpecialTags, x.SpecialNeeds, x.Biography, x.Notes))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
@@ -296,8 +308,25 @@ public sealed class PersonnelExcelController(
|
||||
entity.EnrollmentDate = enrollmentDate.Value;
|
||||
entity.Status = status.Value;
|
||||
entity.DateOfBirth = dateOfBirth;
|
||||
entity.EnglishName = Optional(row, "英文姓名");
|
||||
entity.IdCardNumber = Optional(row, "证件号码");
|
||||
entity.Nationality = Optional(row, "国籍");
|
||||
entity.Ethnicity = Optional(row, "民族");
|
||||
entity.PoliticalStatus = Optional(row, "政治面貌");
|
||||
entity.NativePlace = Optional(row, "籍贯");
|
||||
entity.HouseholdAddress = Optional(row, "户籍地址");
|
||||
entity.CurrentAddress = Optional(row, "现居住地址");
|
||||
entity.PostalCode = Optional(row, "邮政编码");
|
||||
entity.Phone = Optional(row, "联系电话");
|
||||
entity.Email = Optional(row, "电子邮箱");
|
||||
entity.Qq = Optional(row, "QQ");
|
||||
entity.WeChat = Optional(row, "微信");
|
||||
entity.EmergencyContactName = Optional(row, "紧急联系人");
|
||||
entity.EmergencyContactRelationship = Optional(row, "与本人关系");
|
||||
entity.EmergencyContactPhone = Optional(row, "紧急联系电话");
|
||||
entity.SpecialTags = Optional(row, "特殊标记");
|
||||
entity.SpecialNeeds = Optional(row, "特殊情况说明");
|
||||
entity.Biography = Optional(row, "个人简介");
|
||||
entity.Notes = Optional(row, "备注");
|
||||
}
|
||||
return new(created, updated, rows.Count);
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
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.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Jiaowu.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize(Roles = SystemRoles.Student)]
|
||||
[Route("api/student/profile")]
|
||||
public sealed class StudentProfileController(
|
||||
AppDbContext db,
|
||||
ICurrentUserDataScope currentUserDataScope,
|
||||
IAppCache cache) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<StudentProfileDto>> Get(
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var userId = currentUserDataScope.Current.UserId;
|
||||
var profile = await db.Students.AsNoTracking()
|
||||
.Where(x => x.UserId == userId)
|
||||
.Select(x => new StudentProfileDto(
|
||||
x.StudentNumber,
|
||||
x.Name,
|
||||
x.AdministrativeClass!.Name,
|
||||
x.AdministrativeClass.Major!.Name,
|
||||
x.AdministrativeClass.Major.College!.Name,
|
||||
x.EnrollmentYear,
|
||||
x.EnrollmentDate,
|
||||
x.Status,
|
||||
x.Gender,
|
||||
x.DateOfBirth,
|
||||
x.EnglishName,
|
||||
x.IdCardNumber,
|
||||
x.Nationality,
|
||||
x.Ethnicity,
|
||||
x.PoliticalStatus,
|
||||
x.NativePlace,
|
||||
x.HouseholdAddress,
|
||||
x.CurrentAddress,
|
||||
x.PostalCode,
|
||||
x.Phone,
|
||||
x.Email,
|
||||
x.Qq,
|
||||
x.WeChat,
|
||||
x.EmergencyContactName,
|
||||
x.EmergencyContactRelationship,
|
||||
x.EmergencyContactPhone,
|
||||
x.SpecialTags,
|
||||
x.SpecialNeeds,
|
||||
x.Biography))
|
||||
.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return profile is null ? NotFound() : Ok(profile);
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
public async Task<IActionResult> Update(
|
||||
StudentProfileUpdateRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var userId = currentUserDataScope.Current.UserId;
|
||||
var student = await db.Students.SingleOrDefaultAsync(
|
||||
x => x.UserId == userId,
|
||||
cancellationToken);
|
||||
if (student is null) return NotFound();
|
||||
|
||||
student.Gender = request.Gender;
|
||||
student.DateOfBirth = request.DateOfBirth;
|
||||
student.EnglishName = Normalize(request.EnglishName);
|
||||
student.IdCardNumber = Normalize(request.IdCardNumber);
|
||||
student.Nationality = Normalize(request.Nationality);
|
||||
student.Ethnicity = Normalize(request.Ethnicity);
|
||||
student.PoliticalStatus = Normalize(request.PoliticalStatus);
|
||||
student.NativePlace = Normalize(request.NativePlace);
|
||||
student.HouseholdAddress = Normalize(request.HouseholdAddress);
|
||||
student.CurrentAddress = Normalize(request.CurrentAddress);
|
||||
student.PostalCode = Normalize(request.PostalCode);
|
||||
student.Phone = Normalize(request.Phone);
|
||||
student.Email = Normalize(request.Email);
|
||||
student.Qq = Normalize(request.Qq);
|
||||
student.WeChat = Normalize(request.WeChat);
|
||||
student.EmergencyContactName = Normalize(request.EmergencyContactName);
|
||||
student.EmergencyContactRelationship = Normalize(
|
||||
request.EmergencyContactRelationship);
|
||||
student.EmergencyContactPhone = Normalize(request.EmergencyContactPhone);
|
||||
student.SpecialTags = Normalize(request.SpecialTags);
|
||||
student.SpecialNeeds = Normalize(request.SpecialNeeds);
|
||||
student.Biography = Normalize(request.Biography);
|
||||
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
await cache.RemoveByTagAsync(AppCacheTags.Analytics, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
private static string? Normalize(string? value) =>
|
||||
string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
||||
}
|
||||
|
||||
public sealed record StudentProfileDto(
|
||||
string StudentNumber,
|
||||
string Name,
|
||||
string ClassName,
|
||||
string MajorName,
|
||||
string CollegeName,
|
||||
int EnrollmentYear,
|
||||
DateOnly EnrollmentDate,
|
||||
StudentStatus Status,
|
||||
Gender Gender,
|
||||
DateOnly? DateOfBirth,
|
||||
string? EnglishName,
|
||||
string? IdCardNumber,
|
||||
string? Nationality,
|
||||
string? Ethnicity,
|
||||
string? PoliticalStatus,
|
||||
string? NativePlace,
|
||||
string? HouseholdAddress,
|
||||
string? CurrentAddress,
|
||||
string? PostalCode,
|
||||
string? Phone,
|
||||
string? Email,
|
||||
string? Qq,
|
||||
string? WeChat,
|
||||
string? EmergencyContactName,
|
||||
string? EmergencyContactRelationship,
|
||||
string? EmergencyContactPhone,
|
||||
string? SpecialTags,
|
||||
string? SpecialNeeds,
|
||||
string? Biography);
|
||||
|
||||
public sealed record StudentProfileUpdateRequest(
|
||||
Gender Gender,
|
||||
DateOnly? DateOfBirth,
|
||||
[MaxLength(100)] string? EnglishName,
|
||||
[MaxLength(30)] string? IdCardNumber,
|
||||
[MaxLength(50)] string? Nationality,
|
||||
[MaxLength(50)] string? Ethnicity,
|
||||
[MaxLength(50)] string? PoliticalStatus,
|
||||
[MaxLength(100)] string? NativePlace,
|
||||
[MaxLength(300)] string? HouseholdAddress,
|
||||
[MaxLength(300)] string? CurrentAddress,
|
||||
[MaxLength(20)] string? PostalCode,
|
||||
[MaxLength(30)] string? Phone,
|
||||
[EmailAddress, MaxLength(100)] string? Email,
|
||||
[MaxLength(30)] string? Qq,
|
||||
[MaxLength(60)] string? WeChat,
|
||||
[MaxLength(50)] string? EmergencyContactName,
|
||||
[MaxLength(30)] string? EmergencyContactRelationship,
|
||||
[MaxLength(30)] string? EmergencyContactPhone,
|
||||
[MaxLength(300)] string? SpecialTags,
|
||||
[MaxLength(1000)] string? SpecialNeeds,
|
||||
[MaxLength(1000)] string? Biography);
|
||||
@@ -30,8 +30,25 @@ public sealed class Student : EntityBase
|
||||
public DateOnly EnrollmentDate { get; set; }
|
||||
public StudentStatus Status { get; set; } = StudentStatus.Active;
|
||||
public DateOnly? DateOfBirth { get; set; }
|
||||
public string? EnglishName { get; set; }
|
||||
public string? IdCardNumber { get; set; }
|
||||
public string? Nationality { get; set; }
|
||||
public string? Ethnicity { get; set; }
|
||||
public string? PoliticalStatus { get; set; }
|
||||
public string? NativePlace { get; set; }
|
||||
public string? HouseholdAddress { get; set; }
|
||||
public string? CurrentAddress { get; set; }
|
||||
public string? PostalCode { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Qq { get; set; }
|
||||
public string? WeChat { get; set; }
|
||||
public string? EmergencyContactName { get; set; }
|
||||
public string? EmergencyContactRelationship { get; set; }
|
||||
public string? EmergencyContactPhone { get; set; }
|
||||
public string? SpecialTags { get; set; }
|
||||
public string? SpecialNeeds { get; set; }
|
||||
public string? Biography { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public Guid? UserId { get; set; }
|
||||
}
|
||||
|
||||
@@ -257,8 +257,25 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
{
|
||||
entity.Property(x => x.StudentNumber).HasMaxLength(30);
|
||||
entity.Property(x => x.Name).HasMaxLength(50);
|
||||
entity.Property(x => x.EnglishName).HasMaxLength(100);
|
||||
entity.Property(x => x.IdCardNumber).HasMaxLength(30);
|
||||
entity.Property(x => x.Nationality).HasMaxLength(50);
|
||||
entity.Property(x => x.Ethnicity).HasMaxLength(50);
|
||||
entity.Property(x => x.PoliticalStatus).HasMaxLength(50);
|
||||
entity.Property(x => x.NativePlace).HasMaxLength(100);
|
||||
entity.Property(x => x.HouseholdAddress).HasMaxLength(300);
|
||||
entity.Property(x => x.CurrentAddress).HasMaxLength(300);
|
||||
entity.Property(x => x.PostalCode).HasMaxLength(20);
|
||||
entity.Property(x => x.Phone).HasMaxLength(30);
|
||||
entity.Property(x => x.Email).HasMaxLength(100);
|
||||
entity.Property(x => x.Qq).HasMaxLength(30);
|
||||
entity.Property(x => x.WeChat).HasMaxLength(60);
|
||||
entity.Property(x => x.EmergencyContactName).HasMaxLength(50);
|
||||
entity.Property(x => x.EmergencyContactRelationship).HasMaxLength(30);
|
||||
entity.Property(x => x.EmergencyContactPhone).HasMaxLength(30);
|
||||
entity.Property(x => x.SpecialTags).HasMaxLength(300);
|
||||
entity.Property(x => x.SpecialNeeds).HasMaxLength(1000);
|
||||
entity.Property(x => x.Biography).HasMaxLength(1000);
|
||||
entity.Property(x => x.Notes).HasMaxLength(500);
|
||||
entity.HasIndex(x => x.StudentNumber).IsUnique();
|
||||
entity.HasIndex(x => new { x.AdministrativeClassId, x.Status });
|
||||
|
||||
@@ -80,6 +80,8 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
"20260802_42_integrated_experiment_scheduling";
|
||||
private const string RefreshSessionsMigration =
|
||||
"20260803_43_refresh_sessions";
|
||||
private const string StudentPersonalProfileMigration =
|
||||
"20260803_44_student_personal_profile";
|
||||
|
||||
public async Task MigrateAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -599,6 +601,18 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
RefreshSessionsMigration,
|
||||
RefreshSessionsStatements,
|
||||
cancellationToken);
|
||||
var studentPersonalProfileExists = await db.Database
|
||||
.SqlQueryRaw<int>(
|
||||
"""
|
||||
SELECT COUNT(*) AS "Value"
|
||||
FROM pragma_table_info('Students')
|
||||
WHERE name = 'SpecialTags'
|
||||
""")
|
||||
.AnyAsync(value => value > 0, cancellationToken);
|
||||
await ApplyMigrationAsync(
|
||||
StudentPersonalProfileMigration,
|
||||
studentPersonalProfileExists ? [] : StudentPersonalProfileStatements,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ApplyMigrationAsync(
|
||||
@@ -2138,6 +2152,27 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
"""
|
||||
];
|
||||
|
||||
private static readonly string[] StudentPersonalProfileStatements =
|
||||
[
|
||||
"""ALTER TABLE "Students" ADD COLUMN "Biography" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "CurrentAddress" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "EmergencyContactName" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "EmergencyContactPhone" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "EmergencyContactRelationship" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "EnglishName" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "Ethnicity" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "HouseholdAddress" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "IdCardNumber" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "Nationality" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "NativePlace" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "PoliticalStatus" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "PostalCode" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "Qq" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "SpecialNeeds" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "SpecialTags" TEXT NULL;""",
|
||||
"""ALTER TABLE "Students" ADD COLUMN "WeChat" TEXT NULL;"""
|
||||
];
|
||||
|
||||
private static readonly string[] ApprovalTableStatements =
|
||||
[
|
||||
"""CREATE TABLE "CourseExemptions" ("Id" TEXT NOT NULL CONSTRAINT "PK_CourseExemptions" PRIMARY KEY, "StudentId" TEXT NOT NULL, "TeachingTaskId" TEXT NOT NULL, "Reason" TEXT NOT NULL, "Status" INTEGER NOT NULL, "ReviewComment" TEXT NULL, "SubmittedAt" TEXT NOT NULL, "ReviewedAt" TEXT NULL, "ReviewedByUserId" TEXT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, CONSTRAINT "FK_CourseExemptions_Students" FOREIGN KEY ("StudentId") REFERENCES "Students" ("Id") ON DELETE RESTRICT, CONSTRAINT "FK_CourseExemptions_TeachingTasks" FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE RESTRICT);""",
|
||||
|
||||
+6120
File diff suppressed because it is too large
Load Diff
+205
@@ -0,0 +1,205 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class StudentPersonalProfile : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Biography",
|
||||
table: "Students",
|
||||
type: "varchar(1000)",
|
||||
maxLength: 1000,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "CurrentAddress",
|
||||
table: "Students",
|
||||
type: "varchar(300)",
|
||||
maxLength: 300,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "EmergencyContactName",
|
||||
table: "Students",
|
||||
type: "varchar(50)",
|
||||
maxLength: 50,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "EmergencyContactPhone",
|
||||
table: "Students",
|
||||
type: "varchar(30)",
|
||||
maxLength: 30,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "EmergencyContactRelationship",
|
||||
table: "Students",
|
||||
type: "varchar(30)",
|
||||
maxLength: 30,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "EnglishName",
|
||||
table: "Students",
|
||||
type: "varchar(100)",
|
||||
maxLength: 100,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Ethnicity",
|
||||
table: "Students",
|
||||
type: "varchar(50)",
|
||||
maxLength: 50,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "HouseholdAddress",
|
||||
table: "Students",
|
||||
type: "varchar(300)",
|
||||
maxLength: 300,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "IdCardNumber",
|
||||
table: "Students",
|
||||
type: "varchar(30)",
|
||||
maxLength: 30,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Nationality",
|
||||
table: "Students",
|
||||
type: "varchar(50)",
|
||||
maxLength: 50,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "NativePlace",
|
||||
table: "Students",
|
||||
type: "varchar(100)",
|
||||
maxLength: 100,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "PoliticalStatus",
|
||||
table: "Students",
|
||||
type: "varchar(50)",
|
||||
maxLength: 50,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "PostalCode",
|
||||
table: "Students",
|
||||
type: "varchar(20)",
|
||||
maxLength: 20,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Qq",
|
||||
table: "Students",
|
||||
type: "varchar(30)",
|
||||
maxLength: 30,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SpecialNeeds",
|
||||
table: "Students",
|
||||
type: "varchar(1000)",
|
||||
maxLength: 1000,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SpecialTags",
|
||||
table: "Students",
|
||||
type: "varchar(300)",
|
||||
maxLength: 300,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "WeChat",
|
||||
table: "Students",
|
||||
type: "varchar(60)",
|
||||
maxLength: 60,
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Biography",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CurrentAddress",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "EmergencyContactName",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "EmergencyContactPhone",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "EmergencyContactRelationship",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "EnglishName",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Ethnicity",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "HouseholdAddress",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IdCardNumber",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Nationality",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "NativePlace",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PoliticalStatus",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PostalCode",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Qq",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SpecialNeeds",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SpecialTags",
|
||||
table: "Students");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "WeChat",
|
||||
table: "Students");
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
@@ -3492,9 +3492,17 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.Property<Guid>("AdministrativeClassId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Biography")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("varchar(1000)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("CurrentAddress")
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("varchar(300)");
|
||||
|
||||
b.Property<DateTime?>("DateOfBirth")
|
||||
.HasColumnType("date");
|
||||
|
||||
@@ -3502,20 +3510,56 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("varchar(100)");
|
||||
|
||||
b.Property<string>("EmergencyContactName")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("varchar(50)");
|
||||
|
||||
b.Property<string>("EmergencyContactPhone")
|
||||
.HasMaxLength(30)
|
||||
.HasColumnType("varchar(30)");
|
||||
|
||||
b.Property<string>("EmergencyContactRelationship")
|
||||
.HasMaxLength(30)
|
||||
.HasColumnType("varchar(30)");
|
||||
|
||||
b.Property<string>("EnglishName")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("varchar(100)");
|
||||
|
||||
b.Property<DateTime>("EnrollmentDate")
|
||||
.HasColumnType("date");
|
||||
|
||||
b.Property<int>("EnrollmentYear")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Ethnicity")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("varchar(50)");
|
||||
|
||||
b.Property<int>("Gender")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("HouseholdAddress")
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("varchar(300)");
|
||||
|
||||
b.Property<string>("IdCardNumber")
|
||||
.HasMaxLength(30)
|
||||
.HasColumnType("varchar(30)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("varchar(50)");
|
||||
|
||||
b.Property<string>("Nationality")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("varchar(50)");
|
||||
|
||||
b.Property<string>("NativePlace")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("varchar(100)");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("varchar(500)");
|
||||
@@ -3524,6 +3568,26 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
.HasMaxLength(30)
|
||||
.HasColumnType("varchar(30)");
|
||||
|
||||
b.Property<string>("PoliticalStatus")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("varchar(50)");
|
||||
|
||||
b.Property<string>("PostalCode")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<string>("Qq")
|
||||
.HasMaxLength(30)
|
||||
.HasColumnType("varchar(30)");
|
||||
|
||||
b.Property<string>("SpecialNeeds")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("varchar(1000)");
|
||||
|
||||
b.Property<string>("SpecialTags")
|
||||
.HasMaxLength(300)
|
||||
.HasColumnType("varchar(300)");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("int");
|
||||
|
||||
@@ -3538,6 +3602,10 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("WeChat")
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("varchar(60)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("EnrollmentYear");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Version>2.3.0</Version>
|
||||
<Version>2.3.0-rc2</Version>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<SpaRoot>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)/../../web'))</SpaRoot>
|
||||
|
||||
Reference in New Issue
Block a user