? ?对koa搭建后台管理系统做一些总结,使用的是腾讯云开发和对象存储作为数据库和存储地点。
1.首先要安装node,然后npm init初始化,目的是生成package.json文件,package.json将显示安装了哪些模块。
2.安装所需的模块,如下
cnpm install koa --save //koa框架 cnpm install koa-json --save//返回给前端的json对象 cnpm install koa-bodyparser --save//post提交的对象 cnpm install koa-router --save//路由 cnpm install koa2-cors --save//解决跨区 cnpm install nodemon --save//启动服务器端 cnpm install axios --save//Ajax请求模块 cnpm install jsonwebtoken --save //token cnpm install basic-auth --save //解析前端在header中传来的token cnpm install --save @koa/multer multer //静态资源上传:img,video, cnpm install cos-nodejs-sdk-v5 --save /腾讯云cos cnpm install moment --save ?//时间模块 cnpm install e-commerce_price --save //价格补零
3.创建下列文件夹,config放公用的组件,如云开发所用的相关命令,网络请求,验证等,router放要写的接口文件
?4.云开发相关,云开发需要向腾讯云发送网络请求,因为数据都是存储在网络上,所以要用到axios
const axios = require('axios')
const qs = require('querystring')
// 拼接tokenurl地址
let param = qs.stringify({
grant_type:'client_credential',
appid:'wxe9ec3f2fffcc21',//填自己的
secret:'7a798a540c25fae7e8a528a19144df'//填自己的
})
// 获取token的地址:必须要得到token才有权限操作云开发数据库
let url ='https://api.weixin.qq.com/cgi-bin/token?' + param
// 云环境id
let env = 'cloud1-5g6gnk6kabc018f4'
// 数据库插入记录url
let Addurl = 'https://api.weixin.qq.com/tcb/databaseadd?access_token='
// 数据库查询记录url
let Tripurl = 'https://api.weixin.qq.com/tcb/databasequery?access_token='
// 数据库更新记录url
let Updateurl = 'https://api.weixin.qq.com/tcb/databaseupdate?access_token='
// 订阅消息
let Subscribe = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token='
// 小程序码接口
let Qrcode = 'https://api.weixin.qq.com/wxa/getwxacode?access_token='
class getToken{
constructor() {}
// 获取token
async gettoken(){
try{
let token = await axios.get(url)
if(token.status == 200){
return token.data.access_token
}else{
throw '获取token错误'
// 出现throw这个关键词,就会进入到catch里面,并且throw给得值会在catch的参数里
}
}catch(e){
throw '错误1'
}
}
//调用云开发http api接口
async posteve(dataurl,query){
try{
let token = await this.gettoken()
let data = await axios.post(dataurl+token, {env,query})
if(data.data.errcode == 0){
return data.data
}else{
throw '请求出错'
}
}catch(e){
throw '错误2'
}
}
}
module.exports = {getToken,Addurl,Tripurl,Updateurl}
5.写接口,前端就是调用接口获得数据,接口分get和post,get主要用于获得数据,post用于前端提交数据给后端,比如注册等,一个get接口写法
const router = require('koa-router')()//实例化new路由
const {getToken,Addurl,Tripurl,Updateurl} = require('../config/database.js')
router.get('/getlunbo',async ctx=>{
const query =`db.collection("heima-getlunbo").get()`//模板字符串,用于定义云数据库的异步操作
const res= await new getToken().posteve(Tripurl,query)//云数据库的操作结果用变量接收
ctx.body=res.data.map(item=>{return JSON.parse(item)}) //ctx.body就是返回给前端的数据,在数据库存储的是josn字符串,所以用map()函数统一通过JSON.parse()变成josn对象,前端才能使用
})
module.exports=router.routes()
一个post 接口,需要安装koa-bodyparser npm插件,获取post请求参数;
const router = require('koa-router')()//实例化new路由
const {getToken,Addurl,Tripurl,Updateurl} = require('../config/database.js')
const moment = require('moment')
moment.locale('zh-cn')
router.post('/uploadgoods',ctx=>{
const {title,zhaiyao,img_url,sell_price,market_price,stock_quantity}=ctx.request.body//前端提交数据用的字段,代表前端会提交那些数据
let time = moment().utcOffset(8).format('YYYY-MM-DD HH:mm:ss')//utcOffset(8)设置为东八区
let query = `db.collection('dishes-data').add({data:
{
category:'${category}',name:'${name}',unitprice:${unitprice},unit:'${unit}',
image:${image},quantity:0,onsale:true,cid:'${value}',time:'${time}'
}
})`//'${}'代表字符串变量,如果是数组就不用''
})
module.exports=router.routes()
get带参数接口,分为query和params两种,query
const router = require('koa-router')()//实例化new路由
const {getToken,Addurl,Tripurl,Updateurl} = require('../config/database.js')
router.get('/getgoods',async ctx=>{
const {page} = ctx.query// /getgoods/?page=1
const sk = page * 10
const query = `db.collection('heima-getgoods').orderBy('add_time', 'desc').limit(10).skip(${sk}).get()`
try{
const res = await new getToken().posteve(Tripurl,query)
const data = res.data.map(item=>{return JSON.parse(item)})//把字符串转换成对象
const tatal = {tatal:res.pager.Total}//定义总数的对象
const array = {...{result:data},...tatal}//对象组合
ctx.body=array
}
catch(e){
throw '错误500'
}
})
module.exports=router.routes()
//.orderBy云开发排序
params
router.get('/package/:aid/:cid',async (ctx)=>{
//获取动态路由的传值
console.log(ctx.params); //{ aid: '123', cid: '456' }
ctx.body="详情";
})
.ctx.query获取get请求参数 ? ?post提交的值在:ctx.request.body ? ?ctx.body是返回值 ? ? ? ?路由中冒号后面的参数 ? ?router.get("/banners/:id",(ctx,next)=>{ ? ? ?const params = ctx.params; ? ? ?ctx.body = params; ? ?}); ? ?访问 http://localhost:3000/mall/banners/1 ? ? ? ?路由中问号后面的参数 ? ?router.get("/banners",(ctx,next)=>{ ? ? ?const query = ctx.query; ? ? ?ctx.body = query; ? ?}); ? ?访问 http://localhost:3000/mall/banners?id=2 ? ? ? ?路由中header带有的参数 ? ?router.get("/banners",(ctx,next)=>{ ? ? ?const header = ctx.header; ? ? ?ctx.body = header; ? ?});
6.在app.js的代码??
const Koa = require('koa')
const app = new Koa()
const json = require('koa-json')
const bodyParser = require('koa-bodyparser')
const router = require('koa-router')()//实例化new路由
const cors = require('koa2-cors')
app.use(cors())//app.use()注册中间件
app.use(json())
app.use(bodyParser())
//轮播图
const getlunbo = require('./router/getlunbo.js')
//获取商品列表
const getgoods = require('./router/getgoods.js')
//上传接口
const upload = require('./router/uploads.js')
//轮播图接口
router.use('/api',getlunbo)
router.use('/api',getgoods)
router.use('/api',upload)
/* 启动路由 */
app.use(router.routes()).use(router.allowedMethods())
// 自定义启动端口5000:不能跟其他程序的启动端口一样,否则造成端口冲突
app.listen(5000);
console.log('成功')
7.koa的中间件,个人理解为koa的功能模块,可以自定义中间件,格式为
async(ctx,next)=>{
//方法体
}
await next()//关键是有next,这样才能执行下面的代码,在请求和返回之间做的事情就叫中间件
要在app.js中注册,注册后为全局中间件,所有路径都有效,不注册只对匹配的路径和方法生效
一个自定义中间价例子,局部中间件,可以写在路径后
const basicAuth = require('basic-auth')
const jwt = require('jsonwebtoken')
const security = require('./tokentime.js').security
const result = require('../config/handle.js')
class Auth{
constructor() {}
// 取值函数 set:存值函数
get m(){//中间件
return async(ctx,next)=>{
const token = basicAuth(ctx.req)
if(!token || !token.name){
throw new result({errcode:'401',msg:'没有访问权限'},401)
}
try{
var authcode = jwt.verify(token.name,security.secretkey)
}catch(error){
if(error.name == 'TokenExpiredError'){
throw new result({errcode:'401',msg:'账号过期,请重新登陆'},401)
}
throw new result({errcode:'401',msg:'没有访问权限'},401)
}
ctx.auth = {
uid: authcode.uid
}
await next()
}
}
}
module.exports = {Auth}
// 商家信息上传数据库
router.post('/uploadshop', new Auth().m, async ctx=>{
const {id,name,address,logo} = ctx.request.body
new shopinfor(ctx,name,address,logo).start()
// 提交到数据库
// 数组类型不需要这样:'${}'
let query = `db.collection('shop-infor').add({data:{name:'${name}',address:'${address}',logo:${logo}}})`
try{
await new getToken().posteve(Addurl,query)
new result(ctx,'提交成功').answer()
}catch(e){
new result(ctx,'提交失败,服务器发生错误',500).answer()
}
})
中间件写在路径后,没有用app.use()注册
const router = require('koa-router')()//实例化new路由
const {getToken,Addurl,Tripurl,Updateurl} = require('../config/database.js')
const multer = require('@koa/multer')
/// 配置上传文件1.所在的目录和2.更改文件名
const storage = multer.diskStorage({//磁盘存储引擎方法
destination:(req, file, cb)=> {//存储前端传来的文件
cb(null, 'upload/image')
},
filename:(req, file, cb)=> {
// 防止文件重名更改前缀
// Date.now()时间戳6789045678889
cb(null,file.fieldname+'-'+Date.now()+'.jpg')
}
})
const upload = multer({ storage})
router.post('/upload',upload.single('file'),async ctx=>{
// console.log(ctx.file)//接收前端上传的静态资源文件:ctx.file
try{
const res = await cosfun(ctx.file.filename,ctx.file.path)
ctx.body=res
}catch(e){
throw "上传错误"
}
})
module.exports=router.routes()
@koa/multer文件上传的中间件
8.腾讯云模块上传
const COS = require('cos-nodejs-sdk-v5');//用腾讯云的模块进行上传
var cos = new COS({
SecretId:'AKIDgBQO5VeX9UXKq53kAJBl58tNbR0II2',
SecretKey:'vbz6xWprfCSR9ZiaATVFitnRnsgDTS',
Protocol:'https:'
});
let Bucket = 'heima-1307717144'//存储桶
let Region = 'ap-guangzhou'//存储地址
let cosfun = function(filename,path){
return new Promise((resolve,reject)=>{
cos.uploadFile({
Bucket,
Region,
Key:"heima/"+filename, /* 必须 *///上传的文件,可以设定上传到哪个文件夹
FilePath: path,
})
.then(res=>{
resolve(res.Location)
})
.catch(err=>{
reject(err)
})
})
}
|