7 days Wan line and KTV VOD system, including back office systems (full version)

Blog Park ugly ah, look at the Nuggets article

7 days Wan line and KTV VOD system, including back office systems (full version)

 


Recently a little itchy hands wondering Gesha do, dreaming or write KTV VOD systems, simulation account of his thoughts KTV, 7 days exhausted me, but technical point pretty much, I hope you can read (㉨ ^ ~ ^) -

Teach you to write KTV VOD system, including foreground and background content management systems, integration framework and Mongodb Express database server developed with Node (Express); ultra teach you to write beautiful pages with Vue.JS, ElementUI and iViewUI, heart song listen heart

 1 of the original article, please leave a message before reprint or contact the author !!! 

# mind Mapping

** # ** technology stack

* Back end: Express + Mongodb + jsonwebtoken etc.

* Front-end: Vue.JS + ElementUI + iViewUI + Axios etc.

# **Features**

** The project is divided stage development, back-end server development and development **

- User songs need to log in (routing guard)
- the user needs to apply to the administrator account and password
- user login songs (song style, language song, star of song, popular songs, etc. ...)
- the remaining length 30 minute reminder to the next time automatic machine
- administrator of the song additions and deletions to change search
- administrator user account, you can choose a time machine
- an administrator to view orders, delete orders, search orders
- song collection administrator, it is recommended to ktv recommended songs
- and so on ...

** # ** project design structure

- Basic server architecture 
KTV-select_music-System 
├── README.md 
├── index.js - background file entry 
├── test.http - test file 
├── api - routing file 
│ ├── admin .js - configured by the administrator operating 
| ├── music.js - configuration song information 
| ├── user.js - user configuration-related operations 
| └── safecode.js - configuration security code 
├── config - configuration 
| ├── Date.js - configure date formatting plug 
| ├── delNoUse.js - packaging delete unused idle resources method 
| ├── http.js - Configuring Inter 
| ├── isBadAccount .js - packaged account is legitimate 
| ├── newaccount.js - open an account package random method 
| ├── passport.js - verification token is legitimate 
| ├── uploadImg.js - upload pictures packaging method 
| └─ ─ uploadMusic.js - upload songs packaging method 
├── ktv-admin - background management system interface 
├── ktv-client - frontend user interface item song 
├── dbModel
| └── ** - Mongodb database of some models 
├── MongoDB 
| └── mongodb.js - Configuration Mongodb, link database 
├── Secret 
| ├── mongodbURI.js - Mongodb address 
| └── jwtkey.js - token private key 
├── static - resource depository 
| ├── music - songs upload destination folder 
| ├── poster - poster song upload destination folder 
└── └── view - configuration file 404

 

- Manage System Architecture 
KTV-ADMIN 
├── README.md 
├── public 
| ├── index.html - Mount VUE page 
| └── ** - Here you can link a small amount of static resources 
├─ ─ src - development folder 
| ├── App.vue - Vue mount the root page 
| ├── main.js - Vue program entry files, mount the various components 
| ├── router.js - Vue routing profiles 
| ├── store.js - Vuex state management file 
| ├── assets - static resources folder 
| ├── components - common components 
| | └── nav.vue - background navigation 
| ├── plugins - plugin 
| | ├── axios.js - cross-domain configuration, the interceptor etc. 
| | ├── Date.js - formatted date 
| | └── Date.js - loaded animation Loading 
| ├── Stores - state management folder 
| | └── adminStore.js - administrator status 
| ├── views - page folder 
| | ├── 404.vue - 404 page 
| | ├── adminlikes.vue - administrator treatment ktv song collection
| | ├── allorders.vue - Order Management
| | ├── Home.vue - Background root page 
| | ├── Index.vue - Background Home 
| | ├── managemusic.vue - Music Management 
| | ├── user_service.vue - to user accounts 
| | └── login.vue - background login 
└── babel.config.js - babel configuration

  

- Reception users listen to music architecture 
KTV-Client 
├── README.md 
├── public 
| ├── index.html - Mount VUE page 
| └── ** - Here you can link a small amount of static resources 
├ ── src - development folder 
| ├── App.vue - Vue mount the root page 
| ├── main.js - Vue program entry files, mount the various components 
| ├── router.js - Vue routing configuration file 
| ├── store.js - Vuex state management file 
| ├── assets - static resources folder 
| ├── components - common components 
| | ├── bottomNav.vue - the bottom of the music control region 
| | └── topNav.vue - top information region 
| ├── config - configure 
| | ├── addSong.js - song selection method of packaging 
| | ├── isBadAccount.js - verified account legitimate of 
| | ├── isLogin.js - whether Login 
| | ├── nextSong.js - package the next song method 
| | └── prevSong.js - a song on the package method 
| ├── plugins - plug
| | ├── axios.js - cross-domain configuration, the interceptor etc. 
| | └── wsmLoading.js - loading animation Loading 
| ├── Stores - state management folder 
| | └── song.js - store song information 
| ├── views - page folder 
| | ├── 404.vue - 404 page 
| | ├── abc.vue - alphabet song 
| | ├── artist.vue - star VOD 
| | ├── Home.vue - background root page 
| | ├── Index.vue - background Home 
| | ├── hot.vue - hit songs 
| | ├── ktvlikes.vue - - ktv recommended song 
| | ├── selected.vue - selected songs 
| | ├── style.vue - style song 
| | └── language.vue - language song 
├── babel.config. js - babel configuration 
└── vue.config.js - vue configuration

  

** # ** Project Splash

First ##
1. First, do not change the server port, otherwise an error.
2. You need to test Vue equipped with Node and the environment, if one does not please download ([Node Download] (https://nodejs.org/ . en /), [Vue Download] (https://cn.vuejs.org/v2/guide/installation.html))
3. first, the outermost layer Download folder dependent: install rear npm dependent download,
4. then enters ktv-client, npm install distal to download user dependent.
5 then enters ktv-admin, npm install the download manager distal dependent.
6. after completion of the above, using the `npm run server command or command to start the Node server node index` , started successfully will be displayed:

Server running IS ON Port ** [8633]. **

** Mongodb IS A Connected.Please have have Great Coding. **
7. The entered ktv-client, open a command panel, using the command `npm run client` user starts reception project, after a successful start with a browser to access `http: // localhost: xxxx`
8. enter ktv-admin, open a command board, use the command` npm run admin` start back office systems project, started after a successful visit `http browser: localhost //: xxxx`
9. this example Mongodb will be deployed on the local computer, if you carefully read this document, the project started should be easy. If you Mongodb deployed elsewhere, please amend its own `secret / mongodbURI.js` profile information.
10. The project started successfully, it is best to open with chrome browser, beautify the scroll bar

## then registered administrator account
`` `
admin.js the bottom there is a registration interface

// 管理员注册
router.post("/account/register", (req, res) => {
const email = req.body.email;
Admin.findOne({email})
.then(hasOne => {
if(hasOne){
return req.status(422).json({status:"422", result:"邮箱被占用"});
}else{
const username = req.body.username;
const password = req.body.password;
const identity = req.body.identity ? req.body.identity : null;
const date = new Date().format("yyyy/MM/dd HH:mm:ss");
const newAdmin = new Admin({
email,
username,
password,
identity,
date
});
newAdmin.save()
.then(() => {
res.json({status:"200", result:"注册成功"})
}).catch(err => {
the console.log (ERR);
res.status (500) .json ({Status: "500", Result: "unknown error registration failed"})
})
}
})
})

`` `
** then registered with the postman or other tools **

![](https://user-gold-cdn.xitu.io/2019/10/21/16dedaeaef585ff1?w=1361&h=792&f=png&s=32454)

# Technical research

## Date Method

As the head so bad reason js plus method is not an element formatted date on a vain (worth learning)

**Date.js**
```

/ **
*
* @author: Mr_Wei
* @version: 1.0.0
* @description: Date format
* @date: 2019/10/16 09:32
*
* /

Date.prototype.format = function(format) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"H+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"f+": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(format))
format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(format))
format = format.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return format;
}

export default Date.prototype.format


Then we use the date format
The require (a Date);
// now = const new new a Date () format. ( "Yyyy / MM / dd HH: mm: ss.s");
const now = new new a Date () format (. " yyyy / mM / dd HH: mm : ss ");

```


## codes (svg-captcha)

svg-captcha verification code to use to prevent brute force password enhance security.
Detailed documentation Address: [svg-captcha] (https://www.npmjs.com/package/svg-captcha )

** ** codes using
`
@ background generated codes
router.get (" / getCaptcha ", (REQ, RES) => {
var captcha = svgCaptcha.create ({
// rollover color
inverse: to false,
/ / font size
the fontSize: 38 is,
// number of lines noise
noise:. 3,
// width
width: 80,
// height
height: 32,
});
// save the session, ignoring case
req.session = captcha.text. the toLowerCase ();
the console.log (req.session); // 0xtg generated codes
// save the front end to facilitate call authentication cookie
res.cookie ( 'captcha', req.session);
res.setHeader ( 'the Type-the Content ',' Image / XML + SVG ');
res.send (String (captcha.data));
res.end ();
})


// 前台获取验证码
--HTML
<img width="80" style="background:#EEE9E9;margin-left:30px;" ref="captcha" height="32" src="http://localhost:3001/api/user/getCaptcha" @click="refreshCaptcha">

--js
// 获取验证码cookie
getCookie(cname){
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++){
var c = ca[i].trim();
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
}
return "";
},
// 刷新验证码
refreshCaptcha(){
this.$refs.captcha.src = "http://localhost:3001/api/user/getCaptcha?d=" + Math.random();
},

Finally, the comparison with the authentication code filled
`

![](https://user-gold-cdn.xitu.io/2019/10/20/16de8e22c5ac4cf4?w=1720&h=922&f=png&s=2194693)

![](https://user-gold-cdn.xitu.io/2019/10/20/16de8e2a4b88adbe?w=1204&h=729&f=png&s=52841)

## upload songs or pictures
formidable to process the file upload information, easy to use them, very friendly, if you had any contact file operations, and quickly covered up

** ** packaging songs method uploadMusic.js
`` `
/ **
*
* @author: Mr_Wei
* @version: 1.0.0
* @description: encapsulation method to upload music
* @date: 2019/10/16 08:35
*
* /

the require FS = const ( 'FS');
const = path the require ( 'path');
const = formidable the require ( 'formidable'); // file processing library
const formatTime = require ( 'silly- datetime'); // Format data

= module.exports (REQ, RES) => {

the let form new new formidable.IncomingForm = (); // Create the upload form
form.encoding = 'utf-8'; // set the encoding format
form.uploadDir = path.join ( __dirname, '../static/music'); // set the upload directory (the directory must be created)
form.keepExtensions = to true; // leave the file extension
form.maxFieldsSize = 20 * 1024 * 1024; // set File size

/ * Form data format * /
form.parse (REQ, (ERR, Fields, Files) => {
the let File = files.file;
/ * Get exception * /
IF (ERR) {
return res.status (500). json ({ 'status': 500 , result: ' internal server error'});
}
IF (file.size> form.maxFieldsSize) {
fs.unlink (file.path);
return res.status (412) .json ( { 'status': 412, result : ' audio not exceed 20M'});
}

/ * Store suffix * /
the let extname = '';
Switch (file.type) {
Case 'Audio / MP3':
extname = 'MP3';
BREAK;
}
IF (extName.length == 0) {
fs.unlink ( file.path);
return res.status (412) .json ({ 'Status': 412, Result: 'only supports audio formats mp3'});
}
/ * file name of the new splicing * /
the let Time = formatTime.format (new new a Date (), 'YYYYMMDDHHmmss');
the let NUM = Math.floor (Math.random () * 10000 + 8999);
. songName the let $ = `$ {_} {Time NUM}} $` {extname;
the let newPath = form.uploadDir + '/' + songName;

/ * Change the name and path * /
fs.rename (file.path, newPath, (ERR) => {
IF (ERR) {
return res.status (500) .json ({ 'Status': 500, Result:' audio Upload failed '});
} the else {
return res.send ({' Status': 200 is, 'MSG': 'audio successful upload', Result: {the src: songName}});
}
})

})
};
`` `

![](https://user-gold-cdn.xitu.io/2019/10/20/16de8ea6335135f0?w=1465&h=717&f=png&s=62270)

![](https://user-gold-cdn.xitu.io/2019/10/20/16de8fad5128bfac?w=1186&h=617&f=png&s=30247)

## Vue, ElementUI paging use

About ElementUI page for details see: [ElementUI the Pagination tab learning] (https://element.eleme.cn/#/zh-CN/component/pagination)

**上图**
```
-- html
<el-pagination
v-if='paginations.total > 0'
:page-sizes="paginations.page_sizes"
:page-size="paginations.page_size"
:layout="paginations.layout"
:total="paginations.total"
:current-page.sync='paginations.page_index'
@current-change='handleCurrentChange'
@size-change='handleSizeChange'>
</el-pagination>

- JS
Data () {
return {
allUsers: [], // used to store the final information, dom point call is displayed
allTableData: [], // user data receiving settings tab
paginations: {// paging component information
page_index : 1, which is currently in the page //
total: 0, // total
page_size: 5, // display how many pages 1
page_sizes: [5, 10, 15 , 20], // how many page displays
total ": layout , sizes, prev, pager, next , jumper "// page attribute
},
}
},
Methods: {
// get the current page
handleCurrentChange (page) {
the let sortnum this.paginations.page_size = * (page -. 1);
the let = this.allTableData.filter Table ((Item, index) => {
return index> = sortnum;
});
// set default paging data
this.getAllUsers = item table.filter ((, index ) => {
return index < this.paginations.page_size;
});
this.getAllUsers = table.filter((item, index) => {
return index < this.paginations.page_size;
});
},
// 切换size
handleSizeChange(page_size) {
this.paginations.page_index = 1;
this.paginations.page_size = page_size;
this.getAllUsers = this.allTableData.filter((item, index) => {
return index < page_size;
});
},
// 总页数
setPaginations() {
this.paginations.total = this.allTableData.length;
this.paginations.page_index = 1;
this.paginations.page_size = 5;
// 设置默认分页数据
this.getAllUsers = this.allTableData.filter((item, index) => {
return index < this.paginations.page_size;
});
},
}
```


![](https://user-gold-cdn.xitu.io/2019/10/20/16de8ebd6a9c80af?w=1139&h=403&f=png&s=18930)

> Not it? Yes, paging is that simple! You got it? Some students are always on the front-end development paging unfamiliar, learn this, so you no longer lead to trouble!

## token and custom validation legality
jsonwebtoken user information is not encrypted into reverse break token. On passport-jwt, is used when the user requests for token information be brought expired verify if it exceeds the legitimate visas time, Please send a message token reception will fail, prompting the user to reacquire a legitimate token information, or can not continue to request encrypted information;

**用法**
```
- passport-jwt
const key = require("../config/keys").KEYORSECRET;
const JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = key;

module.exports = passport => {
passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
UserInfo.findById(jwt_payload.id)
.then(user => {
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
})
}));
}

 

// 设置token
// 规则
const rule = {
id:String(userinfo._id),
username:userinfo.username,
email:userinfo.email,
date:user.date,
signdate:userinfo.signdate,
signcount:userinfo.signcount,
avatar:userinfo.avatar,
phone:userinfo.phone
};

// visa encryption
// jwt.sign (rules, Key (private key), {arranged: such length expires}, (err, token) {Responder})
jwt.sign (rule, Key, expiresIn {: 7200}, (ERR, token) => {
IF (ERR) the throw ERR;
res.json ({ "token": "Bearer" token +})
})

 

Custom authentication methods
/ **
*
* @author: Mr_Wei
* @version: 1.0.0
* @description: determining whether the user expired
* @date: 2019/10/19 12:19
*
* /
const the require UserOrOrders = (. " ./dbModel/user ");
module.exports the async the params = => {


const the await new new Promise In Flag = ((Resolve) => {
IF (the params) {
const = Account params.account;
UserOrOrders.findOne ({Account})
.then (user => {
IF (user) {
IF (new new a Date () the getTime ()> new new a Date (user.endTime) .getTime ()) {.
the console.log ( "expired user");
// process
return Resolve (to false);
} {the else
the console.log ( "legitimate users");
return Resolve (to true);
}
} the else {
Resolve return (to false);
}
})
} {the else
the console.log ( "invalid user");
return Resolve (to false);
}

})
return In Flag;
}

 


Use:
// test isBadAccount (params) Method
router.post ( "/ Test", passport.authenticate ( "JWT", the session {:} to false), the async (REQ, RES) => {
// the console.log (REQ the .user)
IF (the await isBadAccount (req.user)) {
// do something
res.send ( "the OK");
} the else {
res.status (401) .json ({Status: "401", Result: "account expired, please contact the administrator "})
}
})

```

![](https://user-gold-cdn.xitu.io/2019/10/20/16de91e74dabb7b5?w=1203&h=354&f=png&s=44753)

Detailed documentation Address: [Passport-Jwt legal verification] (https://www.npmjs.com/package/passport-jwt), [token encryption] (https://www.npmjs.com/package/jsonwebtoken)

Screenshot #
## back office systems
-
! [] (Https://user-gold-cdn.xitu.io/2019/10/20/16de8f20c45d16c7?w=1740&h=934&f=png&s=123901)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de8f3aff440179?w=1723&h=926&f=png&s=92578)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de8f4c16660196?w=1733&h=932&f=png&s=121728)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de8f56c6b8f49b?w=1722&h=930&f=png&s=80556)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de8f61023ef8f8?w=1700&h=917&f=png&s=122665)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de8f6dff0f10f4?w=1739&h=933&f=png&s=2756214)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de8f7e2021c16e?w=1727&h=931&f=png&s=2647630)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de8f87ee4336ac?w=1727&h=933&f=png&s=77316)

## Front VOD interface
-
! [] (Https://user-gold-cdn.xitu.io/2019/10/20/16de90855c3a31b7?w=1730&h=936&f=gif&s=626901)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de8fe56259b0df?w=1734&h=929&f=png&s=615102)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de900f3122d838?w=1738&h=940&f=png&s=273612)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de9021416bd557?w=1741&h=938&f=png&s=311696)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de903452757d7c?w=1743&h=943&f=png&s=310171)

-
![](https://user-gold-cdn.xitu.io/2019/10/20/16de90855c3a31b7?w=1730&h=936&f=gif&s=626901)

# Source code where
the code above have been uploaded github

[https://github.com/1046224544/ktv-select_music-system](https://github.com/1046224544/ktv-select_music-system)

Contact #

If you are interested, [welcome star] (https://github.com/1046224544/ktv-select_music-system) are welcome to join me in the front-end exchange group: 866 068 198, can talk about front-end technology. Bloggers have been present in the self-Node, the technology is limited, if possible, will try to provide some help, or some method of learning.
- group of two-dimensional code


![](https://user-gold-cdn.xitu.io/2019/10/16/16dd3758643e9c2b?w=540&h=740&f=jpeg&s=82458)

# Other
- ** Node-vue-iView develop comprehensive website blog-like ** [https://juejin.im/post/5da2a8ed6fb9a04de818eeff](https://juejin.im/post/5da2a8ed6fb9a04de818eeff)


# 最后
If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.

- [juejin@wsm's juejin](https://juejin.im/user/5d1079ab6fb9a07ed4410cc0)
- [GitHub@1046224544](https://github.com/1046224544)
- [Segmentfault@wsm](https://segmentfault.com/u/xiaolajiao_5d81dbf1f09b2)


> ** If you have help, please reward a star ~ ** [github Address] (https://github.com/1046224544/ktv-select_music-system)

Guess you like

Origin www.cnblogs.com/98kk/p/11779808.html