feat: add compact toolbox and public wiki vector search
This commit is contained in:
1 parent
9f29ecae9e
commit
d35d075669
29 files changed
+757
-128
No files matched your search
@@ -237,9 +237,10 @@ export function AgentDetailPanel({
|
||||
|
||||
const isSaving = updateAgent.isPending || setFeatured.isPending;
|
||||
|
||||
// 对话生成文件(md/txt 等 artifact)并在右侧展开预览时,自动收起智能体
|
||||
// 信息面板给预览让位;切换到新文件时同样收起。编辑中不打断用户,用户随时
|
||||
// 可手动重新展开。
|
||||
// 对话生成文件(md/txt 等 artifact)并首次展开预览时,自动收起智能体
|
||||
// 信息面板给预览让位。目录内切换文件不能再次改写用户的手动选择:否则用户
|
||||
// 刚展开智能体信息,点另一个文件时面板又会突然收起,看起来就像收起按钮被
|
||||
// 移除了。编辑中也不打断用户。
|
||||
//
|
||||
// 关键:判定用 open + selectedArtifact,而非 artifacts.length。流式写文件时
|
||||
// message-group 一开始就调用 select()+setOpen(true) 打开预览并选中该文件,但
|
||||
@@ -251,17 +252,13 @@ export function AgentDetailPanel({
|
||||
const artifactPanelVisible =
|
||||
!!artifactsCtx?.open && (!!selectedArtifact || artifactCount > 0);
|
||||
const prevArtifactPanelVisible = useRef(false);
|
||||
const prevSelectedArtifact = useRef<string | null>(null);
|
||||
useEffect(() => {
|
||||
const opened = artifactPanelVisible && !prevArtifactPanelVisible.current;
|
||||
const switched =
|
||||
artifactPanelVisible && selectedArtifact !== prevSelectedArtifact.current;
|
||||
prevArtifactPanelVisible.current = artifactPanelVisible;
|
||||
prevSelectedArtifact.current = selectedArtifact;
|
||||
if ((opened || switched) && !editing) {
|
||||
if (opened && !editing) {
|
||||
setCollapsed(true);
|
||||
}
|
||||
}, [artifactPanelVisible, selectedArtifact, editing]);
|
||||
}, [artifactPanelVisible, editing]);
|
||||
|
||||
const displayName = desensitize(agent?.name ?? agentName);
|
||||
const questions = useMemo(
|
||||
@@ -929,14 +926,16 @@ export function AgentDetailPanel({
|
||||
|
||||
const panelChrome = (collapseButton: ReactNode) => (
|
||||
<>
|
||||
<div className="flex h-12 shrink-0 items-center justify-between border-b px-4">
|
||||
<span className="shrink-0 whitespace-nowrap text-sm font-semibold">
|
||||
<div className="flex h-12 shrink-0 items-center gap-2 border-b px-4">
|
||||
<span className="min-w-0 flex-1 truncate whitespace-nowrap text-sm font-semibold">
|
||||
{panelTitle ?? "智能体信息"}
|
||||
</span>
|
||||
<div className="flex min-w-0 items-center gap-1">
|
||||
{headerActions}
|
||||
{compactAppearanceActions}
|
||||
{collapseButton}
|
||||
<div className="flex min-w-0 items-center justify-end gap-1">
|
||||
<div className="flex min-w-0 items-center justify-end gap-1 overflow-hidden">
|
||||
{headerActions}
|
||||
{compactAppearanceActions}
|
||||
</div>
|
||||
{collapseButton && <div className="shrink-0">{collapseButton}</div>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="min-h-0 flex-1 overflow-y-auto">{body}</div>
|
||||
@@ -954,12 +953,13 @@ export function AgentDetailPanel({
|
||||
<div className="hidden shrink-0 items-start border-l px-2 pt-3 lg:flex">
|
||||
<div className="flex items-center gap-1">
|
||||
{compactAppearanceActions}
|
||||
<Tooltip content="智能体信息">
|
||||
<Tooltip content="展开智能体信息">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
onClick={() => setCollapsed(false)}
|
||||
aria-label="展开智能体信息"
|
||||
aria-expanded={false}
|
||||
>
|
||||
<PanelRightOpenIcon className="size-4" />
|
||||
</Button>
|
||||
@@ -975,6 +975,7 @@ export function AgentDetailPanel({
|
||||
size="icon-sm"
|
||||
onClick={() => setCollapsed(true)}
|
||||
aria-label="收起智能体信息"
|
||||
aria-expanded={true}
|
||||
>
|
||||
<PanelRightCloseIcon className="size-4" />
|
||||
</Button>
|
||||
|
||||
@@ -1432,7 +1432,7 @@ export function ArtifactFileDetail({
|
||||
|
||||
return (
|
||||
<Artifact className={cn(className)}>
|
||||
<ArtifactHeader className="flex flex-wrap items-center gap-3 px-4 py-3">
|
||||
<ArtifactHeader className="relative flex flex-wrap items-center gap-3 px-4 py-3 pr-14">
|
||||
<div className="flex min-w-0 items-center gap-2">
|
||||
<div
|
||||
className={cn(
|
||||
@@ -1526,8 +1526,8 @@ export function ArtifactFileDetail({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-end gap-2 md:ml-auto md:w-auto">
|
||||
<ArtifactActions className="bg-muted/45 max-w-full flex-wrap justify-end rounded-3xl border border-black/6 p-1 dark:border-white/8">
|
||||
<div className="flex min-w-0 w-full items-center justify-end gap-2 md:ml-auto md:w-auto">
|
||||
<ArtifactActions className="bg-muted/45 min-w-0 max-w-full flex-wrap justify-end rounded-3xl border border-black/6 p-1 dark:border-white/8">
|
||||
{canPublishToKnowledge && (
|
||||
<ArtifactAction
|
||||
icon={isPublishingToKnowledge ? LoaderIcon : UploadCloudIcon}
|
||||
@@ -1655,16 +1655,18 @@ export function ArtifactFileDetail({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ArtifactAction
|
||||
className="hover:bg-background"
|
||||
icon={XIcon}
|
||||
label={t.common.close}
|
||||
onClick={() => (onClose ? onClose() : setOpen(false))}
|
||||
tooltip={t.common.close}
|
||||
/>
|
||||
</ArtifactActions>
|
||||
</div>
|
||||
</ArtifactHeader>
|
||||
</ArtifactActions>
|
||||
</div>
|
||||
{/* 文件目录会压缩详情区宽度。关闭入口固定在右上角,不再跟随可换行的
|
||||
动作组,避免工具较多或面板较窄时最右侧按钮被裁掉。 */}
|
||||
<ArtifactAction
|
||||
className="bg-background/90 hover:bg-accent absolute top-3 right-3 z-10 border shadow-sm"
|
||||
icon={XIcon}
|
||||
label="收起文件面板"
|
||||
onClick={() => (onClose ? onClose() : setOpen(false))}
|
||||
tooltip="收起文件面板"
|
||||
/>
|
||||
</ArtifactHeader>
|
||||
<ArtifactContent
|
||||
ref={artifactContentRef}
|
||||
className="relative p-0"
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
"use client";
|
||||
|
||||
import { Wrench, X } from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { useWorkspaceCompactNavItems } from "./workspace-nav-chat-list";
|
||||
|
||||
const TOOLBOX_ICON_TONES = [
|
||||
"bg-blue-500/12 text-blue-600 dark:text-blue-400",
|
||||
"bg-violet-500/12 text-violet-600 dark:text-violet-400",
|
||||
"bg-emerald-500/12 text-emerald-600 dark:text-emerald-400",
|
||||
"bg-amber-500/14 text-amber-600 dark:text-amber-400",
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* 简洁模式右侧工具箱。
|
||||
*
|
||||
* 菜单来源与左侧简洁菜单、设置和更多完全一致,由管理员在菜单管理中把项目
|
||||
* 放到 ``toolbox`` 泳道。点击右侧竖排按钮后展开单列竖向抽屉。
|
||||
*/
|
||||
export function CompactToolbox() {
|
||||
const { toolboxItems } = useWorkspaceCompactNavItems();
|
||||
const { pathname } = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const [open, setOpen] = useState(false);
|
||||
const triggerRef = useRef<HTMLButtonElement>(null);
|
||||
const closeRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
useEffect(() => setOpen(false), [pathname]);
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === "Escape") {
|
||||
setOpen(false);
|
||||
triggerRef.current?.focus();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
closeRef.current?.focus();
|
||||
return () => {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
if (toolboxItems.length === 0) return null;
|
||||
|
||||
const closeDrawer = () => {
|
||||
setOpen(false);
|
||||
requestAnimationFrame(() => triggerRef.current?.focus());
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
ref={triggerRef}
|
||||
type="button"
|
||||
aria-label="打开工具箱"
|
||||
aria-controls="compact-toolbox-panel"
|
||||
aria-expanded={open}
|
||||
title="打开工具箱"
|
||||
onClick={() => setOpen(true)}
|
||||
className={cn(
|
||||
"fixed right-0 top-1/2 z-[80] flex size-16 -translate-y-1/2 flex-col items-center justify-center gap-1 rounded-l-2xl border border-r-0 border-primary/25 bg-primary text-primary-foreground shadow-xl transition-[transform,opacity,background-color] duration-200 hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||
open && "pointer-events-none translate-x-full opacity-0",
|
||||
)}
|
||||
>
|
||||
<Wrench className="size-6 shrink-0" />
|
||||
<span className="text-xs font-semibold leading-4">工具箱</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
aria-label="关闭工具箱抽屉"
|
||||
aria-hidden={!open}
|
||||
onClick={closeDrawer}
|
||||
className={cn(
|
||||
"fixed inset-0 z-[90] bg-black/20 transition-opacity duration-200",
|
||||
open ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0",
|
||||
)}
|
||||
/>
|
||||
|
||||
<aside
|
||||
id="compact-toolbox-panel"
|
||||
role="dialog"
|
||||
aria-modal={open}
|
||||
aria-label="工具箱"
|
||||
aria-hidden={!open}
|
||||
inert={!open}
|
||||
className={cn(
|
||||
"fixed right-0 top-1/2 z-[100] flex max-h-[calc(100vh-32px)] w-32 max-w-[calc(100vw-48px)] -translate-y-1/2 flex-col overflow-hidden rounded-l-2xl bg-background text-foreground shadow-2xl transition-transform duration-300 ease-out",
|
||||
open
|
||||
? "pointer-events-auto translate-x-0"
|
||||
: "pointer-events-none translate-x-full",
|
||||
)}
|
||||
>
|
||||
<header className="relative flex h-12 shrink-0 items-center justify-center px-2">
|
||||
<h2 className="text-sm font-semibold">工具箱</h2>
|
||||
<button
|
||||
ref={closeRef}
|
||||
type="button"
|
||||
aria-label="关闭工具箱"
|
||||
title="关闭"
|
||||
onClick={closeDrawer}
|
||||
className="absolute right-2 flex size-7 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
>
|
||||
<X className="size-4" />
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<nav
|
||||
aria-label="工具箱菜单"
|
||||
className="flex min-h-0 flex-col items-center gap-2.5 overflow-y-auto bg-muted/20 p-2"
|
||||
>
|
||||
{toolboxItems.map((item, index) => {
|
||||
const Icon = item.icon;
|
||||
const active = item.match(pathname);
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
aria-current={active ? "page" : undefined}
|
||||
className={cn(
|
||||
"group flex h-24 w-24 aspect-square shrink-0 flex-col items-center justify-center gap-1.5 rounded-xl p-2 text-center transition-[color,background-color,transform] hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
||||
active
|
||||
? "bg-primary/12 text-primary ring-1 ring-inset ring-primary/25"
|
||||
: "bg-muted/55 text-card-foreground hover:bg-primary/8 hover:text-primary",
|
||||
)}
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
navigate(item.path ?? "/page/workspace/chats/new");
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"flex size-10 shrink-0 items-center justify-center rounded-xl transition-transform group-hover:scale-105",
|
||||
active
|
||||
? "bg-primary text-primary-foreground"
|
||||
: TOOLBOX_ICON_TONES[index % TOOLBOX_ICON_TONES.length],
|
||||
)}
|
||||
>
|
||||
<Icon className="size-6" strokeWidth={1.8} />
|
||||
</span>
|
||||
<span
|
||||
className="line-clamp-2 w-full text-center text-xs font-medium leading-4"
|
||||
title={item.label}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</aside>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -135,6 +135,7 @@ export type EffectiveWorkspaceCompactNavItem = CompactMenuItem & WorkspaceCompac
|
||||
export function useWorkspaceCompactNavItems(): {
|
||||
sidebarItems: EffectiveWorkspaceCompactNavItem[];
|
||||
settingsItems: EffectiveWorkspaceCompactNavItem[];
|
||||
toolboxItems: EffectiveWorkspaceCompactNavItem[];
|
||||
} {
|
||||
const { data: overrides = [] } = useCompactMenuOverrides();
|
||||
return useMemo(() => {
|
||||
@@ -142,6 +143,7 @@ export function useWorkspaceCompactNavItems(): {
|
||||
return {
|
||||
sidebarItems: applied.sidebarItems as EffectiveWorkspaceCompactNavItem[],
|
||||
settingsItems: applied.settingsItems as EffectiveWorkspaceCompactNavItem[],
|
||||
toolboxItems: applied.toolboxItems as EffectiveWorkspaceCompactNavItem[],
|
||||
};
|
||||
}, [overrides]);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,15 @@ test("normalizeCompactMenuType defaults to A", () => {
|
||||
assert.equal(isDefaultCompactMenuType("B"), false);
|
||||
});
|
||||
|
||||
test("applyCompactMenuOverrides splits sidebar vs settings", () => {
|
||||
test("applyCompactMenuOverrides splits sidebar, settings, and toolbox", () => {
|
||||
const items: MenuItem[] = [
|
||||
{ id: "a", label: "对话", icon: I, path: "/a" },
|
||||
{ id: "b", label: "智能体", icon: I, path: "/b" },
|
||||
{ id: "c", label: "技能", icon: I, path: "/c" },
|
||||
];
|
||||
const applied = applyCompactMenuOverrides(items, [
|
||||
{ nodeId: "b", placement: "settings", sortOrder: 0, label: "智能体设置" },
|
||||
{ nodeId: "c", placement: "toolbox", sortOrder: 0, label: "技能工具" },
|
||||
]);
|
||||
assert.deepEqual(
|
||||
applied.sidebarItems.map((item) => item.id),
|
||||
@@ -32,4 +34,6 @@ test("applyCompactMenuOverrides splits sidebar vs settings", () => {
|
||||
);
|
||||
assert.equal(applied.settingsItems[0]?.id, "b");
|
||||
assert.equal(applied.settingsItems[0]?.label, "智能体设置");
|
||||
assert.equal(applied.toolboxItems[0]?.id, "c");
|
||||
assert.equal(applied.toolboxItems[0]?.label, "技能工具");
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { MenuItem } from "./sidebar-menu";
|
||||
import { readRuntimeEnv } from "@/env";
|
||||
|
||||
export type CompactMenuPlacement = "sidebar" | "settings";
|
||||
export type CompactMenuPlacement = "sidebar" | "settings" | "toolbox";
|
||||
|
||||
export const COMPACT_MENU_TYPES = ["A", "B"] as const;
|
||||
export type CompactMenuType = (typeof COMPACT_MENU_TYPES)[number];
|
||||
@@ -64,7 +64,11 @@ function isNavigable(item: MenuItem): boolean {
|
||||
export function applyCompactMenuOverrides(
|
||||
items: MenuItem[],
|
||||
overrides: CompactMenuOverride[],
|
||||
): { sidebarItems: CompactMenuItem[]; settingsItems: CompactMenuItem[] } {
|
||||
): {
|
||||
sidebarItems: CompactMenuItem[];
|
||||
settingsItems: CompactMenuItem[];
|
||||
toolboxItems: CompactMenuItem[];
|
||||
} {
|
||||
const byId = new Map(overrides.map((override) => [override.nodeId, override]));
|
||||
const enhanced = items.filter(isNavigable).map((item, index) => {
|
||||
const override = byId.get(item.id);
|
||||
@@ -82,6 +86,7 @@ export function applyCompactMenuOverrides(
|
||||
return {
|
||||
sidebarItems: sortItems(enhanced.filter((item) => item.compactPlacement === "sidebar")),
|
||||
settingsItems: sortItems(enhanced.filter((item) => item.compactPlacement === "settings")),
|
||||
toolboxItems: sortItems(enhanced.filter((item) => item.compactPlacement === "toolbox")),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -810,7 +810,7 @@ export default function AgentChatPage({
|
||||
agentName={agentDisplayName}
|
||||
disabled={thread.isLoading || isDemoMode}
|
||||
onAskQuestion={(text) => handleSubmit({ text, files: [] })}
|
||||
defaultCollapsed={taskCtxOn}
|
||||
defaultCollapsed
|
||||
showRecentChats={!taskCtxOn}
|
||||
compactAppearanceActions={compactAppearanceActions}
|
||||
/>
|
||||
|
||||
@@ -261,12 +261,17 @@ function compactRowsFromTree(tree: MenuItem[], overrides: CompactMenuOverride[])
|
||||
}
|
||||
|
||||
function normalizeCompactRows(rows: CompactRow[]): CompactRow[] {
|
||||
const placementOrder: Record<CompactMenuPlacement, number> = {
|
||||
sidebar: 0,
|
||||
settings: 1,
|
||||
toolbox: 2,
|
||||
};
|
||||
return rows
|
||||
.slice()
|
||||
.sort(
|
||||
(a, b) =>
|
||||
a.topIndex - b.topIndex ||
|
||||
Number(a.placement === "settings") - Number(b.placement === "settings") ||
|
||||
placementOrder[a.placement] - placementOrder[b.placement] ||
|
||||
a.order - b.order ||
|
||||
a.id.localeCompare(b.id),
|
||||
);
|
||||
@@ -1091,7 +1096,7 @@ function CompactMenuManagementPanel({ baseTree }: { baseTree: MenuItem[] }) {
|
||||
<p className="flex max-w-2xl items-start gap-2.5 rounded-2xl border border-slate-200/50 bg-slate-50/70 p-3.5 text-sm leading-relaxed text-slate-600">
|
||||
<Info className="mt-0.5 size-4 shrink-0 text-slate-400" />
|
||||
<span>
|
||||
这里配置的是简洁模式工作区左侧菜单,保存后仅对当前网页使用的
|
||||
这里配置简洁模式菜单在左侧菜单、设置和更多、右侧工具箱之间的分布,保存后仅对当前网页使用的
|
||||
{COMPACT_MENU_TYPE_LABELS[runtimeType]}生效(两套部署各改各的);全量模式菜单不受影响。
|
||||
</span>
|
||||
</p>
|
||||
@@ -1132,6 +1137,7 @@ function CompactMenuManagementPanel({ baseTree }: { baseTree: MenuItem[] }) {
|
||||
<SelectContent>
|
||||
<SelectItem value="sidebar">左侧菜单</SelectItem>
|
||||
<SelectItem value="settings">设置和更多</SelectItem>
|
||||
<SelectItem value="toolbox">右侧工具箱</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div className="flex justify-end gap-1.5">
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Navigate, Route, Routes } from "react-router-dom";
|
||||
|
||||
import { PageSidebar } from "@/components/page-sidebar";
|
||||
import { PageSidebarDark } from "@/components/page-sidebar-dark";
|
||||
import { CompactToolbox } from "@/components/workspace/compact-toolbox";
|
||||
import { isChatsIframeWorkspacePath } from "@/core/page-layout/chats-iframe-route";
|
||||
import { readSidebarEnabled } from "@/core/page-layout/sidebar-enabled";
|
||||
import { isWujieEnv } from "@/core/embed/wujie";
|
||||
@@ -102,12 +103,19 @@ function PageLayout() {
|
||||
!embedActive &&
|
||||
// `?hideChrome=1` 显式去 chrome:优先级高于上面对 dashboard-agent 的强制全局 chrome。
|
||||
!chromeHidden;
|
||||
const compactToolboxAllowed =
|
||||
!chromeByPreference &&
|
||||
!forceChromeForDashboardAgent &&
|
||||
!embedActive &&
|
||||
!chromeHidden &&
|
||||
!isChatsIframeWorkspacePath(location.pathname);
|
||||
|
||||
// h-full(100%)而非 h-screen(100vh):配合 globals.css 的 html/body/#root height:100%
|
||||
// 高度链,根布局跟随容器高度。全屏下 100% 解析到视口,与 h-screen 等价;无界等嵌套
|
||||
// 下容器不占满整屏时,高度才能正确收缩而非锁死整屏。
|
||||
return (
|
||||
<RoundtableJobNotifier>
|
||||
{compactToolboxAllowed && <CompactToolbox />}
|
||||
<div className="h-full flex flex-col bg-muted/20">
|
||||
{pageSidebarAllowed && !headerHidden && <Header collapsed={collapsed} />}
|
||||
<div className="flex flex-1 overflow-hidden">
|
||||
|
||||
@@ -14,16 +14,20 @@ const BASE = () => `${getBackendBaseURL()}/api/compact-menu-overrides`;
|
||||
|
||||
interface ServerCompactOverride {
|
||||
node_id: string;
|
||||
placement: "sidebar" | "settings";
|
||||
placement: "sidebar" | "settings" | "toolbox";
|
||||
sort_order: number;
|
||||
label: string | null;
|
||||
menu_type?: string | null;
|
||||
}
|
||||
|
||||
function toOverride(s: ServerCompactOverride): CompactMenuOverride {
|
||||
const placement =
|
||||
s.placement === "settings" || s.placement === "toolbox"
|
||||
? s.placement
|
||||
: "sidebar";
|
||||
return {
|
||||
nodeId: s.node_id,
|
||||
placement: s.placement === "settings" ? "settings" : "sidebar",
|
||||
placement,
|
||||
sortOrder: s.sort_order ?? 0,
|
||||
label: s.label ?? null,
|
||||
};
|
||||
@@ -96,8 +100,11 @@ export function useCompactMenuOverrides(menuType?: CompactMenuType) {
|
||||
return useQuery({
|
||||
queryKey: [COMPACT_MENU_OVERRIDES_KEY, type],
|
||||
queryFn: () => listCompactMenuOverrides(type),
|
||||
refetchOnWindowFocus: false,
|
||||
staleTime: 60_000,
|
||||
// 菜单管理常在另一个标签页操作。简洁模式页面重新挂载或获得焦点时必须
|
||||
// 立即读取最新配置,否则新放入右侧工具箱的项目会被旧缓存隐藏一分钟。
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: "always",
|
||||
staleTime: 0,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user