fix: grant teacher admins class management access

bugfix/ai-assessment-evidence-rescore
chenyuan 1 month ago
parent f52ca9b6e7
commit d1b778a6d7

@ -91,20 +91,6 @@
<el-form-item label="班级名称" prop="className"> <el-form-item label="班级名称" prop="className">
<el-input v-model="formInline.className" placeholder="请输入班级名称" class="form-control" /> <el-input v-model="formInline.className" placeholder="请输入班级名称" class="form-control" />
</el-form-item> </el-form-item>
<el-form-item v-if="activeClassType === 'TEACHING' && isCreate" label="名单创建">
<div class="import-create-actions">
<el-upload
action="/api/user/uploadTeachingClassByStudentMembers"
:data="importCreateUploadData"
:show-file-list="false"
:before-upload="beforeImportCreate"
:http-request="uploadImportCreate"
>
<el-button type="primary">导入名单创建</el-button>
</el-upload>
<el-button @click="downloadTeachingClassImportTemplate">模板下载</el-button>
</div>
</el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<span class="dialog-footers"> <span class="dialog-footers">
@ -190,6 +176,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);
@ -236,15 +223,6 @@ const adminClassOptions = computed(() => {
}); });
}); });
const importCreateUploadData = computed(() => ({
schoolId: currentSchoolId.value,
schoolFacultyId: formInline.value.schoolFacultyId,
schoolMajorId: formInline.value.schoolMajorId,
className: formInline.value.className,
operatorId: currentUserId.value,
sourceClassIds: sourceAdminClassIds.value.join(","),
}));
const memberUploadData = computed(() => ({ const memberUploadData = computed(() => ({
teachingClassId: selectedTeachingClass.value?.schoolClassId || "", teachingClassId: selectedTeachingClass.value?.schoolClassId || "",
operatorId: currentUserId.value, operatorId: currentUserId.value,
@ -290,6 +268,7 @@ function defaultMemberParams() {
schoolClassId: "", schoolClassId: "",
name: "", name: "",
userName: "", userName: "",
operatorId: currentUserId.value,
}; };
} }
@ -304,6 +283,9 @@ function canOperateClass(schoolClass) {
if (schoolClass?.dataSource === "ZHIYUN") { if (schoolClass?.dataSource === "ZHIYUN") {
return false; return false;
} }
if (isManagerTeacher.value) {
return !schoolClass?.schoolId || schoolClass.schoolId === currentSchoolId.value;
}
if (normalizeClassType(schoolClass) === "ADMIN") { if (normalizeClassType(schoolClass) === "ADMIN") {
return !schoolClass?.schoolId || schoolClass.schoolId === currentSchoolId.value; return !schoolClass?.schoolId || schoolClass.schoolId === currentSchoolId.value;
} }
@ -419,71 +401,6 @@ function submitForm() {
}); });
} }
async function beforeImportCreate(file) {
if (activeClassType.value !== "TEACHING") {
proxy.$message.warning("请切换到教学班");
return false;
}
if (!formInline.value.schoolFacultyId || !formInline.value.schoolMajorId || !formInline.value.className) {
proxy.$message.warning("请先填写院系、专业和班级名称");
return false;
}
if (sourceAdminClassIds.value.length === 0) {
proxy.$message.warning("请选择来源行政班");
return false;
}
const total = await getSelectedSourceAdminStudentTotal();
if (total <= 0) {
proxy.$message.warning("所选来源行政班暂无学生,请先在学生管理中导入行政班学生后再创建教学班");
return false;
}
if (!/\.(xls|xlsx)$/i.test(file.name)) {
proxy.$message.warning("请选择xls或xlsx格式文件");
return false;
}
return true;
}
async function getSelectedSourceAdminStudentTotal() {
const results = await Promise.all(sourceAdminClassIds.value.map((schoolClassId) => {
return indexApi.getStudentList({
index: 1,
size: 1,
schoolId: currentSchoolId.value,
schoolClassId,
});
}));
return results.reduce((sum, res) => sum + Number(res.data?.total || 0), 0);
}
function uploadImportCreate(options, confirmMultiTeachingClass = false) {
const formData = buildUploadFormData(options.file, importCreateUploadData.value, confirmMultiTeachingClass);
return indexApi
.uploadTeachingClassByStudentMembers(formData)
.then((res) => {
handleImportCreateSuccess(res);
})
.catch((error) => {
if (!isMultiTeachingClassConflict(error)) return;
return ElMessageBox.confirm(multiTeachingClassMessage(error), "学生已在其他教学班", {
confirmButtonText: "继续导入创建",
cancelButtonText: "取消",
type: "warning",
}).then(() => uploadImportCreate(options, true));
});
}
function handleImportCreateSuccess(res) {
if (res?.statusCode && res.statusCode !== "OK" && res.statusCode !== 200) {
proxy.$message.error(res?.message || "导入创建失败");
return;
}
proxy.$message.success("导入创建成功");
dialogVisible.value = false;
getList();
refreshAllClassList();
}
function openMemberDialog(schoolClass) { function openMemberDialog(schoolClass) {
selectedTeachingClass.value = schoolClass; selectedTeachingClass.value = schoolClass;
memberParams.value = { memberParams.value = {
@ -653,28 +570,6 @@ async function downloadMemberImportTemplate() {
XLSX.writeFile(workbook, "教学班成员导入模板.xlsx"); XLSX.writeFile(workbook, "教学班成员导入模板.xlsx");
} }
async function downloadTeachingClassImportTemplate() {
const XLSX = await import("xlsx");
const templateSheet = XLSX.utils.aoa_to_sheet([
["所属院系", "所属专业", "行政班", "学号", "学生姓名", "性别", "手机号", "邮箱"],
["商学院", "电子商务", "2026电子商务1班-行政班", "20260001", "张三", "男", "13800000000", "zhangsan@example.com"],
]);
templateSheet["!cols"] = [{ wch: 18 }, { wch: 18 }, { wch: 28 }, { wch: 18 }, { wch: 16 }, { wch: 10 }, { wch: 18 }, { wch: 26 }];
const guideSheet = XLSX.utils.aoa_to_sheet([
["填写说明"],
["1. 先在新增教学班弹窗中选择院系、专业并填写班级名称;来源行政班可以不选。"],
["2. 不要填写任何数据ID,院系、专业、行政班请填写页面中的名称。"],
["3. 学生必须已存在于对应行政班;如果行政班暂无学生,请先在学生管理中导入行政班学生。"],
["4. 系统会按模板学生名单加入新教学班;学生若已在其他教学班,将自动转入新教学班。"],
["5. 任意一行校验失败时,整批导入创建失败,教学班和成员关系都不会写入。"],
]);
guideSheet["!cols"] = [{ wch: 96 }];
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, templateSheet, "教学班名单创建模板");
XLSX.utils.book_append_sheet(workbook, guideSheet, "填写说明");
XLSX.writeFile(workbook, "教学班名单创建模板.xlsx");
}
function deleteClass(id) { function deleteClass(id) {
ElMessageBox.confirm("确定删除该班级吗?", "提示", { ElMessageBox.confirm("确定删除该班级吗?", "提示", {
confirmButtonText: "确定", confirmButtonText: "确定",
@ -866,13 +761,6 @@ onMounted(() => {
width: 100%; width: 100%;
} }
.import-create-actions {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.member-toolbar { .member-toolbar {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;

@ -0,0 +1,20 @@
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(!/导入名单创建/.test(page));
assert(!/downloadTeachingClassImportTemplate/.test(page));
assert(!/uploadTeachingClassByStudentMembers/.test(page));
assert(!/beforeImportCreate/.test(page));
assert(/const isManagerTeacher = computed\(\(\) => userStore\.userInfo\.teacherAdmin === true\);/.test(page));
assert(/if \(isManagerTeacher\.value\) \{[\s\S]*schoolClass\.schoolId === currentSchoolId\.value;[\s\S]*\}/.test(page));
assert(/const selectedTeachingClassCanOperate = computed\(\(\) => canOperateClass\(selectedTeachingClass\.value\)\);/.test(page));
assert(/operatorId: currentUserId\.value,[\s\S]*function normalizeClassType/.test(page));
assert(/v-if="canOperateClass\(row\.schoolClass\)"/.test(page));
console.log("teacher administrator class access contract passed");
Loading…
Cancel
Save