✨ feat: 添加用户信息加载动画
This commit is contained in:
parent
233af2b1e3
commit
dbe6a3d632
2
components.d.ts
vendored
2
components.d.ts
vendored
@ -24,7 +24,7 @@ declare module 'vue' {
|
||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||
Game2048: typeof import('./src/components/Game2048.vue')['default']
|
||||
IconCsLock: typeof import('~icons/cs/lock')['default']
|
||||
IconEpAvatar: typeof import('~icons/ep/avatar')['default']
|
||||
IconEpLoading: typeof import('~icons/ep/loading')['default']
|
||||
IconEpUserFilled: typeof import('~icons/ep/user-filled')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
|
44
src/App.vue
44
src/App.vue
@ -3,25 +3,28 @@
|
||||
<el-header height="50px">
|
||||
<div class="title-container">社团展示系统</div>
|
||||
<div class="content">
|
||||
<div v-if="userStore.userInfo !== null" class="username">
|
||||
{{ userStore.userInfo.name }}
|
||||
</div>
|
||||
<el-dropdown v-if="userStore.userInfo !== null">
|
||||
<el-avatar :icon="userStore.userInfo.avatar || Avatar" :size="40"></el-avatar>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item :icon="CloseBold" @click="logout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-avatar
|
||||
v-else
|
||||
style="color: black; user-select: none; cursor: pointer"
|
||||
:size="40"
|
||||
@click="showLoginRegisterDialog = true"
|
||||
>
|
||||
登录
|
||||
</el-avatar>
|
||||
<template v-if="userStore.initialized">
|
||||
<div v-if="userStore.userInfo !== null" class="username">
|
||||
{{ userStore.userInfo.name }}
|
||||
</div>
|
||||
<el-dropdown v-if="userStore.userInfo !== null">
|
||||
<el-avatar :icon="userStore.userInfo.avatar || Avatar" :size="40"></el-avatar>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item :icon="CloseBold" @click="logout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-avatar
|
||||
v-else
|
||||
style="color: black; user-select: none; cursor: pointer"
|
||||
:size="40"
|
||||
@click="showLoginRegisterDialog = true"
|
||||
>
|
||||
登录
|
||||
</el-avatar>
|
||||
</template>
|
||||
<el-icon v-else class="is-loading"><icon-ep-loading /></el-icon>
|
||||
</div>
|
||||
</el-header>
|
||||
</el-container>
|
||||
@ -149,7 +152,7 @@ import { Avatar, CloseBold } from '@element-plus/icons-vue';
|
||||
import { AxiosError } from 'axios';
|
||||
import { type FormInstance, type FormRules, ElMessage } from 'element-plus';
|
||||
import { partial, pick } from 'lodash-es';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { onMounted, reactive, ref, watch, onBeforeMount } from 'vue';
|
||||
import { RouterView, useRoute, useRouter } from 'vue-router';
|
||||
import { z } from 'zod';
|
||||
const router = useRouter();
|
||||
@ -244,7 +247,6 @@ async function submitLoginForm() {
|
||||
succeed = await login();
|
||||
} finally {
|
||||
if (succeed) {
|
||||
// await timeout(1000);
|
||||
window.location.reload();
|
||||
} else {
|
||||
logining.value = false;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import axiosInstance from '@/api';
|
||||
import { userInfoResponseSchema, type Route } from '@/schemas';
|
||||
import { useUserStore } from '@/stores';
|
||||
import { errorMessage } from '@/utils';
|
||||
import { errorMessage, timeout } from '@/utils';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { type Component } from 'vue';
|
||||
import { createRouter, createWebHashHistory, type RouteRecordRaw } from 'vue-router';
|
||||
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/',
|
||||
@ -16,7 +16,7 @@ const routes: RouteRecordRaw[] = [
|
||||
}
|
||||
];
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
history: createWebHistory(),
|
||||
routes: routes
|
||||
});
|
||||
const componentMap: Record<string, () => Promise<Component>> = {
|
||||
@ -43,24 +43,29 @@ function getAvailableRoutes(routeResponse: Route[]) {
|
||||
}
|
||||
router.beforeEach(async (to) => {
|
||||
const userStore = useUserStore();
|
||||
console.log(userStore.userInfo);
|
||||
console.log(2, userStore.userInfo);
|
||||
// await timeout(1000);
|
||||
if (!userStore.isInitialized) {
|
||||
const userInfoResponse = userInfoResponseSchema.parse(
|
||||
(await axiosInstance.get('/api/user/info')).data
|
||||
);
|
||||
console.log(userInfoResponse);
|
||||
if (userInfoResponse.type === 'error') {
|
||||
ElMessage.error(
|
||||
errorMessage('获取用户信息失败', userInfoResponse.code, userInfoResponse.msg)
|
||||
console.log(userStore.initialized);
|
||||
if (!userStore.initialized) {
|
||||
try {
|
||||
const userInfoResponse = userInfoResponseSchema.parse(
|
||||
(await axiosInstance.get('/api/user/info')).data
|
||||
);
|
||||
return false;
|
||||
console.log(userInfoResponse);
|
||||
if (userInfoResponse.type === 'error') {
|
||||
ElMessage.error(
|
||||
errorMessage('获取用户信息失败', userInfoResponse.code, userInfoResponse.msg)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// 判断是否已登录.
|
||||
if (userStore.token !== null) {
|
||||
userStore.updateUserInfo(userInfoResponse);
|
||||
}
|
||||
getAvailableRoutes(userInfoResponse.data.auth.permissions[0].routers);
|
||||
} finally {
|
||||
userStore.initialized = true;
|
||||
}
|
||||
if (userStore.token !== null) {
|
||||
userStore.updateUserInfo(userInfoResponse);
|
||||
}
|
||||
getAvailableRoutes(userInfoResponse.data.auth.permissions[0].routers);
|
||||
userStore.isInitialized = true;
|
||||
}
|
||||
if (userStore.addedRouteSet.has(to.fullPath) || to.fullPath === '/404') {
|
||||
return true;
|
||||
|
@ -8,10 +8,10 @@ import { z } from 'zod';
|
||||
type SucceedUserInfoResponse = SucceedResponse<z.infer<typeof userInfoResponseSchema>>;
|
||||
type UserInfo = Pick<SucceedUserInfoResponse['data'], 'id' | 'name' | 'avatar'>;
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const token = useLocalStorage<string>('token', null, {
|
||||
const token = useLocalStorage<string | null>('token', null, {
|
||||
serializer: StorageSerializers.string
|
||||
});
|
||||
const userInfo = useLocalStorage<UserInfo>('user-info', null, {
|
||||
const userInfo = useLocalStorage<UserInfo | null>('user-info', null, {
|
||||
serializer: StorageSerializers.object
|
||||
});
|
||||
const routeMap = reactive(new Map<string, RouteRecordRaw>());
|
||||
@ -27,5 +27,5 @@ export const useUserStore = defineStore('user', () => {
|
||||
addedRouteSet.clear();
|
||||
isInitialized.value = false;
|
||||
}
|
||||
return { token, userInfo, routeMap, addedRouteSet, isInitialized, updateUserInfo, $reset };
|
||||
return { token, userInfo, routeMap, addedRouteSet, initialized: isInitialized, updateUserInfo, $reset };
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user