前言
搭建完一个简单的后台管理系统之后,接下来进行前台页面的开发。一共两个前台页面——主页和博客页面,在看了很多博客之后我决定仿照王垠的博客,风格简洁,当然主要还是因为实现起来比较简单。
后端开发
前台对应的后端只有Controller层,Service层和Dao层在之前都已经编写好,直接调用即可。HomeController.java代码如下:
package com.vansl.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.vansl.dto.BlogData;
import com.vansl.entity.BlogComment;
import com.vansl.service.BlogCommentService;
import com.vansl.service.BlogService;
import com.vansl.service.BlogTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* @author: vansl
* @create: 18-3-17 下午11:58
*/
@Controller
public class HomeController {
@Autowired
BlogService blogService;
@Autowired
BlogTypeService blogTypeService;
@Autowired
BlogCommentService blogCommentService;
// 主页
@GetMapping("/")
public String index(HttpServletRequest request){
request.setAttribute("welcome","主页");
request.setAttribute("articleList",blogService.selectAll(1,true,1,Integer.MAX_VALUE).getData());
request.setAttribute("typeData", JSON.toJSONString(blogTypeService.selectAll(1)));
//返回index.jsp
return "index";
}
// 选择分类后显示分类所属文章
@GetMapping(value="/article",params ={"userId","typeId"})
public String index(Integer userId,Integer typeId,HttpServletRequest request){
request.setAttribute("welcome","博客分类");
request.setAttribute("articleList",blogService.selectByTypeId(userId,typeId,true,1,Integer.MAX_VALUE).getData());
request.setAttribute("typeData", JSON.toJSONString(blogTypeService.selectAll(1)));
//返回index.jsp
return "index";
}
// 博客页面
@GetMapping("/article/{id}")
public String article(@PathVariable Integer id, HttpServletRequest request){
BlogData blogData=blogService.selectById(id);
// 如果未发表则拒绝访问
if (blogData.getPublished()==1){
return "denied";
}
// 返回评论信息
List comments=blogCommentService.selectByBlogId(id,1,Integer.MAX_VALUE);
//转换地址和时间
for (BlogComment comment:comments){
try {
JSONObject addressJson=(JSONObject)JSON.parseObject(comment.getAddress()).get("data");
comment.setAddress((String)addressJson.get("city")+" "+addressJson.get("isp"));
}catch (Exception e){
e.printStackTrace();
}
}
request.setAttribute("blogData",blogData);
request.setAttribute("blogContent",blogService.selectContentByBlogId(id));
request.setAttribute("comments",comments);
//返回article.jsp
return "article";
}
}
页面开发
博客主页主要是一个取出文章信息列表和分类列表,然后实现无极分类建立树形结构;而文章页面主要是一个评论的提交。由于页面结构和功能都比较简单,不再赘述。直接放上代码。
index.jsp:
<%--
Created by IntelliJ IDEA.
User: vansl
Date: 18-4-30
Time: 下午12:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
vansl-个人网站-${welcome}
index.css,做了简单的分辨率适配:
a{
text-decoration:none;
}
li{
list-style: none;
}
nav.top{
background-color: #fff;
opacity: .9;
width:100%;
height:50px;
top:0;
left:0;
position: fixed;
border-bottom:solid 1px #e7e7e7;
z-index:999;
}
@media (max-width: 1000px) {
nav.top{
height:180px;
}
}
nav .navbar-brand{
float: left;
font-size: 24px;
color: #777;
padding: 10px;
height: 50px;
margin-left: 10px;
}
@media (max-width: 1000px) {
nav .navbar-brand{
font-size: 58px;
padding: 50px;
height:180px;
}
}
div.navbar-module{
font-size: 24px;
color: #777;
}
@media (max-width: 1000px) {
div.navbar-module{
font-size: 58px;
}
}
.navbar-module>ul{
float: right;
display: block;
margin: 0;
}
.navbar-module li{
float: left;
position: relative;
display: block;
margin: 0;
}
.navbar-module li>a{
text-shadow: 0 1px 0 rgba(255,255,255,.25);
height: 30px;
padding: 10px 15px;
display: block;
color: #555;
}
@media (max-width: 1000px) {
.navbar-module li>a{
height: 120px;
padding: 30px 30px;
}
}
.navbar-module li.active>a{
background-image: linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);
background-repeat: repeat-x;
box-shadow: inset 0 3px 9px rgba(0,0,0,.075);
background-color: #e7e7e7;
}
div.content{
z-index: 1;
}
div.category{
width:10%;
margin-top:20px;
margin-left: -30px;
position: fixed;
}
@media (max-width: 1000px) {
div.category{
width:30%;
}
}
.category li{
margin-top: 3px;
}
.category ul{
display: block;
margin-top: 10px;
margin-bottom: 20px;
}
.category a{
white-space: nowrap;
font-size: 18px;
border: 1px solid #ddd;
background-color: #fff;
color: #428bca;
}
@media (max-width: 1000px) {
.category a {
font-size: 43px;
}
}
div.article{
display: block;
margin-left: 10%;
margin-top:100px;
margin-bottom: 20px;
}
@media (max-width: 1000px) {
div.article{
margin-top:300px;
margin-left: 30%;
}
}
.article-list:first-child {
border-top-right-radius: 4px;
border-top-left-radius: 4px;
}
li.article-list-item{
border: 1px solid #ddd;
background-color: #fff;
cursor: pointer;
padding: 15px 20px;
margin-bottom: -1px;
}
li.article-list-item:hover{
background-color: #EDEDED;
}
.article-list-item a{
display: block;
font-size: 21px;
color: #428bca;
}
@media (max-width: 1000px) {
.article-list-item a{
font-size: 58px;
}
}
.article-list-item a:hover{
text-decoration: underline;
}
li{
list-style: none;
}
nav.top{
background-color: #fff;
opacity: .9;
width:100%;
height:50px;
top:0;
left:0;
position: fixed;
border-bottom:solid 1px #e7e7e7;
z-index:999;
}
@media (max-width: 1000px) {
nav.top{
height:180px;
}
}
nav .navbar-brand{
float: left;
font-size: 24px;
color: #777;
padding: 10px;
height: 50px;
margin-left: 10px;
}
@media (max-width: 1000px) {
nav .navbar-brand{
font-size: 58px;
padding: 50px;
height:180px;
}
}
div.navbar-module{
font-size: 24px;
color: #777;
}
@media (max-width: 1000px) {
div.navbar-module{
font-size: 58px;
}
}
.navbar-module>ul{
float: right;
display: block;
margin: 0;
}
.navbar-module li{
float: left;
position: relative;
display: block;
margin: 0;
}
.navbar-module li>a{
text-shadow: 0 1px 0 rgba(255,255,255,.25);
height: 30px;
padding: 10px 15px;
display: block;
color: #555;
}
@media (max-width: 1000px) {
.navbar-module li>a{
height: 120px;
padding: 30px 30px;
}
}
.navbar-module li.active>a{
background-image: linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);
background-repeat: repeat-x;
box-shadow: inset 0 3px 9px rgba(0,0,0,.075);
background-color: #e7e7e7;
}
div.content{
z-index: 1;
}
div.category{
width:10%;
margin-top:20px;
margin-left: -30px;
position: fixed;
}
@media (max-width: 1000px) {
div.category{
width:30%;
}
}
.category li{
margin-top: 3px;
}
.category ul{
display: block;
margin-top: 10px;
margin-bottom: 20px;
}
.category a{
white-space: nowrap;
font-size: 18px;
border: 1px solid #ddd;
background-color: #fff;
color: #428bca;
}
@media (max-width: 1000px) {
.category a {
font-size: 43px;
}
}
div.article{
display: block;
margin-left: 10%;
margin-top:100px;
margin-bottom: 20px;
}
@media (max-width: 1000px) {
div.article{
margin-top:300px;
margin-left: 30%;
}
}
.article-list:first-child {
border-top-right-radius: 4px;
border-top-left-radius: 4px;
}
li.article-list-item{
border: 1px solid #ddd;
background-color: #fff;
cursor: pointer;
padding: 15px 20px;
margin-bottom: -1px;
}
li.article-list-item:hover{
background-color: #EDEDED;
}
.article-list-item a{
display: block;
font-size: 21px;
color: #428bca;
}
@media (max-width: 1000px) {
.article-list-item a{
font-size: 58px;
}
}
.article-list-item a:hover{
text-decoration: underline;
}
article.jsp:
<%--
Created by IntelliJ IDEA.
User: vansl
Date: 18-5-5
Time: 上午11:54
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
${blogData.title}
${blogData.title}
${blogContent}
articel.js:
var jq= jQuery.noConflict();
function parseTime(time){
var date = new Date(time);//如果date为13位不需要乘1000
var Y = date.getFullYear() + '/';
var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '/';
var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate());
return Y+M+D;
}
jq("#article-time").text(parseTime("${blogData.time}"));
//点击之后恢复未填写信息而变红的输入框颜色
var commentInfo=["#name","#contact","#comment-content"];
commentInfo.forEach(function (item) {
jq(item).click(function(){
jq(item).css("border","1px solid LightGrey");
});
});
jq("#submit").click(function () {
//检查是否所有字段已经填写
for (var i=0 ;i < commentInfo.length; i++) {
if(!jq(commentInfo[i]).val()){
layui .use('layer', function(){
jq(commentInfo[i]).css("border","1px solid red");
var layer = layui.layer;
layer.msg('请补全评论信息', {icon: 2,time: 1000});
});
return;
}
}
//禁用按钮防止重复提交
jq('#submit').click(function () {
return false;
});
// 异步提交数据
jq.ajax({
url: "/comment/",
type: "post",
data:JSON.stringify({
"name":jq('#name').val(),
"contact":jq('#contact').val(),
"content":jq('#comment-content').val(),
"blogId":window.location.href.split("/")[4],
}),
contentType: "application/json; charset=utf-8",
success: function (result) {
layui .use('layer', function(){
var layer = layui.layer;
layer.msg('评论发表成功', {icon: 1,time: 3000});
});
setTimeout(function () {
window.location.reload();
},1000);
}
});
});
article.css:
body {
font-family: "lucida grande", "lucida sans unicode", lucida, helvetica, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
font-size: 18px;
}
@media (max-width: 1000px) {
body {
font-size:48px;
}
}
#article-title{
font-family: "Palatino Linotype", "Book Antiqua", Palatino, Helvetica, STKaiti, SimSun, serif;
padding: 5px;
border-bottom: 2px LightGrey solid;
width: 98%;
line-height: 150%;
color: #666666;
}
div.inner {
margin: 0% 14%;
padding: 2% 8% 4% 8%;
border: 1px solid LightGrey;
}
@media (max-width: 1000px) {
div.inner {
margin: 0% 2%;
padding: 1% 4% 2% 4%;
}
}
div.comment-list>div.comment{
margin: 2% 14%;
border: 1px solid LightGrey;
height:auto!important;
}
strong{
display:block;
}
@media (max-width: 1000px) {
div.comment-list>div.comment{
font-size: 38px;
margin: 1% 2%;
}
}
div.submit_commit {
margin: 2% 14%;
display: grid;
grid-row-gap:10px;
grid-template-rows: 30px 30px 80px 30px;
grid-template-columns: 120px 400px;
}
@media (max-width: 1000px) {
div.submit_commit {
margin: 1% 2%;
grid-template-rows: 60px 60px 160px 60px;
grid-template-columns: 30% 60%;
font-size: 38px;
}
}
#comment-content{
overflow: hidden;
}
打开服务器,页面如下:
一个具有文章与评论发表、管理功能的简单博客系统就完成了。至此尚未完成的部分还有:文章图片上传、用户登录、全文搜索。
${comment.content}