栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Maynor手把手教你完成一个SpringBoot+Vue+Element实现的SPA商品管理系统(增删改查)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Maynor手把手教你完成一个SpringBoot+Vue+Element实现的SPA商品管理系统(增删改查)

Maynor手把手教你完成一个SpringBoot+Vue+Element实现的SPA商品管理系统(增删改查) 前言

完整代码 三连后私信我获取~
撸了一上午完成的SPA商品管理系统,求三连!

B站演示视频

Maynor手把手教你完成一个SpringBoot+Vue+Element演示视频(最后出现了点小bug)_哔哩哔哩_bilibili

项目需求 商品管理系统 1、商品列表

多条件查询包括模糊查询,区间查询,类别选择和品牌选择、列表分页、类别和品类下拉列表选择

2、添加商品

3、修改商品

4、批量删除

5、单个商品删除

项目搭建:

SpringBoot项目的搭建(你的第一个SpringBoot项目)_A Coder-CSDN博客_springboot 项目

项目结构 后端结构

配置文件

pom.xml


        org.springframework.boot
        spring-boot-starter-parent
        2.5.5
         
    
    
    
        UTF-8
        UTF-8
        1.8
        1.3.2
        2.0.2
        5.1.32
        1.2.5
        1.1.10
        1.18.16
    

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            ${mybatis.starter.version}
        
        
        
            tk.mybatis
            mapper-spring-boot-starter
            ${mapper.starter.version}
        
        
        
            com.github.pagehelper
            pagehelper-spring-boot-starter
            ${pageHelper.starter.version}
        
        
        
            mysql
            mysql-connector-java
            ${mysql.version}
        
        
        
            com.alibaba
            druid-spring-boot-starter
            ${durid.starter.version}
        
        
            org.projectlombok
            lombok
            ${lombok.version}
        
        
            commons-lang
            commons-lang
            2.6
        

    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

application.properties

#Tomcat
server.port=8090
#DB configuration
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test3?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
#druid
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.initial-size=1
spring.datasource.druid.min-idle=1
spring.datasource.druid.max-active=20
spring.datasource.druid.test-on-borrow=true
spring.datasource.druid.stat-view-servlet.allow=true
logging.level.com.czxy=debug

封装类

baseResult

package com.czxy.common;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.http.ResponseEntity;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class baseResult {

    
    private Integer code;
    
    private String msg;
    
    private Object data;

    private Integer total;

    public baseResult(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public static ResponseEntity success(Object data){
        return ResponseEntity.ok(new baseResult(10000,"成功",data));
    }

    public static ResponseEntity fail(){
        return ResponseEntity.ok(new baseResult(10001,"失败",null));
    }

    public static ResponseEntity success(Object data,Integer total){
        return ResponseEntity.ok(new baseResult(10000,"成功",data,total));
    }

}

GlobalCorsConfig

package com.czxy.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlbasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;



@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行哪些原始域
        config.addAllowedOrigin("*");
        //是否发送cookie信息
        config.setAllowCredentials(false);
        //放行哪些原始域(请求方式)
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");     //get
        config.addAllowedMethod("PUT");     //put
        config.addAllowedMethod("POST");    //post
        config.addAllowedMethod("DELETe");  //delete
        config.addAllowedMethod("PATCH");
        config.addAllowedHeader("*");

        //2.添加映射路径
        UrlbasedCorsConfigurationSource configSource = new UrlbasedCorsConfigurationSource();
        configSource.registerCorsConfiguration(";
;
;
;
;
;
;
;
;
;

--
-- Table structure for table `brand`
--

DROP TABLE IF EXISTS `brand`;
;
;
CREATE TABLE `brand` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
;

--
-- Dumping data for table `brand`
--

LOCK TABLES `brand` WRITE;
;
INSERT INTO `brand` VALUES (1,'花花公子'),(2,'唐狮'),(4,'太平鸟'),(5,'森马'),(6,'大嘴猴'),(7,'adidas'),(8,'耐克'),(9,'苹果'),(10,'华为'),(11,'小米'),(12,'格力');
;
UNLOCK TABLES;

--
-- Table structure for table `category`
--

DROP TABLE IF EXISTS `category`;
;
;
CREATE TABLE `category` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
;

--
-- Dumping data for table `category`
--

LOCK TABLES `category` WRITE;
;
INSERT INTO `category` VALUES (1,'女装'),(2,'男装'),(3,'内衣'),(4,'家电'),(5,'吸尘器'),(6,'取暖器'),(7,'手机'),(8,'家纺');
;
UNLOCK TABLES;

--
-- Table structure for table `goods`
--

DROP TABLE IF EXISTS `goods`;
;
;
CREATE TABLE `goods` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `brand_id` int(11) DEFAULT NULL,
  `category_id` int(11) DEFAULT NULL,
  `introduction` varchar(50) DEFAULT NULL,
  `store_num` int(11) DEFAULT NULL,
  `price` double DEFAULT NULL,
  `create_time` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
;

--
-- Dumping data for table `goods`
--

LOCK TABLES `goods` WRITE;
;
INSERT INTO `goods` VALUES (2,'华为Mate30',10,7,'华为MATE30 金色1T',200,9999,'2021-10-22'),(8,'运动鞋',8,1,'百搭潮休闲鞋子',6000,999,'2021-11-02'),(9,'夹克',4,2,'新款迷彩休闲连帽上衣',8888,789,'2021-11-01'),(10,'demo',NULL,NULL,'xxxx',1,999,'2021-11-03'),(11,'1',NULL,NULL,'1',111,11,NULL),(12,'2',NULL,NULL,NULL,222,22,'2021-11-25T16:00:00.000Z'),(13,'123',NULL,NULL,'123',12,123,'2021-11-09');
;
UNLOCK TABLES;
;

;
;
;
;
;
;
;

-- Dump completed on 2021-11-05  9:27:52

后端代码部分

主要完成 entity/dao/service/controller/vo的开发,由于代码重复仅贴出Goods的完整代码

entity层:

@Table(name = "goods")
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class TTeacher implements Serializable {
	//id
//	name
//			brand_id
//	category_id
//			introduction
//	store_num
//			price
//	create_time
    @Id
	private Integer id;
	private String name;
	private Integer brand_id;
	private Integer category_id;
	private String introduction;
	private Integer store_num;
	private Double price;
	private String create_time;
	// 在java的日期类型只要符合2012-02-02
	private TSchool school;
	private TType type;

}

dao层:

@org.apache.ibatis.annotations.Mapper
public interface TeacherMapper extends Mapper {

}

service层:

public interface TeacherService {
    ResponseEntity findByCondition(TeacherSearchVO teacherSearchVO);

    boolean add(TTeacher tea);

    TTeacher findById(Integer id);

    boolean update(TTeacher tea);

    boolean deleteById(Integer id);

    List selectAll();
}

impl 实现类

@Service
@Transactional
public class TeacherServiceImpl implements TeacherService {

    @Autowired
    private TeacherMapper teacherMapper;

    @Autowired
    private SchoolMapper schoolMapper;

    @Autowired
    private TypeMapper typeMapper;

    @Override
    public ResponseEntity findByCondition(TeacherSearchVO teacherSearchVO) {
       // List teaList = new ArrayList<>();//最终要返回到前端的数据
        //拼接条件
        String teacherName = teacherSearchVO.getTeacherName();
        Integer schoolId = teacherSearchVO.getSchoolId();
        Integer typeId = teacherSearchVO.getTypeId();
        String typeName = teacherSearchVO.getTypeName();

        Integer minSalary = teacherSearchVO.getMinSalary();
        Integer maxSalary = teacherSearchVO.getMaxSalary();
        Integer page = teacherSearchVO.getPage();
        Integer rows = teacherSearchVO.getRows();

        Example example = new Example(TTeacher.class);
        Example.Criteria criteria = example.createCriteria();
        //1 名字模糊
        if (StringUtils.isNotBlank(teacherName)){
            criteria.andLike("name","%"+teacherName+"%");
        }
        //2 id精确匹配
        if (schoolId!=null&&StringUtils.isNotBlank(schoolId.toString())){
            criteria.andEqualTo("brand_id",schoolId);
        }

        if (typeId!=null&&StringUtils.isNotBlank(typeId.toString())){
            criteria.andEqualTo("category_id",typeId);
        }
        if (minSalary!=null&&StringUtils.isNotBlank(minSalary.toString())){
            criteria.andGreaterThanOrEqualTo("price",minSalary);
        }
        //4
        if (maxSalary!=null&&StringUtils.isNotBlank(maxSalary.toString())){
            criteria.andLessThanOrEqualTo("price",maxSalary);
        }
        //查找总条数,供分页使用
        int total = teacherMapper.selectByExample(example).size();

        //7 后端分页
        PageHelper.startPage(page,rows);

        //8 查出结果
        List teacherList = teacherMapper.selectByExample(example);

        //后端关联id显示名字
        for (TTeacher tea:teacherList){
            tea.setType(typeMapper.selectByPrimaryKey(tea.getCategory_id()));
            tea.setSchool(schoolMapper.selectByPrimaryKey(tea.getBrand_id()));
        }

        if (teacherList.size()==0&&teacherSearchVO.getPage()!=1){
            page = total%rows==0?total/rows:(total/rows+1);
            teacherSearchVO.setPage(page);
            findByCondition(teacherSearchVO);
        }

        return baseResult.success(teacherList,total);
    }

    @Override
    public boolean add(TTeacher tea) {
        return teacherMapper.insert(tea)==1;
    }

    @Override
    public TTeacher findById(Integer id) {
        return teacherMapper.selectByPrimaryKey(id);
    }

    @Override
    public boolean update(TTeacher tea) {
        return teacherMapper.updateByPrimaryKey(tea)==1;
    }


    @Override
    public boolean deleteById(Integer id) {
        return teacherMapper.deleteByPrimaryKey(id)==1;
    }

    @Override
    public List selectAll() {
        return teacherMapper.selectAll();
    }
}

VO类:

@Data
public class TeacherSearchVO {

    private String teacherName;
    private String typeName;
    private Integer schoolId;
    private Integer typeId;
    private Integer minSalary;
    private Integer maxSalary;
    private Integer page;//页码
    private Integer rows;//行数

}

controller层:

@RestController
@RequestMapping("/teacher")
public class TeacherController {
    @Autowired
    private TeacherServiceImpl teacherService;

    @GetMapping("/condition")
    public ResponseEntity findByCondition(TeacherSearchVO teacherSearchVO){
        ResponseEntity rbr = teacherService.findByCondition(teacherSearchVO);
        return rbr;
    }

    @GetMapping("/all")
    public List selectAll( ){
        List  rbr = teacherService.selectAll();
        return rbr;
    }

    @PostMapping
    public ResponseEntity add(@RequestBody TTeacher tea){
        boolean flag = teacherService.add(tea);
        if (flag){
            return baseResult.success("新增成功");
        }else{
            return baseResult.fail();
        }
    }

    @GetMapping("/{id}")
    public ResponseEntity findById(@PathVariable("id") Integer id){
        TTeacher tea = teacherService.findById(id);
        return baseResult.success(tea);
    }
    @PutMapping
    public ResponseEntity update(@RequestBody TTeacher tea){
        boolean flag = teacherService.update(tea);
        if (flag){
            return baseResult.success("修改成功");
        }else{
            return baseResult.fail();
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity deleteById(@PathVariable Integer id){
        boolean flag= teacherService.deleteById(id);
        if (flag){
            return baseResult.success("删除成功");
        }else{
            return baseResult.fail();
        }
    }
    @DeleteMapping("/batchDelete/{ids}")
    public ResponseEntity bachDelete(@PathVariable String ids){
        String[] splitIds = ids.split(",");
        for (String id:splitIds){
            teacherService.deleteById(Integer.parseInt(id));
        }
        return baseResult.success("删除成功");
    }

}

Maynor小声bb:后端完成,接下来我们转战前端页面的实现!

前端代码部分: vue创建命令:
npm create xxx

cd xxx

npm run serve
vue安装命令:
npm install
elementui 安装
npm i element-ui -S
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import axios from 'axios'
axios.defaults.baseURL = "http://localhost:8090"
Vue.prototype.$http = axios

Vue.use(ElementUI)



Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

App.vue



index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/schoolList',
    name: 'SchoolList',
    component: () => import('@/views/SchoolList.vue')
  },
  {
    path: '/teacherList',
    name: 'TeacherList',
    component: () => import('@/views/TeacherList.vue')
  },
  {
    path: '/addTeacher',
    name: 'AddTeacher',
    component: () => import('@/views/AddTeacher.vue')
  },
  {
    path: '/updateTeacher/:id(\d+)',
    name: 'UpdateTeacher',
    component: () => import('@/views/UpdateTeacher.vue')
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.base_URL,
  routes
})

export default router

前端增删改查 页面显示
 
       
新增商品


品牌: 类别: 商品名称: 商品价格:-
全选 商品ID 商品名称 商品品牌 商品类别 商品价格 商品库存 发布时间 商品介绍 操作
{{tea.id}} {{tea.name}} {{tea.school.name}} {{tea.type.name}} {{tea.price}} {{tea.store_num}} {{tea.create_time}} {{tea.introduction}} 修改 删除

js

export default {
    data() {
        return {
            id:[],
            teacherSearchVo:{
                page:1,
                rows:3,
                schoolId:"",
                typeId:""
            },
            teaList:[],//商品列表
            schoolList:[],//所有的学校集合
            categoryList:[],//所有的类别集合
            total:0,//总条数
            dels:[],//批量删除的id集合
            selectAll:false,//true全选  false全不选
        }
    },
    methods: {
        async initTeaList(){
            let res = await this.$http.get("/teacher/condition",{params:this.teacherSearchVo})
            console.log(res)
            this.teaList = res.data.data
            this.total = res.data.total
        }, 
        async initSchoolList(){
            let res = await this.$http.get("/school/all")
            this.schoolList = res.data.data
            
        },
        async initCategoryList(){
            let res = await this.$http.get("/type/all")
            this.categoryList = res.data.data
            console.log(this.categoryList)
            
        },
        handleSizeChange(val) {
            console.log(`每页 ${val} 条`);
            this.teacherSearchVo.rows = val
            this.initTeaList()

        },
        handleCurrentChange(val) {
            console.log(`当前页: ${val}`);
            this.teacherSearchVo.page = val
            this.initTeaList()
        },
        async deleteById(id){
            console.log(id)
            let res = await this.$http.delete("/teacher/"+id)
            if(res.data.code==10000){
                alert("删除成功")
                this.initTeaList()
            }else{
                alert("删除失败")
            }
        },
        async batchDelete(){
            // 组装id
            let delIds = "";
            for(let i=0;i 
添加功能 
新增商品  

通过点击添加按钮跳转到添加的页面








修改功能
修改 

与添加页面类似,仅需修改js即可

export default {
    data() {
        return {
            teacherSearchVo:{
                page:1,
                rows:3,
                schoolId:"",
                typeId:""
            },
            teacher:{
                sex:"",
                typeId:"",//默认:--请选择--
            },//商品是一个对象
            typeList:[],//商品类型数组
            schoolList:[],//所有的学校集合
        }
    },
    methods: {
        async initTeacher(){
            let res = await this.$http.get("/teacher/"+this.id)
            // debugger
            this.teacher = res.data.data
        },
         //初始化商品类型的方法
        async initTypeList(){
            let res = await this.$http.get("/type/all")
            this.typeList = res.data.data
        },
        async update(){
            let res = await this.$http.put("/teacher",this.teacher)
            if(res.data.code==10000){
                alert("修改成功")
                this.$router.push("/teacherList")
            }else{
                alert("修改失败")
            }
        },
         async initSchoolList(){
            let res = await this.$http.get("/school/all")
            this.schoolList = res.data.data
            
        },
    },  
    created() {
        this.id = this.$route.params.id
        this.initTeacher()
        this.initTypeList()
        this.initSchoolList()
    },
}
删除功能
删除 
 async deleteById(id){
            console.log(id)
            let res = await this.$http.delete("/teacher/"+id)
            if(res.data.code==10000){
                alert("删除成功")
                this.initTeaList()
            }else{
                alert("删除失败")
            }
        },
目前功能基本实现了!我们再来完善一下

批量删除

功能分析:

实现批量删除的办法其实有很多,我这里是把批量传入的id放进数组里,然后后端用for循环遍历删除。


js

async batchDelete(){
            // 组装id
            let delIds = "";
            for(let i=0;i 
模糊查询 多条件查询 

思考一下该怎么写,代码在上面已贴出

Elementui 实现分页查询

使用npm 安装完ui插件后,改下官网模板


    

参数解释:

​ @size-change:每页条数通过下拉列表框发生改变

​ @current-change:当前页码发生改变

​ current-page:当前是第几页 2

​ page-sizes:下拉列表框,设置每页显示条数

​ page-size:每页显示条数 3

​ total:该数据在数据库里的总条数 16,作用:计算总页数

js

        handleSizeChange(val) {
            console.log(`每页 ${val} 条`);
            this.teacherSearchVo.rows = val
            this.initTeaList()

        },
        handleCurrentChange(val) {
            console.log(`当前页: ${val}`);
            this.teacherSearchVo.page = val
            this.initTeaList()
        },
后记

博客主页:manor的博客_小小manor_CSDN博客-Java,全栈,大数据领域博主
欢迎点赞  收藏 ⭐留言  如有错误敬请指正!
本文由 manor 原创,首发于 CSDN博客

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/434477.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号