【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" onclick="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" onclick="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" onclick="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" onload="changeStyle()" style="background-color: rgb(248, 211, 211)"></body>
<p id="header">IronMan</p>
<h4 id="time" onclick="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" onclick="mesPost()">提交</div>
</form>
<div id="headDiv2">
<h4 id="messageBox" onclick="getMesBox()">點我顯示留言欄</h4>
<h4 onclick="getClientMes()" >點我顯示當前訪問的客戶端資訊為:</h4><p id="xiugai"></p>
</div>
<div >
<p id="foot" onclick="getVisit()">點我顯示訪問量</p>
</div>
</body>
</html>
實現後,管理員登入的頁面如下圖:
1)在伺服器時間下多了登入的使用者名稱顯示
2)支援管理對留言欄的刪除處理
3)其實還有一個隱藏的頁面背景色的定時變化,截圖所以看不出來~但是程式碼裡面是可以發現的
結束語
到這裡,基本上整個網站就已經完成了~
這個部落格網站比較簡單,程式碼有很多改進的地方,希望對你們有幫助,如果有什麼建議可以和我聯絡,qq:657897294,有什麼不懂得也可以問我,有空就會回覆啦!
git地址:https://github.com/VeniesLoveJava/nodejs_Koa_BlogWeb.git
非常感謝你讀完這篇這麼長的文章!