git commit -m feat(projects): 对接后端登录接口
This commit is contained in:
12
.env
12
.env
@ -2,9 +2,9 @@
|
||||
# if use a sub directory, it must be end with "/", like "/admin/" but not "/admin"
|
||||
VITE_BASE_URL=/
|
||||
|
||||
VITE_APP_TITLE=SoybeanAdmin
|
||||
VITE_APP_TITLE=Dolphin
|
||||
|
||||
VITE_APP_DESC=SoybeanAdmin is a fresh and elegant admin template
|
||||
VITE_APP_DESC='A fresh and elegant admin management system'
|
||||
|
||||
# the prefix of the icon name
|
||||
VITE_ICON_PREFIX=icon
|
||||
@ -29,16 +29,16 @@ VITE_HTTP_PROXY=Y
|
||||
VITE_ROUTER_HISTORY_MODE=history
|
||||
|
||||
# success code of backend service, when the code is received, the request is successful
|
||||
VITE_SERVICE_SUCCESS_CODE=0000
|
||||
VITE_SERVICE_SUCCESS_CODE=00000000
|
||||
|
||||
# logout codes of backend service, when the code is received, the user will be logged out and redirected to login page
|
||||
VITE_SERVICE_LOGOUT_CODES=8888,8889
|
||||
VITE_SERVICE_LOGOUT_CODES=00010001,00010002
|
||||
|
||||
# modal logout codes of backend service, when the code is received, the user will be logged out by displaying a modal
|
||||
VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
|
||||
VITE_SERVICE_MODAL_LOGOUT_CODES=00010004
|
||||
|
||||
# token expired codes of backend service, when the code is received, it will refresh the token and resend the request
|
||||
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998,3333
|
||||
VITE_SERVICE_EXPIRED_TOKEN_CODES=00010003
|
||||
|
||||
# when the route mode is static, the defined super role
|
||||
VITE_STATIC_SUPER_ROLE=R_SUPER
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# backend service base url, test environment
|
||||
VITE_SERVICE_BASE_URL=https://mock.apifox.cn/m1/3109515-0-default
|
||||
VITE_SERVICE_BASE_URL=http://localhost:8080
|
||||
|
||||
# other backend service base url, test environment
|
||||
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||
VITE_OTHER_SERVICE_BASE_URL=`{
|
||||
"demo": "http://localhost:9528"
|
||||
}`
|
||||
|
||||
@ -73,7 +73,7 @@ function handleDropdown(key: DropdownKey) {
|
||||
<div>
|
||||
<ButtonIcon>
|
||||
<SvgIcon icon="ph:user-circle" class="text-icon-large" />
|
||||
<span class="text-16px font-medium">{{ authStore.userInfo.userName }}</span>
|
||||
<span class="text-16px font-medium">{{ authStore.userInfo.username }}</span>
|
||||
</ButtonIcon>
|
||||
</div>
|
||||
</NDropdown>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const local: App.I18n.Schema = {
|
||||
system: {
|
||||
title: 'SoybeanAdmin',
|
||||
title: 'Dolphin',
|
||||
updateTitle: 'System Version Update Notification',
|
||||
updateContent: 'A new version of the system has been detected. Do you want to refresh the page immediately?',
|
||||
updateConfirm: 'Refresh immediately',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const local: App.I18n.Schema = {
|
||||
system: {
|
||||
title: 'Soybean 管理系统',
|
||||
title: 'Dolphin 管理系统',
|
||||
updateTitle: '系统版本更新通知',
|
||||
updateContent: '检测到系统有新版本发布,是否立即刷新页面?',
|
||||
updateConfirm: '立即刷新',
|
||||
|
||||
@ -35,7 +35,7 @@ export function createRouteGuard(router: Router) {
|
||||
const needLogin = !to.meta.constant;
|
||||
const routeRoles = to.meta.roles || [];
|
||||
|
||||
const hasRole = authStore.userInfo.roles.some(role => routeRoles.includes(role));
|
||||
const hasRole = authStore.userInfo.authorities.some(role => routeRoles.includes(role));
|
||||
const hasAuth = authStore.isStaticSuper || !routeRoles.length || hasRole;
|
||||
|
||||
// if it is login route when logged in, then switch to the root page
|
||||
|
||||
@ -3,15 +3,15 @@ import { request } from '../request';
|
||||
/**
|
||||
* Login
|
||||
*
|
||||
* @param userName User name
|
||||
* @param username User name
|
||||
* @param password Password
|
||||
*/
|
||||
export function fetchLogin(userName: string, password: string) {
|
||||
export function fetchLogin(username: string, password: string) {
|
||||
return request<Api.Auth.LoginToken>({
|
||||
url: '/auth/login',
|
||||
method: 'post',
|
||||
data: {
|
||||
userName,
|
||||
username,
|
||||
password
|
||||
}
|
||||
});
|
||||
|
||||
@ -48,7 +48,7 @@ export const request = createFlatRequest(
|
||||
handleLogout();
|
||||
window.removeEventListener('beforeunload', handleLogout);
|
||||
|
||||
request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== response.data.msg);
|
||||
request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== response.data.message);
|
||||
}
|
||||
|
||||
// when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
|
||||
@ -60,15 +60,15 @@ export const request = createFlatRequest(
|
||||
|
||||
// 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(responseCode) && !request.state.errMsgStack?.includes(response.data.msg)) {
|
||||
request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg];
|
||||
if (modalLogoutCodes.includes(responseCode) && !request.state.errMsgStack?.includes(response.data.message)) {
|
||||
request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.message];
|
||||
|
||||
// prevent the user from refreshing the page
|
||||
window.addEventListener('beforeunload', handleLogout);
|
||||
|
||||
window.$dialog?.error({
|
||||
title: $t('common.error'),
|
||||
content: response.data.msg,
|
||||
content: response.data.message,
|
||||
positiveText: $t('common.confirm'),
|
||||
maskClosable: false,
|
||||
closeOnEsc: false,
|
||||
@ -106,7 +106,7 @@ export const request = createFlatRequest(
|
||||
|
||||
// get backend error message and code
|
||||
if (error.code === BACKEND_ERROR_CODE) {
|
||||
message = error.response?.data?.msg || message;
|
||||
message = error.response?.data?.message || message;
|
||||
backendErrorCode = String(error.response?.data?.code || '');
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ async function handleRefreshToken() {
|
||||
const rToken = localStg.get('refreshToken') || '';
|
||||
const { error, data } = await fetchRefreshToken(rToken);
|
||||
if (!error) {
|
||||
localStg.set('token', data.token);
|
||||
localStg.set('token', data?.accessToken);
|
||||
localStg.set('refreshToken', data.refreshToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -22,9 +22,9 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
const token = ref(getToken());
|
||||
|
||||
const userInfo: Api.Auth.UserInfo = reactive({
|
||||
userId: '',
|
||||
userName: '',
|
||||
roles: [],
|
||||
id: '',
|
||||
username: '',
|
||||
authorities: [],
|
||||
buttons: []
|
||||
});
|
||||
|
||||
@ -32,7 +32,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
const isStaticSuper = computed(() => {
|
||||
const { VITE_AUTH_ROUTE_MODE, VITE_STATIC_SUPER_ROLE } = import.meta.env;
|
||||
|
||||
return VITE_AUTH_ROUTE_MODE === 'static' && userInfo.roles.includes(VITE_STATIC_SUPER_ROLE);
|
||||
return VITE_AUTH_ROUTE_MODE === 'static' && userInfo.authorities.includes(VITE_STATIC_SUPER_ROLE);
|
||||
});
|
||||
|
||||
/** Is login */
|
||||
@ -56,12 +56,12 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
|
||||
/** Record the user ID of the previous login session Used to compare with the current user ID on next login */
|
||||
function recordUserId() {
|
||||
if (!userInfo.userId) {
|
||||
if (!userInfo.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Store current user ID locally for next login comparison
|
||||
localStg.set('lastLoginUserId', userInfo.userId);
|
||||
localStg.set('lastLoginUserId', userInfo.id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,14 +70,14 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
* @returns {boolean} Whether to clear all tabs
|
||||
*/
|
||||
function checkTabClear(): boolean {
|
||||
if (!userInfo.userId) {
|
||||
if (!userInfo.id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const lastLoginUserId = localStg.get('lastLoginUserId');
|
||||
|
||||
// Clear all tabs if current user is different from previous user
|
||||
if (!lastLoginUserId || lastLoginUserId !== userInfo.userId) {
|
||||
if (!lastLoginUserId || lastLoginUserId !== userInfo.id) {
|
||||
localStg.remove('globalTabs');
|
||||
tabStore.clearTabs();
|
||||
|
||||
@ -117,7 +117,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
|
||||
window.$notification?.success({
|
||||
title: $t('page.login.common.loginSuccess'),
|
||||
content: $t('page.login.common.welcomeBack', { userName: userInfo.userName }),
|
||||
content: $t('page.login.common.welcomeBack', { userName: userInfo.username }),
|
||||
duration: 4500
|
||||
});
|
||||
}
|
||||
@ -130,14 +130,14 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
|
||||
async function loginByToken(loginToken: Api.Auth.LoginToken) {
|
||||
// 1. stored in the localStorage, the later requests need it in headers
|
||||
localStg.set('token', loginToken.token);
|
||||
localStg.set('token', loginToken.accessToken);
|
||||
localStg.set('refreshToken', loginToken.refreshToken);
|
||||
|
||||
// 2. get user info
|
||||
const pass = await getUserInfo();
|
||||
|
||||
if (pass) {
|
||||
token.value = loginToken.token;
|
||||
token.value = loginToken.accessToken;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
/** Init auth route */
|
||||
async function initAuthRoute() {
|
||||
// check if user info is initialized
|
||||
if (!authStore.userInfo.userId) {
|
||||
if (!authStore.userInfo.id) {
|
||||
await authStore.initUserInfo();
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
if (authStore.isStaticSuper) {
|
||||
addAuthRoutes(staticAuthRoutes);
|
||||
} else {
|
||||
const filteredAuthRoutes = filterAuthRoutesByRoles(staticAuthRoutes, authStore.userInfo.roles);
|
||||
const filteredAuthRoutes = filterAuthRoutesByRoles(staticAuthRoutes, authStore.userInfo.authorities);
|
||||
|
||||
addAuthRoutes(filteredAuthRoutes);
|
||||
}
|
||||
|
||||
@ -73,8 +73,8 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
const watermarkContent = computed(() => {
|
||||
const { watermark } = settings.value;
|
||||
|
||||
if (watermark.enableUserName && authStore.userInfo.userName) {
|
||||
return authStore.userInfo.userName;
|
||||
if (watermark.enableUserName && authStore.userInfo.username) {
|
||||
return authStore.userInfo.username;
|
||||
}
|
||||
|
||||
if (watermark.enableTime) {
|
||||
|
||||
8
src/typings/api/auth.d.ts
vendored
8
src/typings/api/auth.d.ts
vendored
@ -6,14 +6,14 @@ declare namespace Api {
|
||||
*/
|
||||
namespace Auth {
|
||||
interface LoginToken {
|
||||
token: string;
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
userId: string;
|
||||
userName: string;
|
||||
roles: string[];
|
||||
id: string;
|
||||
username: string;
|
||||
authorities: string[];
|
||||
buttons: string[];
|
||||
}
|
||||
}
|
||||
|
||||
4
src/typings/app.d.ts
vendored
4
src/typings/app.d.ts
vendored
@ -628,9 +628,11 @@ declare namespace App {
|
||||
/** The backend service response code */
|
||||
code: string;
|
||||
/** The backend service response message */
|
||||
msg: string;
|
||||
message: string;
|
||||
/** The backend service response data */
|
||||
data: T;
|
||||
/** The backend service response timestamp */
|
||||
timestamp: number;
|
||||
};
|
||||
|
||||
/** The demo backend service response data */
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive } from 'vue';
|
||||
import { loginModuleRecord } from '@/constants/app';
|
||||
// import { loginModuleRecord } from '@/constants/app';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
@ -20,7 +20,7 @@ interface FormModel {
|
||||
}
|
||||
|
||||
const model: FormModel = reactive({
|
||||
userName: 'Soybean',
|
||||
userName: 'admin',
|
||||
password: '123456'
|
||||
});
|
||||
|
||||
@ -39,8 +39,10 @@ async function handleSubmit() {
|
||||
await authStore.login(model.userName, model.password);
|
||||
}
|
||||
|
||||
/*
|
||||
type AccountKey = 'super' | 'admin' | 'user';
|
||||
|
||||
|
||||
interface Account {
|
||||
key: AccountKey;
|
||||
label: string;
|
||||
@ -48,6 +50,7 @@ interface Account {
|
||||
password: string;
|
||||
}
|
||||
|
||||
|
||||
const accounts = computed<Account[]>(() => [
|
||||
{
|
||||
key: 'super',
|
||||
@ -68,10 +71,13 @@ const accounts = computed<Account[]>(() => [
|
||||
password: '123456'
|
||||
}
|
||||
]);
|
||||
*/
|
||||
|
||||
/*
|
||||
async function handleAccountLogin(account: Account) {
|
||||
await authStore.login(account.userName, account.password);
|
||||
}
|
||||
*/
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -97,6 +103,7 @@ async function handleAccountLogin(account: Account) {
|
||||
<NButton type="primary" size="large" round block :loading="authStore.loginLoading" @click="handleSubmit">
|
||||
{{ $t('common.confirm') }}
|
||||
</NButton>
|
||||
<!--
|
||||
<div class="flex-y-center justify-between gap-12px">
|
||||
<NButton class="flex-1" block @click="toggleLoginModule('code-login')">
|
||||
{{ $t(loginModuleRecord['code-login']) }}
|
||||
@ -111,6 +118,7 @@ async function handleAccountLogin(account: Account) {
|
||||
{{ item.label }}
|
||||
</NButton>
|
||||
</div>
|
||||
-->
|
||||
</NSpace>
|
||||
</NForm>
|
||||
</template>
|
||||
|
||||
@ -48,7 +48,7 @@ const statisticData = computed<StatisticData[]>(() => [
|
||||
</div>
|
||||
<div class="pl-12px">
|
||||
<h3 class="text-18px font-semibold">
|
||||
{{ $t('page.home.greeting', { userName: authStore.userInfo.userName }) }}
|
||||
{{ $t('page.home.greeting', { userName: authStore.userInfo.username }) }}
|
||||
</h3>
|
||||
<p class="text-#999 leading-30px">{{ $t('page.home.weatherDesc') }}</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user