个人博客-6(文章功能模块实现)
作者:互联网
接口
- 文章内容显示
- 文章修改
- 文章删除
页面
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> 新增
</button>
<button class="btn btn-info" onclick="editBlog()"><i
class="fa fa-edit"></i> 修改
</button>
<button class="btn btn-danger" onclick="deleteBlog()"><i
class="fa fa-trash-o"></i> 删除
</button>
<input type="text" placeholder="关键字(标题/分类)" id="keyword"
class="form-control col-2">
<button class="btn btn-info" onclick="search()"><i
class="fa fa-search"></i> 搜索
</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> 新增
</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> 删除
</button>
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> 修改
</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"
});
}
});
});
标签:blog,return,int,blogCoverImage,blogForUpdate,博客,功能模块,文章,blogId 来源: https://blog.csdn.net/qq_42265394/article/details/114658335