diff --git a/src/Jiaowu.Api/Controllers/BaseDataController.cs b/src/Jiaowu.Api/Controllers/BaseDataController.cs index 60ac840..3293318 100644 --- a/src/Jiaowu.Api/Controllers/BaseDataController.cs +++ b/src/Jiaowu.Api/Controllers/BaseDataController.cs @@ -237,6 +237,10 @@ public sealed class BaseDataController(AppDbContext db, IAppCache cache) : Contr int? page, int? pageSize, string? keyword, + Guid? collegeId, + Guid? majorId, + int? grade, + bool? isEnabled, CancellationToken cancellationToken) { if (page.HasValue || pageSize.HasValue) @@ -245,6 +249,11 @@ public sealed class BaseDataController(AppDbContext db, IAppCache cache) : Contr return ValidationProblem("页码必须大于 0,且每页条数应在 1 至 100 之间。"); var source = db.AdministrativeClasses.AsNoTracking(); + if (collegeId.HasValue) + source = source.Where(x => x.Major!.CollegeId == collegeId.Value); + if (majorId.HasValue) source = source.Where(x => x.MajorId == majorId.Value); + if (grade.HasValue) source = source.Where(x => x.Grade == grade.Value); + if (isEnabled.HasValue) source = source.Where(x => x.IsEnabled == isEnabled.Value); if (!string.IsNullOrWhiteSpace(keyword)) { keyword = keyword.Trim(); @@ -511,6 +520,11 @@ public sealed class BaseDataController(AppDbContext db, IAppCache cache) : Contr int? page, int? pageSize, string? keyword, + Guid? campusId, + Guid? buildingId, + int? minimumCapacity, + TeachingVenueNature? teachingVenueNature, + bool? isEnabled, CancellationToken cancellationToken) { if (page.HasValue || pageSize.HasValue) @@ -519,6 +533,14 @@ public sealed class BaseDataController(AppDbContext db, IAppCache cache) : Contr return ValidationProblem("页码必须大于 0,且每页条数应在 1 至 100 之间。"); var source = db.Classrooms.AsNoTracking(); + if (campusId.HasValue) + source = source.Where(x => x.Building!.CampusId == campusId.Value); + if (buildingId.HasValue) source = source.Where(x => x.BuildingId == buildingId.Value); + if (minimumCapacity.HasValue) + source = source.Where(x => x.Capacity >= minimumCapacity.Value); + if (teachingVenueNature.HasValue) + source = source.Where(x => (x.TeachingVenueNature & teachingVenueNature.Value) != 0); + if (isEnabled.HasValue) source = source.Where(x => x.IsEnabled == isEnabled.Value); if (!string.IsNullOrWhiteSpace(keyword)) { keyword = keyword.Trim(); diff --git a/src/Jiaowu.Api/Controllers/GradeAnalyticsController.cs b/src/Jiaowu.Api/Controllers/GradeAnalyticsController.cs index 52b44ce..7d441bd 100644 --- a/src/Jiaowu.Api/Controllers/GradeAnalyticsController.cs +++ b/src/Jiaowu.Api/Controllers/GradeAnalyticsController.cs @@ -93,6 +93,9 @@ public sealed class GradeAnalyticsController( public async Task GetTeachingClasses( Guid? academicTermId, string? keyword, + Guid? collegeId = null, + string? teacherKeyword = null, + bool? riskOnly = null, int page = 1, int pageSize = 20, CancellationToken cancellationToken = default) @@ -105,12 +108,23 @@ public sealed class GradeAnalyticsController( .Where(x => VisibleTeachingTasks().Any(task => task.Id == x.TeachingTaskId)); if (academicTermId.HasValue) source = source.Where(x => x.AcademicTermId == academicTermId); + if (collegeId.HasValue) + source = source.Where(x => x.TeachingTask!.Course!.CollegeId == collegeId.Value); if (keyword is not null) source = source.Where(x => x.TeachingTask!.TaskNumber.Contains(keyword) || x.TeachingTask.Name.Contains(keyword) || x.TeachingTask.Course!.Code.Contains(keyword) || x.TeachingTask.Course.Name.Contains(keyword)); + if (!string.IsNullOrWhiteSpace(teacherKeyword)) + { + teacherKeyword = teacherKeyword.Trim(); + source = source.Where(x => x.TeachingTask!.Teachers.Any(item => + item.Teacher!.Name.Contains(teacherKeyword) || + item.Teacher.TeacherNumber.Contains(teacherKeyword))); + } + if (riskOnly == true) + source = source.Where(x => x.PassRate < 60 || x.AverageScore < 60); var total = await source.CountAsync(cancellationToken); var items = await source diff --git a/src/Jiaowu.Api/Controllers/UsersController.cs b/src/Jiaowu.Api/Controllers/UsersController.cs index c5048cb..83c987b 100644 --- a/src/Jiaowu.Api/Controllers/UsersController.cs +++ b/src/Jiaowu.Api/Controllers/UsersController.cs @@ -24,6 +24,10 @@ public sealed class UsersController( int page = 1, int pageSize = 20, string? keyword = null, + string? roleName = null, + Guid? collegeId = null, + bool? isEnabled = null, + bool? hasLoggedIn = null, CancellationToken cancellationToken = default) { if (page < 1 || pageSize is < 1 or > 100) @@ -42,6 +46,21 @@ public sealed class UsersController( where userRole.UserId == user.Id && role.Name!.Contains(keyword) select role.Id).Any()); } + if (!string.IsNullOrWhiteSpace(roleName)) + { + roleName = roleName.Trim(); + query = query.Where(user => + (from userRole in db.UserRoles + join candidateRole in db.Roles on userRole.RoleId equals candidateRole.Id + where userRole.UserId == user.Id && candidateRole.Name == roleName + select userRole.RoleId).Any()); + } + if (collegeId.HasValue) query = query.Where(user => user.CollegeId == collegeId.Value); + if (isEnabled.HasValue) query = query.Where(user => user.IsEnabled == isEnabled.Value); + if (hasLoggedIn.HasValue) + query = hasLoggedIn.Value + ? query.Where(user => user.LastLoginAt != null) + : query.Where(user => user.LastLoginAt == null); var total = await query.CountAsync(cancellationToken); var users = await query diff --git a/web/src/views/BaseDataView.vue b/web/src/views/BaseDataView.vue index 904a1c5..f93f45f 100644 --- a/web/src/views/BaseDataView.vue +++ b/web/src/views/BaseDataView.vue @@ -77,6 +77,16 @@ const references = reactive>({ campuses: [], colleges: [], majors: [], buildings: [], counselors: [], }) const form = reactive>({}) +const listFilters = reactive({ + collegeId: undefined as string | undefined, + majorId: undefined as string | undefined, + grade: undefined as number | undefined, + campusId: undefined as string | undefined, + buildingId: undefined as string | undefined, + minimumCapacity: undefined as number | undefined, + teachingVenueNature: undefined as number | undefined, + isEnabled: undefined as boolean | undefined, +}) const title = computed(() => tabs.value.find((x) => x.key === active.value)?.label ?? '') const canManage = computed(() => @@ -90,6 +100,10 @@ const filteredRows = computed(() => { .filter(Boolean).some((value) => String(value).toLowerCase().includes(q)), ) }) +const filteredMajors = computed(() => references.majors.filter((item: any) => + !listFilters.collegeId || item.collegeId === listFilters.collegeId)) +const filteredBuildings = computed(() => references.buildings.filter((item: any) => + !listFilters.campusId || item.campusId === listFilters.campusId)) const currentPage = ref(1) const pageSize = ref(20) const total = ref(0) @@ -154,6 +168,18 @@ async function load(resetPage = true) { page: currentPage.value, pageSize: pageSize.value, keyword: keyword.value.trim() || undefined, + ...(active.value === 'classes' ? { + collegeId: listFilters.collegeId, + majorId: listFilters.majorId, + grade: listFilters.grade, + isEnabled: listFilters.isEnabled, + } : { + campusId: listFilters.campusId, + buildingId: listFilters.buildingId, + minimumCapacity: listFilters.minimumCapacity, + teachingVenueNature: listFilters.teachingVenueNature, + isEnabled: listFilters.isEnabled, + }), } : undefined, }) @@ -187,6 +213,11 @@ async function loadReferences() { async function changeTab() { keyword.value = '' + Object.assign(listFilters, { + collegeId: undefined, majorId: undefined, grade: undefined, + campusId: undefined, buildingId: undefined, minimumCapacity: undefined, + teachingVenueNature: undefined, isEnabled: undefined, + }) await load() } @@ -388,6 +419,32 @@ watch(
+ + + + + + + 查询 刷新