diff --git a/src/views/teacherEnd/student/index.vue b/src/views/teacherEnd/student/index.vue index 81cd6cb..d2d7b21 100644 --- a/src/views/teacherEnd/student/index.vue +++ b/src/views/teacherEnd/student/index.vue @@ -12,7 +12,7 @@
班级: - +
@@ -70,6 +70,7 @@ 编辑 删除 密码初始化 + 数据初始化 仅查看 @@ -186,7 +187,7 @@ const status = ref(false); const tableData = ref([]); // 获取院校列表 const getList = () => { - indexApi.getStudentList(paramsquery.value).then((res) => { + indexApi.getStudentList({ ...paramsquery.value, operatorId: currentUserId.value }).then((res) => { tableData.value = res.data.list; schoolTotal.value = res.data.total; }); @@ -303,6 +304,18 @@ const getMajorList = () => { }); }; const uploadStudents = (options) => { + if (isTeacherRosterMode.value) { + const teachingClassId = currentTeachingClassId(); + if (!teachingClassId) { + proxy.$message.warning("请选择自己的教学班后再导入学生"); + return Promise.reject(new Error("teaching class is required")); + } + const formData = new FormData(); + formData.append("file", options.file); + return indexApi.importTeacherRosterMembers(teachingClassId, formData).then((res) => { + handleSuccess(res); + }); + } const formData = buildStudentImportFormData(options.file); return indexApi.importTeacherStudents(formData).then((res) => { handleSuccess(res); @@ -318,7 +331,7 @@ const handleSuccess = (res, file) => { }; // 导出教师账号 const exportTeacher = () => { - indexApi.exportStudentList({ schoolId: userStore.userInfo.schoolId }).then((res) => { + indexApi.exportStudentList({ schoolId: userStore.userInfo.schoolId, operatorId: currentUserId.value, schoolClassId: currentTeachingClassId() }).then((res) => { const blob = new Blob([res], { type: "application/vnd.ms-excel" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); @@ -351,6 +364,17 @@ const buildOwnedAdminClassRows = async () => { const downloadTemplate = async () => { const XLSX = await import("xlsx"); + if (isTeacherRosterMode.value) { + const templateSheet = XLSX.utils.aoa_to_sheet([ + ["学生姓名", "学号"], + ["张三", "20260001"], + ]); + templateSheet["!cols"] = [{ wch: 16 }, { wch: 18 }]; + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, templateSheet, "学生导入模板"); + XLSX.writeFile(workbook, "学生账号导入模板.xlsx"); + return; + } const adminClassRows = await buildOwnedAdminClassRows(); const firstAdminClass = adminClassRows[0] || ["电子商务学院", "电子商务", "行政一班"]; const templateSheet = XLSX.utils.aoa_to_sheet([ @@ -389,6 +413,9 @@ const canUseAdminClassForStudent = (schoolClass) => { }; const classMap = computed(() => new Map(classList.value.map((item) => [item.schoolClassId, item]))); const adminClassList = computed(() => classList.value.filter((item) => canUseAdminClassForStudent(item))); +const studentClassOptions = computed(() => + isTeacherRosterMode.value ? teachingClassOptions.value : adminClassList.value +); const teachingClassOptions = computed(() => classList.value.filter( (schoolClass) => @@ -399,6 +426,11 @@ const teachingClassOptions = computed(() => ); const canOperateStudent = (row) => { const selectedClass = classMap.value.get(paramsquery.value.schoolClassId); + if (isTeacherRosterMode.value) { + return Boolean(selectedClass) + && normalizeClassType(selectedClass) === "TEACHING" + && sameValue(selectedClass.createdBy, currentUserId.value); + } if (selectedClass && normalizeClassType(selectedClass) === "TEACHING") { return sameValue(selectedClass.createdBy, currentUserId.value); } diff --git a/tests/teacher-owned-student-management.static.test.cjs b/tests/teacher-owned-student-management.static.test.cjs new file mode 100644 index 0000000..a74ffbf --- /dev/null +++ b/tests/teacher-owned-student-management.static.test.cjs @@ -0,0 +1,13 @@ +const assert = require("assert"); +const fs = require("fs"); +const path = require("path"); +const root = path.join(__dirname, ".."); +const page = fs.readFileSync(path.join(root, "src", "views", "teacherEnd", "student", "index.vue"), "utf8"); + +assert(page.includes("operatorId: currentUserId.value"), "学生列表必须携带当前教师"); +assert(page.includes("isTeacherRosterMode.value ? teachingClassOptions.value : adminClassList.value"), "教学班模式必须只显示教师自有教学班"); +assert(page.includes("请选择自己的教学班后再导入学生"), "导入必须要求选中教学班"); +assert(page.includes('["学生姓名", "学号"]'), "教学班导入模板必须只有学生姓名和学号"); +assert(page.includes("initPassword(row, 1)"), "学生列表必须提供数据初始化操作"); + +console.log("teacher owned student management static checks passed");