Mysql+MybatisPlus+Vue实现基础增删改查CRUD

数据库

设计数据库

设计几个字段,主键id自动增长且不可为空

create table if not exists `user`
(`id`       bigint(20) primary key auto_increment comment '主键id',`username` varchar(255)   not null comment '用户名',`sex`      char(1)        not null comment '性别',`phone`    varchar(22)    not null comment '手机号',`city`     varchar(255)   not null comment '所在城市',`position` varchar(255)   not null comment '职位',`salary`   decimal(18, 2) not null comment '工资:长度18,保留2位小数'
) engine InnoDB comment '用户表';

插入数据

随机插入几条数据

INSERT INTO `user` (`username`, `sex`, `phone`, `city`, `position`, `salary`) VALUES
('张三', '男', '13912345678', '北京', '软件工程师', 10000.00),
('李四', '女', '13723456789', '上海', '数据分析师', 12000.00),
('王五', '男', '15034567890', '广州', '产品经理', 15000.00),
('赵六', '女', '15145678901', '深圳', '前端工程师', 11000.00),
('刘七', '男', '15856789012', '成都', '测试工程师', 9000.00),
('陈八', '女', '13967890123', '重庆', 'UI设计师', 8000.00),
('朱九', '男', '13778901234', '武汉', '运维工程师', 10000.00),
('杨十', '女', '15089012345', '南京', '数据工程师', 13000.00),
('孙十一', '男', '15190123456', '杭州', '后端工程师', 12000.00),
('周十二', '女', '15801234567', '天津', '产品设计师', 11000.00);
select * from user;

查询成功则建表以及插入数据都成功
在这里插入图片描述

后端

实体类

根据数据库进行实体类的书写,功能要求可以后期再加

package com.wedu.modules.my.entity;import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;/*** <p>* 用户表* </p>** @author xw* @since 2024-01-26*/
@Data
@TableName("user")
@ApiModel(value="User对象", description="用户表")
public class User implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty(value = "主键id")@TableId(value = "id", type = IdType.AUTO)private Long id;@ApiModelProperty(value = "用户名")private String username;@ApiModelProperty(value = "性别")private String sex;@ApiModelProperty(value = "手机号")private String phone;@ApiModelProperty(value = "所在城市")private String city;@ApiModelProperty(value = "职位")private String position;@ApiModelProperty(value = "工资:长度18位,保留2位小数")private BigDecimal salary;}

dao层

使用mybatisplus的框架方法
继承BaseMapper使用其中基础的功能,进行增删改查的撰写

/*** 系统用户 增删改查* 要给mapper层添加@Mapper和@Repository注解*/
@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {
}

service层

在当前层下写一个接口继承IService模板提供的基础功能

/*** IUserService继承IService模板提供的基础功能和方法*/
public interface IUserService extends IService<User> {}

再写一个实现类去实现,由于现在接口中没有方法需要实现,所以实现类中无需实现

/*** MyUserServiceImpl实现了IService,提供了IService中基础功能的实现* 若MyUserServiceImpl无法满足业务需求,则可以使用自定的MyUserService定义方法,并在实现类中实现* service的impl实现类的注释要加实现的是哪个接口*/
@Service("iUserService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}

controller层

新建一个UserController 继承AbstractController 中的方法,可以调用进行删除用户和后续修改根据id得到用户,@RequestMapping("/my/test")表示下面如果再加路径,比如@GetMapping("/select"),查询的路径则是/my/test/select,具有全局效应

@RestController
@RequestMapping("/my/test")
public class UserController extends AbstractController {}

前端

test.vue

首先在modules文件夹下新建一个my文件夹,在my文件夹内新建一个userrr的vue文件,下载了帮助插件的小伙伴就可以打一个<v,选择第一行回车就能得到一个快速撰写vue界面的模板
在这里插入图片描述
出来的界面就像下面的代码片一样,可以在template标签中导入element 要显示的标签主键等,然后进行批量页面渲染,在script标签内写自己所创建的方法或者从外部的引入,style内放什么无需多讲,相信大家都学过css

<template></template><script>
export default {}
</script><style></style>

此时我们数据库已经写好,后端和前端模板都已生成,下一步可以进行增删改查的书写

查询所有用户列表

我们需要查询数据库内所有数据,展示在前端页面中

1.新建表单

在template内新建表单,将表单设置为内联,使控件水平排列

<template><div><el-form :inline="true"></el-form></div>
</template>

2.新建表单项

在新建的表单内新建表单项,在表单项内写一个查询按钮,触发点击即可查询事件

<template><div><el-form :inline="true"><!-- 按钮 --><el-form-item><!-- 查询按钮 --><el-button @click="search()">查询</el-button></el-form-item></el-form></div>
</template>

3.查询方法search

export default {}内的methods:{}中写一个查询方法search(),用这个方法获取当前数据列表getDataList

<script>
export default {methods: {// 查询search() {this.getDataList();},},
};
</script>

4.初始化数据集合

数据列表需要在data(){return{}}内进行初始化,当页的数据集合dataList初始化为空数组

<script>
export default {data() {return {dataList: [],};},methods: {// 查询search() {this.getDataList();},},
};
</script>

5.发送请求获取当前数据列表

获取当前数据列表的getDataList也是一个方法,在方法模块中和查询方法同级,获取数据列表需要向后端发送一个请求this.$http({}),使用ajax请求url地址,这里为了解决跨域问题用到了一个请求地址处理adornUrl(),写入请求路径/xx/xx/xx即可,请求方式根据restful url设计风格来,查询get,添加post,更新put,删除delete,这里查询到的参数还要进行get请求参数处理adornParams,根据后端传递的参数进行处理,有就写没有就忽略。发送请求之后要进行.then判断,如果data存在且data的code值恒等于(===)0则返回当页数据放入data初始化的集合内,不满足则还是为空。
需要code恒等于0是因为后端与前端交互是通过R返回数据,R构造器中默认code等于0的时候返回数据才会成功,恒等于代表着值相同且类型相同,避免了一些由于值相同但类型不同返回的错误数据

<script>
export default {data() {return {dataList: [],};},methods: {// 查询search() {this.getDataList();},// 获取数据列表getDataList() {this.$http({url: this.$http.adornUrl("/my/test/select"),method: "get",params: this.$http.adornParams({}),}).then(({ data }) => {if (data && data.code === 0) {this.dataList = data.dataList;} else {this.dataList = [];}});},},
};
</script>

6.activated生命周期钩子

在export default {}内可以使用生命周期钩子激活组件,这里就可以用activated生命周期钩子激活组件的时候执行getDataList方法获取数据列表,生命周期钩子与data、methods同级

<script>
export default {data() {return {dataList: [],};},activated() {this.getDataList();},methods: {// 查询search() {this.getDataList();},// 获取数据列表getDataList() {this.$http({url: this.$http.adornUrl("/my/test/select"),method: "get",params: this.$http.adornParams({}),}).then(({ data }) => {if (data && data.code === 0) {this.dataList = data.dataList;} else {this.dataList = [];}});},},
};
</script>

7.新建表格

和表单项同级,新建表格显示数据,表格双向绑定dataList,为每个元素生成一行数据,border边框,style属性设置宽度100%

<template><div><el-form :inline="true"><!-- 按钮 --><el-form-item><!-- 查询按钮 --><el-button @click="search()">查询</el-button></el-form-item></el-form><!-- 数据列表表格 --><el-table :data="dataList" border style="width: 100%"></el-table></div>
</template>

8.el-table-column

在新建的表格内写表格项el-table-column,内置属性prop写数据库对应列内容的字段名,header-align表头对齐方式和align对齐方式都可显示为居中center,label显示标题

<template><div><el-form :inline="true"><!-- 按钮 --><el-form-item><!-- 查询按钮 --><el-button @click="search()">查询</el-button></el-form-item></el-form><!-- 数据列表表格 --><el-table :data="dataList" border style="width: 100%"><el-table-columnprop="id"header-align="center"align="center"label="ID"></el-table-column><el-table-columnprop="username"header-align="center"align="center"label="用户名"></el-table-column><el-table-columnprop="sex"header-align="center"align="center"label="性别"></el-table-column><el-table-columnprop="phone"header-align="center"align="center"label="手机号"></el-table-column><el-table-columnprop="city"header-align="center"align="center"label="所在城市"></el-table-column><el-table-columnprop="position"header-align="center"align="center"label="职位"></el-table-column><el-table-columnprop="salary"header-align="center"align="center"label="工资"></el-table-column></el-table></div>
</template>

9.在UserController内写查询方法

查询所有用户可以回忆一下之前mybatisplus是怎么查询的,仿照着写即可,不过有一些区别,上次写mybatisplus是纯后端,现在要和前端进行连接,所以要使用R这个对象,这是给前端返回的对象
LambdaQueryWrapper和QueryWrapper在这里都可以用作于简单的查询,LambdaQueryWrapper使用lambda表达式可以直接通过实体类get()属性,而QueryWrapper必须要与数据库的中表名一致

    //在controller层引用service层接口对象@Autowiredprivate IUserService iUserService;/*** 查询所有用户列表*/@GetMapping("/select")public R selectAll(){LambdaQueryWrapper<User> ulqw = new LambdaQueryWrapper<>();//查询出来的所有数据放入数据库表实体类对象的集合中List<User> dataList=iUserService.list(ulqw);//查询所有用户方法在mapper继承的baseMapper内有方法封装可直接调用,用多态的写法//List<User> dataList=iUserService.getBaseMapper().selectList(null);//通过R的ok方法put键值对返回给前端,这里返回的键就是获取数据列表发送请求成功后需要展示的数据集合return R.ok().put("dataList",dataList);}

10.前端接收查询并显示在页面上

在这里插入图片描述

分页查询

  • 1.在service接口内根据不同的key构建SQL查询条件,结合分页参数进行数据库查询,最后将查询结果封装成PageUtils对象返回给调用者
  • 2.在接口实现类里重写这个接口方法,先从map对象中获取键对应的值,再根据给定的参数查询实体类表中用户的信息,返回一个分页结果。定义一个泛型为SysUserEntity的分页对象,用于存储查询后的分页数据;创建一个新的Query对象,并调用getPage方法初始化一个分页对象;创建一个新的QueryWrapper对象,构建复杂条件查询SQL语句的对象;.like:如果username不为空或空白字符串isnotblank,则在生成的SQL查询中添加一个LIKE条件,匹配所有username字段与给定username值相匹配的记录;.eq:如果createUserId不为null,则在生成的SQL查询中添加一个等于(EQ)条件,匹配所有create_user_id字段与给定createUserId值相等的记录;返回新的分页对象PageUtils
  • 3.给service的接口传入params参数,返回一个分页page,返回一个成功的响应结果

IUserService

public interface IUserService extends IService<User> {/*** 在service接口内根据不同的key构建SQL查询条件,结合分页参数进行数据库查询,最后将查询结果封装成PageUtils对象返回给调用者*/PageUtils queryPage(Map<String,Object> params);
}

UserServiceImpl

@Service("iUserService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Override/*返回PageUtils工具类对象*/public PageUtils queryPage(Map<String, Object> params) {String username = (String) params.get("username");String phone = (String) params.get("phone");/*分页查询*/IPage<User> page=this.page(new Query<User>().getPage(params),new QueryWrapper<User>()/*like-模糊查询*/.like(StringUtils.isNotBlank(username),"username",username)/*eq-相等*/.eq(phone!=null,"phone",phone));return new PageUtils(page);}
}

UserController

@RestController
@RequestMapping("/my/test")
public class UserController extends AbstractController {@Autowiredprivate IUserService iUserService;//分页查询@GetMapping("/list")//@RequestParam 将前端发送的请求参数绑定到controller层的方法参数上public R list(@RequestParam Map<String,Object> params){PageUtils page = iUserService.queryPage(params);return R.ok().put("page",page);}}

ttt.vue

<template><div><el-form :inline="true" :model="dataForm" @keyup.enter.native="search()"><el-form-item><el-input v-model="dataForm.username" placeholder="请输入用户名" clearable></el-input></el-form-item><el-form-item><el-button @click="search()">查询</el-button></el-form-item></el-form><el-table :data="dataList" border style="width: 100%;"><el-table-columnprop="id"header-align="center"align="center"width="80"label="ID"></el-table-column><el-table-columnprop="username"header-align="center"align="center"label="用户名"></el-table-column><el-table-columnprop="sex"header-align="center"align="center"label="性别"></el-table-column><el-table-columnprop="phone"header-align="center"align="center"label="手机号"></el-table-column><el-table-columnprop="city"header-align="center"align="center"label="所在城市"></el-table-column><el-table-columnprop="position"header-align="center"align="center"label="职位"></el-table-column><el-table-columnprop="salary"header-align="center"align="center"label="工资"></el-table-column></el-table><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="pageIndex":page-sizes="[10, 20, 50, 100]":page-size="pageSize"layout="total, sizes, prev, pager, next, jumper":total="totalPage"></el-pagination></div>
</template><script>
export default {data(){return{dataForm:{username:''},dataList:[],pageIndex:1,pageSize:10,totalPage:0}},activated(){this.getDataList()},methods:{search(){this.pageIndex = 1this.getDataList()},getDataList(){this.$http({url:this.$http.adornUrl("/my/test/list"),method:'get',params:this.$http.adornParams({page:this.pageIndex,limit:this.pageSize,username:this.dataForm.username})}).then(({data})=>{if(data&&data.code===0){this.dataList=data.page.list;this.totalPage=data.page.totalCount;}else{this.dataList=[];this.totalPage=0}})},handleSizeChange(val){this.pageSize=val;this.pageIndex=1;this.getDataList();},handleCurrentChange(val){this.pageIndex=val;this.getDataList();}}
}
</script><style></style>

分页查询总结

默认查询数据库内全部信息,按照分页查询一页10条信息,左上角请输入用户名,可以输入完整的用户名,也可以模糊查询,写入按回车或者点查询都是可以查到想到的数据的,如果输错了可以点框框最右边的叉叉全删
在这里插入图片描述

删除(单个或批量)

  • 1.根据传入的一组用户id,一次性从数据库删除多个用户且无返回值
  • 2.将传入的用户id转换为一个ArrayList,再通过removeByIds方法一次性删除所有指定id对象
  • 3.删除用户前三个注释,系统日志注解SysLog、请求方式注解PostMapping、权限注解RequiresPermissions,其中权限注解暂时不写,在controller层的传入对象前加上请求体RequestBody;如果要删除的id里包含1就返回错误信息:它有系统管理员不能删除,调用service层的删除方法,传入ids进行删除,方法没有返回值,最后将结果返回给前端,让前端展现

方法一

IUserService

    /*** 根据传入的一组用户id,一次性从数据库删除多个用户且无返回值*/void deleteBatch(Long[] ids);

UserServiceImpl

    @Overridepublic void deleteBatch(Long[] ids) {this.removeByIds(Arrays.asList(ids));}

UserController

    //批量删除@SysLog("批量删除")@PostMapping("/delete")public R delete(@RequestBody Long[] ids){if (ArrayUtils.contains(ids,1l)){return R.error("有主键,不可删除");}iUserService.deleteBatch(ids);return R.ok();}

在这里插入图片描述
仿照写

ttt.vue

<template><div><el-form :inline="true" :model="dataForm" @keyup.enter.native="search()"><el-form-item><el-inputv-model="dataForm.username"placeholder="请输入用户名"clearable></el-input></el-form-item><el-form-item><el-button @click="search()">查询</el-button><el-buttontype="danger"@click="deleteHandle()":disabled="dataListSelections.length <= 0">批量删除</el-button></el-form-item></el-form><el-table:data="dataList"border@selection-change="selectionChangeHandle"style="width: 100%"><el-table-columntype="selection"header-align="center"align="center"width="50"></el-table-column><el-table-columnprop="id"header-align="center"align="center"width="80"label="ID"></el-table-column><el-table-columnprop="username"header-align="center"align="center"label="用户名"></el-table-column><el-table-columnprop="sex"header-align="center"align="center"label="性别"></el-table-column><el-table-columnprop="phone"header-align="center"align="center"label="手机号"></el-table-column><el-table-columnprop="city"header-align="center"align="center"label="所在城市"></el-table-column><el-table-columnprop="position"header-align="center"align="center"label="职位"></el-table-column><el-table-columnprop="salary"header-align="center"align="center"label="工资"></el-table-column><el-table-columnfixed="right"header-align="center"align="center"width="150"label="操作"><template slot-scope="scope"><el-buttontype="text"size="medium"@click="deleteHandle(scope.row.id)">删除</el-button></template></el-table-column></el-table><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="pageIndex":page-sizes="[10, 20, 50, 100]":page-size="pageSize"layout="total, sizes, prev, pager, next, jumper":total="totalPage"></el-pagination></div>
</template><script>
export default {data() {return {dataForm: {username: "",},dataList: [],pageIndex: 1,pageSize: 10,totalPage: 0,dataListSelections: [],};},activated() {this.getDataList();},methods: {search() {this.pageIndex = 1;this.getDataList();},getDataList() {this.$http({url: this.$http.adornUrl("/my/test/list"),method: "get",params: this.$http.adornParams({page: this.pageIndex,limit: this.pageSize,username: this.dataForm.username,}),}).then(({ data }) => {if (data && data.code === 0) {this.dataList = data.page.list;this.totalPage = data.page.totalCount;} else {this.dataList = [];this.totalPage = 0;}});},handleSizeChange(val) {this.pageSize = val;this.pageIndex = 1;this.getDataList();},handleCurrentChange(val) {this.pageIndex = val;this.getDataList();},selectionChangeHandle(val) {this.dataListSelections = val;},deleteHandle(id) {var ids = id? [id]: this.dataListSelections.map((item) => {return item.id;});this.$confirm(`确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,"提示",{confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {this.$http({url: this.$http.adornUrl("/my/test/delete"),method: "post",data: this.$http.adornData(ids, false),}).then(({ data }) => {if (data && data.code === 0) {this.$message({type: "success",message: "删除成功!",onClose: () => {this.getDataList();},});} else {this.$message.error(data.msg);}})  }).catch(() => {this.$message({type: "info",message: "已取消删除",});});},},
};
</script><style>
</style>

方法二

在实现层只有一行代码无具体实现逻辑时可直接在controller层写该行实现代码(简便写法)
不用写service层方法,直接调用继承接口中的方法

UserController

    //批量删除@SysLog("批量删除")@PostMapping("/delete")public R delete(@RequestBody Long[] ids){if (ArrayUtils.contains(ids,1l)){return R.error("有主键,不可删除");}iUserService.removeByIds(Arrays.asList(ids));return R.ok();}

新增

  • 1.形参为用户实体类,用到的方法是IService中的save保存
  • 2.先使用hibernate-validator校验工具类ValidatorUtils里的校验方法validateEntity,传入实体类和新增数据所需验证规则的注解组AddGroup(一些数据不能为空或者有特定的规则)
  • 3.调用iUserService类接口继承的save方法,传入新增用户保存
  • 4.返回一个成功的响应结果

方法一

IUserService

void saveUser(User user);

UserServiceImpl

    @Overridepublic void saveUser(User user) {this.save(user);}

UserController

    //新增@SysLog("新增用户")@PostMapping("/save")public R save(@RequestBody User user){ValidatorUtils.validateEntity(user, AddGroup.class);iUserService.saveUser(user);return R.ok();}

方法二

不用写service层方法,直接调用继承接口中的方法

UserController

    //新增@SysLog("新增用户")@PostMapping("/save")public R save(@RequestBody User user){ValidatorUtils.validateEntity(user, AddGroup.class);iUserService.save(user);return R.ok();}

修改

  • 1.和新增用户类似,使用方法为updateById,也是继承接口中的方法
  • 2.注解组变为UpdateGroup,也需要验证

方法一

IUserService

void updateUser(User user);

UserServiceImpl

    @Overridepublic void updateUser(User user) {this.updateById(user);}

UserController

    //修改@SysLog("修改用户")@PostMapping("/update")public R update(@RequestBody User user){ValidatorUtils.validateEntity(user, UpdateGroup.class);iUserService.updateUser(user);return R.ok();}

方法二

不用写service层方法,直接调用继承接口中的方法

UserController

    //修改@SysLog("修改用户")@PostMapping("/update")public R update(@RequestBody User user){ValidatorUtils.validateEntity(user, UpdateGroup.class);iUserService.updateById(user);return R.ok();}

新增和修改为相同的方法

二者区别在于是否传入id,可以根据是否传入id来进行新增或是修改

ttt.vue最终版

  • 1.新增按钮:在查询和批量删除中间,类型为primary主要,点击触发addOrUpdateHandle事件
  • 2.修改按钮:和删除并列,写法也与删除类似
  • 3.在分页下写一个弹窗add-or-update:和addOrUpdateVisible双向绑定,默认false不弹出,需要在data内初始化,注册组件引用addOrUpdate,刷新数据集合refreshDataList,和getDataList双向绑定
  • 4.import...from...:从xx导入AddOrUpdate模块->对新增和修改的具体写法放在另一个界面内
  • 5.注册组件:components内写组件的名字
  • 6.addOrUpdateHandle方法:传入一个id,有id值的则为修改,没有传入的则为新增;此时需要弹出新增/修改弹窗,所以要把addOrUpdateVisible写为true弹出;弹出之后才会有下一步$nextTick指向当前访问的$refs对象,在访问的对象中查找addOrUpdate的子组件,调用子组件的init方法并传入一个id
  • 此时主页面已写完,需要自行写addOrUpdate子组件
<template><div><el-form :inline="true" :model="dataForm" @keyup.enter.native="search()"><el-form-item><el-inputv-model="dataForm.username"placeholder="请输入用户名"clearable></el-input></el-form-item><el-form-item><el-button @click="search()">查询</el-button><el-button type="primary" @click="addOrUpdateHandle()">新增</el-button><el-buttontype="danger"@click="deleteHandle()":disabled="dataListSelections.length <= 0">批量删除</el-button></el-form-item></el-form><el-table:data="dataList"border@selection-change="selectionChangeHandle"style="width: 100%"><el-table-columntype="selection"header-align="center"align="center"width="50"></el-table-column><el-table-columnprop="id"header-align="center"align="center"width="80"label="ID"></el-table-column><el-table-columnprop="username"header-align="center"align="center"label="用户名"></el-table-column><el-table-columnprop="sex"header-align="center"align="center"label="性别"></el-table-column><el-table-columnprop="phone"header-align="center"align="center"label="手机号"></el-table-column><el-table-columnprop="city"header-align="center"align="center"label="所在城市"></el-table-column><el-table-columnprop="position"header-align="center"align="center"label="职位"></el-table-column><el-table-columnprop="salary"header-align="center"align="center"label="工资"></el-table-column><el-table-columnfixed="right"header-align="center"align="center"width="150"label="操作"><template slot-scope="scope"><el-buttontype="text"size="medium"@click="deleteHandle(scope.row.id)">删除</el-button><el-buttontype="text"size="medium"@click="addOrUpdateHandle(scope.row.id)">修改</el-button></template></el-table-column></el-table><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="pageIndex":page-sizes="[10, 20, 50, 100]":page-size="pageSize"layout="total, sizes, prev, pager, next, jumper":total="totalPage"></el-pagination><add-or-updatev-if="addOrUpdateVisible"ref="addOrUpdate"@refreshDataList="getDataList"></add-or-update></div>
</template><script>
import AddOrUpdate from "./ttt-add-or-update";
export default {data() {return {dataForm: {username: "",},dataList: [],pageIndex: 1,pageSize: 10,totalPage: 0,dataListSelections: [],addOrUpdateVisible: false,};},components: {AddOrUpdate,},activated() {this.getDataList();},methods: {search() {this.pageIndex = 1;this.getDataList();},getDataList() {this.$http({url: this.$http.adornUrl("/my/test/list"),method: "get",params: this.$http.adornParams({page: this.pageIndex,limit: this.pageSize,username: this.dataForm.username,}),}).then(({ data }) => {if (data && data.code === 0) {this.dataList = data.page.list;this.totalPage = data.page.totalCount;} else {this.dataList = [];this.totalPage = 0;}});},handleSizeChange(val) {this.pageSize = val;this.pageIndex = 1;this.getDataList();},handleCurrentChange(val) {this.pageIndex = val;this.getDataList();},selectionChangeHandle(val) {this.dataListSelections = val;},deleteHandle(id) {var ids = id? [id]: this.dataListSelections.map((item) => {return item.id;});this.$confirm(`确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,"提示",{confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {this.$http({url: this.$http.adornUrl("/my/test/delete"),method: "post",data: this.$http.adornData(ids, false),}).then(({ data }) => {if (data & (data.code === 0)) {this.$message({type: "success",message: "删除成功!",onClose: () => {this.getDataList();},});} else {this.$message.error(data.msg);}});}).catch(() => {this.$message({type: "info",message: "已取消删除",});});},addOrUpdateHandle(id) {this.addOrUpdateVisible = true;this.$nextTick(() => {this.$refs.addOrUpdate.init(id);});},},
};
</script><style>
</style>

ttt-add-or-update.vue

  • 1.根据对话框组件dialog写弹窗内容,动态设置标题内容,属性都需要双向绑定,无id传入就新增,有id传入就修改,将close-on-click-modal设置为false
  • 2.在对话框内写表单,和dataForm双向绑定,dataForm内有数据库全部字段;和dataRule双向绑定,用户名等不为空,手机号有特殊验证格式,通过ref直接访问dataForm dom元素,绑定回车即提交表单事件
  • 3.表单项:username、sex、phone、city、position、salary,均有label、prop属性
  • 4.表单项内username输入框,双向绑定dataForm的username,占位文本placeholder
  • 5.性别男女保密单选
  • 6.最后复制底部插槽 修改确定的点击事件为提交表单事件
  • 可以去element官网找寻自己需要的组件 点击进入element官网
    在这里插入图片描述
<template><el-dialog:title="!dataForm.id ? '新增' : '修改'":visible.sync="dialogVisible":before-close="handleClose":close-on-click-modal="false"><el-form:model="dataForm":rules="dataRule"ref="dataForm"@keyup.enter.native="dataFormSubmit()"><el-form-item label="用户名" prop="username"><el-inputv-model="dataForm.username"placeholder="请输入用户名"></el-input></el-form-item><el-form-item label="性别" prop="sex"><el-radio-group v-model="dataForm.sex"><el-radio label=""></el-radio> <el-radio label=""></el-radio> <el-radio label="保密"></el-radio></el-radio-group></el-form-item><el-form-item label="手机号" prop="phone"><el-inputv-model="dataForm.phone"placeholder="请输入手机号"></el-input></el-form-item><el-form-item label="所在城市" prop="city"><el-inputv-model="dataForm.city"placeholder="请输入所在城市"></el-input></el-form-item><el-form-item label="职位" prop="position"><el-inputv-model="dataForm.position"placeholder="请输入职位"></el-input></el-form-item><el-form-item label="工资" prop="salary"><el-input v-model="dataForm.salary" placeholder="请输入工资"></el-input></el-form-item></el-form><span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="dataFormSubmit()">确 定</el-button></span></el-dialog>
</template><script>
export default {data() {return {dialogVisible: false,dataForm: {id: 0,username: "",sex: "",phone: "",city: "",position: "",salary: "",},dataRule: {},};},methods: {handleClose(done) {this.$confirm('确认关闭?').then(_ => {done();}).catch(_ => {});},}
};
</script><style>
</style>

init方法

1.init(id)根据传入的id值,真则修改,假则为0新增,左上角的标题随之动态改变
2.判断完了设置弹出弹窗为true
3.弹出了再进行下一步操作$nextTick用resetFields把表单内的数据都置空
4.如果有id,则修改单条数据,先根据id查询单条数据,请求方式以及参数处理,then对把data数据放入表单,如果data存在且code恒等于0则进行修改this.dataForm.xxx=data.user.xxx
这里涉及到一个根据id查找返回用户信息的方法

  methods: {handleClose(done) {this.$confirm('确认关闭?').then(_ => {done();}).catch(_ => {});},init(id){this.dataForm.id=id||0;this.dialogVisible = true;this.$nextTick(()=>{this.$refs['dataForm'].resetFields();})if(this.dataForm.id){this.$http({url:this.$http.adornUrl(`/my/test/info/${this.dataForm.id}`),method:'get',}).then(({data})=>{if(data&&data.code===0){this.dataForm.username=data.user.username;this.dataForm.sex=data.user.sex;this.dataForm.phone=data.user.phone;this.dataForm.city=data.user.city;this.dataForm.position=data.user.position;this.dataForm.salary=data.user.salary;}})}}}

涉及到的info方法

    //根据id拿出用户信息@GetMapping("/info/{id}")public R info(@PathVariable Long id){User user = iUserService.getById(id);return R.ok().put("user",user);}

dataRule

1.不能为空:字段:[{required:true,message:“”,trigger:“blur”}]
2.手机号有特殊认证,再加一个{},在里面写验证函数validator: validateMobile
3.自定义函数validateMobile,验证规则对象rule,待验证的值value,回调函数用于通知验证结果callback
4.如果这个待验证的值不符合手机号格式(从另一个格式页面导入)就用回调函数返回一个错误消息,否则就通过验证,回调函数内什么也不写

<template><el-dialog:title="!dataForm.id ? '新增' : '修改'":visible.sync="dialogVisible":before-close="handleClose":close-on-click-modal="false"><el-form:model="dataForm":rules="dataRule"ref="dataForm"@keyup.enter.native="dataFormSubmit()"><el-form-item label="用户名" prop="username"><el-inputv-model="dataForm.username"placeholder="请输入用户名"></el-input></el-form-item><el-form-item label="性别" prop="sex"><el-radio-group v-model="dataForm.sex"><el-radio label=""></el-radio> <el-radio label=""></el-radio> <el-radio label="保密"></el-radio></el-radio-group></el-form-item><el-form-item label="手机号" prop="phone"><el-inputv-model="dataForm.phone"placeholder="请输入手机号"></el-input></el-form-item><el-form-item label="所在城市" prop="city"><el-inputv-model="dataForm.city"placeholder="请输入所在城市"></el-input></el-form-item><el-form-item label="职位" prop="position"><el-inputv-model="dataForm.position"placeholder="请输入职位"></el-input></el-form-item><el-form-item label="工资" prop="salary"><el-input v-model="dataForm.salary" placeholder="请输入工资"></el-input></el-form-item></el-form><span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="dataFormSubmit()">确 定</el-button></span></el-dialog>
</template><script>import { isMobile } from "@/utils/validate";
export default {data() {var valicatePhone=(rule,value,callback)=>{if(!isMobile(value)){callback(new Error('手机号格式错误,请重新输入'))}else{callback()}}return {dialogVisible: false,dataForm: {id: 0,username: "",sex: "",phone: "",city: "",position: "",salary: "",},dataRule: {username:[{required: true,message:'用户名不为空',trigger:'blur'}],phone:[{required: true,message:'手机号不为空',trigger:'blur'},{valivate:valicatePhone,trigger:'blur'}],city:[{required: true,message:'所在城市不为空',trigger:'blur'}],position:[{required: true,message:'职位不为空',trigger:'blur'}],salary:[{required: true,message:'薪水不为空',trigger:'blur'}],},};},methods: {handleClose(done) {this.$confirm('确认关闭?').then(_ => {done();}).catch(_ => {});},init(id){this.dataForm.id=id||0;this.dialogVisible = true;this.$nextTick(()=>{this.$refs['dataForm'].resetFields();})if(this.dataForm.id){this.$http({url:this.$http.adornUrl(`/my/test/info/${this.dataForm.id}`),method:'get',}).then(({data})=>{if(data&&data.code===0){this.dataForm.username=data.user.username;this.dataForm.sex=data.user.sex;this.dataForm.phone=data.user.phone;this.dataForm.city=data.user.city;this.dataForm.position=data.user.position;this.dataForm.salary=data.user.salary;}})}}}
};
</script><style>
</style>

dataFormSubmit

1.访问特定ref属性的dom元素dataForm并进行表单验证validate接收参数
2.如果验证成功,则发送请求,url内写一个三元表达式/xx/xx/${},和title的三元一样,没有id就save,有id就update,要用着重符号处理特殊字符,确保能发送请求,请求方式post要调用adornData传入数据对象,id要写一个逻辑或,是真的就取前面的值,假的就为undefined,其他全this.dataForm.xxx
3.then再处理data,如果存在且code恒等于0就发出提示信息,操作成功,关闭窗口的时候触发关闭事件,把标题重新设置为false,再用$emit方法触发刷新列表数据事件refreshDataList,否则显示data的错误信息

      dataFormSubmit() {this.$refs["dataForm"].validate((val) => {if (val) {this.$http({url: this.$http.adornUrl(`/my/test/${!this.dataForm.id ? "save" : "update"}`),method: "post",data: this.$http.adornData({id: this.dataForm.id || undefined,username: this.dataForm.username,sex: this.dataForm.sex,phone: this.dataForm.phone,city: this.dataForm.city,position: this.dataForm.position,salary: this.dataForm.salary,}),}).then(({ data }) => {if (data && data.code === 0) {this.$message({message: "操作成功",type: "success",onClose: () => {this.dialogVisible = false;this.$emit("refreshDataList");},});} else {this.$message.Error(data.msg);}});}});},

ttt-add-or-update.vue最终版

<template><el-dialog:title="!dataForm.id ? '新增' : '修改'":visible.sync="dialogVisible":close-on-click-modal="false":before-close="handleClose"><el-form:model="dataForm":rules="dataRule"ref="dataForm"@keyup.enter.native="dataFormSubmit()"><el-form-item label="用户名" prop="username"><el-inputv-model="dataForm.username"placeholder="请输入用户名"></el-input></el-form-item><el-form-item label="性别" prop="sex"><el-radio-group v-model="dataForm.sex"><el-radio label=""></el-radio><el-radio label=""></el-radio><el-radio label="保密"></el-radio></el-radio-group></el-form-item><el-form-item label="手机号" prop="phone"><el-inputv-model="dataForm.phone"placeholder="请输入手机号"></el-input></el-form-item><el-form-item label="所在城市" prop="city"><el-inputv-model="dataForm.city"placeholder="请输入所在城市"></el-input></el-form-item><el-form-item label="职位" prop="position"><el-inputv-model="dataForm.position"placeholder="请输入职位"></el-input></el-form-item><el-form-item label="工资" prop="salary"><el-input v-model="dataForm.salary" placeholder="请输入工资"></el-input></el-form-item></el-form><span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="dataFormSubmit()">确 定</el-button></span></el-dialog>
</template><script>
import { isMobile } from "@/utils/validate";
export default {data() {var validatePhone = (rule, value, callback) => {if (!isMobile(value)) {callback(new Error("手机号格式错误,请重新输入"));} else {callback();}};return {dataForm: {id: 0,username: "",sex: "",phone: "",city: "",position: "",salary: "",},dialogVisible: false,dataRule: {username: [{ required: true, message: "用户名不为空", trigger: "blur" },],phone: [{ required: true, message: "手机号不为空", trigger: "blur" },{ validator: validatePhone, trigger: "blur" },],city: [{ required: true, message: "所在城市不为空", trigger: "blur" }],position: [{ required: true, message: "职位不为空", trigger: "blur" }],salary: [{ required: true, message: "工资不为空", trigger: "blur" }],},};},methods: {handleClose(done) {this.$confirm("确认关闭?").then((_) => {done();}).catch((_) => {});},init(id) {this.dataForm.id = id || 0;this.dialogVisible = true;this.$nextTick(() => {this.$refs["dataForm"].resetFields();});if (this.dataForm.id) {this.$http({url: this.$http.adornUrl(`/my/test/info/${this.dataForm.id}`),method: "get",}).then(({ data }) => {if (data && data.code === 0) {(this.dataForm.username = data.user.username),(this.dataForm.sex = data.user.sex),(this.dataForm.phone = data.user.phone),(this.dataForm.city = data.user.city),(this.dataForm.position = data.user.position),(this.dataForm.salary = data.user.salary);} });}},dataFormSubmit() {this.$refs["dataForm"].validate((val) => {if (val) {this.$http({url: this.$http.adornUrl(`/my/test/${!this.dataForm.id ? "save" : "update"}`),method: "post",data: this.$http.adornData({id: this.dataForm.id || undefined,username: this.dataForm.username,sex: this.dataForm.sex,phone: this.dataForm.phone,city: this.dataForm.city,position: this.dataForm.position,salary: this.dataForm.salary,}),}).then(({ data }) => {if (data && data.code === 0) {this.$message({message: "操作成功",type: "success",onClose: () => {this.dialogVisible = false;this.$emit("refreshDataList");},});} else {this.$message.Error(data.msg);}});}});},},
};
</script><style>
</style>

至此Mysql+MybatisPlus+Vue实现基础增删改查CRUD已基本完善

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/657614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【乳腺肿瘤诊断分类及预测】基于Elman神经网络

课题名称&#xff1a;基于Elman神经网络的乳腺肿瘤诊断分类及预测 版本日期&#xff1a;2023-05-15 运行方式: 直接运行Elman0501.m 文件即可 代码获取方式&#xff1a;私信博主或QQ&#xff1a;491052175 模型描述&#xff1a; 威斯康辛大学医学院经过多年的收集和整理&a…

《Numpy 简易速速上手小册》第6章:Numpy 高级数组操作(2024 最新版)

文章目录 6.1 使用布尔索引和条件选取6.1.1 基础知识6.1.2 完整案例&#xff1a;筛选股市数据6.1.3 拓展案例 1&#xff1a;筛选健康数据6.1.4 拓展案例 2&#xff1a;筛选和替换 6.2 缺失数据和无效数据处理6.2.1 基础知识6.2.2 完整案例&#xff1a;气象数据处理6.2.3 拓展案…

突破瓶颈,提升开发效率:Spring框架进阶与最佳实践-IOC

IOC相关内容 1.1 bean基础配置1.1.1 bean基础配置(id与class)1.1.2 bean的name属性步骤1&#xff1a;配置别名步骤2:根据名称容器中获取bean对象步骤3:运行程序 1.1.3 bean作用范围scope配置1.1.3.1 验证IOC容器中对象是否为单例验证思路具体实现 1.1.3.2 配置bean为非单例1.1.…

k8s中调整Pod数量限制的方法

一、介绍 Kubernetes节点每个默认允许最多创建110个pod&#xff0c;有时可能由于主机配置扩容的问题&#xff0c;从而需要修改节点pod运行数量的限制。 即&#xff1a;需要调整Node节点的最大可运行Pod数量。 一般来说&#xff0c;只需要在kubelet启动命令中增加–max-pods参数…

以“美”为鉴,探寻香港比特币现货ETF的未来发展

出品&#xff5c;欧科云链研究院 作者&#xff5c;Hedy Bi 根据The Block于1月29日的报道&#xff0c;嘉实国际成为了首家向香港证监会提交比特币现货ETF申请的机构。早在去年12月22日&#xff0c;香港证监会发布了《有关证监会认可基金投资虚拟资产的通函》&#xff0c;明确…

华为云codeArts使用操作流程

一、开启服务 什么是华为云CodeArts&#xff1f; 本实验将在华为云CodeArts平台上搭建一个凤凰商城开发项目&#xff0c;并完成需求管理、代码仓库、代码检查、编译构建、发布、部署、流水线等软件开发操作。 1)新建项目 进入华为云“控制台”&#xff0c;鼠标移动到页面左侧菜…

使用“快速开始”将数据传输到新的 iPhone 或 iPad

使用“快速开始”将数据传输到新的 iPhone 或 iPad 使用 iPhone 或 iPad 自动设置你的新 iOS 设备。 使用“快速开始”的过程会同时占用两台设备&#xff0c;因此请务必选择在几分钟内都不需要使用当前设备的时候进行设置。 确保你当前的设备已连接到无线局域网&#xff0c;并…

【三维重建】运动恢复结构(SfM)

运动恢复结构是通过三维场景的多张图像&#xff0c;恢复出该场景的三维结构信息以及每张图片对应的摄像机参数。 欧式结构恢复(内参已知&#xff0c;外参未知) 欧式结构恢复问题&#xff1a; 已知&#xff1a;1、n个三维点在m张图像中的对应点的像素坐标 2、相机内参 求解&…

Qt之QLabel介绍

概述 QLabel是QT界面中的标签类&#xff0c;它从QFrame下继承&#xff0c;QLabel 类代表标签&#xff0c;它是一个用于显示文本或图像的窗口部件。我们主要介绍一下QLabel的一些简单的使用。 设置颜色背景色和字体的颜色大小 字体及颜色 设置文字使用的是setText函数。 QStri…

CSA发布 | 法律视角下的数据出境《2023年数据出境合规年鉴》

在全球数字产业以及大数据和云计算技术快速发展的背景下&#xff0c;数据流动对世界经济的影响日益显著。由此带来的数据红利和数据安全之间的冲突&#xff0c;将对未来数字经济的发展方向产生深刻影响。 2023 年可称为中国数据跨境监管的元年&#xff0c;这一年初出境评估的“…

算法:积木游戏学习数学

一、算法描述 小华和小微一起通过玩积木游戏学习数学。 他们有很多积木&#xff0c;每个积木块上都有一个数字&#xff0c;积木块上的数字可能相同。 小华随机拿一些积木挨着排成一排&#xff0c;请小微找到这排积木中数字相同且所处位置最远的2块积木块&#xff0c;计算他们的…

第六讲:函数扩展(static,extern)

今天讲讲两个关键字&#xff0c;在此之前&#xff0c;我们先介绍两个概念。 1.作用域&#xff1a;某变量可以使用的范围。 1.1局部变量的作用域&#xff1a;变量所在的局部范围。 1.2全局变量的作用域&#xff1a;整个工程 2.生命周期&#xff1a;变量从申请内存到被回收内…

高中数学:逻辑用语及量词

一、逻辑用语 充分条件与必要条件 充分必要条件的判断&#xff0c;本质就是判断两个集合之间是子集还是真子集的关系 要点&#xff1a;看清楚谁是条件P&#xff0c;谁是结论Q 二、逻辑量词 存在量词与全称量词 命题的真假 三、常见题型 1、已知充分必要性&#xff0c;求…

Vue+OpenLayers7入门到实战:OpenLayers7使用一张静态图片作为地图的基本底图,使用png图片作为地图底图示例

返回《Vue+OpenLayers7》专栏目录:Vue+OpenLayers7 前言 本章介绍如何使用OpenLayers7在地图上使用一张静态图片作为地图的基本底图。 本章主要用处在于如果我们项目没有vmts、vms、xyz等地图服务,只有一张静态图片,也可以作为地图基本图层使用。 二、依赖和使用 "o…

美国DDOS服务器:应对攻击的策略与技术

分布式拒绝服务(DDOS)攻击是一种常见的网络攻击手段&#xff0c;旨在通过大量无用的请求拥塞目标服务器&#xff0c;使其无法正常处理合法请求。美国作为全球互联网技术的领先者&#xff0c;其DDOS服务器在应对这类攻击时具有一系列先进的技术和策略。本文将详细介绍美国DDOS服…

Arrays.asList()方法调用add()或remove()抛出java.lang.UnsupportedOperationException问题

在使用Arrays.asList方法将以,分割的字符串转为list集合时&#xff0c;调用add和remove等方法时会抛出java.lang.UnsupportedOperationException。以下为原因和解决方法。 原因&#xff1a; Arrays.asList()方法返回了一个Arrays类的一个继承了AbstractList的ArrayList内部类…

ElementUI 组件:Layout布局(el-row、el-col)

ElementUI安装与使用指南 Layout布局 点击下载learnelementuispringboot项目源码 效果图 el-row_el-col.vue页面效果图 项目里el-row_el-col.vue代码 <script> export default {name:el-row_el-col 布局 }</script><template><div class"roo…

科微/金航标kinghelm一直在技术上不断创新

宋仕强说&#xff0c;萨科微slkor&#xff08;www.slkoric.com&#xff09;/金航标kinghelm&#xff08;www.kinghelm.net&#xff09;一直在技术上不断创新&#xff0c;并将这些新技术应用于公司的产品中&#xff0c;推出的新产品&#xff0c;这让我们比同行发展快一些&#x…

【环境配置】安装了pytorch但是报错torch.cuda.is_availabel()=Flase

解决思路&#xff1a;import torch正常&#xff0c;说明torch包安装正常&#xff0c;但是不能和gpu正常互动&#xff0c;猜测还是pytroch和cuda的配合问题 1.查看torch包所需的cuda版本 我的torch是2.0.1&#xff0c;在现在是比较新的包&#xff0c;需要12以上的cuda支持&…

04:容器技术概述|镜像与容器|docker配置管理

容器技术概述&#xff5c;镜像与容器&#xff5c;docker配置管理 什么是容器优点缺点 docker与容器跳板机yum源添加docker软件在node节点验证软件包开启路由转发 镜像管理&容器管理如何获取镜像镜像备份与恢复运行容器查看镜像的启动信息镜像管理命令容器管理命令容器内部署…