import { RouteRecordRaw } from "vue-router"; import { useCmsStore } from "@/store"; /** * CMS 管理端路由(hash 模式,部署于 /yschcms/admin 子路径)。 * 学校化管理双层壳(docs/09 §3.3): * 一级 /workbench 学校工作台(无壳全屏);二级 /sch/:schCode/* 学校专属管理壳(SchoolLayout)。 * 站点分层(docs/13 方案 C):主站 `/sch/{code}/{page}`;子站 `/sch/{code}/site/{siteCode}/{page}`, * URL 为站点上下文唯一事实源。site 版路由由主站清单深拷贝去 name 生成, * 保证 `router.push({ name })` 永远产出主站形态。 * meta.modId 与基础平台模块(GetUserMod)契约对应,供 menuRoute 解析菜单/面包屑; * meta.subOf 声明「列表子页面」(面包屑/侧边栏高亮归属所属列表)。 */ /** 旧路径(无学校前缀)→ 当前学校上下文的对应页;无学校上下文回工作台。 * 首次导航早于 App 启动引导(store 未恢复),故同步读 localStorage 兜底 */ function legacyRedirect(sub: string) { return (to: any) => { let code = useCmsStore().currentSchool?.mainSiteCode; if (!code) { try { code = JSON.parse(localStorage.getItem("cms.currentSchool") || "null")?.mainSiteCode; } catch { /* 空上下文走工作台 */ } } if (!code) { return "/workbench"; } const idSuffix = to.params.id ? `/${to.params.id}` : ""; return `/sch/${code}/${sub}${idSuffix}`; }; } /** 学校壳内功能页(主站形态一份;meta/modId 供菜单解析与剥段高亮) */ const cmsChildren: RouteRecordRaw[] = [ { path: "", redirect: (to: any) => `/sch/${to.params.schCode}/article` }, { path: "article", name: "ArticleList", component: () => import("@/views/cms/ArticleList.vue"), meta: { title: "文章列表", modId: 11 }, }, { // 新增文章 = 文章列表的子页面(docs/09 §3.2):不挂菜单节点, // 面包屑「内容管理>文章列表>新建文章」、侧边栏高亮文章列表 path: "article/edit", name: "ArticleEdit", component: () => import("@/views/cms/ArticleEdit.vue"), meta: { title: "新建文章", modId: 11, subOf: "/article" }, }, { path: "article/edit/:id", name: "ArticleEditId", component: () => import("@/views/cms/ArticleEdit.vue"), meta: { title: "编辑文章", modId: 11, subOf: "/article" }, }, { path: "category", name: "CategoryManage", component: () => import("@/views/cms/CategoryManage.vue"), meta: { title: "栏目管理", modId: 2 }, }, { path: "banner", name: "BannerManage", component: () => import("@/views/cms/BannerManage.vue"), meta: { title: "轮播管理", modId: 3 }, }, { path: "link", name: "LinkManage", component: () => import("@/views/cms/LinkManage.vue"), meta: { title: "友情链接", modId: 4 }, }, { path: "attachment", name: "AttachmentManage", component: () => import("@/views/cms/AttachmentManage.vue"), meta: { title: "附件管理", modId: 5 }, }, { path: "site", name: "SiteManage", component: () => import("@/views/cms/SiteManage.vue"), meta: { title: "站点管理", modId: 6 }, }, { // 站点设置中心(docs/16 主线A):新建 = 创建模式(仅基本信息/皮肤可编辑),编辑 = 完整分区页。 // 列表子页面形态(subOf),面包屑/侧栏高亮归属「站点管理」 path: "site/new", name: "SiteSettingNew", component: () => import("@/views/cms/SiteSetting.vue"), meta: { title: "新建站点", modId: 6, subOf: "/site" }, }, { path: "site/setting/:id", name: "SiteSetting", component: () => import("@/views/cms/SiteSetting.vue"), meta: { title: "站点设置", modId: 6, subOf: "/site" }, }, { // 门户预览(SPA 内嵌简版门户;真实门户由后端 Thymeleaf 提供) path: "portal-preview", name: "PortalPreview", component: () => import("@/views/cms/PortalPreview.vue"), meta: { title: "门户预览", modId: 99 }, }, ]; /** 子站形态:同一批页面,去掉 name(防重复注册告警;子站导航一律走 path 拼装) */ const siteChildren: RouteRecordRaw[] = cmsChildren.map(r => ({ ...r, name: undefined })); export const routes: RouteRecordRaw[] = [ { path: "/", redirect: "/workbench", }, { // 一级:学校工作台(全屏无侧边栏壳) path: "/workbench", name: "SchoolWorkbench", component: () => import("@/views/cms/SchoolWorkbench.vue"), meta: { title: "学校工作台" }, }, { // 平台级:皮肤包管理(任务二收敛:仅超管,工作台按钮进入,不挂左侧菜单) path: "/theme-manage", name: "ThemePackageManage", component: () => import("@/views/cms/ThemeManage.vue"), meta: { title: "皮肤包管理", superOnly: true }, }, { // 二级:学校专属管理壳,:schCode = 主站编码(URL 即学校上下文) // (懒加载引入,避免 routes → SchoolLayout → menuRoute → routes 循环依赖) path: "/sch/:schCode", component: () => import("@/components/SchoolLayout.vue"), children: [ ...cmsChildren, { // 站点段前缀层(docs/13 §2):无 component,子记录直接渲染到 SchoolLayout 的 router-view; // 站点上下文由 SchoolLayout.syncSiteFromRoute 按此段同步 store path: "site/:siteCode", children: [ { path: "", redirect: (to: any) => `/sch/${to.params.schCode}/site/${to.params.siteCode}/article` }, ...siteChildren, ], }, ], }, // ===== 旧路径兼容:重定向到当前学校上下文,不 404 ===== { path: "/article", redirect: legacyRedirect("article") }, { path: "/article/edit/:id?", redirect: legacyRedirect("article/edit") }, { path: "/category", redirect: legacyRedirect("category") }, { path: "/banner", redirect: legacyRedirect("banner") }, { path: "/link", redirect: legacyRedirect("link") }, { path: "/attachment", redirect: legacyRedirect("attachment") }, { path: "/site", redirect: legacyRedirect("site") }, { path: "/site/new", redirect: legacyRedirect("site/new") }, { path: "/site/setting/:id", redirect: legacyRedirect("site/setting") }, { path: "/theme", redirect: "/theme-manage" }, { path: "/portal-preview", redirect: legacyRedirect("portal-preview") }, { path: "/:pathMatch(.*)*", redirect: "/workbench", }, ];