Files
YschcmsFront/src/router/routes.ts
T
chenxing 6f1f666479
build / build (push) Successful in 4m47s
周末修订
2026-09-15 23:41:11 +08:00

168 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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",
},
];