初始化项目
This commit is contained in:
60
src/service/api/auth.ts
Normal file
60
src/service/api/auth.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { request } from '../request';
|
||||
|
||||
/**
|
||||
* Login
|
||||
*
|
||||
* @param username User name
|
||||
* @param password Password
|
||||
*/
|
||||
export function fetchLogin(body: Api.Auth.LoginBody) {
|
||||
return request<Api.Auth.LoginToken>({
|
||||
url: '/auth/login',
|
||||
method: 'post',
|
||||
data: body
|
||||
});
|
||||
}
|
||||
|
||||
/** logout */
|
||||
export function doDeleteLogout() {
|
||||
return request<App.Service.Response<null>>({
|
||||
url: '/auth/logout',
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
/** Get user info */
|
||||
export function doGetUserInfo() {
|
||||
return request<Api.Auth.UserInfo>({ url: '/system/user/getInfo' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh token
|
||||
*
|
||||
* @param refreshToken Refresh token
|
||||
*/
|
||||
export function fetchRefreshToken(refreshToken: string) {
|
||||
return request<Api.Auth.LoginToken>({
|
||||
url: '/auth/refreshToken',
|
||||
method: 'post',
|
||||
data: {
|
||||
refreshToken
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* return custom backend error
|
||||
*
|
||||
* @param code error code
|
||||
* @param msg error message
|
||||
*/
|
||||
export function fetchCustomBackendError(code: string, msg: string) {
|
||||
return request({ url: '/auth/error', params: { code, msg } });
|
||||
}
|
||||
|
||||
/** Get check code */
|
||||
export function doGetCheckCode() {
|
||||
return request<{ uuid: string; img: string }>({
|
||||
url: '/code'
|
||||
});
|
||||
}
|
||||
63
src/service/api/dept.ts
Normal file
63
src/service/api/dept.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { request } from '../request';
|
||||
|
||||
export type DeptFormType = Pick<
|
||||
Api.SystemManage.Dept,
|
||||
'deptName' | 'parentId' | 'orderNum' | 'leader' | 'phone' | 'email' | 'status' | 'remark'
|
||||
>;
|
||||
|
||||
/** 获取部门列表 */
|
||||
export function doGetDeptList(params: Api.SystemManage.DeptSearchParams) {
|
||||
return request<Api.SystemManage.DeptList>({
|
||||
url: '/system/dept/list',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门详情
|
||||
*
|
||||
* @param deptId 部门id
|
||||
*/
|
||||
export function doGetDeptInfo(deptId: number) {
|
||||
return request<Api.SystemManage.Dept>({
|
||||
url: `/system/dept/${deptId}`
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加部门
|
||||
*
|
||||
* @param body 部门信息
|
||||
*/
|
||||
export function doAddDept(body: DeptFormType) {
|
||||
return request({
|
||||
url: '/system/dept',
|
||||
method: 'post',
|
||||
data: body
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改部门
|
||||
*
|
||||
* @param body 部门信息
|
||||
*/
|
||||
export function doEditDept(body: DeptFormType & { deptId: number }) {
|
||||
return request({
|
||||
url: '/system/dept',
|
||||
method: 'put',
|
||||
data: body
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部门
|
||||
*
|
||||
* @param deptId 部门id
|
||||
*/
|
||||
export function doDeleteDept(deptId: string | number) {
|
||||
return request({
|
||||
url: `/system/dept/${deptId}`,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
36
src/service/api/dict.ts
Normal file
36
src/service/api/dict.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { request } from '../request';
|
||||
|
||||
export type DictSubmitModel = Partial<
|
||||
Pick<Api.SystemManage.Dict, 'dictName' | 'dictType' | 'status' | 'remark' | 'dictId'>
|
||||
>;
|
||||
|
||||
export const doGetDictList = (params: Api.SystemManage.DictSearchParams) => {
|
||||
return request<Api.SystemManage.DictList>({
|
||||
url: '/system/dict/type/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
export const doAddDict = (data: DictSubmitModel) => {
|
||||
return request({
|
||||
url: '/system/dict/type',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
export const doEditDict = (data: DictSubmitModel) => {
|
||||
return request({
|
||||
url: '/system/dict/type',
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
export const doDeleteDict = (dictId: string | number) => {
|
||||
return request({
|
||||
url: `/system/dict/type/${dictId}`,
|
||||
method: 'post'
|
||||
});
|
||||
};
|
||||
61
src/service/api/menu.ts
Normal file
61
src/service/api/menu.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import type { MenuModelType } from '@/views/manage/menu/modules/form';
|
||||
import { request } from '../request';
|
||||
|
||||
export type MenuListQuery = Partial<
|
||||
Pick<Api.SystemManage.Menu, 'status' | 'hideInMenu' | 'keepAlive' | 'menuType' | 'menuName'>
|
||||
> &
|
||||
Api.SystemManage.CommonSearchParams;
|
||||
|
||||
export function doGetMenuList(params: MenuListQuery) {
|
||||
return request<Api.SystemManage.MenuList>({ url: '/system/menu/list', method: 'get', params });
|
||||
}
|
||||
|
||||
/** get all pages */
|
||||
export function fetchGetAllPages() {
|
||||
return request<Pick<Api.SystemManage.Menu, 'menuId' | 'menuName' | 'path'>[]>({
|
||||
url: '/system/menu/list',
|
||||
method: 'get',
|
||||
params: {
|
||||
menuType: 'C'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** get menu tree */
|
||||
export function fetchGetMenuTree() {
|
||||
return request<Api.SystemManage.MenuTree[]>({
|
||||
url: '/system/menu/treeselect',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/** get role menu list */
|
||||
export function doGetRoleMenuList(roleId: number) {
|
||||
return request<{
|
||||
checkedKeys: number[];
|
||||
menus: Api.SystemManage.MenuTree[];
|
||||
}>({
|
||||
url: `/system/menu/roleMenuTreeselect/${roleId}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/** add menu */
|
||||
export function doAddMenu(data: MenuModelType) {
|
||||
return request({ url: '/system/menu', method: 'post', data });
|
||||
}
|
||||
|
||||
/** delete menu */
|
||||
export function doDeleteMenu(menuId: number) {
|
||||
return request({ url: `/system/menu/${menuId}`, method: 'delete' });
|
||||
}
|
||||
|
||||
/** get menu detail */
|
||||
export function doGetMenuDetail(menuId: number) {
|
||||
return request<MenuModelType>({ url: `/system/menu/${menuId}`, method: 'get' });
|
||||
}
|
||||
|
||||
/** edit menu */
|
||||
export function doEditMenu(data: MenuModelType) {
|
||||
return request({ url: '/system/menu', method: 'put', data });
|
||||
}
|
||||
43
src/service/api/post.ts
Normal file
43
src/service/api/post.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { request } from '../request';
|
||||
|
||||
export type PostSubmitModel = Partial<
|
||||
Pick<Api.SystemManage.Post, 'postCode' | 'postName' | 'postSort' | 'status' | 'remark'>
|
||||
>;
|
||||
|
||||
export function doGetPostList(params: Api.SystemManage.PostSearchParams) {
|
||||
return request<Api.SystemManage.PostList>({
|
||||
url: '/system/post/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
export function doGetPostDetail(postId: number) {
|
||||
return request({
|
||||
url: `/system/post/${postId}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
export function doAddPost(data: PostSubmitModel) {
|
||||
return request({
|
||||
url: '/system/post',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function doEditPost(data: PostSubmitModel) {
|
||||
return request({
|
||||
url: '/system/post',
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function doDeletePost(postId: string | number) {
|
||||
return request({
|
||||
url: `/system/post/${postId}`,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
39
src/service/api/role.ts
Normal file
39
src/service/api/role.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { request } from '../request';
|
||||
|
||||
/**
|
||||
* edit role info
|
||||
*
|
||||
* @param role role info
|
||||
* @returns
|
||||
*/
|
||||
export function doPutRole(role: Api.SystemManage.Role) {
|
||||
return request({ url: '/system/role', method: 'put', data: role });
|
||||
}
|
||||
|
||||
/**
|
||||
* add role
|
||||
*
|
||||
* @param role role info
|
||||
* @returns
|
||||
*/
|
||||
export function doPostRole(role: Api.SystemManage.Role) {
|
||||
return request({ url: '/system/role', method: 'post', data: role });
|
||||
}
|
||||
|
||||
/**
|
||||
* delete role
|
||||
*
|
||||
* @param roleId role id
|
||||
* @returns
|
||||
*/
|
||||
export function doDeleteRole(roleId: number | string) {
|
||||
return request({ url: `/system/role/${roleId}`, method: 'delete' });
|
||||
}
|
||||
|
||||
export function doGetRoleList(params?: Api.SystemManage.RoleSearchParams) {
|
||||
return request<Api.SystemManage.RoleList>({
|
||||
url: '/system/role/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
20
src/service/api/route.ts
Normal file
20
src/service/api/route.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { request } from '../request';
|
||||
|
||||
/** get constant routes */
|
||||
export function fetchGetConstantRoutes() {
|
||||
return request<Api.Route.MenuRoute[]>({ url: '/route/getConstantRoutes' });
|
||||
}
|
||||
|
||||
/** get user routes */
|
||||
export function doGetUserRoutes() {
|
||||
return request<Api.Route.MenuRoute[]>({ url: '/system/menu/getRouters' });
|
||||
}
|
||||
|
||||
/**
|
||||
* whether the route is exist
|
||||
*
|
||||
* @param routeName route name
|
||||
*/
|
||||
export function fetchIsRouteExist(routeName: string) {
|
||||
return request<boolean>({ url: '/route/isRouteExist', params: { routeName } });
|
||||
}
|
||||
54
src/service/api/user.ts
Normal file
54
src/service/api/user.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { request } from '../request';
|
||||
|
||||
// user api
|
||||
export function doPutUser(user: Api.Auth.User) {
|
||||
return request({ url: '/system/user', method: 'put', data: user });
|
||||
}
|
||||
|
||||
export function doPostUser(user: Api.Auth.User) {
|
||||
return request({ url: '/system/user', method: 'post', data: user });
|
||||
}
|
||||
|
||||
export function doDeleteUser(userId: number | string) {
|
||||
return request({ url: `/system/user/${userId}`, method: 'delete' });
|
||||
}
|
||||
|
||||
export function doGetUserList(params?: Api.SystemManage.UserSearchParams) {
|
||||
return request<Api.SystemManage.UserList>({
|
||||
url: '/system/user/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @returns 用户信息[posts & roles]
|
||||
*/
|
||||
export function doGetUserPostsAndRoles(userId: number | string | undefined) {
|
||||
if (!userId) {
|
||||
return request<Api.SystemManage.UserPostsAndRoles>({
|
||||
url: '/system/user/',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
return request<Api.SystemManage.UserPostsAndRoles>({
|
||||
url: `/system/user/${userId}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
export function doGetAdminUserPostsAndRoles() {
|
||||
return request<Api.SystemManage.UserPostsAndRoles>({
|
||||
url: `/system/user`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
export function doGetUserDeptTree() {
|
||||
return request<Api.Common.CommonTree>({
|
||||
url: '/system/user/deptTree',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
133
src/service/request/index.ts
Normal file
133
src/service/request/index.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { BACKEND_ERROR_CODE, createFlatRequest } from '@sa/axios';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { getServiceBaseURL } from '@/utils/service';
|
||||
import { $t } from '@/locales';
|
||||
import { clearAuthStorage } from '@/store/modules/auth/shared';
|
||||
|
||||
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
||||
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
||||
|
||||
interface InstanceState {
|
||||
/** whether the request is refreshing token */
|
||||
isRefreshingToken: boolean;
|
||||
}
|
||||
|
||||
export const request = createFlatRequest<App.Service.Response, InstanceState>(
|
||||
{
|
||||
baseURL,
|
||||
'axios-retry': {
|
||||
retries: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
async onRequest(config) {
|
||||
const { headers } = config;
|
||||
|
||||
// set token
|
||||
const token = localStg.get('token');
|
||||
const Authorization = token ? `Bearer ${token}` : null;
|
||||
Object.assign(headers, { Authorization });
|
||||
|
||||
return config;
|
||||
},
|
||||
isBackendSuccess(response) {
|
||||
// when the backend response code is "0000"(default), it means the request is success
|
||||
// to change this logic by yourself, you can modify the `VITE_SERVICE_SUCCESS_CODE` in `.env` file
|
||||
return String(response.data.code) === import.meta.env.VITE_SERVICE_SUCCESS_CODE;
|
||||
},
|
||||
async onBackendFail(response, _instance) {
|
||||
const authStore = useAuthStore();
|
||||
|
||||
function handleLogout() {
|
||||
authStore.resetStore();
|
||||
}
|
||||
|
||||
function logoutAndCleanup() {
|
||||
handleLogout();
|
||||
window.removeEventListener('beforeunload', handleLogout);
|
||||
}
|
||||
|
||||
// when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
|
||||
const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || [];
|
||||
if (logoutCodes.includes(String(response.data.code))) {
|
||||
handleLogout();
|
||||
return null;
|
||||
}
|
||||
|
||||
// when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
|
||||
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
||||
if (modalLogoutCodes.includes(String(response.data.code))) {
|
||||
// prevent the user from refreshing the page
|
||||
window.addEventListener('beforeunload', handleLogout);
|
||||
|
||||
$modal?.error({
|
||||
title: 'Error',
|
||||
content: response.data.msg,
|
||||
okText: $t('common.confirm'),
|
||||
maskClosable: false,
|
||||
onOk() {
|
||||
logoutAndCleanup();
|
||||
},
|
||||
onCancel() {
|
||||
logoutAndCleanup();
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// when the backend response code is in `expiredTokenCodes`, it means the token is expired, and refresh token
|
||||
// the api `refreshToken` can not return error code in `expiredTokenCodes`, otherwise it will be a dead loop, should return `logoutCodes` or `modalLogoutCodes`
|
||||
// eslint-disable-next-line no-warning-comments
|
||||
// TODO: fix when back code is 403 the page redirect to login
|
||||
// const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || [];
|
||||
// if (expiredTokenCodes.includes(String(response.data.code)) && !request.state.isRefreshingToken) {
|
||||
// request.state.isRefreshingToken = true;
|
||||
|
||||
// const refreshConfig = await handleRefreshToken(response.config);
|
||||
|
||||
// request.state.isRefreshingToken = false;
|
||||
|
||||
// if (refreshConfig) {
|
||||
// return instance.request(refreshConfig) as Promise<AxiosResponse>;
|
||||
// }
|
||||
// }
|
||||
|
||||
return null;
|
||||
},
|
||||
transformBackendResponse(response) {
|
||||
return response.data.data;
|
||||
},
|
||||
onError(error) {
|
||||
// when the request is fail, you can show error message
|
||||
let message = error.message;
|
||||
let backendErrorCode = '';
|
||||
|
||||
// get backend error message and code
|
||||
if (error.code === BACKEND_ERROR_CODE) {
|
||||
message = error.response?.data?.msg || message;
|
||||
backendErrorCode = error.response?.data?.code || '';
|
||||
}
|
||||
|
||||
// the error message is displayed in the modal
|
||||
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
||||
if (modalLogoutCodes.includes(backendErrorCode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// when the token is expired, refresh token and retry request, so no need to show error message
|
||||
const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || [];
|
||||
if (expiredTokenCodes.includes(backendErrorCode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (backendErrorCode === import.meta.env.VITE_SERVICE_SERVER_ERROR_CODE) {
|
||||
clearAuthStorage();
|
||||
return;
|
||||
}
|
||||
|
||||
$message?.error?.(message);
|
||||
}
|
||||
}
|
||||
);
|
||||
31
src/service/request/shared.ts
Normal file
31
src/service/request/shared.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { fetchRefreshToken } from '../api';
|
||||
|
||||
/**
|
||||
* refresh token
|
||||
*
|
||||
* @param axiosConfig - request config when the token is expired
|
||||
*/
|
||||
export async function handleRefreshToken(axiosConfig: AxiosRequestConfig) {
|
||||
const { resetStore } = useAuthStore();
|
||||
|
||||
const refreshToken = localStg.get('refreshToken') || '';
|
||||
const { error, data } = await fetchRefreshToken(refreshToken);
|
||||
if (!error) {
|
||||
localStg.set('token', data.access_token);
|
||||
localStg.set('refreshToken', data.refreshToken);
|
||||
|
||||
const config = { ...axiosConfig };
|
||||
if (config.headers) {
|
||||
config.headers.Authorization = data.access_token;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
resetStore();
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user