/** * This file is part of the NocoBase (R) project. * Copyright (c) 2020-2024 NocoBase Co., Ltd. * Authors: NocoBase Team. * * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ import { PageHeader } from '@ant-design/pro-layout'; import { css } from '@emotion/css'; import { Layout, Menu, Result } from 'antd'; import React, { createContext, useCallback, useMemo } from 'react'; import { Navigate, Outlet, useLocation, useNavigate, useParams } from 'react-router-dom'; import { ADMIN_SETTINGS_PATH, PluginSettingsPageType, useApp } from '../application'; import { useCompile } from '../schema-component'; import { useStyles } from './style'; export const SettingsCenterContext = createContext({}); SettingsCenterContext.displayName = 'SettingsCenterContext'; function getMenuItems(list: PluginSettingsPageType[]) { return list.map((item) => { return { key: item.name, label: item.label, title: item.title, icon: item.icon, children: item.children?.length ? getMenuItems(item.children) : undefined, }; }); } function matchRoute(data, url) { const keys = Object.keys(data); if (data[url]) { return data[url]; } for (const pattern of keys) { const regexPattern = pattern.replace(/:[^/]+/g, '([^/]+)'); const match = url.match(new RegExp(`^${regexPattern}$`)); if (match) { return data[pattern]; } } return null; } function replaceRouteParams(urlTemplate, params) { // 使用正则表达式替换占位符 return urlTemplate.replace(/:\w+/g, (match) => { const paramName = match.substring(1); return params?.[paramName] || match; }); } export const AdminSettingsLayout = () => { const { styles, theme } = useStyles(); const app = useApp(); const navigate = useNavigate(); const location = useLocation(); const params = useParams(); const compile = useCompile(); const settings = useMemo(() => { const list = app.pluginSettingsManager.getList(); // compile title function traverse(settings: PluginSettingsPageType[]) { settings.forEach((item) => { item.title = compile(item.title); item.label = compile(item.title); if (item.children?.length) { traverse(item.children); } }); } traverse(list); return list; }, [app.pluginSettingsManager, compile]); const getFirstDeepChildPath = useCallback((settings: PluginSettingsPageType[]) => { if (!settings || !settings.length) { return '/admin'; } if (settings.filter((item) => item.isTopLevel).length === 1) { // 如果是外链类型的,需要跳转外链,如果是内页则返回内页 path const pluginSetting = settings.find((item) => item.isTopLevel); // 如果仅有 1 个,且是外链类型的,跳转到 /admin // @see https://nocobase.height.app/inbox/T-5038 return pluginSetting.link ? '/admin' : pluginSetting.path; } function find(settings: PluginSettingsPageType[]) { const first = settings.find((item) => !item.link); // 找到第一个非外链类型的 if (first.children?.length) { return getFirstDeepChildPath(first.children); } return first; } return find(settings).path; }, []); const settingsMapByPath = useMemo>(() => { const map = {}; const traverse = (settings: PluginSettingsPageType[]) => { settings.forEach((item) => { map[item.path] = item; if (item.children?.length) { traverse(item.children); } }); }; traverse(settings); return map; }, [settings]); const currentSetting = useMemo( () => matchRoute(settingsMapByPath, location.pathname), [location.pathname, settingsMapByPath], ); const currentTopLevelSetting = useMemo(() => { if (!currentSetting) { return null; } return settings.find((item) => item.name === currentSetting.topLevelName); }, [currentSetting, settings]); const sidebarMenus = useMemo(() => { return getMenuItems(settings.filter((v) => v.isTopLevel !== false).map((item) => ({ ...item, children: null }))); }, [settings]); if (!currentSetting || location.pathname === ADMIN_SETTINGS_PATH || location.pathname === ADMIN_SETTINGS_PATH + '/') { return ; } if (location.pathname === currentTopLevelSetting.path && currentTopLevelSetting.children?.length > 0) { return ; } // 如果是外链类型的,需要跳转并返回到上一个页面 if (currentSetting.link) { return ; } return (
{ const plugin = settings.find((item) => item.name === key); if (plugin.link) { window.open(plugin.link, '_blank'); return; } if (plugin.children?.length) { return navigate(getFirstDeepChildPath(plugin.children)); } else { return navigate(plugin.path); } }} items={sidebarMenus} /> {currentSetting && ( 0 && currentTopLevelSetting.showTabs !== false ? 0 : theme.paddingSM, }} ghost={false} title={currentTopLevelSetting.title} footer={ currentTopLevelSetting.children?.length > 0 && currentTopLevelSetting.showTabs !== false && ( { navigate(replaceRouteParams(app.pluginSettingsManager.getRoutePath(key), params)); }} selectedKeys={[currentSetting?.name]} mode="horizontal" items={getMenuItems(currentTopLevelSetting.children)} > ) } /> )}
{currentSetting ? ( ) : ( )}
); };