fix: 修复用户未登录相关的导航栏显示问题

1、修复用户未登录不显示导航栏
2、修复用户未登录也会发送请求
3、用户未登录时只显示部分导航栏
This commit is contained in:
huertian 2025-01-09 17:51:16 +08:00
parent 230fab5017
commit 33c5b343a7
9 changed files with 85 additions and 25 deletions

View File

@ -4,10 +4,14 @@ import { useTabbar } from "./stores/useTabbar";
import BussApi from "./api/BussApi"; import BussApi from "./api/BussApi";
import { useUser } from "./stores/useUser"; import { useUser } from "./stores/useUser";
import { useToast } from "wot-design-uni"; import { useToast } from "wot-design-uni";
import { useRoute } from "uni-mini-router";
import { useRouter } from "uni-mini-router";
const tab = useTabbar() const tab = useTabbar()
const user = useUser() const user = useUser()
const toast = useToast() const toast = useToast()
const route = useRoute()
const router = useRouter()
onLaunch(() => { onLaunch(() => {
console.debug("App Launch"); console.debug("App Launch");
@ -15,12 +19,21 @@ onLaunch(() => {
// reset tabbar // reset tabbar
tab.activeTab = 'home' tab.activeTab = 'home'
// refersh user info // refresh user info if token exists
if (user.hasValidToken()) {
toast.loading({ msg: '加载用户信息...' })
BussApi.profile(user.token!).then(res => { BussApi.profile(user.token!).then(res => {
user.userinfo = res user.userinfo = res
toast.close()
}).catch(err => { }).catch(err => {
toast.error({ msg: err.message }) user.setToken(null) // clear invalid token
toast.error({ msg: '登录已过期,请重新登录' })
//
if (!['home', 'my'].includes(route.name!)) {
router.pushTab({ name: 'home' })
}
}) })
}
}); });
onShow(() => { onShow(() => {

View File

@ -27,16 +27,27 @@ export default class BussApi {
* *
* @param token - token * @param token - token
* @returns Promise<User> * @returns Promise<User>
* @throws Error token
*/ */
static profile(token: string): Promise<User> { static profile(token: string): Promise<User> {
if (!token || token.trim().length === 0) {
return Promise.reject(new Error('Token is required'));
}
return http return http
.server() .server()
.get("users/current", { .get("users/current", {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token.trim()}`,
}, },
}) })
.then((res) => res.data.data); .then((res) => res.data.data)
.catch((error) => {
if (error.response?.status === 401) {
throw new Error('Token is invalid or expired');
}
throw error;
});
} }
/** /**

View File

@ -47,21 +47,31 @@ const nameLabelIconMap = {
} }
const tabList = computed(() => { const tabList = computed(() => {
// //
if (!user.userinfo) {
return router.routes
.filter((r: { name: string }) => ['home', 'my'].includes(r.name))
.map((route: { name: keyof typeof nameLabelIconMap }) => ({
name: route.name,
title: nameLabelIconMap[route.name]?.title,
icon: nameLabelIconMap[route.name]?.icon
}));
}
//
return router.routes return router.routes
.filter((r: { name: string }) => { .filter((r: { name: string }) => {
const config = nameLabelIconMap[r.name as keyof typeof nameLabelIconMap] const config = nameLabelIconMap[r.name as keyof typeof nameLabelIconMap]
// 访 // 访
return config && config.roles.some(role => user.hasRole(role as "teacher" | "admin" | "liaison" | "sysadmin")) return config && config.roles.some(role => user.hasRole(role as "teacher" | "admin" | "liaison" | "sysadmin"))
}) })
.map((route: { name: keyof typeof nameLabelIconMap }) => { .map((route: { name: keyof typeof nameLabelIconMap }) => ({
return {
name: route.name, name: route.name,
title: nameLabelIconMap[route.name]?.title, title: nameLabelIconMap[route.name]?.title,
icon: nameLabelIconMap[route.name]?.icon icon: nameLabelIconMap[route.name]?.icon
} }));
})
}) })
</script> </script>
<template> <template>

View File

@ -2,7 +2,8 @@ import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
export const useConfig = defineStore('config', () => { export const useConfig = defineStore('config', () => {
const BASE_URL = ref<string>("http://service5.fenshenzhike.com:1218/api/users/login"); const BASE_URL = ref<string>("http://service5.fenshenzhike.com:1218/api/");
// const BASE_URL = ref<string>("http://localhost:1218/api/");
return { return {
BASE_URL BASE_URL
} }

View File

@ -75,13 +75,12 @@ const openLessonDetail = (courseId: number) => {
const loadLessons = async () => { const loadLessons = async () => {
if (!user.userinfo) { if (!user.hasValidToken() || !user.userinfo) {
toast.error({ msg: '请先登录' }) toast.error({ msg: '请先登录' })
router.replace('/pages/login/index')
return return
} }
toast.loading({ msg: '加载中...' }) toast.loading({ msg: '加载中...' })
try { try {
let res; let res;

View File

@ -36,11 +36,11 @@ const handleSubmit = () => {
password: model.password, password: model.password,
remember: model.remember remember: model.remember
}).then(res => { }).then(res => {
user.token = res.token user.setToken(res.token)
toast.loading({ toast.loading({
msg: '加载资料...' msg: '加载资料...'
}) })
BussApi.profile(user.token).then(res => { BussApi.profile(res.token).then(res => {
user.userinfo = res user.userinfo = res
toast.success({ msg: '登录成功' }) toast.success({ msg: '登录成功' })
setTimeout(() => { setTimeout(() => {

View File

@ -14,13 +14,19 @@ const toast = useToast()
const user = useUser() const user = useUser()
const userInfo = ref<User | null>(null) const userInfo = ref<User | null>(null)
const loadUserInfo = async () => { async function loadUserInfo() {
try { try {
if (!user.hasValidToken() || !user.userinfo) {
toast.error({ msg: '请先登录' })
router.replace('/pages/login/index')
return
}
toast.loading({ toast.loading({
msg: '加载中...' msg: '加载中...'
}) })
const res = await BussApi.profile(user.token!) const res = await BussApi.profile(user.token!)
toast.close() toast.close()
console.log(res)
user.userinfo = res user.userinfo = res
userInfo.value = res userInfo.value = res
} catch (error: any) { } catch (error: any) {

View File

@ -10,7 +10,9 @@ import { useRoute } from 'uni-mini-router';
import { useUser } from '@/stores/useUser'; import { useUser } from '@/stores/useUser';
import { useTabbar } from '@/stores/useTabbar' import { useTabbar } from '@/stores/useTabbar'
import { onPullDownRefresh } from '@dcloudio/uni-app' import { onPullDownRefresh } from '@dcloudio/uni-app'
import { useRouter } from 'uni-mini-router';
const router = useRouter()
const route = useRoute() const route = useRoute()
const message = useMessage() const message = useMessage()
const message_reject = useMessage('wd-message-box-slot') const message_reject = useMessage('wd-message-box-slot')
@ -304,8 +306,9 @@ const onStep4 = (rejected: boolean = false) => {
const updateLessons = async () => { const updateLessons = async () => {
adviseTextValue.value = "" adviseTextValue.value = ""
if (!user.userinfo) { if (!user.hasValidToken() || !user.userinfo) {
toast.error({ msg: '请先登录' }) toast.error({ msg: '请先登录' })
router.replace('/pages/login/index')
return return
} }

View File

@ -3,7 +3,7 @@ import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
export const useUser = defineStore("user", () => { export const useUser = defineStore("user", () => {
const token = ref<string | null>(null); const token = ref<string | null>(uni.getStorageSync('token') || null);
const userinfo = ref<User | null>(null); const userinfo = ref<User | null>(null);
/** /**
@ -74,6 +74,21 @@ export const useUser = defineStore("user", () => {
return false; return false;
} }
// 设置 token 并持久化
function setToken(newToken: string | null) {
token.value = newToken;
if (newToken) {
uni.setStorageSync('token', newToken);
} else {
uni.removeStorageSync('token');
}
}
// 检查 token 是否有效
function hasValidToken(): boolean {
return !!token.value && token.value.length > 0;
}
function logout() { function logout() {
token.value = null; token.value = null;
userinfo.value = null; userinfo.value = null;
@ -87,5 +102,7 @@ export const useUser = defineStore("user", () => {
canViewAllCourses, canViewAllCourses,
canEditCourse, canEditCourse,
logout, logout,
setToken,
hasValidToken
}; };
}); });