1. 程式人生 > >NodeJS簡易部落格系統(九)後臺管理實現及專案總結

NodeJS簡易部落格系統(九)後臺管理實現及專案總結

功能描述及流程在上一篇已經說明,現在來寫具體實現過程。

一、頁面實現

(1)模板

首頁模板main_template.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>部落格後臺管理</title>
    <link rel="stylesheet" href="/public/css/bootstrap.css">
    <link rel="stylesheet" href="/public/css/admin.css">
    <script type="text/javascript" src="/public/js/jquery.js"></script>
    <script type="text/javascript" src="/public/js/bootstrap.js"></script>
    <script type="text/javascript" src="/public/js/admin.js"></script>
</head>
<body>
{% if userInfo.isadmin %}
<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/admin">後臺管理</a>
        </div>
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li><a href="/admin/user">使用者資訊</a></li>
                <li><a href="/admin/category">所有分類</a></li>
                <li><a href="/admin/category/add">新增分類</a></li>
                <li><a href="/admin/content">所有博文</a></li>
                <li><a href="/admin/content/add">新增博文</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{userInfo.username}}<span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="/">退出管理</a></li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
</nav>
{% block main %}
{% endblock %}
{% else %}
<div class="welcome" >
    <h1>對不起,你不是管理員!</h1>
    <p><a class="btn btn-primary btn-lg" href="/" role="button">返回上一步</a></p>
</div>
{% endif %}
</body>
</html>

首頁index.html

{% extends "main_template.html" %}
{% block main %}
<div class="welcome" >
    <h1>Welcome,管理員!</h1>
    <p>歡迎您管理後臺!</p>
</div>
{% endblock %}

使用者資訊userindex.html

{% extends "main_template.html" %}

{% block main %}

<ol class="breadcrumb">
    <li><a href="#">管理首頁</a></li>
    <li><a href="#">使用者資訊</a></li>
</ol>

<table class="table table-bordered table-hover table-striped" style="color:#fc6423">
    <tr >
        <th>使用者ID</th>
        <th>使用者名稱</th>
        <th>密碼</th>
        <th>是否為管理員</th>
    </tr>
    {% for user in users %}
    <tr>
        <td>{{user._id.toString()}}</td>
        <td>{{user.username}}</td>
        <td>{{user.password}}</td>
        <td>{{user.isadmin}}</td>
    </tr>
    {% endfor %}

</table>
<nav aria-label="...">
    <ul class="pager">
        <li><a href="/admin/user?page=1">首頁</a></li>
        <li><a href="/admin/user?page={{page-1}}">上一頁</a></li>
        <li><span>共{{counts}}條資料</span></li>
        <li><a href="/admin/user?page={{page+1}}">下一頁</a></li>
        <li><a href="/admin/user?page={{total}}">最後一頁</a></li>
    </ul>
</nav>
{% endblock %}

所有分類category.html

{% extends "main_template.html" %}

{% block main %}

<ol class="breadcrumb">
    <li><a href="#">管理首頁</a></li>
    <li><a href="#">分類管理</a></li>
</ol>

<table class="table table-bordered table-hover table-striped" style="color:#fc6423">
    <tr >
        <th>分類ID</th>
        <th>分類名稱</th>
        <th>分類操作</th>
    </tr>
    {% for category in categories %}
    <tr>
        <td>{{category._id.toString()}}</td>
        <td>{{category.name}}</td>
        <td>
            <a href="/admin/category/edit?id={{category._id.toString()}}">修改</a> |
            <a href="/admin/category/delete?id={{category._id.toString()}}">刪除</a>
        </td>

    </tr>
    {% endfor %
</table>

{% endblock %}

新增分類addcategory.html

{% extends "main_template.html" %}
{% block main %}
<ol class="breadcrumb">
    <li><a href="#">管理首頁</a></li>
    <li><a href="#">分類管理</a></li>
</ol>
<form role="form" method="post" style="font-size: 22px;text-align: center">
    <div class="form-group">
        <label for="name">分類名稱</label>
        <input type="text" class="form-control" name="name" id="name" placeholder="請填寫分類名稱">
    </div>
    <button type="submit" class="btn btn-primary btn-md">新增分類</button>
</form>
{% endblock %}

分類編輯editcategory.html

{% extends "main_template.html" %}
{% block main %}
<ol class="breadcrumb">
    <li><a href="#">管理首頁</a></li>
    <li><a href="#">分類管理</a></li>
</ol>
<form role="form" method="post" style="font-size: 22px;text-align: center">
    <div class="form-group">
        <label for="name">分類名稱</label>
        <input type="text" class="form-control" name="name" id="name" placeholder="請填寫新名稱">
    </div>
    <button type="submit" class="btn btn-primary btn-md">提交修改</button>
    <a class="btn btn-primary btn-md" href="/admin/category">取消修改</a>
</form>
{% endblock %}

所有博文content.html

{% extends "main_template.html" %}
{% block main %}
<ol class="breadcrumb">
    <li><a href="#">管理首頁</a></li>
    <li><a href="#">博文管理</a></li>
</ol>
<table class="table table-bordered table-hover table-striped" style="color:#fc6423">
    <tr >
        <th>博文ID</th>
        <th>博文標題</th>
        <th>所屬分類</th>
        <th>作者</th>
        <th>新增時間</th>
        <th>閱讀量</th>
        <th>博文增刪</th>
    </tr>
    {% for content in contents %}
    <tr>
        <td>{{content._id.toString()}}</td>
        <td>{{content.title}}</td>
        <td>{{content.category.name}}</td>
        <td>{{content.user.username}}</td>
        <td>{{content.addtime|date('Y-m-d  H:i:s', -8*60)}}</td>
        <td>{{content.num}}</td>
        <td>
        <a href="/admin/content/edit?id={{content._id.toString()}}">修改</a> |
        <a href="/admin/content/delete?id={{content._id.toString()}}">刪除</a>
        </td>
    </tr>
    {% endfor %
</table>
{% endblock %}

新增博文addcontent.html

{% extends "main_template.html" %}
{% block main %}
<ol class="breadcrumb">
    <li><a href="#">管理首頁</a></li>
    <li><a href="#">新增博文</a></li>
</ol>
<form role="form" method="post" style="font-size: 22px;text-align: center">
    <div class="form-group">
        <label for="name">博文標題</label>
        <input type="text" class="form-control" name="name" id="name" placeholder="請填寫博文名稱">
    </div>
    <div class="form-group">
        <label for="category">請選擇分類</label>
        <select name="category" id="category" class="form-control">
            {% for category in categories %}
            <option value="{{category.id}}">{{category.name}}</option>
            {% endfor %}
        </select>
        <div class="form-group" style="margin-top: 20px;font-size: 20px;">
            <label for="description">請填寫簡介</label>
            <textarea name="description" id="description" class="form-control" rows="4"
                      placeholder="請輸入內容簡介" style="overflow: auto;"></textarea>
        </div>
        <div class="form-group" style="margin-top: 20px;font-size: 20px;">
            <label for="content">請填寫正文</label>
            <textarea name="content" id="content" class="form-control" rows="15" placeholder="請輸入內容"></textarea>
        </div>
    </div>
    <button type="submit" class="btn btn-primary btn-lg" style="margin-top: 50px;">新增博文</button>
</form>
{% endblock %}

博文編輯editcontent.html

{% extends "main_template.html" %}
{% block main %}
<ol class="breadcrumb">
    <li><a href="#">管理首頁</a></li>
    <li><a href="#">修改博文</a></li>
</ol>
<form role="form" method="post" style="font-size: 22px;text-align: center">
    <div class="form-group">
        <label for="name">博文標題</label>
        <input type="text" class="form-control" name="name" id="name" value="{{info.title}}">
    </div>
    <div class="form-group">
        <label for="category">請選擇分類</label>
        <select name="category" id="category" class="form-control">
            {% for category in categories %}
                {% if info.category._id.toString() == category._id.toString() %}
                    <option value="{{category.id}}" selected>{{category.name}}</option>
                {% else %}}
                    <option value="{{category.id}}" >{{category.name}}</option>
                {% endif %}
            {% endfor %}
        </select>
        <div class="form-group" style="margin-top: 20px;font-size: 20px;">
            <label for="description">請填寫簡介</label>
            <textarea name="description" id="description" class="form-control" rows="4"
                      style="overflow: auto;">{{info.description}}</textarea>
        </div>
        <div class="form-group" style="margin-top: 20px;font-size: 20px;">
            <label for="content">請填寫正文</label>
            <textarea name="content" id="content" class="form-control" rows="15"
                      placeholder="請輸入內容">{{info.composition}}</textarea>
        </div>
    </div>
    <button type="submit" class="btn btn-primary btn-lg" style="margin-top: 50px;">提交修改</button>
</form>
{% endblock %}

刪除分類確認頁面confirm.html

{% extends "main_template.html" %}
{% block main %}
<div class="welcome" >
    <h1>您確定刪除?</h1>
    <form role="form" method="post" style="font-size: 22px;text-align: center" action="/admin/category/delete?id={{id}}">
        <button type="submit" class="btn btn-primary btn-lg">確定!</button>
        <a class="btn btn-primary btn-lg" href="/admin/category">再想想</a>
    </form>
</div>
{% endblock %}

刪除博文確認頁面confirm2.html

{% extends "main_template.html" %}
{% block main %}
<div class="welcome" >
    <h1>您確定刪除?</h1>
    <form role="form" method="post" style="font-size: 22px;text-align: center" action="/admin/content/delete?id={{id}}">
        <button type="submit" class="btn btn-primary btn-lg">確定!</button>
        <a class="btn btn-primary btn-lg" href="/admin/content">再想想</a>
    </form>
</div>
{% endblock %}

操作成功頁面success.html

{% extends "main_template.html" %}
{% block main %}
<div class="welcome" >
    <h1>操作成功,請點選返回上一頁面</h1>
    <p><a class="btn btn-primary btn-lg" href="/admin/category" role="button">返回</a></p>
</div>
{% endblock %}

操作失敗頁面error.html

{% extends "main_template.html" %}
{% block main %}
<div class="welcome" >
    <h1>操作無效,請返回並重試!</h1>
    <p><a class="btn btn-primary btn-lg" href="/admin/category/add" role="button">返回上一步</a></p>
</div>
{% endblock %}

(2)樣式檔案

admin.css

.welcome {
    text-align: center;
}
.table th, .table td {
    text-align: center;
    vertical-align: middle!important;
}
.table{
    table-layout: fixed;
}
.pager{
    font-size: 20px;
}

二、routers程式碼

admin.js

let express = require("express");
let router = express.Router();
let User = require("../models/user");
let Category = require("../models/category");
let Content = require("../models/content");
router.get("/",function(req,res){
    res.render("admin/index",{userInfo:req.userInfo});
});
router.get("/user",function(req,res){
    let page = Number(req.query.page||1);
    // 預設每頁顯示8條資料
    let limit = 8;
    let skip = (page-1)*limit;
    let total;
    let counts;
    User.count().then(function(count){
        total = Math.ceil(count/limit);
        page = Math.max(1,page);
        page = Math.min(page,total);
        counts = count;
    });
    User.find().limit(limit).skip(skip).then(function(users){
        res.render("admin/userindex",{
            userInfo:req.userInfo,
            users:users,
            page:page,
            total:total,
            counts:counts
        })
    });

});
router.get("/category",function(req,res){
    Category.find().sort({_id:-1}).then(function(categories){
        res.render("admin/category",{
            userInfo:req.userInfo,
            categories:categories
        });
    });


});
router.get("/category/add",function(req,res){
    res.render("admin/addcategory",{userInfo:req.userInfo});

});
router.post("/category/add",function(req,res){
    let name =req.body.name||"";
    if(name==""){
        res.render("admin/error",{userInfo:req.userInfo});
    }
    else{
        Category.findOne({name:name},function(err,info){
            if(err){
                console.log(err);
            }
            if(info){
                res.render("admin/error",{userInfo:req.userInfo});
                return false;
            }
            let newcate = new Category({
                name:name
            });
            newcate.save();
            res.render("admin/success",{userInfo:req.userInfo});

        });
    }
});
router.get("/category/edit",function(req,res){
    let cateid = req.query.id||"";
    Category.find({id:cateid}).then(function(cateinfo){
        res.render("admin/categoryedit",{
            userInfo:req.userInfo ,
            name:cateinfo.name
        });
    });

});
router.post("/category/edit",function(req,res){
    let name =req.body.name||"";
    let id = req.query.id||"";

    if(name==""){
        res.render("admin/error",{userInfo:req.userInfo});
        return false;
    }else{
        Category.findOne({_id:id},function(err,info){
            if(err){
                console.log(err);
            }
            if(info){
                console.log(info);
                info.name = name;
                info.save();
                res.render("admin/success",{userInfo:req.userInfo});
            }

        });
    }
});
router.get("/category/delete",function(req,res){
        let id = req.query.id||"";
        //console.log(id);
        res.render("admin/confirm",{
            userInfo:req.userInfo,
            id:id
        });
});
router.post("/category/delete",function(req,res){
    let id = req.query.id||"";
    //console.log(id);
    Category.remove({_id:id}).then(function(){
        res.render("admin/success",{
            userInfo:req.userInfo
        });
    });

});
router.get("/content",function(req,res){    Content.find().populate(["category","user"]).sort({_id:-1}).then(function(contents){
        res.render("admin/content",{
            userInfo:req.userInfo,
            contents:contents
        });
    });

});
router.get("/content/add",function(req,res){
    let cate=null;
    Category.find().then(function(categories){
        cate = categories;
        res.render("admin/addcontent",{
            userInfo:req.userInfo,
            categories :cate
        });
    });

});
router.post("/content/add",function(req,res){
    let title = req.body.name||"";
    let category = req.body.category||"";
    let description = req.body.description||"";
    let content = req.body.content||"";
    if(title==""||category==""||description==""||content==""){
        res.render("admin/addok",{
            userInfo:req.userInfo,
            message:"還有未填入的資訊,請重新填入!"
        });
        return false;
    }else {
        let newcontent = new Content({
            title:title,
            category:category,
            description:description,
            composition:content,
            addtime:new Date(),
            num:0,
            user :req.userInfo._id.toString()
        });
        newcontent.save();
        res.render("admin/addok",{
            userInfo:req.userInfo,
            message : "更新博文成功"
        });
    }

});
router.get("/content/edit",function(req,res){
    let cate=null;
    let id = req.query.id||"";
    Category.find().then(function(categories){
        cate = categories;
    });

    Content.findOne({_id:id}).populate("category").then(function(info){
        //console.log(info);
        res.render("admin/editcontent",{
            userInfo:req.userInfo,
            info :info,
            categories:cate
        });
    });

});
router.post("/content/edit",function(req,res){
    let id = req.query.id||"";
    let title = req.body.name||"";
    let category = req.body.category||"";
    let description = req.body.description||"";
    let content = req.body.content||"";
    if(title==""||category==""||description==""||content==""){
        res.render("admin/addok",{
            userInfo:req.userInfo,
            message:"無效的修改,請重新修改!"
        });
        return false;
    }else {
        Content.update({_id:id},{
            title : title,
            category: category,
            description : description,
            content : content,
            addtime:new Date(),
            user :req.userInfo._id.toString()
        }).then(function(){
            res.render("admin/addok",{
                userInfo:req.userInfo,
                message : "修改成功!"
            });
        });

    }

});
router.get("/content/delete",function(req,res){
    let id = req.query.id||"";
    res.render("admin/confirm2",{
        userInfo:req.userInfo,
        id:id
    });
});
router.post("/content/delete",function(req,res){
    let id = req.query.id||"";
    //console.log(id);
    Content.remove({_id:id}).then(function(){
        res.render("admin/addok",{
            userInfo:req.userInfo,
            message : "刪除成功!點選返回上一頁!"
        });
    });

});
module.exports = router;

三、執行效果

四、專案總結

至此,這個簡單的專案就完結了,作為一個入門專案,簡單是必須的,不過,通過這個我也學到了express框架、mongodb、mongoose資料庫框架的基本使用,express框架作為一個輕量級的web框架,小而快是它的特性。這個專案也有了最基本的業務邏輯,前端向後端提交資料,提交方法根據不同需求可以是get、post、put、delete方法,其中本專案沒有使用到後面兩個方法,後端收到前端提交的資料後,用body-parse框架去獲取傳送過來的資料,這些資料由業務邏輯程式碼作相應的解析和格式化後請求資料庫資訊並反饋給前端,前端用swig模板引擎去作渲染,這就是體現了一個web應用的基本資料傳遞的流程。當然,nodejs和express以及mongoose還有很多強大的功能待作者後續研究,以上便是我對這個小專案的總結。所有的程式碼都貼出來了,如果還需要原始碼請轉:https://download.csdn.net/download/weixin_42363997/10745703