个人博客-6(文章功能模块实现)

接口

声明:该项目是GitHub上的开源项目,本人已购买作者相关课程,仅供个人学习使用。
课程链接https://www.lanqiao.cn/courses/1367

  • 文章内容显示
  • 文章修改
  • 文章删除

页面

sidber.html

<li class="nav-item">
    <a th:href="@{/admin/blogs}" th:class="${path}=='blogs'?'nav-link active':'nav-link'">
        <i class="fa fa-list-alt nav-icon" aria-hidden="true"></i>
        <p>
            博客管理
        </p>
    </a>
</li>

BlogController

  • 控制跳转到文章管理页
//跳转到文章管理页面
@RequestMapping("/blogs")
public String toBlog(HttpServletRequest request){
    request.setAttribute("path","blogs");
    return "admin/blog";
}

blog.html

<div class="card card-primary card-outline">
   <div class="card-header">
       <h3 class="card-title">博客管理</h3>
   </div> <!-- /.card-body -->
   <div class="card-body">
       <div class="grid-btn">
           <button class="btn btn-success" onclick="addBlog()"><i
                   class="fa fa-plus"></i>&nbsp;新增
           </button>
           <button class="btn btn-info" onclick="editBlog()"><i
                   class="fa fa-edit"></i>&nbsp;修改
           </button>
           <button class="btn btn-danger" onclick="deleteBlog()"><i
                   class="fa fa-trash-o"></i>&nbsp;删除
           </button>&nbsp;&nbsp;
           <input type="text" placeholder="关键字(标题/分类)" id="keyword" 
           class="form-control col-2">&nbsp;
           <button class="btn btn-info" onclick="search()"><i
                   class="fa fa-search"></i>&nbsp;搜索
           </button>
       </div>
       <!-- JqGrid必要DOM,用于创建表格展示列表数据 -->
       <table id="jqGrid" class="table table-bordered"></table>
       <!-- JqGrid必要DOM,分页信息区域 -->
       <div id="jqGridPager"></div>
   </div><!-- /.card-body -->
</div>

在这里插入图片描述

文章内容展示

使用jqgrid

前端页面

<!-- JqGrid必要DOM,用于创建表格展示列表数据 -->
<table id="jqGrid" class="table table-bordered"></table>
<!-- JqGrid必要DOM,分页信息区域 -->
<div id="jqGridPager"></div>

blog.js

$(function () {
    //标签列表展示
    $("#jqGrid").jqGrid({
        //大括号内写属性
        //从服务器接收数据的请求
        url: '/admin/blogs/list',
        //接收到的数据格式
        datatype: "json",
        mtype:"POST",
        /*
            colModel:表格的列属性
            label:如果colNames为空则用此值来作为列的显示名称,如果都没有设置则使用name值
        */
        colNames:["id","标题","封面",'浏览量','状态','博客分类','添加时间'],
        colModel: [
            {name: 'blogId', index:'blogId', key: true, hidden: true},
            {name: 'blogTitle',index: 'blogTitle'},
            //格式化图片展示
            {name:'blogCoverImage',index:'blogCoverImage',align:'center',formatter:imgFormatter},//
            {name: 'blogViews',index: 'blogViews'},
            {name: 'blogStatus',index: 'blogStatus',formatter:function (cellvalue) {
            		//如果状态是0,显示草稿,否则显示发布
                    if (cellvalue == 0) {
                        return "<button type=\"button\"
                         class=\"btn btn-block btn-secondary btn-sm\" style=\"width: 50%;\">
                         草稿</button>";
                    }
                    else if (cellvalue == 1) {
                        return "<button type=\"button\"
                         class=\"btn btn-block btn-success btn-sm\" style=\"width: 50%;\">
                         发布</button>";
                    }
                }},
            {name: 'blogCategoryName',index: 'blogCategoryName'},
            {name: 'createTime',index: 'createTime'}
        ],
        rowNum: 5,
        styleUI: 'Bootstrap',
        autowidth: true,
        multiselect: true,
        height:443,

        pager: "#jqGridPager",
        //传递给后端的数据,page默认1,limit是rowNum设置的值,默认10
        prmNames: {
            page: "page",
            rows: "limit"
        },
        gridComplete: function () {
            //隐藏grid底部滚动条
            $("#jqGrid").closest(".ui-jqgrid-bdiv").css({"overflow-x": "hidden"});
        }
    })
});
function imgFormatter(cellvalue) {
    return "<a href='" + cellvalue + "'> <img src='" 
    + cellvalue + "' height=\"80\" width=\"130\" alt='icon'/></a>";
}

在这里插入图片描述

分页功能实现

工具类

PageUtil

//根据前端获取的参数创建一个map集合
//该集合包括开始索引,起始页,每页显示数据数
@Data
public class PageUtil extends LinkedHashMap<String, Object> {
    //当前页码
    private int currentPage;
    //每页条数
    private int pageSize;

    //根据前端传递的参数构造一个LinkedHashMap存放开始索引,
    public PageUtil(Map<String, Object> params) {
        this.putAll(params);
        //分页参数page在前端默认就是page
        this.currentPage = Integer.parseInt(params.get("page").toString());
        //limit在前端默认的是rows,通过prmNames进行映射,键值为limit
        this.pageSize = Integer.parseInt(params.get("limit").toString());
        this.put("start", (currentPage - 1) * pageSize);
        this.put("page", currentPage);
        this.put("pageSize", pageSize);
    }

}
dao层
//分页功能
List<Blog> findBlogList(PageUtil pageUtil);

//查询总数
int getTotalBlogs();
<!--start是当前页,默认1。pageSize是每页显示多少条数据 PageUtil中的属性-->
<select id="findBlogList" parameterType="map" resultType="blog">
    select *
    from rm_blog.blog
    where is_deleted=0
    order by create_time desc
    <if test="start!=null and pageSize!=null">
        limit #{start},#{pageSize}
    </if>
</select>


<select id="getTotalBlogs"  resultType="int">
	select count(*)  from blog
	where is_deleted=0
</select>
service层
//分页功能
List<Blog> findBlogList(PageUtil pageUtil);
//查询总数
int getTotalBlogs();
//根据总数,当前页,每页展示的条数创建一个结果页
PageResult getBlogPage(PageUtil pageUtil);
@Override
public List<Blog> findBlogList(PageUtil pageUtil) {
    return blogMapper.findBlogList(pageUtil);
}

@Override
public int getTotalBlogs() {
    return blogMapper.getTotalBlogs();
}

@Override
public PageResult getBlogPage(PageUtil pageUtil) {
    //查询所有的数据
    List<Blog> blogList = blogMapper.findBlogList(pageUtil);
    //查询总数
    int total = blogMapper.getTotalBlogs();
    //根据总数,当前页,每页展示的条数创建一个pageResult
    PageResult pageResult = 
    new PageResult(blogList, total,pageUtil.getPageSize(),pageUtil.getCurrentPage());
    return pageResult;
}

工具类pageResult

package com.rm.util;

import lombok.Data;
import java.io.Serializable;
import java.util.List;


//分页工具类
@Data
public class PageResult implements Serializable {

    //属性名不能修改,和js文件中的属性相同
    //如果不同,可以使用jsonReader进行映射

    //总记录数
    private int records;
    //每页记录数
    private int pageSize;
    //总页数
    private int total;
    //当前页数
    private int page;
    //列表数据
    private List<?> rows;


    public PageResult(List<?> list, int total, int pageSize, int currentPage) {
        //数据
        this.rows = list;
        //总数据数
        this.records = total;
        //每页展示几条数据
        this.pageSize = pageSize;
        //当前页
        this.page = currentPage;
        //总页数ceil:向上取整,小数部分直接舍去如:16/5 就是共4页
        this.total = (int) Math.ceil((double)records/pageSize);
    }

}

controller层
//查询所有的博客信息用于前端页面展示
@PostMapping("/blogs/list")
@ResponseBody //返回的是json数据格式
public PageResult list(@RequestParam Map<String, Object> params){
    //根据前端传递的起始页和每页显示的条数,创建一个map集合
    PageUtil pageUtil = new PageUtil(params);

    //结果以json数据发送给前端,包括(列表数据,总记录数,总页数,每页多少条数据,当前页)
    return blogService.getBlogPage(pageUtil);
}
结果

在这里插入图片描述

新增功能实现

点击新增按钮,跳到博客管理页面

<button class="btn btn-success" onclick="addBlog()"><i
        class="fa fa-plus"></i>&nbsp;新增
</button>
//新增博客
function addBlog() {
    window.location.href = "/admin/blogs/edit";
}

删除功能实现

软删除

  • is_deleted字段设置为1
<button class="btn btn-danger" onclick="deleteBlog()"><i
        class="fa fa-trash-o"></i>&nbsp;删除
</button>&nbsp;&nbsp;

blog.js

  • 可以多选删除
function deleteBlog() {
    var ids = getSelectedRows();
    if (ids == null) {
        return;
    }
    $.ajax({
        type: "POST",
        url: "/admin/blogs/delete",
        contentType: "application/json",
        data: JSON.stringify(ids),
        success: function (r) {
            if (r>0) {
                swal("删除成功", {
                    icon: "success",
                });
                $("#jqGrid").trigger("reloadGrid");
            } else {
                swal("删除失败", {
                    icon: "error",
                });
            }
        }
    });
}

/**
 * jqGrid重新加载
 */
function reload() {
    var page = $("#jqGrid").jqGrid('getGridParam', 'page');
    $("#jqGrid").jqGrid('setGridParam', {
        page: page
    }).trigger("reloadGrid");
}
controller层
//删除博客
@PostMapping("/blogs/delete")
@ResponseBody
public int delete(@RequestBody Integer[] ids) {
    int i=0;
    for (Integer id : ids) {
        i=blogService.deleteById(id);
    }
    return i;
}
service层
 @Override
    public int deleteById(int blogId) {
        return blogMapper.deleteById(blogId);
    }
dao层
<!--通过id删除博客-->
<update id="deleteById" parameterType="blog">
    update rm_blog.blog set is_deleted =1  where blog_id=#{blogId};
</update>

编辑功能实现

选中文章点击修改,会根据id跳转到博客管理页面,页面显示有查询出来的内容

  • 想要修改一篇文章,首先需要获取这篇文章的所有属性,之后再回显到编辑页面中,用户根据需要来修改页面上的内容,点击保存按钮后会想后端发送文章修改请求,后端接口接收到请求后会进行参数验证以及相应的逻辑操作,之后进行数据的入库操作,整个文章修改流程完成。
<button class="btn btn-info" onclick="editBlog()"><i
        class="fa fa-edit"></i>&nbsp;修改
</button>

获取选择文章的id,交给controller处理
blog.js

function editBlog() {
    var id = getSelectedRow();
    if (id == null) {
        return;
    }
    window.location.href = "/admin/blogs/edit/" + id;
}

BlogController
接收选择文章的id,查询该id的文章内容,回显到前端

  • 将blog和categories存入到request中
 //修改内容页
@GetMapping("/blogs/edit/{blogId}")
public String edit(HttpServletRequest request, @PathVariable("blogId") int blogId) {
    request.setAttribute("path", "edit");
    Blog blog = blogService.selectById(blogId);
    if (blog == null) {
        return "error/error_400";
    }
    request.setAttribute("blog", blog);
    request.setAttribute("categories", categoryService.getAllCategories());
    return "admin/edit";
}

回显到前端页面
id

  • 隐藏域
  • 如果是新增博客,blog=null并且blogId=null,该值默认为0
 <input type="hidden" id="blogId" name="blogId" 
 th:value="${blog!=null and blog.blogId!=null }?${blog.blogId}: 0">

blogName

  • 如果是修改,输入框的值是blog.blogTitle
  • 如果是新增,输入框为空
<input type="text" class="form-control col-sm-6" id="blogName" name="blogName"
       placeholder="*请输入文章标题(必填)"
       th:value="${blog!=null and blog.blogTitle!=null }?${blog.blogTitle}: ''"
       required="true">

blogTags

  • 如果是修改,输入框的值是blog.blogTags
  • 如果是新增,输入框为空
<input type="text" class="form-control" id="blogTags" name="blogTags"
                   placeholder="请输入文章标签"
                   th:value="${blog!=null and blog.blogTags!=null }?${blog.blogTags}: ''"
                   style="width: 100%;">

dao层
<!--根据id修改博客-->
<update id="updateBlog" parameterType="blog">
    update rm_blog.blog set blog_title=#{blogTitle},
    blog_sub_url=#{blogSubUrl},
    blog_cover_image=#{blogCoverImage},
    blog_content=#{blogContent},
    blog_category_id=#{blogCategoryId},
    blog_category_name=#{blogCategoryName},
    blog_tags=#{blogTags},
    blog_status=#{blogStatus},
    enable_comment=#{enableComment} where blog_id=#{blogId};
</update>
service层
 @Override
    public int updateBlog(Blog blog) {
        //通过分类id获取分类
        Blog blogForUpdate = blogMapper.selectById(blog.getBlogId());
        if (blogForUpdate == null) {
            return 0;
        }
        blogForUpdate.setBlogTitle(blog.getBlogTitle());
        blogForUpdate.setBlogSubUrl(blog.getBlogSubUrl());
        blogForUpdate.setBlogContent(blog.getBlogContent());
        blogForUpdate.setBlogCoverImage(blog.getBlogCoverImage());
        blogForUpdate.setBlogStatus(blog.getBlogStatus());
        blogForUpdate.setEnableComment(blog.getEnableComment());
        BlogCategory blogCategory = categoryMapper.selectByPrimaryKey(blog.getBlogCategoryId());
        if (blogCategory == null) {
            blogForUpdate.setBlogCategoryId(0);
            blogForUpdate.setBlogCategoryName("默认分类");
        } else {
            //设置博客分类名称
            blogForUpdate.setBlogCategoryName(blogCategory.getCategoryName());
            blogForUpdate.setBlogCategoryId(blogCategory.getCategoryId());
            //分类的排序值加1
            blogCategory.setCategoryRank(blogCategory.getCategoryRank() + 1);
        }
        //处理标签数据
        String[] tags = blog.getBlogTags().split(",");
        if (tags.length > 6) {
            return 0;
        }
        blogForUpdate.setBlogTags(blog.getBlogTags());
        //新增的tag对象
        List<BlogTag> tagListForInsert = new ArrayList<>();
        //所有的tag对象,用于建立关系数据
        List<BlogTag> allTagsList = new ArrayList<>();
        for (int i = 0; i < tags.length; i++) {
            BlogTag tag = tagMapper.selectByTagName(tags[i]);
            if (tag == null) {
                //不存在就新增
                BlogTag tempTag = new BlogTag();
                tempTag.setTagName(tags[i]);

                tagListForInsert.add(tempTag);
            } else {
                allTagsList.add(tag);
            }
        }
        //新增标签数据不为空->新增标签数据
        if (!CollectionUtils.isEmpty(tagListForInsert)) {
            tagMapper.batchInsertBlogTag(tagListForInsert);
        }
        List<BlogTagRelation> blogTagRelations = new ArrayList<>();
        //新增关系数据
        allTagsList.addAll(tagListForInsert);
        for (BlogTag tag : allTagsList) {
            BlogTagRelation blogTagRelation = new BlogTagRelation();
            blogTagRelation.setBlogId(blog.getBlogId());
            blogTagRelation.setTagId(tag.getTagId());
            blogTagRelations.add(blogTagRelation);
        }
        //修改blog信息->修改分类排序值->删除原关系数据->保存新的关系数据
        blogTagRelationMapper.deleteByBlogId(blog.getBlogId());
        blogTagRelationMapper.batchInsert(blogTagRelations);

		//将修改后的blog信息传入sql语句
        blogMapper.updateBlog(blogForUpdate);
        System.out.println(blogForUpdate);
        if (blogMapper.updateBlog(blogForUpdate)> 0) {
            return 1;
        }
        return 0;
    }
controller层
 @PostMapping("/blogs/update")
    @ResponseBody
    public String update(@RequestParam("blogId") int blogId,
                         @RequestParam("blogTitle") String blogTitle,
                         @RequestParam(name = "blogSubUrl", required = false) String blogSubUrl,
                         @RequestParam("blogCategoryId") Integer blogCategoryId,
                         @RequestParam("blogTags") String blogTags,
                         @RequestParam("blogContent") String blogContent,
                         @RequestParam("blogCoverImage") String blogCoverImage,
                         @RequestParam("blogStatus") Byte blogStatus,
                         @RequestParam("enableComment") Byte enableComment) {
        if (StringUtils.isEmpty(blogTitle)) {
            return "请输入文章标题";
        }
        if (blogTitle.trim().length() > 150) {
            return "标题过长";
        }
        if (StringUtils.isEmpty(blogTags)) {
            return "请输入文章标签";
        }
        if (blogTags.trim().length() > 150) {
            return "标签过长";
        }
        if (blogSubUrl.trim().length() > 150) {
            return "路径过长";
        }
        if (StringUtils.isEmpty(blogContent)) {
            return "请输入文章内容";
        }
        if (blogTags.trim().length() > 100000) {
            return "文章内容过长";
        }
        if (StringUtils.isEmpty(blogCoverImage)) {
            return "封面图不能为空";
        }
        Blog blog = new Blog();
        blog.setBlogId(blogId);
        blog.setBlogTitle(blogTitle);
        blog.setBlogSubUrl(blogSubUrl);
        blog.setBlogCategoryId(blogCategoryId);
        blog.setBlogTags(blogTags);
        blog.setBlogContent(blogContent);
        blog.setBlogCoverImage(blogCoverImage);
        blog.setBlogStatus(blogStatus);
        blog.setEnableComment(enableComment);
        int updateBlogResult = blogService.updateBlog(blog);
        if (updateBlogResult>0) {
            return "修改成功";
        } else {
            return "修改失败";
        }
    }
前端js
//模态框开启后点击保存按钮
$('#saveButton').click(function () {
    //隐藏域
    var blogId = $('#blogId').val();
    var blogTitle = $('#blogName').val();
    var blogSubUrl = $('#blogSubUrl').val();
    var blogCategoryId = $('#blogCategoryId').val();
    var blogTags = $('#blogTags').val();
    var blogContent = blogEditor.getMarkdown();
    var blogCoverImage = $('#blogCoverImage')[0].src;
    var blogStatus = $("input[name='blogStatus']:checked").val();
    var enableComment = $("input[name='enableComment']:checked").val();
    if (isNull(blogCoverImage) || blogCoverImage.indexOf('img-upload') != -1) {
        swal("封面图片不能为空", {
            icon: "error"
        });
        return;
    }
    //默认请求url是添加
    var url = '/admin/blogs/save';
    var data = {
        "blogTitle": blogTitle, "blogSubUrl": blogSubUrl, "blogCategoryId": blogCategoryId,
        "blogTags": blogTags, "blogContent": blogContent, "blogCoverImage": blogCoverImage,
        "blogStatus": blogStatus,
        "enableComment": enableComment
    };
    
    //如果blogId>0是修改,请求url是修改请求
    if (blogId > 0) {
        url = '/admin/blogs/update';
        data = {
            "blogId": blogId,
            "blogTitle": blogTitle,
            "blogSubUrl": blogSubUrl,
            "blogCategoryId": blogCategoryId,
            "blogTags": blogTags,
            "blogContent": blogContent,
            "blogCoverImage": blogCoverImage,
            "blogStatus": blogStatus,
            "enableComment": enableComment
        };
    }
    console.log(data);
    
    //ajax提交数据到后台
    $.ajax({
        type: 'POST',//方法类型
        url: url,
        data: data,
        success: function (result) {
            if (result==="修改成功") {
                //隐藏模态框
                $('#articleModal').modal('hide');
                swal("修改成功", {
                    icon: "success"
                });
            }
            else {
                $('#articleModal').modal('hide');
                swal("修改失败", {
                    icon: "error"
                });
            }
        },
        error: function () {
            swal("修改失败", {
                icon: "error"
            });
        }
    });
});
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值