feat(site-layer): 学校站点分层方案C落地(docs/13)+栏目管理增强+管理端三修复+首页视觉升级管理端+审计复检T1~T5(docs/15)整合批次-URL站点段/site/{siteCode}无component镜像层(去name防重名,router-view跳过推进渲染)+身份条SiteSwitcher自绘(徽章#577afb/#ff9900+分组下拉✓+path次级列+Esc/外点收起)+URL唯一事实源syncSiteFromRoute(非法/跨校/主站码当子站段告警打回同页主站,localStorage降级刷新首帧兜底)+菜单剥段高亮stripSiteSeg/withSiteSeg补段+menuRoute镜像层防重影+跳转收敛adminPathOf(工作台进入/全部站点总览/站点管理行进入管理纯URL切站);栏目管理-上级栏目可选可改(禁选自身及后代防成环)+批量添加BatchAddCategory(行序写排序号单行失败不中断)+单页wangEditor富文本预览字数分区+categoryIds契约前端/types/mock三处统一+SchoolLayout高度链.layout-wrap修复+ArticleListPanel fixed模式;管理端三修复-皮肤预览Modal全屏(ThemePreviewFrame可选fill prop)+SiteManage补themeUnregistered声明+长图文编辑器随内容增高;管理端视觉升级配套-SiteConfigForm 12新键+BannerManage gallery展示位切换+栏目homeStyle下拉+PortalPreview侧栏同步;审计复检-新增siteRouter.spec真实路由集成7用例(镜像层matched3层/守卫子站码定向主站前缀/越权回工作台/旧链带id重定向)+sitePath空白容错+siteLayer持久化round-trip与身份条次级入口(docs/15);vitest 99/99+build通过+S1~S10 GUI走查全过
build / build (push) Successful in 2m43s

This commit is contained in:
chenxing
2026-09-10 11:11:23 +08:00
parent 9ba4cb135a
commit 6ee9ab5684
26 changed files with 1931 additions and 222 deletions
+76 -57
View File
@@ -5,7 +5,9 @@ import { useCmsStore } from "@/store";
* CMS 管理端路由(hash 模式,部署于 /yschcms/admin 子路径)。
* 学校化管理双层壳(docs/09 §3.3):
* 一级 /workbench 学校工作台(无壳全屏);二级 /sch/:schCode/* 学校专属管理壳(SchoolLayout)。
* 站点/学校上下文经 localStorage 持久化,各页面从 store 读取。
* 站点分层(docs/13 方案 C):主站 `/sch/{code}/{page}`;子站 `/sch/{code}/site/{siteCode}/{page}`,
* URL 为站点上下文唯一事实源。site 版路由由主站清单深拷贝去 name 生成,
* 保证 `router.push({ name })` 永远产出主站形态。
* meta.modId 与基础平台模块(GetUserMod)契约对应,供 menuRoute 解析菜单/面包屑;
* meta.subOf 声明「列表子页面」(面包屑/侧边栏高亮归属所属列表)。
*/
@@ -30,6 +32,71 @@ function legacyRedirect(sub: string) {
};
}
/** 学校壳内功能页(主站形态一份;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 },
},
{
// 门户预览(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: "/",
@@ -55,63 +122,15 @@ export const routes: RouteRecordRaw[] = [
path: "/sch/:schCode",
component: () => import("@/components/SchoolLayout.vue"),
children: [
{ path: "", redirect: (to: any) => `/sch/${to.params.schCode}/article` },
...cmsChildren,
{
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 },
},
{
// 门户预览(SPA 内嵌简版门户;真实门户由后端 Thymeleaf 提供)
path: "portal-preview",
name: "PortalPreview",
component: () => import("@/views/cms/PortalPreview.vue"),
meta: { title: "门户预览", modId: 99 },
// 站点段前缀层(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,
],
},
],
},