diff --git a/src/api/teacher.js b/src/api/teacher.js index 262f133..ecf201c 100644 --- a/src/api/teacher.js +++ b/src/api/teacher.js @@ -354,6 +354,14 @@ export function importTeacherRosterMembers(teachingClassId, data) { headers: { "Content-Type": "multipart/form-data" }, }); } +export function importTeacherRosterStudents(data) { + return request({ + url: "/api/user/teaching-classes/students/import", + method: "POST", + data, + headers: { "Content-Type": "multipart/form-data" }, + }); +} export function importTeacherStudents(data) { return request({ url: "/api/user/importTeacherStudents", diff --git a/src/views/teacherEnd/student/index.vue b/src/views/teacherEnd/student/index.vue index 7d83bcd..56f7e9c 100644 --- a/src/views/teacherEnd/student/index.vue +++ b/src/views/teacherEnd/student/index.vue @@ -305,14 +305,9 @@ 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) => { + return indexApi.importTeacherRosterStudents(formData).then((res) => { handleSuccess(res); }); } @@ -365,11 +360,12 @@ const buildOwnedAdminClassRows = async () => { const downloadTemplate = async () => { const XLSX = await import("xlsx"); if (isTeacherRosterMode.value) { + const exampleClassName = teachingClassOptions.value[0]?.className || "教学一班"; const templateSheet = XLSX.utils.aoa_to_sheet([ - ["学生姓名", "学号"], - ["张三", "20260001"], + ["学生姓名", "学号", "班级"], + ["张三", "20260001", exampleClassName], ]); - templateSheet["!cols"] = [{ wch: 16 }, { wch: 18 }]; + templateSheet["!cols"] = [{ wch: 16 }, { wch: 18 }, { wch: 20 }]; const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, templateSheet, "学生导入模板"); XLSX.writeFile(workbook, "学生账号导入模板.xlsx"); diff --git a/tests/teacher-owned-student-management.static.test.cjs b/tests/teacher-owned-student-management.static.test.cjs index b3324a2..613ca94 100644 --- a/tests/teacher-owned-student-management.static.test.cjs +++ b/tests/teacher-owned-student-management.static.test.cjs @@ -3,6 +3,7 @@ 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"); +const api = fs.readFileSync(path.join(root, "src", "api", "teacher.js"), "utf8"); assert(page.includes("operatorId: currentUserId.value"), "学生列表必须携带当前教师"); assert(page.includes("const isManagerTeacher = computed(() => userStore.userInfo.teacherAdmin === true);"), "教师管理员身份必须由当前登录账号识别"); @@ -12,8 +13,9 @@ assert(page.includes("const resolveRowTeachingClassId = (row) =>"), "未选择 assert(page.includes('class="student-action-group"'), "学生操作按钮必须使用固定操作组布局"); assert(page.includes("flex-wrap: nowrap"), "学生操作按钮不得换行"); assert(!page.includes("仅查看"), "学生列表不应再展示仅查看操作"); -assert(page.includes("请选择自己的教学班后再导入学生"), "导入必须要求选中教学班"); -assert(page.includes('["学生姓名", "学号"]'), "教学班导入模板必须只有学生姓名和学号"); +assert(page.includes('["学生姓名", "学号", "班级"]'), "教学班导入模板必须包含班级列"); +assert(!page.includes("请选择自己的教学班后再导入学生"), "按班级导入不应要求页面先选中教学班"); +assert(api.includes('url: "/api/user/teaching-classes/students/import"'), "按班级导入必须调用新的上传接口"); assert(page.includes("initPassword(row, 1)"), "学生列表必须提供数据初始化操作"); console.log("teacher owned student management static checks passed");