修复
This commit is contained in:
@@ -58,9 +58,8 @@ public static class ExperimentGradeAggregationService
|
||||
cancellationToken);
|
||||
var requestedStudentIds = studentIds.Distinct().ToArray();
|
||||
var persistedScores = await db.ExperimentCourseGrades.AsNoTracking()
|
||||
.Where(x =>
|
||||
x.TeachingTaskId == teachingTaskId &&
|
||||
requestedStudentIds.Contains(x.StudentId))
|
||||
.Where(x => x.TeachingTaskId == teachingTaskId)
|
||||
.WhereIn(requestedStudentIds, x => x.StudentId)
|
||||
.ToDictionaryAsync(
|
||||
x => x.StudentId,
|
||||
x => x.WeightedAverageScore,
|
||||
|
||||
@@ -109,6 +109,34 @@ public sealed class MySqlMigrationTests
|
||||
Assert.Contains(ids[1].ToString(), sql, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MySql_experiment_course_grade_lookup_uses_provider_safe_predicates()
|
||||
{
|
||||
using var db = new AppDbContext(CreateMySqlOptions());
|
||||
var teachingTaskId = Guid.Parse(
|
||||
"33333333-3333-3333-3333-333333333333");
|
||||
var studentIds = new[]
|
||||
{
|
||||
Guid.Parse("11111111-1111-1111-1111-111111111111"),
|
||||
Guid.Parse("22222222-2222-2222-2222-222222222222")
|
||||
};
|
||||
|
||||
var sql = db.ExperimentCourseGrades
|
||||
.Where(x => x.TeachingTaskId == teachingTaskId)
|
||||
.WhereIn(studentIds, x => x.StudentId)
|
||||
.ToQueryString();
|
||||
|
||||
Assert.Contains(" IN (", sql, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains(
|
||||
teachingTaskId.ToString(),
|
||||
sql,
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
Assert.All(studentIds, studentId => Assert.Contains(
|
||||
studentId.ToString(),
|
||||
sql,
|
||||
StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MySql_attendance_device_hash_query_uses_provider_safe_predicates()
|
||||
{
|
||||
|
||||
@@ -151,21 +151,14 @@ const navigationGroups = computed<NavigationGroup[]>(() => [
|
||||
),
|
||||
...whenVisible(isStudent.value || isTeacher.value, { path: '/my-timetable', label: isTeacher.value ? '我的授课课表' : '我的课表' }),
|
||||
...whenVisible(isStudent.value, { path: '/free-classrooms', label: '空闲教室' }),
|
||||
{
|
||||
path: '/class-timetable',
|
||||
label: isTimetableManager.value ? '课表查询中心' : '班级课表查询',
|
||||
},
|
||||
{
|
||||
path: '/classroom-reservations',
|
||||
label: hasAnyRole(['CollegeAdmin']) ? '教室借用审核' : '教室借用',
|
||||
},
|
||||
...whenVisible(isTeacher.value || isTeachingAdmin.value || hasAnyRole(['Counselor']), { path: '/teacher-attendance', label: '教学点名' }),
|
||||
...whenVisible(isStudent.value, { path: '/my-attendance', label: '我的考勤' }),
|
||||
{
|
||||
path: '/evaluations',
|
||||
label: isStudent.value ? '学生评教' : isTeacher.value ? '评教结果' : '教学评价',
|
||||
},
|
||||
...whenVisible(isTeacher.value, { path: '/teacher-roster', label: '选课名单' }),
|
||||
...whenVisible(!isStudent.value, {
|
||||
path: '/class-timetable',
|
||||
label: isTimetableManager.value ? '课表查询中心' : '班级课表查询',
|
||||
}),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Student']),
|
||||
{
|
||||
@@ -173,6 +166,26 @@ const navigationGroups = computed<NavigationGroup[]>(() => [
|
||||
label: isTeachingAdmin.value ? '选课管理' : '学生选课',
|
||||
},
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Teacher']),
|
||||
{
|
||||
path: '/course-adjustments',
|
||||
label: isTeacher.value ? '我的调停课' : '调停课审核',
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'teaching-assessment',
|
||||
label: '教学考核',
|
||||
items: [
|
||||
...whenVisible(isTeacher.value || isTeachingAdmin.value || hasAnyRole(['Counselor']), { path: '/teacher-attendance', label: '教学点名' }),
|
||||
...whenVisible(isStudent.value, { path: '/my-attendance', label: '我的考勤' }),
|
||||
{
|
||||
path: '/evaluations',
|
||||
label: isStudent.value ? '学生评教' : isTeacher.value ? '评教结果' : '教学评价',
|
||||
},
|
||||
...whenVisible(isTeacher.value, { path: '/teacher-roster', label: '选课名单' }),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Teacher', 'Student', 'Counselor']),
|
||||
{ path: '/grades', label: isStudent.value ? '学业成绩' : isTeacher.value ? '成绩录入' : '成绩管理' },
|
||||
@@ -181,6 +194,12 @@ const navigationGroups = computed<NavigationGroup[]>(() => [
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Leader', 'Teacher']),
|
||||
{ path: '/grade-analytics', label: isTeacher.value ? '教学班成绩分析' : '成绩分析中心' },
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'examinations',
|
||||
label: '考试管理',
|
||||
items: [
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'Student']),
|
||||
{ path: '/other-exams', label: '其他考试成绩' },
|
||||
@@ -199,26 +218,11 @@ const navigationGroups = computed<NavigationGroup[]>(() => [
|
||||
label: isStudent.value ? '我的补考' : isTeacher.value ? '补考监考' : '补考安排',
|
||||
},
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Teacher']),
|
||||
{
|
||||
path: '/course-adjustments',
|
||||
label: isTeacher.value ? '我的调停课' : '调停课审核',
|
||||
},
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor', 'Teacher', 'Student']),
|
||||
{ path: '/approvals', label: '审批中心' },
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'Counselor', 'Student']),
|
||||
{ path: '/warnings', label: '学业预警' },
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'student-status',
|
||||
label: '学籍管理',
|
||||
label: '学籍与服务',
|
||||
items: [
|
||||
...whenVisible(
|
||||
isStudent.value,
|
||||
@@ -232,6 +236,14 @@ const navigationGroups = computed<NavigationGroup[]>(() => [
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Student']),
|
||||
{ path: '/official-documents', label: isStudent.value ? '电子成绩单与证明' : '官方凭证签发' },
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor', 'Teacher', 'Student']),
|
||||
{ path: '/approvals', label: '审批中心' },
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'Counselor', 'Student']),
|
||||
{ path: '/warnings', label: '学业预警' },
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1274,6 +1274,9 @@ button { cursor: pointer; }
|
||||
.sso-binding-card > a { color: #315b73; font-size: 13px; font-weight: 650; text-decoration: none; }
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.desktop-navigation { padding-inline: 20px; }
|
||||
.horizontal-menu.el-menu--horizontal > .el-menu-item,
|
||||
.horizontal-menu.el-menu--horizontal > .el-sub-menu .el-sub-menu__title { padding-inline: 12px; }
|
||||
.metric-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.dashboard-grid { grid-template-columns: 1fr; }
|
||||
.login-page { grid-template-columns: 1fr 430px; }
|
||||
|
||||
Reference in New Issue
Block a user