SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现

news2024/12/23 0:28:38

系列文章:
SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计
SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接
SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接

文章目录

    • 前端实现
    • 编写user.vue(整个`user.vue`代码已经放在文章最后)
      • 第一部分——搜索框
      • 第二部分——data表格
      • 第三部分——分页插件
    • 配置后端接口
    • 后端编写代码
    • user.vue

前端实现

之前自定义的user.vue页面为空白,现来实现其功能
在这里插入图片描述

先去element官网浏览需要的组件
官网链接: https://element.eleme.cn/2.13/#/zh-CN/component/dialog
版本:2.13.2
在这里插入图片描述

需要用到的组件:

  1. 卡片
    在这里插入图片描述
  2. 表格
    在这里插入图片描述
  3. 分页——完整功能
    在这里插入图片描述
  4. 输入框
    在这里插入图片描述
  5. 按钮
    在这里插入图片描述
  6. 打开表单的对话框
    在这里插入图片描述

编写user.vue(整个user.vue代码已经放在文章最后)

整体的页面分为3个部分,搜索——显示——分页插件
在这里插入图片描述

第一部分——搜索框

前端组件代码如下:
在这里插入图片描述

红色:绑定数据
黄色:绑定函数
白色:element自带的icon图标
在这里插入图片描述

  • 红色:
    在这里插入图片描述

  • 橙色:
    在这里插入图片描述
    在这里插入图片描述

  • 白色
    在这里插入图片描述

第二部分——data表格

在这里插入图片描述

  • 红色:绑定的数据列表变量
    在这里插入图片描述

  • 橙色,显示表格数据的序号,涉及到searchModel.pageNosearchModel.pageSize两个变量
    在这里插入图片描述

  • 白色:与后端的实体变量名保持一致
    在这里插入图片描述

第三部分——分页插件

在这里插入图片描述

  • 红色:更改插件的显示页数会再次查询数据库显示数据
    在这里插入图片描述
  • 橙色:分页插件的一些变量
    在这里插入图片描述
    至此,三个部分的前端介绍完毕

写上前端的钩子函数(页面加载自动取查询数据库然后显示)
在这里插入图片描述

配置后端接口

src\api新建一个userManage.js写上代码
在这里插入图片描述

import request from '@/utils/request'


export default{
  getUserList(searchModel){
    return request({
      url:'/user/list',
      method:'get',
      params:{    // 传给后端的参数
        pageNo: searchModel.pageNo,
        pageSize: searchModel.pageSize,
        username: searchModel.username,
        phone: searchModel.phone,
      }

    });
  },

}

然后去user.vue注册该文件
在这里插入图片描述

// 前后端对接的配置
import userApi from '@/api/userManage'

后端编写代码

UserController里面写对接前端的代码
在这里插入图片描述

// 增删改查,增:post请求,查:get请求,修改:put请求,删除:delete请求
@GetMapping("/list")
public Result<Map<String,Object>> getUserList(@RequestParam(value = "username",required = false) String username,
                                              @RequestParam(value = "phone",required = false) String phone,
                                              @RequestParam(value = "pageNo") Long pageNo,
                                              @RequestParam(value = "pageSize") Long pageSize
                                              ){

    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

    // 第一个参数是对username进行判空条件,第三个username是传过来进行比较的值
    wrapper.eq(StringUtils.hasLength(username),User::getUsername,username);
    wrapper.eq(StringUtils.hasLength(phone),User::getPhone,phone);

    // 苞米豆 里的Page包,不是Spring的,传入当前页数和每页大小
    Page<User> page = new Page<>(pageNo, pageSize);

    // 分页查找,用 .page()方法
    userService.page(page,wrapper);

    Map<String,Object> data = new HashMap<>();
    data.put("total",page.getTotal());
    data.put("rows",page.getRecords());

    return Result.success(data);
}

注意下图中红色部分与前端的userManage.js中红色部分需保持一致
在这里插入图片描述在这里插入图片描述


此处后端返回的数据名也需和前端保持一致
在这里插入图片描述
在这里插入图片描述

借助postman验证
在这里插入图片描述
此处返回一个json对象,里面有codemessagedata字段,而且data中有totalrows字段

前端user.vue中代码 this.total = response.data.total;就是获取该data中的total数据

新增Mybatis-Plus的分页配置代码:在config\下新增MpConfig文件
在这里插入图片描述

package com.ums.config;

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


// 官网地址 https://baomidou.com/pages/2976a3/#spring
@Configuration
public class MpConfig {
    //配置 mybatis plus的分页插件,死代码
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

user.vue

<template>
  <div>
    <!-- 搜索栏 -->
    <el-card id="search">

      <el-row>
        <el-col :span="20">
          <el-input v-model="searchModel.username" placeholder="用户名" clearable></el-input>
          <el-input v-model="searchModel.phone" placeholder="电话" clearable></el-input>
          <el-button @click="getUserList" type="primary" round icon="el-icon-search">查询</el-button>
        </el-col>

        <el-col :span="4" align="right">
          <el-button @click="openEditUI" type="primary" icon="el-icon-plus" circle></el-button>
        </el-col>
      </el-row>

    </el-card>

    <!-- 结果列表 -->
    <el-card>
      <el-table :data="userList" stripe style="width: 100%">
        <el-table-column  label="#" width="80">
          <template slot-scope="scope">
            <!-- (pageNo-1) * pageSize + index + 1 -->
            {{(searchModel.pageNo-1) * searchModel.pageSize + scope.$index + 1}}
          </template>
        </el-table-column>
        <el-table-column prop="id" label="用户ID" width="180">
        </el-table-column>
        <el-table-column prop="username" label="用户名" width="180">
        </el-table-column>
        <el-table-column prop="phone" label="电话" width="180">
        </el-table-column>
        <el-table-column prop="email" label="电子邮件">
        </el-table-column>
        <el-table-column label="操作" width="180">
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 分页插件 -->
    <el-pagination 
    @size-change="handleSizeChange" 
    @current-change="handleCurrentChange"
      :current-page="searchModel.pageNo" 
      :page-sizes="[5, 10, 20, 30, 40]" 
      :page-size="searchModel.pageSize"
      layout="total, sizes, prev, pager, next, jumper" 
      :total="total">
    </el-pagination>


    <!-- 用户信息编辑对话框 -->
    <!-- :title 加了冒号就变成一个变量,属性绑定了,后面的东西需要在data中说明 -->
    <el-dialog @close="clearForm" :title="title" :visible.sync="dialogFormVisible">
      <el-form :model="userForm">
        <el-form-item label="用户名" :label-width="formLabelWidth">
          <el-input v-model="userForm.username" autocomplete="off"></el-input>
        </el-form-item>

        <el-form-item label="登录密码" :label-width="formLabelWidth">
          <el-input type="password" v-model="userForm.password" autocomplete="off"></el-input>
        </el-form-item>

        <el-form-item label="联系电话" :label-width="formLabelWidth">
          <el-input v-model="userForm.phone" autocomplete="off"></el-input>
        </el-form-item>

        <el-form-item label="用户状态" :label-width="formLabelWidth">
          <el-switch v-model="userForm.status" 
            :active-value="1"
            :inactive-value="0"
            active-color="#13ce66" 
            inactive-color="#ff4949">
          </el-switch>
        </el-form-item>

        <el-form-item label="电子邮件" :label-width="formLabelWidth">
          <el-input v-model="userForm.email" autocomplete="off"></el-input>
        </el-form-item>
        
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
      </div>
    </el-dialog>


  </div>
</template>

<!-- 定义查询对象 -->
<script>
  // 前后端对接的配置
  import userApi from '@/api/userManage'

  // 页面变量
  export default {
    data () {
      return {
        formLabelWidth: '130px',
        userForm: {},
        dialogFormVisible: false,
        title: "",
        total: 0,
        searchModel: {    // 当前页面参数,会调用方法传给后端
          pageNo: 1,
          pageSize: 5
        },
        userList: [],
      }
    },

    methods: {
      clearForm(){
        // 清空表单
        this.userForm={}
      },

      openEditUI(){
        this.title = '新增用户';
        this.dialogFormVisible = true;
      },

      // 此处对应pageSize和pageNo改变时更改前端的显示
      handleSizeChange(pageSize){
        // 更新数据,完毕后重新调用函数
        this.searchModel.pageSize = pageSize;
        this.getUserList(); 
      },

      handleCurrentChange(pageNo){
        // 更新数据,完毕后重新调用函数
        this.searchModel.pageNo = pageNo;
        this.getUserList(); 
      },
      getUserList(){
        // userApi.getUserList 开始调用后端,并传递参数searchModel
        // then表示后端查询后返回的数据
        userApi.getUserList(this.searchModel).then(response=>{
          this.userList = response.data.rows;   // 后端返回的 json中的字段
          this.total = response.data.total;
        });
      }
    },

    // 钩子函数定义处
    created(){
      // 定义了一个钩子函数,即加载页面后就自动执行getUserList函数,显示数据
      this.getUserList();
    },

  }
</script>


<style>
  #search .el-input {
    width: 200px;
    margin-right: 10px;
  }
  .el-dialog .el-input{
    width: 85%;
  }
</style>

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

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

相关文章

微服务: sleuth和zipkin的用处与zipkin安装使用(下)

目录 0. 上篇传送门: 1. 前言简介 mq安装传送门: 微服务: 01-rabbitmq的应用场景及安装(docker) 1.1 Sleuth是一款分布式跟踪解决方案。 1.2 Zipkin是一个开源的分布式跟踪系统。 2. zipkin安装方式 2.1 windows下安装zipkin: 2.1.0 下载jar包位置 2.1.1 下载后,找…

数值计算例题整理

数值计算 一、误差的来源和分类二、有效数字第一个大题&#xff08;非线性方程组的迭代法&#xff09;第二个大题&#xff08;LU分解&#xff09;第三个大题&#xff08;牛顿插值法&#xff09;第四个大题&#xff08;直线拟合&#xff09; 一、误差的来源和分类 误差是描述数…

Git 原理和使用

Git 安装 Git是开放源代码的代码托管⼯具&#xff0c;最早是在Linux下开发的。开始也只能应⽤于Linux平台&#xff0c;后⾯慢慢的被移植到windows下&#xff0c;现在&#xff0c;Git可以在Linux、Unix、Mac和Windows这⼏⼤平台上正常运⾏了。 Linux-centos 安装git sudo yu…

8.3 PowerBI系列之DAX函数专题-矩阵Matrix中高亮显示最大最小值

需求 用颜色标量年度最大最小值 用颜色标示折线的最大值最小值 实现 在条件格式–规则–基于字段进行计算 度量值 is_max_min var displayed_data calculatetable( addcolumns( summarize(‘订单表’&#xff0c;‘产品表’[商品次级类别]&#xff0c;‘订单表’[订单日…

arcgis栅格影像裁剪--shp

1、打开软件&#xff0c;导入数据&#xff0c;如下&#xff1a; 2、裁剪面形状如下&#xff0c;为shp文件&#xff1a; 3、在arctoolbox中找到"数据管理工具"--"栅格"--"栅格处理"--"裁剪"工具&#xff0c;如下&#xff1a; 4、打开裁…

(ESP32)报错-portTICK_RATE_MS‘ undeclared

&#xff08;ESP32&#xff09;报错-portTICK_RATE_MS undeclared 问题详情ESP- IDF未正确设置 问题详情 报错提示 portTICK_RATE_MS undeclared (first use in this function); did you mean portTICK_PERIOD_MS?具体情况 已经引用相关头文件&#xff0c;并且右键后可以大概…

leetcode 2462. Total Cost to Hire K Workers(雇用 K 名员工的总成本)

每次从 开头candidates个 和 末尾candidates个 工人中选择一个cost最小的。 如果有2个工人cost相同&#xff0c;就选index较小的。 每个工人的cost在数组costs里。 直到雇够k个工人。 问雇k个工人需要多少cost. 思路&#xff1a; 可以考虑用一个优先队列&#xff0c;按cost排…

2023开放原子全球开源峰会——一场开发者的盛宴

文章目录 上午场下午场开发者之夜 #“2023我在开源峰会”特别征文# 2023开放原子全球开源峰会&#xff0c;6月11日-13日在北京盛大召开&#xff0c;开幕第一天正好是周六&#xff0c;没什么事情&#xff0c;一大早就过去了&#xff0c;早晨大概7点出发&#xff0c;公交、地铁一…

Docker Desktop 安装使用教程

一、前言 作为开发人员&#xff0c;在日常开发中&#xff0c;我们需要在本地去启动一些服务&#xff0c;如&#xff1a;redis、MySQL等&#xff0c;就需要去下载这些在本地去启动&#xff0c;操作较为繁琐。此时&#xff0c;我们可以使用Docker Desktop&#xff0c;来搭建我们需…

php+mysql期末作业小项目

目录 1、登录界面 2、注册界面 3、主界面 4、学生表界面 5 、查询学生界面​编辑 6、修改学生信息界面​编辑 7、删除学生信息界面 8、添加学生信息界面 9、后台数据库​编辑 一个简单的php➕mysql项目学生信息管理系统&#xff0c;用于广大学子完成期末作业的参考&…

Android Studio导入flutter项目,运行和调试按钮灰色

描述&#xff1a;用android Studio导入flutter项目&#xff0c;运行和调试按钮无法点击并置灰&#xff0c;显示如下 解决方法&#xff1a;检查是否设置如下内容&#xff1a; 1.是否配置了Android SDK &#xff0c;打开 file > project Structure >project 2.是否配置了F…

【架构】领域驱动设计(DDD)的几种典型架构介绍

文章目录 前言一、专业术语二、架构演变三、限界上下文四、领域驱动设计的四重边界五、整洁分层架构六、六边形架构七、洋葱架构总结 前言 我们生活中都听说了DDD&#xff0c;也了解了DDD&#xff0c;那么怎么将一个新项目从头开始按照DDD的过程进行划分与架构设计呢&#xff…

【Web自动化测试】如何生成高质量的测试报告

运行了所有测试用例&#xff0c;控制台输入的结果&#xff0c;如果很多测试用例那也不能够清晰快速的知道多少用例通过率以及错误情况。 web自动化测试实战之批量执行测试用例场景: 运行 AllTest.py 文件后得到的测试结果不够专业&#xff0c;无法直观的分析测试结果,我们能否…

如何学习和提高CAPL语言编程能力

CAPL是Vector公司开发的&#xff0c;用来配合它的系列产品使用的一款面向过程的语言。CAPL是Communication Access Programming Language的缩写&#xff0c;从字面意思来说&#xff0c;是专门用于通信访问的编程语言。 最初访问CAN总线&#xff0c;现在已扩展到所有的汽车总线…

代理模式(Proxy)

定义 代理是一种结构型设计模式&#xff0c;让你能够提供对象的替代品或其占位符。代理控制着对于原对象的访问&#xff0c;并允许在将请求提交给对象前后进行一些处理。 前言 1. 问题 举个例子&#xff1a;有这样一个消耗大量系统资源的巨型对象&#xff0c; 你只是偶尔需…

mac部署fastadmin踩坑记录

粘贴一下解决配置&#xff0c;主要Nginx配置问题 //后台NGINX location / {if (!-e $request_filename) {rewrite ^(.?\.php)(/.)$ /$1?s$2 last;# 加上这一句配置试试rewrite ^(.*)$ /ewgadmin.php?s$1 last; # 对应项目修改对应入口文件break;}}//接口文档Nginx配置 loca…

sql server还原新数据库,解决原库还原中...

1&#xff09;用studyDB库&#xff0c;备份出数据库备份文件 studyDB_backup_2023_06_19.bak 2&#xff09;用备份文件 studyDB_backup_2023_06_19.bak还原数据新库CollegeStudyDB和原库studyDB到同一服务器 3&#xff09;数据库CollegeStudyDB按原成功&#xff0c;但是原库s…

Linux环境准备以及CentOS7.6系统安装

&#xff08;该图由AI绘制 本人提供教学 FREE&#xff09; 运维概述与Linux系统安装 一、VMware虚拟机 1、什么是虚拟机 其实虚拟机就是在Windows的真机上创建一个独立的其他操作系统的运行环境而且其对宿主机&#xff08;Windows&#xff09;没有任何影响。 2、虚拟机的种…

《操作系统》by李治军 | 实验7 - 地址映射与共享

目录 一、实验目的 二、实验内容 &#xff08;一&#xff09;跟踪地址翻译过程 &#xff08;二&#xff09;基于共享内存的生产者—消费者程序 &#xff08;三&#xff09;共享内存的实现 三、实验准备 1. Linux 中的共享内存 2. 获得空闲物理页面 3. 地址映射 4. 寻…

TS学习笔记——模块

模块 module 模块&#xff1a;在自身的作用域里执行&#xff0c;不是在全局作用域中&#xff0c;若是外部想要使用需要导入导出。 好处&#xff1a;1、提高了代码的复用性 2、解决命名冲突 3、提高代码的可维护性 模块导入导出&#xff1a;export &#xff08;interface…