You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dianshang-qianduan/src/views/teacherEnd/class/index.vue

781 lines
27 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="class-page app-container">
<el-tabs v-if="adminClassManagementEnabled" v-model="activeClassType" class="class-tabs" @tab-change="handleTabChange">
<el-tab-pane label="行政班" name="ADMIN" />
<el-tab-pane label="教学班" name="TEACHING" />
</el-tabs>
<div class="query-bar">
<el-select v-if="facultyManagementEnabled" v-model="paramsquery.schoolFacultyId" placeholder="所属院系" clearable class="query-control" @change="getMajorList">
<el-option v-for="faculty in facultyList" :key="faculty.schoolFacultyId" :label="faculty.schoolFacultyName" :value="faculty.schoolFacultyId" />
</el-select>
<el-select v-if="majorManagementEnabled" v-model="paramsquery.schoolMajorId" placeholder="所属专业" clearable class="query-control">
<el-option v-for="major in majorList" :key="major.schoolMajorId" :label="major.schoolMajorName" :value="major.schoolMajorId" />
</el-select>
<el-input v-model="paramsquery.className" placeholder="班级名称" clearable class="query-control" />
<el-button type="primary" :icon="Search" @click="getList">查询</el-button>
<el-button :icon="Refresh" @click="refresh">刷新</el-button>
</div>
<div v-if="canCreateCurrentClass" class="table-actions">
<el-button type="primary" :icon="Plus" @click="openCreateDialog">新增{{ activeClassType === 'ADMIN' ? '行政班' : '教学班' }}</el-button>
</div>
<el-table :data="filteredTableData" border v-loading="loading" class="class-table" :header-cell-style="tableHeaderStyle">
<el-table-column label="班级名称" prop="schoolClass.className" align="center" />
<el-table-column v-if="facultyManagementEnabled" label="所属院系" align="center">
<template #default="{ row }">
<span>{{ row.schoolFacultyName || "-" }}</span>
</template>
</el-table-column>
<el-table-column v-if="majorManagementEnabled" label="所属专业" align="center">
<template #default="{ row }">
<span>{{ row.schoolMajorName || "-" }}</span>
</template>
</el-table-column>
<el-table-column label="创建人" align="center">
<template #default="{ row }">
<span>{{ row.createdByName || "-" }}</span>
</template>
</el-table-column>
<el-table-column label="数据来源" align="center" width="120">
<template #default="{ row }">
<el-tag :type="row.schoolClass.dataSource === 'ZHIYUN' ? 'warning' : 'success'">
{{ row.schoolClass.dataSource === "ZHIYUN" ? "智云" : "本系统" }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" prop="schoolClass.createTime" align="center" width="180">
<template #default="{ row }">
<span>{{ formatDate(row.schoolClass.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" min-width="320">
<template #default="{ row }">
<div class="action-buttons">
<el-button v-if="activeClassType === 'TEACHING'" type="primary" text @click="openMemberDialog(row.schoolClass)">
成员管理
</el-button>
<template v-if="canOperateClass(row.schoolClass)">
<el-button type="primary" text @click="editClass(row)">编辑</el-button>
<el-button type="danger" text @click="deleteClass(row.schoolClass.schoolClassId)">删除</el-button>
<el-button v-if="activeClassType === 'TEACHING'" type="warning" text @click="initializeClass(row.schoolClass)">
数据初始化
</el-button>
</template>
<el-tag v-else type="info">仅查看</el-tag>
</div>
</template>
</el-table-column>
</el-table>
<pagination v-show="schoolTotal > 0" :total="schoolTotal" v-model:page="paramsquery.index" v-model:limit="paramsquery.size" @pagination="getList" />
<el-dialog v-model="dialogVisible" width="520px" :title="dialogTitle" class="teacher-dialog" @close="onClose">
<el-form ref="formInlineref" :model="formInline" label-width="96px" :rules="rules">
<el-form-item v-if="facultyManagementEnabled" label="所属院系" prop="schoolFacultyId">
<el-select v-model="formInline.schoolFacultyId" placeholder="请选择院系" clearable class="form-control" @change="getMajorListForForm">
<el-option v-for="faculty in facultyList" :key="faculty.schoolFacultyId" :label="faculty.schoolFacultyName" :value="faculty.schoolFacultyId" />
</el-select>
</el-form-item>
<el-form-item v-if="majorManagementEnabled" label="所属专业" prop="schoolMajorId">
<el-select v-model="formInline.schoolMajorId" placeholder="请选择专业" clearable class="form-control" @change="handleFormMajorChange">
<el-option v-for="major in majorListForForm" :key="major.schoolMajorId" :label="major.schoolMajorName" :value="major.schoolMajorId" />
</el-select>
</el-form-item>
<el-form-item v-if="activeClassType === 'TEACHING' && isCreate && adminClassManagementEnabled" label="来源行政班" prop="sourceClassIds">
<el-select v-model="sourceAdminClassIds" placeholder="请选择来源行政班" clearable multiple collapse-tags collapse-tags-tooltip class="form-control">
<el-option v-for="schoolClass in adminClassOptions" :key="schoolClass.schoolClassId" :label="schoolClass.className" :value="schoolClass.schoolClassId" />
</el-select>
</el-form-item>
<el-form-item label="班级名称" prop="className">
<el-input v-model="formInline.className" placeholder="请输入班级名称" class="form-control" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footers">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="memberDialogVisible" width="900px" :title="memberDialogTitle" class="teacher-dialog" @close="closeMemberDialog">
<div class="member-toolbar">
<el-input v-model="memberParams.name" placeholder="学生姓名" clearable class="member-query" />
<el-input v-model="memberParams.userName" placeholder="学号" clearable class="member-query" />
<el-button type="primary" :icon="Search" @click="getMemberList">查询</el-button>
<el-button :icon="Refresh" @click="refreshMemberList">刷新</el-button>
<template v-if="selectedTeachingClassCanOperate">
<el-upload
action="/api/user/uploadTeachingClassStudentMembers"
:data="memberUploadData"
:show-file-list="false"
:before-upload="beforeImportMembers"
:http-request="uploadMemberImport"
>
<el-button type="primary">导入成员</el-button>
</el-upload>
<el-button @click="downloadMemberImportTemplate">模板下载</el-button>
</template>
</div>
<el-table :data="memberList" border v-loading="memberLoading" class="member-table" :header-cell-style="tableHeaderStyle">
<el-table-column label="学生姓名" prop="name" align="center" />
<el-table-column label="学号" prop="username" align="center" />
<el-table-column label="所属班级" prop="className" align="center" />
<el-table-column label="电话" prop="phone" align="center" />
<el-table-column label="邮箱" prop="email" align="center" />
<el-table-column label="账号来源" prop="codeFrom" align="center" />
<el-table-column label="操作" align="center" width="210">
<template #default="{ row }">
<template v-if="selectedTeachingClassCanOperate">
<el-button type="danger" text @click="removeMember(row)">移除</el-button>
<el-button type="primary" text @click="initializeMember(row)">数据初始化</el-button>
</template>
<el-tag v-else type="info">仅查看</el-tag>
</template>
</el-table-column>
</el-table>
<pagination
v-show="memberTotal > 0"
:total="memberTotal"
v-model:page="memberParams.index"
v-model:limit="memberParams.size"
@pagination="getMemberList"
/>
</el-dialog>
</div>
</template>
<script setup>
import { Plus, Refresh, Search } from "@element-plus/icons-vue";
import { ElMessageBox } from "element-plus";
import { formatDate } from "@/utils/index";
import useUserStore from "@/store/modules/user";
import * as indexApi from "@/api/teacher";
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const activeClassType = ref("ADMIN");
const dialogVisible = ref(false);
const memberDialogVisible = ref(false);
const loading = ref(false);
const memberLoading = ref(false);
const isCreate = ref(true);
const tableData = ref([]);
const memberList = ref([]);
const schoolTotal = ref(0);
const memberTotal = ref(0);
const facultyList = ref([]);
const majorList = ref([]);
const majorListForForm = ref([]);
const allClassList = ref([]);
const sourceAdminClassIds = ref([]);
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);
const adminClassManagementEnabled = computed(() => userStore.schoolProductConfig?.adminClassManagementEnabled ?? legacyAdminEnabled.value);
const isTeacherRosterMode = computed(() => !facultyManagementEnabled.value && !majorManagementEnabled.value && !adminClassManagementEnabled.value);
const canCreateCurrentClass = computed(() => activeClassType.value === "ADMIN" || activeClassType.value === "TEACHING");
const paramsquery = ref({
index: 1,
size: 10,
schoolId: currentSchoolId.value,
schoolFacultyId: "",
schoolMajorId: "",
className: "",
});
const formInline = ref(defaultForm());
const memberParams = ref(defaultMemberParams());
const rules = computed(() => ({
...(facultyManagementEnabled.value ? { schoolFacultyId: [{ required: true, message: "请选择所属院系", trigger: "change" }] } : {}),
...(majorManagementEnabled.value ? { schoolMajorId: [{ required: true, message: "请选择所属专业", trigger: "change" }] } : {}),
className: [{ required: true, message: "请输入班级名称", trigger: "blur" }],
}));
const tableHeaderStyle = {
color: "#0f3052",
fontSize: "14px",
backgroundColor: "#eaf4ff",
};
const dialogTitle = computed(() => `${isCreate.value ? "新增" : "编辑"}${activeClassType.value === "ADMIN" ? "行政班" : "教学班"}`);
const memberDialogTitle = computed(() => `${selectedTeachingClass.value?.className || ""} 成员管理`);
const selectedTeachingClassCanOperate = computed(() => canOperateClass(selectedTeachingClass.value));
const filteredTableData = computed(() => {
return tableData.value.filter((row) => normalizeClassType(row.schoolClass) === activeClassType.value);
});
const adminClassOptions = computed(() => {
return allClassList.value.filter((schoolClass) => {
return normalizeClassType(schoolClass) === "ADMIN"
&& (!formInline.value.schoolMajorId || schoolClass.schoolMajorId === formInline.value.schoolMajorId);
});
});
const memberUploadData = computed(() => ({
teachingClassId: selectedTeachingClass.value?.schoolClassId || "",
operatorId: currentUserId.value,
}));
function isMultiTeachingClassConflict(error) {
return error?.response?.data?.code === 409;
}
function multiTeachingClassMessage(error) {
const body = error?.response?.data || {};
const students = Array.isArray(body.data) ? body.data : [];
const details = students.length ? `\n${students.slice(0, 12).join("、")}${students.length > 12 ? " 等" : ""}` : "";
return `${body.msg || "部分学生已在其他教学班,是否继续操作?"}${details}`;
}
function buildUploadFormData(file, data, confirmMultiTeachingClass = false) {
const formData = new FormData();
formData.append("file", file);
Object.keys(data).forEach((key) => {
formData.append(key, data[key] ?? "");
});
formData.append("confirmMultiTeachingClass", confirmMultiTeachingClass);
return formData;
}
function defaultForm() {
return {
schoolFacultyId: "",
schoolId: currentSchoolId.value,
schoolMajorId: "",
className: "",
classType: activeClassType.value,
sourceClassIds: "",
};
}
function defaultMemberParams() {
return {
index: 1,
size: 10,
schoolId: currentSchoolId.value,
schoolClassId: "",
name: "",
userName: "",
operatorId: currentUserId.value,
};
}
function normalizeClassType(schoolClass) {
if (schoolClass?.classType) {
return schoolClass.classType;
}
return schoolClass?.createdBy ? "TEACHING" : "ADMIN";
}
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;
}
return schoolClass?.createdBy === currentUserId.value;
}
function getList(options = {}) {
const { showLoading = true } = options;
if (showLoading) {
loading.value = true;
}
indexApi
.getClassesList({
...paramsquery.value,
operatorId: currentUserId.value,
})
.then((res) => {
tableData.value = res.data?.list || [];
schoolTotal.value = res.data?.total || 0;
})
.finally(() => {
if (showLoading) {
loading.value = false;
}
});
}
function handleTabChange() {
paramsquery.value.index = 1;
getList();
}
function openCreateDialog() {
if (!canCreateCurrentClass.value) {
proxy.$message.warning("普通教师不能新增行政班");
return;
}
isCreate.value = true;
formInline.value = defaultForm();
sourceAdminClassIds.value = [];
dialogVisible.value = true;
}
function editClass(row) {
const schoolClass = row?.schoolClass || row;
const schoolFacultyId = schoolClass?.schoolFacultyId || row?.schoolFacultyId || "";
const schoolMajorId = schoolClass?.schoolMajorId || row?.schoolMajorId || "";
isCreate.value = false;
formInline.value = {
...schoolClass,
schoolFacultyId,
schoolMajorId,
classType: normalizeClassType(schoolClass),
userId: currentUserId.value,
};
sourceAdminClassIds.value = [];
majorListForForm.value = [];
dialogVisible.value = true;
hydrateClassFormOptions(formInline.value);
}
function addClass(confirmMultiTeachingClass = false) {
const payload = {
...formInline.value,
schoolId: currentSchoolId.value,
classType: activeClassType.value,
sourceClassIds: activeClassType.value === "TEACHING" ? sourceAdminClassIds.value.join(",") : "",
userId: currentUserId.value,
confirmMultiTeachingClass,
};
indexApi
.addClass(payload)
.then(() => {
proxy.$message.success("添加成功");
dialogVisible.value = false;
getList({ showLoading: false });
refreshAllClassList();
})
.catch((error) => {
if (!isMultiTeachingClassConflict(error)) return;
ElMessageBox.confirm(multiTeachingClassMessage(error), "学生已在其他教学班", {
confirmButtonText: "继续创建",
cancelButtonText: "取消",
type: "warning",
}).then(() => addClass(true));
});
}
function updateClass() {
const payload = {
...formInline.value,
schoolId: currentSchoolId.value,
classType: activeClassType.value,
userId: currentUserId.value,
status: true,
};
indexApi.updateClass(payload).then(() => {
proxy.$message.success("编辑成功");
dialogVisible.value = false;
getList({ showLoading: false });
refreshAllClassList();
});
}
function submitForm() {
proxy.$refs.formInlineref.validate((valid) => {
if (!valid) return;
if (adminClassManagementEnabled.value && isCreate.value && activeClassType.value === "TEACHING" && sourceAdminClassIds.value.length === 0) {
proxy.$message.warning("请选择来源行政班");
return;
}
isCreate.value ? addClass() : updateClass();
});
}
function openMemberDialog(schoolClass) {
selectedTeachingClass.value = schoolClass;
memberParams.value = {
...defaultMemberParams(),
schoolClassId: schoolClass.schoolClassId,
};
memberDialogVisible.value = true;
getMemberList();
}
function closeMemberDialog() {
selectedTeachingClass.value = null;
memberList.value = [];
memberTotal.value = 0;
memberParams.value = defaultMemberParams();
}
function getMemberList() {
if (!memberParams.value.schoolClassId) {
return;
}
memberLoading.value = true;
indexApi
.getStudentList(memberParams.value)
.then((res) => {
memberList.value = res.data?.list || [];
memberTotal.value = res.data?.total || 0;
})
.finally(() => {
memberLoading.value = false;
});
}
function refreshMemberList() {
memberParams.value.name = "";
memberParams.value.userName = "";
memberParams.value.index = 1;
getMemberList();
}
function beforeImportMembers(file) {
if (!selectedTeachingClass.value?.schoolClassId) {
proxy.$message.warning("请先选择教学班");
return false;
}
if (!selectedTeachingClassCanOperate.value) {
proxy.$message.warning("只能维护自己创建的教学班成员");
return false;
}
if (!/\.(xls|xlsx)$/i.test(file.name)) {
proxy.$message.warning("请选择xls或xlsx格式文件");
return false;
}
return true;
}
function uploadMemberImport(options, confirmMultiTeachingClass = false) {
if (isTeacherRosterMode.value) {
const formData = new FormData();
formData.append("file", options.file);
return indexApi
.importTeacherRosterMembers(selectedTeachingClass.value.schoolClassId, formData)
.then((res) => {
handleMemberImportSuccess(res);
});
}
const formData = buildUploadFormData(options.file, memberUploadData.value, confirmMultiTeachingClass);
return indexApi
.uploadTeachingClassStudentMembers(formData)
.then((res) => {
handleMemberImportSuccess(res);
})
.catch((error) => {
if (!isMultiTeachingClassConflict(error)) return;
return ElMessageBox.confirm(multiTeachingClassMessage(error), "学生已在其他教学班", {
confirmButtonText: "继续导入",
cancelButtonText: "取消",
type: "warning",
}).then(() => uploadMemberImport(options, true));
});
}
function handleMemberImportSuccess(res) {
if (res?.statusCode && res.statusCode !== "OK" && res.statusCode !== 200) {
proxy.$message.error(res?.message || "导入失败");
return;
}
proxy.$message.success("导入成功");
getMemberList();
}
function removeMember(row) {
ElMessageBox.confirm("确定将该学生从当前教学班移除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
indexApi
.deleteStudent({
userId: row.userId,
operatorId: currentUserId.value,
teachingClassId: selectedTeachingClass.value.schoolClassId,
})
.then(() => {
proxy.$message.success("移除成功");
getMemberList();
});
});
}
function initializeMember(row) {
ElMessageBox.confirm("确定初始化该学生在当前教学班的实训数据吗?该操作不可恢复。", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
indexApi
.initializeTeachingClassStudentTrainingData({
teachingClassId: selectedTeachingClass.value.schoolClassId,
studentUserId: row.userId,
operatorId: currentUserId.value,
})
.then(() => {
proxy.$message.success("初始化成功");
});
});
}
async function downloadMemberImportTemplate() {
const XLSX = await import("xlsx");
if (isTeacherRosterMode.value) {
const templateSheet = XLSX.utils.aoa_to_sheet([
["学生姓名", "学号"],
["张三", "20260001"],
]);
templateSheet["!cols"] = [{ wch: 16 }, { wch: 18 }];
const guideSheet = XLSX.utils.aoa_to_sheet([
["填写说明"],
["1. 本模板用于向当前教学班添加成员。"],
["2. 仅填写学生姓名和学号,不需要填写班级或其他个人信息。"],
["3. 学号已存在时,系统会复用该学生并加入当前教学班。"],
["4. 任意一行校验失败时,整批导入失败并返回失败原因。"],
]);
guideSheet["!cols"] = [{ wch: 72 }];
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, templateSheet, "教学班成员导入模板");
XLSX.utils.book_append_sheet(workbook, guideSheet, "填写说明");
XLSX.writeFile(workbook, "教学班成员导入模板.xlsx");
return;
}
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. 任意一行校验失败时,整批导入失败并返回失败原因。"],
]);
guideSheet["!cols"] = [{ wch: 72 }];
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) {
ElMessageBox.confirm("确定删除该班级吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
indexApi.deleteClass({ schoolClassId: id, userId: currentUserId.value }).then(() => {
proxy.$message.success("删除成功");
getList();
refreshAllClassList();
});
});
}
function initializeClass(schoolClass) {
ElMessageBox.confirm("确定初始化该教学班全班实训数据吗?该操作不可恢复。", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
indexApi
.initializeTeachingClassTrainingData({
teachingClassId: schoolClass.schoolClassId,
operatorId: currentUserId.value,
})
.then(() => {
proxy.$message.success("初始化成功");
});
});
}
function refresh() {
getList();
}
function onClose() {
formInline.value = defaultForm();
sourceAdminClassIds.value = [];
}
function getFacultyList() {
return indexApi.seleteSchoolFacultyList({ schoolId: currentSchoolId.value }).then((res) => {
facultyList.value = res.data || [];
return facultyList.value;
});
}
function getMajorList() {
paramsquery.value.schoolMajorId = "";
if (!paramsquery.value.schoolFacultyId) {
majorList.value = [];
return;
}
indexApi.getMajorListBySchoolId({ schoolFacultyId: paramsquery.value.schoolFacultyId }).then((res) => {
majorList.value = res.data || [];
});
}
function loadMajorListForForm(schoolFacultyId) {
if (!schoolFacultyId) {
majorListForForm.value = [];
return Promise.resolve([]);
}
return indexApi.getMajorListBySchoolId({ schoolFacultyId }).then((res) => {
majorListForForm.value = res.data || [];
return majorListForForm.value;
});
}
function getMajorListForForm() {
sourceAdminClassIds.value = [];
formInline.value.schoolMajorId = "";
loadMajorListForForm(formInline.value.schoolFacultyId);
}
async function hydrateClassFormOptions(row) {
const schoolMajorId = row?.schoolMajorId;
if (!schoolMajorId) {
return;
}
if (row.schoolFacultyId) {
await loadMajorListForForm(row.schoolFacultyId);
return;
}
const faculties = facultyList.value.length ? facultyList.value : await getFacultyList();
const results = await Promise.all(
faculties.map((faculty) =>
indexApi
.getMajorListBySchoolId({ schoolFacultyId: faculty.schoolFacultyId })
.then((res) => ({
facultyId: faculty.schoolFacultyId,
majors: res.data || [],
}))
.catch(() => ({
facultyId: faculty.schoolFacultyId,
majors: [],
}))
)
);
const matched = results.find((item) => item.majors.some((major) => major.schoolMajorId === schoolMajorId));
if (!matched) {
return;
}
majorListForForm.value = matched.majors;
formInline.value = {
...formInline.value,
schoolFacultyId: matched.facultyId,
schoolMajorId,
};
}
function handleFormMajorChange() {
sourceAdminClassIds.value = [];
}
function getAllClassList() {
indexApi.getClassListBySchoolId({ schoolId: currentSchoolId.value }).then((res) => {
allClassList.value = res.data || [];
});
}
function refreshAllClassList() {
indexApi.clearClassListBySchoolIdCache(currentSchoolId.value);
indexApi.getClassListBySchoolId({ schoolId: currentSchoolId.value }, { force: true }).then((res) => {
allClassList.value = res.data || [];
});
}
onMounted(() => {
if (!adminClassManagementEnabled.value) {
activeClassType.value = "TEACHING";
}
getList();
getAllClassList();
getFacultyList();
});
</script>
<style lang="scss" scoped>
.class-page {
min-height: calc(100vh - 70px);
background: #f7fbff;
.class-tabs {
margin-bottom: 12px;
}
.query-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12px;
padding: 14px;
border: 1px solid #d8e8f7;
border-radius: 6px;
background: #ffffff;
}
.query-control {
width: 220px;
}
.table-actions {
display: flex;
justify-content: flex-start;
margin: 14px 0;
}
.class-table {
width: 100%;
}
.action-buttons {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
flex-wrap: wrap;
:deep(.el-button) {
margin-left: 0;
min-width: 56px;
padding: 6px 10px;
line-height: 1;
}
}
.form-control {
width: 100%;
}
.member-toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px;
margin-bottom: 12px;
}
.member-query {
width: 180px;
}
.member-table {
width: 100%;
}
}
</style>