前后端实现增删改查

紧接着上一次的博客,我们接下来实现增加、删除、批量删除、分页查询、模糊查询、编辑功能,页面样式效果如下:

1.分页查询和模糊查询

分页器样式代码如下:

html 复制代码
    <div class="block" style="margin: 20px 0px;">
      <el-pagination
          @current-change="handlerCurrentChange"
          :current-page="pageNum"
          :page-size="pageSize"
          layout="total, prev, pager, next"
          :total="total">
      </el-pagination>
    </div>

我们来分析下上面的代码:

复制代码
@current-change="handlerCurrentChange"  @current-change表示当前页码数改变之后就会触发绑定的函数handlerCurrentChange,函数如下:
javascript 复制代码
handlerCurrentChange(pageNum){
      this.pageNum = pageNum
      this.load()
    },
复制代码
load()函数里封装的是分页查询的请求,如下,这个代码我们等会介绍
javascript 复制代码
//分页查询的请求
    load(pageNum){
      if (pageNum){
        this.pageNum = pageNum
      }
      request.get('/user/selectByPage',{
        params:{
          pageNum:this.pageNum,
          pageSize:this.pageSize,
          name:this.name,
        }
      }).then(res =>{
        this.users = res.data.records
        this.total = res.data.total
      })
    },
复制代码
:current-page="pageNum"  表示当前页码数,pageNum是我们自定义的变量,他的初始值我们给他赋成1,表示从第一页开始,至于为什么他会改变呢?答案在上面的那部分代码,通过handlerCurrentChange函数,我们获取到了前端页码数,然后再将这个值传给自定义的pageNum,然后再将这个pageNum与:current-page属性进行双向绑定,这样就能动态改变页码数
复制代码
:page-size="pageSize" 表示每页显示的数据个数,pageSize是我们自定义的变量,我在这给他定义的是7,表示每页展示7条数据
复制代码
layout="total, prev, pager, next"表示分页页面的布局
  • total表示总页数
  • prev表示上一页的按钮或者链接
  • pager表示页码列表,用户可以根据列表来切换页面
  • next表示下一页的按钮或者链接
复制代码
:total="total表示总页数,total是我们自定义的变量,初始值赋为0,之后在分页请求的回调函数中将后端返回来的总数据量赋值给total

讲完了这些属性的作用之后,我们再来重点看下load()这个发送分页请求的函数,其实触发这个函数的入口有两个,第一个 是在create钩子函数中触发 ,当页面在加载的时候就发送分页查询的请求,第二个 是在进行模糊查询的时候,当用户点击查询按钮之后触发,一般在网页功能里,模糊查询和分页查询是不分开的,当进行完模糊查询之后,还得要进行分页查询才能将搜索的数据渲染出来,模糊查询样式如下:

html 复制代码
    <div>
      <el-input placeholder="查询用户名" style="width: 250px" size="small" v-model="name"></el-input>
      <el-button type="primary" size="small" style="margin-left: 10px" @click="load(1)">查 询</el-button>
      <el-button type="danger" size="small" style="margin-left: 10px" @click="reset">重 置</el-button>
    </div>

接下来着重讲一下load()函数

reset()函数,具有重置功能


接下来看下后端是怎么实现的,首先是引入mybatisplus的依赖

XML 复制代码
        <!--MybatisPlus-SpringBoot-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.5</version>
        </dependency>

然后引入官方提供的分页查询的插件

java 复制代码
package com.kuang.common;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.kuang.mapper")
public class MybatisPlusConfig {

    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加
        //interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbType
        return interceptor;
    }
}

改造mapper层和service层,这里就略了,可以看看往期的博客,里面有讲到,下面是分页查询的controller层

java 复制代码
@GetMapping("/selectByPage")
    public Result selectByPage(@RequestParam("pageNum") Integer pageNum,@RequestParam("pageSize") Integer pageSize,@RequestParam("name") String name){
        //构造分页查询器
        Page<User> pageInfo = new Page<>(pageNum,pageSize);
        //构造条件查询器
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //添加一个排序条件
        wrapper.orderByAsc("id");
        //添加模糊查询
        wrapper.like(StringUtils.isNotBlank(name),"name",name);
        //执行查询
        userService.page(pageInfo, wrapper);
        //返回数据
        return Result.success(pageInfo);
    }

2.新增和编辑

为什么要把这两个功能放在一起讲呢?因为这两个功能,在前端中用的是同一个函数来向后端来传递数据,编辑按钮和新增按钮如下:

html 复制代码
          
  <template v-slot="scope">
     <el-button @click="handleEdit(scope.row)" type="primary" size="small" plain >编辑</el-button>
  </template>
html 复制代码
    <div style="margin: 10px 0px">
      <el-button @click="handleAddPatient" size="small" type="primary" plain>新 增</el-button>
    </div>

下面是这两个按钮绑定的click函数,这两个函数都是用来打开编辑和新增用户的弹窗

javascript 复制代码
    //编辑用户(打开弹窗)
    handleEdit(row){
      this.title = '编辑用户'
      //将信息深拷贝到addPatientInfo中(用于回显数据)
      this.addPatientInfo = JSON.parse(JSON.stringify(row))
      //打开弹窗
      this.addPatient = true
    },
    //新增用户(打开弹窗)
    handleAddPatient(){
      this.title = '新增用户'
      //初始化,并设置性别为男
      this.addPatientInfo = {gender:'男'}
      //让表单显现
      this.addPatient = true
    },

弹窗样式如下:

html 复制代码
      <div>
        <el-dialog  :title="title" :visible.sync="addPatient" style="width: 100%">
          <el-form :model="addPatientInfo" label-width="80px" ref="patientRef">
            <el-form-item label="姓名" prop="name">
              <el-input  v-model="addPatientInfo.name" autocomplete="off" placeholder="请输入姓名"></el-input>
            </el-form-item>
            <el-form-item label="用户名" prop="username">
              <el-input  v-model="addPatientInfo.username" autocomplete="off" placeholder="请输入用户名"></el-input>
            </el-form-item>
            <el-form-item label="病房" prop="address">
              <el-input  v-model="addPatientInfo.address" autocomplete="off" placeholder="请输入病房"></el-input>
            </el-form-item>
            <el-form-item label="症状" prop="symptom">
              <el-input type="textarea" v-model="addPatientInfo.symptom" autocomplete="off" placeholder="请输入症状"></el-input>
            </el-form-item>
            <el-form-item label="性别">
              <el-radio-group v-model="addPatientInfo.gender">
                <el-radio label="男"></el-radio>
                <el-radio label="女"></el-radio>
              </el-radio-group>
            </el-form-item>
          </el-form>
          <!--      09-->
          <div slot="footer" class="dialog-footer">
            <el-button @click="addPatient = false">取 消</el-button>
            <el-button type="primary" @click="submitInfo">确 定</el-button>
          </div>
        </el-dialog>
      </div>
复制代码
:visible.sync="addPatient"  用来控制弹窗的可见性,addPatient是自定义的变量,一开始赋值为false表示这个弹窗不显示,当点击编辑或者新增按钮后,再将这个值改成true
复制代码
autocomplete="off"  用来控制浏览器自动填充功能,off表示关闭这个功能

当点击弹窗里的确定按钮后,就会触发点击函数submitInfo,注意,编辑和新增功能用的弹窗是同一个,所以这个点击函数也是同一个,那么我们重点来看看,在同一个函数中是怎么区分这两个功能从而发送不同的请求的

javascript 复制代码
//新增用户和编辑用户请求发送
    submitInfo(){
      //提交请求
      this.$refs["patientRef"].validate((valid) => {
        if (valid){
          console.log(this.addPatientInfo)
          this.request({
            //有id就是更新,没有就是新增
            method:this.addPatientInfo.id ? 'PUT' : 'POST',
            url:this.addPatientInfo.id ? '/user/update' : '/user/add',
            data: this.addPatientInfo,
          }).then(res => {
            if (res.code === '200'){
              this.$message.success("保存成功")
              //增加用户之后,再次调用分页查询,并将页数置为1
              this.load(1)
              //关闭弹窗
              this.addPatient = false
            }else {
              this.$message.error(res.msg)
            }
          })
        }
      })
    },

答案是用id来区分,当addPatientInfo中携带的有id,那么就是编辑功能,没有id就是新增功能,在点击编辑按钮后的点击函数会获取当前行对象的数据,并且赋值给了addPatientInfo,这样这个变量里就有了id,而点击新增按钮后,并没有这个过程
后端添加用户的controller接口如下

java 复制代码
  /**
     * 新增用户
     * @param user
     * @return
     */
    @PostMapping("/add")
    public Result addUser(@RequestBody User user){
        userService.save(user);
        return Result.success();
    }

在service实现类中重写了一下save方法,如下

重写sava方法里主要完成了如果有重名的情况,那么就要给前端返回信息,并且还要给用户添加一个初始密码

java 复制代码
    /**
     * 重写save方法
     * @param entity
     * @return
     */
    @Override
    public boolean save(User entity) {
        //先拿这个name去查数据库,如果有重名的话就抛异常
        //添加条件查询器
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //添加条件(select * from patient where username = #{username})
        wrapper.eq("username",entity.getUsername());
        List<User> users = userMapper.selectList(wrapper);

        if (!users.isEmpty()){
            System.out.println(users);
            throw new ServiceException("用户名重复");
        }
        //如果添加的用户password为空,则手动添加初始密码
        if (StringUtils.isBlank(entity.getPassword())){
            System.out.println("密码为空");
            entity.setPassword("123456789");
        }
        return super.save(entity);
    }
相关推荐
熊的猫37 分钟前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
mosen8681 小时前
Uniapp去除顶部导航栏-小程序、H5、APP适用
vue.js·微信小程序·小程序·uni-app·uniapp
别拿曾经看以后~2 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
川石课堂软件测试2 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
JerryXZR3 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
problc3 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
Gavin_9153 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼4 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
待磨的钝刨5 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
Devil枫8 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试