168 lines
6.9 KiB
TypeScript
168 lines
6.9 KiB
TypeScript
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",
|
||
},
|
||
];
|