在前面项目的基础上继续,因为我们的项目进来页面主题就是用户数据,所以我们想让它一进来就是高亮状态,那么我们可以这样做,同时我们再加上一个菜单:
<template>
<div>
<el-menu
style="width: 200px; min-height: calc(100vh - 50px)"
default-active="user"
:default-openeds="[1]"
class="el-menu-vertical-demo">
<!--这是两个函数,我们可以先不写@open="handleOpen"-->
<!--@close="handleClose"-->
<el-sub-menu index="1">
<template #title>系统管理</template>
<el-menu-item index="user" :route-="{path:'/'}">用户管理</el-menu-item>
</el-sub-menu>
<el-menu-item index="data" :route-="{path:'/'}">数据管理</el-menu-item>
</el-menu>
</div>
</template>
<script>
export default {
name: "Aside"
}
</script>
<style scoped>
</style>
访问效果如下:
可以看到一进来因为页面主体是用户管理界面,所以“用户管理”菜单栏是默认高亮的,然后还多了一个数据管理的菜单栏。
菜单之间怎么跳转一会儿再讲,我们现在先写注册和登录。
在写注册和登录之前,我们先讲一下路由,可以看到我们这个路由文件下的文件中,默认的“/”访问的是Home文件:
Home页面写的就是我们这个用户表的增删改查,然后Home页面呢是在我们的App.vue中给它嵌入进去了的,
首先我们尝试一下可不可以直接在路由文件下写上一个Login路由,同时我们在views页面下创建一个Login.vue,看看能不能成功:
注意引入路由的写法要特别注意,不能直接像下面这样写:
而应该用引入的方式;
现在我们重启访问/login:
成功;
但是同时我们也看到了问题,我们明明是登录界面,为什么进到了后台主页了,而我们想要的登录界面应该是一个非常独立的界面,所以我们的这个路由是有问题的。因为我们之前是直接使用App.vue作为项目的框架,其实这个App.vue在我们的main.js里面是引入进来了的:
引进来之后呢直接作为createApp的根节点来使用,所以这个App.vue这个界面呢,不适合用来作为我们的这个后台骨架来使用:
它应该是一个全局的根节点,所以我们需要把App.vue里面的东西把它给挪走,挪到另一个界面,我们要把App.vue呢给它空出来,让App.vue可以直接访问我们所有的界面。
怎么做呢?
我们在src目录下新建一个layout文件夹,这个文件夹呢就用来做我们项目的骨架部分,再在这个文件下建一个Layout组件:
然后把之前在App.vue的东西copy过来:
然后Header啊Aside啊那些组件我们需要在这个组件里面进行引入,然后App里面的那些原来引入的就删掉就行了:
然后现在我们就完成了迁移,现在我们要去配置一下我们的路由,实现我们后台的一个访问。
路由怎么配置呢?非常简单。
我们来讲解一下刚才这个什么意思,App.vue里面我们只写了一个router-view,而这个router-view呢就作为我们这个全局的一个根节点访问,
这个router-view里面既可以是登录界面也可以是注册界面也可以是后台主体,就是根据它是路由进行一个展示。当我们访问到我们的后台主体的时候,会进行一个二次的嵌套路由,那这个嵌套路由怎么写呢?我们先配置登录页面的路由和后台管理布局的路由:
但是访问/时,Home主体页面并没有出来,只出来了/对应的页面骨架的路由,怎么让这个Home主体页面出来呢,这就涉及到了嵌套路由,像下面这样写,children属性是一个数组属性,意味着其可以嵌套多个路由:
访问/下的home路由,可以看到如下页面:
vue-router给我们提供了重定向属性,可以让我们在访问某个路由页面时自动重定向到一个我们指定的路由页面:
现在我们直接访问/试试,可以看到依然是访问的home页面:
现在路由问题解决之后我们就可以去写我们的登录页面了。
<template>
<!--将整个浏览器页面放在一个大div里
width: 100%表示这个让div撑满全屏
height: 100vh同上,一个撑满高度一个撑满宽度-->
<div style="width: 100%; height: 100vh;background: darkslateblue; overflow: hidden">
<!--margin: 参数1 参数2; 参数1表示上下距离,参数2表示左右距离,auto表示自动匹配
如果页面产生了空白,就在外层最大的div上加一个overflow,设置为hidden即可-->
<div style="width: 400px; margin: 150px auto">
<!--font-size表示字体大小,text-align表示字体居中-->
<div style="color: #cccccc; font-size: 30px; text-align: center; padding: 30px 0">
欢迎登录
</div>
<!--然后去element上copy一个表单-->
<el-form ref="form" :model="form" size="normal">
<el-form-item>
<el-input prefix-icon="el-icon-user-solid" v-model="form.username"></el-input>
</el-form-item>
</el-form>
<el-form ref="form" :model="form" size="normal">
<el-form-item>
<el-input prefix-icon="el-icon-lock" v-model="form.password" show-password></el-input>
</el-form-item>
</el-form>
<el-form ref="form" :model="form" size="normal">
<el-button style="width: 100%" type="primary" @click="login">登录</el-button>
</el-form>
</div>
</div>
</template>
<script>
import request from "../utils/request";
export default {
name: "Login",
data(){
return{
form:{
}
}
},
methods: {
login() {
request.post("/api/user/login",this.form).then(res => {
if(res.code === "0"){
this.$messageBox({
type: "success",
message: "登录成功"
})
// 登录成功之后进行页面跳转,跳转到主页
this.$router.push("/")
}else{
this.$messageBox({
type: "error",
message: res.msg
})
}
})
}
}
}
</script>
<style scoped>
</style>
然后现在去写我们后端的接口:
//用户登录
@PostMapping("/login")
public Result login(@RequestBody User user){
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()).eq(User::getPassword,user.getPassword()));
if(res != null){
//登录成功
return Result.success();
}else{
//登录失败
return Result.error("-1","用户名或密码错误");
}
}
现在数据库中的数据有:
我们试着访问登录:
可以看到登录成功:
然后我们再去我们的网页头部右侧的用户信息栏写一下退出系统的操作:
点击则路由跳转到登录页面。
然后还有注册页面,也一起写了,注册页面其实逻辑和登录界面差不多,我们copy一个登录组件进行更改即可。
然后进行更改就行了,注册不过就比登录多了一个确认密码的操作。
<template>
<!--将整个浏览器页面放在一个大div里
width: 100%表示这个让div撑满全屏
height: 100vh同上,一个撑满高度一个撑满宽度-->
<div style="width: 100%; height: 100vh;background: darkslateblue; overflow: hidden">
<!--margin: 参数1 参数2; 参数1表示上下距离,参数2表示左右距离,auto表示自动匹配
如果页面产生了空白,就在外层最大的div上加一个overflow,设置为hidden即可-->
<div style="width: 400px; margin: 150px auto">
<!--font-size表示字体大小,text-align表示字体居中-->
<div style="color: #cccccc; font-size: 30px; text-align: center; padding: 30px 0">
欢迎登录
</div>
<!--然后去element上copy一个表单-->
<el-form ref="form" :model="form" size="normal" :rules="rules">
<el-form-item prop="username">
<el-input prefix-icon="el-icon-user-solid" v-model="form.username"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input prefix-icon="el-icon-lock" v-model="form.password" show-password></el-input>
</el-form-item>
</el-form>
<el-form ref="form" :model="form" size="normal">
<el-button style="width: 100%" type="primary" @click="login">登录</el-button>
</el-form>
</div>
</div>
</template>
<script>
import request from "../utils/request";
export default {
name: "Login",
data(){
return{
form:{
},
rules:{
username:[
{
required: true,message:"请输入用户名",trigger:'blur'},
],
password:[
{
required: true,message:"请输入密码",trigger:'blur'},
]
}
}
},
methods: {
login() {
//发送请求之前先加这个判断,不为空且满足规则时才发送请求
this.$refs['form'].validate((valid) => {
if (valid) {
request.post("/api/user/login",this.form).then(res => {
if(res.code === "0"){
this.$messageBox({
type: "success",
message: "登录成功"
})
// 登录成功之后进行页面跳转,跳转到主页
this.$router.push("/")
}else{
this.$messageBox({
type: "error",
message: res.msg
})
}
})
}
})
}
}
}
</script>
<style scoped>
</style>
其中我们还要注意在请求数据之前要先判断表单内部是否数据符合要求,否则不予请求,同样在Login页面内也要加入该判断:
<template>
<!--将整个浏览器页面放在一个大div里
width: 100%表示这个让div撑满全屏
height: 100vh同上,一个撑满高度一个撑满宽度-->
<div style="width: 100%; height: 100vh;background: darkslateblue; overflow: hidden">
<!--margin: 参数1 参数2; 参数1表示上下距离,参数2表示左右距离,auto表示自动匹配
如果页面产生了空白,就在外层最大的div上加一个overflow,设置为hidden即可-->
<div style="width: 400px; margin: 150px auto">
<!--font-size表示字体大小,text-align表示字体居中-->
<div style="color: #cccccc; font-size: 30px; text-align: center; padding: 30px 0">
欢迎登录
</div>
<!--然后去element上copy一个表单-->
<el-form ref="form" :model="form" size="normal" :rules="rules">
<el-form-item prop="username">
<el-input prefix-icon="el-icon-user-solid" v-model="form.username"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input prefix-icon="el-icon-lock" v-model="form.password" show-password></el-input>
</el-form-item>
</el-form>
<el-form ref="form" :model="form" size="normal">
<el-button style="width: 100%" type="primary" @click="login">登录</el-button>
</el-form>
</div>
</div>
</template>
<script>
import request from "../utils/request";
export default {
name: "Login",
data(){
return{
form:{
},
rules:{
username:[
{
required: true,message:"请输入用户名",trigger:'blur'},
],
password:[
{
required: true,message:"请输入密码",trigger:'blur'},
]
}
}
},
methods: {
login() {
//发送请求之前先加这个判断,不为空且满足规则时才发送请求
this.$refs['form'].validate((valid) => {
if (valid) {
request.post("/api/user/login",this.form).then(res => {
if(res.code === "0"){
this.$messageBox({
type: "success",
message: "登录成功"
})
// 登录成功之后进行页面跳转,跳转到主页
this.$router.push("/")
}else{
this.$messageBox({
type: "error",
message: res.msg
})
}
})
}
})
}
}
}
</script>
<style scoped>
</style>
然后现在去后端写register的接口:
//用户注册
@PostMapping("/register")
public Result register(@RequestBody User user){
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()));
if(res != null){
//说明用户名重复
return Result.success();
}
//该用户不存在,予以注册
if(user.getPassword() == null){
user.setPassword("123456");
}
userMapper.insert(user);
return Result.success();
}
就此我们的注册页面也写完啦。