一、实现分页功能:利用bootstrap的分页组件
IndexController.java
定义两个参数分别负责
page-页码数
size-分页数
@Controller
public class IndexController {
@Autowired
private QuestionService questionService;
@Autowired
private HotTagCache hotTagCache;
@GetMapping("/")
public String index(Model model,
@RequestParam(name = "page", defaultValue = "1") Integer page,
@RequestParam(name = "size", defaultValue = "10") Integer size,
PaginationDTO.java
负责页面所承载的元素,分页的逻辑,判断数字的位置,展示的逻辑等问题。
@Data public class PaginationDTO{ private List data; private boolean showPrevious; private boolean showFirstPage; private boolean showNext; private boolean showEndPage; private Integer page; private List pages = new ArrayList<>(); private Integer totalPage; public void setPagination(Integer totalPage, Integer page) { this.totalPage = totalPage; this.page = page; pages.add(page); for (int i = 1; i <= 3; i++) { if (page - i > 0) { pages.add(0, page - i); } if (page + i <= totalPage) { pages.add(page + i); } } // 是否展示上一页 if (page == 1) { showPrevious = false; } else { showPrevious = true; } // 是否展示下一页 if (page == totalPage) { showNext = false; } else { showNext = true; } // 是否展示第一页 if (pages.contains(1)) { showFirstPage = false; } else { showFirstPage = true; } // 是否展示最后一页 if (pages.contains(totalPage)) { showEndPage = false; } else { showEndPage = true; } } }
QuestionService.java
通过所给的页码显示数等和相应的逻辑去计算有关的数据,同时包含一些容错处理,计算偏移量。
Integer totalCount = questionExtMapper.countBySearch(questionQueryDTO);
if (totalCount % size == 0) {
totalPage = totalCount / size;
} else {
totalPage = totalCount / size + 1;
}
if (page < 1) {
page = 1;
}
if (page > totalPage) {
page = totalPage;
}
paginationDTO.setPagination(totalPage, page);
Integer offset = page < 1 ? 0 : size * (page - 1);
questionQueryDTO.setSize(size);
questionQueryDTO.setPage(offset);
List questions = questionExtMapper.selectBySearch(questionQueryDTO);
List questionDTOList = new ArrayList<>();
二、完善导航栏 利用bootstrop的导航组件
- 我的问题
- 退出登录
编辑出三个功能index.html publish.html
三、搜索功能的实现
IndexController.java
定义负责搜索的参数search
@GetMapping("/")
public String index(Model model,
@RequestParam(name = "search", required = false) String search,
QuestionService.java
if (StringUtils.isNotBlank(search)) {
String[] tags = StringUtils.split(search, " ");
search = Arrays
.stream(tags)
.filter(StringUtils::isNotBlank)
.map(t -> t.replace("+", "").replace("*", "").replace("?", ""))
.filter(StringUtils::isNotBlank)
.collect(Collectors.joining("|"));
}
Integer totalPage;
QuestionQueryDTO questionQueryDTO = new QuestionQueryDTO();
questionQueryDTO.setSearch(search);
QuestionQueryDTO .java
import lombok.Data;
@Data
public class QuestionQueryDTO {
private String search;
private String sort;
private Long time;
private String tag;
private Integer page;
private Integer size;
}
interface QuestionExtMapper
public interface QuestionExtMapper {
int incView(Question record);
int incCommentCount(Question record);
List selectRelated(Question question);
Integer countBySearch(QuestionQueryDTO questionQueryDTO);
List selectBySearch(QuestionQueryDTO questionQueryDTO);
List selectSticky();
}
QuestionExtMapper.xml
update question
set
view_count = view_count + #{viewCount,jdbcType=INTEGER}
where id = #{id}
update question
set
comment_count = comment_count + #{commentCount,jdbcType=INTEGER}
where id = #{id}
四、评论功能
question.html
个回复
提交回复
利用js插件实现动画效果
function collapseComments(e) {
var id = e.getAttribute("data-id");
var comments = $("#comment-" + id);
// 获取一下二级评论的展开状态
var collapse = e.getAttribute("data-collapse");
if (collapse) {
// 折叠二级评论
comments.removeClass("in");
e.removeAttribute("data-collapse");
e.classList.remove("active");
} else {
var subCommentContainer = $("#comment-" + id);
if (subCommentContainer.children().length != 1) {
//展开二级评论
comments.addClass("in");
// 标记二级评论展开状态
e.setAttribute("data-collapse", "in");
e.classList.add("active");
} else {
$.getJSON("/comment/" + id, function (data) {
$.each(data.data.reverse(), function (index, comment) {
var mediaLeftElement = $("", {
"class": "media-left"
}).append($("", {
"class": "media-object img-rounded",
"src": comment.user.avatarUrl
}));
var mediaBodyElement = $("", {
"class": "media-body"
}).append($("", {
"class": "media-heading",
"html": comment.user.name
})).append($("", {
"html": comment.content
})).append($("", {
"class": "menu"
}).append($("", {
"class": "pull-right",
"html": moment(comment.gmtCreate).format('YYYY-MM-DD')
})));
var mediaElement = $("", {
"class": "media"
}).append(mediaLeftElement).append(mediaBodyElement);
var commentElement = $("", {
"class": "col-lg-12 col-md-12 col-sm-12 col-xs-12 comments"
}).append(mediaElement);
subCommentContainer.prepend(commentElement);
});
//展开二级评论
comments.addClass("in");
// 标记二级评论展开状态
e.setAttribute("data-collapse", "in");
e.classList.add("active");
});
}
}
}
利用bootstrap的表单组件
CommentController.java
@ResponseBody
@RequestMapping(value = "/comment/{id}", method = RequestMethod.GET)
public ResultDTO> comments(@PathVariable(name = "id") Long id) {
List commentDTOS = commentService.listByTargetId(id, CommentTypeEnum.COMMENT);
return ResultDTO.okOf(commentDTOS);
}



