源碼地址html
博客地址前端
CSDNvue
myblog3
爲數據庫名稱, admin 登陸頁面有個 一鍵生成
地方生成帳號:admin 密碼:123, 只能生成一次,由於是程序寫死的帳號,省的您手動去數據庫中 User 表去添加一條帳戶信息。帳戶的體系的增刪改查的接口都已經實現,根據本身的需求去釋放出來 您能夠很愉快的登陸玩耍了proxyTable: {
"/mapi": {
target: "http://localhost:5454",
changeOrigin: true,
pathRewrite: {
"^/mapi": ""
}
},
}
複製代碼
import Axios from 'axios'
import Router from '../router'
export default {
get(url, params) {
return new Promise((resolve, reject) => {
Axios({
method: "get",
url: url,
params: {
...params,
author: 'admin'
},
validateStatus: function(status) {
// 截獲狀態碼範圍
return status >= 200 && status < 500
},
}).then(response => {
if (response.status == 200) {
resolve(response.data);
} else if (response.status == 401) {
// 無權限
} else if (response.status == 403) {
// session 過時
Router.push('/login')
} else {
reject(response.data)
}
})
.catch(error => {
reject(error);
})
})
},
post(url, method = 'post', params) {
return new Promise((resolve, reject) => {
Axios({
method,
url: url,
data: {
...params,
author: 'admin'
},
validateStatus: function(status) {
return status >= 200 && status < 500
},
}).then(response => {
if (response.status == 200) {
resolve(response.data);
} else if (response.status == 401) {
// Message.error('登陸信息過時,請從新登陸');
// Router.replace('/login')
resolve({});
} else if (response.status == 403) {
Router.push('/login')
} else {
reject(response.data)
}
})
.catch(error => {
reject(error);
})
})
},
fetch(url, params, headers = {}) {
return new Promise((resolve, reject) => {
Axios({
method: "post",
url: url,
data: params,
headers: {
"Content-Type": "application/json",
...headers
}
}).then(response => {
if (response.status == 200) {
resolve(response.data);
} else {
reject(response.data)
}
})
.catch(error => {
reject(error);
})
})
},
}
複製代碼
<mavon-editor ref="editor" :value="content" :subfield="false"
:defaultOpen="'preview'" :toolbarsFlag="false" :editable="false"
:scrollStyle="true" :ishljs="true">
</mavon-editor>
複製代碼
生成 H2,H3 的文章目錄 具體查看(vue-blog-web/views/article/detail.vue)node
其餘都是 vue 的基礎的知識,省略。。。mysql
proxy: {
"/mapi": {
target: "http://localhost:5454",
changeOrigin: true,
pathRewrite: {
"^/mapi": ""
}
},
},
複製代碼
實現的主要方法: meta 的 hidden
的屬性
具體查看(vue-blog-admin/src/router/routes.js)ios
使用 koa-generator 生成 koa2 項目nginx
運行的項目必定先修改 config/db.js 的文件,否則會報錯的,項目運行自動生成數據庫,本身在數據庫 User 表建立的一個用戶,而後登陸 admin 的操做github
const Sequelize = require('sequelize');
/**
*
* 配置數據庫
*
* 第一個參數 myblog3 數據庫名字 (本身修改)
* 第二個參數 root 數據庫名字 (本身修改)
* 第三個參數 password 數據庫密碼 (本身修改)
*/
const sequelize = new Sequelize('myblog3', 'root', '你的數據庫密碼', {
host: 'localhost',
dialect: 'mysql',
operatorsAliases: false,
dialectOptions: {
charset: "utf8mb4",
collate: "utf8mb4_unicode_ci",
supportBigNumbers: true,
bigNumberStrings: true
},
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
timezone: '+08:00' //東八時區
});
module.exports = {
sequelize
}
複製代碼
// 簽發token
const token = jwt.sign(userToken, JWT_SECRET, { expiresIn: '10h' });
複製代碼
// jwt
app.use(
koajwt({ secret: JWT_SECRET }).unless({
path: [
// 登陸
/^\/api\/user\/login/,
...
],
})
);
複製代碼
module.exports = [
// 登陸
'/api/user/login',
...
];
複製代碼
const nodemailer = require("nodemailer");
// code...
// Use Smtp Protocol to send Email
var transporter = nodemailer.createTransport({
//node_modules/nodemailer/well-known/services.json 支持列表
host: 'smtp.qq.com',
port: 465, // SMTP 端口
secure: true,
auth: {
user: NODEMAILER.email,
//這裏密碼不是qq密碼,是你設置的smtp密碼(受權碼)
pass: NODEMAILER.pass
}
});
複製代碼
const koaRequest = require('koa-http-request');
app.use(koaRequest({
json: true, //automatically parsing of JSON response
timeout: 3000, //3s timeout
// host: 'https://api.github.com'
}));
複製代碼
github 受權 流程(controllers/GithubToken.js)web
上傳圖片(controllers/UploadServer.js)
koa-body 實現上傳圖片,遞歸建立目錄等
sequelize 數據庫實現 (controllers/schema.js) 以 user.js 爲例子
const moment = require('moment');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('user', {
id: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
// 用戶名字
username: {
type: DataTypes.STRING(100),
field: 'username',
allowNull: false
},
// 用戶密碼
password: {
type: DataTypes.STRING(255),
field: 'password',
allowNull: false
},
// 用戶郵箱
email: {
type: DataTypes.STRING(100),
field: 'email',
allowNull: false
},
createdAt: {
type: DataTypes.DATE,
field: 'created_at',
get() {
return moment(this.getDataValue('createdAt')).format('YYYY-MM-DD HH:mm:ss');
}
},
updatedAt: {
field: 'updated_at',
type: DataTypes.DATE,
get() {
return moment(this.getDataValue('updatedAt')).format('YYYY-MM-DD HH:mm:ss');
}
}
}, {
// 若是爲 true 則表的名稱和 model 相同,即 user
// 爲 false MySQL建立的表名稱會是複數 users
// 若是指定的表名稱本就是複數形式則不變
freezeTableName: true
})
}
複製代碼
sequelize 的使用方法:
以 Article 爲模型例子
Article.create(params)
複製代碼
Article.update({ browser }, {
where: {
id
},
fields: ['browser']
})
複製代碼
Article.findOne({
where: id,
});
複製代碼
Article.destroy({
where: {
id,
}
})
複製代碼
Article.findAndCountAll({
row: true,
limit: +pageSize,
offset: (pageIndex - 1) * (+pageSize),
order: [
['id', 'DESC']
],
});
複製代碼
const Op = Sequelize.Op;
Article.findAndCountAll({
row: true,
limit: +pageSize,
offset: (pageIndex - 1) * (+pageSize),
where:{
title: {
// 模糊查詢
[Op.like]: '%' + keyword + '%',
},
}
order: [
['id', 'DESC']
],
});
複製代碼
補充 Op 的知識
[Op.and]: {a: 5} // 且 (a = 5)
[Op.or]: [{a: 5}, {a: 6}] // (a = 5 或 a = 6)
[Op.gt]: 6, // id > 6
[Op.gte]: 6, // id >= 6
[Op.lt]: 10, // id < 10
[Op.lte]: 10, // id <= 10
[Op.ne]: 20, // id != 20
[Op.eq]: 3, // = 3
[Op.not]: true, // 不是 TRUE
[Op.between]: [6, 10], // 在 6 和 10 之間
[Op.notBetween]: [11, 15], // 不在 11 和 15 之間
[Op.in]: [1, 2], // 在 [1, 2] 之中
[Op.notIn]: [1, 2], // 不在 [1, 2] 之中
[Op.like]: '%hat', // 包含 '%hat'
[Op.notLike]: '%hat' // 不包含 '%hat'
[Op.iLike]: '%hat' // 包含 '%hat' (不區分大小寫) (僅限 PG)
[Op.notILike]: '%hat' // 不包含 '%hat' (僅限 PG)
[Op.regexp]: '^[h|a|t]' // 匹配正則表達式/~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]' // 不匹配正則表達式/!~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.iRegexp]: '^[h|a|t]' // ~_ '^[h|a|t]' (僅限 PG)
[Op.notIRegexp]: '^[h|a|t]' // !~_ '^[h|a|t]' (僅限 PG)
[Op.like]: { [Op.any]: ['cat', 'hat']} // 包含任何數組['cat', 'hat'] - 一樣適用於 iLike 和 notLike
[Op.overlap]: [1, 2] // && [1, 2](PG數組重疊運算符)
[Op.contains]: [1, 2] // @> [1, 2](PG數組包含運算符)
[Op.contained]: [1, 2] // <@ [1, 2](PG數組包含於運算符)
[Op.any]: [2,3] // 任何數組[2, 3]::INTEGER (僅限 PG)
[Op.col]: 'user.organization_id' // = 'user'.'organization_id', 使用數據庫語言特定的列標識符, 本例使用 PG
複製代碼
Category.belongsToMany(Article, {
through: {
model: ArticleToCategory,
},
foreignKey: 'categoryId',
})
Article.belongsToMany(Category, {
through: {
model: ArticleToCategory,
},
foreignKey: 'articleId',
})
複製代碼
yum
的命令安裝myblog3-web-2222.js / myblog3-admin-1111.js (2 個文件就是端口號不同)
執行 pm2 start myblog3-web-2222.js
把 web 的項目啓動
執行 pm2 start myblog3-admin-1111.js
把 admin 的項目啓動
執行 pm2 start myblog3-app-5454.js
把 node 的項目啓動
文件夾結構; 以 web 爲例子(須要先下載 express)
|--web
|---- dist (vue 打包的文件)
|---- myblog3-web-2222.js ( 文件以下代碼所示)
|---- package.json (npm i express)
|---- node_moudles
//引入express中間件
var express = require('express');
var app = express();
//指定啓動服務器到哪一個文件夾,我這邊指的是dist文件夾
app.use(express.static('./dist'));
// 監聽端口爲1111
var server = app.listen(2222, function() {
console.info('複製打開瀏覽器');
});
複製代碼
登陸服務器(2 種登陸方式)
ssh -p 22 root@你的服務器ip地址
回車
輸入密碼
複製代碼
已 ssh 登陸爲例子: 查找 nginx.conf 的位置
whereis nginx.conf
複製代碼
查找結果:
/usr/local/nginx/conf
複製代碼
熟悉 vim 的操做的,直接操做,不熟悉的使用的 FileZilla 的軟件去修改
#博客 - 後臺管理
upstream myblog3Admin {
server 127.0.0.1:1111;
}
server {
listen 80;
server_name www.zhooson.cn;
#charset koi8-r;
#access_log logs/host.access.lsog main;
location / {
#設置主機頭和客戶端真實地址,以便服務器獲取客戶端真實IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#禁用緩存
proxy_buffering off;
#反向代理的地址
proxy_pass http://myblog3Web;
root /webproject/myblog3/web;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://myblog3Koa2;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
複製代碼
location /api {
proxy_pass http://myblog3Koa2;
}
複製代碼
root /webproject/myblog3/web;
index index.html index.htm;
try_files $uri $uri/ /index.html;
複製代碼
PM2 是 node 進程管理工具,能夠利用它來簡化不少 node 應用管理的繁瑣任務,如性能監控、自動重啓、負載均衡等,並且使用很是簡單。
npm i pm2 -g
複製代碼
pm2 start app.js # 啓動 app.js 應用程序
pm2 start app.js -i 4 # cluster mode 模式啓動 4 個 app.js 的應用實例
pm2 start app.js --name="api" # 啓動應用程序並命名爲 "api"
pm2 start app.js --watch # 當文件變化時自動重啓應用
pm2 start script.sh # 啓動 bash 腳本
pm2 list # 列表 PM2 啓動的全部的應用程序
pm2 monit # 顯示每一個應用程序的 CPU 和內存佔用狀況
pm2 show [app-name] # 顯示應用程序的全部信息
pm2 logs # 顯示全部應用程序的日誌
pm2 logs [app-name] # 顯示指定應用程序的日誌
pm2 flush # 清空全部日誌文件
pm2 stop all # 中止全部的應用程序
pm2 stop 0 # 中止 id 爲 0 的指定應用程序
pm2 restart all # 重啓全部應用
pm2 reload all # 重啓 cluster mode 下的全部應用
pm2 gracefulReload all # Graceful reload all apps in cluster mode
pm2 delete all # 關閉並刪除全部應用
pm2 delete 0 # 刪除指定應用 id 0
pm2 scale api 10 # 把名字叫 api 的應用擴展到 10 個實例
pm2 reset [app-name] # 重置重啓數量
pm2 startup # 建立開機自啓動命令
pm2 save # 保存當前應用列表
pm2 resurrect # 從新加載保存的應用列表
pm2 update # Save processes, kill PM2 and restore processes
pm2 generate # Generate a sample json configuration file
pm2 文檔地址:pm2.keymetrics.io/docs/usage/…
在 blog-koa/package.json 中
"scripts": {
"dev": "cross-env NODE_ENV=development nodemon myblog3-app-5454.js",
"prod": "cross-env NODE_ENV=production nodemon myblog3-app-5454.js"
},
複製代碼
咱們在本地調試中可使用 npm run dev
去拿到 process.env.NODE_ENV
的環境變量,咱們在 pm2 的環境下如何拿到呢??
具體實現的方法:(本文此處的才標註此代碼,具體文件中不作代碼添加
)
步驟 1: 和 myblog3-app-5454.js
同級別建立文件: ecosystem.config.js
// 這裏能夠寫 生產環境,測試環境,預發佈環境等
module.exports = {
apps: [{
// 生產環境
name: "myblog3-app-5454-prod",
// 項目啓動入口文件
script: "./myblog3-app-5454.js",
// 項目環境變量
env: {
"NODE_ENV": "production",
"PORT": 5454
}
},
{
....
}]
}
複製代碼
步驟 2: 修改的package.json
文件,添加一行代碼:
"start": "pm2 start ecosystem.config.js --only myblog3-app-5454-prod --watch"
複製代碼
步驟 3: 如何運行項目
本文初說明能夠用的 pm2 start myblog3-app-5454.js
的方式運行,如今使用 npm start
啓動, myblog3-app-5454-prod
表明這個進程的 name ,其實就是--name=myblog3-app-5454-prod 的寫法
步驟 4: 直接文件中就能夠 process.env.NODE_ENV
PS: 不須要的 process.env.NODE_ENV
此功能的徹底前一種方式就能夠了,不過項目畢竟都是區分環境,最好的使用下哈
轉載請附上原文出處連接及本聲明。 原文連接:www.zhooson.cn/article/det… github.com/liuxingzhij…