2.3.0-rc2

This commit is contained in:
biss committed 2026-08-04 10:48:08 +08:00
1 parent 6735a6d3fc
commit 10b51eb08a
19 files changed
+7292 -7

No files matched your search

@@ -1639,13 +1639,25 @@ public sealed class CourseSelectionsController(
var students = await LoadTeachingTaskRosterAsync(id, cancellationToken); var students = await LoadTeachingTaskRosterAsync(id, cancellationToken);
var bytes = ExcelWorkbookHelper.Create( var bytes = ExcelWorkbookHelper.Create(
"教学班名单", "教学班名单",
["学号", "姓名", "班级", "专业", "进入方式", "选课时间"], [
"学号", "姓名", "班级", "专业", "联系电话", "电子邮箱",
"微信", "紧急联系人", "与本人关系", "紧急联系电话",
"特殊标记", "特殊情况说明", "进入方式", "选课时间"
],
students.Select(student => new List<object?> students.Select(student => new List<object?>
{ {
student.StudentNumber, student.StudentNumber,
student.Name, student.Name,
student.ClassName, student.ClassName,
student.MajorName, student.MajorName,
student.Phone,
student.Email,
student.WeChat,
student.EmergencyContactName,
student.EmergencyContactRelationship,
student.EmergencyContactPhone,
student.SpecialTags,
student.SpecialNeeds,
student.EnrolledAt.HasValue ? "选课" : "行政班关联", student.EnrolledAt.HasValue ? "选课" : "行政班关联",
student.EnrolledAt?.ToString("yyyy-MM-dd HH:mm") ?? "-" student.EnrolledAt?.ToString("yyyy-MM-dd HH:mm") ?? "-"
}).ToList<IReadOnlyList<object?>>()); }).ToList<IReadOnlyList<object?>>());
@@ -1754,6 +1766,14 @@ public sealed class CourseSelectionsController(
x.Name, x.Name,
x.AdministrativeClass!.Name, x.AdministrativeClass!.Name,
x.AdministrativeClass.Major!.Name, x.AdministrativeClass.Major!.Name,
x.Phone,
x.Email,
x.WeChat,
x.EmergencyContactName,
x.EmergencyContactRelationship,
x.EmergencyContactPhone,
x.SpecialTags,
x.SpecialNeeds,
db.CourseEnrollments db.CourseEnrollments
.Where(enrollment => .Where(enrollment =>
enrollment.StudentId == x.Id && enrollment.StudentId == x.Id &&
@@ -2154,6 +2174,14 @@ public sealed class CourseSelectionsController(
string Name, string Name,
string ClassName, string ClassName,
string MajorName, string MajorName,
string? Phone,
string? Email,
string? WeChat,
string? EmergencyContactName,
string? EmergencyContactRelationship,
string? EmergencyContactPhone,
string? SpecialTags,
string? SpecialNeeds,
DateTime? EnrolledAt); DateTime? EnrolledAt);
} }
@@ -224,6 +224,12 @@ public sealed class PersonnelController(
[FromQuery] PersonnelQuery query, [FromQuery] PersonnelQuery query,
CancellationToken cancellationToken) 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 page = NormalizePage(query.Page);
var pageSize = NormalizePageSize(query.PageSize); var pageSize = NormalizePageSize(query.PageSize);
var source = ApplyStudentScope(db.Students.AsNoTracking()); var source = ApplyStudentScope(db.Students.AsNoTracking());
@@ -268,9 +274,26 @@ public sealed class PersonnelController(
x.EnrollmentDate, x.EnrollmentDate,
x.Status, x.Status,
x.DateOfBirth, 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.Phone,
x.Email, 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.UserId,
x.CreatedAt x.CreatedAt
}) })
@@ -304,8 +327,26 @@ public sealed class PersonnelController(
EnrollmentDate = request.EnrollmentDate, EnrollmentDate = request.EnrollmentDate,
Status = request.Status, Status = request.Status,
DateOfBirth = request.DateOfBirth, 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), Phone = Normalize(request.Phone),
Email = Normalize(request.Email), 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) Notes = Normalize(request.Notes)
}; };
db.Students.Add(entity); db.Students.Add(entity);
@@ -343,8 +384,26 @@ public sealed class PersonnelController(
entity.EnrollmentDate = request.EnrollmentDate; entity.EnrollmentDate = request.EnrollmentDate;
entity.Status = request.Status; entity.Status = request.Status;
entity.DateOfBirth = request.DateOfBirth; 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.Phone = Normalize(request.Phone);
entity.Email = Normalize(request.Email); 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); entity.Notes = Normalize(request.Notes);
return await SaveNoContentAsync(cancellationToken); return await SaveNoContentAsync(cancellationToken);
} }
@@ -522,8 +581,25 @@ public sealed record StudentRequest(
DateOnly EnrollmentDate, DateOnly EnrollmentDate,
StudentStatus Status, StudentStatus Status,
DateOnly? DateOfBirth, 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, [MaxLength(30)] string? Phone,
[EmailAddress, MaxLength(100)] string? Email, [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); [MaxLength(500)] string? Notes);
public sealed record TeacherAccountActivationRequest( public sealed record TeacherAccountActivationRequest(
@@ -31,6 +31,9 @@ public sealed class PersonnelExcelController(
SystemRoles.AcademicAdmin + "," + SystemRoles.AcademicAdmin + "," +
SystemRoles.CollegeAdmin; SystemRoles.CollegeAdmin;
private const string ExportRoles =
WriteRoles + "," + SystemRoles.Counselor;
private static readonly string[] TeacherHeaders = private static readonly string[] TeacherHeaders =
[ [
"工号", "姓名", "性别", "学院编码", "职称", "任职状态", "工号", "姓名", "性别", "学院编码", "职称", "任职状态",
@@ -40,7 +43,10 @@ public sealed class PersonnelExcelController(
private static readonly string[] StudentHeaders = private static readonly string[] StudentHeaders =
[ [
"学号", "姓名", "性别", "行政班编码", "入学年级", "入学日期", "学号", "姓名", "性别", "行政班编码", "入学年级", "入学日期",
"学籍状态", "出生日期", "联系电话", "电子邮箱", "备注" "学籍状态", "出生日期", "英文姓名", "证件号码", "国籍", "民族",
"政治面貌", "籍贯", "户籍地址", "现居住地址", "邮政编码",
"联系电话", "电子邮箱", "QQ", "微信", "紧急联系人", "与本人关系",
"紧急联系电话", "特殊标记", "特殊情况说明", "个人简介", "备注"
]; ];
[HttpGet("{kind}/template")] [HttpGet("{kind}/template")]
@@ -66,6 +72,7 @@ public sealed class PersonnelExcelController(
} }
[HttpGet("{kind}/export")] [HttpGet("{kind}/export")]
[Authorize(Roles = ExportRoles)]
public async Task<IActionResult> Export( public async Task<IActionResult> Export(
string kind, string kind,
[FromQuery] PersonnelQuery query, [FromQuery] PersonnelQuery query,
@@ -96,7 +103,12 @@ public sealed class PersonnelExcelController(
.Select(x => Row( .Select(x => Row(
x.StudentNumber, x.Name, GenderName(x.Gender), x.StudentNumber, x.Name, GenderName(x.Gender),
x.AdministrativeClass!.Code, x.EnrollmentYear, x.EnrollmentDate, 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(); .ToList();
} }
@@ -296,8 +308,25 @@ public sealed class PersonnelExcelController(
entity.EnrollmentDate = enrollmentDate.Value; entity.EnrollmentDate = enrollmentDate.Value;
entity.Status = status.Value; entity.Status = status.Value;
entity.DateOfBirth = dateOfBirth; 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.Phone = Optional(row, "联系电话");
entity.Email = 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, "备注"); entity.Notes = Optional(row, "备注");
} }
return new(created, updated, rows.Count); return new(created, updated, rows.Count);
Loaded 3 of 19 files, more files were not shown because too many files have changed in this diff. Show more