diff --git a/src/views/teacherEnd/class/index.vue b/src/views/teacherEnd/class/index.vue
index 8376ff9..1c414c3 100644
--- a/src/views/teacherEnd/class/index.vue
+++ b/src/views/teacherEnd/class/index.vue
@@ -190,6 +190,7 @@ const selectedTeachingClass = ref(null);
const currentUserId = computed(() => userStore.userInfo.userId);
const currentSchoolId = computed(() => userStore.userInfo.schoolId);
+const isManagerTeacher = computed(() => userStore.userInfo.teacherAdmin === true);
const legacyAdminEnabled = computed(() => userStore.schoolProductConfig?.organizationMode !== "TEACHING_CLASS_ONLY");
const facultyManagementEnabled = computed(() => userStore.schoolProductConfig?.facultyManagementEnabled ?? legacyAdminEnabled.value);
const majorManagementEnabled = computed(() => userStore.schoolProductConfig?.majorManagementEnabled ?? legacyAdminEnabled.value);
@@ -290,6 +291,7 @@ function defaultMemberParams() {
schoolClassId: "",
name: "",
userName: "",
+ operatorId: currentUserId.value,
};
}
@@ -304,6 +306,9 @@ function canOperateClass(schoolClass) {
if (schoolClass?.dataSource === "ZHIYUN") {
return false;
}
+ if (isManagerTeacher.value) {
+ return !schoolClass?.schoolId || String(schoolClass.schoolId) === String(currentSchoolId.value);
+ }
if (normalizeClassType(schoolClass) === "ADMIN") {
return !schoolClass?.schoolId || schoolClass.schoolId === currentSchoolId.value;
}
diff --git a/src/views/teacherEnd/student/index.vue b/src/views/teacherEnd/student/index.vue
index 56f7e9c..cc84d8d 100644
--- a/src/views/teacherEnd/student/index.vue
+++ b/src/views/teacherEnd/student/index.vue
@@ -11,7 +11,7 @@
班级:
-
+
@@ -403,6 +403,11 @@ const normalizeClassType = (schoolClass) => {
return schoolClass?.createdBy ? "TEACHING" : "ADMIN";
};
const sameValue = (left, right) => String(left || "") === String(right || "");
+const classCreateTime = (schoolClass) => {
+ if (!schoolClass?.createTime) return Number.MAX_SAFE_INTEGER;
+ const value = new Date(schoolClass.createTime).getTime();
+ return Number.isNaN(value) ? Number.MAX_SAFE_INTEGER : value;
+};
const canUseAdminClassForStudent = (schoolClass) => {
if (normalizeClassType(schoolClass) !== "ADMIN") return false;
return !schoolClass?.schoolId || sameValue(schoolClass.schoolId, currentSchoolId.value);
@@ -414,7 +419,7 @@ const teachingClassOptions = computed(() =>
normalizeClassType(schoolClass) === "TEACHING" &&
sameValue(schoolClass.schoolId, currentSchoolId.value) &&
(isManagerTeacher.value || sameValue(schoolClass.createdBy, currentUserId.value))
- )
+ ).sort((left, right) => classCreateTime(left) - classCreateTime(right))
);
const studentClassOptions = computed(() => teachingClassOptions.value);
const currentTeachingClassId = () => {
@@ -430,10 +435,19 @@ const beforeImportStudents = (file) => {
return true;
};
const getClassList = () => {
- indexApi.getClassListBySchoolId({ schoolId: userStore.userInfo.schoolId }).then((res) => {
+ return indexApi.getClassListBySchoolId({ schoolId: userStore.userInfo.schoolId }).then((res) => {
classList.value = res.data;
});
};
+const selectDefaultStudentClass = () => {
+ if (!isManagerTeacher.value && !paramsquery.value.schoolClassId) {
+ paramsquery.value.schoolClassId = teachingClassOptions.value[0]?.schoolClassId || "";
+ }
+};
+const handleClassFilterChange = () => {
+ paramsquery.value.index = 1;
+ getList();
+};
const classList1 = ref([]);
// 根据专业查班级
const getClassByMajor = () => {
@@ -484,8 +498,9 @@ const initPassword = (row, status) => {
};
onMounted(async () => {
await userStore.ensureSchoolProductConfig().catch(() => null);
+ await getClassList();
+ selectDefaultStudentClass();
getList();
- getClassList();
if (!isTeacherRosterMode.value) {
getFacultyList();
}
diff --git a/tests/teacher-admin-class-access.static.test.cjs b/tests/teacher-admin-class-access.static.test.cjs
new file mode 100644
index 0000000..0f9dfe8
--- /dev/null
+++ b/tests/teacher-admin-class-access.static.test.cjs
@@ -0,0 +1,16 @@
+const assert = require("assert");
+const fs = require("fs");
+const path = require("path");
+
+const page = fs.readFileSync(
+ path.resolve(__dirname, "../src/views/teacherEnd/class/index.vue"),
+ "utf8"
+);
+
+assert(page.includes("const isManagerTeacher = computed(() => userStore.userInfo.teacherAdmin === true);"));
+assert(/if \(isManagerTeacher\.value\) \{[\s\S]*schoolClass\.schoolId[\s\S]*currentSchoolId\.value[\s\S]*\}/.test(page));
+assert(page.includes("const selectedTeachingClassCanOperate = computed(() => canOperateClass(selectedTeachingClass.value));"));
+assert(/function defaultMemberParams\(\) \{[\s\S]*operatorId: currentUserId\.value,[\s\S]*\}/.test(page));
+assert(page.includes('v-if="canOperateClass(row.schoolClass)"'));
+
+console.log("teacher administrator class access contract passed");
diff --git a/tests/teacher-owned-student-management.static.test.cjs b/tests/teacher-owned-student-management.static.test.cjs
index 613ca94..6a0773b 100644
--- a/tests/teacher-owned-student-management.static.test.cjs
+++ b/tests/teacher-owned-student-management.static.test.cjs
@@ -9,6 +9,11 @@ assert(page.includes("operatorId: currentUserId.value"), "学生列表必须携
assert(page.includes("const isManagerTeacher = computed(() => userStore.userInfo.teacherAdmin === true);"), "教师管理员身份必须由当前登录账号识别");
assert(page.includes("const studentClassOptions = computed(() => teachingClassOptions.value);"), "学生筛选下拉框必须只展示教学班");
assert(page.includes("isManagerTeacher.value || sameValue(schoolClass.createdBy, currentUserId.value)"), "教师管理员必须可查看本校全部教学班");
+assert(page.includes(".sort((left, right) => classCreateTime(left) - classCreateTime(right))"), "普通教师的班级选项必须按创建时间升序排列");
+assert(page.includes("if (!isManagerTeacher.value && !paramsquery.value.schoolClassId)"), "普通教师必须默认选中自己最早创建的教学班");
+assert(page.includes('paramsquery.value.schoolClassId = teachingClassOptions.value[0]?.schoolClassId || "";'), "默认班级必须取排序后的第一个教学班");
+assert(page.includes("await getClassList();\n selectDefaultStudentClass();\n getList();"), "学生列表必须在默认班级确定后查询");
+assert(page.includes('@change="handleClassFilterChange"'), "切换班级后必须立即刷新学生列表");
assert(page.includes("const resolveRowTeachingClassId = (row) =>"), "未选择班级时操作必须从学生行解析教学班");
assert(page.includes('class="student-action-group"'), "学生操作按钮必须使用固定操作组布局");
assert(page.includes("flex-wrap: nowrap"), "学生操作按钮不得换行");