feat(W2): 栏目树修订-虚拟根(学校名/子站名)+工具栏收敛4按钮+高度链修复,T-W2-01..10 绿 44/44
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* W2 栏目树修订:虚拟根装配纯函数(方案 §6.3 T-W2-01..05)。
|
||||
* rootLabelOf:根 label 随站点上下文(主站→学校名,缺省回退 mainSiteName;子站→子站名);
|
||||
* wrapTreeWithRoot:单根包装 {id:0,name:label,virtual:true,children};
|
||||
* initialSelectId:虚拟根下钻首个真实栏目 id,空树 null。
|
||||
*/
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { initialSelectId, rootLabelOf, wrapTreeWithRoot } from "@/utils/categoryTree";
|
||||
|
||||
const school = (overrides: Partial<any> = {}) => ({
|
||||
schId: 1,
|
||||
schName: "演示学校",
|
||||
mainSiteId: 1,
|
||||
mainSiteCode: "demo1",
|
||||
mainSiteName: "演示主站",
|
||||
...overrides,
|
||||
});
|
||||
|
||||
describe("rootLabelOf(T-W2-01..03)", () => {
|
||||
it("T-W2-01: 主站上下文 → schName", () => {
|
||||
expect(rootLabelOf({ currentSchool: school(), currentSite: { id: 1, code: "demo1", name: "演示主站" } }))
|
||||
.toBe("演示学校");
|
||||
});
|
||||
|
||||
it("T-W2-02: 主站 schName 缺省 → 回退 mainSiteName", () => {
|
||||
expect(rootLabelOf({ currentSchool: school({ schName: "" }), currentSite: { id: 1, code: "demo1", name: "演示主站" } }))
|
||||
.toBe("演示主站");
|
||||
expect(rootLabelOf({ currentSchool: school({ schName: undefined as any }), currentSite: { id: 1, code: "demo1", name: "演示主站" } }))
|
||||
.toBe("演示主站");
|
||||
});
|
||||
|
||||
it("T-W2-03: 子站上下文 → 子站名", () => {
|
||||
expect(rootLabelOf({ currentSchool: school(), currentSite: { id: 2, code: "jdxy", name: "机械学院" } }))
|
||||
.toBe("机械学院");
|
||||
});
|
||||
});
|
||||
|
||||
describe("wrapTreeWithRoot(T-W2-04)", () => {
|
||||
it("返回单根虚拟节点,原树挂 children", () => {
|
||||
const tree = [
|
||||
{ id: 5, parentId: 0, name: "新闻中心", children: [] },
|
||||
{ id: 6, parentId: 0, name: "学校简介", children: [] },
|
||||
];
|
||||
const root = wrapTreeWithRoot(tree, "演示学校");
|
||||
expect(root).toMatchObject({ id: 0, name: "演示学校", virtual: true });
|
||||
expect(root.children).toHaveLength(2);
|
||||
expect(root.children[0].id).toBe(5);
|
||||
});
|
||||
|
||||
it("空树也有根(children=[])", () => {
|
||||
const root = wrapTreeWithRoot([], "演示学校");
|
||||
expect(root).toMatchObject({ id: 0, name: "演示学校", virtual: true, children: [] });
|
||||
expect(wrapTreeWithRoot(null as any, "演示学校").children).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("initialSelectId(T-W2-05)", () => {
|
||||
it("虚拟根下钻首个真实栏目 id(非 0)", () => {
|
||||
const root = wrapTreeWithRoot([
|
||||
{ id: 5, parentId: 0, name: "新闻中心", children: [] },
|
||||
{ id: 6, parentId: 0, name: "学校简介", children: [] },
|
||||
], "演示学校");
|
||||
expect(initialSelectId(root)).toBe(5);
|
||||
});
|
||||
|
||||
it("空树 → null", () => {
|
||||
expect(initialSelectId(wrapTreeWithRoot([], "演示学校"))).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* W2 栏目树修订:虚拟根装配纯函数(方案 §6.4 步骤 1)。
|
||||
* 虚拟根约定(D5):id=0 的前端虚拟节点包裹真实栏目树;新增子栏目→parentId=0(顶级)、
|
||||
* 子栏目排序→parentId=0、编辑/删除→拒绝并提示(CategoryManage 既有 !node?.id 守卫天然拦截)。
|
||||
*/
|
||||
import type { CurrentSchool, CurrentSite } from "@/types/cms";
|
||||
|
||||
/** 根节点 label:主站上下文=学校名(schName 缺省回退 mainSiteName);子站上下文=该子站名 */
|
||||
export function rootLabelOf(ctx: {
|
||||
currentSchool: CurrentSchool | null;
|
||||
currentSite: CurrentSite | null;
|
||||
}): string {
|
||||
const school = ctx.currentSchool;
|
||||
const site = ctx.currentSite;
|
||||
if (site && school && site.id !== school.mainSiteId) {
|
||||
return site.name || "";
|
||||
}
|
||||
const label = school?.schName?.trim();
|
||||
return label || school?.mainSiteName || "";
|
||||
}
|
||||
|
||||
/** 把真实栏目树包装到虚拟根下(单根;空树也有根,children 恒为数组) */
|
||||
export function wrapTreeWithRoot(tree: any[] | null | undefined, label: string): any {
|
||||
return { id: 0, name: label, virtual: true, children: Array.isArray(tree) ? tree : [] };
|
||||
}
|
||||
|
||||
/** 初始选中:虚拟根下钻首个真实栏目 id;空树 → null(不落到根 id=0) */
|
||||
export function initialSelectId(wrapped: any): number | null {
|
||||
if (wrapped == null) {
|
||||
return null;
|
||||
}
|
||||
const root = Array.isArray(wrapped) ? wrapped[0] : wrapped;
|
||||
if (root?.virtual) {
|
||||
return root.children?.length ? root.children[0].id : null;
|
||||
}
|
||||
return root?.id ?? null;
|
||||
}
|
||||
Reference in New Issue
Block a user