From c4fd23ad54528780ed483dde2fa48bebe297e961 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Thu, 30 Jul 2026 11:57:09 +0800 Subject: [PATCH] feat: configure school organization menus --- src/layout/components/Sidebar/index.vue | 30 +++++-- src/permission.js | 11 ++- src/router/index.js | 34 ++++---- src/views/platformAdmin/school/index.vue | 93 +++++++++++++++++++-- src/views/teacherEnd/class/index.vue | 30 ++++--- tests/school-product-config.static.test.cjs | 14 ++++ 6 files changed, 169 insertions(+), 43 deletions(-) diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue index 521e810..fd752aa 100644 --- a/src/layout/components/Sidebar/index.vue +++ b/src/layout/components/Sidebar/index.vue @@ -574,17 +574,33 @@ const getTaskList = () => { proxy.$cache.session.setJSON("disabledTitles", disabledTitles); sidebarRouters.value = [...constantRoutes, ...dynamicRoutes]; }); - } else { - sidebarRouters.value = [...constantRoutes, ...teacherRoutes]; - } + } else { + sidebarRouters.value = [...constantRoutes, ...filterRoutesByOrganizationMode(teacherRoutes)]; + } }; function filterRoutesByOrganizationMode(routes) { - if (userStore.schoolProductConfig?.organizationMode !== "TEACHING_CLASS_ONLY") { - return routes; - } - return routes.filter((route) => !route.meta?.requiresAdminClass); + const config = userStore.schoolProductConfig; + const legacyAdminEnabled = config?.organizationMode !== "TEACHING_CLASS_ONLY"; + const facultyEnabled = config?.facultyManagementEnabled ?? legacyAdminEnabled; + const majorEnabled = config?.majorManagementEnabled ?? legacyAdminEnabled; + const adminClassEnabled = config?.adminClassManagementEnabled ?? legacyAdminEnabled; + return routes.filter((route) => { + if (route.meta?.requiresFacultyManagement && !facultyEnabled) return false; + if (route.meta?.requiresMajorManagement && !majorEnabled) return false; + if (route.meta?.requiresAdminClass && !adminClassEnabled) return false; + return true; + }); } +watch( + () => userStore.schoolProductConfig?.organizationMode, + (organizationMode, previousOrganizationMode) => { + if (organizationMode === previousOrganizationMode) return; + if ([2, 3].includes(Number(userStore.userInfo.roleId))) { + getTaskList(); + } + } +); onMounted(() => { getTaskList(); loadTrainingTaskTitles(); diff --git a/src/permission.js b/src/permission.js index 10f0981..6f16c63 100644 --- a/src/permission.js +++ b/src/permission.js @@ -42,7 +42,16 @@ router.beforeEach((to, from, next) => { userStore .ensureSchoolProductConfig() .then((config) => { - if (config?.organizationMode === "TEACHING_CLASS_ONLY" && to.matched.some((record) => record.meta?.requiresAdminClass)) { + const legacyAdminEnabled = config?.organizationMode !== "TEACHING_CLASS_ONLY"; + const facultyEnabled = config?.facultyManagementEnabled ?? legacyAdminEnabled; + const majorEnabled = config?.majorManagementEnabled ?? legacyAdminEnabled; + const adminClassEnabled = config?.adminClassManagementEnabled ?? legacyAdminEnabled; + const unavailableManagementRoute = to.matched.some((record) => + (record.meta?.requiresFacultyManagement && !facultyEnabled) + || (record.meta?.requiresMajorManagement && !majorEnabled) + || (record.meta?.requiresAdminClass && !adminClassEnabled) + ); + if (unavailableManagementRoute) { next({ path: "/admin-school/index" }); NProgress.done(); return null; diff --git a/src/router/index.js b/src/router/index.js index c06a44f..b2bfa3e 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -451,11 +451,11 @@ export const dynamicRoutes = [ // 教师端路由 export const teacherRoutes = [ { - path: "/school", - component: Layout, - redirect: "/school/index", - roles: ["teacher"], - meta: { title: "院系管系", icon: "院系管系", affix: true }, + path: "/school", + component: Layout, + redirect: "/school/index", + roles: ["teacher"], + meta: { title: "院系管系", icon: "院系管系", affix: true, requiresFacultyManagement: true }, children: [ // 院校管理 { @@ -468,11 +468,11 @@ export const teacherRoutes = [ }, // 专业管理 { - path: "/major", - component: Layout, - redirect: "/major/index", - roles: ["teacher"], - meta: { title: "专业管理", icon: "专业管理", affix: true }, + path: "/major", + component: Layout, + redirect: "/major/index", + roles: ["teacher"], + meta: { title: "专业管理", icon: "专业管理", affix: true, requiresMajorManagement: true }, children: [ // 专业管理 { @@ -502,11 +502,11 @@ export const teacherRoutes = [ }, // 教师管理 { - path: "/teacher", - component: Layout, - redirect: "/teacher/index", - roles: ["teacher"], - meta: { title: "教师管理", icon: "教师管理", affix: true }, + path: "/teacher", + component: Layout, + redirect: "/teacher/index", + roles: ["teacher"], + meta: { title: "教师管理", icon: "教师管理", affix: true, requiresAdminClass: true }, children: [ // 教师管理 { @@ -653,7 +653,7 @@ export const schoolAdminRoutes = [ component: Layout, redirect: "/admin-faculty/index", roles: ["schoolAdmin"], - meta: { title: "院系管理", icon: "院系管理", affix: true, requiresAdminClass: true }, + meta: { title: "院系管理", icon: "院系管理", affix: true, requiresFacultyManagement: true }, children: [ { path: "index", @@ -668,7 +668,7 @@ export const schoolAdminRoutes = [ component: Layout, redirect: "/admin-major/index", roles: ["schoolAdmin"], - meta: { title: "专业管理", icon: "专业管理", affix: true, requiresAdminClass: true }, + meta: { title: "专业管理", icon: "专业管理", affix: true, requiresMajorManagement: true }, children: [ { path: "index", diff --git a/src/views/platformAdmin/school/index.vue b/src/views/platformAdmin/school/index.vue index 2cd90a6..6159321 100644 --- a/src/views/platformAdmin/school/index.vue +++ b/src/views/platformAdmin/school/index.vue @@ -78,11 +78,24 @@ - + + -
新建学校默认采用标准模式;已有行政组织数据的学校不能直接切换模式。
+
选择预设会同步更新下方开关;已有组织数据会保留,关闭开关仅隐藏菜单和阻止新增编辑。
+
+ + + 关闭后会同时关闭专业管理和行政班管理。 + + + + 需先启用院系管理;关闭后会同时关闭行政班管理。 + + + + 关闭后班级管理仅保留教学班,教师维护学生名单。