# 刪除無用文件夾
刪除routes、views、public 3個文件夾
# 修改app.js
```
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
//修改模板后綴為html
app.set('view engine', 'html');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', (req, res) => {
res.send('hello world!');
});
module.exports = app;
```

# 查看瀏覽器
此時瀏覽器中只會輸出hello world!
# 在應用根目錄新建config.js保存將來的應用配置信息
```
var fs = require('fs');
var path = require('path');
module.exports = {
url: 'http://localhost:3000',
mysql: {
host: 'localhost',
user: 'root',
password: 'root',
database: 'myapp',
connectionLimit: 100,
timezone: '+08:00',
charset: 'utf8_general_ci',
},
}
```
# 安裝mysql包
```
cnpm install mysql --save
```
**"mysql":?"^2.18.1"**

# 新建/libs/tools.js
```
var ejs = require('ejs');
var fs = require('fs');
var path = require('path');
//引用config.js
var config = require(__dirname + '/../config');
module.exports = {
//https://www.jb51.net/article/107406.htm
getUrlByParam: function (param) {
var url = "";
for (field in param) {
url += "&" + field + "=" + encodeURIComponent(param[field]);
};
return url == "" ? url : url.substring(1);
},
//分頁函數
pagination: function (url, param, page, pagesize, total) {
page = parseInt(page);
let total_page = Math.ceil(total / pagesize);
let previous_disabled = "";
let next_disabled = "";
if (page <= 1) {
previous_disabled = "disabled";
}
if (page >= total_page) {
next_disabled = "disabled";
}
let previous_page = Math.max(page - 1, 1);
let next_page = Math.min(page + 1, total);
let first_page = 1;
let last_page = total_page;
let _p1 = param;
let p1 = this.getUrlByParam(Object.assign(_p1, { page: previous_page }));
let _p2 = param;
let p2 = this.getUrlByParam(Object.assign(_p2, { page: next_page }));
let _p3 = param;
let p3 = this.getUrlByParam(Object.assign(_p3, { page: first_page }));
let _p4 = param;
let p4 = this.getUrlByParam(Object.assign(_p4, { page: last_page }));
let url1 = '';
let url2 = '';
let url_first = '';
let url_last = '';
if (url.indexOf('?') > -1) {
url1 = url + '&' + p1;
url2 = url + '&' + p2;
url_first = url + '&' + p3;
url_last = url + '&' + p4;
} else {
url1 = url + '?' + p1;
url2 = url + '?' + p2;
url_first = url + '?' + p3;
url_last = url + '?' + p4;
}
if (previous_disabled == 'disabled') {
url_first = url1 = 'javascript:void(0);';
}
if (next_disabled == 'disabled') {
url_last = url2 = 'javascript:void(0);';
}
let html = `
<script>
function EnterPress(e){
var e = e || window.event;
if(e.keyCode == 13){
var page=Math.abs(parseInt(e.target.value));
if(!page) return;
if(page>${total_page}) return;
location.href='${url}${url.indexOf('?') > -1 ? '&' : '?'}page='+page;
}
}
</script>
<div class="paging_simple_numbers" style="width:500px;margin:0 auto;">
<ul class="pagination">
<li class="paginate_button page-item ${previous_disabled}">
<a href="${url_first}" class="page-link">首頁</a>
</li>
<li class="paginate_button page-item previous ${previous_disabled}">
<a href="${url1}" class="page-link">上一頁</a>
</li>
<li class="paginate_button page-item active">
<a href="javascript:void(0);" class="page-link">${page}/${total_page} [共${total}條]</a>
</li>
<li class="paginate_button page-item next ${next_disabled}">
<a href="${url2}" class="page-link">下一頁</a>
</li>
<li class="paginate_button page-item ${next_disabled}">
<a href="${url_last}" class="page-link">尾頁</a>
</li>
<li class="paginate_button page-item">
<input type="text" placeholder="頁碼" value="" size="2" style="margin-top:4px;" onkeyup="EnterPress()">
</li>
</ul>
</div>
`;
return html;
},
//現在的時間戳
////https://www.cnblogs.com/fozero/p/6959946.html
time: function () {
return parseInt(new Date().getTime() / 1000);
},
//2019-12-12 23:59:59 轉 時間戳
strtotime: function (str) {
if (!str) return 0;
return parseInt(new Date(str).getTime() / 1000);
},
// 格式化日期,如月、日、時、分、秒保證為2位數
formatNumber: function (n) {
n = n.toString()
return n[1] ? n : '0' + n;
},
// 參數number為毫秒時間戳,format為需要轉換成的日期格式
//data(value, 'Y-M-D h:m:s');
date: function (number = '', format = 'Y-M-D h:m:s') {
if (!number) {
number = this.time();
}
//增加 2020-04-16T11:29:10.000Z 類型的處理
let time = typeof (number) == 'object' ? number : new Date(number * 1000);
let newArr = [];
let formatArr = ['Y', 'M', 'D', 'h', 'm', 's'];
newArr.push(time.getFullYear());
newArr.push(this.formatNumber(time.getMonth() + 1));
newArr.push(this.formatNumber(time.getDate()));
newArr.push(this.formatNumber(time.getHours()));
newArr.push(this.formatNumber(time.getMinutes()));
newArr.push(this.formatNumber(time.getSeconds()));
for (let i in newArr) {
format = format.replace(formatArr[i], newArr[i])
}
return format;
},
//數組合并
array_merge: function (a, b) {
return a.concat(b);
},
//對象合并
object_merge: function (a, b) {
let o = {};
return Object.assign(o, a, b);
},
//字符串重復
//http://www.manongjc.com/article/17174.html
str_repeat: function (str, num) {
return num > 1 ? str.repeat(num) : str;
},
//判斷是否在數組中
in_array: function (value, arr) {
return arr.indexOf(value) > -1;
},
//判斷是否在對象中
in_object: function (key, obj) {
key += '';
return typeof (obj[key]) != 'undefined';
},
//判斷數組或對象是否為空
//https://www.jianshu.com/p/cbdd58749489
empty: function (d) {
if (d.constructor === Array) {
return d.length > 0;
} else {
return Object.keys(d).length > 0;
}
},
//獲取文件后綴
//https://www.cnblogs.com/FallIntoDarkness/p/9757334.html
extension: function (filename) {
let index = filename.lastIndexOf(".");
let suffix = filename.substr(index + 1);
return suffix;
},
//生成從minNum到maxNum的隨機數
//https://www.cnblogs.com/wenxuehai/p/10285585.html
randomNum: function (minNum, maxNum) {
switch (arguments.length) {
case 1:
return parseInt(Math.random() * minNum + 1, 10);
break;
case 2:
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
//或者 Math.floor(Math.random()*( maxNum - minNum + 1 ) + minNum );
break;
default:
return 0;
break;
}
},
//消息提示函數
msg: function (code, msg = '', url = '') {
if (code) {
if (!msg) msg = '操作成功';
}
if (!code) {
if (!msg) msg = '操作失敗';
}
var str = fs.readFileSync(this.viewPath + 'msg.html', 'utf-8');
return ejs.render(str, { code: code, msg: msg, url: url });
},
//model加載函數
model: function (name) {
var m = require(this.modelPath + name + '.js');
return new m();
},
//myapp根目錄
rootPath: path.normalize(__dirname + '/../'),
//應用目錄
appPath: path.normalize(__dirname + '/../application/'),
//model目錄
modelPath: path.normalize(__dirname + '/../application/models/'),
//視圖目錄
viewPath: path.normalize(__dirname + '/../application/views/'),
//控制器目錄
controllerPath: path.normalize(__dirname + '/../application/controllers/'),
//runtime目錄
runtimePath: path.normalize(__dirname + '/../runtime/'),
//mysql表緩存目錄
tableCachePath: path.normalize(__dirname + '/../runtime/table/'),
//上傳文件目錄
uploadsPath: path.normalize(__dirname + '/../public/uploads/'),
//網站公共目錄
publicPath: path.normalize(__dirname + '/../public/'),
};
```
# 建立所有文件夾
```
mkdir application
mkdir application/models
mkdir application/views
mkdir application/controllers
mkdir runtime
mkdir runtime/table
mkdir public
mkdir public/uploads
```

# 新建/application/views/msg.html
```
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>系統提醒</title>
</head>
<body>
<div style="background:#4984DF;align:center;width:500px;margin:0 auto;">
<h2><% if(code){ %>操作成功<% }else{ %>操作失敗<% } %></h2>
<h3><%=msg%></h3>
<script>
<% if(code){ %>
<% if(url){%>
setTimeout(function(){
location.href='<%=url%>';
},1000);
<% }else{ %>
window.history.back();
<% } %>
<% } %>
<% if(!code){ %>
setTimeout(function(){
window.history.back();
},3000);
<% } %>
</script>
</div>
</body>
</html>
```
# 新建/application/views/404.html
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404</title>
</head>
<body>
404
</body>
</html>
```
- 課程介紹
- 開發環境搭建
- 安裝express.js框架
- 為diy自己的web框架做準備(1)
- 為diy自己的web框架做準備(2)
- 為應用綁定域名
- 封裝控制器基類base.js
- 封裝數據庫操作基類model.js
- curd操作-準備工作
- curd操作-文章列表
- curd操作-添加文章
- curd操作-編輯文章
- curd操作-刪除文章
- model文件的使用
- 文件上傳
- session實現登錄
- 郵件發送
- 文件下載
- 執行子任務
- 圖片縮放
- 圖片裁剪
- 圖片驗證碼
- Excel讀取與寫入
- 編寫計劃任務
- 工具函數使用實例
- websocket
- 集成ckeditor
- 微信公眾號開發-1:內網穿透
- 微信公眾號開發-2:自動回復
- 微信公眾號開發-3:api接口調用
- 微信公眾號開發-4:oauth登錄
- 微信公眾號開發-5:沙箱支付
- 微信公眾號開發-6:真實支付
- 項目上線運行
- 項目代碼下載