first commit
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import useAuthStore from "@/stores/user";
|
||||
|
||||
function useAuth() {
|
||||
const access = useAuthStore(state => state.access);
|
||||
|
||||
const auth = (key: string) => access.includes(key);
|
||||
|
||||
return {auth};
|
||||
}
|
||||
|
||||
export default useAuth;
|
||||
@@ -0,0 +1,48 @@
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {useMemo} from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import options from '@/locales/options';
|
||||
|
||||
/**
|
||||
* 语言切换 Hook
|
||||
*/
|
||||
const useLanguage = () => {
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
/**
|
||||
* 切换语言
|
||||
* @param lng 语言代码
|
||||
*/
|
||||
const changeLanguage = async (lng: string) => {
|
||||
const config = getLanguageConfig(lng);
|
||||
dayjs.locale(config.dayjsLocale);
|
||||
await i18n.changeLanguage(lng);
|
||||
localStorage.setItem('i18nextLng', lng);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前语言配置对象
|
||||
*/
|
||||
const getLanguageConfig = (lng: string) => {
|
||||
return options.find(opt => opt.value === lng) || options[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Antd Locale Hook
|
||||
*/
|
||||
const antdLocale = useMemo(() => {
|
||||
const currentLang = i18n.language;
|
||||
const config = options.find(opt => opt.value === currentLang);
|
||||
return config ? config.antdLocale : options[0].antdLocale;
|
||||
}, [i18n.language]);
|
||||
|
||||
return {
|
||||
antdLocale,
|
||||
language: i18n.language,
|
||||
changeLanguage,
|
||||
getLanguageConfig,
|
||||
languageOptions: options,
|
||||
};
|
||||
};
|
||||
|
||||
export default useLanguage;
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
/**
|
||||
* 移动端检测Hook
|
||||
* 根据屏幕宽度检测设备类型,默认768px以下为移动端
|
||||
*/
|
||||
const useMobile = (breakpoint: number = 768): boolean => {
|
||||
const [isMobile, setIsMobile] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
setIsMobile(window.innerWidth < breakpoint);
|
||||
};
|
||||
|
||||
// 初始检测
|
||||
checkMobile();
|
||||
|
||||
// 监听窗口大小变化
|
||||
window.addEventListener('resize', checkMobile);
|
||||
window.addEventListener('orientationchange', checkMobile);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', checkMobile);
|
||||
window.removeEventListener('orientationchange', checkMobile);
|
||||
};
|
||||
}, [breakpoint]);
|
||||
|
||||
return isMobile;
|
||||
};
|
||||
|
||||
export default useMobile;
|
||||
@@ -0,0 +1,76 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import type { AxiosResponse, AxiosError } from 'axios';
|
||||
|
||||
interface UseRequestOptions<T> {
|
||||
manual?: boolean;
|
||||
onSuccess?: (data: T | undefined, response: AxiosResponse<API.ResponseStructure<T>>) => void;
|
||||
onError?: (error: AxiosError) => void;
|
||||
onFinally?: () => void;
|
||||
}
|
||||
|
||||
interface UseRequestResult<T> {
|
||||
data: T | undefined;
|
||||
loading: boolean;
|
||||
success: boolean | null;
|
||||
error: AxiosError | null;
|
||||
run: (...args: any[]) => Promise<AxiosResponse<API.ResponseStructure<T>> | undefined>;
|
||||
}
|
||||
|
||||
function useRequest<T = any>(
|
||||
apiFunction: (...args: any[]) => Promise<AxiosResponse<API.ResponseStructure<T>>>,
|
||||
options: UseRequestOptions<T> = {}
|
||||
): UseRequestResult<T> {
|
||||
const { manual = false, onSuccess, onError, onFinally } = options;
|
||||
const [data, setData] = useState<T>();
|
||||
const [loading, setLoading] = useState(!manual);
|
||||
const [success, setSuccess] = useState<boolean | null>(null);
|
||||
const [error, setError] = useState<AxiosError | null>(null);
|
||||
|
||||
const run = useCallback(
|
||||
async (...args: any[]) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setSuccess(null);
|
||||
setError(null);
|
||||
|
||||
const response = await apiFunction(...args);
|
||||
|
||||
setData(response.data.data);
|
||||
setSuccess(true);
|
||||
|
||||
if (onSuccess) {
|
||||
onSuccess(response.data.data, response);
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (err) {
|
||||
const axiosError = err as AxiosError;
|
||||
setError(axiosError);
|
||||
setSuccess(false);
|
||||
|
||||
if (onError) {
|
||||
onError(axiosError);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
if (onFinally) {
|
||||
onFinally();
|
||||
}
|
||||
}
|
||||
},
|
||||
[apiFunction, onSuccess, onError, onFinally]
|
||||
);
|
||||
|
||||
// 自动执行
|
||||
useState(() => {
|
||||
if (!manual) {
|
||||
run();
|
||||
}
|
||||
});
|
||||
|
||||
return { data, loading, success, error, run };
|
||||
}
|
||||
|
||||
export default useRequest;
|
||||
Reference in New Issue
Block a user