第一次登录后首页空白

解决:第一次登录,动态添加路由规则
ts
import {
createRouter,
createWebHashHistory,
type RouteRecordRaw
} from 'vue-router'
import { type App } from 'vue'
import store from '../store'
import Cookie from 'js-cookie'
const routes: RouteRecordRaw[] = [
{
path: '/login',
name: 'login',
component: () => import('../views/login/login.vue')
},
// {
// path: '/home',
// name: 'home',
// component: () => import('../views/home/home.vue')
// },
// 动态生成的路由配置结构需要如下
// {
// path: '/pms',
// name: 'pms',
// component: () => import('../views/home/home.vue'),
// children: [
// {
// path: 'product',
// name: 'product',
// component: () => import('../views/pms/product.vue'),
// }
// ]
// }
]
const router = createRouter({
history: createWebHashHistory(),
routes // 路由配置
})
// 根据 getters 里面的菜单生成路由规则
const genRoutes = () => {
const menus = store.getters.getNewMenus;
console.log('menus--->', menus)
// const newRoutes:RouteRecordRaw[] = []
// 循环菜单对象
for(let key in menus) {
const newRoute: RouteRecordRaw = {
path: `/${menus[key].name}`,
name: menus[key].name,
component: () => import(`../views/home/home.vue`),
redirect: `/${menus[key].name}/${menus[key].children[0].name}`,
children: []
}
for(let i = 0; i < menus[key].children.length; i++) {
newRoute.children?.push({
path: menus[key].children[i].name,
name: menus[key].children[i].name,
component: () => import(`../views/${menus[key].name}/${menus[key].children[i].name}.vue`),
})
}
// 动态添加路由规则
router.addRoute(newRoute)
}
// 动态添加首页
router.addRoute({
path: "/",
name: "home",
component: () => import(`../views/home/home.vue`),
redirect: '/index', // 访问 / 跳转到 /index 然后匹配上 index.vue
children: [{
path: "index",
name: "index",
component: () => import(`../views/index/index.vue`),
}]
})
console.log('routes--->', routes)
}
// 前置导航守卫
router.beforeEach((to, from, next) => {
// 1、token && vuex里面的 menus 为空
const token = Cookie.get('token')
console.log(store)
if(token && store.state.menus.length === 0) {
console.log('menus为空')
// 获取用户信息
store.dispatch('getAdminInfoApi').then(() => {
genRoutes()
// 路由规则没有刷新,需要再次next进入路由守卫
next(to)
})
} else if(token && store.state.menus.length !== 0 && to.path === '/temp' && from.path === '/login') {
// 第一次登录,动态添加路由规则 to.path === '/index' 要改成其他路由 /temp 避免登录进来进入 index 直接死循环
genRoutes()
// 路由规则没有刷新,需要再次next进入路由守卫
next('/index')
} else {
next()
}
})
export const initRouter = (app: App<Element>) => {
app.use(router)
}
html
<template>
<div class="login-rule-form">
<div class="content">
<div class="title">商品管理系统</div>
<el-form ref="ruleFormRef" :model="ruleForm" status-icon :rules="rules" label-width="60px">
<el-form-item prop="username" label="账号">
<el-input v-model="ruleForm.username" type="text" placeholder="请输入账号"/>
</el-form-item>
<el-form-item prop="pwd" label="密码">
<el-input v-model="ruleForm.pwd" type="password" placeholder="请输入密码"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loginFn()">登录</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script lang='ts' setup>
import { onMounted, reactive, ref } from 'vue'
import { adminLoginApi } from '@/api/login'
import Cookie from 'js-cookie'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'
let ruleForm = reactive({
username: "",
pwd: ""
})
// 自定义密码校验规则(_variable - 未使用的变量 ts不校验)
const validatePwd = (_rule: unknown, value: string | undefined, callback: (msg?: string) => void) => {
if(!value) {
callback('密码不能为空')
} else {
callback()
}
}
// 校验规则
let rules = reactive({
username: [
{
required: true,
message: '用户名不能为空',
trigger: 'blur'
}
],
pwd: [
{
required: true,
validator: validatePwd,
trigger: 'blur'
}
]
})
// 获取el-form组件对象
let ruleFormRef = ref()
// 获取项目路由对象
let router = useRouter()
// 获取当前项目的vuex对象
let store = useStore()
onMounted(() => {
// console.log('组件实例:', ruleFormRef.value)
// console.log('DOM 元素:', ruleFormRef.value?.$el)
})
// 点击登录
const loginFn = () => {
ruleFormRef.value.validate().then(() => {
adminLoginApi({
username: ruleForm.username,
password: ruleForm.pwd
}).then((res) => {
if(res.code === 200) {
// 储存cookie
Cookie.set('token', res.data.token, { expires: 7 })
ElMessage.success('登录成功')
// 获取用户信息
store.dispatch('getAdminInfoApi').then(res => {
// 跳转首页的时候先跳转一个临时路由 /temp 去生成路由规则,然后在路由守卫里在去跳转 /index
router.push('/temp')
})
} else {
ElMessage.error('登录报错')
}
})
}).catch(() => {
console.log('校验不通过')
})
}
</script>
<style lang='less' scoped>
.login-rule-form {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
overflow: hidden;
box-sizing: border-box;
margin: 0;
padding: 0;
.content {
width: 420px;
padding: 40px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
box-sizing: border-box;
.title {
font-size: 28px;
font-weight: bold;
text-align: center;
margin-bottom: 30px;
}
}
:deep(.el-form) {
.el-form-item {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
}
.el-button {
width: 100%;
}
}
}
</style>