Node实战——留言及回复

一、需求

  1. 用户可添加昵称、头像、内容进行评论
  2. 站长可在后台回复评论

二、建表

  1. message表
    Node实战——留言及回复_第1张图片

  2. reply表
    Node实战——留言及回复_第2张图片

添加外键:
在这里插入图片描述

三、页面及样式

message.ejs:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>留言</title>
    <link rel="stylesheet" href="/css/bootstrap.min.css">
    <link rel="stylesheet" href="/css/index.css">
    <script src="js/jquery-3.3.1.min.js"></script>
    <script src="js/index.js"></script>
</head>
<body>
    <%-include('detachPart/nav.ejs')%>
    <div class="container">
        <%-include('detachPart/guestbook.ejs')%>
    </div>
    <%-include('detachPart/footer.ejs')%>
</body>
</html>

guestbook.ejs:

<div class="message">
    <h2 class="updatetitle">留言</h2>
    <div class="message_form">
        <form action="/sendmsg" method="POST">
            <ul class="message_form_list list-inline">
                <li>
                    <span>您的姓名:<input name="nickname" type="text" placeholder="请输入您的姓名..."></span>
                </li>
                <li class="message_form_list_logoitem">
                    <span>选择头像:</span>
                    <input value="http://localhost:8100/image/userlogo/tx1.jpg" class="addtick" name="logo" type="radio" checked>
                    <input value="http://localhost:8100/image/userlogo/tx2.jpg" name="logo" type="radio">
                    <input value="http://localhost:8100/image/userlogo/tx3.jpg" name="logo" type="radio">
                    <input value="http://localhost:8100/image/userlogo/tx4.jpg" name="logo" type="radio">
                    <input value="http://localhost:8100/image/userlogo/tx5.jpg" name="logo" type="radio">
                    <input value="http://localhost:8100/image/userlogo/tx6.jpg" name="logo" type="radio">
                    <input value="http://localhost:8100/image/userlogo/tx7.jpg" name="logo" type="radio">
                    <input value="http://localhost:8100/image/userlogo/tx8.jpg" name="logo" type="radio">
                </li>
                <li class="message_form_list_note">
                    <span>留言内容:</span>
                    <textarea name="content"></textarea>
                </li>
                <li class="message_form_list_button">
                    <input type="submit" value="留言">
                </li>
            </ul>
        </form>
        <div class="message_box">
            <%for(var i=0;i<findmsgres.length;i++){%>
                <div class="message_box_line">
                    <div>
                        <div class="message_box_line_left"><img src="<%=findmsgres[i].logo%>" alt=""></div>
                        <div class="message_box_line_right">
                            <span><%=findmsgres[i].nickname%></span>
                            <span><%=new Date(findmsgres[i].time).getFullYear()+"-"+("0"+(new Date(findmsgres[i].time).getMonth()+1)).slice(-2)+"-"+("0"+(new Date(findmsgres[i].time).getDate())).slice(-2)%></span>
                            <p><%=findmsgres[i].content%></p>
                        </div>
                    </div>
                    <%for(var k=0;k<replymsgres.length;k++){%>
                        <%if(findmsgres[i].id==replymsgres[k].towho){%>
                            <div class="message_box_line_reply">
                                <span>回复的消息:</span>
                                <p><%=replymsgres[k].tocontent%></p>
                            </div>
                        <%}%>
                    <%}%>
                </div>
            <%}%>
        </div>
    </div>
</div>

index.css:

.message{
    width: 100%;
    height: auto;
    background-color: #fff;
    border-radius: 3px;
    padding: 1.2rem;
    margin-top: 1.5rem;
}
.message_form{
    margin: 1.5rem 0;
}
.message_form_list>li{
    font-size: 0.9rem;
    padding: 0.5rem 0;
}
.message_form_list>li span{
    display: block;
}
.message_form_list>li:first-child input{
    width: 10rem;
    font-size: 0.8rem;
    outline: none;
    padding-left: 0.2rem;
}
.message_form_list_logoitem input{
    position: relative;
    -webkit-appearance: none;
    outline: none;
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    margin: 0.4rem 0.2rem;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    overflow: hidden;
}
.message_form_list_logoitem input:nth-child(2){
    background-image: url("../image/userlogo/tx1.jpg");
}
.message_form_list_logoitem input:nth-child(3){
    background-image: url("../image/userlogo/tx2.jpg");
}
.message_form_list_logoitem input:nth-child(4){
    background-image: url("../image/userlogo/tx3.jpg");
}
.message_form_list_logoitem input:nth-child(5){
    background-image: url("../image/userlogo/tx4.jpg");
}
.message_form_list_logoitem input:nth-child(6){
    background-image: url("../image/userlogo/tx5.jpg");
}
.message_form_list_logoitem input:nth-child(7){
    background-image: url("../image/userlogo/tx6.jpg");
}
.message_form_list_logoitem input:nth-child(8){
    background-image: url("../image/userlogo/tx7.jpg");
}
.message_form_list_logoitem input:nth-child(9){
    background-image: url("../image/userlogo/tx8.jpg");
}
.addtick::after{
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    content: "";
    width: 3rem;
    height: 3rem;
    background-image: url("../image/icon/dui.png");
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-color: hsla(0, 5%, 80%, 0.459);
}
.message_form_list_note>textarea{
    width: 100%;
    height: 15rem;
    outline: none;
    resize: none;
    margin: 0.4rem 0;
    padding: 0.5rem;
}
.message_form_list_button{
    float: right;
}
.message_form_list_button>input{
    width: 6rem;
    height: 2rem;
    background-color: goldenrod;
    color: whitesmoke;
    font-size: 0.9rem;
    outline: none;
    border: 1px solid transparent;
    border-radius: 3px;
}
.message_box{
    margin: 3.5rem 0 2rem 0;
    padding: 1rem 0;
}
.message_box_line{
    display: flex;
    flex-direction: column;
    border-bottom: 1px dashed silver;
    margin-top: 1rem;
}
.message_box_line>div{
    display: flex;
    flex-direction: row;
}
.message_box_line_left{
    flex: 0.7;
    margin-left: 2rem;
}
.message_box_line_left>img{
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
}
.message_box_line_right{
    flex: 11.3;
}
.message_box_line_right>span{
    font-size: 0.9rem;
}
.message_box_line_right>span:nth-child(2){
    float: right;
    margin-right: 2rem;
}
.message_box_line_right>p{
    margin-top: 1rem;
}
.message_box_line_reply{
    background-color: #e7dfdf;
    padding: 0.8rem 2rem 0 2rem;
    margin-bottom: 0.5rem;
    border-radius: 3px;
}
.message_box_line_reply>span{
    color: #f32e2e;
    font-size: 0.9rem;
}
.message_box_line_reply>p{
    font-size: 0.9rem;
}

index.js:

$(function(){
    $(".message_form_list_logoitem>input").each(function(index){
        $(this).click(function(){
            $(this).addClass("addtick").siblings().removeClass("addtick");
        });
    });
});

四、MySQL数据

connection.js:

var mysql=require("mysql");
var setting=require("./setting");
var connection;
var connectionmysql=function(){
    connection=mysql.createConnection({
        host:setting.host,
        port:setting.port,
        user:setting.user,
        password:setting.pwd,
        database:setting.base
    });
}
connectionmysql();  //初始化连接数据库
// 不带参
exports.select=function(str,callback){
    connectionmysql();  //重新连接数据库
    connection.query(str,function(err,res){
        if(err) throw err;
        callback(res);
        connection.end();  //关闭服务器
    });
}   
// 带参
exports.find=function(str,params,callback){
    connectionmysql();  //重新连接数据库
    connection.query(str,params,function(err,res){
        if(err) throw err;
        callback(res);
        connection.end();  //关闭服务器
    });
}   

sql.js:

module.exports={
	findTitle:"select * from nav",
	insertMsg:"insert into message(id,nickname,logo,content,time) values(null,?,?,?,?)",
    findMsg:"select * from message order by time desc",
    replyMsg:"select reply.id,towho,tocontent,totime from reply,message where reply.towho=message.id"
}

promise.js:

var mysql=require("../MySQL/connection");
var sql=require("../MySQL/sql");
module.exports={
    findTitle:function(){
        return new Promise(function(resolve){
            mysql.select(sql.findTitle,function(result){
                resolve(JSON.parse(JSON.stringify(result)));
            });
        })
    },
    insertMsg:function(arr){
        return new Promise(function(resolve){
            mysql.find(sql.insertMsg,arr,function(result){
                resolve(JSON.parse(JSON.stringify(result)));
            });
        });
    },
    findMsg:function(){
        return new Promise(function(resolve){
            mysql.select(sql.findMsg,function(result){
                resolve(JSON.parse(JSON.stringify(result)));
            });
        });
    },
    replyMsg:function(){
        return new Promise(function(resolve){
            mysql.select(sql.replyMsg,function(result){
                resolve(JSON.parse(JSON.stringify(result)));
            });
        });
    }
}

router.js:

var promise=require("../MySQL/promise");
var bodyParser=require("body-parser");
module.exports=function(app){
    app.use(bodyParser.urlencoded({extended:false}));
    app.use(bodyParser.json());

    app.get("/message",function(req,res){
        async function getData(){
            var res1=await promise.findTitle();
            var res19=await promise.findMsg();
            var res20=await promise.replyMsg();
            var allres={
                titleindex:5,
                navres:res1,
                findmsgres:res19,
                replymsgres:res20
            }
            return allres;
        }
        getData().then(function(result){
            res.render("message",result);
        });
    });
    // 用户留言的提交路由
    app.post("/sendmsg",function(req,res){ 
        var msginfo=req.body;
        var arr=[msginfo.nickname,msginfo.logo,msginfo.content,new Date().toLocaleDateString()];
        async function getData(){
            var res18=await promise.insertMsg(arr);
            var allres={
                insertmsgres:res18
            }
            return allres;
        }
        getData().then(function(result){
            if(result.insertmsgres.affectedRows==1){
                res.redirect("/message");
            }else{
                res.send("留言失败!");
            }
        });
    });
}

目录:
Node实战——留言及回复_第3张图片
五、效果展示

留言区域:
Node实战——留言及回复_第4张图片
回复区域:
Node实战——留言及回复_第5张图片
六、问题及解决方法

  1. form 表单使用 post 方式,无法提交数据

解决:使用第三方中间件 body-parser 获取 post 提交数据,直接使用 req.body 就可直接获取到 json 数据

https://editor.csdn.net/md/?articleId=102479408

  1. 用户留言成功后,需重定向到当前留言界面

解决:使用 express 中的res.redirect()

https://www.oecom.cn/nodejs-redirect/

var express = require('express');
var app = express();
app.get('/',function(req,res){
res.redirect('/admin');
});
app.get('/admin',function(req,res){
res.send('欢迎管理员');
});
app.listen(8100);
  • 当访问:http://localhost:8100/ 时将自动调整到 http://localhost:8100/admin

你可能感兴趣的:(node)