From 259eb2041151becb4838f1b0d9a2cf03178504f7 Mon Sep 17 00:00:00 2001 From: CNWei Date: Sun, 1 Nov 2026 22:22:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=80=8C=E6=9F=A5=E7=9C=8B=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E3=80=8D=E6=94=B9=E4=B8=BA=E7=AB=99=E5=86=85=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=EF=BC=8C=E5=8F=AA=E6=8D=A2=E5=8F=B3=E4=BE=A7=E5=86=85?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ServicePanel 新增 onOpenApi,链接点击接管为 navigate('/interface'); 按住 Ctrl/Cmd/Shift/Alt 仍保留新标签打开 - 前台内容区已有 route.kind === 'api' 分支,直接渲染接口一览 - 顺手删掉两个没人引用的旧组件:sidebar/Sidebar.tsx、sidebar/CategoryNav.tsx --- stash-web/src/AppNext.tsx | 1 + .../src/components/sidebar/CategoryNav.tsx | 86 ------------------- .../src/components/sidebar/ServicePanel.tsx | 21 ++++- stash-web/src/components/sidebar/Sidebar.tsx | 64 -------------- 4 files changed, 20 insertions(+), 152 deletions(-) delete mode 100644 stash-web/src/components/sidebar/CategoryNav.tsx delete mode 100644 stash-web/src/components/sidebar/Sidebar.tsx diff --git a/stash-web/src/AppNext.tsx b/stash-web/src/AppNext.tsx index 7b05919..9e3a2df 100644 --- a/stash-web/src/AppNext.tsx +++ b/stash-web/src/AppNext.tsx @@ -710,6 +710,7 @@ export default function AppNext() { live={live} refreshing={refreshing} onRefresh={refresh} + onOpenApi={() => navigate('/interface')} /> )} {site.sidebar.show_nav !== false && ( diff --git a/stash-web/src/components/sidebar/CategoryNav.tsx b/stash-web/src/components/sidebar/CategoryNav.tsx deleted file mode 100644 index 14c19fc..0000000 --- a/stash-web/src/components/sidebar/CategoryNav.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { Card, Menu, type MenuItem } from '@stash/ui' -import type { NavTarget } from '../../data/nav' -import type { Category } from '../../data/types' - -/** - * 分类导航树:由内容树派生。 - * - * - 有分组的分类(apps)是折叠节点,子项是分组(分组可用 show_in_sidebar 单独隐藏); - * - 没有分组、或分组全被隐藏的分类,就是一个普通菜单项。 - * - * 折叠状态由组件库的 Menu 内部维护;这里只负责把内容树翻译成 items。 - */ -type CategoryNavProps = { - /** 内容目录;顺序即侧栏顺序 */ - categories: Category[] - /** 当前明细视图的分类 / 分组,用于高亮 */ - activeCategoryId?: string - activeGroupId?: string - /** 是否在首页(高亮「首页」项) */ - homeActive?: boolean - onNavigate: (target: NavTarget) => void - /** 点击「首页」 */ - onHome: () => void -} - -const HOME_KEY = 'home' -const categoryKey = (id: string) => `cat:${id}` -const groupKey = (categoryId: string, groupId: string) => `group:${categoryId}:${groupId}` - -export function CategoryNav({ - categories, - activeCategoryId, - activeGroupId, - homeActive = false, - onNavigate, - onHome, -}: CategoryNavProps) { - const items: MenuItem[] = [ - { key: HOME_KEY, label: '首页' }, - ...categories.map((category) => { - // 「允许子分组」的分区才有 groups;空分组不出现在侧栏(后台仍保留) - const groups = category.groups.filter((group) => group.items.length > 0) - - return { - key: categoryKey(category.id), - label: category.title, - children: - groups.length > 0 - ? groups.map((group) => ({ - key: groupKey(category.id, group.id), - label: group.name, - })) - : undefined, - } - }), - ] - - const activeKey = homeActive - ? HOME_KEY - : activeCategoryId === undefined - ? undefined - : activeGroupId !== undefined - ? groupKey(activeCategoryId, activeGroupId) - : categoryKey(activeCategoryId) - - const handleSelect = (key: string) => { - if (key === HOME_KEY) { - onHome() - return - } - - if (key.startsWith('group:')) { - const [, categoryId, groupId] = key.split(':') - onNavigate({ categoryId, groupId }) - return - } - - onNavigate({ categoryId: key.slice('cat:'.length) }) - } - - return ( - - - - ) -} diff --git a/stash-web/src/components/sidebar/ServicePanel.tsx b/stash-web/src/components/sidebar/ServicePanel.tsx index 7d4b7f5..a28fbd5 100644 --- a/stash-web/src/components/sidebar/ServicePanel.tsx +++ b/stash-web/src/components/sidebar/ServicePanel.tsx @@ -10,9 +10,17 @@ type ServicePanelProps = { live: boolean refreshing: boolean onRefresh: () => void + /** 打开接口一览:走站内路由,不整页刷新 */ + onOpenApi: () => void } -export function ServicePanel({ projects, live, refreshing, onRefresh }: ServicePanelProps) { +export function ServicePanel({ + projects, + live, + refreshing, + onRefresh, + onOpenApi, +}: ServicePanelProps) { const host = typeof window === 'undefined' ? '-' : window.location.host return ( @@ -56,7 +64,16 @@ export function ServicePanel({ projects, live, refreshing, onRefresh }: ServiceP 重新扫描 - + { + // 无修饰键时接管点击,走站内路由,只换右侧内容;按住修饰键仍可新标签打开 + if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return + event.preventDefault() + onOpenApi() + }} + > 查看接口 diff --git a/stash-web/src/components/sidebar/Sidebar.tsx b/stash-web/src/components/sidebar/Sidebar.tsx deleted file mode 100644 index d051240..0000000 --- a/stash-web/src/components/sidebar/Sidebar.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import type { Project } from '../../api' -import type { NavTarget } from '../../data/nav' -import type { Category } from '../../data/types' -import type { ProfileSettings } from '../../settings' -import { CategoryNav } from './CategoryNav' -import { ProfileCard } from './ProfileCard' -import { ServicePanel } from './ServicePanel' - -/** - * 左侧栏容器:用户资料 + 本地服务面板 + 分类导航。 - * 只负责布局与数据透传,具体内容由三个子组件分别渲染。 - */ -type SidebarProps = { - projects: Project[] - /** 内容目录;侧栏直接由它派生 */ - categories: Category[] - profile: ProfileSettings - live: boolean - refreshing: boolean - onRefresh: () => void - activeCategoryId?: string - activeGroupId?: string - /** 是否在首页 */ - homeActive?: boolean - onNavigate: (target: NavTarget) => void - /** 点击「首页」 */ - onHome: () => void -} - -export function Sidebar({ - projects, - categories, - profile, - live, - refreshing, - onRefresh, - activeCategoryId, - activeGroupId, - homeActive = false, - onNavigate, - onHome, -}: SidebarProps) { - return ( -
- - - - - -
- ) -}