preface

It took me more than a month to make my own product because I had free time after work. Although I encountered many problems during development, I finally solved them. I felt very proud after completion.

A small order

Remember What Rebus once said: “We want to be the best tech company in rice fans’ minds.” To tell the truth, millet for myself (although I’m a fake rice noodles, but not for millet advertising), millet this decade made a lot of hard work, so that you can buy a higher ratio of the mass of technology products, millet, I appreciated every time there are some advanced ideas I will go to millet official public comment or feedback, also very want to go to millet, But I know THAT I am not qualified now and I still need to improve.

Although millet no direct relationship with me, but their spirit, is a positive, full of power, is encouraged and deeply affects me, many friends say I’m a millet mobile phone powder, little imagine my fan is the spirit of millet, because I also want to do a very cow force of the product, provide for the use of tens of thousands of people, I will be so proud.

There is a soul question: what can programmers do at 35?

If we do not climb the management level, we will become expensive and useless things, that is, luxury goods in the workplace. After the age of 35, understand that we will eventually be abandoned by The Times, because the enterprise needs fresh energy and more contemporary innovation. If you were the boss, you might as well. There are only two types of people over 35 in the workplace: luxury goods in the workplace, and horses that eat grass. Save your physical strength, exchange it for experience, exchange it for wisdom, exchange it for money, and at the same time, have a dream that you can love and still be able to do after 35 and even live on.

Now most young people without a dream, some is encircled by impetuous, lazy, lack of power, the car have been house have become the so-called dream, I can only sigh with emotion, because I may also be one of them, however, I firmly believe that my future is not them, I’m taking out the encirclement, find my dream, fighting for, even if fail, I shall not be held as long!

In fact, when we have a dream, grow up, I want to be a scientist, when the doctor…… , remember? But for a series of reasons (here….) No conditions? Not guiding properly? No support? . SOB… Reasons for skipping tens of thousands of words……) “, the dream disappeared. When I grew up, in order to make a living, a car, a house, a child and a family, the word “dream” became luxurious and unreachable.

Based on the above, I have figured out how important support and guidance are. Therefore, I want to make a tool to find, screen, guide and support students who want to have dreams or want to realize their dreams without knowing how to achieve them.

I want to make products that can help me better plan my life and even benefit all the confused people. So I tried to develop a full-stack product, but passion alone was useless. I was just a front end, not a background, and I could not write interfaces, nor operate servers, let alone deploy online… It’s too much to think about.

Unfortunately, the epidemic situation made me more eager to realize my product dream.

People still want to have a dream, when you have this dream, there will be a natural momentum of not three minutes of heat. In addition, when you see a lot of business leaders who started their business after they got married in middle age, you will find that age is not the problem, the key is whether you have the determination to do it and the persistence of lifelong struggle.

All things are difficult at the beginning, who cares, who loses, try again. So began my personal product.

Product introduction

My dream, want to do a very cool product: wechat small program “dream will reach”.

Have a dream will reach the original intention is a help confused, do not have a dream, still looking for a dream, have a dream but do not know how to achieve the children’s shoes better to find or realize the dream of wechat small program.

Dream will reach the initial design functions: login, registration, password retrieval, dream list, dream details, recommended courses, favorites, browsing records, reading number.

Product is not perfect, still need to improve, do not like spray.

GitHub open source address

The background template address is vue-admin-template

Address of all interfaces on the background Node: nodeExpress

The development process

Note: If you develop your product completely according to this blog, you may encounter some problems, such as unknown bugs caused by version problems or installation system restrictions, etc. I’ve had a lot of hiccups in my development, but as long as I stick to them, they don’t bother me. Even though I was a little nervous at the beginning when I encountered unknown bugs, I would find the answer through various methods and be proud when it was solved.

The overall development process is as follows:

3. Buy Aliyun server Cent Os 4. Install Node, Npm, Cnpm, Mysql, Nginx and configure PM2 5. Connect to the Mysql server, create a data table, install Xshell to connect to the remote server, and view the server files by Xftp. 6. Node+Express create a functional interface 9, Ali cloud background domain name upgrade HTTP=> HTTPS, after obtaining the certificate to the server and nginx configuration 10, wechat background set the domain name to HTTPS (HTTPS is required for normal requests) 11, wechat small program +Vant front end display 12, release wechat small program

First, there is a determination to achieve the dream

If you want to do a product, you should put him as a dream, because had the dream, there will be a drive, you will feel meaningful, so as to keep momentum, have a passion for his, not three days fishing net, two days at most adhere to a few days will fall by the wayside, in the end, the product didn’t finish, oneself also feel ability have a problem. So, even if the dream is difficult, we have to complete him, even if it will be a little slower!

Purchase ali Cloud domain name and put it on record

Here is relatively simple, go directly to aliyun official website – purchase domain name can aliyun wanwan link address

Note: after the purchase of domain name, you need to do the domain name record to access online (we want to do formal) Ali Cloud first record reference link address

Yi Ke consults other blog method to put on record, can realize put on record purpose to go

3. Purchase Ali Cloud server Cent Os

Install Node, Npm, Cnpm, Mysql, Nginx and PM2

Install Navicat Premium locally, connect to Mysql on remote server, create table, install Xshell to connect to remote server, Xftp to view server files

Due to the length of step 3, 4 and 5, I will directly move to open Source China preview

Node+Express create a functional interface

Nodejs parts:

1, package. Json

{" name ":" nodeDream ", "version" : "1.0.0", "description" : ""," main ":" app. Js ", "scripts" : {" test ", "echo \" Error: no test specified\" && exit 1" }, "author": "parchments", "license": "MIT", "dependencies": { "body-parser": "^ 1.19.0 cors", ""," ^ 2.8.5 ", "express" : "^ 4.17.1", "jsonwebtoken" : "^ 8.5.1", "multer" : "^ 1.4.2", "mysql" : "^ 2.17.1 nodemon", ""," ^ 2.0.2 ", "request" : "^ 2.88.2"}}Copy the code

2, connect. Js

const path = require("path"); const mysql = require("mysql"); const express = require("express"); const app = express(); // Instantiate an app const router = express.router (); const cors = require('cors'); const jwt = require('jsonwebtoken'); // generate token const request = require('request'); const bodyParser = require('body-parser'); app.use(bodyParser.json()); // Json request app.use(bodyParser.urlencoded({extended: false})); // form request // global configuration cross-domain app.use(cors()); Const pathName = __dirname; const pathname = __dirname; // Static file access app.use(express.static(pathname)); App. use(express. Static ('vueDream/dist')) function verifyToken(req, res, next){ let secretOrPrivateKey = 'jwtDream'; Jwt. verify(req.headers. Token, secretOrPrivateKey, function (__err, Decode) {if (__err) {return res.status(401). Send ({code: 401, data: null, message: "Login expired, please log in again"}); } else { next(); App. all('*', (req, res, next) => {// Set the response header res.header(" access-Control-allow-origin ", "*"); Header (" access-Control-allow-headers ", "*"); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); res.header("Content-Type", "application/json; charset=utf-8"); Token let isLogin = req.url.indexof ('login'); let isRegister = req.url.indexOf('register'); let isForgotPassword = req.url.indexOf('forgotPassword'); let isCollection = req.url.indexOf('collection'); let isHistory = req.url.indexOf('history'); // let isWechatLogin = req.url.indexOf('wechatLogin'); // let isGetWxAccessToken = req.url.indexOf('getWxAccessToken'); Token let systype = req.headers. Systype; if(systype === 'wechat'){ if(isCollection ! == -1 || isHistory ! == -1){ verifyToken(req, res, next) } else { next(); }} else if(systype === 'PC '){if(isLogin! == -1 || isRegister ! == -1 || isForgotPassword ! == -1){ next(); }else{verifyToken(req, res, next)}}}) VueDream /dist/index.html res.sendFile(path.resolve(__dirname,)) 'vueDream', 'dist', 'index.html')); }) // configure mysql const option = {host: "www.yousit", // host: "49.985.02.01", user: 'admin', port: '3306', password: ", database: "node", connectTimeout: 5000, // Connection timeout //multipleStatements: False // Whether to allow multiple SQL statements in a query} let pool; repool(); function Res ({ code = 200, message = '', data = {} }) { this.code = code; this.message = message; this.data = data; } function resJson (_res, Result) {return _res.json(new Res(result))} function repool() {mysql.createpool ({... Option, waitForConnections: true, // Wait (true) or throw (false) when no connection pool is available connectionLimit: 200, // queueLimit: On ('error', err => {err.code === 'PROTOCOL_CONNECTION_LOST' && setTimeout(repool, err.code === 'PROTOCOL_CONNECTION_LOST' && setTimeout(repool, 2000) }) app.all('*', (_,__, next) => { pool.getConnection( err => { err && setTimeout(repool, 2000) || next() }) }) } module.exports = { app, pool, router, resJson , jwt , request}Copy the code

3, app. Js

const { app, pool } = require('./connect'); //test app.all('/api', (req, res) => { pool.getConnection((err, conn) => { res.json({ type: 'test success'}) pool.releaseconnection (conn) Const multerUpload = require('./routes/upload'); const user = require('./routes/user'); const dreamList = require('./routes/dream'); const collectionList = require('./routes/collection'); const historyList = require('./routes/history'); // app.use('/upload', multerUpload); app.use('/user', user); app.use('/dream', dreamList); app.use('/collection', collectionList); app.use('/history', historyList); App. get('/ API /test', function (req, res) {res.json({message: "connect successfully"})}); // Enable the listening app. Listen (8888, () => {console.log(" Server port 8888 is open... ); })Copy the code

Express interface part:

1. Add, delete, change and check interface of list

Const {app, pool, router, resJson, JWT} = require('.. /connect'); GetData */ app.post("/ API /dream/getData", (req, Let {pageSize, pageNo, name, userId} = req.body; // Default pageSize = pageSize? pageSize : 5; pageNo = pageNo ? pageNo : 1; name = name ? name : null; SqlStr = 'select * from dream'; //let sqlStr = 'select d.name,d.id from dream'; Pool.getconnection ((err, conn) => {conn.query(sqlStr, (err, data) => {if (err) throw err; Let total = data.length; // let n = (pageno-1) * pageSize; // sqlStr += ` limit ${n}, ${pageSize}`; If (name){sqlStr += 'where name like '%${name}%'; if(name){sqlStr +=' where name like '%${name}%'; Conn.query (sqlStr, (_err, _data) => {if (_err) throw _err; Res. send({code: 1, data: {rows: _data, total: _data.length, pageNo: pageNo, pageSize: pageSize,}, message: 'Query succeeded! '}); }); }else{ sqlStr += ` limit ${n} , ${pageSize}`; conn.query(sqlStr, (_err, data) => { if (_err) throw _err; Res. send({code: 1, data: {rows: data, total: total, pageNo: pageNo, pageSize: pageSize,}, message: 'Query successful! '}); }); }}); Pool.releaseconnection (conn) // Release the connection pool and wait for another connection to use})}); // Add interface app.post('/ API /dream/add', (req, res) => {const data = req.body; const name = req.body.name; const sqlSameName = `select name from dream where name='${name}'`; Pool.getconnection ((err, conn) => {conn.query(sqlSameName, data, (_err, _results) => { if(_err){console.log(_err); return false; } // If (_results.length > 0){return res.json({code: 0, message: "Not repeatable!" , data: null }) }else{ const sqlStr = 'insert into dream set ? '; conn.query(sqlStr, data, (err, results) => { console.log(data) if (err) throw err; Res. json({code: 1, message: 'added successfully ', data: results}); })}) pool.releaseconnection (conn) // Release the connection pool and wait for another connection to use})}); // app.post('/ API /dream/edit', function (req, res) {const data = req.body; const id = req.body.id; // let { name, collectionStatus, price, age, experience, education, analysis, introduce, duty, ask, coverImagePath, planImagePathArray, viedoUrl} = req.body; let { name, coverImagePath, content, viedoUrl , recommend} = req.body; let modSql = `update dream set name='${name}', coverImagePath='${coverImagePath}', content='${content}', viedoUrl='${viedoUrl}', recommend='${recommend}' where id ='${id}'`; let nameSql = `select * from dream where name='${name}' and id ! ='${id}'`; Pool.getconnection ((err, conn) => {conn.query(nameSql, data, (err, conn)) Results) => {console.log(results) if(results.length >= 1){return res.json({code: 0, message: "Name already exists!" , data: null})}else{conn.query(modSql, data, (err, results) => {res.json({code: 1, message: 'modified successfully ', data: null})} Else {conn.query(modSql, data, (err, results) => {res.json({code: 1, message:' modified successfully ', data: results }); })}) pool.releaseconnection (conn) // Release the connection pool and wait for another connection to use})}); App.post ('/ API /dream/show', function (req, res) {let data = req.body; Let {id, userId} = req.body; let modSql = `select * from dream where id='${id}'`; pool.getConnection((err, conn) => { conn.query(modSql, data, (err, Results) => {if (err) {console.log(" query failed cause ",err) return res.json({code: 0, message: "query failed ", affectedRows: err }) } // 1. ReadCount results[0]. ReadCount = results[0]. ReadCount +1; let newReadCount = results[0].readCount; SqlDreamCountStr =' update dream set readCount='${newReadCount}' where id ='${id}'; conn.query(sqlDreamCountStr, data, (_err, _data) => { if (_err) throw _err; Console. log(' Update list ID readCount succeeded '); }); // Return res.json({code: 1, message: 'query succeeded ', data: results}); }) pool.releaseconnection (conn) // Release the connection pool and wait for another connection to use})}); // delete app.post('/ API /dream/del', (req, Res) => {console.log(req.body) // let sqlStr = 'DELETE FROM dream WHERE id = ${req.body.id}'; SqlStr = 'DELETE FROM dream WHERE id in (${req.body})'; pool.getConnection((err, conn) => { conn.query( sqlStr, (err , results) => { if(err) { console.log(err); }else {res.json({code: 1, message: 'delete successful ', data: results}); }}) pool.releaseconnection (conn) // releaseConnection pool, wait for other connection to use})}) module.exports = router;Copy the code

2. For more interfaces, please go to Github for preview

Vue+Element create background management system

Vue-admin-template as the basic background framework, check vue-admin-template address, set up my small program background management system, in order to achieve login, registration, user list add, delete, change and check, dream list add, delete, change and check, dream details, favorites, favorites list add, delete, change and check, browsing records and other functions

9, Ali cloud background domain name upgrade HTTP=> HTTPS, after obtaining the certificate put to the server and nginx configuration

As the eight and nine steps are too long, we will move to open Source China preview

X. wechat background domain name set to HTTPS (HTTPS is required for normal requests)

The ali Cloud background needs to set the open port HTTPS open port

Xi. Wechat small program +Vant front end display

Distinguish between environment variables, encapsulate HTTP requests, encapsulate interface addresses

Xii. Release wechat mini programs

The normal review time is 1-7, the first time I upload the review time is 2 days, the review speed is faster and faster, the fastest is within 30 minutes (published in the morning). The review time of each small program varies, but it is just for reference. It is suggested to upload the review time in advance after completion to avoid project timeout. It is also suggested to estimate the minimum review time of 1-2 days during project evaluation to avoid embarrassment.

Results show