fix(walkthrough): menuRoute 识别 /sch/{code} 壳路径免回退告警;栏目弹窗按钮 type=link 改 text;mock 补 cherry-bloom/violet-iris 主题
build / build (push) Successful in 2m20s

This commit is contained in:
chenxing
2026-09-19 17:47:51 +08:00
parent f29c193ea7
commit be19ed066a
5 changed files with 90 additions and 4 deletions
+54
View File
@@ -0,0 +1,54 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("@/store", () => ({
useCmsStore: () => ({ schoolCode: "demo" }),
}));
import { resolveMenuPage } from "./menuRoute";
describe("resolveMenuPage 学校壳具体路径匹配", () => {
let warn: ReturnType<typeof vi.spyOn>;
beforeEach(() => {
warn = vi.spyOn(console, "warn").mockImplementation(() => {});
});
it("/sch/{code}/article 直接命中,不回退名称识别、不告警", () => {
expect(resolveMenuPage("/sch/demo/article", null, "文章列表")).toEqual({
path: "/sch/demo/article",
external: false,
});
expect(warn).not.toHaveBeenCalled();
});
it("他校编码的壳路径重映射到当前学校上下文", () => {
expect(resolveMenuPage("/sch/fsz/category", null, "栏目管理")).toEqual({
path: "/sch/demo/category",
external: false,
});
expect(warn).not.toHaveBeenCalled();
});
it("裸子路径 /article 仍命中学校壳路由", () => {
expect(resolveMenuPage("/article", null, "文章列表")).toEqual({
path: "/sch/demo/article",
external: false,
});
expect(warn).not.toHaveBeenCalled();
});
it("顶层绝对路由不受影响(/workbench)", () => {
expect(resolveMenuPage("/workbench", null, "工作台")).toEqual({
path: "/workbench",
external: false,
});
expect(warn).not.toHaveBeenCalled();
});
it("配错路径仍走名称回退(行为保持)", () => {
expect(resolveMenuPage("/no-such-page", null, "友情链接")).toEqual({
path: "/sch/demo/link",
external: false,
});
expect(warn).toHaveBeenCalledTimes(1);
});
});
+5 -1
View File
@@ -119,7 +119,11 @@ function matchRoute(candidate: string): string | null {
// 2. 学校壳内子路径匹配(/article → /sch/{code}/article),兼容新旧上下文前缀(历史 /cms、现网 /yschcms)
const stripped = lower.startsWith("/cms/") ? lower.slice("/cms".length)
: lower.startsWith("/yschcms/") ? lower.slice("/yschcms".length) : lower;
const entry = ROUTE_ENTRIES.find(e => !e.absolute && e.sub.toLowerCase() === stripped);
// 平台侧已配成具体壳路径(/sch/{任意编码}/article):剥壳后按子路径命中,
// 运行时经 toConcrete 重映射到当前学校上下文(他校编码不直接透传)
const deshelled = /^\/sch\/[^/]+(?=\/)/.test(stripped) ? stripped.replace(/^\/sch\/[^/]+/, "") : stripped;
const entry = ROUTE_ENTRIES.find(e => !e.absolute &&
(e.sub.toLowerCase() === stripped || e.sub.toLowerCase() === deshelled));
if (entry) {
return toConcrete(entry);
}
+1 -1
View File
@@ -563,7 +563,7 @@ function openLink(url: string) {
</FormItem>
</Form>
<template #footer>
<Button v-if="!form.id" type="link" @click="switchToBatch">切换至批量添加</Button>
<Button v-if="!form.id" type="text" @click="switchToBatch">切换至批量添加</Button>
<Button @click="modalVisible = false">取消</Button>
<Button type="primary" :loading="saving" @click="save">保存</Button>
</template>