The source address

Blog address

CSDN

Must read before running the project

  1. All kinds of authorization parameters in the three projects have been modified into their own authorization parameters, I forgot !!!! Forget to know !!!! Forget to know !!!!
  2. Create your own database name. Tables are created automatically when you run Node

    myblog3Is the database name, and the admin login page has aA key generationLocal generated account: admin password: 123, can only be generated once, because the program write dead account, you need to manually go to the database User table to add an account information. Add, delete, change and check the interface of the account system have been realized, according to their own needs to release you can be very happy to log in to play

Function of the whole project

  1. Front-end BLOG function introduction:
  • Home Page (Mind Map (tree))
  • Articles (List of articles, Individual categories, Popular Articles, Article details, Article directory structure)
  • Leave a message (login, leave a message, send an email)
  • Works (Project addresses over the years)
  • About (About the Project introduction)
  • Login (normal login, Github login, QQ login (under review…) )
  1. Admin Describes the functions of the background system
  • Home page
  • Classification Management (CURD)
  • Message management (CURD, Pass, reject, reply)
  • Article list: CURD, Dropdown, Upload image, Markdown Editor, Comment List button Comment list: CURD, dropdown, Comment, Email
  1. KOA implements the back-end interface
  • Node is mainly back-end interface, specific interface specific view code.

vue-blog-web

  • Proxy (5454 is node port)
    proxyTable: {
        "/mapi": {
            target: "http://localhost:5454",
            changeOrigin: true,
            pathRewrite: {
                "^/mapi": ""}}},Copy the code
  • Interface layer encapsulation (HTTP /index.js)
    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) {// Intercept the range of status codesreturn status >= 200 && status < 500
                        },
                    }).then(response => {
                        if (response.status == 200) {
                            resolve(response.data);
                        } else if(Response. status == 401) {// No permission}else if(Response.status == 403) {// Session expires router.push ('/login')}else {
                            reject(response.data)
                        }
                    })
                    .catch(error => {

                        reject(error);
                    })
            })
        },
        post(url, method = 'post', params) {
            returnnew 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('Login information expired, please log in again');
                            // 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); }})})},Copy the code
  • Markdown’s syntax is compiled into HTML
    <mavon-editor ref="editor" :value="content" :subfield="false"
      :defaultOpen="'preview'" :toolbarsFlag="false" :editable="false"
      :scrollStyle="true" :ishljs="true">
    </mavon-editor>
Copy the code
  • Generate H2, H3 article directory Specific view (vue – blog – web/views/article/detail. Vue)

  • The rest are the basic knowledge of VUE, omitted…

vue-blog-admin

  • For details about basic project configurations, see vue-cli3-admin. [github.com/liuxingzhij…]
  • Agent (vue. Config. Js)
    proxy: {
        "/mapi": {
            target: "http://localhost:5454",
            changeOrigin: true,
            pathRewrite: {
                "^/mapi": ""}}},Copy the code
  • The global variable
  1. .env.development
  2. .env.production
  • Multi-level routing implementation (home page/article management/article comments) multi-level routing reason, because now a lot of add and delete are popover implementation, but once the content is a lot of time, the new page is the best method

The implementation of the main methods: meta hidden attributes Specific view (vue – blog – admin/SRC/router/routes. Js)

vue-blog-koa

  • Use KOA-Generator to generate the KOA2 project

    Blog.csdn.net/Zhooson/art…

  • Run the project must first modify the config/db.js file, otherwise it will report an error, the project run automatically generate database, their own in the database User table to create a User, and then log in admin operation

    const Sequelize = require('sequelize'); ** myblog3 database name ** root database name ** third parameter password database password */ const sequelize = new Sequelize('myblog3'.'root'.'Your database password', {
        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 }Copy the code
  • JWT permission verification
Const token = jwt.sign(userToken, JWT_SECRET, {expiresIn:'10h' });
Copy the code
  • Interface whitelist
  1. myblog3-app-5454.js
/ / JWT app. Use (koajwt ({secret: JWT_SECRET}). Unless ({path: [/ / login / ^ \ \ / API/user \ / login /,... ,}));Copy the code
  1. middleware/JWTPath.js
Module.exports = [// exports'/api/user/login'. ] ;Copy the code
  • Send E-mail (controllers/SendEmailServer. Js) send mail articles reference
    const nodemailer = require("nodemailer"); // code... // Use Smtp Protocol to send Email var transporter = nodemailer.createTransport({ //node_modules/nodemailer/well-known/services.json'smtp.qq.com', port: 465, // SMTP porttrue, auth: {user: nodemail. email, // The password is not qq password, is your SMTP password (authorization code) pass: nodemail. pass}});Copy the code
  • Node invokes a third-party interface
    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'
    }));
Copy the code
  • Making authorization process (controllers/GithubToken. Js)

    1. Register the application of OAuth APP
    2. Save the client_id client_secret
    3. Visit the GET: github.com/login/oauth…
    4. Goto http://localhost:3000/auth? Code = 8B309CC03f95 Save the code field
    5. Github.com/login/oauth… POST request body:{client_id,client_secret,code} to obtain the token
    6. api.github.com/user POST request: body:{client_id,client_secret} header: {Authorization: token token}
  • Upload images (controllers/UploadServer. Js)

    Koa-body implements uploading images, creating directories recursively, and so on

  • The Sequelize database implementation (controllers/schema.js) uses user.js as an example

  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}, // user password 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'); }}}, {// if istrueThe name of the table is the same as model, that is, user // isfalseMySQL > create table with plural users // create table with plural userstrue})}Copy the code
  • Sequelize sequelize

    Take Article as an example

  1. create
    Article.create(params)
Copy the code
  1. The editor
    Article.update({ browser }, {
        where: {
            id
        },
        fields: ['browser']})Copy the code
  1. Check the details
    Article.findOne({
        where: id,
    });
Copy the code
  1. delete
  Article.destroy({
      where: {
          id,
      }
  })
Copy the code
  1. Paging list
  Article.findAndCountAll({
      row: true.limit: +pageSize,
      offset: (pageIndex - 1) * (+pageSize),
      order: [
          ['id'.'DESC']],});Copy the code
  1. Fuzzy search
  const Op = Sequelize.Op;

  Article.findAndCountAll({
      row: true.limit: +pageSize,
      offset: (pageIndex - 1) * (+pageSize),
      where[op.like]: {title: {// fuzzy query [op.like]:The '%' + keyword + The '%',
        },
      }
      order: [
          ['id'.'DESC']],});Copy the code

Supplement Op’s knowledge

[Op. And] : {5} a: / / (a = 5) and (Op) or] : [{a: 5}, {a: 6}] / / (a = 5 or 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, / / not TRUE [Op. Between] : [6, 10], / / between 6 and 10 [Op. NotBetween] : [11, 15], / / not [make] in between 11 and 15: [1, 2], / / in [1, 2], [Op. NotIn] : [1, 2], / / not in [1, 2] / Op. Like:'%hat'/ / contains'%hat'
    [Op.notLike]: '%hat'/ / does not contain'%hat'
    [Op.iLike]: '%hat'/ / contains'%hat'(case insensitive) (PG only) [op.notilike]:'%hat'/ / does not contain'%hat'(PG only) [op. regexp]:'^[h|a|t]'// Matches the regular expression /~'^[h|a|t]'(MySQL/PG only) [op.notregexp]:'^[h|a|t]'// Does not match the regular expression /! ~'^[h|a|t]'(MySQL/PG only) [op.iregexp]:'^[h|a|t]'/ / ~ _'^[h|a|t]'(PG only) [op. notIRegexp]:'^[h|a|t]'/ /! ~ _'^[h|a|t]'(only PG) [op. like]: {[op. any]: ['cat'.'hat'} // Contain any array ['cat'.'hat'] - also applies to iLike and notLike [op. overlap]: [1, 2] // && [1, 2](PG array overlap operator) [op. contains]: / / @ [1, 2] > [1, 2] (PG) array contains operator (Op) contained] : [1, 2] / / < @ [1, 2] (PG) array contains the operator/Op. Any: [2,3] // Any array [2,3] ::INTEGER (PG only) [op.col]:'user.organization_id'/ / ='user'.'organization_id', using database language-specific column identifiers, in this case PGCopy the code
  1. Many-to-many relationships
  Category.belongsToMany(Article, {
      through: {
          model: ArticleToCategory,
      },
      foreignKey: 'categoryId',
  })
  Article.belongsToMany(Category, {
      through: {
          model: ArticleToCategory,
      },
      foreignKey: 'articleId',})Copy the code

Introduction to Database Tables

  • The article — — — — — — — — — — — — — –
  • ArticleComment ——- article reviews
  • ArticleTocategory —- Article tags (many-to-many relationships)
  • The category — — — — — — — — — — — — — the label
  • The comment — — — — — — — — — — — — — — message
  • The user — — — — — — — — — — — — — — — — — the user

release

  1. My server environment is CentOS 7.5 64-bit
  2. Dist web and admin package release file, koA all file release, do not release nodel_modules ah, their own server install node, nginx, pM2, Mysql and other operations
  3. Attention should be paid to the release of KOA project, because every time an online picture is uploaded in public/images, the file cannot be overwritten. In order to avoid this problem, we set up a file service project to manage file resources
  • For installing other environmentsyumCommand installation
  • Install Mysql blog.csdn.net/Zhooson/art…
  • Nginx configuration blog.csdn.net/Zhooson/art…
  • Other environments install themselves, simple ah-ha
  • Myblog3-web-2222.js/myblog3-admin-1111.js execute pm2 start myblog3-web-2222.js to start the web project execute pm2 start Pm2 start myblog3-app-5454.js start the node project

  • Folder structure; Use the Web as an example (You need to download Express first)

| – web | – dist (vue packaged files) | – myblog3 – web – 2222. Js (files as shown in the following code) | — package. Json (NPM I express) | — – node_moudles

Var express = require('express'); var app = express(); Use (express. Static (dist) app.use(dist)'./dist')); Var server = app.listen(2222,function() {
        console.info('Copy open browser');
    });
Copy the code

Nginx configuration

  • Logging In to the server (Two login methods)

    1. Log in to Filezilla
    2. SSH login
    SSH -p 22 root@ Your server IP address Press Enter and enter the passwordCopy the code
  • SSH login is used as an example to find the location of nginx.conf

    whereis nginx.conf
Copy the code

Search results:

    /usr/local/nginx/conf

Copy the code

If you are familiar with vim’s operation, you can directly operate it. If you are not familiar with FileZilla’s software, you can modify it

  • Conf (using the Web as an example) see ngixn.conf for details
    # Blog - Backstage AdministrationUpstream 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 / {

          Set the host header and client real address so that the server can obtain the real IP address of the client
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          # disable cache
          proxy_buffering off;

          Address of the reverse proxy
          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; }}Copy the code
  • How to proxy the Node interface when accessing the Web and admin projects, the key code is as follows
     location /api {
          proxy_pass http://myblog3Koa2;
     }
Copy the code
  • Configuration in Web and admin with mode: history
    root /webproject/myblog3/web;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
Copy the code

pm2

PM2 is a node process management tool. It can be used to simplify many node application management tasks, such as performance monitoring, automatic restart, load balancing, and so on.

Installation method

    npm i pm2 -g
Copy the code

Common Command Records

  • Pm2 start app.js # Start app.js

  • Pm2 start app.js -I 4 # cluster mode Starts four app.js application instances

  • Pm2 start app.js –name=” API”

  • Pm2 start app.js –watch # Automatically restart the app when the file changes

  • Pm2 start script.sh # Start bash script

  • Pm2 list # Lists all applications started by PM2

  • Pm2 Monit # displays CPU and memory usage for each application

  • Pm2 show [app-name] #

  • Pm2 logs # Displays logs for all applications

  • Pm2 logs [app-name] # pm2 logs [app-name] #

  • Pm2 Flush # Flush all log files

  • Pm2 stop all # Stop all applications

  • Pm2 stop 0 # Stop the specified application with id 0

  • Pm2 restart all applications

  • Pm2 reload all # Restart all applications in cluster mode

  • pm2 gracefulReload all # Graceful reload all apps in cluster mode

  • Pm2 delete all # Delete all applications

  • Pm2 delete 0 # Delete the specified application id

  • Pm2 Scale API 10 # Extends the application named API to 10 instances

  • Pm2 reset [app-name] # Reset the number of restarts

  • Pm2 startup # create a startup command

  • Pm2 Save # Saves the current app list

  • Pm2 resurrect # reloads the list of saved applications

  • pm2 update # Save processes, kill PM2 and restore processes

  • pm2 generate # Generate a sample json configuration file

Address: pm2 document pm2. Keymetrics. IO/docs/usage /…

About environment variables in KOA

In 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"
  },
Copy the code

We can use NPM run dev to get the environment variable of process.env.node_env locally.

Specific implementation method :(this code is only marked here, the specific file does not add code)

Step 1: Create file file.config.js at the same level as myblog3-app-5454.js

Module. exports = {apps: [{// exports: {// exports: {// exports: {// exports: {// exports: {// exports: {// exports: {// exports: {// exports: {// exports: {"myblog3-app-5454-prod"// project startup entry script:"./myblog3-app-5454.js", // project environment variable env: {"NODE_ENV": "production"."PORT": 5454}}, {.... }}]Copy the code

Step 2: Modify the package.json file and add a line of code:

    "start": "pm2 start ecosystem.config.js --only myblog3-app-5454-prod --watch"
Copy the code

Step 3: How do I run the project

Pm2 start myblog3-app-5544.js; NPM start myblog3-app-5544-prod; pm2 start myblog3-app-5544.js; Name =myblog3-app-5454-prod

Step 4: Direct file to process.env.node_env

NODE_ENV (process.env.node_env)

Please attach the original source link and this statement. The original link: www.zhooson.cn/article/det… Github.com/liuxingzhij…