【nodeJS】从nodejs原生的博客网站搭建到 koa框架实现个人博客网站搭建

nodejs实现搭建博客网站

前言:原java后端渣渣一枚,因项目需要转学了nodejs进行开发,正式进行项目开发之前,师傅安排了一些项目训练,先熟悉js语法,然后熟悉nodejs,再慢慢重构向框架的使用。

    写这一篇文章的目的在于记录自己学习的历程,同时也是给其他的nodejs学习者一点参考,如果有修正之处,请给予意见,感谢各位,希望对你有用~


开发环境

系统:可以的话建议使用Linux系统,推荐Ubuntu,笔者习惯了Windows开发,暂时使用的是win7

开发工具:Visual Studio Code

语言:node 5.6.0

npm 5.6.0(其他的依赖模块靠npm去安装)


语法基础

1.熟悉js的基本语法,把nodejs的req、res以及其他相关的api熟悉起来;

2.mysql的使用,熟悉的sql脚本的编写


项目开发

目标功能(主要功能还是比较简单的几个需求,要求一天内完成)

1.网站显示图片、文字、有简洁的样式

2.网站返回服务器时间

3.网站支持用户留言以及显示当前最新10条留言

4.网站显示当前访问的客户的客户端信息

5.底部显示当前网站的访问量(日访问量以及总访问量)


——————————————————————coding———————————————————————————

选定某个文件夹路径,先新建一个index.js文件,作为项目入口,然后,在命令提示符环境下运行以下命令

npm init

之后就按照提示,输入对应的项目信息,初始化项目工程,完成之后,就可以开始coding啦~

打开index.js文件,先把对应模块引入(经由师傅提醒,为项目导入的时候应同时建立依赖文件的记录,这样能保证工程在其他机器运行的前能够安装所有的依赖模块)

npm install 模块名 --save

好了,这么一来,依赖的模块也搞定了,剩下的只剩下博客的后台处理逻辑以及前端展示的页面了。

var http = require('http');
var util = require('util');
var url = require('url');
var fs = require('fs');
var path = require('path');
var querystring = require('querystring');

目前模块引入如上,关于搭建服务器的基本语法,菜鸟教程上讲的非常详细,我们就不赘述了

在入口index.js文件里面,我们搭建了服务器,监听对应的端口,并对相应的接口地址进行逻辑处理:

const http = require('http');
const util = require('util');
const url = require('url');
const fs = require('fs');
const path = require('path');
const querystring = require('querystring');
//连接数据库
const mysql = require('mysql');
const connection = mysql.createConnection({     
  host     : 'localhost',       
  user     : 'root',              
  password : '1234',       
  port: '3306',                   
  database: 'mysql', 
}); 
connection.connect();


//留言功能
let message = [];
let mesLength = 0;
let messageShow = '';

let sql = 'SELECT message FROM MyOwnPage_messageBox';

const uriName = ['html','css','jsp','jpg','png'];

console.log("项目已经启动……127.0.0.1:3000监听当中")

var app = http.createServer(function (req, res) {
    let body = "";
    req.on('data', function (chunk) {
        body += chunk;
    });

    req.on('end',function(){
        body = querystring.parse(body);
        let pathName = url.parse(req.url).pathname;
        //static resource
            if(req.method == 'GET' && pathName == '/' ){
                fs.readFile(__dirname+"\\LoginPage.html", function (err, data){
                    if(err){
                        res.writeHead(404, {'Content-Type': 'text/html'});
                    }else{
                        res.writeHead(200,{'Content-Type': 'text/html'});
                        res.write(data);
                        res.end();
                    }
                })
            }
            if(req.method == 'GET' && uriName.indexOf(path.extname(pathName).substring(1)) != -1){
                if(pathName ==='/HomePage.html'){
                    let addsql = 'INSERT INTO login_log (page,ip,login_time) value (?,?,?)';
                    let ip = req.socket["remoteAddress"];
                    let date = new Date();
                    let day = date.getDate();
                    let month = date.getMonth()+1;
                    let year = date.getFullYear();
                    let login_time = year+'-'+month+'-'+day;
                    let sqlParams = [pathName,ip,login_time];
                    connection.query(addsql,sqlParams,function(err,result){
                        if(err){
                        return;
                        }        
                    })
                }
                fs.readFile(__dirname+"\\"+pathName.substring(1), function (err, data){
                    if(err){
                        res.writeHead(404, {'Content-Type': 'text/html'});
                    }else{
                        if(path.extname(pathName).substring(1) === 'css'){
                            res.writeHead(200,{'Content-Type': 'text/css'});
                        }else if(path.extname(pathName).substring(1) === 'html'){
                            res.writeHead(200,{'Content-Type': 'text/html'});
                        }else if(path.extname(pathName).substring(1) === 'jpg'){
                            res.writeHead(200,{'Content-Type': 'image/jpeg'});
                        }
                        res.write(data);
                        res.end();
                    }
                })
            }
        //获取系统时间
            if(req.method == 'GET'  && pathName == '/sysTime_wenzhiqun'){
                    let time = new Date();
                    let year = time.getFullYear();
                    let month = time.getMonth()+1;
                    let date= time.getDate();
                    let hour = time.getHours();
                    let minutes = time.getMinutes();
                    let seconds = time.getSeconds();
                    if(month<10){
                    month = "0"+month; 
                    }
                    if(date<10){
                    date = "0"+date; 
                    }
                    if(hour<10){
                    hour = "0"+hour; 
                    }
                    if(minutes<10){
                    minutes = "0"+minutes; 
                    }
                    if(seconds<10){
                    seconds = "0"+seconds; 
                    }
                    let currentTime = "当前服务器时间为:"+year+"年"+month+"月"+date+"日"+hour+":"+minutes+":"+seconds;
                res.write(currentTime); 
                res.end();
            }
            
            //提交留言信息
            if(req.method == 'POST' && pathName == '/message'){
                // 新增留言栏中的留言
                let addsql = 'INSERT INTO MyOwnPage_messageBox (messageCount,message) value (?,?)'
                let userMes = body['message'];
                let sqlParams = [mesLength+1,userMes];
                connection.query(addsql,sqlParams,function(err,result){
                    if(err){
                    res.write("提交失败,请重试");
                    res.end();
                    return;
                    }        
                    res.write("提交成功");
                    res.end();        
                  })
            }
            //获取留言栏
            if(req.method == 'GET' && pathName == '/message/list'){
                let sql = 'SELECT message FROM MyOwnPage_messageBox';
                //查询目前的留言栏
                connection.query(sql,function (err, result) {
                        if(err){
                        return;
                        }
                    message = [];
                    mesLength = 0;
                    for(i of result){
                        message[mesLength]=i.message;
                        mesLength++;
                    } 
                });
                let messageShow = '留言栏:';
                if(message.length<=10){
                    for(let i = message.length,j=1;i>0;i--){
                        messageShow = messageShow+'<br>'+'('+j+')'+message[i-1];
                        j++;
                    }
                }else if(message.length>10){
                    for(let i = message.length,j=1;i>(message.length-10);i--){
                        messageShow = messageShow+'<br>'+'('+j+')'+message[i-1];
                        j++;
                    }
                }
                res.write(messageShow);
                res.end();
            }
            //获取客户端信息
            if(req.method == 'GET' && pathName == '/sysinfo'){
                let ob = req.headers["user-agent"].split(" ");
                let system = ob[1].substring(1);
                let chrome = ob[9].split('/')[0];
                let ip = req.socket["remoteAddress"];
                let iptype = req.socket["remoteFamily"];
                res.write("<b>操作系统:</b>"+system+"  <b>浏览器:</b> "+chrome+"<b>ip地址:</b> "+ip+"     <b>ip类型:</b> "+iptype);
                res.end();
            }

            //获取访客量
            if(req.method == 'GET' && pathName == '/visit'){
                let sql = 'SELECT login_time FROM login_log';
                //查询目前的总访客量和日访客量
                connection.query(sql,function (err, result) {
                        if(err){
                        return;
                        }
                    let arr = [];
                    //日访问量
                    let date = new Date();
                    let day = date.getDate();
                    let month = date.getMonth()+1;
                    let year = date.getFullYear();
                    let login_date = year+'-'+month+'-'+day;
                    let day_vi = 0;
                    for(i of result){
                        arr.push(i.login_time);
                    }
                    // 访问总量
                    let vi = arr.length;
                    for (let i = 0; i<arr.length;i++){
                        if(arr[i] == login_date){
                            day_vi++;
                        }
                    }
                    console.log("总访问量为:"+vi+"\n今日访问量为:"+day_vi);
                    res.write("当前页面总访问量为:"+vi+"次"+"\n今日访客量为:"+day_vi+"次");
                    res.end();  
                });
            }
    })
});

app.listen(3000);

以上是一个非常简单的实现,由于是很久很久以前写的了,所以会有很多不足的地方,包括:

1)数据库没有使用连接池去管理,没有考虑每条数据库连接之后的处理

2)有较多的模块没有抽象出来写成公共的工具类(其实也是想要一次性完成,毕竟只用一天的时间……比较粗糙)

3)听说没有error处理的代码不是好代码

另外关于具体的代码实现有几点是需要补充说明的:

1)读取静态文件,像html、css、jpg等文件时,需要判断请求文件的类型,并对其做出相应的处理,而不只是单纯的针对html后缀的文件进行返回(毕竟也是自己踩过的坑,对于html的基础没有学好,导致漏处理)

2)熟练的应用node的原生模块,可以使用querysthing、url等模块对http请求进行解析,以便于我们对于访问资源的处理以及请求的响应

3)依据restful风格,get请求与post请求归类之后针对其uri进行操作

4)由于当时对于整块html不算熟悉,用了最原生态的返回html源码去写页面,⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄

主要的代码如上,其实逻辑很简单,API也很简单,完成之后点击一波F5,或者在命令提示符窗口里,输入node index.js 运行工程…(其实我大部分的时间还是花在这个渣渣的前端页面编写上)

跑起来的工程大概就是这样了——


在浏览器输入localhost:3000/HomePage.html,前端显示如下——


至此,原生的博客网站搭建完成了,勉强完成以上的需求(页面有点丑…勿喷~)

——————————————————————我是分割线—————————————————————————

经过一番koa框架的学习,终于我要迈出从渣渣原生到美腻的框架实现的蜕变了!

学习资料参考:

1.koa官网:https://koa.bootcss.com/

2.ejs模板引擎学习

开始之前重新澄清一下需求,这一次,我们的需求更新了一些细节上的东西

目标功能

包含之前的五个功能

6.增加登录、注册功能

7.增加登录后的角色权限,并分配给管理员角色操作留言栏的功能

8.在页面中添加显示登录的角色的用户名

9.网站的样式定时更换

10.优化后台的数据持久化方式(使用连接池)


——————————————————————coding———————————————————————————

一、项目创建

选定文件夹作为工程存放位置,之后还是在cmd环境下使用

npm init
先对工程进行初始化,之后使用以下指令创建koa工程结构
npm koa

好了,接下来还是需要我们手动创建一个index.js文件,开始敲我们的代码——

二、工程目录结构


三、开始书写我们的主代码:

主目录下的index.js(入口文件)

const koa = require('koa');
const app = new koa();
const static = require('koa-static');
const index = require('./routes/index');
const views = require('koa-views');
const bodyParser = require('koa-bodyparser');
var MysqlStore = require('koa-mysql-session');
const session = require('koa-session-minimal');
const config = require('./config/default.js');
const ejs = require('ejs');
const path = require('path');

//静态资源加载
app.use(static(__dirname+'/public'));
//视图调用
// app.use(views(__dirname+'/views'));
app.use(views(path.join(__dirname, './views'), {
    extension: 'ejs'
}))

// session存储配置
const sessionMysqlConfig= {
    user: config.database.USERNAME,
    password: config.database.PASSWORD,
    database: config.database.DATABASE,
    host: config.database.HOST,
}
  
  // 配置session中间件
app.use(session({
    key: 'USER_SID',
    store: new MysqlStore(sessionMysqlConfig)
}))

app.use(bodyParser());

//这里的 allowedMethods 用于校验请求的方法,如果用 post 请求访问 get 接口,就会直接返回失败
app.use(index.routes(),index.allowedMethods());


app.listen(3000,function(){
    console.log("项目已经启动");
});

这里面,我们引入了本次工程依赖的模块,和原生的工程不同,我们这次加入了很多的“新面孔”,包括有处理静态资源的public、views模块,session模块(对于角色的控制)、ejs模块(模板引擎)以及数据库连接池配置等等

关于koa我有几点想说的:

1)koa框架将req和res封装到了ctx当中,方便我们直接使用ctx调用原来res和req的方法

2)koa中引入了中间件的概念,我们使用.use()的方法去调用我们需要使用的中间件,按照从上往下的顺序,中间件的使用是有顺序区分的

3)采用MVC的思想,我们会将整个工程目录去做分层,如同工程结构截图所示,views里存放的是我们返回的视图,routes存放的是控制器和我们的业务处理(核心所在)…

routes目录下的index.js

const fs = require('fs');
const router = require('koa-router')();
const timeGetter = require('../utils/timeGetter');
const sqlUser = require('../lib/mysql');
const session = require('koa-session-minimal');
let mesLength2 ;

router.get('/HomePage',async (ctx)=>{
    //记录访客量
    let ip = ctx.request.socket["remoteAddress"];
    let currentTime = timeGetter.getServerDate();
    let path = '/HomePage.html' ;
    let value =[path,ip,currentTime]; 
    if(ctx.session){
        await  ctx.render('homePage',{
            session : ctx.session
        })
    }else{
        await ctx.render('homePage',{
            session : null
        })
    }
    sqlUser.addVisit(value);
    sqlUser.getAllMesCount().then(result=>{
        mesLength2 = result['count(message)'];
    })
})

//获取服务器时间
router.get('/sysTime_wenzhiqun', ctx => {
    ctx.body = (timeGetter.getServerTime()).toString();
})

//获取留言栏
router.get('/message/list', async(ctx) => {
    let mesLength = 0;
    let message = [];
    await sqlUser.getAllMes().then(result =>{
        for(i of result){
            message[mesLength]=i.message;
            mesLength++;
        }
    })
    let messageShow = '留言栏:';
    //普通用户
    if(ctx.session.role != 'admin'){
        if(message.length<=10){
            for(let i = message.length,j=1;i>0;i--){
                messageShow = messageShow+'<br>'+'('+j+')'+message[i-1];
                j++;
            }
        }else if(message.length>10){
            for(let i = message.length,j=1;i>(message.length-10);i--){
                messageShow = messageShow+'<br>'+'('+j+')'+message[i-1];
                j++;
            }
        }
    }else{
        if(message.length<=10){
            for(let i = message.length,j=1;i>0;i--){
                messageShow = '<table style="text-align: left"><tr><th>'+messageShow+'</th><th></th><th></th></tr>'+'<tr><td>('+j+')</td><td><p id="'+j+'">'+message[i-1]+'</p></td><td><button onclick = deleteMes('+j+')>删除留言</button></td></tr>';
                j++;
            }
        }else if(message.length>10){
            for(let i = message.length,j=1;i>(message.length-10);i--){
                messageShow = '<table style="text-align: left"><tr><th>'+messageShow+'</th><th></th><th></th></tr>'+'<tr><td>('+j+')</td><td><p id="'+j+'">'+message[i-1]+'</p></td><td><button onclick = deleteMes('+j+')>删除留言</button></td></tr>';
                j++;
            }
        }
        messageShow = messageShow +'</table>';
    }
    mesLength2 = mesLength;
    ctx.body = messageShow;
})

//获取客户端信息
router.get('/sysinfo', ctx => {
    let ob = ctx.request.headers["user-agent"].split(" ");
    let system = ob[1].substring(1);
    let chrome = ob[9].split('/')[0];
    let ip = ctx.request.socket["remoteAddress"];
    let iptype = ctx.request.socket["remoteFamily"];
    ctx.body = "<b>操作系统:</b>"+system+"  <b>浏览器:</b> "+chrome+"<b>ip地址:</b> "+ip+" <b>ip类型:</b> "+iptype;
})

//获取访问量
router.get('/visit',async (ctx) => {
    await sqlUser.getVisitCount()
    .then(result =>{
        let arr = [];
        let day_vi = 0;
        let today_date = timeGetter.getServerDate(); 
        for(i of result){
            arr.push(i.login_time);
        }
        // 访问总量
        let vi = arr.length;
        for (let i = 0; i<arr.length;i++){
            if(arr[i] == today_date){
                day_vi++;
            }
        }
        ctx.body = "当前页面总访问量为:"+vi+"次"+"\n今日访客量为:"+day_vi+"次";
    });
})

// 提交留言
router.post('/message',async (ctx) =>{
    let userMes = ctx.request.body.message;
    let sqlParams = [mesLength2+1,userMes];
    await sqlUser.insertMes(sqlParams).then(result=>{
        ctx.body = "成功了!";
    });
});

//删除留言
router.post('/deleteMes',async (ctx) =>{
    let userMes = ctx.request.body.message;
    let sqlParams = [userMes];
    await sqlUser.deleteMes(sqlParams).then(result=>{
        ctx.body = "删除成功!";
    });
});


//登陆
router.post('/login',async (ctx) =>{
    let username = ctx.request.body.profile;
    let pwd = ctx.request.body.pwd;
    let user = {'username':username};
    await sqlUser.findDataByUser(username,pwd).then( result=>{
        if(result[0]){
            user['role'] = result[0].role;
            ctx.session = user;
            ctx.body = '2';
        }else{
            ctx.body = '1' ;
        }
    })
})

//登录引导页
router.get('/',async ctx =>{
    if(JSON.stringify(ctx.session) =='{}'){
        await ctx.render('login');
    }else{
        await ctx.render('homePage',{
            session : ctx.session
        });
    }
})

//登出
router.get('/clearSession',async (ctx) =>{
    let clear = function(){
        ctx.session = null;
    }
    clear();
    await ctx.render('login');
})

//注册
router.post('/register',async(ctx) =>{
    let profile = ctx.request.body.profile;
    let pwd = ctx.request.body.pwd;
    let username = ctx.request.body.username;
    let create_time = timeGetter.getServerDate();
    let role = 'normal_user';
    let value = [profile,pwd,username,role,create_time];
    await sqlUser.insertUser(value).then(result=>{
        if(result){
            let user = {username:username,role:role};
            ctx.session = user;
            ctx.body = "1";
        }else{
            ctx.body = '2';
        }
    })
})

module.exports = router;

值得注意的是,我们在这里面开始应用上ES6、7标准的语法,async/await函数以及promise的语法:

1)在routes中的index文件,我们应该在装有异步的事件中使用async函数,部分api是不需要使用到async函数,因为不存在异步回调的使用,如返回服务器时间、获取客户端系统信息等

2)使用了async函数,参数列表是否使用next取决于函数的内容,next()会直接进入下一个中间件,等待中间件处理完毕之后再回到当前函数继续执行

3)我们在数据库操作完成返回了一个promise对象,可以利用promise对象的.then()对await 里获得的返回对象进行下一步的操作,并且建议await后面的语句是一个异步的事件,当然如果不是也没关系,await会按照正常的语句去处理,相当于同步处理

关于使用的几大模块:

1.session:直接对session的操作,依赖koa-session-minimal我们实现了对ctx.session非常简便的操作,进行用户角色和权限的控制

2.sql:将sql的管理控制抽离出来,在工程结构里集成管理


sql数据持久化操作

mysql.js

var mysql = require('mysql');
var config = require('../config/default.js')

var pool  = mysql.createPool({
  host     : config.database.HOST,
  user     : config.database.USERNAME,
  password : config.database.PASSWORD,
  database : config.database.DATABASE
});

let query = function( sql, values ) {

  return new Promise(( resolve, reject ) => {
    pool.getConnection(function(err, connection) {
      if (err) {
        resolve( err )
      } else {
        connection.query(sql, values, ( err, rows) => {

          if ( err ) {
            reject( err )
          } else {
            resolve( rows )
          }
          connection.release()
        })
      }
    })
  })

}

// 提交留言
let insertMes = function(value) {
  let _sql = "INSERT INTO MyOwnPage_messageBox (messageCount,message) value (?,?) "
  return query( _sql, value )
}
// 删除留言
let deleteMes = function(value) {
  let _sql = "DELETE FROM MyOwnPage_messageBox WHERE message = ?"
  return query( _sql, value )
}

// 获取所有的留言总量
let getAllMesCount = function() {
  let _sql = "SELECT count(message) FROM MyOwnPage_messageBox"
  return query( _sql)
}

// 获取所有的留言
let getAllMes = function() {
  let _sql = "SELECT message FROM MyOwnPage_messageBox"
  return query( _sql)
}

// 查询访客量
let getVisitCount = function() {
  let _sql = "SELECT login_time FROM login_log"
  return query( _sql)
}

//增加访客量
let addVisit = function(value) {
  let _sql = "INSERT INTO login_log (page,ip,login_time) value (?,?,?) ";
  return query( _sql, value);
}

//通过账户名密码查询登陆id及角色
let findDataByUser = function (profile,pwd) {
  let _sql = `SELECT username, role FROM USER_PROFILE WHERE email = "${profile}"`
  return query( _sql)
}

//新增(注册)用户
let insertUser = function(value) {
  let _sql = "INSERT INTO user_profile (email,pwd,username,role,create_time) value (?,?,?,?,?) ";
  return query( _sql, value );
}

module.exports={
    insertMes,
    deleteMes,
    getAllMes,
    findDataByUser,
    getVisitCount,
    addVisit,
    getAllMesCount,
    insertUser
}

登录页面

login.ejs

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>IronMan 登陆页面</title>
    <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
    <style>
        #header{
            background-color:black;
            color:white;
            text-align:center;
            padding:5px;
            height: 20px;
        }
    </style>
    <script>
        function login(){
            let profile = $("#profile").val() ;
            let pwd = $("#pwd").val();
            $.ajax({
                type:'POST',
                url:'/login',
                data:{profile : profile,
                    pwd : pwd
                },
                success: function(data){
                    if(data == '2'){
                        // alert(data);
                        red(data);
                    }else{
                        alert('账号或密码出错了!');
                        }
                    }
                })
        }
        function red(data){
            // let dd = data.split(',');
            // let us = dd[0];
            // let ro = dd[1];
            let link = '/HomePage';
            window.location.href=link;
        }
        function register(){
            let profile = $("#profile2").val() ;
            let username = $("#username").val();
            let pwd = $("#pwd2").val();
            $.ajax({
                type:'POST',
                url:'/register',
                data:{profile : profile,
                    username : username,
                    pwd : pwd
                },
                success: function(data){
                    if(data == '1'){
                        alert("注册成功,跳转至首页!");
                        red(data);
                    }else{
                        alert('账号名或密码已存在!');
                        }
                    }
                })
        }
        function changePwd(){
            let profile = $("#profile3").val() ;
            let old_pwd = $("#old_pwd").val();
            let new_pwd = $("#pwd3").val();
            let new_pwd2 = $("#pwd4").val();
            if(new_pwd != new_pwd2){
                alert("输入的两次密码不一致,请重新输入");
            }else{
                $.ajax({
                type:'POST',
                url:'/changePwd',
                data:{profile : profile,
                    pwd : old_pwd,
                    pwd2 : new_pwd
                },
                success: function(data){
                    if(data){
                        alert("修改成功");
                        red(data);
                    }else{
                        alert('账号名或密码已存在!');
                        }
                    }
                })
            }
        }
    </script>
</head>
<body>
        <p id="header">IronMan</p>
        <h2 style="text-align: center">
            <b style="color: rgb(255, 180, 180)">欢迎来到IronMan的个站</b>
        </h2>
        <table>
            <tr>
                <th>
                    <h3 style="color: rgb(145, 145, 253)" >登陆</h3>
                </th>
            </tr>
            <tr>
                <td>账号:</td><td><input id="profile"></td>
            </tr>
            <tr>
                <td>密码:</td><td><input id="pwd"></td>
            </tr>
            <tr>
                <td><input value="登陆" type="submit" οnclick="login()"></td>
            </tr>
        </table>
        <br>

        <table style="text-align: left">
            <tr>
                <th><h3 style="color: rgb(145, 145, 253)" >注册</h3></th>
            </tr>
            <tr>
                <td><b>请填写以下信息并完成注册:</b></td>
            </tr>
            <tr>
                <td>账号(邮箱):</td><td><input id="profile2"></td>
            </tr>
            <tr>
                <td>用户名:</td><td><input id="username"></td>
            </tr>
            <tr>
                <td>密码:</td><td><input id="pwd2"></td>
            </tr>
            <tr>
                <td><input value="注册" type="submit" οnclick="register()"></td>
            </tr>
        </table>
        <br>
        <table style="text-align: left">
            <tr>
                <th><h3 style="color: rgb(145, 145, 253)" >修改密码</h3></th>
            </tr>
            <tr>
                <td>账号</td><td><input id="profile3"></td>
            </tr>
            <tr>
                <td>请输入旧密码:</td><td><input id="old_pwd"></td>
            </tr>
            <tr>
                <td>新密码:</td><td><input id="pwd3"></td>
            </tr>
            <tr>
                <td>确认密码:</td><td><input id="pwd4"></td>
            </tr>
            <tr>
                <td><input value="确认修改" type="submit" οnclick="changePwd()"></td>
            </tr>
        </table>
</body>
</html>

登录页面是常规的操作了,很简单,重点在于我们的主页,使用模板引擎去把session的内容展示出来

主页 homePage.ejs

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <link type="text/css" rel="styleSheet"  href="./iron.css" />
    <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
    <title>个人站点主页</title>
    <script> 
        //获取系统时间
        function getSystemTime(){
            $.ajax({
            type:'GET',
            url:'/sysTime_wenzhiqun',
            success: function(data){
                if(data){
                    document.getElementById('time').innerHTML= data;

                }else{
                    alert('失败了!');
                    }
                }
            })
        }
        //获取访问次数
        function getVisit(){
            $.ajax({
            type:'GET',
            url:'/visit',
            success: function(data){
                if(data){
                    document.getElementById('foot').innerHTML= data;
                }else{
                    alert('失败了!');
                    }
                }
            })
        }
        //获取留言信息
        function getMesBox(){
            $.ajax({
            type:'GET',
            url:'/message/list',
            success: function(data){
                if(data){
                    document.getElementById('messageBox').innerHTML= data;
                }else{
                    alert('失败了!');
                    }
                }
            })
        }
        //提交留言
        function mesPost(){
            console.log($('.form').serialize())
            let mes = $("#message").val() ;
            alert(mes);
            if(mes == '' || mes.length >= 20){
                alert("留言不能为空或超过20个字符长度");
            }else{
                $.ajax({
            type:'POST',
            url:'/message',
            data:$('.form').serialize(),
            success: function(data){
                if(data){
                    getMesBox();
                }else{
                    alert('失败了!');
                    }
                }
            })
            }
        }
        //获取客户端信息
        function getClientMes(){
            $.ajax({
            type:'GET',
            url:'/sysinfo',
            success: function(data){
                if(data){
                    document.getElementById('xiugai').innerHTML= data;
                }else{
                    alert('失败了!');
                    }
                }
            })
        }
        function choose(){
            let choose = parseInt(3*Math.random())+1;
            if(choose === 1 ){
                document.getElementById('body').style.backgroundColor = 'white';
            }if(choose === 2){
                document.getElementById('body').style.backgroundColor = 'rgb(212, 211, 211)';
            }if(choose ===3){
                document.getElementById('body').style.backgroundColor = 'rgb(251, 255, 188)';
            }
        }
        function changeStyle(){
            setInterval('choose()',3000); 
        }

        function deleteMes(j){
            let mes = document.getElementById(j).innerText;
                $.ajax({
                    type:'POST',
                    url:'/deleteMes',
                    data:{message : mes },
                    success: function(data){
                        if(data){
                            getMesBox();
                        }else{
                            alert('失败了!');
                            }
                    }
                })
        }
    </script>

</head>
<body id="body"  οnlοad="changeStyle()" style="background-color: rgb(248, 211, 211)"></body>
    <p id="header">IronMan</p>
    <h4 id="time" οnclick="getSystemTime()">点我刷新服务器时间</h4>
    <div class="user_name" style="text-align: right">
        您好,
        <% if(session.username){ %>
             <%= session.username %>
             <a href="/clearSession">退出登录</a>
        <% } %>
        <% if(!session.username){ %>
            您还未登录
        <% } %>
        
    </div>
    <div>
        <div id="myimage">
            <img src="./iron2.jpg">
        </div>
        <div id="kongbai"></div>
        <div id="headDiv">
            <h3>个人介绍</h3>
            <h4>IronMan</h4>
            <h4>诞生地:Marvel</h4>
            <h4>详细介绍:</h4>
            <p>托尼·史塔克(Tony Stark)即钢铁侠(Iron Man),
                是美国漫威漫画旗下超级英雄,初次登场于《悬疑故事》(Tales of Suspense)第39期(1963年3月),
                由斯坦·李、赖瑞·理柏、唐·赫克以及杰克·科比联合创造。全名安东尼·爱德华·“托尼”·斯塔克(Anthony Edward “Tony” Stark),
                是斯塔克工业(STARK INDUSTRIES)的董事长,因于一场阴谋绑架中,胸部遭弹片穿入,生命危在旦夕,为了挽救自己的生命,
                在同被绑架的物理学家殷森(Yin Sen)的协助下托尼造出了防止弹片侵入心脏的方舟反应炉从而逃过一劫,后又用方舟反应炉作为能量运转的来源,
                暗中制造了一套高科技战衣杀出重围后逃脱,后参与创立复仇者联盟。</p>
            </p>
        </div>
    </div>
    
    <form class="form create" method="post ">
        <div>
            <label>留言板 :</label> 
            <input placeholder="留言" type="text" name="message" id="message">
        </div>
        <div class="submit" οnclick="mesPost()">提交</div>
    </form> 

    <div id="headDiv2">
        <h4 id="messageBox"  οnclick="getMesBox()">点我显示留言栏</h4>
        <h4 οnclick="getClientMes()" >点我显示当前访问的客户端信息为:</h4><p id="xiugai"></p>
    </div>
   
       
    <div >
        <p id="foot" οnclick="getVisit()">点我显示访问量</p>
    </div>
    
</body>
</html>

实现后,管理员登录的页面如下图:

1)在服务器时间下多了登录的用户名显示

2)支持管理对留言栏的删除处理

3)其实还有一个隐藏的页面背景色的定时变化,截图所以看不出来~但是代码里面是可以发现的


结束语

到这里,基本上整个网站就已经完成了~

这个博客网站比较简单,代码有很多改进的地方,希望对你们有帮助,如果有什么建议可以和我联系,qq:657897294,有什么不懂得也可以问我,有空就会回复啦!

git地址:https://github.com/VeniesLoveJava/nodejs_Koa_BlogWeb.git

非常感谢你读完这篇这么长的文章!

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值