SpringBoot+Vue+Mybatis-plus 博客(五):完成分类管理和标签管理前后端对接

小L星光博客 专栏收录该内容
8 篇文章 6 订阅

SpringBoot+Vue+Mybatis-plus 博客:个人博客介绍及效果展示
SpringBoot+Vue+Mybatis-plus 博客(一):完成博客后台前端登录页面、后端登录接口
SpringBoot+Vue+Mybatis-plus 博客(二):完成登录的前后端对接、完善左侧菜单栏
SpringBoot+Vue+Mybatis-plus 博客(三):完成搜索及博客列表展示功能前后端
SpringBoot+Vue+Mybatis-plus 博客(四):完成发布文章、编辑文章、删除文章及查询文章功能
SpringBoot+Vue+Mybatis-plus 博客(五):完成分类管理和标签管理前后端对接
SpringBoot+Vue+Mybatis-plus 博客(六):完成评论管理前后端交互
SpringBoot+Vue+Mybatis-plus 博客(七):完成友链管理前后端对接

效果

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

一、分类管理后端接口

1、TTypeService

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author 关注公众号:小L星光
 * @since 2020-11-30
 */
public interface TTypeService extends IService<TType> {

    RespBean pageTypes(Long current, Long size);

    RespBean getTypeByName(String name);

    RespBean deleteTypeById(Long id);

    RespBean updateType(TType tType);

    RespBean getTypeById(Long id);
}

2、TTypeServiceImpl

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 关注公众号:小L星光
 * @since 2020-11-30
 */
@Service
public class TTypeServiceImpl extends ServiceImpl<TTypeMapper, TType> implements TTypeService {

    @Autowired
    TTypeMapper tTypeMapper;

    @Override
    public RespBean pageTypes(Long current, Long size) {
        RespBean respBean = RespBean.build();
        //创建Page对象
        Page<TType> typePage = new Page<>(current,size);
        //构建条件
        QueryWrapper<TType> wrapper = new QueryWrapper<>();
        //调用mybatis plus分页方法进行查询
        tTypeMapper.selectPage(typePage,wrapper);
        //通过Page对象获取分页信息
        List<TType> typeList = typePage.getRecords(); //每页的数据 list集合
        long pagesize = typePage.getSize(); //每页显示的条数
        long total = typePage.getTotal(); //总记录数
        long pages = typePage.getPages(); //总页数

        respBean.setStatus(200);
        respBean.setObj(typePage);
        return respBean;
    }

    /**
     * 通过名称查询分类
     * @param name
     * @return
     */
    @Override
    public RespBean getTypeByName(String name) {
        RespBean respBean = RespBean.build();
        QueryWrapper<TType> queryWrapper = new QueryWrapper<TType>();
        queryWrapper.like("name",name);
        List<TType> typeList = tTypeMapper.selectList(queryWrapper);
        respBean.setStatus(200);
        respBean.setObj(typeList);
        return respBean;
    }

    @Override
    public RespBean deleteTypeById(Long id) {
        RespBean respBean = RespBean.build();
        if (tTypeMapper.deleteById(id) == 1){
            respBean.setStatus(200);
            respBean.setMsg("删除分类成功");
            return respBean;
        }
        respBean.setMsg("删除分类失败");
        return respBean;
    }

    @Override
    public RespBean updateType(TType tType) {
        RespBean respBean = RespBean.build();
        if (tTypeMapper.updateById(tType) == 1){
            respBean.setMsg("更新分类成功");
            respBean.setStatus(200);
            return respBean;
        }
        respBean.setMsg("更新分类失败");
        return respBean;
    }

    @Override
    public RespBean getTypeById(Long id) {
        RespBean respBean = RespBean.build();
        TType tType = tTypeMapper.selectById(id);
        respBean.setStatus(200);
        respBean.setObj(tType);
        return respBean;
    }

}

3、TTypeController

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 关注公众号:小L星光
 * @since 2020-11-30
 */
@RestController
@RequestMapping("/type")
public class TTypeController {

    @Autowired
    TTypeService tTypeService;

    RespBean respBean = RespBean.build();

    /**
     * 保存分类专栏
     * @param tType
     * @return
     */
    @PostMapping("/saveType")
    public RespBean saveType(@RequestBody TType tType){
        if (StringUtils.isEmpty(tType.getName())){
            respBean.setStatus(500);
            respBean.setMsg("分类专栏名称不能为空!");
            return respBean;
        }
        QueryWrapper<TType> queryWrapper = new QueryWrapper<TType>();
        queryWrapper.eq("name",tType.getName());
        List<TType> tBlogList = tTypeService.list(queryWrapper);
        if (tBlogList.size() > 0){
            respBean.setStatus(500);
            respBean.setMsg("添加失败,已有该分类专栏名称");
            return respBean;
        }
        Boolean result = tTypeService.save(tType);
        if (result){
            respBean.setStatus(200);
            respBean.setMsg("添加成功!");
            return respBean;
        }else {
            respBean.setStatus(500);
            respBean.setMsg("添加失败!");
            return respBean;
        }

    }

    /**
     * 查询所有分类
     * @return
     */
    @GetMapping("/getAllType")
    public RespBean getAllType(){
        List<TType> typeList = tTypeService.list();
        return RespBean.ok("查询成功!",typeList);
    }

    /**
     * 分类的分页查询
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/getTypeByPage")
    @ApiOperation("分类的分页查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current",value = "当前页") ,
            @ApiImplicitParam(name = "size",value = "每页的数量"),
    })
    public RespBean getByPage(Long current, Long size){
        return tTypeService.pageTypes(current, size);
    }

    /**
     * 通过名称查找分类
     * @param name
     * @return
     */
    @GetMapping("/getTypeByName")
    public RespBean getTypeByName(String name){
        return tTypeService.getTypeByName(name);
    }

    /**
     * 更新分类
     * @param tType
     * @return
     */
    @PutMapping("/updateType")
    public RespBean updateType(@RequestBody TType tType){
        if (StringUtils.isEmpty(tType.getName())){
            respBean.setMsg("分类名称不能为空");
            return respBean;
        }
        return tTypeService.updateType(tType);
    }

    /**
     * 删除分类
     * @param id
     * @return
     */
    @DeleteMapping("deleteTypeById")
    public RespBean deleteTypeById(Long id){
        return tTypeService.deleteTypeById(id);
    }

    /**
     * 根据id查询分类
     * @param id
     * @return
     */
    @GetMapping("/getTypeById")
    public RespBean getTypeById(Long id){
        return tTypeService.getTypeById(id);
    }

}

4、测试

更新分类
在这里插入图片描述
删除分类
在这里插入图片描述
通过名称查找
在这里插入图片描述
分页
在这里插入图片描述

二、标签管理后端接口

1、TTagService

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author 关注公众号:小L星光
 * @since 2020-11-30
 */
public interface TTagService extends IService<TTag> {

    RespBean pageTags(Long current, Long size);

    RespBean getTagByName(String name);

    RespBean updateTag(TTag tTag);

    RespBean deleteTagById(Long id);
    
    RespBean getTagById(Long id);
}

2、TTagServiceImpl

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 关注公众号:小L星光
 * @since 2020-11-30
 */
@Service
public class TTagServiceImpl extends ServiceImpl<TTagMapper, TTag> implements TTagService {

    @Autowired
    TTagMapper tTagMapper;

    @Override
    public RespBean pageTags(Long current, Long size) {
        RespBean respBean = RespBean.build();
        //创建Page对象
        Page<TTag> tagPage = new Page<>(current,size);
        //构建条件
        QueryWrapper<TTag> wrapper = new QueryWrapper<>();
        //调用mybatis plus分页方法进行查询
        tTagMapper.selectPage(tagPage,wrapper);
        //通过Page对象获取分页信息
        List<TTag> typeList = tagPage.getRecords(); //每页的数据 list集合
        long pagesize = tagPage.getSize(); //每页显示的条数
        long total = tagPage.getTotal(); //总记录数
        long pages = tagPage.getPages(); //总页数

        respBean.setStatus(200);
        respBean.setObj(tagPage);
        return respBean;
    }

    @Override
    public RespBean getTagByName(String name) {
        RespBean respBean = RespBean.build();
        QueryWrapper<TTag> queryWrapper = new QueryWrapper<TTag>();
        queryWrapper.like("name",name);
        List<TTag> tagList = tTagMapper.selectList(queryWrapper);
        respBean.setStatus(200);
        respBean.setObj(tagList);
        return respBean;
    }

    @Override
    public RespBean updateTag(TTag tTag) {
        RespBean respBean = RespBean.build();
        if (tTagMapper.updateById(tTag) == 1){
            respBean.setMsg("更新标签成功");
            respBean.setStatus(200);
            return respBean;
        }
        respBean.setMsg("更新标签失败");
        return respBean;
    }

    @Override
    public RespBean deleteTagById(Long id) {
        RespBean respBean = RespBean.build();
        if (tTagMapper.deleteById(id) == 1){
            respBean.setStatus(200);
            respBean.setMsg("删除标签成功");
            return respBean;
        }
        respBean.setMsg("删除标签失败");
        return respBean;
    }

    @Override
    public RespBean getTagById(Long id) {
        RespBean respBean = RespBean.build();
        TTag tTag = tTagMapper.selectById(id);
        respBean.setStatus(200);
        respBean.setObj(tTag);
        return respBean;
    }

}

3、TTagController

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 关注公众号:小L星光
 * @since 2020-11-30
 */
@RestController
@RequestMapping("/tag")
public class TTagController {

    @Autowired
    TTagService tTagService;

    RespBean respBean = RespBean.build();

    @PostMapping("/saveTag")
    public RespBean saveTag(@RequestBody TTag tTag){
        if (StringUtils.isEmpty(tTag.getName())){
            respBean.setStatus(500);
            respBean.setMsg("标签名称不能为空!");
            return respBean;
        }
        QueryWrapper<TTag> queryWrapper = new QueryWrapper<TTag>();
        queryWrapper.eq("name",tTag.getName());
        List<TTag> tagList = tTagService.list(queryWrapper);
        if (tagList.size() > 0){
            respBean.setStatus(500);
            respBean.setMsg("添加失败,已有该标签名称");
            return respBean;
        }
        Boolean result = tTagService.save(tTag);
        if (result){
            respBean.setStatus(200);
            respBean.setMsg("添加标签成功!");
            return respBean;
        }else {
            respBean.setStatus(500);
            respBean.setMsg("添加标签失败!");
            return respBean;
        }

    }

    /**
     * 查询所有标签
     * @return
     */
    @GetMapping("/getAllTag")
    public RespBean getAllTag(){
        List<TTag> tagList = tTagService.list();
        return RespBean.ok("查询成功!",tagList);
    }

    /**
     * 标签的分页查询
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/getTagByPage")
    @ApiOperation("标签的分页查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current",value = "当前页") ,
            @ApiImplicitParam(name = "size",value = "每页的数量"),
    })
    public RespBean getTagByPage(Long current, Long size){
        return tTagService.pageTags(current, size);
    }

    /**
     * 通过名称查找标签
     * @param name
     * @return
     */
    @GetMapping("/getTagByName")
    public RespBean getTagByName(String name){
        return tTagService.getTagByName(name);
    }

    /**
     * 更新标签
     * @param tTag
     * @return
     */
    @PutMapping("/updateTag")
    public RespBean updateTag(@RequestBody TTag tTag){
        if (StringUtils.isEmpty(tTag.getName())){
            respBean.setMsg("分类名称不能为空");
            return respBean;
        }
        return tTagService.updateTag(tTag);
    }

    /**
     * 删除标签
     * @param id
     * @return
     */
    @DeleteMapping("deleteTagById")
    public RespBean deleteTagById(Long id){
        return tTagService.deleteTagById(id);
    }

    /**
     * 根据id查询标签
     * @param id
     * @return
     */
    @GetMapping("/getTagById")
    public RespBean getTagById(Long id){
        return tTagService.getTagById(id);
    }

}

4、测试

查询所有标签
在这里插入图片描述
分页
在这里插入图片描述
通过名称查找标签
在这里插入图片描述
添加标签
在这里插入图片描述
更新标签
在这里插入图片描述
删除标签
在这里插入图片描述

三、分类、标签管理前端

1、CategoryBlog.vue

在这里插入图片描述

<template>
  <div>
      <div style="margin-top: 20px;">
          <!-- 搜索 -->
          <el-input size="small" v-model="input_name" placeholder="请输入分类名称,可回车搜索..." prefix-icon="el-icon-search"
          style="width: 400px;margin-right: 10px;" @keydown.enter.native="search_name"></el-input>
          <el-button size="small" type="primary"  @click="search_name" icon="el-icon-search">搜索</el-button>
          <el-button size="small" type="success"  @click="dialog_add = true" icon="el-icon-plus">新增</el-button>
      </div>
      <div>
          <el-table
          :data="typeData"
          style="width: 50%">
          <el-table-column
            label="编号"
            width="230">
            <template slot-scope="scope"> 
              <span style="margin-left: 10px">{{ scope.row.id }}</span>
            </template>
          </el-table-column>
          <el-table-column
            label="名称"
            width="230">
            <template slot-scope="scope">
              <el-tag size="medium">{{ scope.row.name }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button
                size="mini"
                @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
              <el-button
                size="mini"
                type="danger"
                @click="handleDelete(scope.$index, scope.row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <!-- 分页 -->
      <div style="margin-top: 20px;">
        <el-pagination
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page.sync="currentPage"
        :page-size="pagesize"
        layout="total, prev, pager, next"
        :total="total">
      </el-pagination>
      </div>

       <!-- 对话框 新建分类专栏 -->
       <el-dialog
       title="新建分类专栏"
       :visible.sync="dialog_add"
       width="30%"
       >
       <el-form status-icon  label-width="120px">
         <el-form-item label="分类专栏名">
           <el-input v-model="type_add.name" placeholder="请输入要新建的分类专栏名"
           :rules="{
            required: true, message: '文章类型不能为空', trigger: 'blur'
            }"></el-input>
         </el-form-item>
       </el-form>
        <span slot="footer" class="dialog-footer">
           <el-button @click="dialog_add = false">取 消</el-button>
           <el-button type="primary" @click="addNewType">确 定</el-button>
         </span>
     </el-dialog>

      <!-- 对话框 编辑分类专栏 -->
      <el-dialog
      title="编辑分类专栏"
      :visible.sync="dialog_edit"
      width="30%"
      >
      <el-form status-icon  label-width="120px">
        <el-form-item label="分类专栏名">
          <el-input v-model="type_edit.name"
          :rules="{
            required: true, message: '文章类型不能为空', trigger: 'blur'
            }"></el-input>
        </el-form-item>
      </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="dialog_edit = false">取 消</el-button>
          <el-button type="primary" @click="updateType">确 定</el-button>
        </span>
      </el-dialog>

  </div>
</template>

<script>
export default {
  name: 'CategoryBlog',
  data () {
   return {
      typeData:[],  //分类数据
      currentPage: 1,  //当前页
      total:0, //总记录数
      pagesize:5, //页面大小
      input_name:'', //搜索框值
      dialog_add: false, //添加分类的对话框
      dialog_edit: false, //编辑分类的对话框
      type_add:{
        name:'',  //分类名称
      },
      type_edit:{
        id:'',
        name:''
      }
   }
  },
  mounted() {
    this.initType();
  },
  methods:{
    //初始化分类数据
    initType(){
      const _this = this
      this.getRequest('/type/getTypeByPage?current=' + this.currentPage + '&size=' + this.pagesize).then(resp=>{
        console.log(resp)
        _this.typeData = resp.obj.records
        _this.total = resp.obj.total
      })
    },
    //编辑分类
    handleEdit(index, row) {
      const _this = this
      console.log(index, row);
      this.dialog_edit = true
      this.getRequest('/type/getTypeById?id=' + row.id).then(resp=>{
          console.log(resp)
          _this.type_edit = resp.obj
      })
    },
    //更新分类
    updateType(){
      const _this = this 
      this.putRequest('/type/updateType',this.type_edit).then(resp=>{
        if(resp){
          this.initType()
          _this.dialog_edit = false
        }
      })
    },
    //删除分类
    handleDelete(index, row) {
      console.log(index, row);
      const _this = this
      this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.deleteRequest('/type/deleteTypeById?id=' + row.id).then(resp=>{
            if(resp){
              this.initType()
            }
          })
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });          
        });
     
    },
    //添加分类
    addNewType(){
      const _this = this
      this.postRequest('/type/saveType',this.type_add).then(resp=>{
        console.log(resp)
        _this.input_name =''
        _this.dialog_add = false
      })
    },
    //搜索分类
    search_name(){
       const _this = this
       this.getRequest('/type/getTypeByName?name=' + this.input_name).then(resp=>{
         console.log(resp)
         if(_this.input_name == ''){
           _this.initTag();
         }else{
          _this.typeData = resp.obj
          _this.input_name = ''
         }
         

       })
    },
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
      this.currentPage = val
      this.initType()
    }
  }
}
</script>

<style scoped>

</style>

2、TagBlog.vue

在这里插入图片描述

<template>
  <div>
      <div style="margin-top: 20px;">
          <!-- 搜索 -->
          <el-input size="small" v-model="input_name" placeholder="请输入标签名称,可回车搜索..." prefix-icon="el-icon-search"
          style="width: 400px;margin-right: 10px;" @keydown.enter.native="search_name"></el-input>
          <el-button size="small" type="primary"  @click="search_name" icon="el-icon-search">搜索</el-button>
          <el-button size="small" type="success"  @click="dialog_add = true" icon="el-icon-plus">新增</el-button>
      </div>
      <div>
          <el-table
          :data="tagData"
          style="width: 50%">
          <el-table-column
            label="编号"
            width="230">
            <template slot-scope="scope"> 
              <span style="margin-left: 10px">{{ scope.row.id }}</span>
            </template>
          </el-table-column>
          <el-table-column
            label="名称"
            width="230">
            <template slot-scope="scope">
              <el-tag size="medium">{{ scope.row.name }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button
                size="mini"
                @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
              <el-button
                size="mini"
                type="danger"
                @click="handleDelete(scope.$index, scope.row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <!-- 分页 -->
      <div style="margin-top: 20px;">
        <el-pagination
        background
        @current-change="handleCurrentChange"
        :current-page.sync="currentPage"
        :page-size="pagesize"
        layout="total, prev, pager, next"
        :total="total">
      </el-pagination>
      </div>

       <!-- 对话框 新建标签 -->
       <el-dialog
       title="新建标签"
       :visible.sync="dialog_add"
       width="30%"
       >
       <el-form status-icon  label-width="120px">
         <el-form-item label="标签名称">
           <el-input v-model="tag_add.name" placeholder="请输入要新建的标签名称"
           :rules="{
            required: true, message: '不能为空', trigger: 'blur'
            }"></el-input>
         </el-form-item>
       </el-form>
        <span slot="footer" class="dialog-footer">
           <el-button @click="dialog_add = false">取 消</el-button>
           <el-button type="primary" @click="addNewTag">确 定</el-button>
         </span>
     </el-dialog>

      <!-- 对话框 编辑标签 -->
      <el-dialog
      title="编辑标签"
      :visible.sync="dialog_edit"
      width="30%"
      >
      <el-form status-icon  label-width="120px">
        <el-form-item label="标签名称">
          <el-input v-model="tag_edit.name"
          :rules="{
            required: true, message: '不能为空', trigger: 'blur'
            }"></el-input>
        </el-form-item>
      </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="dialog_edit = false">取 消</el-button>
          <el-button type="primary" @click="updateTag">确 定</el-button>
        </span>
      </el-dialog>

  </div>
</template>

<script>
export default {
  name: 'TagBlog',
  data () {
   return {
      tagData:[],  //标签数据
      currentPage: 1,  //当前页
      total:0, //总记录数
      pagesize:5, //页面大小
      input_name:'', //搜索框值
      dialog_add: false, //添加标签的对话框
      dialog_edit: false, //编辑标签的对话框
      tag_add:{
        name:'',  //标签名称
      },
      tag_edit:{
        id:'',
        name:''
      }
   }
  },
  mounted() {
    this.initTag();
  },
  methods:{
    //初始化分类数据
    initTag(){
      const _this = this
      this.getRequest('/tag/getTagByPage?current=' + this.currentPage + '&size=' + this.pagesize).then(resp=>{
        console.log(resp)
        _this.tagData = resp.obj.records
        _this.total = resp.obj.total
      })
    },
    //编辑分类
    handleEdit(index, row) {
      const _this = this
      console.log(index, row);
      this.dialog_edit = true
      this.getRequest('/tag/getTagById?id=' + row.id).then(resp=>{
          console.log(resp)
          _this.tag_edit = resp.obj
      })
    },
    //更新分类
    updateTag(){
      const _this = this 
      this.putRequest('/tag/updateTag',this.tag_edit).then(resp=>{
        if(resp){
          this.initTag()
          _this.dialog_edit = false
        }
      })
    },
    //删除分类
    handleDelete(index, row) {
      console.log(index, row);
      const _this = this
      this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.deleteRequest('/tag/deleteTagById?id=' + row.id).then(resp=>{
            if(resp){
              this.initTag()
            }
          })
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });          
        });
     
    },
    //添加分类
    addNewTag(){
      const _this = this
      this.postRequest('/tag/saveTag',this.tag_add).then(resp=>{
        console.log(resp)
        _this.input_name =''
        _this.dialog_add = false
      })
    },
    //搜索分类
    search_name(){
       const _this = this
       this.getRequest('/tag/getTagByName?name=' + this.input_name).then(resp=>{
         console.log(resp)
         if(_this.input_name == ''){
           _this.initTag();
         }else{
          _this.tagData = resp.obj
          _this.input_name = ''
         }
         

       })
    },
    //分页
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
      this.currentPage = val
      this.initTag()
    }
  }
}
</script>

<style scoped>

</style>

关注【小L星光】回复 “博客” 即可获整个项目源码 ~
在这里插入图片描述

  • 1
    点赞
  • 1
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值