springBoot+mybatisplus+vue前后端分离的增删改查+分页模糊查询

效果图

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

项目结构

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

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

后端

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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wang</groupId>
    <artifactId>springBoot-vue</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springBoot-vue</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </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>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

yml

server:
  port: 8081
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/spring?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
    username: root
    password: root
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
mybatis-plus:
  mapper-locations: classpath:/mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

实体类

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

mapper接口

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

mapper.xml

在这里插入图片描述

service层

在这里插入图片描述

在这里插入图片描述

controller层

package com.wang.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wang.pojo.Goods;
import com.wang.pojo.Type;
import com.wang.service.impl.GoodsServiceImpl;
import com.wang.service.impl.TypeServiceImpl;
import com.wang.util.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author wjc
 * @since 2022-12-06
 */
@Controller
@Api(tags = "食品管理")
@RequestMapping("/goods")
@CrossOrigin
public class GoodsController {

    @Autowired
    private GoodsServiceImpl goodsService;

    @Autowired
    private TypeServiceImpl typeService;

    @ApiOperation(value = "分页查询所有食品")
    @GetMapping("/pageList")
    @ResponseBody
    public R pageList(@RequestParam(name = "pageNum",defaultValue = "1",required = false)Integer pageNum,
                      @RequestParam(name = "pageSize",defaultValue = "2",required = false)Integer pageSize,
                      @RequestParam(name = "name",required = false)String name){

     /*   QueryWrapper<Goods> queryWrapper=new QueryWrapper();
        queryWrapper.orderByAsc("count");
        if (name!=null||name!=""){
            queryWrapper.like("name",name);
        }
        Page<Goods> page=new Page<>(pageNum,pageSize);*/
        Page<Goods> allByName = goodsService.findAllByName(pageNum, pageSize, name);
        return R.ok().data("goodsList",allByName);
    }


    @ApiOperation(value = "查看食品信息")
    @GetMapping("/findAll")
    @ResponseBody
    public R findAll(){
        List<Goods> list = goodsService.list();
        return R.ok().data("goodsList",list);
    }

    @ApiOperation(value = "删除食品信息")
    @DeleteMapping("/deleteGoods")
    @ResponseBody
    public R deleteGoods(Integer id){
        boolean b = goodsService.removeById(id);
        return R.ok().data("istrue",b);
    }

    @ApiOperation(value = "新增食品信息")
    @PostMapping("/addGoods")
    @ResponseBody
    public R addGoods(@RequestBody Goods goods){
        boolean b = goodsService.save(goods);
        return R.ok().data("istrue",b);
    }

    @ApiOperation(value = "修改食品信息")
    @PutMapping("/updateGoods")
    @ResponseBody
    public R updateGoods(@RequestBody Goods goods){
        int i = goodsService.updateGoods(goods);
        return R.ok().data("istrue",i);
    }

    @ApiOperation(value = "查看食品类型")
    @GetMapping("/typeAll")
    @ResponseBody
    public R typeAll(){
        List<Type> list = typeService.list();
        return R.ok().data("typeList",list);
    }
}

工具类

package com.wang.util;

/*
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
*/
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;
/*@Configuration用于定义配置类, 相当于 配置的头部
可替换xml配置文件,被注解的类内部包含有一个或多个被
@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext
或AnnotationConfigWebApplicationContext类进行扫描,
并用于构建bean定义,初始化Spring容器。 注意:@Configuration注解的配置类有如下要求:*/

@Configuration
public class MybatisPlusConfig {

    //@Configuration启动容器+@Bean注册Bean
    /**
     * mybatis拦截器   注册插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        // 初始化拦截器
        MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }


    /*@Configuation等价于<Beans></Beans>
    @Bean等价于<Bean></Bean>
    @ComponentScan等价于<context:component-scan base-package="com.xxx"/>*/
}

package com.wang.util;


import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author:帅帅的刘
 * @Description:
 * @Date:Create In 2019-11-14 11:29
 **/
@Data
@ApiModel(value = "全局统一返回结果")
public class R {

    @ApiModelProperty(value = "是否成功")
    private Boolean success;

    @ApiModelProperty(value = "返回码")
    private Integer code;

    @ApiModelProperty(value = "返回消息")
    private String message;

    @ApiModelProperty(value = "返回数据")
    private Map<String, Object> data = new HashMap<String, Object>();

    private R(){}

    public static R ok(){
        R r = new R();
        r.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
        r.setCode(ResultCodeEnum.SUCCESS.getCode());
        r.setMessage(ResultCodeEnum.SUCCESS.getMessage());
        return r;
    }

    public static R error(){
        R r = new R();
        r.setSuccess(ResultCodeEnum.UNKNOWN_REASON.getSuccess());
        r.setCode(ResultCodeEnum.UNKNOWN_REASON.getCode());
        r.setMessage(ResultCodeEnum.UNKNOWN_REASON.getMessage());
        return r;
    }

    public static R setResult(ResultCodeEnum resultCodeEnum){
        R r = new R();
        r.setSuccess(resultCodeEnum.getSuccess());
        r.setCode(resultCodeEnum.getCode());
        r.setMessage(resultCodeEnum.getMessage());
        return r;
    }

    public R success(Boolean success){
        this.setSuccess(success);
        return this;
    }

    public R message(String message){
        this.setMessage(message);
        return this;
    }

    public R code(Integer code){
        this.setCode(code);
        return this;
    }

    public R data(String key, Object value){
        this.data.put(key, value);
        return this;
    }

    public R data(Map<String, Object> map){
        this.setData(map);
        return this;
    }
}

package com.wang.util;

import lombok.Getter;

@Getter
public enum ResultCodeEnum {

    SUCCESS(true, 20000,"成功"),
    UNKNOWN_REASON(false, 20001, "未知错误"),
    BAD_SQL_GRAMMAR(false, 21001, "sql语法错误"),
    JSON_PARSE_ERROR(false, 21002, "json解析异常"),
    PARAM_ERROR(false, 21003, "参数不正确"),
    FILE_UPLOAD_ERROR(false, 21004, "文件上传错误"),
    EXCEL_DATA_IMPORT_ERROR(false, 21005, "Excel数据导入错误"),
    USERLOGIN_INVALID_ERROR(false, 21007,"登录信息过期,请重新登录"),
    USERUNLOGIN_ERROR(false, 21008,"用户未登录,请重新登录");

    private Boolean success;

    private Integer code;

    private String message;

    private ResultCodeEnum(Boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }
}

注意goods是要跟你controller类的路径对应

package com.wang.util;

import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Bean
    public Docket webApiConfig() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("webApi")
                .apiInfo(webApiInfo())
                .select()
                .paths(Predicates.not(PathSelectors.regex("/goods/.*")))
                .paths(Predicates.not(PathSelectors.regex("/error.*")))
                .build();

    }

    @Bean
    public Docket adminApiConfig() {

        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("adminApi")
                .apiInfo(adminApiInfo())
                .select()
                .paths(Predicates.and(PathSelectors.regex("/goods/.*")))
                .build();

    }

    private ApiInfo webApiInfo() {

        return new ApiInfoBuilder()
                .title("网站-课程中心API文档")
                .description("本文档描述了课程中心微服务接口定义")
                .version("1.0")
                .build();
    }

    private ApiInfo adminApiInfo() {

        return new ApiInfoBuilder()
                .title("后台管理系统-课程中心API文档")
                .description("本文档描述了后台管理系统课程中心微服务接口定义")
                .version("1.0")
                .build();
    }
}

前端

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

//引入router
import VueRouter from "vue-router";
Vue.use(VueRouter)
Vue.use(router)
//引入ElementUinpm install element-ui
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(Element)
Vue.config.productionTip = false

//引入axios
import axios from "axios";
Vue.prototype.$axios=axios
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router:router,
  components: { App },
  template: '<App/>'
})

index.js

import Vue from 'vue'
import Router from 'vue-router'
import Goods from "../components/goods/Goods";

Vue.use(Router)
export default new Router({
  routes: [
    {
      path: '/',
      name: 'MainView',
      component: MainView,
      children:[
        {
        path:'/Goods',
          name:'Goods',
          component:Goods
      }
      ]
    }
  ]
})

goods.js

import axios from "./base";


//查询所有信息
export const pageList=(params)=>axios.get('/goods/pageList',{params})

//查询所有信息
export const findAll=()=>axios.get('/goods/findAll')

//删除食品
export const deleteById = (params) => axios.delete('/goods/deleteGoods', {params})

//添加食品
export const addGoods = (params) => axios.post('/goods/addGoods',params)

//修改食品信息
export const updateGoods = (params) => axios.put('/goods/updateGoods', params)

//查询食品类型
export const typeAll=()=>axios.get('/goods/typeAll')

base.js

import axios from 'axios'

const instance = axios.create({
  baseURL: 'http://localhost:8081',
  timeout: 5000
})

instance.interceptors.request.use(config=>{
  return config
},err=>{
  return Promise.reject(err)
})

instance.interceptors.response.use(res=>{
  return res
},err=>{
  return Promise.reject(err)
})


export default instance

Goods.vue

<template>
  <div>
    <el-input v-model="pagination.name" placeholder="食品名称"></el-input>
    <el-button style="margin-left: 20px" type="primary" @click="getGoodsList()"><i class="el-icon-search"></i>查询</el-button>
    <template>
      <el-button type="primary" @click="openGoods()">添加食品</el-button>
    </template>
  <el-table
    :data="tableData"
    style="width: 100%">
    <el-table-column
      prop="id"
      label="编号"
      width="180">
    </el-table-column>
    <el-table-column
      prop="name"
      label="食品名称"
      width="180">
    </el-table-column>
    <el-table-column
      prop="price"
      label="价格"
      width="180">
    </el-table-column>
    <el-table-column
      prop="count"
      label="数量"
      width="180">
    </el-table-column>
    <el-table-column
      prop="types.typename"
      label="类型"
      width="180">
    </el-table-column>
    <el-table-column label="操作">
      <template slot-scope="scope">
        <el-button
          size="mini"
          type="primary"
          @click="editgoods(scope.row)">编辑</el-button>
        <el-button
          size="mini"
          type="primary"
          @click="deleteById(scope.row.id)">删除</el-button>
      </template>
    </el-table-column>
  </el-table>
    <!--    添加食品弹窗-->
    <el-dialog :visible.sync="addGoods" title="添加食品">
      <el-form :model="ruleForm" status-icon  ref="ruleForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="食品名称" prop="name">
          <el-input type="text" v-model="ruleForm.name" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="价格" prop="price">
          <el-input type="text" v-model="ruleForm.price" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="数量" prop="count">
          <el-input type="text" v-model="ruleForm.count" autocomplete="off"></el-input>
        </el-form-item>
<!--        <el-form-item label="类型" prop="type">-->
<!--          <el-input type="text" v-model="ruleForm.type" autocomplete="off"></el-input>-->
<!--        </el-form-item>-->
        <el-form-item label="类型" prop="type" >
        <el-select v-model="ruleForm.type" clearable placeholder="请选择">
          <el-option
            v-for="item in typeFrom"
            :key="item.id"
            :label="item.typename"
            :value="item.id">
          </el-option>
        </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="save">添加</el-button>

          <el-button @click="outcancel()">取消</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <!--    修改食品弹窗-->
    <el-dialog :visible.sync="updateGood" title="修改食品">
      <el-form :model="updateForm" status-icon  ref="updateForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="编号" prop="id" hidden>
          <el-input type="text" v-model="updateForm.id" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="食品名称" prop="name">
          <el-input type="text" v-model="updateForm.name" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="价格" prop="price">
          <el-input type="text" v-model="updateForm.price" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="数量" prop="count">
          <el-input type="text" v-model="updateForm.count" autocomplete="off"></el-input>
        </el-form-item>
<!--        <el-form-item label="类型" prop="type">-->
<!--          <el-input type="text" v-model="updateForm.type" autocomplete="off"></el-input>-->
<!--        </el-form-item>-->
        <el-form-item label="类型" prop="type" >
          <el-select v-model="updateForm.type" clearable placeholder="请选择">
            <el-option
              v-for="item in typeFrom"
              :key="item.id"
              :label="item.typename"
              :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="update">修改</el-button>
          <el-button @click="outcancel()">取消</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>
    <template>
      <!--            <span class="demonstration">完整功能</span>-->
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="pagination.pageNum"
        :page-sizes="[2, 5, 10, 20]"
        :page-size="pagination.pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pagination.total">
      </el-pagination>
    </template>
  </div>
</template>

<script>
    import { findAll,deleteById,addGoods,updateGoods,pageList,typeAll} from "../../api/goods"
export default {
  name:'Goods',
  data() {
    return {
      tableData: [],
      addGoods:false,
      updateGood:false,
      typeFrom:[],
      ruleForm:{
        name:"",
        price:"",
        count:"",
        type:""
      },
      updateForm:{
        id:"",
        name:"",
        price:"",
        count:"",
        type:""
      },
      pagination:{
        pageNum:"",
        pageSize:"",
        total:"",
        name:""
      }
    }
  },created() {
      //初始化
    this.getGoodsList();
    this.typeAll();
  },
  methods: {
    typeAll(){
      typeAll().then(res=>{
        console.log(res);
        this.typeFrom=res.data.data.typeList;
      })
    },
    //清空表单
    clear(){
      this.ruleForm={}
      // this.ruleForm.id=''
      // this.ruleForm.name=''
      // this.ruleForm.price=''
      // this.ruleForm.count=''
      // this.ruleForm.type=''
    },
    getGoodsList(){
      pageList(this.pagination).then(res=>{
          console.log(res);
          this.tableData=res.data.data.goodsList.records;
          this.pagination.pageNum=res.data.data.goodsList.current;
          this.pagination.pageSize=res.data.data.goodsList.size;
          this.pagination.total=res.data.data.goodsList.total;
      })
    },
    handleSizeChange(val) {
      this.pagination.pageSize = val;
      this.getGoodsList()
    },
    handleCurrentChange(val) {
      this.pagination.pageNum = val;
      this.getGoodsList()
    },
    findAll(){
      findAll().then(res=>{
          console.log(res)
          this.tableData=res.data.data.goodsList;
      })
    },
    deleteById(id){
      this.$confirm('此操作将永久删除编号为'+id+', 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteById({id}).then(res=>{
          console.log(res)
          if(res.data.data.istrue===true){
            this.$message({
              type: 'success',
              message: '删除成功!'
            });
            this.getGoodsList();
          }else{
            this.$message.error('删除失败');
          }
        })
      }).catch(()=>{}) //添加错误捕获
    },
    openGoods(){
      this.addGoods=true;
    },
    outcancel(){
      this.addGoods=false;
      this.updateGood=false;
    },save(){
      addGoods(this.ruleForm).then(res=>{
        if(res.data.data.istrue===true){
          this.$message({
            message: '添加成功',
            type: 'success'
          });
          this.getGoodsList();
          this.outcancel();
          this.clear();
          // this.$router.go()
        }else{
          this.$message.error('添加失败');
        }
        // location.reload();
      }).catch(()=>{}) // 添加错误捕获
    },
    editgoods(goods) {
      this.updateGood = true;
      this.updateForm.id=goods.id;
      this.updateForm.name=goods.name;
      this.updateForm.price=goods.price;
      this.updateForm.count=goods.count;
      this.updateForm.type=goods.type;
    },update(){
      updateGoods(this.updateForm).then(res=>{
        if(res.data.data.istrue>=1){
          this.$message({
            message: '修改成功',
            type: 'success'
          });
          this.getGoodsList();
          this.outcancel();
        }else{
          this.$message.error('修改失败');
        }
      }).catch(()=>{}) // 添加错误捕获
    }
  }
}
</script>

<style scoped>
.el-input{
  width: 200px;
  margin-left: 15px;
}
</style>

需要源码私信

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值