【学生管理系统】用户管理之用户登录
目录
2. 用户管理
2.1 环境搭建
2.1.1 前端环境
-
编写默认布局
-
编写自定义登陆布局
-
编写登录页面,使用登录布局
-
编写默认布局
![]()
-
编写自定义登陆布局
![]()
<template> <nuxt/> </template> <script> export default { } </script> <style> </style> -
编写登录页面,使用登录布局
![]()
<template> <div> 登录 </div> </template> <script> export default { layout: 'user' } </script> <style> </style>
2.1.2 后端环境(9000)
-
项目名:nacos-nuxt-student-service-user
-
pom文件
<dependencies> <!--web起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- nacos 客户端 --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> </dependency> <!-- nacos 服务发现 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--swagger2--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> </dependency> <!-- feign 远程调用 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- mybatis plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--自定义项目--> <dependency> <groupId>com.czxy</groupId> <artifactId>nacos-nuxt-student-domain</artifactId> </dependency> <!-- redis 启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- JavaMail 启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <!-- MQ 启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <!--开发者工具--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!--jwt工具--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> </dependency> <!--joda 时间工具类 --> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> </dependency> <!--JavaBean工具类,用于JavaBean数据封装--> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> </dependency> </dependencies>
-
yml文件
# 服务端口号 server: port: 9000 # 服务名 spring: application: name: user-service datasource: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/cloud_es_user?useUnicode=true&characterEncoding=utf8 username: root password: 1234 druid: #druid 连接池配置 initial-size: 1 #初始化连接池大小 min-idle: 1 #最小连接数 max-active: 20 #最大连接数 test-on-borrow: true #获取连接时候验证,会影响性能 cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #nacos服务地址 #开启log4j打印SQL语句 logging: level: com: czxy: user: mapper: debug # mp日志打印 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-value: 1 logic-not-delete-value: 0 sc: jwt: secret: sc@Login(Auth}*^31)&czxy% # 登录校验的密钥 pubKeyPath: D:/rsa/rsa.pub # 公钥地址 priKeyPath: D:/rsa/rsa.pri # 私钥地址 expire: 360 # 过期时间,单位分钟
-
启动类
package com.czxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @SpringBootApplication //spring boot @EnableDiscoveryClient //服务发现 @EnableFeignClients //远程调用 public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } } -
拷贝config
![]()
-
基本结构:mapper、service、controller
![]()
package com.czxy.user.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.czxy.domain.TbUser; import org.apache.ibatis.annotations.Mapper; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @Mapper public interface TbUserMapper extends BaseMapper<TbUser> { } package com.czxy.user.service; import com.baomidou.mybatisplus.extension.service.IService; import com.czxy.domain.TbUser; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ public interface TbUserService extends IService<TbUser> { } package com.czxy.user.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.czxy.domain.TbUser; import com.czxy.user.mapper.TbUserMapper; import com.czxy.user.service.TbUserService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @Service @Transactional public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser> implements TbUserService { } package com.czxy.user.controller; import com.czxy.user.service.TbUserService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @RestController @RequestMapping("/user") public class TbUserController { @Resource private TbUserService tbUserService; }
2.2 用户登录
2.2.1 需求
-
基本校验:非空、长度
![]()
-
异步校验:

-
登录成功后,跳转到首页
2.2.2 后端实现
1)用户名校验
-
需求:用户名不存在不能登录、用户存在可以登录
-
编写service
-
编写controller
-
编写service
-
接口
package com.czxy.user.service; import com.baomidou.mybatisplus.extension.service.IService; import com.czxy.domain.TbUser; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ public interface TbUserService extends IService<TbUser> { TbUser findByUserName(String userName); } -
实现类
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser> implements TbUserService { @Override public TbUser findByUserName(String userName) { //1 拼条件 QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_name", userName); //2 查询 TbUser findUser = baseMapper.selectOne(queryWrapper); return findUser; } }
-
-
编写controller
package com.czxy.user.controller; import com.czxy.domain.TbUser; import com.czxy.user.service.TbUserService; import com.czxy.vo.BaseResult; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @RestController @RequestMapping("/user") public class TbUserController { @Resource private TbUserService tbUserService; /** * 用户登录的校验 * @author 桐叔 * @email liangtong@itcast.cn * @return */ @PostMapping("/check") public BaseResult check(@RequestBody TbUser tbUser) { //1 查询:通用用户名查询 TbUser findUser = tbUserService.findByUserName(tbUser.getUserName()); //2 返回 if(findUser != null) { return BaseResult.ok("可以登录"); } return BaseResult.error("用户名不存在"); } }
2)用户登录
-
编写service
-
编写controller
-
编写service
-
接口
package com.czxy.user.service; import com.baomidou.mybatisplus.extension.service.IService; import com.czxy.domain.TbUser; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ public interface TbUserService extends IService<TbUser> { /** * 登录 * @author 桐叔 * @email liangtong@itcast.cn * @return */ TbUser login(TbUser loginUser); } -
实现类
@Override public TbUser login(TbUser loginUser) { //1 拼条件 QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_name", loginUser.getUserName()); queryWrapper.eq("password", loginUser.getPassword()); //2 查询 TbUser findUser = baseMapper.selectOne(queryWrapper); return findUser; }
-
-
编写controller
package com.czxy.user.controller; import com.czxy.domain.TbUser; import com.czxy.user.service.TbUserService; import com.czxy.vo.BaseResult; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @RestController @RequestMapping("/user") public class TbUserController { @Resource private TbUserService tbUserService; /** * 登录 * @author 桐叔 * @email liangtong@itcast.cn * @return */ @PostMapping("/login") public BaseResult login(@RequestBody TbUser tbUser) { //1 查询:通用用户名查询 TbUser findUser = tbUserService.login(tbUser); //2 返回 if(findUser != null) { return BaseResult.ok("登录成功"); } return BaseResult.error("用户名或密码不匹配"); } }
2.2.3 前端实现
1)绘制登录页面
<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-button type="text" icon="el-icon-s-home">传智专修学院</el-button>
</div>
<!-- 正文 -->
<el-form :model="user" :rules="rules" ref="loginForm" label-width="80px" >
<el-form-item label="用户名" prop="userName">
<el-input v-model="user.userName"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="user.password" show-password></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" >登录</el-button>
<el-button >取消</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
export default {
layout: 'user',
data() {
return {
user: {},
rules: {
userName: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'blur' }
]
}
}
},
}
</script>
<style>
.login {
}
.login .box-card {
width: 500px;
}
</style>
2)登录框居中
-
扩展:登录框居中
-
登录页面拷贝样式
![]()
.login { height: 100%; display: flex; justify-content: center; align-items: center; } -
登录布局页面拷贝样式
![]()
html, body, #__nuxt, #__layout { height: 100%; }
-
3)登录
<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-button type="text" icon="el-icon-s-home">传智专修学院</el-button>
</div>
<!-- 正文 -->
<el-form :model="user" :rules="rules" ref="loginForm" label-width="80px" >
<el-form-item label="用户名" prop="userName">
<el-input v-model="user.userName"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="user.password" show-password></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login" >登录</el-button>
<el-button >取消</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
export default {
layout: 'user',
data() {
return {
user: {
userName: 'jack',
password: '1234'
},
rules: {
userName: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'blur' }
]
}
}
},
methods: {
login() {
// 校验
//this.$refs['loginForm'].validate((valid) => {
this.$refs.loginForm.validate(async (valid) => {
if (valid) {
// 校验通过后ajax登录
let { data:baseResult } = await this.$axios.post('/user-service/user/login', this.user)
if(baseResult.code == 20000) {
// 成功
this.$message.success(baseResult.message)
// 跳转
this.$router.push('/')
} else {
// 失败
this.$message.error(baseResult.message)
}
} else {
console.log('error submit!!');
return false;
}
});
}
},
}
</script>
<style>
.login {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.login .box-card {
width: 500px;
}
</style>
4)表单校验:内置校验

5)用户名校验:自定义校验

<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-button type="text" icon="el-icon-s-home">传智专修学院</el-button>
</div>
<!-- 正文 -->
<el-form :model="user" :rules="rules" ref="loginForm" label-width="80px" >
<el-form-item label="用户名" prop="userName">
<el-input v-model="user.userName"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="user.password" show-password></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login" >登录</el-button>
<el-button >取消</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
export default {
layout: 'user',
data() {
// 自定义校验规则start
var validateLoginCheck = async (rule, value, callback) => {
// 校验通过:callback();
// 校验未通过:callback(new Error('请输入密码'));
// 发送ajax,进行用户名校验
let user = {
userName: value
}
let { data:baseResult } = await this.$axios.post(`/user-service/user/check`, user)
if(baseResult.code == 20000) {
// 成功
callback();
} else {
// 失败
callback(new Error(baseResult.message));
}
};
// 自定义校验规则end
return {
user: {
userName: 'jack',
password: '1234'
},
rules: {
userName: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'blur' },
{ validator: validateLoginCheck, trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'blur' }
]
}
}
},
methods: {
login() {
// 校验
//this.$refs['loginForm'].validate((valid) => {
this.$refs.loginForm.validate(async (valid) => {
if (valid) {
// 校验通过后ajax登录
let { data:baseResult } = await this.$axios.post('/user-service/user/login', this.user)
if(baseResult.code == 20000) {
// 成功
this.$message.success(baseResult.message)
// 跳转
this.$router.push('/')
} else {
// 失败
this.$message.error(baseResult.message)
}
} else {
console.log('error submit!!');
return false;
}
});
}
},
}
</script>
<style>
.login {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.login .box-card {
width: 500px;
}
</style>
2.3 首页
2.3.1 需求

2.3.2 前端实现
-
将element ui布局内容编写nuxt的
默认布局中-
编写布局
-
左侧垂直菜单
-
头像+弹出提示
-
-
设置reset.css(优化)
-
将element ui布局内容编写nuxt的
默认布局中-
编写布局
-
左侧垂直菜单
-
头像+弹出提示
![]()
<template> <el-container> <el-header> <el-row> <el-col :span="22" class="title"> 学生管理系统(SMS) </el-col> <el-col :span="2"> <!-- <el-popover placement="top-start" width="200" trigger="hover" content="这是一段内容,这是一段内容,这是一段内容,这是一段内容。"> <el-avatar slot="reference" size="large" src="/5.jpg"></el-avatar> <div class="avatarItem">用户详情</div> <div class="avatarItem">修改密码</div> <div class="avatarItem">退出登录</div> </el-popover> --> <el-dropdown> <span class="el-dropdown-link"> <el-avatar :size="50" src="/5.jpg"></el-avatar> </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>用户详情</el-dropdown-item> <el-dropdown-item>修改密码</el-dropdown-item> <el-dropdown-item>退出登录</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-col> </el-row> </el-header> <el-container> <el-aside width="200px"> <!-- 菜单start --> <el-menu :default-active="$route.path" router background-color="#545c64" text-color="#fff" active-text-color="#ffd04b"> <el-menu-item index="/"> <i class="el-icon-menu"></i> <span slot="title">首页</span> </el-menu-item> <el-submenu index="/classes"> <template slot="title"> <i class="el-icon-location"></i> <span>班级管理</span> </template> <el-menu-item index="/classes/classesAdd">添加班级</el-menu-item> <el-menu-item index="/classes/classesList">班级列表</el-menu-item> </el-submenu> <el-submenu index="/student"> <template slot="title"> <span>学生管理</span> </template> <el-menu-item index="/student/studentList">学生列表</el-menu-item> </el-submenu> </el-menu> <!-- 菜单end --> </el-aside> <el-main> <!-- 视图显示 --> <nuxt/> </el-main> </el-container> <el-footer>传智专修学院</el-footer> </el-container> </template> <script> export default { } </script> <style> html, body, #__nuxt, #__layout, .el-container { height: 100%; } body { margin: 0; } .avatarItem { width: 100px; display: inline-block; margin: 5px 0; } .title { font-size: 30px; font-weight: bold; } .el-header, .el-footer { background-color: #B3C0D1; color: #333; text-align: center; line-height: 60px; } .el-aside { background-color: #545c64; color: #fff; } .el-main { background-color: #E9EEF3; color: #333; text-align: center; } </style> -
-
设置reset.css(优化)--待定









浙公网安备 33010602011771号