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
build / build (push) Successful in 2m43s
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
// @vitest-environment jsdom
|
||||
/**
|
||||
* docs/13 方案 C 复检:真实 vue-router 集成(docs/15 §3 T1/T4)。
|
||||
* siteLayer.spec.ts 全程 router 桩(vi.mock vue-router),覆盖不到镜像层真实匹配与守卫重定向,
|
||||
* 本文件装载 routes.ts 全量路由 + router/index.ts 守卫补位:
|
||||
* ① 路由结构:/site/{code} 无 component 镜像层存在、镜像去 name、meta.modId 保留、空段 redirect 兜底;
|
||||
* ② 镜像层真实 resolve 命中(渲染层由 router-view 对无 component 记录跳过推进,此处验匹配链);
|
||||
* ③ 守卫:子站编码当学校段 → 定向主站前缀且余部原样保留(含站点段),并恢复学校上下文;
|
||||
* ④ legacyRedirect 旧链带 id 重定向。
|
||||
*/
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { useCmsStore } from "@/store";
|
||||
import router from "@/router";
|
||||
import { routes } from "@/router/routes";
|
||||
|
||||
const SITES = [
|
||||
{ id: 1, code: "demo", name: "云海大学门户", parentSiteId: 0, schId: 1001, schName: "云海大学" },
|
||||
{ id: 2, code: "jdxy", name: "机电学院", parentSiteId: 1, schId: 1001, schName: "云海大学" },
|
||||
];
|
||||
|
||||
let store: ReturnType<typeof useCmsStore>;
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
const pinia = createPinia();
|
||||
setActivePinia(pinia);
|
||||
store = useCmsStore(pinia);
|
||||
store.user = { superAdmin: true, sites: SITES } as any;
|
||||
});
|
||||
|
||||
describe("docs/13 路由结构(真实 routes 数组,docs/15 T1)", () => {
|
||||
it("① /site/{code} 无 component 镜像层存在;镜像去 name、meta.modId 保留、空段 redirect 到 article", () => {
|
||||
const sch = routes.find(r => r.path === "/sch/:schCode")!;
|
||||
const siteLayer = sch.children!.find(r => r.path === "site/:siteCode") as any;
|
||||
expect(siteLayer).toBeTruthy();
|
||||
expect(siteLayer.component).toBeUndefined();
|
||||
expect(siteLayer.children![0].path).toBe("");
|
||||
expect(siteLayer.children![0].redirect).toBeTruthy();
|
||||
const mirror = siteLayer.children!.find((c: any) => c.path === "category");
|
||||
expect(mirror!.name).toBeUndefined();
|
||||
expect((mirror!.meta as any).modId).toBe(2);
|
||||
});
|
||||
|
||||
it("①b 主站清单与镜像层不重名(防重复注册告警)", () => {
|
||||
expect(router.getRoutes().filter(r => r.name === "CategoryManage")).toHaveLength(1);
|
||||
expect(router.getRoutes().filter(r => r.name === "ArticleList")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("② 子站 URL 真实 resolve 命中镜像记录;主站 URL 命中主记录", () => {
|
||||
const sub = router.resolve("/sch/demo/site/jdxy/category");
|
||||
expect(sub.matched).toHaveLength(3);
|
||||
expect(sub.name).toBeUndefined();
|
||||
expect(sub.meta.modId).toBe(2);
|
||||
|
||||
const main = router.resolve("/sch/demo/category");
|
||||
expect(main.matched).toHaveLength(2);
|
||||
expect(main.name).toBe("CategoryManage");
|
||||
});
|
||||
});
|
||||
|
||||
describe("docs/13 守卫与旧链兼容(真实 router.push,docs/15 T4)", () => {
|
||||
it("③ 子站编码当学校段 → 重定向主站前缀(余部保留)并恢复学校上下文", async () => {
|
||||
await router.push("/sch/jdxy/article");
|
||||
expect(router.currentRoute.value.path).toBe("/sch/demo/article");
|
||||
expect(store.currentSchool?.mainSiteCode).toBe("demo");
|
||||
});
|
||||
|
||||
it("③b 子站编码当学校段且 URL 已带站点段 → 站点段原样保留", async () => {
|
||||
await router.push("/sch/jdxy/site/jdxy/category");
|
||||
expect(router.currentRoute.value.path).toBe("/sch/demo/site/jdxy/category");
|
||||
expect(router.currentRoute.value.params.siteCode).toBe("jdxy");
|
||||
});
|
||||
|
||||
it("③c 学校编码不在用户可管理站点内 → 回工作台", async () => {
|
||||
await router.push("/sch/other-school/article");
|
||||
expect(router.currentRoute.value.path).toBe("/workbench");
|
||||
});
|
||||
|
||||
it("④ 旧链 /article/edit/:id → 当前学校上下文主站形态(id 后缀保留)", async () => {
|
||||
store.currentSchool = {
|
||||
schId: 1001,
|
||||
schName: "云海大学",
|
||||
mainSiteId: 1,
|
||||
mainSiteCode: "demo",
|
||||
mainSiteName: "云海大学门户",
|
||||
} as any;
|
||||
await router.push("/article/edit/9");
|
||||
expect(router.currentRoute.value.path).toBe("/sch/demo/article/edit/9");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user