feat: add backend-mock app
This commit is contained in:
@@ -3,4 +3,4 @@
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/vben-api
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
@@ -1,3 +1,3 @@
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
VITE_GLOB_API_URL=/vben-api
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
@@ -2,4 +2,4 @@
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/vben-api
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
@@ -1,33 +0,0 @@
|
||||
function resultSuccess<T = Record<string, any>>(
|
||||
result: T,
|
||||
{ message = 'ok' } = {},
|
||||
) {
|
||||
return {
|
||||
code: 0,
|
||||
message,
|
||||
result,
|
||||
type: 'success',
|
||||
};
|
||||
}
|
||||
|
||||
function resultError(
|
||||
message = 'Request failed',
|
||||
{ code = -1, result = null } = {},
|
||||
) {
|
||||
return {
|
||||
code,
|
||||
message,
|
||||
result,
|
||||
type: 'error',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh_CN 本函数用于从request数据中获取token,请根据项目的实际情况修改
|
||||
*
|
||||
*/
|
||||
function getRequestToken({ headers }: any): string | undefined {
|
||||
return headers?.authorization;
|
||||
}
|
||||
|
||||
export { getRequestToken, resultError, resultSuccess };
|
@@ -1,101 +0,0 @@
|
||||
import { getRequestToken, resultError, resultSuccess } from './_util';
|
||||
|
||||
const fakeUserList = [
|
||||
{
|
||||
accessToken: 'fakeAdminToken',
|
||||
avatar: '',
|
||||
desc: 'manager',
|
||||
homePath: '/',
|
||||
password: '123456',
|
||||
realName: 'Vben Admin',
|
||||
roles: [
|
||||
{
|
||||
roleName: 'Super Admin',
|
||||
value: 'super',
|
||||
},
|
||||
],
|
||||
userId: '1',
|
||||
username: 'vben',
|
||||
},
|
||||
{
|
||||
accessToken: 'fakeTestToken',
|
||||
avatar: '',
|
||||
desc: 'tester',
|
||||
homePath: '/',
|
||||
password: '123456',
|
||||
realName: 'test user',
|
||||
roles: [
|
||||
{
|
||||
roleName: 'Tester',
|
||||
value: 'test',
|
||||
},
|
||||
],
|
||||
userId: '2',
|
||||
username: 'test',
|
||||
},
|
||||
];
|
||||
|
||||
export default [
|
||||
{
|
||||
method: 'post',
|
||||
response: ({ body }: any) => {
|
||||
const { password, username } = body;
|
||||
const checkUser = fakeUserList.find(
|
||||
(item) => item.username === username && password === item.password,
|
||||
);
|
||||
if (!checkUser) {
|
||||
return resultError('Incorrect account or password!');
|
||||
}
|
||||
const {
|
||||
accessToken,
|
||||
desc,
|
||||
realName,
|
||||
roles,
|
||||
userId,
|
||||
username: _username,
|
||||
} = checkUser;
|
||||
return resultSuccess({
|
||||
accessToken,
|
||||
desc,
|
||||
realName,
|
||||
roles,
|
||||
userId,
|
||||
username: _username,
|
||||
});
|
||||
},
|
||||
timeout: 200,
|
||||
url: '/vben-api/login',
|
||||
},
|
||||
{
|
||||
method: 'get',
|
||||
response: (request: any) => {
|
||||
const token = getRequestToken(request);
|
||||
if (!token) return resultError('Invalid token');
|
||||
const checkUser = fakeUserList.find((item) => item.accessToken === token);
|
||||
if (!checkUser) {
|
||||
return resultError(
|
||||
'The corresponding user information was not obtained!',
|
||||
);
|
||||
}
|
||||
const { accessToken: _token, password: _pwd, ...rest } = checkUser;
|
||||
return resultSuccess(rest);
|
||||
},
|
||||
url: '/vben-api/getUserInfo',
|
||||
},
|
||||
{
|
||||
method: 'get',
|
||||
response: (request: any) => {
|
||||
const token = getRequestToken(request);
|
||||
if (!token) return resultError('Invalid token');
|
||||
const checkUser = fakeUserList.find((item) => item.accessToken === token);
|
||||
if (!checkUser) {
|
||||
return resultError('Invalid token!');
|
||||
}
|
||||
return resultSuccess(undefined, {
|
||||
message: 'Token has been destroyed',
|
||||
});
|
||||
},
|
||||
timeout: 200,
|
||||
url: '/vben-api/logout',
|
||||
},
|
||||
];
|
@@ -46,8 +46,5 @@
|
||||
"pinia": "2.1.7",
|
||||
"vue": "^3.4.31",
|
||||
"vue-router": "^4.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite-plugin-mock": "^3.0.2"
|
||||
}
|
||||
}
|
||||
|
@@ -2,20 +2,20 @@ import type { UserInfo } from '@vben/types';
|
||||
|
||||
import type { UserApiType } from '../types';
|
||||
|
||||
import { get, post } from '#/forward';
|
||||
import { requestClient } from '#/forward';
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
async function userLogin(data: UserApiType.LoginParams) {
|
||||
return post<UserApiType.LoginResult>('/login', data);
|
||||
return requestClient.post<UserApiType.LoginResult>('/auth/login', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
async function getUserInfo() {
|
||||
return get<UserInfo>('/getUserInfo');
|
||||
return requestClient.get<UserInfo>('/auth/getUserInfo');
|
||||
}
|
||||
|
||||
export { getUserInfo, userLogin };
|
||||
|
@@ -10,6 +10,7 @@ namespace UserApiType {
|
||||
accessToken: string;
|
||||
desc: string;
|
||||
realName: string;
|
||||
refreshToken: string;
|
||||
userId: string;
|
||||
username: string;
|
||||
}
|
||||
|
@@ -22,13 +22,6 @@ async function bootstrap(namespace: string) {
|
||||
app.use(router);
|
||||
|
||||
app.mount('#app');
|
||||
|
||||
// production mock server
|
||||
if (import.meta.env.PROD) {
|
||||
import('./mock-prod-server').then(({ setupProdMockServer }) => {
|
||||
setupProdMockServer();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { bootstrap };
|
||||
|
@@ -15,8 +15,8 @@ interface HttpResponse<T = any> {
|
||||
* 0 means success, others means fail
|
||||
*/
|
||||
code: number;
|
||||
data: T;
|
||||
message: string;
|
||||
result: T;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,7 +31,10 @@ function createRequestClient() {
|
||||
return {
|
||||
handler: () => {
|
||||
const accessStore = useAccessStore();
|
||||
return accessStore.getAccessToken;
|
||||
return {
|
||||
refreshToken: `Bearer ${accessStore.getRefreshToken}`,
|
||||
token: `Bearer ${accessStore.getAccessToken}`,
|
||||
};
|
||||
},
|
||||
// 默认
|
||||
key: 'Authorization',
|
||||
@@ -39,23 +42,18 @@ function createRequestClient() {
|
||||
},
|
||||
});
|
||||
setupRequestInterceptors(client);
|
||||
const request = client.request.bind(client);
|
||||
const get = client.get.bind(client);
|
||||
const post = client.post.bind(client);
|
||||
return {
|
||||
get,
|
||||
post,
|
||||
request,
|
||||
};
|
||||
return client;
|
||||
}
|
||||
|
||||
function setupRequestInterceptors(client: RequestClient) {
|
||||
client.addResponseInterceptor(
|
||||
(response: AxiosResponse<HttpResponse>) => {
|
||||
const { data: responseData, status } = response;
|
||||
const { code, message: msg, result } = responseData;
|
||||
if (status === 200 && code === 0) {
|
||||
return result;
|
||||
|
||||
const { code, data, message: msg } = responseData;
|
||||
|
||||
if (status >= 200 && status < 400 && code === 0) {
|
||||
return data;
|
||||
} else {
|
||||
message.error(msg);
|
||||
throw new Error(msg);
|
||||
@@ -73,17 +71,19 @@ function setupRequestInterceptors(client: RequestClient) {
|
||||
} else if (error?.message?.includes?.('timeout')) {
|
||||
errMsg = '请求超时。';
|
||||
} else {
|
||||
errMsg = error?.response?.data?.error?.message ?? '';
|
||||
const data = error?.response?.data;
|
||||
errMsg = (data?.message || data?.error?.message) ?? '';
|
||||
}
|
||||
|
||||
message.error(errMsg);
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const { get, post, request } = createRequestClient();
|
||||
const requestClient = createRequestClient();
|
||||
|
||||
// 其他配置的请求方法
|
||||
// const { request: xxxRequest } = createRequest();
|
||||
|
||||
export { get, post, request };
|
||||
export { requestClient };
|
||||
|
@@ -28,8 +28,9 @@ async function initApplication() {
|
||||
|
||||
/**
|
||||
* 移除并销毁loading
|
||||
* 放在这里是而不是放在 index.html 的app标签内,主要是因为这样比较不会生硬,渲染过快可能会有闪烁
|
||||
* 放在这里是而不是放在 index.html 的app标签内,是因为这样比较不会生硬,渲染过快可能会有闪烁
|
||||
* 通过先添加css动画隐藏,在动画结束后在移除loading节点来改善体验
|
||||
* 不好的地方是会增加一些代码量
|
||||
*/
|
||||
function destroyAppLoading() {
|
||||
// 查找全局 loading 元素
|
||||
|
@@ -1,10 +0,0 @@
|
||||
import { createProdMockServer } from 'vite-plugin-mock/client';
|
||||
|
||||
// 逐一导入您的mock.ts文件
|
||||
// 如果使用vite.mock.config.ts,只需直接导入文件
|
||||
// 可以使用 import.meta.glob功能来进行全部导入
|
||||
import userModule from '../mock/user';
|
||||
|
||||
export function setupProdMockServer() {
|
||||
createProdMockServer([...userModule]);
|
||||
}
|
@@ -4,6 +4,7 @@ import type { LoginAndRegisterParams } from '@vben/universal-ui';
|
||||
import { computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH } from '@vben/constants';
|
||||
import { $t } from '@vben/locales';
|
||||
import { AuthenticationLogin } from '@vben/universal-ui';
|
||||
import { useRequest } from '@vben-core/request';
|
||||
@@ -39,7 +40,7 @@ async function handleLogin(values: LoginAndRegisterParams) {
|
||||
// 异步处理用户登录操作并获取 accessToken
|
||||
// Asynchronously handle the user login operation and obtain the accessToken
|
||||
|
||||
const { accessToken } = await runUserLogin(values);
|
||||
const { accessToken, refreshToken } = await runUserLogin(values);
|
||||
|
||||
// 如果成功获取到 accessToken
|
||||
// If accessToken is successfully obtained
|
||||
@@ -47,15 +48,17 @@ async function handleLogin(values: LoginAndRegisterParams) {
|
||||
// 将 accessToken 存储到 accessStore 中
|
||||
// Store the accessToken in accessStore
|
||||
accessStore.setAccessToken(accessToken);
|
||||
accessStore.setRefreshToken(refreshToken);
|
||||
|
||||
// 获取用户信息并存储到 accessStore 中
|
||||
// Get user information and store it in accessStore
|
||||
const userInfo = await runGetUserInfo();
|
||||
|
||||
accessStore.setUserInfo(userInfo);
|
||||
|
||||
// 跳转到用户信息中定义的 homePath 路径
|
||||
// Redirect to the homePath defined in the user information
|
||||
await router.push(userInfo.homePath);
|
||||
await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
|
||||
notification.success({
|
||||
description: `${$t('authentication.login-success-desc')}:${userInfo.realName}`,
|
||||
duration: 3,
|
||||
|
@@ -46,10 +46,11 @@ export default defineConfig({
|
||||
vite: {
|
||||
server: {
|
||||
proxy: {
|
||||
'/vben-api': {
|
||||
'/api': {
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/vben-api/, ''),
|
||||
target: 'http://localhost:3000',
|
||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
// 代理目标地址 - backend-mock 项目
|
||||
target: 'http://localhost:5320/api',
|
||||
ws: true,
|
||||
},
|
||||
},
|
||||
|
Reference in New Issue
Block a user