2
0

初始化项目

This commit is contained in:
caiyuchao
2024-11-14 11:06:38 +08:00
parent 988b9e6799
commit 4ffac789e1
320 changed files with 34244 additions and 0 deletions

60
src/service/api/auth.ts Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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'
});
}

View 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);
}
}
);

View 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;
}