实现用户新增
当点击新增用户按钮进行添加,并填写添加相应的信息;
编辑新增页面
官网API
定义对话框
第一步
<!--
:visible.sync 控制对话框是否展现
-->
<el-dialog title="用户新增" :visible.sync="addUserDialogVisible" width="65%"
@close="closeAddUserDialog">
<el-form :model="addUserForm" :rules="rules" ref="addUserRuleForm" label-width="100px" class="demo-ruleForm">
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addUserDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addUserBtn">确 定</el-button>
</span>
</el-dialog>
第二步
第三步
第四步
第五步
关于正则表达式
正则介绍
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
正则语法
{固定次数} [取值的范围] (分组)
demo: “[a-z]+.(jpg|png|gif)”
完成用户校验
<script>
export default {
data(){
//自定义校验规则 rule:当前规则对象一般不用 value: 当前校验的数据 callback:回调函数
//校验邮箱规则
const checkEmail = (rule, value, callback) => {
//定义邮箱的正则表达式 JS中用/来表示正则表达式的开始和结束
const emailRege = /^[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+$/
if (emailRege.test(value)) {
//表示邮箱合法 正确返回 通过返回true 失败返回false
return callback() //自定义规则执行成功,之后后续操作
}
callback(new Error('请填写正确的邮箱地址'))
}
//校验手机号的邮箱规则
const checkPhone = (rule, value, callback) => {
//定义校验手机号的正则语法
const phoneRege = /^1[3456789][0-9]{9}$/
if (phoneRege.test(value)) {
return callback()
}
callback(new Error('请填写正确的手机号'))
}
//密码确认 判断与password是否相同
const checkPassword = (rule, value, callback) => {
if(value !== this.addUserForm.password){
return callback(new Error('2次密码填写不一致'))
}
//如果相同,则调用回调函数
callback()
}
return {
//定义分页查询对象
queryInfo: {
query: '', //用户查询的数据
pageNum: 1, //默认第一页
pageSize: 5 //每页5条
},
userList: [], //获取分页后的结果
total: 0,
addUserDialogVisible: false,
//设定新增用户的对象
addUserForm: {
username: '',
password: '',
password2: '',
phone: '',
email: ''
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' }
],
password2: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' },
{ validator: checkPassword, trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入电话', trigger: 'blur' },
{ min: 11, max: 11, message: '长度必须11个字符', trigger: 'blur' },
// //validator与正则表达式的电话校验进行绑定
{ validator: checkPhone, trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' },
//validator与正则表达式的邮箱校验进行绑定
{ validator: checkEmail, trigger: 'blur' }
],
}
}
}
....后边省略
密码校验
//密码确认 判断与password是否相同
const checkPassword = (rule, value, callback) => {
//如果两次密码不相同
if(value !== this.addUserForm.password){
return callback(new Error('2次密码填写不一致'))
}
//如果相同,则调用回调函数
callback()
}
效果展示
<template>
<!-- 准备根标签-->
<div>
<!-- 1.编辑面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
<el-breadcrumb-item>用户列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 2.定义卡片标签 -->
<el-card class="box-card">
<!-- 2.1 定义一行元素 -->
<el-row :gutter="20">
<el-col :span="9">
<!-- 2.2定义用户的输入框 -->
<el-input placeholder="请输入内容" v-model="queryInfo.query" class="input-with-select"
clearable @clear="getUserList">
<el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button>
</el-input>
</el-col>
<el-col :span="4">
<!-- 2.2 定义新增用户按钮-->
<el-button type="primary" @click="addUserDialogVisible = true">添加用户</el-button>
</el-col>
</el-row>
<!-- 定义表格数据
:data: 表格的数据来源
prop: 从userList中获取的属性值
label: 字段名称
stripe: 斑马纹效果
border: 列
-->
<el-table :data="userList" style="width: 100%" stripe border>
<!-- 定义表格的序号 -->
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column prop="username" label="用户名"></el-table-column>
<el-table-column prop="phone" label="电话"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column prop="status" label="状态">
<template slot-scope="scope">
<!-- scope封装的对象 获取行级元素 row属性实现 -->
<el-switch v-model="scope.row.status" @change="updateStatus(scope.row)"
active-color="#13ce66" inactive-color="#ff4949">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="small"></el-button>
<el-button type="danger" icon="el-icon-delete" size="small" @click="deleteUser(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<!-- 3.定义分页功能
1.@size-change 当页面的条数变化时触发
2.@current-change 当页数改变时触发
3.current-page 显示当前的页数 ??
4.:page-sizes 显示页数的数组
5.page-size 初始条件下每页的条数
6.layout 显示分页的样式种类 全部显示
7.total 数据的总数
-->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="queryInfo.pageNum"
:page-sizes="[5, 10, 20, 40]"
:page-size="queryInfo.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</el-card>
<!--
:visible.sync 控制对话框是否展现
-->
<el-dialog title="用户新增" :visible.sync="addUserDialogVisible" width="65%"
@close="closeAddUserDialog">
<el-form :model="addUserForm" :rules="rules" ref="addUserRuleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="username">
<el-input v-model="addUserForm.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="addUserForm.password" type="password"></el-input>
</el-form-item>
<el-form-item label="密码确认" prop="password2">
<el-input v-model="addUserForm.password2" type="password"></el-input>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model="addUserForm.phone"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="addUserForm.email"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addUserDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addUserBtn">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data(){
//自定义校验规则 rule:当前规则对象一般不用 value: 当前校验的数据 callback:回调函数
//校验邮箱规则
const checkEmail = (rule, value, callback) => {
//定义邮箱的正则表达式 JS中用/来表示正则表达式的开始和结束
const emailRege = /^[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+$/
if (emailRege.test(value)) {
//表示邮箱合法 正确返回 通过返回true 失败返回false
return callback() //自定义规则执行成功,之后后续操作
}
callback(new Error('请填写正确的邮箱地址'))
}
//校验手机号的邮箱规则
const checkPhone = (rule, value, callback) => {
//定义校验手机号的正则语法
const phoneRege = /^1[3456789][0-9]{9}$/
if (phoneRege.test(value)) {
return callback()
}
callback(new Error('请填写正确的手机号'))
}
//密码确认 判断与password是否相同
const checkPassword = (rule, value, callback) => {
if(value !== this.addUserForm.password){
return callback(new Error('2次密码填写不一致'))
}
//如果相同,则调用回调函数
callback()
}
return {
//定义分页查询对象
queryInfo: {
query: '', //用户查询的数据
pageNum: 1, //默认第一页
pageSize: 5 //每页5条
},
userList: [], //获取分页后的结果
total: 0,
addUserDialogVisible: false,
//设定新增用户的对象
addUserForm: {
username: '',
password: '',
password2: '',
phone: '',
email: ''
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' }
],
password2: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' },
{ validator: checkPassword, trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入电话', trigger: 'blur' },
{ min: 11, max: 11, message: '长度必须11个字符', trigger: 'blur' },
{ validator: checkPhone, trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' },
{ validator: checkEmail, trigger: 'blur' }
]
}
}
},
methods: {
//1.动态获取userList数据
async getUserList(){
const {data: result} = await this.$http.get("/user/list",{params: this.queryInfo})
if(result.status !== 200) return this.$message.error("获取列表失败")
//为total属性赋值
this.total = result.data.total
this.userList = result.data.rows
},
handleSizeChange(pageSize){
//查询的条件需要变化
this.queryInfo.pageSize = pageSize
//重新查询数据
this.getUserList()
},
handleCurrentChange(pageNum){
this.queryInfo.pageNum = pageNum
this.getUserList()
},
async updateStatus(user){
//获取用户的Id号/状态信息 发起restFul请求.
//this.$http.put("/user/status/"+user.id+"/"+user.status)
//模板字符串写法 `` 可以编辑多行,可以直接对象取值${key}
//es6的高端写法
const {data: result} =
await this.$http.put(`/user/status/${user.id}/${user.status}`)
if(result.status !== 200) return this.$message.error("更新操作失败")
this.$message.success("更新操作成功!")
},
closeAddUserDialog(){
//当对话框关闭时,应该重置表单
this.$refs.addUserRuleForm.resetFields()
},
addUserBtn(){
//对整个表单重新进行校验 1.获取表单的对象 2.进行数据校验
this.$refs.addUserRuleForm.validate(async valid => {
if(!valid) return this.$message.error("请正确填写数据")
//之后发起ajax请求实现用户新增
const {data: result} = await this.$http.post('/user/addUser',this.addUserForm)
if(result.status !== 200) return this.$message.error("新增用户失败")
this.$message.success("新增用户成功")
//将对话框关闭
this.addUserDialogVisible = false
//重新刷新列表页面
this.getUserList()
})
}
},
//当页面加载完成之后 调用该函数
mounted(){
//获取userList列表数据
this.getUserList()
}
}
</script>
<!--
当前样式是否支持less语法 样式的一种语言
scoped 让样式只对当前组件有效 防止样式击穿
-->
<style lang="less" scoped>
</style>
重置表单
官网API
说明: 当用户点击取消/关闭对话框时,触发关闭回调操作.即就是点击取消按钮之后,再次点击添加用户需要重新输入相应信息;
编辑页面
第一步
第二步
用户最终校验
问题:由于当先输入第一次密码之后在输入第二次确认密码会进行校验,但是反过来先输入确认密码在输入密码就不会进行校验;
解决:当点击确认提交之后再次进行提交;
编辑页面JS
closeAddUserDialog(){
//当对话框关闭时,应该重置表单
this.$refs.addUserRuleForm.resetFields()
},
addUserBtn(){
//对整个表单重新进行校验 1.获取表单的对象 2.进行数据校验
this.$refs.addUserRuleForm.validate(async valid => {
if(!valid) return this.$message.error("请正确填写数据")
//之后发起ajax请求实现用户新增
const {data: result} = await this.$http.post('/user/addUser',this.addUserForm)
if(result.status !== 200) return this.$message.error("新增用户失败")
this.$message.success("新增用户成功")
//将对话框关闭
this.addUserDialogVisible = false
//重新刷新列表页面
this.getUserList()
})
},
用户新增业务接口
编辑页面JS
closeAddUserDialog(){
//当对话框关闭时,应该重置表单
this.$refs.addUserRuleForm.resetFields()
},
addUserBtn(){
//对整个表单重新进行校验 1.获取表单的对象 2.进行数据校验
this.$refs.addUserRuleForm.validate(async valid => {
if(!valid) return this.$message.error("请正确填写数据")
//之后发起ajax请求实现用户新增
const {data: result} = await this.$http.post('/user/addUser',this.addUserForm)
if(result.status !== 200) return this.$message.error("新增用户失败")
this.$message.success("新增用户成功")
//将对话框关闭
this.addUserDialogVisible = false
//重新刷新列表页面
this.getUserList()
})
},
用户新增的后端的操作
编辑UserController
/**
* 业务分析: 实现用户新增 注意密码加密
* URL: /user/addUser
* 请求参数: 用户的form表单
* 返回值: SysResult对象
*/
@PostMapping("/addUser")
public SysResult addUser(@RequestBody User user){
userService.addUser(user);
return SysResult.success();
}
package com.jt.controller;
import com.jt.pojo.User;
import com.jt.service.UserService;
import com.jt.vo.PageResult;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author
* 时间 2021/5/11
*/
@RestController
@CrossOrigin
@RequestMapping("/user") //抽取公共的请求
public class UserController {
@Autowired
private UserService userService;
/**
* 1.url地址: /user/login
* 2.请求参数: 用户表单对象的JSON串 post类型
* 3.返回值结果 SysResult token?有值 正确 null 错误
*/
@PostMapping("/login")
public SysResult login(@RequestBody User user){
String token = userService.findUserByUP(user);
if(StringUtils.hasLength(token)){
return SysResult.success(token);
}else{
return SysResult.fail();
}
/*try {
String token = userService.findUserByUP(user);
if(StringUtils.hasLength(token)){
return SysResult.success(token);
}else{
return SysResult.fail();
}
}catch (Exception e){
e.printStackTrace();
return SysResult.fail();
}*/
}
/**
* 需求: 进行分页查询
* URL地址: /user/list
* 请求参数: 使用PageResult对象接收
* 请求返回值: SysResult对象
* 请求类型: get请求
*/
@GetMapping("/list")
public SysResult findUserByPage(PageResult pageResult){//只有3个参数
//携带所有的数据返回
pageResult = userService.findUserByPage(pageResult);
return SysResult.success(pageResult);
}
/**
* 更新状态信息
* URL: /user/status/{id}/{status}
* 参数: id/status
* 返回值: SysResult对象
*/
@PutMapping("/status/{id}/{status}")
public SysResult updateStatus(User user){
userService.updateStatus(user);
return SysResult.success();
}
/**
* 业务分析: 实现用户新增 注意密码加密
* URL: /user/addUser
* 请求参数: 用户的form表单
* 返回值: SysResult对象
*/
@PostMapping("/addUser")
public SysResult addUser(@RequestBody User user){
userService.addUser(user);
return SysResult.success();
}
编辑UserService
接口代码
package com.jt.service;
import com.jt.pojo.User;
import com.jt.vo.PageResult;
import java.util.List;
/**
* @author 刘昱江
* 时间 2021/5/11
*/
public interface UserService {
List<User> findAll();
String findUserByUP(User user);
PageResult findUserByPage(PageResult pageResult);
void updateStatus(User user);
void addUser(User user);
}
实现类代码
package com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import com.jt.vo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.selectList(null);
}
/**
* user对象: username/password 明文
* 业务思路:
* 1.将密码进行加密处理 md5加密方式
* 2.根据新的用户名和密码查询数据
* 3. 结果:null 没查到 u/p错误
* 不为null u/p正确 返回令牌 token UUID算法
*
* * @param user
* @return
*
* 数据库信息: 用户名 :admin 密码:admin123456
*/
@Override
public String findUserByUP(User user) {
//1.将密码加密 一般可能添加 盐值: 由公司域名构成
// hash(md5(www.baidu.com12345))
// getBytes() 是Java编程语言中将一个字符串转化为一个字节数组byte[]的方法。
String md5Pass =DigestUtils
.md5DigestAsHex(user.getPassword().getBytes());
//2.根据用户名/密码查询数据库.
user.setPassword(md5Pass);
//根据对象中不为null的属性当做where条件
QueryWrapper queryWrapper = new QueryWrapper(user);
User userDB = userMapper.selectOne(queryWrapper);
//3.返回密钥token
String token = UUID.randomUUID().toString()
.replace("-", "");
return userDB==null?null:token;
}
/**
* 业务说明: 将后台数据实现分页查询
* 分页Sql:
* select * from user limit 起始位置,查询记录数
* 查询第一页 每页20条
* select * from user limit 0,20
* @param pageResult
* @return
*
* MP实现分页查询
* MP通过分页对象进行查询,获取所有的分页相关的数据.
*
* 参数说明:
* page: 定义当前的分页对象 页面/每页的条数
* queryWrapper: 条件构造器 只有query属性不为null 才会拼接where条件.
*/
@Override
public PageResult findUserByPage(PageResult pageResult) {
//1.定义分页对象 2个参数
IPage<User> page = new Page<>(pageResult.getPageNum(),
pageResult.getPageSize());
//2.定义查询条件
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//3.判断用户是否有参数
boolean flag = StringUtils.hasLength(pageResult.getQuery());
queryWrapper.like(flag,"username", pageResult.getQuery());
//page 参数4个
page = userMapper.selectPage(page,queryWrapper);
//4.获取总记录数
long total = page.getTotal();
//5.获取分页后的结果
List<User> userList = page.getRecords();
return pageResult.setTotal(total).setRows(userList);
}
@Override
public void updateStatus(User user) { //id/status
userMapper.updateById(user);
}
@Override
public void addUser(User user) {
//1.密码加密
String md5Pass =
DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setPassword(md5Pass).setStatus(true);
userMapper.insert(user);
}
}
数据自动填充
业务说明
由于架构设计通常会添加一些必要的属性,但是该属性每次都要写,造成重复. 代码冗余,能否优化?
自动填充:
在对数据可进行一些操作的时候,有些字段基本是固定,比如创建时间和修改时间,我们可以利用mybatisplus的自动填充功能来实现。即也就是我们所说的相应的操作的时间记录;
所以使用自动填充,就不需要我们手动的进行实现,而是自动的会进行实现;
编辑POJO
说明: 将公共的属性进行抽取,之后根据MP的自动填充的机制,挑选合适的操作(CRUD)进行填充
编辑自动填充代码(编辑配置类)
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//入库操作时,需要更新 创建事件/更新时间
@Override
public void insertFill(MetaObject metaObject) {
Date date = new Date();
this.setFieldValByName("created",date,metaObject);
this.setFieldValByName("updated",date,metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updated",new Date(),metaObject);
}
}
package com.jt.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//入库操作时,需要更新 创建事件/更新时间
@Override
public void insertFill(MetaObject metaObject) {
Date date = new Date();
this.setFieldValByName("created",date,metaObject);
this.setFieldValByName("updated",date,metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updated",new Date(),metaObject);
}
}
效果展现
用户数据删除
绑定某一行的数据使用作用域插槽
官网API
编辑前端JS
async deleteUser(user){
//定义消息确认框 promise对象 如果从中获取用户的选项 不方便
const result = await this.$confirm('此操作将永久删除'+user.username+', 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
//发生报错则可以进行抛出报错信息,同时有报错则不会执行下面的代码。
}).catch(error => error)
//当点击确定按钮时会输出 确定: confirm ,当点击取消按钮时会输出 取消 cancel
if(result !== 'confirm') return this.$message.info("用户取消操作")
//发起ajax请求实现数据的删除...
const {data: resultDB} = await this.$http.delete('/user/'+user.id)
if(resultDB.status !== 200) return this.$message.error("用户删除失败!")
this.$message.success("用户删除成功!")
//重新加载用户列表
this.getUserList()
}
编辑删除的后端的代码
编辑UserController
/**
* 删除用户
* URL: /user/{id}
* 参数: 用户的ID号
* 返回值: SysResult对象
* 关于ajax说明:
* @RequestBody PUT/POST 要求将前端的json转换为对象,所以在后端添加注解
* GET/DELETE 数据都是普通数据 后端正常接收可以
*
*/
@DeleteMapping("/{id}")
public SysResult deleteUserById(@PathVariable Integer id){
userService.deleteUserById(id);
return SysResult.success();
}
package com.jt.controller;
import com.jt.pojo.User;
import com.jt.service.UserService;
import com.jt.vo.PageResult;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author 刘昱江
* 时间 2021/5/11
*/
@RestController
@CrossOrigin
@RequestMapping("/user") //抽取公共的请求
public class UserController {
@Autowired
private UserService userService;
/**
* 1.url地址: /user/login
* 2.请求参数: 用户表单对象的JSON串 post类型
* 3.返回值结果 SysResult token?有值 正确 null 错误
*/
@PostMapping("/login")
public SysResult login(@RequestBody User user){
String token = userService.findUserByUP(user);
if(StringUtils.hasLength(token)){
return SysResult.success(token);
}else{
return SysResult.fail();
}
/*try {
String token = userService.findUserByUP(user);
if(StringUtils.hasLength(token)){
return SysResult.success(token);
}else{
return SysResult.fail();
}
}catch (Exception e){
e.printStackTrace();
return SysResult.fail();
}*/
}
/**
* 需求: 进行分页查询
* URL地址: /user/list
* 请求参数: 使用PageResult对象接收
* 请求返回值: SysResult对象
* 请求类型: get请求
*/
@GetMapping("/list")
public SysResult findUserByPage(PageResult pageResult){//只有3个参数
//携带所有的数据返回
pageResult = userService.findUserByPage(pageResult);
return SysResult.success(pageResult);
}
/**
* 更新状态信息
* URL: /user/status/{id}/{status}
* 参数: id/status
* 返回值: SysResult对象
*/
@PutMapping("/status/{id}/{status}")
public SysResult updateStatus(User user){
userService.updateStatus(user);
return SysResult.success();
}
/**
* 业务分析: 实现用户新增 注意密码加密
* URL: /user/addUser
* 请求参数: 用户的form表单
* 返回值: SysResult对象
*/
@PostMapping("/addUser")
public SysResult addUser(@RequestBody User user){
userService.addUser(user);
return SysResult.success();
}
/**
* 删除用户
* URL: /user/{id}
* 参数: 用户的ID号
* 返回值: SysResult对象
* 关于ajax说明:
* @RequestBody PUT/POST 要求ajax传递的对象 自己封装为JSON 所以在后端添加注解
* GET/DELETE 数据都是普通数据 后端正常接收可以
*
*/
@DeleteMapping("/{id}")
public SysResult deleteUserById(@PathVariable Integer id){
userService.deleteUserById(id);
return SysResult.success();
}
}
编辑UserService
接口代码
package com.jt.service;
import com.jt.pojo.User;
import com.jt.vo.PageResult;
import java.util.List;
/**
* @author
* 时间 2021/5/11
*/
public interface UserService {
List<User> findAll();
String findUserByUP(User user);
PageResult findUserByPage(PageResult pageResult);
void updateStatus(User user);
void addUser(User user);
void deleteUserById(Integer id);
}
实现类代码
@Override
public void deleteUserById(Integer id) {
userMapper.deleteById(id);
}
package com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import com.jt.vo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* @author
* 时间 2021/5/11
*/
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.selectList(null);
}
/**
* user对象: username/password 明文
* 业务思路:
* 1.将密码进行加密处理 md5加密方式
* 2.根据新的用户名和密码查询数据
* 3. 结果:null 没查到 u/p错误
* 不为null u/p正确 返回令牌 token UUID算法
*
* * @param user
* @return
*
* 数据库信息: 用户名 :admin 密码:admin123456
*/
@Override
public String findUserByUP(User user) {
//1.将密码加密 一般可能添加 盐值: 由公司域名构成
// hash(md5(www.baidu.com12345))
String md5Pass =DigestUtils
.md5DigestAsHex(user.getPassword().getBytes());
//2.根据用户名/密码查询数据库.
user.setPassword(md5Pass);
//根据对象中不为null的属性当做where条件
QueryWrapper queryWrapper = new QueryWrapper(user);
User userDB = userMapper.selectOne(queryWrapper);
//3.返回密钥token
String token = UUID.randomUUID().toString()
.replace("-", "");
return userDB==null?null:token;
}
/**
* 业务说明: 将后台数据实现分页查询
* 分页Sql:
* select * from user limit 起始位置,查询记录数
* 查询第一页 每页20条
* select * from user limit 0,20
* @param pageResult
* @return
*
* MP实现分页查询
* MP通过分页对象进行查询,获取所有的分页相关的数据.
*
* 参数说明:
* page: 定义当前的分页对象 页面/每页的条数
* queryWrapper: 条件构造器 只有query属性不为null 才会拼接where条件.
*/
@Override
public PageResult findUserByPage(PageResult pageResult) {
//1.定义分页对象 2个参数
IPage<User> page = new Page<>(pageResult.getPageNum(),
pageResult.getPageSize());
//2.定义查询条件
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//3.判断用户是否有参数
boolean flag = StringUtils.hasLength(pageResult.getQuery());
queryWrapper.like(flag,"username", pageResult.getQuery());
//page 参数4个
page = userMapper.selectPage(page,queryWrapper);
//4.获取总记录数
long total = page.getTotal();
//5.获取分页后的结果
List<User> userList = page.getRecords();
return pageResult.setTotal(total).setRows(userList);
}
@Override
public void updateStatus(User user) { //id/status
userMapper.updateById(user);
}
@Override
public void addUser(User user) {
//1.密码加密
String md5Pass =
DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setPassword(md5Pass).setStatus(true);
userMapper.insert(user);
}
@Override
public void deleteUserById(Integer id) {
userMapper.deleteById(id);
}
}
知识总结
usermapper的代码
package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import java.util.List;
/**
* @author
* 时间 2021/2/2
*/
public interface UserMapper extends BaseMapper<User> {
}
usercontroller的代码
package com.jt.controller;
import com.jt.pojo.User;
import com.jt.service.UserService;
import com.jt.vo.PageResult;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author
* 时间 2021/5/11
*/
@RestController
@CrossOrigin
@RequestMapping("/user") //抽取公共的请求
public class UserController {
@Autowired
private UserService userService;
/**
* 1.url地址: /user/login
* 2.请求参数: 用户表单对象的JSON串 post类型
* 3.返回值结果 SysResult token?有值 正确 null 错误
*/
@PostMapping("/login")
public SysResult login(@RequestBody User user){
String token = userService.findUserByUP(user);
if(StringUtils.hasLength(token)){
return SysResult.success(token);
}else{
return SysResult.fail();
}
/*try {
String token = userService.findUserByUP(user);
if(StringUtils.hasLength(token)){
return SysResult.success(token);
}else{
return SysResult.fail();
}
}catch (Exception e){
e.printStackTrace();
return SysResult.fail();
}*/
}
/**
* 需求: 进行分页查询
* URL地址: /user/list
* 请求参数: 使用PageResult对象接收
* 请求返回值: SysResult对象
* 请求类型: get请求
*/
@GetMapping("/list")
public SysResult findUserByPage(PageResult pageResult){//只有3个参数
//携带所有的数据返回
pageResult = userService.findUserByPage(pageResult);
return SysResult.success(pageResult);
}
/**
* 更新状态信息
* URL: /user/status/{id}/{status}
* 参数: id/status
* 返回值: SysResult对象
*/
@PutMapping("/status/{id}/{status}")
public SysResult updateStatus(User user){
userService.updateStatus(user);
return SysResult.success();
}
/**
* 业务分析: 实现用户新增 注意密码加密
* URL: /user/addUser
* 请求参数: 用户的form表单
* 返回值: SysResult对象
*/
@PostMapping("/addUser")
public SysResult addUser(@RequestBody User user){
userService.addUser(user);
return SysResult.success();
}
/**
* 删除用户
* URL: /user/{id}
* 参数: 用户的ID号
* 返回值: SysResult对象
* 关于ajax说明:
* @RequestBody PUT/POST 要求ajax传递的对象 自己封装为JSON 所以在后端添加注解
* GET/DELETE 数据都是普通数据 后端正常接收可以
*
*/
@DeleteMapping("/{id}")
public SysResult deleteUserById(@PathVariable Integer id){
userService.deleteUserById(id);
return SysResult.success();
}
}
userservice的代码
接口的代码
package com.jt.service;
import com.jt.pojo.User;
import com.jt.vo.PageResult;
import java.util.List;
/**
* @author
* 时间 2021/5/11
*/
public interface UserService {
List<User> findAll();
String findUserByUP(User user);
PageResult findUserByPage(PageResult pageResult);
void updateStatus(User user);
void addUser(User user);
void deleteUserById(Integer id);
}
实现类的代码
package com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import com.jt.vo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* @author 刘昱江
* 时间 2021/5/11
*/
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.selectList(null);
}
/**
* user对象: username/password 明文
* 业务思路:
* 1.将密码进行加密处理 md5加密方式
* 2.根据新的用户名和密码查询数据
* 3. 结果:null 没查到 u/p错误
* 不为null u/p正确 返回令牌 token UUID算法
*
* * @param user
* @return
*
* 数据库信息: 用户名 :admin 密码:admin123456
*/
@Override
public String findUserByUP(User user) {
//1.将密码加密 一般可能添加 盐值: 由公司域名构成
// hash(md5(www.baidu.com12345))
String md5Pass =DigestUtils
.md5DigestAsHex(user.getPassword().getBytes());
//2.根据用户名/密码查询数据库.
user.setPassword(md5Pass);
//根据对象中不为null的属性当做where条件
QueryWrapper queryWrapper = new QueryWrapper(user);
User userDB = userMapper.selectOne(queryWrapper);
//3.返回密钥token
String token = UUID.randomUUID().toString()
.replace("-", "");
return userDB==null?null:token;
}
/**
* 业务说明: 将后台数据实现分页查询
* 分页Sql:
* select * from user limit 起始位置,查询记录数
* 查询第一页 每页20条
* select * from user limit 0,20
* @param pageResult
* @return
*
* MP实现分页查询
* MP通过分页对象进行查询,获取所有的分页相关的数据.
*
* 参数说明:
* page: 定义当前的分页对象 页面/每页的条数
* queryWrapper: 条件构造器 只有query属性不为null 才会拼接where条件.
*/
@Override
public PageResult findUserByPage(PageResult pageResult) {
//1.定义分页对象 2个参数
IPage<User> page = new Page<>(pageResult.getPageNum(),
pageResult.getPageSize());
//2.定义查询条件
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//3.判断用户是否有参数
boolean flag = StringUtils.hasLength(pageResult.getQuery());
queryWrapper.like(flag,"username", pageResult.getQuery());
//page 参数4个
page = userMapper.selectPage(page,queryWrapper);
//4.获取总记录数
long total = page.getTotal();
//5.获取分页后的结果
List<User> userList = page.getRecords();
return pageResult.setTotal(total).setRows(userList);
}
@Override
public void updateStatus(User user) { //id/status
userMapper.updateById(user);
}
@Override
public void addUser(User user) {
//1.密码加密
String md5Pass =
DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setPassword(md5Pass).setStatus(true);
userMapper.insert(user);
}
@Override
public void deleteUserById(Integer id) {
userMapper.deleteById(id);
}
}
user.vue 即user页面的代码
<template>
<!-- 准备根标签-->
<div>
<!-- 1.编辑面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
<el-breadcrumb-item>用户列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 2.定义卡片标签 -->
<el-card class="box-card">
<!-- 2.1 定义一行元素 -->
<el-row :gutter="20">
<el-col :span="9">
<!-- 2.2定义用户的输入框 -->
<el-input placeholder="请输入内容" v-model="queryInfo.query" class="input-with-select"
clearable @clear="getUserList">
<el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button>
</el-input>
</el-col>
<el-col :span="4">
<!-- 2.2 定义新增用户按钮-->
<el-button type="primary" @click="addUserDialogVisible = true">添加用户</el-button>
</el-col>
</el-row>
<!-- 定义表格数据
:data: 表格的数据来源
prop: 从userList中获取的属性值
label: 字段名称
stripe: 斑马纹效果
border: 列
-->
<el-table :data="userList" style="width: 100%" stripe border>
<!-- 定义表格的序号 -->
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column prop="username" label="用户名"></el-table-column>
<el-table-column prop="phone" label="电话"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column prop="status" label="状态">
<template slot-scope="scope">
<!-- scope封装的对象 获取行级元素 row属性实现 -->
<el-switch v-model="scope.row.status" @change="updateStatus(scope.row)"
active-color="#13ce66" inactive-color="#ff4949">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="small"></el-button>
<el-button type="danger" icon="el-icon-delete" size="small" @click="deleteUser(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<!-- 3.定义分页功能
1.@size-change 当页面的条数变化时触发
2.@current-change 当页数改变时触发
3.current-page 显示当前的页数 ??
4.:page-sizes 显示页数的数组
5.page-size 初始条件下每页的条数
6.layout 显示分页的样式种类 全部显示
7.total 数据的总数
-->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="queryInfo.pageNum"
:page-sizes="[5, 10, 20, 40]"
:page-size="queryInfo.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</el-card>
<!--
:visible.sync 控制对话框是否展现
-->
<el-dialog title="用户新增" :visible.sync="addUserDialogVisible" width="65%"
@close="closeAddUserDialog">
<el-form :model="addUserForm" :rules="rules" ref="addUserRuleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="username">
<el-input v-model="addUserForm.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="addUserForm.password" type="password"></el-input>
</el-form-item>
<el-form-item label="密码确认" prop="password2">
<el-input v-model="addUserForm.password2" type="password"></el-input>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input v-model="addUserForm.phone"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="addUserForm.email"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addUserDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addUserBtn">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data(){
//自定义校验规则 rule:当前规则对象一般不用 value: 当前校验的数据 callback:回调函数
//校验邮箱规则
const checkEmail = (rule, value, callback) => {
//定义邮箱的正则表达式 JS中用/来表示正则表达式的开始和结束
const emailRege = /^[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+$/
if (emailRege.test(value)) {
//表示邮箱合法 正确返回 通过返回true 失败返回false
return callback() //自定义规则执行成功,之后后续操作
}
callback(new Error('请填写正确的邮箱地址'))
}
//校验手机号的邮箱规则
const checkPhone = (rule, value, callback) => {
//定义校验手机号的正则语法
const phoneRege = /^1[3456789][0-9]{9}$/
if (phoneRege.test(value)) {
return callback()
}
callback(new Error('请填写正确的手机号'))
}
//密码确认 判断与password是否相同
const checkPassword = (rule, value, callback) => {
if(value !== this.addUserForm.password){
return callback(new Error('2次密码填写不一致'))
}
//如果相同,则调用回调函数
callback()
}
return {
//定义分页查询对象
queryInfo: {
query: '', //用户查询的数据
pageNum: 1, //默认第一页
pageSize: 5 //每页5条
},
userList: [], //获取分页后的结果
total: 0,
addUserDialogVisible: false,
//设定新增用户的对象
addUserForm: {
username: '',
password: '',
password2: '',
phone: '',
email: ''
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' }
],
password2: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' },
{ validator: checkPassword, trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入电话', trigger: 'blur' },
{ min: 11, max: 11, message: '长度必须11个字符', trigger: 'blur' },
{ validator: checkPhone, trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' },
{ validator: checkEmail, trigger: 'blur' }
]
}
}
},
methods: {
//1.动态获取userList数据
async getUserList(){
const {data: result} = await this.$http.get("/user/list",{params: this.queryInfo})
if(result.status !== 200) return this.$message.error("获取列表失败")
//为total属性赋值
this.total = result.data.total
this.userList = result.data.rows
},
handleSizeChange(pageSize){
//查询的条件需要变化
this.queryInfo.pageSize = pageSize
//重新查询数据
this.getUserList()
},
handleCurrentChange(pageNum){
this.queryInfo.pageNum = pageNum
this.getUserList()
},
async updateStatus(user){
//获取用户的Id号/状态信息 发起restFul请求.
//this.$http.put("/user/status/"+user.id+"/"+user.status)
//模板字符串写法 `` 可以编辑多行,可以直接对象取值${key}
//es6的高端写法
const {data: result} =
await this.$http.put(`/user/status/${user.id}/${user.status}`)
if(result.status !== 200) return this.$message.error("更新操作失败")
this.$message.success("更新操作成功!")
},
closeAddUserDialog(){
//当对话框关闭时,应该重置表单
this.$refs.addUserRuleForm.resetFields()
},
addUserBtn(){
//对整个表单重新进行校验 1.获取表单的对象 2.进行数据校验
this.$refs.addUserRuleForm.validate(async valid => {
if(!valid) return this.$message.error("请正确填写数据")
//之后发起ajax请求实现用户新增
const {data: result} = await this.$http.post('/user/addUser',this.addUserForm)
if(result.status !== 200) return this.$message.error("新增用户失败")
this.$message.success("新增用户成功")
//将对话框关闭
this.addUserDialogVisible = false
//重新刷新列表页面
this.getUserList()
})
},
async deleteUser(user){
//定义消息确认框 promise对象 如果从中获取用户的选项 不方便
const result = await this.$confirm('此操作将永久删除'+user.username+', 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).catch(error => error)
//确定: confirm 取消 cancel
if(result !== 'confirm') return this.$message.info("用户取消操作")
//发起ajax请求实现数据的删除...
const {data: resultDB} = await this.$http.delete('/user/'+user.id)
if(resultDB.status !== 200) return this.$message.error("用户删除失败!")
this.$message.success("用户删除成功!")
//重新加载用户列表
this.getUserList()
}
},
//当页面加载完成之后 调用该函数
mounted(){
//获取userList列表数据
this.getUserList()
}
}
</script>
<!--
当前样式是否支持less语法 样式的一种语言
scoped 让样式只对当前组件有效 防止样式击穿
-->
<style lang="less" scoped>
</style>
关于知识点梳理
列表页面结构
新增用户页面