generated from kevisual/vite-react-template
132 lines
3.9 KiB
TypeScript
132 lines
3.9 KiB
TypeScript
|
|
import { queryLogin, stackQueryClient } from '@/modules/query';
|
|
import { create } from 'zustand';
|
|
import { toast } from 'sonner';
|
|
import { authQueryKeys } from './hooks';
|
|
export type UserInfo = {
|
|
id?: string;
|
|
username?: string;
|
|
nickname?: string | null;
|
|
needChangePassword?: boolean;
|
|
description?: string | null;
|
|
type?: 'user' | 'org';
|
|
orgs?: string[];
|
|
avatar?: string;
|
|
};
|
|
export type LayoutStore = {
|
|
open: boolean;
|
|
setOpen: (open: boolean) => void;
|
|
openUser: boolean;
|
|
setOpenUser: (openUser: boolean) => void;
|
|
me?: UserInfo;
|
|
setMe: (me: UserInfo) => void;
|
|
clearMe: () => void;
|
|
getMe: () => Promise<void>;
|
|
switchOrg: (username?: string) => Promise<void>;
|
|
isAdmin: boolean;
|
|
setIsAdmin: (isAdmin: boolean) => void
|
|
init: () => Promise<void>;
|
|
openLinkList: string[];
|
|
setOpenLinkList: (openLinkList: string[]) => void;
|
|
loginPageConfig: {
|
|
title: string;
|
|
subtitle: string;
|
|
footer: string;
|
|
};
|
|
setLoginPageConfig: (config: Partial<LayoutStore['loginPageConfig']>) => void;
|
|
links: HeaderLink[];
|
|
setLinks: (links: HeaderLink[]) => void;
|
|
showBaseHeader: boolean;
|
|
setShowBaseHeader: (showBaseHeader: boolean) => void;
|
|
serverData: Record<string, any> | null;
|
|
setServerData: (data: Record<string, any>) => void;
|
|
initConvex: () => Promise<void>;
|
|
};
|
|
type HeaderLink = {
|
|
title?: string;
|
|
href: string;
|
|
description?: string;
|
|
icon?: React.ReactNode;
|
|
key?: string;
|
|
isRoot?: boolean;
|
|
};
|
|
|
|
export const useLayoutStore = create<LayoutStore>((set, get) => ({
|
|
open: false,
|
|
setOpen: (open) => set({ open }),
|
|
openUser: false,
|
|
setOpenUser: (openUser) => set({ openUser }),
|
|
me: undefined,
|
|
setMe: (me) => set({ me }),
|
|
clearMe: () => {
|
|
set({ me: undefined, isAdmin: false });
|
|
},
|
|
getMe: async () => {
|
|
const data = await stackQueryClient.fetchQuery({
|
|
queryKey: authQueryKeys.me,
|
|
queryFn: async () => {
|
|
const res = await queryLogin.getMe();
|
|
if (res.code === 200) {
|
|
return res.data;
|
|
}
|
|
throw new Error(res.message || 'Failed to fetch user info');
|
|
},
|
|
});
|
|
set({ me: data, isAdmin: data?.orgs?.includes?.('admin') || false });
|
|
},
|
|
switchOrg: async (username?: string) => {
|
|
const res = await queryLogin.switchUser(username || '');
|
|
if (res.code === 200) {
|
|
toast.success('切换成功');
|
|
stackQueryClient.invalidateQueries({ queryKey: authQueryKeys.me });
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 1000);
|
|
} else {
|
|
toast.error(res.message || '请求失败');
|
|
}
|
|
},
|
|
isAdmin: false,
|
|
setIsAdmin: (isAdmin) => set({ isAdmin }),
|
|
init: async () => {
|
|
await queryLogin.init();
|
|
const token = await queryLogin.checkTokenValid();
|
|
if (token) {
|
|
set({ me: {} });
|
|
try {
|
|
const userInfo = await queryLogin.checkLocalUser();
|
|
if (userInfo) {
|
|
set({ me: userInfo as UserInfo, isAdmin: userInfo.orgs?.includes?.('admin') || false });
|
|
} else {
|
|
set({ me: undefined, isAdmin: false });
|
|
}
|
|
} catch {
|
|
set({ me: undefined, isAdmin: false });
|
|
}
|
|
}
|
|
// 获取服务端数据
|
|
// @ts-ignore
|
|
const sererData = window.__SERVER_DATA__;
|
|
if (sererData) {
|
|
set({ serverData: sererData });
|
|
}
|
|
},
|
|
initConvex: async () => { },
|
|
openLinkList: ['/login'],
|
|
setOpenLinkList: (openLinkList) => set({ openLinkList }),
|
|
loginPageConfig: {
|
|
title: '可视化管理平台',
|
|
subtitle: '让工具和智能化触手可及',
|
|
footer: '欢迎使用可视化管理平台 · 连接您的工具',
|
|
},
|
|
setLoginPageConfig: (config) => set((state) => ({
|
|
loginPageConfig: { ...state.loginPageConfig, ...config },
|
|
})),
|
|
links: [{ title: '', href: '/', key: 'home' }],
|
|
setLinks: (links) => set({ links }),
|
|
showBaseHeader: true,
|
|
setShowBaseHeader: (showBaseHeader) => set({ showBaseHeader }),
|
|
serverData: null,
|
|
setServerData: (data) => set({ serverData: data }),
|
|
}));
|