后端Java代码?
src\router\a6router.ts文件
import { createRouter, createWebHashHistory } from 'vue-router'
import { useStorage } from '@vueuse/core'
import { Menu, Route } from '../model/Model8080'
const clientRoutes = [
{
path: '/login',
name: 'login',
component: () => import('../views/A6Login.vue')
},
{
path: '/404',
name: '404',
component: () => import('../views/A6NotFound.vue')
}, {
path: '/',
name: 'main',
component: () => import('../views/A6Main.vue')
}, {
path: '/:pathMatcher(.*)*',
name: 'remaining',
redirect: '/404'
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: clientRoutes
})
//在每次路由跳转之前都会执行beforeEach里面的箭头函数,to代表要跳转的目标路由对象,from代表源路由对象
router.beforeEach((to,from)=>{
if(to.name ==='main' && !serverToken.value){
return '/login'
}
})
//修改页面标题
router.afterEach((to,from)=>{
document.title = to.name?.toString() || ''
})
const serverRoutes = useStorage<Route[]>('serverRoutes', [])
export const serverMenus = useStorage<Menu[]>('serverMenus',[])
//把从后端返回的token中的用户名存储起来
export const serverUsername = useStorage<string>('serverUsername','')
//把从后端返回的token存储起来
export const serverToken = useStorage<string>('serverToken','')
addServerRoutes(serverRoutes.value)
export function addServerRoutes(routeList: Route[]) {
for (const r of routeList) {
// r.parentName:是加入的路由的父路由,是addRoute()需要的参数
router.addRoute(r.parentName, {
path: r.path,
name: r.name,
component: () => import(r.component)
})
}
serverRoutes.value = routeList
}
export function resetRoutes() {
for (const r of clientRoutes) {
router.addRoute(r)
}
serverRoutes.value= null
serverMenus.value = null
serverToken.value = null
serverUsername.value = null
}
export default router
src\views\A6Login.vue文件
<template>
<div class="login">
<a-form :label-col="{ span: 6 }" autocomplete="off">
<a-form-item label="用户名" v-bind="validateInfos.username">
<a-input v-model:value="dto.username" />
</a-form-item>
<a-form-item label="密码" v-bind="validateInfos.password">
<a-input-password v-model:value="dto.password" />
</a-form-item>
<a-form-item :wrapper-col="{ offset: 6, span: 16 }">
<a-button type="primary" @click="onClick">登录</a-button>
</a-form-item>
</a-form>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref} from 'vue'
import { Form } from 'ant-design-vue'
import { addServerRoutes ,resetRoutes,serverMenus,serverToken,serverUsername} from '../router/a6router'
import _axios from '../api/request'
import { useRequest } from 'vue-request'
import { AxiosRespToken, LoginDto, AxiosRespMenuAndRoute } from '../model/Model8080'
import { useRouter } from 'vue-router'
const router = useRouter()
const dto = ref({ username: '', password: '' })
const rules = ref({
username: [
{ required: true, message: '用户名必填' }
],
password: [
{ required: true, message: '密码必填' }
]
})
const { validateInfos, validate } = Form.useForm(dto, rules)
const { runAsync: login } = useRequest<AxiosRespToken, LoginDto[]>((dto) => _axios.post('/api/loginJwt', dto), { manual: true })
const { runAsync: menu } = useRequest<AxiosRespMenuAndRoute, string[]>((username) => _axios.get(`/api/menu/${username}`), { manual: true })
async function onClick() {
try {
await validate()
const loginResp = await login(dto.value)
if (loginResp.data.code === 200) {
resetRoutes()
const token = loginResp.data.data.token
console.log(token)
serverToken.value= token
serverUsername.value = getUsername(token)
const menuResp = await menu(serverUsername.value)
serverMenus.value =menuResp.data.data.menuTree
console.log(menuResp.data.data.routeList)
addServerRoutes(menuResp.data.data.routeList)
router.push('/')
}
} catch (error) {
console.error(error)
}
}
function getUsername(token:string){
if(!token){
return ''
}
const s = token.split('.')
return JSON.parse(atob(s[1])).sub
}
onMounted(()=>{
resetRoutes()
})
</script>
<style scoped>
.login {
margin: 200px auto;
width: 300px;
padding: 20px;
height: 180px;
background-color: antiquewhite;
}
</style>
src\views\A6Main.vue文件
<template>
<div class="a6main">
<a-layout>
<a-layout-header>
<span>{{ serverUsername }} 【{{ UserInfo.name }} -{{ UserInfo.sex }}】</span>
</a-layout-header>
<a-layout>
<a-layout-sider>
<a-menu theme="dark" mode="inline">
<template v-for="m1 of serverMenus">
<a-sub-menu v-if="m1.children" :key="m1.id" :title="m1.title">
<template #icon><a-icon :icon="m1.icon"></a-icon></template>
<a-menu-item v-for="m2 of m1.children" :key="m2.id">
<template #icon> <a-icon :icon="m2.icon"></a-icon> </template>
<router-link v-if="m2.routePath" :to="m2.routePath">{{ m2.title }}</router-link>
<span v-else>{{ m2.title }}</span>
</a-menu-item>
</a-sub-menu>
<a-menu-item v-else :key="m1.id">
<template #icon> <a-icon :icon="m1.icon"></a-icon></template>
<router-link v-if="m1.routePath" :to="m1.routePath">{{ m1.title }}</router-link>
<span v-else>{{ m1.title }}</span>
</a-menu-item>
</template>
</a-menu>
</a-layout-sider>
<a-layout-content>
<router-view></router-view>
</a-layout-content>
</a-layout>
</a-layout>
</div>
</template>
<script setup lang="ts">
import { serverMenus,serverUsername } from '../router/a6router'
import AIcon from '../components/AIcon3';
import {useUserInfo} from '../store/UserInfo'
import { onMounted } from 'vue';
const UserInfo = useUserInfo()
onMounted(()=>{
UserInfo.get(serverUsername.value)
})
</script>
<style scoped>
.a6main {
height: 100%;
background-color: rgb(220, 225, 255);
box-sizing: border-box;
}
.ant-layout-header {
height: 50px;
background-color: gold;
border-bottom: 1px solid black;
padding: 0 25px 0 0;
line-height: 50px;
text-align: right;
}
.ant-layout-sider {
background-color: gold;
border-right: 1px solid black;
}
.ant-layout-content {
background-color: gold;
}
.ant-layout-footer {
background-color: darkslateblue;
height: 30px;
}
.ant-layout {
height: 100%;
}
.ant-layout-has-sider {
height: calc(100% - 50px);
}
</style>