fix: scope teacher students and grant admin access

bugfix/ai-assessment-evidence-rescore
chenyuan 1 month ago
parent ec5c86f3d2
commit eff4201cb7

@ -190,6 +190,7 @@ const selectedTeachingClass = ref(null);
const currentUserId = computed(() => userStore.userInfo.userId); const currentUserId = computed(() => userStore.userInfo.userId);
const currentSchoolId = computed(() => userStore.userInfo.schoolId); const currentSchoolId = computed(() => userStore.userInfo.schoolId);
const isManagerTeacher = computed(() => userStore.userInfo.teacherAdmin === true);
const legacyAdminEnabled = computed(() => userStore.schoolProductConfig?.organizationMode !== "TEACHING_CLASS_ONLY"); const legacyAdminEnabled = computed(() => userStore.schoolProductConfig?.organizationMode !== "TEACHING_CLASS_ONLY");
const facultyManagementEnabled = computed(() => userStore.schoolProductConfig?.facultyManagementEnabled ?? legacyAdminEnabled.value); const facultyManagementEnabled = computed(() => userStore.schoolProductConfig?.facultyManagementEnabled ?? legacyAdminEnabled.value);
const majorManagementEnabled = computed(() => userStore.schoolProductConfig?.majorManagementEnabled ?? legacyAdminEnabled.value); const majorManagementEnabled = computed(() => userStore.schoolProductConfig?.majorManagementEnabled ?? legacyAdminEnabled.value);
@ -290,6 +291,7 @@ function defaultMemberParams() {
schoolClassId: "", schoolClassId: "",
name: "", name: "",
userName: "", userName: "",
operatorId: currentUserId.value,
}; };
} }
@ -304,6 +306,9 @@ function canOperateClass(schoolClass) {
if (schoolClass?.dataSource === "ZHIYUN") { if (schoolClass?.dataSource === "ZHIYUN") {
return false; return false;
} }
if (isManagerTeacher.value) {
return !schoolClass?.schoolId || String(schoolClass.schoolId) === String(currentSchoolId.value);
}
if (normalizeClassType(schoolClass) === "ADMIN") { if (normalizeClassType(schoolClass) === "ADMIN") {
return !schoolClass?.schoolId || schoolClass.schoolId === currentSchoolId.value; return !schoolClass?.schoolId || schoolClass.schoolId === currentSchoolId.value;
} }

@ -11,7 +11,7 @@
<div class="df"> <div class="df">
<div class="online"> <div class="online">
<span>班级:</span> <span>班级:</span>
<el-select v-model="paramsquery.schoolClassId" placeholder="" style="width: 14rem" clearable class="ml10"> <el-select v-model="paramsquery.schoolClassId" placeholder="" style="width: 14rem" clearable class="ml10" @change="handleClassFilterChange">
<el-option v-for="school in studentClassOptions" :key="school.schoolClassId" :label="school.className" :value="school.schoolClassId" /> <el-option v-for="school in studentClassOptions" :key="school.schoolClassId" :label="school.className" :value="school.schoolClassId" />
</el-select> </el-select>
</div> </div>
@ -403,6 +403,11 @@ const normalizeClassType = (schoolClass) => {
return schoolClass?.createdBy ? "TEACHING" : "ADMIN"; return schoolClass?.createdBy ? "TEACHING" : "ADMIN";
}; };
const sameValue = (left, right) => String(left || "") === String(right || ""); 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) => { const canUseAdminClassForStudent = (schoolClass) => {
if (normalizeClassType(schoolClass) !== "ADMIN") return false; if (normalizeClassType(schoolClass) !== "ADMIN") return false;
return !schoolClass?.schoolId || sameValue(schoolClass.schoolId, currentSchoolId.value); return !schoolClass?.schoolId || sameValue(schoolClass.schoolId, currentSchoolId.value);
@ -414,7 +419,7 @@ const teachingClassOptions = computed(() =>
normalizeClassType(schoolClass) === "TEACHING" && normalizeClassType(schoolClass) === "TEACHING" &&
sameValue(schoolClass.schoolId, currentSchoolId.value) && sameValue(schoolClass.schoolId, currentSchoolId.value) &&
(isManagerTeacher.value || sameValue(schoolClass.createdBy, currentUserId.value)) (isManagerTeacher.value || sameValue(schoolClass.createdBy, currentUserId.value))
) ).sort((left, right) => classCreateTime(left) - classCreateTime(right))
); );
const studentClassOptions = computed(() => teachingClassOptions.value); const studentClassOptions = computed(() => teachingClassOptions.value);
const currentTeachingClassId = () => { const currentTeachingClassId = () => {
@ -430,10 +435,19 @@ const beforeImportStudents = (file) => {
return true; return true;
}; };
const getClassList = () => { const getClassList = () => {
indexApi.getClassListBySchoolId({ schoolId: userStore.userInfo.schoolId }).then((res) => { return indexApi.getClassListBySchoolId({ schoolId: userStore.userInfo.schoolId }).then((res) => {
classList.value = res.data; 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 classList1 = ref([]);
// 根据专业查班级 // 根据专业查班级
const getClassByMajor = () => { const getClassByMajor = () => {
@ -484,8 +498,9 @@ const initPassword = (row, status) => {
}; };
onMounted(async () => { onMounted(async () => {
await userStore.ensureSchoolProductConfig().catch(() => null); await userStore.ensureSchoolProductConfig().catch(() => null);
await getClassList();
selectDefaultStudentClass();
getList(); getList();
getClassList();
if (!isTeacherRosterMode.value) { if (!isTeacherRosterMode.value) {
getFacultyList(); getFacultyList();
} }

@ -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");

@ -9,6 +9,11 @@ assert(page.includes("operatorId: currentUserId.value"), "学生列表必须携
assert(page.includes("const isManagerTeacher = computed(() => userStore.userInfo.teacherAdmin === true);"), "教师管理员身份必须由当前登录账号识别"); assert(page.includes("const isManagerTeacher = computed(() => userStore.userInfo.teacherAdmin === true);"), "教师管理员身份必须由当前登录账号识别");
assert(page.includes("const studentClassOptions = computed(() => teachingClassOptions.value);"), "学生筛选下拉框必须只展示教学班"); assert(page.includes("const studentClassOptions = computed(() => teachingClassOptions.value);"), "学生筛选下拉框必须只展示教学班");
assert(page.includes("isManagerTeacher.value || sameValue(schoolClass.createdBy, currentUserId.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("const resolveRowTeachingClassId = (row) =>"), "未选择班级时操作必须从学生行解析教学班");
assert(page.includes('class="student-action-group"'), "学生操作按钮必须使用固定操作组布局"); assert(page.includes('class="student-action-group"'), "学生操作按钮必须使用固定操作组布局");
assert(page.includes("flex-wrap: nowrap"), "学生操作按钮不得换行"); assert(page.includes("flex-wrap: nowrap"), "学生操作按钮不得换行");

Loading…
Cancel
Save