SpringBoot日记本系统全程直播07:把日记分类管理的增删改查搞起来撒~

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: SpringBoot日记本系统全程直播07:把日记分类管理的增删改查搞起来撒~

哈哈,我又来了,今天还是继续来撸这个《SpringBoot日记本系统》!

这一节,我们把日记分类管理的增删改查搞起来。

创建类型表:

/*
Navicat MySQL Data Transfer
Source Server         : mysql
Source Server Version : 50531
Source Host           : localhost:3306
Source Database       : diary
Target Server Type    : MYSQL
Target Server Version : 50531
File Encoding         : 65001
Date: 2022-04-17 13:52:56
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for sys_blog_type
-- ----------------------------
DROP TABLE IF EXISTS `sys_blog_type`;
CREATE TABLE `sys_blog_type` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type_name` varchar(20) DEFAULT NULL,
  `create_date` varchar(20) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


1.png


为了方便起见,这次我们用MP的自动生成工具,添加依赖:

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-generator</artifactId>
  <version>3.5.0</version>
</dependency>
<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity</artifactId>
  <version>1.7</version>
</dependency>


编写启动类: AutoGeneratorConfig

package com.rabbit.diary.util;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.Scanner;
public class AutoGeneratorConfig {
    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }
    public static <FileOutConfig> void main(String[] args) {
        String projectPath = System.getProperty("user.dir");
        // 全局配置
        GlobalConfig gc = new GlobalConfig.Builder()
                .author("剽悍一小兔")
                .outputDir(projectPath + "/src/main/java")
                .openDir(false).build();
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig.Builder("jdbc:mysql://localhost:3306/diary?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC","root","").build();
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator(dsc);
        mpg.global(gc);
        // 包配置
        PackageConfig pc = new PackageConfig.Builder()
                .controller("web")
                .entity("bean")
                .mapper("dao")
                .service("service")
                .serviceImpl("service.impl")
                .parent("com.rabbit.diary").build();
        mpg.packageInfo(pc);
        // 5、策略配置
        StrategyConfig strategy = new StrategyConfig.Builder()
                .addInclude(scanner("数据表名"))
                .addTablePrefix("")
                .entityBuilder()
                // 数据库表映射到实体的命名策略,驼峰命名法
                .naming(NamingStrategy.underline_to_camel)
                //数据库表字段映射到实体的命名策略
                .columnNaming(NamingStrategy.underline_to_camel)
                // lombok 模型 @Accessors(chain = true) setter链式操作
                .enableLombok()
                .controllerBuilder()
                //restful api风格控制器
                .enableRestStyle()
                //url中驼峰转连字符
                .enableHyphenStyle().build();
        mpg.strategy(strategy);
        mpg.execute();
    }
}


作用就是根据表名,自动生成各种文件。我没有用自定义模板,因为项目比较简单,为了最大的灵活性,感觉没必要。

运行

13:51:28.591 [main] DEBUG com.baomidou.mybatisplus.generator.AutoGenerator - ==========================准备生成文件...==========================
13:51:28.607 [main] WARN com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine - Velocity 1.x is outdated, please upgrade to 2.x or later.
13:51:29.404 [main] DEBUG com.baomidou.mybatisplus.generator.config.querys.MySqlQuery - 执行SQL:show table status WHERE 1=1  AND NAME IN ('sys_blog_type')
13:51:29.466 [main] DEBUG com.baomidou.mybatisplus.generator.config.querys.MySqlQuery - 返回记录数:1,耗时(ms):58
13:51:29.513 [main] DEBUG com.baomidou.mybatisplus.generator.config.querys.MySqlQuery - 执行SQL:show full fields from `sys_blog_type`
13:51:29.529 [main] DEBUG com.baomidou.mybatisplus.generator.config.querys.MySqlQuery - 返回记录数:4,耗时(ms):28
13:51:29.779 [main] DEBUG com.baomidou.mybatisplus.generator.AutoGenerator - ==========================文件生成完成!!!==========================


我们先把后台写好,类别这种东西,没必要分页了,直接来个搜全部的方法。

@RestController
@RequestMapping("/sys-blog-type")
@SaCheckLogin
public class SysBlogTypeController {
    @Autowired
    ISysBlogTypeService sysBlogTypeService;
    @RequestMapping("/selectAll")
    public List<SysBlogType> selectAll(){
        return sysBlogTypeService.selectAll();
    }
}


我在类上加了SaCheckLogin,表示跟类别有关的所有方法都需要登录。(PS:生成的@RequestMapping("//sys-blog-type")不知道为啥有两个 / ,改成一个/的)

实现类:

@Service
public class SysBlogTypeServiceImpl extends ServiceImpl<SysBlogTypeMapper, SysBlogType> implements ISysBlogTypeService {
    @Autowired
    SysBlogTypeMapper sysBlogTypeMapper;
    @Override
    public List<SysBlogType> selectAll() {
        QueryWrapper<SysBlogType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", StpUtil.getLoginId());
        return sysBlogTypeMapper.selectList(queryWrapper);
    }
}


SysBlogTypeMapper 生成出来没有加@Mapper,我们给他加上。

@Mapper
public interface SysBlogTypeMapper extends BaseMapper<SysBlogType> {
}


接下来,我们继续写和日记类别有关的后台接口。

新增或者修改

/**
 * 新增或者修改
 * @return
 */
@RequestMapping("/add")
@SaCheckLogin
public Result add(@RequestBody SysBlogType sysBlogType){
    //新增
    if(StrUtil.isBlankIfStr(sysBlogType.getId())){
        //拼装BlogBean
        sysBlogType.setCreateDate(DateUtil.now());
        sysBlogType.setUserId(StpUtil.getLoginIdAsInt());
        sysBlogTypeService.save(sysBlogType);
    }else{
        //修改
        SysBlogType sysBlogType2 = sysBlogTypeService.selectOne(sysBlogType.getId());
        BeanUtil.copyProperties(sysBlogType,sysBlogType2);
        sysBlogTypeService.updateById(sysBlogType2);
    }
    return Result.success();
}


和日记的保存差不多,也是根据是否有id来判断新增还是修改。

sysBlogTypeService.save实现:

@Override
public List<SysBlogType> selectAll() {
    QueryWrapper<SysBlogType> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("user_id", StpUtil.getLoginId());
    return sysBlogTypeMapper.selectList(queryWrapper);
}


根据当前登录用户,查询其所拥有的所有的类型。

前端代码:

getData(){
  var index = layer.load(1); //添加laoding,0-2两种方式
  axios.post('${basePath}/sys-blog-type/selectAll',{}).then(r =>{
    layer.close(index);    //返回数据关闭loading
    if(r.data.code != '0000'){
      layer.msg(r.data.message,{icon:2});
      return;
    }
    console.log(r.data.data);
    this.listData = r.data.data;
  }).catch(error => {
    layer.msg(error.response.status,{icon:2});
    layer.close(index);    //返回数据关闭loading
  })
},


用的是vue,渲染代码如下

<tr v-for="item in listData">
  <td>{{item.id}}</td>
  <td>{{item.typeName}}</td>
  <td>{{item.createDate}}</td>
  <td>
    <a :href="'${basePath}/diary/blogType/add.html?id='+item.id"><button type="button" class="layui-btn layui-btn-normal layui-btn-sm">修改</button></a>
    <button @click="del(item.id)" type="button" class="layui-btn layui-btn-danger layui-btn-sm">删除</button>
  </td>
</tr>


因为代码实在太多,不适合全部贴出来,所以我只贴核心的。大家可以到时候下载源码,进行比对和运行。

界面效果:


2.png


新增功能,根据新增按钮跳转到新增页面。


3.png


提交后:


4.png


修改和删除功能和日记模块差不多,只是删除的时候,我们需要加一些特定的逻辑。

@RequestMapping("/delete")
@SaCheckLogin
public Result delete(@RequestParam Integer id ){
    //检查是否是自己创建类型
    SysBlogType sysBlogType = sysBlogTypeService.selectOne(id);
    Integer userId = sysBlogType.getUserId();
    if(!userId.equals(StpUtil.getLoginIdAsInt()) ){
        throw new BizException(ExceptionCodeEnum.ERROR_PARAM.setDesc("您无法删除他人的日记类型!"));
    }
    //检查是否有该类型的日记,如果有,则不允许删除
    Integer sysBlogTypeId = sysBlogType.getId();
    Page<TblSynBlog> pageBean = new Page<>(1,10);
    TblSynBlog blog = new TblSynBlog();
    blog.setBlogType(String.valueOf(sysBlogTypeId));
    Page<TblSynBlog> page = blogService.selectPage(pageBean,blog);
    if(page.getTotal() > 0){
        throw new BizException(ExceptionCodeEnum.ERROR_PARAM.setDesc("该类别下还有"+page.getTotal()+"篇日记,不允许删除!"));
    }
    sysBlogTypeService.delete(id);
    return Result.success();
}


大概意思呢,就是用户只能删除自己的日记类型,而且如果已经有了该类型的日记,则不允许删除。 哦对了,我们还需要做一下日记分类的菜单选中效果。


6.png


layui.use(['jquery', 'layer'], function(){
  let $ = layui.$;
  let pathName = window.location.pathname;
  switch (pathName) {
    case "/diary/add.html":
      $('.layui-nav-item').eq(2).addClass("layui-this").siblings().removeClass("layui-this")
          break;
    case "/diary/blogType.html":
      $('.layui-nav-item').eq(3).addClass("layui-this").siblings().removeClass("layui-this")
      break;
  }
});


7.png


右侧模块的日记分类,之前是写死的,现在改成动态的。


8.png


这个模块是分出去的,我们采用vue的方式,给这个模块最外层的div加一个id,然后用Vue去控制。

<div class="layui-row" id="sider">
    ...
</div>


下面去新建一个Vue对象。

new Vue({
  el:'#sider',
  data:{
    typelist:[]
  },
  methods:{
    getTypelist(){
      var index = layer.load(1); //添加laoding,0-2两种方式
      axios.post('${basePath}/sys-blog-type/selectAll',{}).then(r =>{
        layer.close(index);    //返回数据关闭loading
        if(r.data.code != '0000'){
          layer.msg(r.data.message,{icon:2});
          return;
        }
        this.typelist = r.data.data;
      }).catch(error => {
        layer.msg(error.response.status,{icon:2});
        layer.close(index);    //返回数据关闭loading
      })
    }
  },
  created(){
    this.getTypelist();
  }
});


渲染li元素

<ul class="tlist">
  <li v-for="item in typelist"> <a href="">{{item.typeName}}</a></li>
</ul>


效果:


9.png


我刚才又添加了一笔数据,证明是可行的。

下一个问题,当我点击某一个日记类别应该发生什么呢?

我想,应该就是跳转到首页,然后首页展示的就是该类别的数据吧!

改变后的li元素

<li v-for="item in typelist"> <a :href="'${basePath}?typeId='+item.id">{{item.typeName}}</a></li>


地址栏是 http://localhost/?typeId=1

有点丑。额,先这样吧,不管了。

这边我们做一个改动,把layPage的引入代码放到list.jsp。

layui.use('laypage', function(){
  var laypage = layui.laypage;
  window.laypage = laypage; //绑定到windows对象上,方便vue去获取
});


然后呢,我们要根据是否有typeId传过来,显示不同的内容。

查询日记的axios改成

axios.post('${basePath}/blog/select?pageIndex='+this.pageIndex+'&size=' + this.size,{
  typeId:'${typeId}'
})


刷新页面,看到参数已经传过去了。


10.png


后台关键代码

public Page<TblSynBlog> selectPage(Page<TblSynBlog> pageBean, TblSynBlog blog) {
    QueryWrapper<TblSynBlog> queryWrapper = new QueryWrapper<>();
    queryWrapper.orderByDesc("update_date");
    //只允许查看自己发布的日记
    queryWrapper.eq("user_id", StpUtil.getLoginId());
    queryWrapper.eq("is_delete", "0");
    if(StrUtil.isNotEmpty(blog.getBlogType())){
        queryWrapper.eq("blog_type",blog.getBlogType());
    }
    return blogMapper.selectPage(pageBean,queryWrapper);
}


很简单吧,就看下type传过来没有,有的话就把条件加上,搞定。


11.png


前端再加一个小提示,只要没有日记,就显示。

computed:{
  empty(){
    return this.total == 0
  }
},


html:

<div id="dlist" class="layui-card dbox" style="border-right: 2px solid #eaeaea;">
  <div class="layui-card-header"><b><i class="layui-icon layui-icon-list" style="color: #000;"></i></b>日记列表</div>
  <div class="layui-card-body">
    <ul class="dlist">
      <li v-for="item in datalist"><a :href="'${basePath}/diary/' + item.id + '.html'">{{item.title}}</a></li>
    </ul>
    {{empty?'该类型还没有日记哦,快去写一篇吧!':''}}
    <div id="pageCode"></div>
  </div>
</div>


效果:


12.png


好啦,这一讲就到此为止了,总结一下,这一节的内容主要是日记类型的增删改查,还有MP自动生成代码的方法。


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
22天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的老孙电子点菜系统的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的老孙电子点菜系统的详细设计和实现
29 1
|
2天前
|
前端开发 Java 关系型数据库
Java医院绩效考核系统源码B/S架构+springboot三级公立医院绩效考核系统源码 医院综合绩效核算系统源码
作为医院用综合绩效核算系统,系统需要和his系统进行对接,按照设定周期,从his系统获取医院科室和医生、护士、其他人员工作量,对没有录入信息化系统的工作量,绩效考核系统设有手工录入功能(可以批量导入),对获取的数据系统按照设定的公式进行汇算,且设置审核机制,可以退回修正,系统功能强大,完全模拟医院实际绩效核算过程,且每步核算都可以进行调整和参数设置,能适应医院多种绩效核算方式。
21 2
|
3天前
|
运维 监控 Java
springboot基层区域HIS系统源码
医疗(医院)机构正式使用云HIS系统之前,要先进行院内基础数据的配置,主要在数据管理模块中进行,由系统管理员来操作。
10 0
|
4天前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
46 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
|
22天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的4S店客户管理系统的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的4S店客户管理系统的详细设计和实现
44 4
|
22天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的汽车保养系统的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的汽车保养系统的详细设计和实现
10 1
|
22天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的个人行政复议在线预约系统的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的个人行政复议在线预约系统的详细设计和实现
29 1
|
22天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的医院核酸检测服务系统的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的医院核酸检测服务系统的详细设计和实现
39 0
|
22天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的购物系统平台的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的购物系统平台的详细设计和实现
30 0
|
23天前
|
人工智能 移动开发 前端开发
Springboot医院智慧导诊系统源码:精准推荐科室
医院智慧导诊系统是在医疗中使用的引导患者自助就诊挂号,在就诊的过程中有许多患者不知道需要挂什么号,要看什么病,通过智慧导诊系统,可输入自身疾病的症状表现,或选择身体部位,在经由智慧导诊系统多维度计算,精准推荐科室,引导患者挂号就诊,实现科学就诊,不用担心挂错号。
35 2