增加网站管理功能

This commit is contained in:
2026-09-17 23:00:06 +08:00
parent 1224735aa8
commit 67e819c629
98 changed files with 8711 additions and 2254 deletions
+77
View File
@@ -0,0 +1,77 @@
/**
* 页头导航菜单配置
*
* 数据来源:后端「官网管理 - 导航菜单」(yz_platform_website_nav),
* 由 GET /site/nav 下发(仅启用且显示中的菜单,已按 pid 组好树)。
* 接口异常或后台未配置任何菜单时,回退到 config/site.ts 里的静态 navItems,
* 保证页头导航不会为空。
*
* 菜单类型(与平台端一致):
* 1 目录 仅分组,本身可带 path;配置了子菜单时页头渲染为下拉
* 2 页面 路由地址
* 3 外链 完整 URL,新窗口打开
* 4 单页 路由地址(内容取自「单页管理」)
*/
import { ref } from "vue";
import { getJSON } from "@/api/request";
import { navItems } from "./site";
export interface NavMenuItem {
/** v-for key:后端菜单用 nav-{id},静态回退用 static-{path} */
key: string;
label: string;
path: string;
/** 是否站外链接:后台菜单类型为「外链」或 path 填写了完整 URL */
external: boolean;
children: NavMenuItem[];
}
/** /site/nav 返回的节点结构 */
interface RemoteNavNode {
id: number;
pid: number;
title: string;
type: number;
path: string;
icon?: string;
external?: boolean;
children?: RemoteNavNode[];
}
const isExternalPath = (path: string): boolean => /^https?:\/\//i.test(path);
function toMenuItem(node: RemoteNavNode): NavMenuItem {
const path = node.path || "/";
return {
key: `nav-${node.id}`,
label: node.title || "",
path,
external: node.external ?? (node.type === 3 || isExternalPath(path)),
children: (node.children ?? []).map(toMenuItem),
};
}
/** 静态回退菜单:后台未配置时使用 */
const fallbackMenus = (): NavMenuItem[] =>
navItems.map((item) => ({
key: `static-${item.path}`,
label: item.label,
path: item.path,
external: isExternalPath(item.path),
children: [],
}));
/** 页头导航菜单(应用启动时由 loadNavMenus 拉取,初始为静态回退) */
export const navMenus = ref<NavMenuItem[]>(fallbackMenus());
/**
* 拉取后台配置的导航菜单(应用启动时调用一次)。
* 接口异常或后台未配置时保持静态回退菜单,不置空。
*/
export async function loadNavMenus(): Promise<void> {
const data = await getJSON<{ list: RemoteNavNode[] }>("/site/nav");
const list = data?.list ?? [];
if (list.length > 0) {
navMenus.value = list.map(toMenuItem);
}
}