Files
deerflow-code/frontend-web/src/core/system-settings/hooks.ts
T
董宏凯andClaude Haiku 4.5 01012ff300 feat(settings): 轻应用登录参数与界面模式管理员默认
- 登录时从路由参数 yUserId/access_token 获取并存入 userInfo
- 轻应用管理页路由参数新增 userName/gateDepartName/typeName 选项
- 添加系统默认界面模式设置(管理员可指定全量/简洁)
- useLayoutMode hook 支持优先级:用户自选 > 管理员默认 > 会话级

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-15 11:39:02 +08:00

210 lines
6.6 KiB
TypeScript

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useLocalSettings } from "@/core/settings";
import {
loadAppearanceSettings,
loadCitationDisplaySettings,
loadLeaderboardSettings,
loadPrivateSquareStatus,
loadPromptPrefixSettings,
loadPublishSquares,
updateAppearanceSettings,
updateCitationDisplaySettings,
updateLeaderboardSettings,
updatePrivateSquareSettings,
updatePromptPrefixSettings,
updatePublishSquares,
type AppearanceUpdate,
type CitationDisplayUpdate,
type LeaderboardSettingsUpdate,
type PrivateSquareUpdate,
type PromptPrefixUpdate,
type PublishSquaresUpdate,
type LayoutMode,
type ViewMode,
} from "./api";
const PROMPT_PREFIX_KEY = ["systemSettings", "promptPrefix"] as const;
const PRIVATE_SQUARE_KEY = ["systemSettings", "privateSquare"] as const;
const PUBLISH_SQUARES_KEY = ["systemSettings", "publishSquares"] as const;
const APPEARANCE_KEY = ["systemSettings", "appearance"] as const;
const CITATION_DISPLAY_KEY = ["systemSettings", "citationDisplay"] as const;
const LEADERBOARD_KEY = ["systemSettings", "leaderboard"] as const;
export function usePromptPrefixSettings() {
return useQuery({
queryKey: PROMPT_PREFIX_KEY,
queryFn: () => loadPromptPrefixSettings(),
staleTime: 60_000,
refetchOnWindowFocus: false,
refetchOnMount: false,
});
}
export function useUpdatePromptPrefixSettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (body: PromptPrefixUpdate) => updatePromptPrefixSettings(body),
onSuccess: (data) => {
queryClient.setQueryData(PROMPT_PREFIX_KEY, data);
},
});
}
export function usePrivateSquareStatus() {
return useQuery({
queryKey: PRIVATE_SQUARE_KEY,
queryFn: () => loadPrivateSquareStatus(),
staleTime: 60_000,
refetchOnWindowFocus: false,
});
}
export function useUpdatePrivateSquareSettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (body: PrivateSquareUpdate) =>
updatePrivateSquareSettings(body),
onSuccess: (data) => {
queryClient.setQueryData(PRIVATE_SQUARE_KEY, data);
},
});
}
/** The configured publish squares (发布广场). Readable by any logged-in user —
* the gallery sub-tabs and the publish-flow square picker both need it. */
export function usePublishSquares() {
return useQuery({
queryKey: PUBLISH_SQUARES_KEY,
queryFn: () => loadPublishSquares(),
staleTime: 60_000,
refetchOnWindowFocus: false,
retry: false,
});
}
export function useUpdatePublishSquares() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (body: PublishSquaresUpdate) => updatePublishSquares(body),
onSuccess: (data) => {
queryClient.setQueryData(PUBLISH_SQUARES_KEY, data);
// Squares changing can re-bucket gallery tabs; refresh agent/skill lists.
queryClient.invalidateQueries({ queryKey: ["agents"] });
queryClient.invalidateQueries({ queryKey: ["skills"] });
},
});
}
export function useAppearanceSettings() {
return useQuery({
queryKey: APPEARANCE_KEY,
queryFn: () => loadAppearanceSettings(),
staleTime: 60_000,
refetchOnWindowFocus: false,
// The provider runs even on the login page (where the user has no auth)
// — gracefully tolerate the fetch failing rather than retrying.
retry: false,
});
}
export function useUpdateAppearanceSettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (body: AppearanceUpdate) => updateAppearanceSettings(body),
onSuccess: (data) => {
queryClient.setQueryData(APPEARANCE_KEY, data);
},
});
}
/**
* Effective card/list display mode for the skill or agent list. A user's own
* choice (persisted in local settings) wins; otherwise the admin-configured
* system default applies; otherwise a built-in fallback (skills → list,
* agents → card, matching the historical layout of each page). `setMode`
* persists the user's override locally.
*/
export function useViewMode(
kind: "skill" | "agent",
): [ViewMode, (mode: ViewMode) => void] {
const [settings, setSettings] = useLocalSettings();
const { data: appearance } = useAppearanceSettings();
const overrideKey = kind === "skill" ? "skillViewMode" : "agentViewMode";
const userOverride = settings.display[overrideKey];
const adminDefault =
kind === "skill"
? appearance?.default_skill_view
: appearance?.default_agent_view;
const fallback: ViewMode = kind === "skill" ? "list" : "card";
const mode: ViewMode = userOverride ?? adminDefault ?? fallback;
const setMode = (next: ViewMode) =>
setSettings("display", { [overrideKey]: next });
return [mode, setMode];
}
/**
* Effective interface layout mode (full chrome vs compact). A user's own choice
* (persisted in local settings) wins; otherwise the admin-configured system
* default applies; otherwise `undefined` (callers fall back to the session-level
* `sidebarEnabled` flag set by portal / yUserId login). `setMode` persists the
* user's override locally.
*/
export function useLayoutMode(): [
LayoutMode | undefined,
(mode: LayoutMode) => void,
] {
const [settings, setSettings] = useLocalSettings();
const { data: appearance } = useAppearanceSettings();
const userOverride = settings.display.layoutMode;
const adminDefault = appearance?.default_layout_mode;
const mode = userOverride ?? adminDefault;
const setMode = (next: LayoutMode) =>
setSettings("display", { layoutMode: next });
return [mode, setMode];
}
export function useCitationDisplaySettings() {
return useQuery({
queryKey: CITATION_DISPLAY_KEY,
queryFn: () => loadCitationDisplaySettings(),
staleTime: 60_000,
refetchOnWindowFocus: false,
retry: false,
});
}
export function useUpdateCitationDisplaySettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (body: CitationDisplayUpdate) =>
updateCitationDisplaySettings(body),
onSuccess: (data) => {
queryClient.setQueryData(CITATION_DISPLAY_KEY, data);
},
});
}
export function useLeaderboardSettings() {
return useQuery({
queryKey: LEADERBOARD_KEY,
queryFn: () => loadLeaderboardSettings(),
staleTime: 60_000,
refetchOnWindowFocus: false,
retry: false,
});
}
export function useUpdateLeaderboardSettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (body: LeaderboardSettingsUpdate) =>
updateLeaderboardSettings(body),
onSuccess: (data) => {
queryClient.setQueryData(LEADERBOARD_KEY, data);
queryClient.invalidateQueries({ queryKey: ["admin-activity", "leaderboard"] });
},
});
}