- 登录时从路由参数 yUserId/access_token 获取并存入 userInfo - 轻应用管理页路由参数新增 userName/gateDepartName/typeName 选项 - 添加系统默认界面模式设置(管理员可指定全量/简洁) - useLayoutMode hook 支持优先级:用户自选 > 管理员默认 > 会话级 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
210 lines
6.6 KiB
TypeScript
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"] });
|
|
},
|
|
});
|
|
}
|