SpringBoot集成Vue3实现的系统(一)

学习目标:SpringBoot2+Vue3+MP图文摘录(一)

提示:SpringBoot2与Vue3的小练习图文摘录

高能提示:

  • 三篇文章带你更熟悉掌握前后端分离的基本实现

一、vue的基本环境搭建

新建项目vue3-springboot
  • 1、安装axios、element-plus等必须的依赖即可
  • 2、其他的插件应用
修改App.vue
<template>
  <div>
    <router-view/>
  </div>
</template>
<script>
export default{
  name:"App"
}  
</script>

<style>

</style>
src/main.js基本的引入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from  'element-plus/es/locale/lang/zh-cn'

// 引入icon的js文件
import elementIcon from './plugins/icon'

import '@/assets/css/global.css'

createApp(App).use(store).use(router).use(ElementPlus,{locale:zhCn}).use(elementIcon).mount('#app')
全局的css样式【新建css文件夹并新建global.css文件】
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}
引入element-plus中的图标(在src下新建plugins文件夹并新建icon.js文件):
// 如果您正在使用CDN引入,请删除下面一行。
import * as components from '@element-plus/icons-vue'
export default{
   install:(app)=>{
    for (const key in components) {
      const componentConfig=components[key];
      app.component(componentConfig.name,componentConfig);
    }
   }
}
在utils目录下存放封装的请求js文件:
import axios from "axios";

//声明一个后端的父路径
const server="http://localhost:8888/";

/*
  async  异步处理
  await  等待处理完成 
*/
async function getData(url,param){
  var ret="";
  await axios.get(server+url,{params:param}).then(function(res){
      ret=res.data;
  });
  return ret;
}

/*
  post带有请求体传输数据【json格式的数据】
  async  异步处理
  await  等待处理完成 
*/
async function postData(url,param){
  var ret="";

  //设置axios的参数
  var options={
    url:server+url,
    method:"post",
    data:param
  }

  await axios(options).then(function(res){
      ret=res.data;
  });
  return ret;
}

/*
  post带有表单传输数据【url?name=value&name2=value2格式】
  async  异步处理
  await  等待处理完成 
*/
async function postDataForm(url,param){
  var ret="";

  //设置axios的参数
  var options={
    url:server+url,
    method:"post",
    data:param,
    headers:{'Content-Type':'application/x-www-form-urlencoded'}
  }

  await axios(options).then(function(res){
      ret=res.data;
  });
  return ret;
}


/*
  post带有文件域传输数据【file格式】
  async  异步处理
  await  等待处理完成 
*/
async function uploadFile(url,param){
  var ret="";

  //设置axios的参数
  var options={
    url:server+url,
    method:"post",
    data:param,
    headers:{
      'Content-Type':'multipart/form-data'
    }
  }

  await axios(options).then(function(res){
      ret=res.data;
  });
  return ret;
}


//如果需要在其他引入当前js的vue中使用需要导出
// export  导出变量、函数
export {getData,postData,postDataForm,uploadFile}
在router目录下的index.js中进行引入首页:
import { createRouter, createWebHashHistory } from 'vue-router'
import Layout from '../layout/Layout.vue'

const routes = [
  {
    path: '/',
    name: 'layout',
    component: Layout
  },
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router
在src下新建layout文件夹并新建Layout.vue文件:
<template>
    <div>
        <!-- 头部 -->
        <Header></Header>
        <div style="display:flex;">
          <!-- 侧边导航啦 -->
          <Aside></Aside>  
          <!-- 内容区域 -->
          <router-view style="flex:1;"></router-view>
        </div>
    </div>
</template>

<script>

import Header from '@/components/Header.vue'
import Aside from '@/components/Aside.vue'

export default {
  name:"Layout",
  components:{
    Header,
    Aside
  }

}
</script>

<style>

</style>
在components文件夹下新建Header.vue和Aside.vue文件:
<template>
    <div 
    style="height:50px;line-height:50px;
    border-bottom:solid 1px darkcyan;display: flex;">
    <div style="width: 200px;padding-left:30px;font-weight:bold;color:deepskyblue;">
      XX后台管理系统
    </div>
    <div style="flex:1;"></div>
    <div style="width:100px;padding-right:30px;padding-top:20px;">
      <el-dropdown>
    <span class="el-dropdown-link">
      管理员
      <el-icon class="el-icon--right">
        <arrow-down />
      </el-icon>
    </span>
    <template #dropdown>
      <el-dropdown-menu>
        <el-dropdown-item>个人信息</el-dropdown-item>
        <el-dropdown-item>修改密码</el-dropdown-item>
        <el-dropdown-item>注销登录</el-dropdown-item>
      </el-dropdown-menu>
    </template>
  </el-dropdown>
    </div>
    </div>
</template>

<script>
export default {
  name:"Header"
}
</script>

<style>

</style>
<template>
  <div>
    <el-col :span="12">
      <el-menu style="width:220px;min-height:100vh;"
        default-active="2"
        router
        class="el-menu-vertical-demo"
        @open="handleOpen"
        @close="handleClose"
      >
        <el-sub-menu index="1">
          <template #title>
            <el-icon><location /></el-icon>
            <span>用户管理</span>
          </template>
          <el-menu-item index="/home">用户列表</el-menu-item>
          <el-menu-item index="1-2">禁用用户</el-menu-item>
        </el-sub-menu>
        <el-sub-menu index="2">
          <template #title>
            <el-icon><location /></el-icon>
            <span>书籍管理</span>
          </template>
          <el-menu-item index="/book">书籍列表</el-menu-item>
          <el-menu-item index="2-2">下架书籍</el-menu-item>
        </el-sub-menu>
        <el-menu-item index="3">
          <el-icon><document /></el-icon>
          <span>公告管理</span>
        </el-menu-item>
        <el-menu-item index="4">
          <el-icon><document /></el-icon>
          <span>订单管理</span>
        </el-menu-item>
        <el-menu-item index="5">
          <el-icon><setting /></el-icon>
          <span>个人信息</span>
        </el-menu-item>
      </el-menu>
    </el-col>
  </div>

</template>

<script>
export default {
  name:"Aside"
}
</script>

<style>

</style>
修改router目录下的index.js文件内容【路由处理】:
在view目录下新建UserHome.vue文件:
<template>
    <div>
        <h1>用户列表页面</h1>
        <!-- 表格数据渲染用户列表信息 -->
        <el-table :data="tableData" style="width: 100%">
          <el-table-column prop="id" label="用户ID" width="180" />
          <el-table-column prop="username" label="用户名" width="180" />
          <el-table-column prop="nickname" label="昵称" />
          <el-table-column prop="sex" label="性别" />
          <el-table-column prop="address" label="地址" />
          <el-table-column fixed="right" label="操   作" width="300">
              <el-button type="success" size="small">
                  查看
              </el-button>
              <el-button type="danger" size="small">
                  删除
              </el-button>
              <el-button type="primary" size="small">
                  编辑
              </el-button>
          </el-table-column>
       </el-table>
    </div>
</template>

<script>
import {getData} from "../utils/remote";

export default {
  name:"UserHome",
  data(){
    return{
      tableData:[]
    }
  },
  created(){
    this.load();
  },
  methods:{
    load(){
        getData("users/loadAll").then(res=>{
          console.log(res);
          this.tableData=res.data;
        });
    }
  }
}
</script>

<style>

</style>
预览基本的效果:

在这里插入图片描述

二、搭建基础的后台进行请求处理

基于maven构建一个springboot2+mp的后台应用:
pom.xml文件的基础依赖坐标:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.xuguoguo</groupId>
    <artifactId>springboot2-vue3-mp</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot2-vue3-mp</name>
    <description>springboot2-vue3-mp</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.7.6</spring-boot.version>
    </properties>
    <dependencies>


        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.9</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.xuguoguo.Springboot2Vue3MpApplication</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
创建用户信息表:
CREATE TABLE `t_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户的主键编号',
  `username` varchar(255) DEFAULT NULL COMMENT '用户名',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  `nickname` varchar(255) DEFAULT NULL COMMENT '昵称',
  `sex` varchar(255) DEFAULT NULL COMMENT '性别',
  `address` varchar(255) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
通过MybatisX插件生成对应的三层代码:

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

基础的配置文件和类对象
1、配置文件application.yml
server:
  port: 8888
  tomcat:
    uri-encoding: UTF-8
    threads:
      max: 200


 数据源配置
spring:

  # 数据源配置
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/2103cloud
    username: root
    password: 123
    type: com.alibaba.druid.pool.DruidDataSource

  main:
    banner-mode: off # 关闭springboot启动图标
# 开启日志
mybatis-plus:
  global-config:
    db-config:
      id-type: auto #默认值
      logic-delete-field: deleted # 逻辑删除的字段
      logic-not-delete-value: 0 # 逻辑删除的字面值:未删除为0
      logic-delete-value: 1  # 逻辑删除的字面值:未删除为1
    banner: off # 关闭mybatisPlus的启动图标
  #      table-prefix: tb_ #统一配置数据标的前缀



  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true
    cache-enabled: false #  默认的全局的缓存为true
  #  config-location: classpath:mybatis-config.xml
  type-aliases-package: com.xuguoguo.entity
  mapper-locations: classpath*:mappers/*.xml

# 查看sql语句的日志
#  日志记录
logging:
  level:
    com.xuguoguo: debug
    org.springframework: info
通用的返回的结果类对象:
package com.xuguoguo.commons;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 统一返回对象
 */

@Data
@NoArgsConstructor
public class Result<T> implements Serializable {
    /**
     * 通信数据
     */
    private T data;
    /**
     * 通信状态
     */
    private boolean flag = true;
    /**
     * 通信描述
     */
    private String msg = "操作成功";

    /**
     * 通过静态方法获取实例
     */
    public static <T> Result<T> of(T data) {
        return new Result<>(data);
    }

    public static <T> Result<T> of(T data, boolean flag) {
        return new Result<>(data, flag);
    }

    public static <T> Result<T> of(T data, boolean flag, String msg) {
        return new Result<>(data, flag, msg);
    }


    private Result(T data) {
        this.data = data;
    }

    private Result(T data, boolean flag) {
        this.data = data;
        this.flag = flag;
    }

    private Result(T data, boolean flag, String msg) {
        this.data = data;
        this.flag = flag;
        this.msg = msg;
    }

}
跨域的配置类:
package com.xuguoguo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 @Package: com.xuguoguo.config
 @ClassName: CorsConfig
 @Author: XuGuoGuo
 @CreateTime: 2023/12/5-16:09
 @Description:
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {


    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //设置允许跨域的路径
        registry.addMapping("/**")
                //设置允许跨域请求的域名
                .allowedOriginPatterns("*")
                //是否允许cookie
                .allowCredentials(true)
                //设置允许请求的方式
                .allowedMethods("*")
//                .allowedMethods("GET","POST","DELETE","PUT");
                //设置允许的header请求头的属性
                .allowedHeaders("*")
                //设置允许跨域的时间
                .maxAge(3600);

    }
}
MybatisPlus的分页插件配置类:
package com.xuguoguo.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;

/**
 @Package: com.xuguoguo.config
 @ClassName: MybatisPlusConfig
 @Author: XuGuoGuo
 @CreateTime: 2023/12/13-8:36
 @Description:
 */
@Configuration
public class MybatisPlusConfig {

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

}
用户控制器编写:
package com.xuguoguo.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuguoguo.commons.Result;
import com.xuguoguo.entity.Users;
import com.xuguoguo.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 @Package: com.xuguoguo.controller
 @ClassName: UsersController
 @Author: XuGuoGuo
 @CreateTime: 2023/12/12-16:40
 @Description:
 */
@RestController
@RequestMapping("/users")
public class UsersController {

    //注入service
    @Autowired
    private UsersService usersService;

    @RequestMapping("/loadAll")
    public Result loadAll(){
        List<Users> list = usersService.list();
        return Result.of(list);
    }
    
}
分别启动服务器:
npm run serve

在这里插入图片描述

打开浏览器访问:

在这里插入图片描述

分页以及条件查询的处理:
页面的修改:
参照官方的文档去添加分页条

https://element-plus.gitee.io/zh-CN/component/pagination.html
在这里插入图片描述

在UserHome.vue文件中添加
分页代码:

在这里插入图片描述

搜索框代码:

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

UserHome.vue修改后的完整代码如下:
<template>
    <div style="padding:10px;">
        <h1>用户列表页面</h1>
        <!-- 功能区域 -->
        <div style="margin:10px 0px;">
          <el-button type="primary">新增用户</el-button>
          <el-button type="danger">删除用户</el-button>
          <el-button type="danger">批量删除</el-button>
          <el-button type="success">修改用户</el-button>
          <el-button type="info">导入用户</el-button>
          <el-button type="warning">导出用户</el-button>
          <el-button type="info">帮助中心</el-button>
        </div>
        <!-- 搜索区域 -->
        <div style="margin:10px 0px;">
          <el-input 
          v-model="search" 
          clearable
          placeholder="请输入您要搜索的条件" 
          style="width:25%;"
          :prefix-icon="Search"
          />
          <el-button type="primary" @click="load">&nbsp;&nbsp;&nbsp;</el-button>
        </div>

        <!-- 表格数据渲染用户列表信息 -->
        <el-table :data="tableData" style="width: 100%">
          <el-table-column prop="id" label="用户ID" width="180" />
          <el-table-column prop="username" label="用户名" width="180" />
          <el-table-column prop="nickname" label="昵称" />
          <el-table-column prop="sex" label="性别" />
          <el-table-column prop="address" label="地址" />
          <el-table-column fixed="right" label="操   作" width="300">
              <el-button type="success" size="small">
                  查看
              </el-button>
              <el-button type="danger" size="small">
                  删除
              </el-button>
              <el-button type="primary" size="small">
                  编辑
              </el-button>
          </el-table-column>
       </el-table>
        <!-- 分页列表 -->
       <div>
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[2, 5, 10, 20]"
          :small="small"
          :disabled="disabled"
          :background="background"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
       </div> 
    </div>
</template>

<script>
import {getData} from "../utils/remote";

export default {
  name:"UserHome",
  data(){
    return{
      tableData:[],
      currentPage:1,
      pageSize:2,
      total:0,
      search:""
    }
  },
  created(){
    this.load();
  },
  methods:{
    load(){
        getData("users/loadAllByPage",{
          pageNum:this.currentPage,
          pageSize:this.pageSize,
          search:this.search
        }).then(res=>{
          console.log(res);
          this.tableData=res.data.records;
          this.total=res.data.total;  
        });
    },
    handleSizeChange(pageSize){
        this.pageSize=pageSize;
        this.load();
    },
    handleCurrentChange(pageNum){
        this.currentPage=pageNum;
        this.load();
    }
  }
}
</script>

<style>

</style>
后台控制器的修改:
@RequestMapping("/loadAllByPage")
public Result loadAllByPage(@RequestParam("pageNum")Integer pageNum,
                            @RequestParam("pageSize")Integer pageSize,
                            String search){
    //通过分页的插件【拦截器】
    Page<Users> pages = new Page<>(pageNum, pageSize);
    //构造条件构造器
    QueryWrapper<Users> usersQueryWrapper = new QueryWrapper<>();
    if (search!=null&& !"".equals(search)) {
        usersQueryWrapper.like("username",search);
    }
    Page<Users> page = usersService.page(pages, usersQueryWrapper);
    return Result.of(page);
}
添加用户信息的的实现:
页面中处理:
<!-- 添加用户的对话框 -->
       <div>
        <el-dialog
          v-model="dialogVisible"
          title="用户信息"
          width="30%"
        >
         <!-- 表单数据 -->
         <el-form 
         :model="form" 
         label-width="120px"
         :rules="rules"
         ref="form"
         >
          <el-form-item label="用户名:" prop="username">
            <el-input v-model="form.username" style="width: 80%;" clearable />
          </el-form-item>
          <el-form-item label="密码:" prop="password">
            <el-input v-model="form.password" style="width: 80%;" clearable />
          </el-form-item>
          <el-form-item label="昵称:" prop="nickname">
            <el-input v-model="form.nickname" style="width: 80%;" clearable/>
          </el-form-item>
          <el-form-item label="性  别:" prop="sex">
            <el-radio v-model="form.sex" label="" size="large" ></el-radio>
            <el-radio v-model="form.sex" label="" size="large" ></el-radio>
            <el-radio v-model="form.sex" label="未知" size="large" >未知</el-radio>
          </el-form-item>
          <el-form-item label="地  址:" prop="address">
            <el-input type="textarea" v-model="form.address" style="width: 80%;" clearable/>
          </el-form-item>
        </el-form>
          <template #footer>
            <span class="dialog-footer">
              <el-button @click="dialogVisible = false">关闭</el-button>
              <el-button type="primary" @click="save">确认</el-button>
            </span>
          </template>
        </el-dialog>
表单提交的事件:
save(){
      //表单提交处理
      //表单校验处理
      this.$refs["form"].validate((valid)=>{
          //校验通过发起请求保存用户信息
          // console.log(valid);
          if(valid){
            postData("users/save",this.form).then(res=>{
              console.log(res.data);
              if(res.data){
                this.load();
                this.dialogVisible=false;
                this.$message({
                  message: '成功添加用户信息!',
                  type: 'success',
                });
              }else{
                ElMessage.error('添加用户信息失败!');
              }
            }); 
          }
      });
    }
后端控制器中的编写:
@RequestMapping("/save")
public Result save(@RequestBody Users users){
    //调用service实现新增用户
    boolean save = usersService.save(users);
    return Result.of(save);
}
完整的UserHome.vue代码如下:
<template>
    <div style="padding:10px;">
        <h1>用户列表页面</h1>
        <!-- 功能区域 -->
        <div style="margin:10px 0px;">
          <el-button type="primary" @click="add"><el-icon><DocumentAdd /></el-icon>新增用户</el-button>
          <el-button type="danger"><el-icon><DocumentDelete /></el-icon>删除用户</el-button>
          <el-button type="danger"><el-icon><Delete /></el-icon>批量删除</el-button>
          <el-button type="success"><el-icon><Edit /></el-icon>修改用户</el-button>
          <el-button type="info">导入用户</el-button>
          <el-button type="warning">导出用户</el-button>
          <el-button type="info">帮助中心</el-button>
        </div>
        <!-- 搜索区域 -->
        <div style="margin:10px 0px;">
          <el-input 
          v-model="search" 
          clearable
          placeholder="请输入您要搜索的条件" 
          style="width:25%;"
          :prefix-icon="Search"
          />
          <el-button type="primary" @click="load">&nbsp;&nbsp;&nbsp;</el-button>
        </div>

        <!-- 表格数据渲染用户列表信息 -->
        <el-table :data="tableData" style="width: 100%" border>
          <el-table-column prop="id" label="用户ID" width="180" />
          <el-table-column prop="username" label="用户名" width="180" />
          <el-table-column prop="nickname" label="昵称" />
          <el-table-column prop="sex" label="性别" />
          <el-table-column prop="address" label="地址" />
          <el-table-column fixed="right" label="操   作" width="300">
              <el-button type="success" size="small">
                  查看
              </el-button>
              <el-button type="danger" size="small">
                  删除
              </el-button>
              <el-button type="primary" size="small">
                  编辑
              </el-button>
          </el-table-column>
       </el-table>
        <!-- 分页列表 -->
       <div style="margin:10px 0px;">
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[2, 5, 10, 20]"
          :small="small"
          :disabled="disabled"
          :background="background"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
       </div> 
       <!-- 添加用户的对话框 -->
       <div>
        <el-dialog
          v-model="dialogVisible"
          title="用户信息"
          width="30%"
        >
         <!-- 表单数据 -->
         <el-form 
         :model="form" 
         label-width="120px"
         :rules="rules"
         ref="form"
         >
          <el-form-item label="用户名:" prop="username">
            <el-input v-model="form.username" style="width: 80%;" clearable />
          </el-form-item>
          <el-form-item label="密码:" prop="password">
            <el-input v-model="form.password" style="width: 80%;" clearable />
          </el-form-item>
          <el-form-item label="昵称:" prop="nickname">
            <el-input v-model="form.nickname" style="width: 80%;" clearable/>
          </el-form-item>
          <el-form-item label="性  别:" prop="sex">
            <el-radio v-model="form.sex" label="" size="large" ></el-radio>
            <el-radio v-model="form.sex" label="" size="large" ></el-radio>
            <el-radio v-model="form.sex" label="未知" size="large" >未知</el-radio>
          </el-form-item>
          <el-form-item label="地  址:" prop="address">
            <el-input type="textarea" v-model="form.address" style="width: 80%;" clearable/>
          </el-form-item>
        </el-form>
          <template #footer>
            <span class="dialog-footer">
              <el-button @click="dialogVisible = false">关闭</el-button>
              <el-button type="primary" @click="save">确认</el-button>
            </span>
          </template>
        </el-dialog>
       </div>
    </div>
</template>

<script>
import {getData,postData} from "../utils/remote";

export default {
  name:"UserHome",
  data(){
    return{
      tableData:[],
      currentPage:1,
      pageSize:2,
      total:0,
      search:"",
      dialogVisible:false,
      form:{},
      rules:{
         username:[
            {required:true,message:"请输入用户名!",trigger:"blur"}
         ],
         password:[
            {required:true,message:"请输入密码!",trigger:"blur"}
         ],
         nickname:[
            {required:true,message:"请输入昵称!",trigger:"blur"}
         ],
         address:[
            {required:true,message:"请输入地址!",trigger:"blur"}
         ]
      }
    }
  },
  created(){
    this.load();
  },
  methods:{
    load(){
        getData("users/loadAllByPage",{
          pageNum:this.currentPage,
          pageSize:this.pageSize,
          search:this.search
        }).then(res=>{
          console.log(res);
          this.tableData=res.data.records;
          this.total=res.data.total;  
        });
    },
    handleSizeChange(pageSize){
        this.pageSize=pageSize;
        this.load();
    },
    handleCurrentChange(pageNum){
        this.currentPage=pageNum;
        this.load();
    },
    add(){
      //显示对话框
      this.dialogVisible=true;
      this.form={};
    },
    save(){
      //表单提交处理
      //表单校验处理
      this.$refs["form"].validate((valid)=>{
          //校验通过发起请求保存用户信息
          // console.log(valid);
          if(valid){
            postData("users/save",this.form).then(res=>{
              console.log(res.data);
              if(res.data){
                this.load();
                this.dialogVisible=false;
                this.$message({
                  message: '成功添加用户信息!',
                  type: 'success',
                });
              }else{
                ElMessage.error('添加用户信息失败!');
              }
            }); 
          }
      });
    }
  }
}
</script>

<style>

</style>
添加用户信息的扩展【mp的自动填充】

在实际操作数据表的过程中,很多列都是可以自己填充的。比如说创建时间、修改时间、创建用户等,所以这个时候我们考虑使用mp的自动填充的策略来实现


  1. 可参考mp的官网:https://baomidou.com/pages/4c6bcf/
数据表的修改:

在这里插入图片描述

用户实体对象的修改:

在这里插入图片描述

需要注意的是mysql服务器的版本的区别,如果是mysql5,使用Date表示时间,如果是mysql8可以使用LocalDateTime来处理时间对象

编写自动填充的配置类:
代码如下:

参考官网即可https://baomidou.com/pages/4c6bcf/ (也需要注意数据库的版本哦!!!)

package com.xuguoguo.utils;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;

/**
 @Package: com.xuguoguo.utils
 @ClassName: MyMetaObjectHandler
 @Author: XuGuoGuo
 @CreateTime: 2023/12/14-8:53
 @Description:
 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("开始自动填充【insert】 ....");
//        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
//        // 或者
//        this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
        // 或者
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); // 也可以使用(3.3.0 该方法有bug)
//        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date()); // 也可以使用(3.3.0 该方法有bug)
//        this.fillStrategy(metaObject, "createUser", BaseContext.getCurrentId()); // 也可以使用(3.3.0 该方法有bug)
        this.strictInsertFill(metaObject, "createUser", Integer.class, 666); // 也可以使用(3.3.0 该方法有bug)
//        metaObject.setValue("createTime",LocalDateTime.now());
//        metaObject.setValue("updateTime",LocalDateTime.now());
//        metaObject.setValue("createUser",666);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("开始自动填充【update】 ....");
//        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
//        // 或者
//        this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
        // 或者
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); // 也可以使用(3.3.0 该方法有bug)
        this.strictUpdateFill(metaObject, "updateUser", Integer.class,888); // 也可以使用(3.3.0 该方法有bug)
//        metaObject.setValue("updateTime",LocalDateTime.now());
//        metaObject.setValue("updateUser",888);
    }
}
用户信息的话可以使用LocalThread来设置和获取:
package com.xuguoguo.utils;

/**
 @Package: com.xuguoguo.utils
 @ClassName: BaseContext
 @Author: XuGuoGuo
 @CreateTime: 2023/12/14-8:56
 @Description:
 */
//使用ThreadLocal封装工具类
public class BaseContext {

     public static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>();

     /**
     *  设置值
      */
     public static void setCurrentId(Integer id) {
            threadLocal.set(id);
     }

    /**
     *  获取值
     */
    public static Integer getCurrentId() {
        return  threadLocal.get();
    }


}
检查application.yml的配置:

在这里插入图片描述

前端vue中的时间渲染处理
有多种方式,这里我用两种插件来简化实现
1、安装插件 【moment.js或者day.js进行时间格式化】
npm install moment

或者

npm install dayjs
在时间列上绑定一个时间格式化函数【:formatter=“函数名”】

在这里插入图片描述

在需要使用格式化的vue中引入插件

在这里插入图片描述

最后在methods中定义函数即可:

在这里插入图片描述

 formatDate(row, column) {
      let datas = row[column.property];
      if (datas == null) {
        return "";
      } else {
        return moment(datas).format("yyyy-MM-DD HH:mm:ss");
      }
    }

在这里插入图片描述

修改用户信息的实现
在修改的html代码中通过template进行引导页面【#default="scope"进行传递行数据】

在这里插入图片描述

在methods中定义函数回显当前行的数据:

在这里插入图片描述

handleEdit(row) {
      console.log(row);
      this.form = JSON.parse(JSON.stringify(row));
      this.dialogVisible = true;
}
更新提交处理:

在这里插入图片描述

因为是共用的事件,所以需要通过判断是否有id值来判断是新增还是修改

在这里插入图片描述

save() {
      //表单提交处理
      //表单校验处理
      this.$refs["form"].validate((valid) => {
        //校验通过发起请求保存用户信息
        // console.log(valid);
        if (valid) {
          //如何区分是添加/更新
          //更新【携带了id】
          if (this.form.id) {
            postData("users/edit",this.form).then(res=>{
              if (res.data) {
                this.load();
                this.dialogVisible = false;
                this.$message({
                  message: "成功更新用户信息!",
                  type: "success",
                });
              } else {
                ElMessage.error("更新用户信息失败!");
              }
            });  

          } else {
            //新增【没有id】
            postData("users/save", this.form).then((res) => {
              console.log(res.data);
              if (res.data) {
                this.load();
                this.dialogVisible = false;
                this.$message({
                  message: "成功添加用户信息!",
                  type: "success",
                });
              } else {
                ElMessage.error("添加用户信息失败!");
              }
            });
          }
        }
      });
    }
后端的控制器处理:
@RequestMapping("/save")
public Result save(@RequestBody Users users){
    //调用service实现新增用户
    boolean save = usersService.save(users);
    return Result.of(save);
}

@RequestMapping("/edit")
public Result edit(@RequestBody Users users){
    boolean b = usersService.updateById(users);
    return Result.of(b);
}

在这里插入图片描述

删除用户信息

在这里插入图片描述

在methods中自定义删除的事件

在这里插入图片描述

deleteUser(id){
        console.log(id);
        postData("users/"+id).then(res=>{
          if (res.data) {
                this.load();
                this.$message({
                  message: "成功删除用户信息!",
                  type: "success",
                });
              } else {
                ElMessage.error("删除用户信息失败!");
           }
        });
    }
  }
后端控制器的编写:
@RequestMapping("/{id}")
public Result deleted(@PathVariable("id")Integer id){
    boolean b = usersService.removeById(id);
    return Result.of(b);
}

本节完毕,章节后续更新!如果需要源码的朋友们可关注微信公众号"锅锅编程生活"或者扫描二维码关注回复关键字/后台留言获取即可!
在这里插入图片描述

  • 31
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot 是一款非常流行的 Java Web 开发框架,而 Vue.js 是一款非常流行的前端框架,两者的结合可以构建出一个高效的、现代化的全栈 Web 应用。下面是一个简单的 Spring Boot 集成 Vue.js 的流程: 1. 创建 Spring Boot 项目 使用 Spring Initializr 创建一个 Spring Boot 项目,选择 Web、Thymeleaf 和 Spring Data JPA 依赖。 2. 集成 Vue.js 在 Spring Boot 项目中创建一个名为 "frontend" 的文件夹,在其中创建一个名为 "src" 的子文件夹。在 "src" 文件夹中创建一个名为 "main.js" 的文件,添加以下代码: ``` import Vue from 'vue' import App from './App.vue' new Vue({ el: '#app', render: h => h(App) }) ``` 在 "frontend" 文件夹中运行以下命令安装 Vue.js: ``` npm init -y npm install vue npm install -g @vue/cli vue create my-app ``` 然后将 "my-app" 目录中的所有文件复制到 "frontend/src" 中。 3. 修改模板文件 在 "src/main/resources/templates" 文件夹中创建一个名为 "index.html" 的文件,添加以下代码: ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My App</title> </head> <body> <div id="app"></div> <script src="/frontend/dist/js/chunk-vendors.js"></script> <script src="/frontend/dist/js/app.js"></script> </body> </html> ``` 4. 配置 Spring Boot 在 "application.properties" 文件中添加以下配置: ``` spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:/frontend/dist/ ``` 5. 构建前端代码 在 "frontend" 文件夹中运行以下命令构建前端代码: ``` npm run build ``` 6. 运行 Spring Boot 应用程序 启动 Spring Boot 应用程序,访问 http://localhost:8080 即可看到 Vue.js 应用程序。 以上是一个简单的 Spring Boot 集成 Vue.js 的流程。需要注意的是,在实际开发中,可能需要更加复杂的配置和集成

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值