React has been used for front-end development since 19 years. React has been abandoned for a long time. It has been used since react learned koA + Sequelize, and wanted to use this backend to write interfaces

First, the effect drawing

1. Front-end display

2. Back-end display

Two, back-end usekoa+sequelizeAs the framework,mysqlAs a back-end database type

1. How to create a project

1.1 Installation Dependencies

npm install -g koa-generator 
Copy the code

1.2 In the current Path, Use KOA-Generator to generate koA2 Projects (CMD command Line)

koa2 koa-test-sequelize-auto
Copy the code

1.3 Go to the Koa-test-Sequelize-Auto directory (If yarn has not been downloaded, download yarn globally. NPM install -g yarn

yarn install 
Copy the code

The generated document directory

├ ─ ─ bin ├ ─ ─ public ├ ─ ─ routes ├ ─ ─ the view ├ ─ ─ package. The json └ ─ ─ app. JsCopy the code

1.4 Starting the Project

npm run dev
Copy the code

2. Build orM library

Install the following dependencies in the current project (CMD command line)

yarn add sequelize
yarn add sequelize-auto
yarn add mysql
yarn add mysql2
Copy the code

3. Start project construction: adopt MVC mode

In the root directory to create controllers, modules, schema, the config folder

  • Controllers: Write the control logic part
  • Modules: Write the SQL part
  • Schema: Write the data table part
  • Config: writes the database configuration

As is shown in

4. Initialize the connection pool using Sequelize

Create the config/db.js file in the root directory: (Note: the connected database must exist. If not, create a database. CREATE DATABASE blogs DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;)

Configuring the Database

const Sequelize = require('sequelize')
    const sequelize = new Sequelize('koa'.'root'.'123456', {host:'localhost'.dialect:'mysql'.operatorsAliases:false.dialectOptions: {/ / character set
            charset:'utf8mb4'.collate:'utf8mb4_unicode_ci'.supportBigNumbers: true.bigNumberStrings: true
        },
        pool: {max: 5.min: 0.acquire: 30000.idle: 10000
        },
        timezone: '+ 08:00'  // Time zone 8 EAST
    })
    
    module.exports = {
        sequelize
    }
Copy the code

5. Model creation

Create tags.js in the schema directory

const Sequelize = require("sequelize");
const moment = require("moment");
const tag = (sequelize, DataTypes) = > {
  return sequelize.define(
    "tag",
    {
      id: {
        type: DataTypes.INTEGER(11),
        primaryKey: true.autoIncrement: true,},name: {
        type: Sequelize.STRING,
        unique: {
          msg: "Added",},field: "name"
      },
      createdAt: {
        type: Sequelize.DATE,
        defaultValue: Sequelize.NOW,
        get() {
          return moment(this.getDataValue("createdAt")).format(
            "YYYY-MM-DD HH:mm"); }},updatedAt: {
        type: Sequelize.DATE,
        defaultValue: Sequelize.NOW,
        get() {
          return moment(this.getDataValue("updatedAt")).format(
            "YYYY-MM-DD HH:mm"); }},}, {freezeTableName: true}); }module.exports = tag;
Copy the code

5. Model use

Create tags.js in the modules directory

/* * @Author: Booble * @Date: 2021-05-Th 03:45:47 * @Last Modified by: Booble * @Last Modified time: 2021-05-Th 03:45:47 */
const db = require(".. /config/db");
const Sequelize = db.sequelize;
const Tags = Sequelize.import(".. /schema/tags.js");
Tags.sync({ alter: true });

class TagsModule {
  static async gettags(query, limit){-- Paged listreturn await Tags.findAndCountAll({
      where: {
        ...query,
      },
      order: [["id"."DESC"]],
      offset: limit.offset,
      limit: limit.limit,
    });
  }
  static async gettagsAll(){-- Total number of entriesconst list = await Tags.findAll(
    {attributes: ['id'.'name'} -- display only the field);return list
  }
  static async delTag(id){-- delete the tagreturn await Tags.destroy({
      where: {
        id,
      },
    });
  }
  static async updateTag(data){-- Update notesconst { id, name } = data;
    return await Tags.update(
      {
        id,
        name,
      },
      {
        where: {
          id,
        },
      }
    );
  }
  static async addTag(query){-- add labelsreturn await Tags.create({
      name: query.name, }); }}module.exports = TagsModule;
Copy the code

6, control layer write logic

Create tags.js in the controllers directory

/* * @Author: Booble * @Date: 2021-05-Th 04:36:42 * @Last Modified by: Booble * @Last Modified time: 2021-05-Th 04:36:42 */
const Sequelize = require("sequelize");
const Op = Sequelize.Op;
const TagModule = require(".. /modules/tags");
class TagControler {
  static async taglist(ctx) {     // Query the list
    let ctx_query = ctx.request.body;
    try {
      let pageSize = ctx_query.pageSize;
      let page = ctx_query.pageNo ? (ctx_query.pageNo - 1) * pageSize : 0;
      let sql = {
        name: {
          [Op.like]: "%" + ctx_query.name + "%",}};let limitpage = {
        offset: page,
        limit: pageSize,
      };
       const { rows: result, count: total } = await TagModule.gettags(
         sql,
         limitpage
       );
      ctx.response.status = 200;
      if (result) {
        ctx.body = {
          code: 200.data: result,
          total: total ? total: 0}; }else {
        ctx.body = {
          code: 400.message: "Connection request error"}; }}catch (err) {
      ctx.response.status = 500;
      ctx.body = {
        code: 500.message: "Server error, request failed!"}; }}static async getAll(ctx){-- gets the total number of entriestry {
       const data = await TagModule.gettagsAll();
       ctx.response.status = 200;
       if (data) {
         ctx.body = {
           code: 200.data: data,
           message: "Get ahead"}; }else {
         ctx.body = {
           code: 201.message: "Fetch failed"}; }}catch (err) {
      const msg = err.errors[0];
      ctx.body = {
        code: 500.message: msg.value + msg.message, }; }}static async addtag(ctx) {
    let query = ctx.request.body;
    if(! query.name) { ctx.response.status =200;
      ctx.body = {
        code: 1003.desc: "Tag cannot be empty."};return false;
    }
    try {
      const data = await TagModule.addTag(query);
      ctx.response.status = 200;
      if (data) {
        ctx.body = {
          code: 200.message: "New success"}; }else {
        ctx.body = {
          code: 201.message: "New failure"}; }}catch (err) {
      const msg = err.errors[0];
      ctx.body = {
        code: 500.message: msg.value + msg.message, }; }}static async deletag(ctx) {   / / delete
    //const { id } = ctx.request.body;
    const { id } = ctx.params;
    try {
        const result = await TagModule.delTag(id);
        if (result) {
          ctx.response.status = 200;
          ctx.body = {
            code: 200.message: "Data deleted successfully"}; }}catch (err) {
        ctx.response.status = 500;
        ctx.body = {
          code: 500.message: "Server error, request failed!"}; }}static async updatetag(ctx) {    / / update
    let query = ctx.request.body;
    try {
      const result = await TagModule.updateTag(query);
      if (result) {
        ctx.response.status = 200;
        ctx.body = {
          code: 200.message: "Data changed successfully"}; }}catch (err) {
      ctx.response.status = 500;
      ctx.body = {
        code: 500.message: "Server error, request failed"}; }}}module.exports = TagControler;
Copy the code

7. Configure the Router interface

Create tags.js in the Routes directory

const router = require("koa-router") ();const Tag = require(".. /controller/tags");

router.prefix("/api"); -- Route prefix router.post("/taglist", Tag.taglist);

router.get("/tag/alllist", Tag.getAll);

router.post("/tag/add", Tag.addtag);

router.del("/tag/delete/:id", Tag.deletag);

router.post("/tag/edit", Tag.updatetag);
module.exports = router;
Copy the code

Three, the front end is usedreact+antd

The front-end directory is

├ ─ ─ public ├ ─ ─ index. The HTML └ ─ ─ ─ the SRC │ │ ─ ─ API, interface │ │ static resources - assets - │ │ components - components - | | | - config - configuration | - pages - page | | - the Router routing | | - store - state management | | - utils - tools └ ─ ─ ─ index. The js └ ─ ─ ─ serviceWorker. Js - cross-domain configuration └ ─ ─ ─ app. JsCopy the code

1. Front-end request encapsulation

1.1. Create apiip. js domain name for production and development in API folder

// Address of the external service
export const publicIp =
  process.env.NODE_ENV === "development"
    ? "http://127.0.0.1:3001"
    : "Production domain name";
// Provide the address to obtain the image externally
export const logoImgIp = process.env.NODE_ENV === "development" ? "" : "";
// Log in to the route
export const LOGIN = "";

Copy the code

1.2. Create requiest. Js under API

import axios from "axios"; import { publicIp } from "./apiIp"; import { message } from "antd"; import store from ".. /store"; let hide = null; Const instance = axios.create({// Create an axios instance, where you can set the request's default configuration timeout: 10000, // set the timeout time to 10s baseURL: PublicIp, // According to their configured reverse proxy to set different environment baeUrl}); // Set the post header uniformly in the document. Here would say to the post request some 'the content-type. / / the instance defaults. Headers. Post [] "the content-type" = "application/json"; instance.defaults.headers["Content-Type"] = "application/json; chartset=UTF-8"; 400: "request parameter error ", 401:" permission not allowed, please log in again ", 403: "server refused this access ", 405: 404: "Requested resource not found ", 500:" internal server error ", 501: "server does not support method used in this request ", 502:" gateway error ", 504: "gateway timeout ",}; / * * / * * add request interceptor instance. The interceptors. Request. Use ((config) = > {config. Headers (" token ") = store. GetState (). The token | | "";  hide = message.loading({ content: "Loading..." , duration: 0 }); // Here: what can be done before sending the request according to the business requirements: for example, I export the file interface, because the return is a binary stream, so need to set the request response type to BLOB, can be set here. if (config.url.includes("pur/contract/export")) { config.headers["responseType"] = "blob"; } // I'm uploading a file, sending a binary stream, If (config.url.includes("pur/contract/upload")) {config.headers[" content-type "] = "multipart/form-data"; } return config; }, (error) => {// what to do about the request error return promise.reject (error); }); / * * * * / instance interceptor add response. The interceptors. Response. Use ((res) = > {hide () the if (res) status = = "200") {/ / response results in statusText: Resolve (res.data); return promise.resolve (res.data); }else{ this.props.history.push("/login"); } // else { // message.error(res.data.message); // return Promise.reject(res.data.message); // } // return Promise.resolve(res); }, (error) => {hide() if (error. Response) {let tips = error. Response. Status in httpCode? httpCode[error.response.status] : error.response.data.message; message.error(tips); If (error.response.status === 401) {// If the token or login fails, the login page is redirected. // this.props.history. Push ("/admin/page"); // this.props.history. } return Promise.reject(error); } else {message.error(" Request timed out, please refresh and try again "); Return promise.reject (" Request timed out, please refresh and retry "); }}); / / export const get = (url, params, config = {}) => {return new Promise((resolve, resolve)) reject) => { instance({ method: "get", url, params, ... config, }).then((response) => { resolve(response); },err =>{ reject(err); }).catch((error) => { reject(error); }); }); }; /* export const post = (url, data, config = {}) => {return new Promise((resolve, resolve, reject) => { instance({ method: "post", url, data, ... config, }).then((response) => { resolve(response); },err =>{ reject(err); }).catch((error) => { reject(error); }); }); }; /* export const del = (url, data, config = {}) => {return new Promise((resolve, resolve)) reject) => { instance({ method: "delete", url, data, ... config, }).then((response) => { resolve(response); },err =>{ reject(err); }).catch((error) => { reject(error); }); }); }; /* update request */ export const patch = (url, data, config = {}) => {return new Promise((resolve, reject) => { instance({ method: "patch", url, data, ... config, }).then((response) => { resolve(response); },err =>{ reject(err); }).catch((error) => { reject(error); }); }); };Copy the code

1.3 request mode and interface mount

Set it in index.js

import React, { Component } from "react";
import ReactDOM from 'react-dom';
import './index.less';
import './assets/root.css';
import App from './App';
import { get, post, del, patch } from "./api/request";
import { apiUrl } from "./api/apiUrl";
import * as serviceWorker from './serviceWorker';
// import Router from './Router/router'
Component.prototype.get = get;
Component.prototype.post = post;
Component.prototype.del = del;
Component.prototype.patch = patch;
Component.prototype.api = apiUrl;
ReactDOM.render(<App />.document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
Copy the code

2. How to call the front-end interface

As in the tag.js page

The project address

The front-end blog http://weblod.wxinxianyun.com/web/index

Project address https://gitee.com/xinxianbaiguoshu/koa-react