03、后台系统登录功能
3.1、需求分析
1、页面原型展示
2、登录页面展示
3、数据模型(employee
表)
3.2、代码开发
3.2.1、页面开发
【login.html
】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>瑞吉外卖管理端</title>
<link rel="shortcut icon" href="../../favicon.ico">
<!-- 引入样式 -->
<link rel="stylesheet" href="../../plugins/element-ui/index.css" />
<link rel="stylesheet" href="../../styles/common.css">
<link rel="stylesheet" href="../../styles/login.css">
<link rel="stylesheet" href="../../styles/icon/iconfont.css" />
<style>
.body{
min-width: 1366px;
}
</style>
</head>
<body>
<div class="login" id="login-app">
<div class="login-box">
<img src="../../images/login/login-l.png" alt="">
<div class="login-form">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" >
<div class="login-form-title">
<img src="../../images/login/logo.png" style="width:139px;height:42px;" alt="" />
</div>
<el-form-item prop="username">
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号" maxlength="20"
prefix-icon="iconfont icon-user" />
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" placeholder="密码" prefix-icon="iconfont icon-lock" maxlength="20"
@keyup.enter.native="handleLogin" />
</el-form-item>
<el-form-item style="width:100%;">
<el-button :loading="loading" class="login-btn" size="medium" type="primary" style="width:100%;"
@click.native.prevent="handleLogin">
<span v-if="!loading">登录</span>
<span v-else>登录中...</span>
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="../../plugins/vue/vue.js"></script>
<!-- 引入组件库 -->
<script src="../../plugins/element-ui/index.js"></script>
<!-- 引入axios -->
<script src="../../plugins/axios/axios.min.js"></script>
<script src="../../js/request.js"></script>
<script src="../../js/validate.js"></script>
<script src="../../api/login.js"></script>
<script>
new Vue({
el: '#login-app',
data() {
return {
loginForm:{
username: 'admin',
password: '123456'
},
loading: false
}
},
computed: {
loginRules() {
const validateUsername = (rule, value, callback) => {
if (value.length < 1 ) {
callback(new Error('请输入用户名'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('密码必须在6位以上'))
} else {
callback()
}
}
return {
'username': [{ 'validator': validateUsername, 'trigger': 'blur' }],
'password': [{ 'validator': validatePassword, 'trigger': 'blur' }]
}
}
},
created() {
},
methods: {
async handleLogin() {
this.$refs.loginForm.validate(async (valid) => {
if (valid) {
this.loading = true
let res = await loginApi(this.loginForm)
if (String(res.code) === '1') {//1表示登录成功
localStorage.setItem('userInfo',JSON.stringify(res.data))
window.location.href= '/backend/index.html'
} else {
this.$message.error(res.msg)
this.loading = false
}
}
})
}
}
})
</script>
</body>
</html>
【login.js
】
function loginApi(data) {
return $axios({
'url': '/employee/login',
'method': 'post',
data
})
}
3.2.2、后端开发
1、创建实体类Employee,和employee表进行映射
/**
* 员工实体
*/
@Data
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String name;
private String password;
private String phone;
private String sex;
private String idNumber;//身份证号码
private Integer status;
private LocalDateTime createTime;
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
}
2、创建controller
、service
、mapper
【EmployeeMapper.java
】
@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {
}
【EmployeeService.java
】
public interface EmployeeService extends IService<Employee> {
}
【EmployeeServiceImpl.java
】
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {
}
【EmployeeController.java
】
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
}
3、返回结果类
此类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回给前端页面
/**
* 通用返回结果类,服务端响应的数据最终都会封装成此对象
* @param <T>
*/
@Data
public class R<T> {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
private Map map = new HashMap(); //动态数据
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) {
this.map.put(key, value);
return this;
}
}
4、在controller
中创建登录方法
处理逻辑如下:
- 将页面提交的密码
password
进行md5
加密处理 - 根据页面提交的用户名
username
查询数据库 - 如果没有查询到则返回登录失败结果
- 密码比对,如果不一致则返回登录失败结果
- 查看员工状态,如果为已禁用状态,则返回员工已禁用结果
- 登录成功,将员工
id
存入session
并返回登录成功结果
3.3、功能测试
【EmployeeController.java
】
/**
* 员工登录
* @param request
* @param employee 将前端页面请求的用户名、密码封装成employee实体类
* @return
*/
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee) {
//1、将页面提交的密码password进行md5加密处理
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
//2、根据页面提交的用户名username查询数据库
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getUsername, employee.getUsername());
Employee emp = employeeService.getOne(queryWrapper);//username在数据库中是唯一的
//3、如果没有查询到则返回登录失败结果
if (emp == null) {
return R.error("登录失败,无此用户!");
}
//4、密码比对,如果不一致则返回登录失败结果
if (!emp.getPassword().equals(password)) {
return R.error("登录失败,密码输入错误!");
}
//5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果
if (emp.getStatus() == 0) {
return R.error("登录失败,该账号已禁用!");
}
//6、登录成功,将员工id存入session并返回登录成功结果
request.getSession().setAttribute("employee", emp.getId());
return R.success(emp);
}